简体   繁体   English

i386 和 x86-64 上的 UNIX 和 Linux 系统调用(和用户空间函数)的调用约定是什么

[英]What are the calling conventions for UNIX & Linux system calls (and user-space functions) on i386 and x86-64

Following links explain x86-32 system call conventions for both UNIX (BSD flavor) & Linux:以下链接解释了 UNIX(BSD 风格)和 Linux 的 x86-32 系统调用约定:

But what are the x86-64 system call conventions on both UNIX & Linux?但是 UNIX 和 Linux 上的 x86-64 系统调用约定是什么?

Further reading for any of the topics here: The Definitive Guide to Linux System Calls进一步阅读此处的任何主题: Linux 系统调用权威指南


I verified these using GNU Assembler (gas) on Linux.我在 Linux 上使用 GNU Assembler (gas) 验证了这些。

Kernel Interface内核接口

x86-32 aka i386 Linux System Call convention: x86-32 又名 i386 Linux 系统调用约定:

In x86-32 parameters for Linux system call are passed using registers.在 x86-32 中,Linux 系统调用的参数是使用寄存器传递的。 %eax for syscall_number. %eax为 syscall_number。 %ebx, %ecx, %edx, %esi, %edi, %ebp are used for passing 6 parameters to system calls. %ebx, %ecx, %edx, %esi, %edi, %ebp 用于将 6 个参数传递给系统调用。

The return value is in %eax .返回值在%eax All other registers (including EFLAGS) are preserved across the int $0x80 .所有其他寄存器(包括 EFLAGS)都保留在int $0x80

I took following snippet from the Linux Assembly Tutorial but I'm doubtful about this.我从Linux 汇编教程中获取了以下片段,但我对此表示怀疑。 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.如果有六个以上的参数, %ebx必须包含存储参数列表的内存位置 - 但不要担心这一点,因为您不太可能使用具有六个以上参数的系统调用。

For an example and a little more reading, refer to http://www.int80h.org/bsdasm/#alternate-calling-convention .有关示例和更多阅读内容,请参阅http://www.int80h.org/bsdasm/#alternate-calling-convention Another example of a Hello World for i386 Linux using int 0x80 : Hello, world in assembly language with Linux system calls?另一个使用int 0x80 i386 Linux Hello World 示例: Hello, world in assembly language with Linux system calls?

There is a faster way to make 32-bit system calls: using sysenter .有一种更快的方法来进行 32 位系统调用:使用sysenter The kernel maps a page of memory into every process (the vDSO), with the user-space side of the sysenter dance, which has to cooperate with the kernel for it to be able to find the return address.内核的内存页映射到每一个进程(VDSO),与用户空间侧sysenter舞,这与内核合作,它能够找到返回地址。 Arg to register mapping is the same as for int $0x80 .注册映射的 Arg 与int $0x80相同。 You should normally call into the vDSO instead of using sysenter directly.通常应调入VDSO而是采用sysenter直接。 (See The Definitive Guide to Linux System Calls for info on linking and calling into the vDSO, and for more info on sysenter , and everything else to do with system calls.) (见权威指南到Linux系统调用有关链接和调用到VDSO,以及有关的详细信息信息sysenter ,一切做系统调用)。

x86-32 [Free|Open|Net|DragonFly]BSD UNIX System Call convention: x86-32 [Free|Open|Net|DragonFly]BSD UNIX 系统调用约定:

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然后推送额外的 32 位虚拟数据(它实际上不是虚拟数据。请参阅以下链接了解更多信息),然后给出系统调用指令int $0x80

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


x86-64 Linux System Call convention: x86-64 Linux 系统调用约定:

(Note: x86-64 Mac OS X is similar but different from Linux. TODO: check what *BSD does) (注意: x86-64 Mac OS X 与Linux 相似但不同。TODO:检查 *BSD 做了什么)

