什么是UNIX和放大器的调用约定; Linux系统调用的x86-64 [英] What are the calling conventions for UNIX & Linux system calls on x86-64

查看:305
本文介绍了什么是UNIX和放大器的调用约定; Linux系统调用的x86-64的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下链接解释的x86-32系统调用约定为UNIX(BSD味)及Linux的:


  • <一个href=\"http://www.int80h.org/bsdasm/#system-calls\">http://www.int80h.org/bsdasm/#system-calls


  • <一个href=\"http://www.freebsd.org/doc/en/books/developers-handbook/x86-system-calls.html\">http://www.freebsd.org/doc/en/books/developers-handbook/x86-system-calls.html


但什么是在UNIX和放大器的X86-64系统调用约定; Linux呢?


解决方案

我验证了这些使用GNU汇编器(气)在Linux上。

内核接口

X86-32的Linux系统调用约定:

在为Linux系统调用的参数X86-32通过寄存器传递。 %EAX 的syscall_number。 EBX%,ECX%,%EDX,ESI%,%EDI,EBP%是用于传递6个参数到系统调用。

返回值是在%EAX 。所有其它寄存器(包括EFLAGS)在各个pserved $ P $的 0x80的INT

我就把下面从<片段href=\"https://web.archive.org/web/20120822144129/http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html\">Linux大会教程但我怀疑这一点。如果任何一个可以显示一个例子,这将是巨大的。


  

如果存在多于六个参数,
  %EBX 必须包含内存
  位置,参数列表
  存储 - 但不要担心这个
  因为它是不可能的,你会使用
  有超过六个系统调用
  参数。


有关的例子,多一点阅读,请参阅<一个href=\"http://www.int80h.org/bsdasm/#alternate-calling-convention\">http://www.int80h.org/bsdasm/#alternate-calling-convention

有更快的方式,使32位系统调用:在使用 SYSENTER 。内核内存页映射到每一个进程(VDSO),随着 SYSENTER 用户空间方面,它具有与内核合作,它能够找到返回地址。 ARG注册映射的是相同 0x80的INT ,但不是该指令,code应该叫在VDSO的功能。 (TODO:一个链接和/或特定的信息更新这个)

X86-32 [免费|打开|网络|蜻蜓] BSD UNIX系统调用约定:

参数传递堆栈。按参数(最后一个参数压在前)到堆栈中。然后按下虚拟数据的另外32位(它实际上没有无效数据。请参考以下链接了解更多信息),然后给一个系统调用的指令 INT $ 0x80的

<一个href=\"http://www.int80h.org/bsdasm/#default-calling-convention\">http://www.int80h.org/bsdasm/#default-calling-convention


的x86-64 Linux和放大器; * BSD系统调用约定:

请参见: System V应用程序二进制接口AMD64架构处理器补编A.2 AMD64 Linux内核约定

下面是本节中的片段:


  

      
  1. 用户级应用程序作为整数寄存器用于传递
      序列%RDI,RSI%,%RDX,RCX%,
      %R8和R9%。 内核接口使用%RDI,RSI%,%RDX,R10%,%R8和R9%

  2.   
  3. 一个系统调用是通过在系统调用指令完成。内核
      破坏寄存器%RCX和R11%。

  4.   
  5. 系统调用的数量在寄存器%RAX传递。

  6.   
  7. 系统通话仅限于六个参数,无参数传递
      直接在堆栈中。

  8.   
  9. 从系统调用返回,寄存器%RAX包含的结果
      该系统调用。在A值
      -4095和-1之间的范围表示
      一个错误,这是 -errno

  10.   
  11. 只有Integer类或类内存值传递给内核。

  12.   

用户界面

X86-32函数调用约定:

在X86-32参数传递栈。最后一个参数首先被压入堆栈,直到所有的参数都做了,然后被执行呼叫指令。这是用于从汇编调用C库(libc)函数在Linux上。


x86-64的函数调用约定:

我想正因为如此,我们有这么多的通用寄存器和较高的宽度其它寄存器的函数调用机制改变的原因。在这种的新的的机制。首先,参数分成若干类。类中每个参数的确定在其中它被传递给被调用的函数的方式。

