【问题标题】:global variable always initialized zero全局变量始终初始化为零
【发布时间】:2017-07-24 17:46:06
【问题描述】:

我一直在使用this 教程编写操作系统。我在哪里 引导加载程序完成并使用C进行编程(然后链接在一起......)。但这只是一个说明,我相信我遇到的问题与 gcc 有关。

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

int test_var = 1234;

// yes, void main() is correct (the boot-loader will call this)
void main() {} 

如果我用 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

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

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

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

# ...
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"

编辑:作为@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");
  }
}

遗憾的是它打印了It's zero

【问题讨论】:

  • 你是用gcc -g3编译的吗?
  • @alinsoar 我用-g 编译了它们,但我只是尝试了-g3 并没有什么不同。
  • 你有启动代码吗?它负责设置初始化 .data 和 .bss 段。
  • @EugeneSh 不,这是个问题吗?我的意思是我有一个引导加载程序,可以将程序加载到 RAM 等中。但我没有初始化任何变量
  • @PaulScharnofske 初始化变量进入.data 部分。您需要一些启动代码(在调用 main() 之前)将此部分从 ROM 复制到 RAM。

标签: c gcc cross-compiling


【解决方案1】:

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

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

【讨论】:

  • 如果您正在分配内存或 memset 完整内存,那么这可能不是必需的,但有时由于对齐 loader() 从 ELF 图像中复制一些额外的数据,这些数据也可能是垃圾。这一切都取决于您的加载器和 ROM--> RAM 传输实现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多