Refer to section: "A.2 AMD64 Linux Kernel Conventions" of System V Application Binary Interface AMD64 Architecture Processor Supplement .请参阅System V Application Binary Interface AMD64 Architecture Processor Supplement 的“A.2 AMD64 Linux Kernel Conventions”部分。 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 .最新版本的 i386 和 x86-64 System V psABI 可以从 ABI 维护者的 repo 中的这个页面找到链接 (See also the tag wiki for up-to-date ABI links and lots of other good stuff about x86 asm.) (另请参阅标签 wiki 以获取最新的 ABI 链接和许多其他关于 x86 asm 的好东西。)

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.用户级应用程序使用整数寄存器来传递序列 %rdi、%rsi、%rdx、%rcx、%r8 和 %r9。 The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.内核接口使用 %rdi、%rsi、%rdx、%r10、%r8 和 %r9。
  2. A system-call is done via the syscall instruction .系统调用是通过syscall指令完成的。 This clobbers %rcx and %r11 as well as the %rax return value, but other registers are preserved.这会破坏 %rcx 和 %r11以及 %rax 返回值,但保留其他寄存器。
  3. The number of the syscall has to be passed in register %rax.系统调用的编号必须在寄存器 %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.从系统调用返回,寄存器 %rax 包含系统调用的结果。 A value in the range between -4095 and -1 indicates an error, it is -errno . -4095 和 -1 之间范围内的值表示错误,它是-errno
  6. Only values of class INTEGER or class MEMORY are passed to the kernel.只有类 INTEGER 或类 MEMORY 的值被传递给内核。

Remember this is from the Linux-specific appendix to the ABI, and even for Linux it's informative not normative.请记住,这是来自 ABI 的特定于 Linux 的附录,即使对于 Linux,它也是信息性的而非规范性的。 (But it is in fact accurate.) (但实际上它是准确的。)

This 32-bit int $0x80 ABI is usable in 64-bit code (but highly not recommended).这个 32 位int $0x80 ABI用于 64 位代码(但强烈不推荐)。 What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code? 如果在 64 位代码中使用 32 位 int 0x80 Linux ABI,会发生什么? It still truncates its inputs to 32-bit, so it's unsuitable for pointers, and it zeros r8-r11.它仍然将其输入截断为 32 位,因此它不适合指针,并将 r8-r11 置零。

User Interface: function calling用户界面:函数调用

x86-32 Function Calling convention: x86-32 函数调用约定:

In x86-32 parameters were passed on stack.在 x86-32 中,参数在堆栈上传递。 Last parameter was pushed first on to the stack until all parameters are done and then call instruction was executed.最后一个参数首先被压入堆栈,直到所有参数都完成,然后call指令被执行。 This is used for calling C library (libc) functions on Linux from assembly.这用于从汇编调用 Linux 上的 C 库 (libc) 函数。

Modern versions of the i386 System V ABI (used on Linux) require 16-byte alignment of %esp before a call , like the x86-64 System V ABI has always required. i386 System V ABI 的现代版本(在 Linux 上使用)在call之前需要%esp 16 字节对齐,就像 x86-64 System V ABI 一直需要的那样。 Callees are allowed to assume that and use SSE 16-byte loads/stores that fault on unaligned.允许被调用者假设并使用在未对齐时出错的 SSE 16 字节加载/存储。 But historically, Linux only required 4-byte stack alignment, so it took extra work to reserve naturally-aligned space even for an 8-byte double or something.但从历史上看,Linux 只需要 4 字节的堆栈对齐,因此即使为 8 字节的double或其他东西保留自然对齐的空间也需要额外的工作。

Some other modern 32-bit systems still don't require more than 4 byte stack alignment.其他一些现代 32 位系统仍然不需要超过 4 字节的堆栈对齐。


x86-64 System V user-space Function Calling convention: x86-64 System V 用户空间函数调用约定:

