Saya telah membaca dan mengikuti tutorial menulis sistem operasi dari awal oleh Nick Blundell yang dapat ditemukan di https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf
Saya telah berhasil menulis boot loader yang dapat memanggil kode C, jadi saya mulai menulis kernel saya dalam C. Sekarang saya mencoba menulis fungsi yang dapat mencetak karakter dan string di layar. Pada saat saya mulai mengeksekusi kode C, saya berada dalam mode terlindungi 32-bit, jadi saya mencoba menghitung offset memori dengan benar dari alamat memori video 0xb8000.
Masalah saya dimulai ketika saya mencoba mengakses wilayah tertentu dari memori video menggunakan offset yang dihitung. Karena area teksnya 25 baris kali 80 kolom, saya menggunakan rumus ((baris * 80) + kolom) * 2 karena saya harus memiliki byte karakter dan byte atribut. Saat saya menyetel baris = 0 dan kolom = 0, X yang saya coba cetak tidak ada. Setting baris = 0 dan kolom = 1, muncul tanda X di pojok kiri atas.
Dimulai dengan char* video_memory = 0xb8000 dan berulang kali mengeluarkan video_memory++ memungkinkan saya mengunjungi setiap byte dengan benar dan mencetak spasi dengan latar belakang hitam.
Ini adalah kode utama saya:
#include "../drivers/screen.h"
void main() {
//clear_screen();
//print_character('X', 0, 0, 0);
// Helper variables.
int row;
int column;
// We need to point at 0xB8000, where video memory resides.
unsigned char* video_memory = (unsigned char*)0xB8000;
for(row = 0; row < 25; row++) {
for(column = 0; column < 80; column++) {
// Clear the screen by printing a space on a black background.
*video_memory = ' ';
video_memory += 1;
*video_memory = 0x0F;
video_memory += 1;
}
}
// Test the offset calculation by printing at row 0, column 0 (the upper
// left corner of the screen).
row = 0;
column = 0;
// For an 80 by 25 grid. Multiply by 2 to account for the need of two bytes
// to display a character with given attributes.
int offset = ((row * 80) + column) * 2;
// Reset memory location after the loop.
video_memory = (unsigned char*)0xB8000;
// Add the offset to get the desired cell.
// THIS IS WHERE THE PROBLEM IS! Setting column = 1 prints in the first cell
// of video memory instead of the second.
video_memory += offset;
// Set character and its attributes.
*video_memory = 'X';
video_memory++;
*video_memory = 0x0F;
}
Ini adalah konsol yang ditampilkan ketika baris = 0 dan kolom = 0: Konsol ketika baris dan kolom adalah 0. Tidak ada X yang muncul.
Ini adalah konsol ketika baris = 0 dan kolom = 1: Konsol ketika baris adalah 0 dan kolom adalah 1 . Tanda X muncul.
Ini adalah objek dari file kernel.c saya di atas:
kernel.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
#include "../drivers/screen.h"
void main() {
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
// Helper variables.
int row;
int column;
// We need to point at 0xB8000, where video memory resides.
unsigned char* video_memory = (unsigned char*)0xB8000;
4: 48 c7 45 f8 00 80 0b mov QWORD PTR [rbp-0x8],0xb8000
b: 00
for(row = 0; row < 25; row++) {
c: c7 45 ec 00 00 00 00 mov DWORD PTR [rbp-0x14],0x0
13: eb 2f jmp 44 <main+0x44>
for(column = 0; column < 80; column++) {
15: c7 45 f0 00 00 00 00 mov DWORD PTR [rbp-0x10],0x0
1c: eb 1c jmp 3a <main+0x3a>
// Clear the screen by printing a space on a black background.
*video_memory = ' ';
1e: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
22: c6 00 20 mov BYTE PTR [rax],0x20
video_memory += 1;
25: 48 83 45 f8 01 add QWORD PTR [rbp-0x8],0x1
*video_memory = 0x0F;
2a: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
2e: c6 00 0f mov BYTE PTR [rax],0xf
video_memory += 1;
31: 48 83 45 f8 01 add QWORD PTR [rbp-0x8],0x1
int column;
// We need to point at 0xB8000, where video memory resides.
unsigned char* video_memory = (unsigned char*)0xB8000;
for(row = 0; row < 25; row++) {
for(column = 0; column < 80; column++) {
36: 83 45 f0 01 add DWORD PTR [rbp-0x10],0x1
3a: 83 7d f0 4f cmp DWORD PTR [rbp-0x10],0x4f
3e: 7e de jle 1e <main+0x1e>
int row;
int column;
// We need to point at 0xB8000, where video memory resides.
unsigned char* video_memory = (unsigned char*)0xB8000;
for(row = 0; row < 25; row++) {
40: 83 45 ec 01 add DWORD PTR [rbp-0x14],0x1
44: 83 7d ec 18 cmp DWORD PTR [rbp-0x14],0x18
48: 7e cb jle 15 <main+0x15>
}
}
// Test the offset calculation by printing at row 0, column 0 (the upper
// left corner of the screen).
row = 0;
4a: c7 45 ec 00 00 00 00 mov DWORD PTR [rbp-0x14],0x0
column = 0;
51: c7 45 f0 00 00 00 00 mov DWORD PTR [rbp-0x10],0x0
// For an 80 by 25 grid. Multiply by 2 to account for the need of two bytes
// to display a character with given attributes.
int offset = ((row * 80) + column) * 2;
58: 8b 55 ec mov edx,DWORD PTR [rbp-0x14]
5b: 89 d0 mov eax,edx
5d: c1 e0 02 shl eax,0x2
60: 01 d0 add eax,edx
62: c1 e0 04 shl eax,0x4
65: 89 c2 mov edx,eax
67: 8b 45 f0 mov eax,DWORD PTR [rbp-0x10]
6a: 01 d0 add eax,edx
6c: 01 c0 add eax,eax
6e: 89 45 f4 mov DWORD PTR [rbp-0xc],eax
// Reset memory location after the loop.
video_memory = (unsigned char*)0xB8000;
71: 48 c7 45 f8 00 80 0b mov QWORD PTR [rbp-0x8],0xb8000
78: 00
// Add the offset to get the desired cell.
// THIS IS WHERE THE PROBLEM IS! Setting column = 1 prints in the first cell
// of video memory instead of the second.
video_memory += offset;
79: 8b 45 f4 mov eax,DWORD PTR [rbp-0xc]
7c: 48 98 cdqe
7e: 48 01 45 f8 add QWORD PTR [rbp-0x8],rax
// Set character and its attributes.
*video_memory = 'X';
82: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
86: c6 00 58 mov BYTE PTR [rax],0x58
video_memory++;
89: 48 83 45 f8 01 add QWORD PTR [rbp-0x8],0x1
*video_memory = 0x0F;
8e: 48 8b 45 f8 mov rax,QWORD PTR [rbp-0x8]
92: c6 00 0f mov BYTE PTR [rax],0xf
}
95: 90 nop
96: 5d pop rbp
97: c3 ret
Saya telah menelusuri dan memeriksa langsung instruksi perakitan sebenarnya untuk perhitungan offset saya, dan tampaknya instruksi tersebut benar. Saya menduga masalah ini muncul ketika saya mencoba menambahkan offset saya (ketik int) ke alamat memori video saya (ketik unsigned char*), tapi sekali lagi saya tidak sepenuhnya yakin.
Juga, saya mencoba mengkodekan angka-angka tertentu untuk offset. Menggunakan video_memory += 0 alih-alih video_memory += offset berfungsi sesuai keinginan.
video_memory
dan tujuannya. Gunakan pengindeksan array normal sebagai gantinya. Seperti divideo_memory[row * 80 + column] = 'X';
- person Some programmer dude   schedule 22.05.2018