从 gcc 调用一个简单的汇编程序

Calling a simple assembly program from gcc

我有以下程序通过 printf 函数打印数字:

format: .ascii "Your number is: %d.\n[=10=]"

.globl main
main:

    // printf('%d', 55);
    mov $format, %rdi
    mov , %rsi
    mov [=10=], %eax

    // call printf with 16-byte aligned stack:
    sub , %rsp
    call printf
    add , %rsp

    // return 0;
    mov [=10=], %eax
    ret
$ gcc -no-pie int.s -o int; ./int
Your number is: 55.

我在写这篇文章的时候有几个问题:

Does the sub ...add work fine to preserve alignment? For example, the same as doing push %rbp...pop %rbp.

是的。如果你阅读了 pushpop 的指令描述,你会发现它们对堆栈指针有相同的影响,除了 reading/writing 对寄存器和堆栈内存你不关心。但是 pushpop 是较短的指令。

How, for example, does C know that "format" is .data and "main" is in .text ?

除非你告诉它,否则它不会,他们也不会。如果使用 objdump --full-contents 转储可执行文件,您会看到您的字符串已与其他所有内容一起放入 .text 中,因为您从未告诉汇编程序否则会这样做。

Is mov [=20=], %eax; ret the proper way to exit the C main function from assembly?

是的,尽管 xor %eax, %eax ; ret 效率更高。

Finally, what modifications would I need to make this program run without doing -no-pie ?

不允许在与位置无关的可执行文件中使用绝对地址作为立即数,因此 mov $format, %rdi 不好。而是使用 RIP 相对寻址:lea format(%rip), %rdi。其他都还好。