Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I verified these using GNU Assembler (gas) on Linux.</p> <h1> Kernel Interface </h1> <p><strong>x86-32 Linux System Call convention:</strong></p> <p>In x86-32 parameters for Linux system call are passed using registers. <code>%eax</code> for syscall_number. %ebx, %ecx, %edx, %esi, %edi, %ebp are used for passing 6 parameters to system calls.</p> <p>The return value is in <code>%eax</code>. All other registers (including EFLAGS) are preserved across the <code>int $0x80</code>.</p> <p>I took following snippet from the <a href="https://web.archive.org/web/20120822144129/http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html" rel="noreferrer">Linux Assembly Tutorial</a> but I'm doubtful about this. If any one can show an example, it would be great.</p> <blockquote> <p>If there are more than six arguments, <code>%ebx</code> 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.</p> </blockquote> <p>For an example and a little more reading, refer to <a href="http://www.int80h.org/bsdasm/#alternate-calling-convention" rel="noreferrer">http://www.int80h.org/bsdasm/#alternate-calling-convention</a></p> <p>There is faster way to make 32bit system calls: using <code>sysenter</code>. The kernel maps a page of memory into every process (the vdso), with the user-space side of the <code>sysenter</code>, 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 <code>int $0x80</code>, but instead of that instruction, code should call a function in the vdso. (TODO: update this with a link and/or specific info).</p> <p><strong>x86-32 [Free|Open|Net|DragonFly]BSD UNIX System Call convention:</strong></p> <p>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 <code>int $0x80</code></p> <p><a href="http://www.int80h.org/bsdasm/#default-calling-convention" rel="noreferrer">http://www.int80h.org/bsdasm/#default-calling-convention</a></p> <hr> <p><strong>x86-64 Linux System Call convention:</strong></p> <p><a href="https://stackoverflow.com/questions/47834513/64-bit-syscall-documentation-for-macos-assembly">x86-64 Mac OS X is similar but different</a>. TODO: check what *BSD does.</p> <p>Refer to section: "A.2 AMD64 <strong>Linux</strong> Kernel Conventions" of <a href="http://refspecs.linuxfoundation.org/elf/x86_64-abi-0.99.pdf" rel="noreferrer">System V Application Binary Interface AMD64 Architecture Processor Supplement</a>. The latest versions of the i386 and x86-64 System V psABIs can be found <a href="https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI" rel="noreferrer">linked from this page in the ABI maintainer's repo</a>. (See also the <a href="/questions/tagged/x86" class="post-tag" title="show questions tagged &#39;x86&#39;" rel="tag">x86</a> tag wiki for up-to-date ABI links and lots of other good stuff about x86 asm.)</p> <p>Here is the snippet from this section:</p> <blockquote> <ol> <li>User-level applications use as integer registers for passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. <strong>The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.</strong></li> <li>A system-call is done via the <strong><code>syscall</code> instruction</strong>. This clobbers %rcx and %r11, as well as %rax, but other registers are preserved.</li> <li>The number of the syscall has to be passed in register %rax.</li> <li>System-calls are limited to six arguments, no argument is passed directly on the stack.</li> <li>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 <code>-errno</code>.</li> <li>Only values of class INTEGER or class MEMORY are passed to the kernel.</li> </ol> </blockquote> <p>Remember this is from the Linux-specific appendix to the ABI, and even for Linux it's informative not normative. (But it is in fact accurate.)</p> <h1> User Interface </h1> <p><strong>x86-32 Function Calling convention:</strong></p> <p>In x86-32 parameters were passed on stack. Last parameter was pushed first on to the stack until all parameters are done and then <code>call</code> instruction was executed. This is used for calling C library (libc) functions on Linux from assembly.</p> <hr> <p><strong>x86-64 Function Calling convention:</strong></p> <p>x86-64 passes args in registers, which is more efficient than i386 System V's stack args convention. It avoids the latency and extra instructions of storing args to memory (cache) and then loading them back again in the callee. This works well because there are more registers available, and is better for modern high-performance CPUs where latency and out-of-order execution matter. (The i386 ABI is very old).</p> <p>In this <em>new</em> 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.</p> <p>For complete information refer to : "3.2 Function Calling Sequence" of <a href="http://refspecs.linuxfoundation.org/elf/x86_64-abi-0.99.pdf" rel="noreferrer">System V Application Binary Interface AMD64 Architecture Processor Supplement</a> which reads, in part:</p> <blockquote> <p>Once arguments are classified, the registers get assigned (in left-to-right order) for passing as follows:</p> <ol> <li>If the class is MEMORY, pass the argument on the stack.</li> <li>If the class is INTEGER, the next available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used</li> </ol> </blockquote> <p>So <code>%rdi, %rsi, %rdx, %rcx, %r8 and %r9</code> are the registers <em>in order</em> used to pass integer/pointer (i.e. INTEGER class) parameters to any libc function from assembly. %rdi is used for the first INTEGER parameter. %rsi for 2nd, %rdx for 3rd and so on. Then <code>call</code> instruction should be given. The stack (<code>%rsp</code>) must be 16B-aligned when <code>call</code> executes.</p> <p>If there are more than 6 INTEGER parameters, the 7th INTEGER parameter and later are passed on the stack. (Caller pops, same as x86-32.)</p> <p>The first 8 floating point args are passed in %xmm0-7, later on the stack. There are no call-preserved vector registers. (A function with a mix of FP and integer arguments can have more than 8 total register arguments.)</p> <p>Variadic functions (<a href="https://stackoverflow.com/questions/6212665/why-is-eax-zeroed-before-a-call-to-printf">like <code>printf</code></a>) always need <code>%al</code> = the number of FP register args.</p> <p>There are rules for when to pack structs into registers (<code>rdx:rax</code> on return) vs. in memory. See the ABI for details, and check compiler output to make sure your code agrees with compilers about how something should be passed/returned.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload