我将从OS/X Syscall tutorial 开始(在您的情况下是 64 位部分)。它是为 NASM 语法编写的,但重要的信息是 SYSCALL 调用约定的文本和链接。 SYSCALL 表位于此Apple webpage。有关 64 位 OS/X 标准调用约定的更多信息,请参阅System V 64-bit ABI。
SYSCALL 约定的重要性:
- 参数通过这些寄存器 rdi、rsi、rdx、r10、r8 和 r9 按顺序传递
- rax 寄存器中的系统调用号
- 调用是通过syscall指令完成的
- OS X 的贡献在于您必须将 0x20000000 添加到系统调用号(仍然必须弄清楚原因)
您的sys_read 系统调用存在许多问题。 SYSCALL 表是这样写的:
3 AUE_NULL ALL { user_ssize_t read(int fd, user_addr_t cbuf, user_size_t nbyte); }
所以根据调用约定,int fd 在 RDI 中,user_addr_t cbuf(指向保存返回数据的字符缓冲区的指针)在 RSI 中,@987654328 @(缓冲区可以包含的最大字节数)在 RDX 中。
您的程序段在 ret 上出错,因为您没有正确的函数结尾来匹配顶部的函数序言:
push %rbp #
mov %rsp,%rbp # Function prologue
你需要在底部做相反的事情,在RAX中设置结果代码,然后执行ret。比如:
mov %rbp,%rsp # \ Function epilogue
pop %rbp # /
xor %eax, %eax # Return value = 0
ret # Return to C runtime which will exit
# gracefully and return to OS
我做了其他一些小的清理工作,但试图保持代码的结构相似。您将不得不学习更多的汇编来更好地理解使用sys_read SYSCALL 的地址设置 RSI 的代码。一般来说,您应该尝试找到一本关于 x86-64 汇编语言编程的好教程/书籍。撰写关于该主题的入门书超出了此答案的范围。
考虑到上述情况,可能更接近您正在寻找的代码:
.section __DATA,__data
str:
.asciz "Hello world!\n"
sto:
.asciz "Nope!\n"
.section __TEXT,__text
.globl _main
_main:
push %rbp #
mov %rsp,%rbp # Function prologue
sub $0x20, %rsp # Allocate 32 bytes of space on stack
# for temp local variables
movl $0x2, -4(%rbp) # Number for comparison
# 16-bytes from -20(%rbp) to -5(%rbp)
# for char input buffer
movl $0x2000003, %eax
mov $0, %edi # 0 for STDIN
lea -20(%rbp), %rsi # Address of temporary buffer on stack
mov $16, %edx # Read 16 character maximum
syscall
movb (%rsi), %r10b # RSI = pointer to buffer on stack
# get first byte
subb $48, %r10b # Convert first character to number 0-9
cmpb -4(%rbp), %r10b # Did we find magic number (2)?
jne L2 # If No exit with error message
L1: # If the magic number matched print
# Hello World
xor %rax, %rax
movl $0x2000004, %eax
movl $1, %edi
movq str@GOTPCREL(%rip), %rsi
movq $14, %rdx
syscall
jmp L0 # Jump to exit code
L2: # Print "Nope"
xor %eax, %eax
movl $0x2000004, %eax
movl $1, %edi
movq sto@GOTPCREL(%rip), %rsi
movq $6, %rdx
syscall
L0: # Code to exit main
mov %rbp,%rsp # \ Function epilogue
pop %rbp # /
xor %eax, %eax # Return value = 0
ret # Return to C runtime which will exit
# gracefully and return to OS