问题陈述(使用人为的例子):
按预期工作('b'打印到屏幕):
void Foo(const char* bar);
void main()
{
const char bar[4] = "bar";
Foo(bar);
}
void Foo(const char* bar)
{
// Pointer to first text cell of video memory
char* memory = (char*) 0xb8000;
*memory = bar[0];
}
Run Code Online (Sandbox Code Playgroud)
不按预期工作(\0打印到屏幕):
void Foo(const char* bar);
void main()
{
Foo("bar");
}
void Foo(const char* bar)
{
// Pointer to first text cell of video memory
char* memory = (char*) 0xb8000;
*memory = bar[0];
}
Run Code Online (Sandbox Code Playgroud)
换句话说,如果我const char*直接传递,它就不能正确传递.在const char*我进去Foo点以某种方式清零内存.我究竟做错了什么?
背景信息(根据要求):
我正在开发一个有趣的操作系统,使用我在这里找到的指南.该指南通常假设您使用的是基于unix的计算机,但我正在使用PC进行开发,因此我使用MinGW以便我可以访问gcc,ld等.在指南中,我目前在第54页,你刚刚引导你的自定义内核.我决定使用我现有的C/C++知识来尝试编写自己的基本打印字符串函数,而不是简单地在指南中显示"X".该函数应该const char*通过char将char写入视频内存.目前该项目涉及三个文件:
生成组合的.bin文件后,我将其转换为.VDI(VirtualBox磁盘映像)并在我设置的VM中运行它.
附加信息:
我刚刚注意到,当VirtualBox将.bin文件转换为.vdi时,它会报告两个示例的不同大小.我有一种预感,也许字符串被完全从编译产品中省略.果然,当我在十六进制编辑器中查看.bin的第一个示例时,我可以找到文本"bar",但是当我查看第二个示例的.bin的十六进制转储时,我不能.
这让我相信我正在使用的编译过程在某处有一个缺陷.这是我正在使用的命令:
nasm boot_sector.asm -f bin -o boot_sector.bin
nasm kernel_entry.asm -f elf -o kernel_entry.o
gcc -ffreestanding -c kernel.c -o kernel.o
ld -T NUL -o kernel.tmp -Ttext 0x1000 kernel_entry.o kernel.o
objcopy -O binary -j .text kernel.tmp kernel.bin
copy /b boot_sector.bin+kernel.bin os_image.bin
Run Code Online (Sandbox Code Playgroud)
os_image.bin是转换为vm中使用的.vdi文件的内容.
在您的第一个示例中,编译器将(或者至少可以)将数据放入代码中的自动数组初始化(.text部分 - 当我尝试使用时,使用立即值的移动).
在第二个示例中,字符串文字放在该.rodata部分中,代码将包含对该部分的引用.
您的objcopy命令只复制该.text部分,因此最终二进制文件中将缺少该字符串.您应该添加该.rodata部分,或-j .text完全删除.