以下链接解释了UNIX(BSD风格)和;Linux:

  • 一百

  • 一百

但是,UNIX和Windows上的x86-64系统调用约定是什么;Linux?

推荐答案

以下任何主题的进一步阅读:The Definitive Guide to Linux System Calls


我在Linux上使用GNU汇编程序(gas)验证了这些.

Kernel Interface

x86-32 aka i386 Linux System Call convention:

在x86-32中,Linux系统调用的参数使用寄存器传递.系统调用号为%eax%ebx、%ecx、%edx、%esi、%edi、%ebp用于向系统调用传递6个参数.

返回值以%eax为单位.所有其他寄存器(包括EFLAG)都在int $0x80中保留.

我从Linux Assembly Tutorial人中选取了以下片段,但我对此表示怀疑.如果有人能举个例子,那就太好了.

如果有六个以上的论点,

有关示例和更多阅读,请参阅http://www.int80h.org/bsdasm/#alternate-calling-convention.i386 Linux的Hello World使用int 0x80:Hello, world in assembly language with Linux system calls?的另一个示例

有一种更快的方法可以进行32位系统调用:使用sysenter.内核将一页内存映射到每个进程(vDSO),sysenter舞蹈的用户空间端必须与内核配合才能找到返回地址.Arg到寄存器的映射与int $0x80相同.您通常应该调用vDSO,而不是直接使用sysenter.(有关链接和调用vDSO的信息,请参见The Definitive Guide to Linux System Calls;有关sysenter以及与系统调用有关的所有其他信息,请参见sysenter.)

x86-32 [Free|Open|Net|DragonFly]BSD UNIX System Call convention:

参数在堆栈上传递.将参数(最后一个先推的参数)推送到堆栈上.然后再推送一个额外的32位伪数据(实际上不是伪数据.更多信息请参阅下面的链接),然后给出一个系统调用指令int $0x80

http://www.int80h.org/bsdasm/#default-calling-convention


x86-64 Linux系统调用约定:

(注意:x86-64 Mac OS X is similar but different来自Linux.TODO:判断*BSD的功能)

Refer to section: "A.2 AMD64 Linux Kernel Conventions" of System V Application Binary Interface AMD64 Architecture Processor Supplement. The latest versions of the i386 and x86-64 System V psABIs can be found linked from this page in the ABI maintainer's repo. (See also the tag wiki for up-to-date ABI links and lots of other good stuff about x86 asm.)

以下是本节的片段:

  1. 用户级应用程序用作整数寄存器,用于传递
  2. 系统调用通过101 instruction完成.这clobbers %rcx and %r11以及%rax返回值,但保留了其他寄存器.
  3. 系统调用的编号必须在寄存器%rax中传递.
  4. 系统调用仅限于六个参数,不传递任何参数
  5. 从系统调用返回的寄存器%rax包含
  6. 只有类整数或类内存的值被传递给内核.

请记住,这是ABI特定于Linux的附录,即使对于Linux,它也是信息性的,而不是规范性的.(但事实上这是准确的.)

此32位int $0x80 ABI is在64位代码中可用(但强烈不推荐).What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?它仍然将其输入截断为32位,因此不适用于指针,并将r8-r11置零.

User Interface: function calling

x86-32 Function Calling convention:

在x86-32中,参数在堆栈上传递.最后一个参数首先被推送到堆栈上,直到所有参数都完成,然后执行call条指令.这用于从程序集调用Linux上的C库(libc)函数.

i386 System V ABI(在Linux上使用)的现代版本要求在call之前先对%esp字节进行16字节对齐,就像x86-64 System V ABI一直要求的那样.被调用者可以假设并使用SSE 16字节加载/存储未对齐上的故障.但从历史上看,Linux只需要4字节的堆栈对齐,所以即使是8字节的double或其他东西,也需要额外的工作来保留自然对齐的空间.

其他一些现代32位系统仍然不需要超过4字节的堆栈对齐.


x86-64 System V用户空间函数调用约定:

x86-64 System V在寄存器中传递参数,这比i386 System V的堆栈参数约定更有效.它避免了将参数存储到内存(缓存),然后在被调用方中重新加载这些参数的延迟和额外指令.这很好,因为有更多的寄存器可用,并且对于延迟和无序执行很重要的现代高性能CPU来说更好.(i386 ABI非常古老).

在这个new机制中:首先将参数划分为类.每个参数的类决定了它传递给被调用函数的方式.

有关完整信息,请参阅System V Application Binary Interface AMD64 Architecture Processor Supplement的"3.2函数调用序列",其中部分内容如下:

一旦参数被分类,寄存器就会被分配(在

  1. 如果类是内存,则在堆栈上传递参数.
  2. 如果类是INTEGER,则

因此,%rdi, %rsi, %rdx, %rcx, %r8 and %r9是寄存器in order,用于将整型/指针(即整型类)参数从汇编传递给任何libc函数rdi用于第一个整数参数.%第二名为rsi,第三名为rdx,依此类推.然后应该给出call个指令.当call执行时,堆栈(%rsp)必须与16B对齐.

如果有6个以上的整数参数,则在堆栈上传递第7个整数参数和更高的整数参数.(调用者弹出,与x86-32相同.)

前8个浮点参数在%xmm0-7中传递,随后在堆栈中传递.没有保留呼叫的向量寄存器.(混合使用FP和整数参数的函数的寄存器参数总数可以超过8个.)

可变函数(like printf)总是需要%al=FP寄存器arg的数量.

对于何时将 struct 打包到寄存器(返回时为rdx:rax)和内存中,有一些规则.有关详细信息,请参阅ABI,并判断编译器输出,以确保您的代码与编译器在传递/返回内容方面的一致性.


请注意,the Windows x64 function calling convention与x86-64 System V有多个显著差异,比如must由调用者保留的阴影空间(而不是红色区域),以及保留调用的xmm6-xmm15.arg进入哪个寄存器的规则非常不同.

Linux相关问答推荐

为什么仅使用&i-i标志时仍会从容器进程中输出

如何在带模式的文件频繁更改的管道中使用grep-f带模式的文件?

如何在Linux上获取clang中的模板实例化统计?

如何在不进行轮询且不吃掉其他人子进程的退出代码的情况下等待一组子进程(并且只有它们)?

8 个半小时范围的 Crontab 表达式

在 bash 中解析变量

根据其他列的值创建一个新列

进程Forking 后 pthread_key_create() 生成的密钥会发生什么?

在 bash 中查找匹配多个模式的文件

如果 bash 中已经存在文件名,则创建新文件但添加数字

如何重新安装最新的 cmake 版本?

Java 8 上的 SQL Server JDBC 错误:驱动程序无法使用安全套接字层 (SSL) 加密建立与 SQL Server 的安全连接

将 awk 输出保存到变量

如何更改某些文件模式/扩展名的权限?

为什么这个命令会杀死我的 shell?

Linux批量转换:使用转换更改jpg的质量但保留其名称

Linux AMD64 中如何使用 fs/gs 寄存器?

ldconfig 错误:使用 Linux 加载程序时不是符号链接

如何使用 sed 通过灵活的键和值更改我的配置文件?

如何将 ISO8859-15 转换为 UTF8?