首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gcc编译时-ffreestanding与-nostdlib的区别

问gcc编译时-ffreestanding与-nostdlib的区别
EN

Stack Overflow用户
提问于 2020-01-06 12:36:57
回答 2查看 2.2K关注 0票数 2

我使用的是一台64位linux机器,带有x84-elf64-gcc编译器.我刚刚开始低级编程,并想了解C代码是如何实际转换为二进制代码的。这主要是为了操作系统的开发,因为我知道处理器不理解ELF或任何其他格式,而只理解二进制。

例如,以下c文件:

代码语言:javascript
复制
//test.c
int func()
{
    return 0x12345678;
}

当我和gcc一起编译时:

代码语言:javascript
复制
gcc test.c

我得到以下错误:

代码语言:javascript
复制
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

所以我猜链接器有问题。我知道:

代码语言:javascript
复制
gcc test.c -c 

我得到了一个ELF对象文件,我做了一个objdump并得到了预期的:

代码语言:javascript
复制
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位版本时,我得到:

代码语言:javascript
复制
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++编程比较陌生,我认为这里的主要问题是我并不真正理解链接器/编译器是如何工作的。:(

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-06 12:58:36

这些选项控制着流程的两个部分:

  • -freestanding向编译器表示它应该是一个独立的编译器,AFAIK唯一的效果是禁用一些内置函数,比如memcpy;
  • -nostdlib表示默认情况下不应该链接库和启动文件。
票数 3
EN

Stack Overflow用户

发布于 2020-01-06 12:46:08

我不知道-ffreestanding到底做了什么,那部分是个好问题。

但不幸的是,您的问题在32位饼码中有一个很大的侧翼:

使用-m32选项编译时,为什么会发生这样的更改?

因为您忽略了任何-O优化选项,32位模式对数据没有EIP相对寻址模式(只有相对跳转/调用)。因此,很明显,调试模式总是将寄存器设置为GOT指针,作为寻址静态数据的基础,即使在不使用它的函数中也是如此。

请始终使用-fno-pie关闭该默认值,除非您特别希望使饼图可执行。

您还可能需要-mcmodel=kernel -如果您正在编译64位的上半内核(静态地址可以使用32位符号扩展的即时性,而不是32位零扩展),这是个好主意。但是IDK如果对32位代码做任何事情的话。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59612257

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档