x86-64 System V passes args in registers, which is more efficient than i386 System V's stack args convention. x86-64 System V 在寄存器中传递 args,这比 i386 System V 的堆栈 args 约定更有效。 It avoids the latency and extra instructions of storing args to memory (cache) and then loading them back again in the callee.它避免了将 args 存储到内存(缓存)然后在被调用者中再次加载它们的延迟和额外指令。 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.这很有效,因为有更多可用的寄存器,并且更适合延迟和乱序执行很重要的现代高性能 CPU。 (The i386 ABI is very old). (i386 ABI 很旧了)。

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:有关完整信息,请参阅: System V Application Binary Interface AMD64 Architecture Processor Supplement 的“3.2 Function Calling Sequence”,部分内容如下:

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.如果类是 MEMORY,则在堆栈上传递参数。
  2. If the class is INTEGER, the next available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9 is used如果类是整数,则使用序列 %rdi、%rsi、%rdx、%rcx、%r8 和 %r9 的下一个可用寄存器

So %rdi, %rsi, %rdx, %rcx, %r8 and %r9 are the registers in order used to pass integer/pointer (ie INTEGER class) parameters to any libc function from assembly.所以%rdi, %rsi, %rdx, %rcx, %r8 and %r9是用于/指针(即INTEGER类)参数从组件传递给任何libc函数整数,以便在寄存器中。 %rdi is used for the first INTEGER parameter. %rdi 用于第一个 INTEGER 参数。 %rsi for 2nd, %rdx for 3rd and so on. %rsi 表示第二个,%rdx 表示第三个,依此类推。 Then call instruction should be given.然后应给出call指令。 The stack ( %rsp ) must be 16B-aligned when call executes. call执行时,堆栈 ( %rsp ) 必须是 16B 对齐的。

If there are more than 6 INTEGER parameters, the 7th INTEGER parameter and later are passed on the stack.如果有超过 6 个 INTEGER 参数,则第 7 个 INTEGER 参数及之后的参数将在堆栈上传递。 (Caller pops, same as x86-32.) (来电弹出,与 x86-32 相同。)

The first 8 floating point args are passed in %xmm0-7, later on the stack.前 8 个浮点参数在 %xmm0-7 中传递,稍后在堆栈中。 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.) (混合了 FP 和整数参数的函数可以有 8 个以上的寄存器参数。)

Variadic functions ( like printf ) always need %al = the number of FP register args.可变参数函数( printf )总是需要%al = FP 寄存器参数的数量。

There are rules for when to pack structs into registers ( rdx:rax on return) vs. in memory.关于何时将结构打包到寄存器(返回时为rdx:rax )与内存中的规则。 See the ABI for details, and check compiler output to make sure your code agrees with compilers about how something should be passed/returned.有关详细信息,请参阅 ABI,并检查编译器输出以确保您的代码与编译器就应如何传递/返回某些内容达成一致。


Note that the Windows x64 function calling convention has multiple significant differences from x86-64 System V, like shadow space that must be reserved by the caller (instead of a red-zone), and call-preserved xmm6-xmm15.请注意, Windows x64 函数调用约定与 x86-64 System V 有多个显着差异,例如调用者必须保留的阴影空间(而不是红色区域)和调用保留的 xmm6-xmm15。 And very different rules for which arg goes in which register.对于哪个 arg 进入哪个寄存器的非常不同的规则。

Perhaps you're looking for the x86_64 ABI?也许您正在寻找 x86_64 ABI?

If that's not precisely what you're after, use 'x86_64 abi' in your preferred search engine to find alternative references.如果这不是您想要的,请在您首选的搜索引擎中使用“x86_64 abi”来查找替代参考。

Linux kernel 5.0 source comments Linux 内核 5.0 源码注释

I knew that x86 specifics are under arch/x86 , and that syscall stuff goes under arch/x86/entry .我知道 x86 细节在arch/x86下,系统调用的东西在arch/x86/entry So a quick git grep rdi in that directory leads me to arch/x86/entry/entry_64.S :因此,该目录中的快速git grep rdi将我引导至arch/x86/entry/entry_64.S

