让程序链接是最简单的部分:
- Change
_start
to start
$ nasm -f macho exit.asm
$ ld -arch i386 -o exiter exit.o
问题是exit.asm
正在调用 i386 Linuxexit()
系统调用(EAX= 1) 并且程序将NOT按照 OS X 的预期,以零状态退出。
系统调用
A 系统调用是对内核的请求。exit()
,不像sqrt()
,必须向在其实现中具有更高权限的软件组件发出请求,因为它终止正在运行的程序。应用程序无法自行创建或终止进程。系统调用为应用程序提供了一种要求内核代表它们执行操作的方法。
进行系统调用是这样的:
- Apps describe the operation they want to perform by placing data in CPU registers (or memory pointed to by registers), e.g.
- 价值
1
in EAX是系统调用号exit
.
- 价值
0
in EBX (EBX被清除xor
) 是系统调用的第一个参数,即退出状态。
- Apps issue an instruction that causes control to transfer to the kernel, e.g.
-
int 80
on i386
-
sycall
在 x86-64 上
-
svc
在 ARMv7 上处于 Thumb 模式
- 内核检查请求并决定执行或拒绝它。
- 内核将控制权转移回应用程序,并将返回值放在约定的位置,例如EAX在 i386 上。
Linux 和 OS X 都提供了void exit(int)
函数用于 C 程序,但不同意如何向内核描述此请求的细节。代码在exit.asm
与实施的水平相同_exit()
函数于libc
.
即使在运行 Linux 的不同体系结构之间,系统调用号和调用约定也不同。例如在 x86-64 Linux 上,exit(0)
更常见的是这样发出的:
xor rdi, rdi
mov al, 60
syscall
拆解一下就可以看到_exit
in /lib64/libc.so.6
.
我们不能直接从 libc 调用 exit() 吗?
你可以。但你必须将程序链接到libc
。这就是链接的区别exit.asm
上面有:
$ cc -m32 -nostdlib exit.o -o exiter
and
退出-libc.asm
extern exit
global main
main:
push 0
call exit
必须与以下内容相关联:
$ cc -m32 exit-libc.o -o exit-libc
尝试一下并查看文件大小。