System V ABI: Difference between revisions

Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
(Add information about -fomit-frame-pointer)
Line 18: Line 18:
This is a 32-bit platform. The stack grows downwards. Parameters to functions are passed on the stack in reverse order such that the first parameter is the last value pushed to the stack, which will then be the lowest value on the stack. Parameters passed on the stack may be modified by the called function. Functions are called using the <tt>call</tt> instruction that pushes the address of the next instruction to the stack and jumps to the operand. Functions return to the caller using the <tt>ret</tt> instruction that pops a value from the stack and jump to it. The stack is 4-byte aligned just before the call instruction is called.
This is a 32-bit platform. The stack grows downwards. Parameters to functions are passed on the stack in reverse order such that the first parameter is the last value pushed to the stack, which will then be the lowest value on the stack. Parameters passed on the stack may be modified by the called function. Functions are called using the <tt>call</tt> instruction that pushes the address of the next instruction to the stack and jumps to the operand. Functions return to the caller using the <tt>ret</tt> instruction that pops a value from the stack and jump to it. The stack is 4-byte aligned just before the call instruction is called.


Functions preserve the registers <tt>ebx</tt>, <tt>esi</tt>, <tt>edi</tt>, <tt>ebp</tt>, and <tt>esp</tt>; while <tt>eax</tt>, <tt>ecx</tt>, <tt>edx</tt> are scratch registers. The return value is stored in the <tt>eax</tt> register, or if it is a 64-bit value, then the higher 32-bits go in <tt>edx</tt>. Functions push <tt>ebp</tt> such that the <tt>caller-return-eip</tt> is 4 bytes above it, and set <tt>ebp</tt> to the address of the saved ebp. This allows iterating through the existing stack frames.
Functions preserve the registers <tt>ebx</tt>, <tt>esi</tt>, <tt>edi</tt>, <tt>ebp</tt>, and <tt>esp</tt>; while <tt>eax</tt>, <tt>ecx</tt>, <tt>edx</tt> are scratch registers. The return value is stored in the <tt>eax</tt> register, or if it is a 64-bit value, then the higher 32-bits go in <tt>edx</tt>. Functions push <tt>ebp</tt> such that the <tt>caller-return-eip</tt> is 4 bytes above it, and set <tt>ebp</tt> to the address of the saved ebp. This allows iterating through the existing stack frames. This can be eliminated by specifying the <tt>-fomit-frame-pointer</tt> GCC option.


Additionally, if you compile with [[GCC]], it assumes the stack is 16-byte aligned (not just 4-byte aligned) when the <tt>call</tt> instruction in the caller was executed. This is required to properly store SSE values on the stack, as they require 16-byte alignment, or other values (such as 64-bit values) with higher-than-4-byte alignment. As a special exception, GCC assumes the stack is not properly aligned and realigns it when entering <tt>main</tt> or if the <tt>attribute ((force_align_arg_pointer))</tt> is set on the function.
Additionally, if you compile with [[GCC]], it assumes the stack is 16-byte aligned (not just 4-byte aligned) when the <tt>call</tt> instruction in the caller was executed. This is required to properly store SSE values on the stack, as they require 16-byte alignment, or other values (such as 64-bit values) with higher-than-4-byte alignment. As a special exception, GCC assumes the stack is not properly aligned and realigns it when entering <tt>main</tt> or if the <tt>attribute ((force_align_arg_pointer))</tt> is set on the function.
Line 26: Line 26:
This is a 64-bit platform. The stack grows downwards. Parameters to functions are passed in the registers <tt>rdi</tt>, <tt>rsi</tt>, <tt>rdx</tt>, <tt>rcx</tt>, <tt>r8</tt>, <tt>r9</tt>, and further values are passed on the stack in reverse order. Parameters passed on the stack may be modified by the called function. Functions are called using the <tt>call</tt> instruction that pushes the address of the next instruction to the stack and jumps to the operand. Functions return to the caller using the <tt>ret</tt> instruction that pops a value from the stack and jump to it. The stack is 16-byte aligned just before the call instruction is called.
This is a 64-bit platform. The stack grows downwards. Parameters to functions are passed in the registers <tt>rdi</tt>, <tt>rsi</tt>, <tt>rdx</tt>, <tt>rcx</tt>, <tt>r8</tt>, <tt>r9</tt>, and further values are passed on the stack in reverse order. Parameters passed on the stack may be modified by the called function. Functions are called using the <tt>call</tt> instruction that pushes the address of the next instruction to the stack and jumps to the operand. Functions return to the caller using the <tt>ret</tt> instruction that pops a value from the stack and jump to it. The stack is 16-byte aligned just before the call instruction is called.


Functions preserve the registers <tt>rbx</tt>, <tt>rsp</tt>, <tt>rbp</tt>, <tt>r12</tt>, <tt>r13</tt>, <tt>r14</tt>, and <tt>15</tt>; while <tt>rax</tt>, <tt>rdi</tt>, <tt>rsi</tt>, <tt>rdx</tt>, <tt>rcx</tt>, <tt>r8</tt>, <tt>r9</tt>, <tt>r10</tt>, <tt>r11</tt> are scratch registers. The return value is stored in the <tt>rax</tt> register, or if it is a 128-bit value, then the higher 64-bits go in <tt>rdx</tt>. Optionally, functions push <tt>rbp</tt> such that the <tt>caller-return-rip</tt> is 8 bytes above it, and set <tt>erp</tt> to the address of the saved rbp. This allows iterating through the existing stack frames.
Functions preserve the registers <tt>rbx</tt>, <tt>rsp</tt>, <tt>rbp</tt>, <tt>r12</tt>, <tt>r13</tt>, <tt>r14</tt>, and <tt>r15</tt>; while <tt>rax</tt>, <tt>rdi</tt>, <tt>rsi</tt>, <tt>rdx</tt>, <tt>rcx</tt>, <tt>r8</tt>, <tt>r9</tt>, <tt>r10</tt>, <tt>r11</tt> are scratch registers. The return value is stored in the <tt>rax</tt> register, or if it is a 128-bit value, then the higher 64-bits go in <tt>rdx</tt>. Optionally, functions push <tt>rbp</tt> such that the <tt>caller-return-rip</tt> is 8 bytes above it, and set <tt>rbp</tt> to the address of the saved rbp. This allows iterating through the existing stack frames. This can be eliminated by specifying the <tt>-fomit-frame-pointer</tt> GCC option.


Signal handlers are executed on the same stack, but 128 bytes known as the red zone is subtracted from the stack before anything is pushed to the stack. This allows small leaf functions to use 128 bytes of stack space without reserving stack space by subtracting from the stack pointer. The red zone is well-known to cause problems for x86-64 kernel developers, as the CPU itself doesn't respect the red zone when calling interrupt handlers. This leads to a subtle kernel breakage as the ABI contradicts the CPU behavior. The solution is to build all kernel code with <tt>-mno-red-zone</tt> or by handling interrupts in kernel mode on another stack than the current (and thus implementing the ABI).
Signal handlers are executed on the same stack, but 128 bytes known as the red zone is subtracted from the stack before anything is pushed to the stack. This allows small leaf functions to use 128 bytes of stack space without reserving stack space by subtracting from the stack pointer. The red zone is well-known to cause problems for x86-64 kernel developers, as the CPU itself doesn't respect the red zone when calling interrupt handlers. This leads to a subtle kernel breakage as the ABI contradicts the CPU behavior. The solution is to build all kernel code with <tt>-mno-red-zone</tt> or by handling interrupts in kernel mode on another stack than the current (and thus implementing the ABI).