/*
 * 64-bit SYSCALL instruction entry. Up to 6 arguments in registers.
 *
 * This is the only entry point used for 64-bit system calls.  The
 * hardware interface is reasonably well designed and the register to
 * argument mapping Linux uses fits well with the registers that are
 * available when SYSCALL is used.
 *
 * SYSCALL instructions can be found inlined in libc implementations as
 * well as some other programs and libraries.  There are also a handful
 * of SYSCALL instructions in the vDSO used, for example, as a
 * clock_gettimeofday fallback.
 *
 * 64-bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
 * then loads new ss, cs, and rip from previously programmed MSRs.
 * rflags gets masked by a value from another MSR (so CLD and CLAC
 * are not needed). SYSCALL does not save anything on the stack
 * and does not change rsp.
 *
 * Registers on entry:
 * rax  system call number
 * rcx  return address
 * r11  saved rflags (note: r11 is callee-clobbered register in C ABI)
 * rdi  arg0
 * rsi  arg1
 * rdx  arg2
 * r10  arg3 (needs to be moved to rcx to conform to C ABI)
 * r8   arg4
 * r9   arg5
 * (note: r12-r15, rbp, rbx are callee-preserved in C ABI)
 *
 * Only called from user space.
 *
 * When user can change pt_regs->foo always force IRET. That is because
 * it deals with uncanonical addresses better. SYSRET has trouble
 * with them due to bugs in both AMD and Intel CPUs.
 */

and for 32-bit at arch/x86/entry/entry_32.S :对于 32 位的arch/x86/entry/entry_32.S

/*
 * 32-bit SYSENTER entry.
 *
 * 32-bit system calls through the vDSO's __kernel_vsyscall enter here
 * if X86_FEATURE_SEP is available.  This is the preferred system call
 * entry on 32-bit systems.
 *
 * The SYSENTER instruction, in principle, should *only* occur in the
 * vDSO.  In practice, a small number of Android devices were shipped
 * with a copy of Bionic that inlined a SYSENTER instruction.  This
 * never happened in any of Google's Bionic versions -- it only happened
 * in a narrow range of Intel-provided versions.
 *
 * SYSENTER loads SS, ESP, CS, and EIP from previously programmed MSRs.
 * IF and VM in RFLAGS are cleared (IOW: interrupts are off).
 * SYSENTER does not save anything on the stack,
 * and does not save old EIP (!!!), ESP, or EFLAGS.
 *
 * To avoid losing track of EFLAGS.VM (and thus potentially corrupting
 * user and/or vm86 state), we explicitly disable the SYSENTER
 * instruction in vm86 mode by reprogramming the MSRs.
 *
 * Arguments:
 * eax  system call number
 * ebx  arg1
 * ecx  arg2
 * edx  arg3
 * esi  arg4
 * edi  arg5
 * ebp  user stack
 * 0(%ebp) arg6
 */

glibc 2.29 Linux x86_64 system call implementation glibc 2.29 Linux x86_64 系统调用实现

Now let's cheat by looking at a major libc implementations and see what they are doing.现在让我们通过查看主要的 libc 实现来作弊,看看它们在做什么。

What could be better than looking into glibc that I'm using right now as I write this answer?有什么比在我写这个答案时查看我现在正在使用的 glibc 更好的呢? :-) :-)

glibc 2.29 defines x86_64 syscalls at sysdeps/unix/sysv/linux/x86_64/sysdep.h and that contains some interesting code, eg: glibc 2.29 在sysdeps/unix/sysv/linux/x86_64/sysdep.h定义了 x86_64 系统调用,其中包含一些有趣的代码,例如:

