2014-10-12 52 views
7

问题陈述(使用一个人为的例子):为什么我的char *不能正确传递?

如预期工作( '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,你刚刚引导你的定制内核。我不是简单地按照指导教导显示'X',而是决定使用我现有的C/C++知识来尝试编写我自己的基本打印字符串函数。该函数应该采取const char*并将它按char字符写入视频内存。 三个文件,目前参与该项目:

  • 引导扇区 - 通过NASM编译成一个.bin文件
  • 内核输入程序 - 无需通过NASM链接到的.o编译,对内核链接
  • 内核 - 通过GCC编译,通过ld命令与内核输入程序沿着联,其产生被附加到由引导扇区

一旦组合产生的bin文件一个的.bin。 bin文件生成,我是将其转换为.VDI(VirtualBox Disk Image)并在我设置的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就是被转换成虚拟机中使用的.vdi文件。

+0

foo里面的str是什么? – 2014-10-12 07:34:39

+2

什么是str和你在哪里打印? – sas 2014-10-12 07:35:09

+0

在窗口中运行。通过MinGW使用gcc和ld进行编译。有可能我的某些命令行选项不正确,但大多数代码运行正常...... – 2014-10-12 07:41:35

回答

6

在你的第一个例子中,编译器将(或者至少可以)将数据放在代码中初始化自动数组右边(.text部分 - 当我尝试使用时立即使用移动值)。

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

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

相关问题