尝试在我的Macbook Pro(Intel i7,64位)上运行程序集并遇到了一个奇怪的错误。
这是一个基本的“Hello,world!”程序只使用系统调用。
SECTION .text
global start
start:
mov rax, 2
shl rax, 24
add al , 4
mov rdi, 1
mov rsi, Msg
mov rdx, Len
syscall
mov al , 1
mov rdi, 0
syscall
SECTION .data
Msg db `Hello, world!\n`
Len: equ $-Msg
与NASM 2.11组装 控制台命令:
nasm -f macho64 -o main.o main.s
ld main.o
它打印“Hello,world”和换行符,但随后返回总线错误:10(错误的内存地址)。
但如果我这样做:
mov rax, 2
shl rax, 24
add al , 1
我没有收到总线错误。
问题是:为什么我不能使用“mov al,1”更改不同调用的rax的第一个字节
答案 0 :(得分:2)
第一个rax
并未保留syscall
注册,因此只需将al
设置为1
,就无法为 next < / em>系统调用rax
,因为它保持所有高位不变。 不给出总线错误的方法是重新填充 rax
的所有位的方法。
由于write
是为了返回实际写入的字节数,所以返回rax
,确保您需要将完全填入下一个{ {1}}。可以在the Wikipedia calling convention page上找到支持使用syscall
获取返回代码的内容,其中列出rax
:
System V AMD64 ABI [11]的调用约定遵循Solaris,GNU / Linux,FreeBSD, Mac OS X,以及其他类UNIX或POSIX兼容的操作系统。前六个整数或指针参数在寄存器RDI,RSI,RDX,RCX,R8和R9中传递,而XMM0,XMM1,XMM2,XMM3,XMM4,XMM5,XMM6和XMM7用于浮点参数。对于系统调用,使用R10代替RCX。[11]与Microsoft x64调用约定一样,其他参数在堆栈上传递,返回值存储在RAX中。
附录A中的System V Application Binary Interface, AMD64 Architecture Processor Supplement文件中也对此进行了详细说明。
在修复代码方面,最好不要执行完整的填充序列(不必要的位移):
System V AMD64 ABI
退出。实际上,我将两个系统调用的方法用于简化源代码:
mov rax, 0x2000001
mov rdi, 0
syscall