/* The Linux/x86-64 kernel expects the system call parameters in
   registers according to the following table:

    syscall number  rax
    arg 1       rdi
    arg 2       rsi
    arg 3       rdx
    arg 4       r10
    arg 5       r8
    arg 6       r9

    The Linux kernel uses and destroys internally these registers:
    return address from
    syscall     rcx
    eflags from syscall r11

    Normal function call, including calls to the system call stub
    functions in the libc, get the first six parameters passed in
    registers and the seventh parameter and later on the stack.  The
    register use is as follows:

     system call number in the DO_CALL macro
     arg 1      rdi
     arg 2      rsi
     arg 3      rdx
     arg 4      rcx
     arg 5      r8
     arg 6      r9

    We have to take care that the stack is aligned to 16 bytes.  When
    called the stack is not aligned since the return address has just
    been pushed.


    Syscalls of more than 6 arguments are not supported.  */

and:和:

/* Registers clobbered by syscall.  */
# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"

#undef internal_syscall6
#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \
({                                  \
    unsigned long int resultvar;                    \
    TYPEFY (arg6, __arg6) = ARGIFY (arg6);              \
    TYPEFY (arg5, __arg5) = ARGIFY (arg5);              \
    TYPEFY (arg4, __arg4) = ARGIFY (arg4);              \
    TYPEFY (arg3, __arg3) = ARGIFY (arg3);              \
    TYPEFY (arg2, __arg2) = ARGIFY (arg2);              \
    TYPEFY (arg1, __arg1) = ARGIFY (arg1);              \
    register TYPEFY (arg6, _a6) asm ("r9") = __arg6;            \
    register TYPEFY (arg5, _a5) asm ("r8") = __arg5;            \
    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;           \
    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;           \
    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;           \
    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;           \
    asm volatile (                          \
    "syscall\n\t"                           \
    : "=a" (resultvar)                          \
    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),     \
      "r" (_a5), "r" (_a6)                      \
    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);            \
    (long int) resultvar;                       \
})

which I feel are pretty self explanatory.我觉得这是不言自明的。 Note how this seems to have been designed to exactly match the calling convention of regular System V AMD64 ABI functions: https://en.wikipedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions请注意这似乎是如何设计为与常规 System V AMD64 ABI 函数的调用约定完全匹配的: https : //en.wikipedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions

Quick reminder of the clobbers:快速提醒clobbers:

  • cc means flag registers. cc表示标志寄存器。 But Peter Cordes comments that this is unnecessary here.Peter Cordes 评论说,这在这里是不必要的。
  • memory means that a pointer may be passed in assembly and used to access memory memory表示可以在汇编中传递指针并用于访问内存

For an explicit minimal runnable example from scratch see this answer: How to invoke a system call via syscall or sysenter in inline assembly?有关从头开始的显式最小可运行示例,请参阅以下答案: 如何在内联汇编中通过 syscall 或 sysenter 调用系统调用?

Make some syscalls in assembly manually手动在程序集中进行一些系统调用

Not very scientific, but fun:不是很科学,但很有趣:

  • x86_64.S x86_64.S

     .text .global _start _start: asm_main_after_prologue: /* write */ mov $1, %rax /* syscall number */ mov $1, %rdi /* stdout */ mov $msg, %rsi /* buffer */ mov $len, %rdx /* len */ syscall /* exit */ mov $60, %rax /* syscall number */ mov $0, %rdi /* exit status */ syscall msg: .ascii "hello\\n" len = . - msg

    GitHub upstream . GitHub 上游.

Make system calls from C从 C 进行系统调用

Here's an example with register constraints: How to invoke a system call via syscall or sysenter in inline assembly?这是一个带有寄存器约束的示例: 如何在内联汇编中通过 syscall 或 sysenter 调用系统调用?

aarch64 aarch64

I've shown a minimal runnable userland example at: https://reverseengineering.stackexchange.com/questions/16917/arm64-syscalls-table/18834#18834 TODO grep kernel code here, should be easy.我在此处展示了一个最小的可运行用户空间示例: https: //reverseengineering.stackexchange.com/questions/16917/arm64-syscalls-table/18834#18834 TODO grep 内核代码在这里,应该很容易。

