从 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
与此相关的两个问题:
- 是否可以仅使用
as
(gas)和 ld
to link this to the printf
function, using _start
as the entry观点?如果可以,那该怎么做?
- 如果不是,除了将
_start
更改为 main
之外,gcc
对 运行 的正确调用是什么?
可以使用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 压入堆栈来确保这种对齐(记得在最后将其弹出)。
我遇到了一些与此相关的问题,例如 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
与此相关的两个问题:
- 是否可以仅使用
as
(gas)和ld
to link this to theprintf
function, using_start
as the entry观点?如果可以,那该怎么做? - 如果不是,除了将
_start
更改为main
之外,gcc
对 运行 的正确调用是什么?
可以使用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 压入堆栈来确保这种对齐(记得在最后将其弹出)。