我目前正在开发一个用于教育目的的小型操作系统(因为这很有趣)。我成功地通过了 64 位模式,并跳转到 C 函数“kmain”以使用更高级别的语言进行编程。一切都已设置完毕(交叉编译器、磁盘读取以将我的 c 函数加载到地址 0x7e00 处的第二个扇区...)。以下代码完美运行:
#define VIDEO_MEMORY_LOCATION 0xb8000
void kmain() {
char msg[] = "Hello world!";
int i =0;
char *video_memory = (char *)VIDEO_MEMORY_LOCATION;
while (msg[i]) {
*video_memory = msg[i];
i++;
video_memory += 2;
}
}
我的字符串正确显示。但是,我试图在rodata 中放置一个字符串,如下所示:
#define VIDEO_MEMORY_LOCATION 0xb8000
void kmain() {
char *msg = "Hello world!";
char *video_memory = (char *)VIDEO_MEMORY_LOCATION;
while (*msg) {
*video_memory = *msg;
msg++;
video_memory += 2;
}
}
而且它不起作用。更准确地说,我的屏幕与以前相同,但未显示字符串。它也不会崩溃。只是字符串不在这里。我的第一个想法是:“.rodata 加载不正确,因此我的字符串不在我的可执行文件中”,但我确信这不是这个,原因如下: 当我拆开时:
00000200 55 push rbp
00000201 4889E5 mov rbp,rsp
00000204 48C745F845FE0000 mov qword [rbp-0x8],0xfe45
0000020C 48C745F000800B00 mov qword [rbp-0x10],0xb8000
00000214 EB17 jmp short 0x22d
00000216 488B45F8 mov rax,[rbp-0x8]
0000021A 0FB610 movzx edx,byte [rax]
0000021D 488B45F0 mov rax,[rbp-0x10]
00000221 8810 mov [rax],dl
00000223 488345F801 add qword [rbp-0x8],byte +0x1
00000228 488345F002 add qword [rbp-0x10],byte +0x2
0000022D 488B45F8 mov rax,[rbp-0x8]
00000231 0FB600 movzx eax,byte [rax]
00000234 84C0 test al,al
00000236 75DE jnz 0x216
00000238 90 nop
00000239 90 nop
0000023A 5D pop rbp
0000023B C3 ret
0000023C 0F1F4000 nop dword [rax+0x0]
00000240 E8BBFFFFFF call 0x200
00000245 48 rex.w # not code, my "Hello world!" string located at 0xfe45
00000246 656C gs insb
00000248 6C insb
00000249 6F outsd
0000024A 20776F and [rdi+0x6f],dh
...
我们希望看到我的字符串在这里,并且当我们得到字符串时的地址是正确的。 我不明白为什么“你好世界!”不显示。
在 qemu 中,当我显示地址 0xfe45 处的内存内容时,我得到: (qemu)x/8c 0x7e45 000000000007e45:'H''e''l''l''o'''''w''o''r''l''d''!' 'x00'
这种代码:
void kmain() {
char *video_memory = (char *)VIDEO_MEMORY_LOCATION;
char msg0[] = "AZE";
int i = 0;
while (msg0[i]) {
*video_memory = msg0[i];
i++;
video_memory += 2;
}
char *msg = "Hello world!";
while (*msg) {
*video_memory = *msg;
msg++;
video_memory += 2;
}
}
仅显示“AZE”。
它不起作用。
两个循环之间绝对没有区别。
我怀疑您没有像重新定位堆栈一样重新定位
.rodata
,因此从.rodata
读取失败。