Calling conventions defines how parameters are passed in the registers when calling or being called by other program.调用约定定义了在调用或被其他程序调用时如何在寄存器中传递参数。 And the best source of these convention is in the form of ABI standards defined for each these hardware.这些约定的最佳来源是为每个这些硬件定义的 ABI 标准。 For ease of compilation, the same ABI is also used by userspace and kernel program.为了便于编译,用户空间和内核程序也使用相同的 ABI。 Linux/Freebsd follow the same ABI for x86-64 and another set for 32-bit. Linux/Freebsd 对 x86-64 遵循相同的 ABI,对 32 位遵循相同的 ABI。 But x86-64 ABI for Windows is different from Linux/FreeBSD.但是用于 Windows 的 x86-64 ABI 与 Linux/FreeBSD 不同。 And generally ABI does not differentiate system call vs normal "functions calls".通常 ABI 不会区分系统调用与正常的“函数调用”。 Ie, here is a particular example of x86_64 calling conventions and it is the same for both Linux userspace and kernel: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/ (note the sequence a,b,c,d,e,f of parameters):即,这是 x86_64 调用约定的一个特定示例,它对于 Linux 用户空间和内核都是相同的: http : //eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64 / (注意参数的序列 a,b,c,d,e,f):

调用约定与寄存器使用的良好呈现

Performance is one of the reasons for these ABI (eg, passing parameters via registers instead of saving into memory stacks)性能是这些 ABI 的原因之一(例如,通过寄存器传递参数而不是保存到内存堆栈中)

For ARM there is various ABI:对于 ARM,有各种 ABI:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference.pdf https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference.pdf

ARM64 convention: ARM64 约定:

http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf

For Linux on PowerPC:对于 PowerPC 上的 Linux:

http://refspecs.freestandards.org/elf/elfspec_ppc.pdf http://refspecs.freestandards.org/elf/elfspec_ppc.pdf

http://www.0x04.net/doc/elf/psABI-ppc64.pdf http://www.0x04.net/doc/elf/psABI-ppc64.pdf

And for embedded there is the PPC EABI:对于嵌入式,有 PPC EABI:

http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf

This document is good overview of all the different conventions:本文档很好地概述了所有不同的约定:

http://www.agner.org/optimize/calling_conventions.pdf http://www.agner.org/optimize/calling_conventions.pdf

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 as 和 ld 在 x86-64 Linux 上组装并运行 i386 asm 程序 - Assemble and run i386 asm program on x86-64 Linux with as and ld i386 输入文件的架构与 i386:x86-64 不兼容 - Architecture of i386 input file is incompatible with i386:x86-64 timer_create在i386系统上导致分段错误,但在x86_64系统上未引起分段错误(linux) - timer_create causing segmentation fault on i386 system, but not x86_64 system(linux) GCC:输入文件“ ../window.ui.o”的i386体系结构与i386:x86-64输出不兼容 - GCC: i386 architecture of input file `../window.ui.o' is incompatible with i386:x86-64 output 适用于i386和x86_64的Linux单个二进制文件 - Linux single binary for i386 and x86_64 GDB 错误:所选架构 i386 与报告的目标架构 i386:x86-64 不兼容 - GDB error: Selected architecture i386 is not compatible with reported target architecture i386:x86-64 为什么x86-64 Linux系统调用会修改RCX,值是什么意思? - Why do x86-64 Linux system calls modify RCX, and what does the value mean? 分段故障组装i386:x86_64 - Segmentation fault assembly i386:x86_64 如何使用 x86-64 Linux 系统调用附加到文件? - How to append to a file using x86-64 Linux system calls? i386:x64-32 vs i386 vs i386:x86_64之间的差异 - difference between i386:x64-32 vs i386 vs i386:x86_64
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM