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
所以汇编中调用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在内存中由高到底存放,所以是减去)
所以汇编中调用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寄存器中。
参考: