从 gas assembly 链接和调用 printf

Linking and calling printf from gas assembly

我遇到了一些与此相关的问题,例如 Printf with gas assembly and Calling C printf from assembly,但我希望这会有所不同。

我有以下程序:

.section .data
format:
    .ascii "%d\n"

.section .text
.globl _start

_start:
    
    // print "55"
    mov $format, %rdi
    mov , %rsi
    mov [=10=], %eax
    call printf # how to link?

    // exit
    mov , %eax
    mov [=10=], %rdi
    syscall

与此相关的两个问题:

可以使用ld,但不推荐:如果使用libc函数,需要初始化C运行时。如果您让 C 编译器提供 _start 并以 main 启动您的程序,那将自动完成。如果您使用 libc 而不是 C 运行时初始化代码,它可能看起来有效,但它也可能导致奇怪的虚假故障。

如果您从 main(您的第二种情况)开始您的程序,它就像执行 gcc -o program program.s 一样简单,其中 program.s 是您的源文件。在某些 Linux 发行版中,您可能还需要提供 -no-pie,因为您的程序不是以 PIC 风格编写的(暂时不要担心)。

另请注意,我建议不要将 libc 调用与原始系统调用混合使用。不执行原始退出系统调用,而是调用 C 库函数 exit。这让 C 运行时正确地取消初始化自身,包括刷新任何 IO 流。

现在,如果您 assemble 和 link 您的程序如我在第一段中所说,您会注意到它可能会崩溃。这是因为调用函数时堆栈需要对齐到 16 字节的倍数。您可以通过在每个函数的开头将数据的 qword 压入堆栈来确保这种对齐(记得在最后将其弹出)。