全局变量始终初始化为零

7 c gcc cross-compiling

我一直在使用教程编写操作系统.我在启动加载器完成的部分,C用于编程(然后链接在一起......).但这只是一个注释,我相信我遇到的问题与gcc有关.

i386-elf为操作系统构建了一个交叉编译器.一切正常,我可以执行我的代码一切正常.除了所有全局变量都初始化为零之外,尽管我提供了一个默认值.

int test_var = 1234;

// yes, void main() is correct (the boot-loader will call this)
void main() {} 
Run Code Online (Sandbox Code Playgroud)

如果我用GDB调试这段代码,我得到:( gcc-7.1.0, target: i328-elf)

(gdb) b main
Breakpoint 1 at 0x1554: file src/kernel/main.c, line 11.
(gdb) c
Continuing.

Breakpoint 1, main () at src/kernel/main.c:11
11  void main() {
(gdb) p test_var
$1 = 0
Run Code Online (Sandbox Code Playgroud)

如果我在我的本地机器(gcc-6.3.0, target: x86_64)上运行相同的代码,它会打印出来1234.

我的问题是:我是否错误配置了gcc,这是我操作系统中的错误,这是一个已知问题吗?我找不到任何关于它的东西.

我的整个源代码:链接 我使用以下命令编译我的东西:

# ...
i386-elf-gcc -g -ffreestanding -Iinclude/ -c src/kernel/main.c -o out/kernel/main.o
# ...
i386-elf-ld -e 0x1000 -Ttext 0x1000 -o out/kernel.elf out/kernel_entry.o out/kernel/main.o # some other stuff ...
i386-elf-objcopy -O binary out/kernel.elf out/kernel.bin
cat out/boot.bin out/kernel.bin > out/os.bin
qemu-system-i386 -drive "format=raw,file=out/os.bin"
Run Code Online (Sandbox Code Playgroud)

编辑:作为@EugeneSh.这里建议一些逻辑来确保它没有被删除:

#include <cpu/types.h>
#include <cpu/isr.h>

#include <kernel/print.h>

#include <driver/vga.h>

int test_var = 1234;

void main() {
  vga_text_init();

  switch (test_var) {
    case 1234: print("That's correct"); break;
    case 0: print("It's zero"); break;

    // I don't have a method like atoi() in place, I would use
    // GDB to get the value
    default: print("It's something else");
  }
}
Run Code Online (Sandbox Code Playgroud)

可悲的是它打印出来 It's zero

小智 1

编译器永远不会将未初始化的全局变量清除为零,其逻辑内置于加载器内部,因此当您为数据段分配内存时,它的大小也包含 bss 部分。因此,您必须检查数据段中的 bss 部分偏移、对齐和大小,并使用 memset() 将它们设置为“0”。

当您编写操作系统时,可能所有库例程都不可用,因此最好使用汇编编写 memset() 函数。