为什么我的char *没有正确传递?

时间:2014-10-12 07:30:05

标签: c

问题陈述(使用人为的例子):

按预期工作('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];
}

未按预期工作(\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];
}

换句话说,如果我直接传递const char*,它就无法正确传递。 const char*我进入Foo指向以某种方式将记忆归零。我做错了什么?

背景信息(根据要求):

我正在使用我找到here的指南开发一个有趣的操作系统。该指南通常假设您使用的是基于unix的计算机,但我正在使用PC进行开发,因此我使用MinGW以便可以访问gcc,ld等。 在本指南中,我目前在第54页,您刚刚引导了自定义内核。我决定使用我现有的C / C ++知识来尝试编写自己的基本打印字符串函数,而不是简单地在指南中显示“X”。该函数应该采用const char*并将char(char)写入视频内存。 目前该项目涉及三个文件:

  • 引导扇区 - 通过NASM编译为.bin文件
  • 内核入口例程 - 编译时未通过NASM链接到.o,与内核链接
  • 内核 - 通过gcc编译,通过ld命令与内核入口例程链接,生成.bin,后者附加到引导扇区生成的.bin文件

生成组合的.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

os_image.bin是转换为vm中使用的.vdi文件的内容。

1 个答案:

答案 0 :(得分:6)

使用您的第一个示例,编译器将(或至少可以)将数据放入代码中的自动数组初始化(.text部分 - 当我尝试此操作时使用立即值的移动)

使用第二个示例,字符串文字放在.rodata部分中,代码将包含对该部分的引用。

您的objcopy命令仅复制.text部分,因此最终二进制文件中将缺少该字符串。您应该添加.rodata部分,或完全删除-j .text