我使用的是一台64位linux机器,带有x84-elf64-gcc编译器.我刚刚开始低级编程,并想了解C代码是如何实际转换为二进制代码的。这主要是为了操作系统的开发,因为我知道处理器不理解ELF或任何其他格式,而只理解二进制。
例如,以下c文件:
//test.c
int func()
{
return 0x12345678;
}当我和gcc一起编译时:
gcc test.c我得到以下错误:
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status所以我猜链接器有问题。我知道:
gcc test.c -c 我得到了一个ELF对象文件,我做了一个objdump并得到了预期的:
0000000000000000 <func>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: b8 78 56 34 12 mov $0x12345678,%eax
9: 5d pop %rbp
a: c3 retq 但是,当我使用-m32选项和objdump“交叉编译”32位版本时,我得到:
hello.o: file format elf32-i386
Disassembly of section .text:
00000000 <func>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: e8 fc ff ff ff call 4 <func+0x4>
8: 05 01 00 00 00 add $0x1,%eax
d: b8 78 56 34 12 mov $0x12345678,%eax
12: 5d pop %ebp
13: c3 ret
Disassembly of section .text.__x86.get_pc_thunk.ax:
00000000 <__x86.get_pc_thunk.ax>:
0: 8b 04 24 mov (%esp),%eax
3: c3 ret 我在以前的回答中看到,这与位置无关的代码有关:‘在gcc的32位代码中,一个琐碎的函数,独立操作系统
使用-m32选项编译时,为什么会发生这样的更改?此外,我被建议在编译时使用-ffreestanding选项,但在这里它似乎没有效果。我读过-ffreestanding告诉编译器没有标准库,那么-nostdlib是什么呢?
注意:我对这种核心的c++编程比较陌生,我认为这里的主要问题是我并不真正理解链接器/编译器是如何工作的。:(
发布于 2020-01-06 12:58:36
这些选项控制着流程的两个部分:
发布于 2020-01-06 12:46:08
我不知道-ffreestanding到底做了什么,那部分是个好问题。
但不幸的是,您的问题在32位饼码中有一个很大的侧翼:
使用-m32选项编译时,为什么会发生这样的更改?
因为您忽略了任何-O优化选项,32位模式对数据没有EIP相对寻址模式(只有相对跳转/调用)。因此,很明显,调试模式总是将寄存器设置为GOT指针,作为寻址静态数据的基础,即使在不使用它的函数中也是如此。
请始终使用-fno-pie关闭该默认值,除非您特别希望使饼图可执行。
您还可能需要-mcmodel=kernel -如果您正在编译64位的上半内核(静态地址可以使用32位符号扩展的即时性,而不是32位零扩展),这是个好主意。但是IDK如果对32位代码做任何事情的话。
https://stackoverflow.com/questions/59612257
复制相似问题