【问题标题】:Can gcc compile x86 assembly or just link it?gcc 可以编译 x86 程序集还是只链接它?
【发布时间】:2013-02-02 13:27:21
【问题描述】:

gcc 可以生成程序集,但是如何使用 gcc 或其他编译器编译纯程序集?我知道 x86 汇编很困难,并且是另一个指令集,而不是我正在查看的 MIPS 和 Nios,但现在我想尝试直接编译 x86 asm。有如何做到这一点的说明,但其中包含一个 C 文件,我的第一个最基本的编译不需要 C 文件。

gcc -o test_asm asm_functions.S test_asm.c

创建.o文件的步骤

gcc -c asm_functions.S
gcc -c test_asm.c
gcc -o test_asm asm_functions.o test_asm.o

但是我没有看到可以使用 gcc 直接编译 x86 asm 的步骤。还有一个名为GNU as (GNU Assembler)的程序,它可以用来将x86汇编翻译成机器码吗?

测试

代码 (32.s)

.globl  _start

.text
_start:
        movl    $len, %edx
        movl    $msg, %ecx
        movl    $1, %ebx
        movl    $4, %eax
        int     $0x80

        movl    $0, %ebx
        movl    $1, %eax
        int     $0x80
.data
msg:
        .ascii  "Hello, world!\n"
        len =   . - msg

步骤

$ gcc -c 32.s 
$ ls 32*
32.o  32.s
$ gcc -o 32 32.o 
32.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'

看来它可能混合了 32 位和 64 位,我必须告诉编译器汇编是 32 位还是 64 位指令吗?

更新

此测试适用于 gcc。

$ cat hello.s
.data
.globl hello
hello:
.string "Hi World\n"

.text
.global main
main:
    pushq   %rbp
    movq    %rsp,       %rbp
    movq    $hello,     %rdi
    call    puts
    movq    $0,         %rax
    leave
    ret
$ gcc hello.s -o hello
$ ./hello 
Hi World

【问题讨论】:

  • 是的,这正是as(1) 所做的。
  • 另请参阅this Q&A,了解如何使用 gcc 进行汇编和链接,以了解定义 _startmain 的程序,带/不带 libc。

标签: gcc assembly compiler-construction x86


【解决方案1】:

虽然更新有效,但原始代码可以通过简单地使用gcc -nostdlib 进行编译。例如,

gcc -nostdlib 32.s -o 32

【讨论】:

  • 不太可能将您的姓名作为参数传递会产生很大的影响。那个随机的 32 是什么?使用换行符和代码格式将使您的答案更具可读性。
  • 一些代码也将受益于(或需要)现代发行版上的-no-pie。 no-pie 曾经是默认设置,但在大多数现代 GNU/Linux 发行版 GCC 配置中不再是默认设置。特别是对于使用绝对地址的 64 位代码。使用gcc -m32 -nostdlib foo.S,它可能仍然可以构建 PIE,但如果您链接 libc,那么您需要 puts@plt 或手动 -fno-plt asm;请参阅Can't call C standard library function on 64-bit Linux from assembly (yasm) code
【解决方案2】:

你已经在做。

gcc -c asm_functions.S

该步骤会生成一个目标文件asm_functions.o。目标文件是“可链接”(相对于“可加载”)文件,其中包含机器代码,并附有一些关于链接器在链接时应如何修改代码的额外说明。 gcc 程序本身只是一个驱动程序,它在后台运行as 为您生成asm_functions.o。因此,您确实可以选择直接运行 as,但通常运行 gcc 前端更容易。

【讨论】:

  • 但是当我尝试仅链接从纯程序集创建的目标文件时,我收到一条我无法理解的错误消息 (In function _start': (.text+0x0): multiple definition of @ 987654329@_start': (.text+0x20): undefined reference to main' 谢谢你的回答。
  • 这是链接问题,不是编译问题!如果使用gcc链接,默认获取C运行时,入口点应该是main
  • 谢谢。它现在可以编译并运行到 x86 程序集 (gcc hello.s -o hello)。我用我使用的代码和 cmd 更新了问题。我没有尝试这段代码是否是 linux 的规范,它可能是其他操作系统的其他程序集,as 程序也可能编译它,但在这种情况下,我可以使用 gcc 和一个简单的 hello world 程序进行编译并运行 x86 程序集。
猜你喜欢
  • 2019-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-30
  • 1970-01-01
相关资源
最近更新 更多