有关完整的信息,请参阅: System V应用程序二进制接口AMD64架构处理器补编3.2函数调用序列其内容,部分内容如下:


  

在参数进行分类时,
  寄存器会被分配(以
  左到右的顺序)在通过为
  如下:


  
  

      
  1. 如果该类是记忆,在栈上传递的说法。

  2.   
  3. 如果该类是INTEGER,的下一个可用的寄存器
      序列%RDI,RSI%,%RDX,RCX%,%R8和R9%使用

  4.   

所以%RDI,%RSI,%RDX,%RCX,%R8和%R9 是寄存器的的用于传递参数从装配任何libc中的功能。 %RDI用于第一个参数。对于第2%RSI,RDX%为第三等。然后呼叫指令应该放在首位。

如果参数超过6然后7日起的参数是在栈上传递。

Following links explain x86-32 system call conventions for both UNIX (BSD flavor) & Linux:

But what are the x86-64 system call conventions on both UNIX & Linux?

解决方案

I verified these using GNU Assembler (gas) on Linux.

Kernel Interface

x86-32 Linux System Call convention:

In x86-32 parameters for Linux system call are passed using registers. %eax for syscall_number. %ebx, %ecx, %edx, %esi, %edi, %ebp are used for passing 6 parameters to system calls.

The return value is in %eax. All other registers (including EFLAGS) are preserved across the int 0x80.

I took following snippet from the Linux Assembly Tutorial but I'm doubtful about this. If any one can show an example, it would be great.

If there are more than six arguments, %ebx must contain the memory location where the list of arguments is stored - but don't worry about this because it's unlikely that you'll use a syscall with more than six arguments.

For an example and a little more reading, refer to http://www.int80h.org/bsdasm/#alternate-calling-convention

There is faster way to make 32bit system calls: using sysenter. The kernel maps a page of memory into every process (the vdso), with the user-space side of the sysenter, which has to cooperate with the kernel for it to be able to find the return address. arg to register mapping is the same as for int 0x80, but instead of that instruction, code should call a function in the vdso. (TODO: update this with a link and/or specific info).

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

Parameters are passed on the stack. Push the parameters (last parameter pushed first) on to the stack. Then push an additional 32-bit of dummy data (Its not actually dummy data. refer to following link for more info) and then give a system call instruction int $0x80

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


x86-64 Linux & *BSD System Call convention:

Refer to section: "A.2 AMD64 Linux Kernel Conventions" of System V Application Binary Interface AMD64 Architecture Processor Supplement

Here is the snippet from this section:

  1. User-level applications use as integer registers for passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.
  2. A system-call is done via the syscall instruction. The kernel destroys registers %rcx and %r11.
  3. The number of the syscall has to be passed in register %rax.
  4. System-calls are limited to six arguments, no argument is passed directly on the stack.
  5. Returning from the syscall, register %rax contains the result of the system-call. A value in the range between -4095 and -1 indicates an error, it is -errno.
  6. Only values of class INTEGER or class MEMORY are passed to the kernel.

User Interface

x86-32 Function Calling convention:

In x86-32 parameters were passed on stack. Last parameter was pushed first on to the stack until all parameters are done and then call instruction was executed. This is used for calling C library (libc) functions on Linux from assembly.


x86-64 Function Calling convention:

I guess because of the reason that we have so many general purpose registers and higher width other registers the function calling mechanism is changed. In this new mechanism. First the parameters are divided into classes. The class of each parameter determines the manner in which it is passed to the called function.

For complete information refer to : "3.2 Function Calling Sequence" of System V Application Binary Interface AMD64 Architecture Processor Supplement which reads, in part:

Once arguments are classified, the registers get assigned (in left-to-right order) for passing as follows:

  1. If the class is MEMORY, pass the argument on the stack.
  2. If the class is INTEGER, the next available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used

so %rdi, %rsi, %rdx, %rcx, %r8 and %r9 are the registers in order used to pass parameters to any libc function from assembly. %rdi is used for first parameter. %rsi for 2nd, %rdx for 3rd and so on. Then call instruction should be given.

If parameters are more than 6 then 7th parameter onwards is passed on the stack.

这篇关于什么是UNIX和放大器的调用约定; Linux系统调用的x86-64的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