nasm汇编 linux和macos int 80h调用系统函数的参数传递

linux和macos的汇编中通过 int 80h 软中断来调用系统函数,但是给函数传入的参数方法不同。以下说明32位程序的调用方式。

Linux

对于linux,如果我要调用如下的C语言函数:

sys_write(unsigned int fd, const char * buf, size_t count);

函数参数和寄存器对应关系为:

ebx: fd
ecx: buf
edx: count

然后函数编号对应寄存器 eax, 函数编号对照表可以参考https://blog.csdn.net/xiaominthere/article/details/17287965

所以汇编中调用sys_write这个函数来显示一个字符串对应的汇编如下:

section .data
msg db 'Hello'

section .text

__display:
    mov edx, 5 ;字符串长度, 对应count参数
    mov cdx, msg ;字符串所在地址, 对应buf参数 
    mov ebx, 1 ;对应fd参数,fd为1时表示stdout, 显示屏
    mov eax, 4 ;对应sys_write在linux系统中调用好为4
    int 80h

macOS

在macos中,C语言函数的参数不使用寄存器来存放,而是使用stack来存放,参数顺序倒序入栈,总共支持16字节。比如同样的显示字符串功能,在macos中的C函数为:

write(int fd, user_addr_t cbuf, user_size_t nbyte);

因此,函数参数入栈顺序为:

push nbyte
push cbuf
push fd
sub esp 4 ;参数总共要占用16字节,因为这个函数需要3个参数,所以实际占用了 3*4=12个字节,为了填满16字节,这里将stack地址再减去4个字节(stack在内存中由高到底存放,所以是减去)

然后函数编号对应寄存器 eax, 函数编号对照表可以参考https://opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master

所以汇编中调用write这个函数来显示一个字符串对应的汇编如下:

section .data
msg db 'Hello'

section .text

__display:
    push dword 5 ;字符串长度, 对应nbyte参数
    push dword msg ;字符串所在地址, 对应cbuf参数 
    push dword 1 ;对应fd参数,fd为1时表示stdout, 显示屏
    sub esp, 4 ;填满16字节
    mov eax, 4 ;对应sys_write在macos系统中调用好为4
    int 80h

无论在linux还是macos中,函数的返回值都最后保存在eax寄存器中。

参考:

linux调用方式: https://blog.csdn.net/xiaominthere/article/details/17287965

macos调用方式: https://filippo.io/making-system-calls-from-assembly-in-mac-os-x/

标签: nasm, 汇编