x86-64传参规则

  1. 一个参数用rdi(edi)传
  2. 两个参数用rdi、rsi(edi、rsi)传
  3. 三个参数用rdi、rsi、rdx(edi、esi、edx)传
  4. 四个参数用rdi、rsi、rdx、rcx(edi、esi、edx、ecx)传
  5. 五个参数用rdi、rsi、rdx、rcx、r8(edi、esi、edx、ecx、r8)传
  6. 六个参数用rdi、rsi、rdx、rcx、r8、r9(edi、esi、edx、ecx、r8、r9)传

这里用gcc编了一个小程序用来验证传参规则

source


#include<stdio.h>
void fun1(int a)
{}
void fun2(int a,int b)
{}
void fun3(int a,int b,int c)
{}
void fun4(int a,int b,int c,int d)
{}
void fun5(int a,int b,int c,int d,int e)
{}
void fun6(int a,int b,int c,int d,int e,int f)
{}
void main()
{
	int a,b,c,d,e,f;
	a=b=c=d=e=f=2;
	fun1(a);
	fun2(a,b);
	fun3(a,b,c);
	fun4(a,b,c,d);
	fun5(a,b,c,d,e);
	fun6(a,b,c,d,e,f);
}

disassemble



   0x0000555555554696 <+48>:	mov    edi,eax
   0x0000555555554698 <+50>:	call   0x5555555545fa <fun1>//一个参数用edi(rdi)传
   0x000055555555469d <+55>:	mov    edx,DWORD PTR [rbp-0x8]
   0x00005555555546a0 <+58>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555546a3 <+61>:	mov    esi,edx
   0x00005555555546a5 <+63>:	mov    edi,eax
   0x00005555555546a7 <+65>:	call   0x555555554604 <fun2>//两个参数用edi、rsi(rdi、rsi)传
   0x00005555555546ac <+70>:	mov    edx,DWORD PTR [rbp-0xc]
   0x00005555555546af <+73>:	mov    ecx,DWORD PTR [rbp-0x8]
   0x00005555555546b2 <+76>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555546b5 <+79>:	mov    esi,ecx
   0x00005555555546b7 <+81>:	mov    edi,eax
   0x00005555555546b9 <+83>:	call   0x555555554611 <fun3>//三个参数用edi、esi、edx(rdi、rsi、rdx)传
   0x00005555555546be <+88>:	mov    ecx,DWORD PTR [rbp-0x10]
   0x00005555555546c1 <+91>:	mov    edx,DWORD PTR [rbp-0xc]
   0x00005555555546c4 <+94>:	mov    esi,DWORD PTR [rbp-0x8]
   0x00005555555546c7 <+97>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555546ca <+100>:	mov    edi,eax
   0x00005555555546cc <+102>:	call   0x555555554621 <fun4>//四个参数用edi、esi、edx、ecx(rdi、rsi、rdx、rcx)传
   0x00005555555546d1 <+107>:	mov    edi,DWORD PTR [rbp-0x14]
   0x00005555555546d4 <+110>:	mov    ecx,DWORD PTR [rbp-0x10]
   0x00005555555546d7 <+113>:	mov    edx,DWORD PTR [rbp-0xc]
   0x00005555555546da <+116>:	mov    esi,DWORD PTR [rbp-0x8]
   0x00005555555546dd <+119>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555546e0 <+122>:	mov    r8d,edi
   0x00005555555546e3 <+125>:	mov    edi,eax
   0x00005555555546e5 <+127>:	call   0x555555554634 <fun5>//五个参数用edi、esi、edx、ecx、r8(rdi、rsi、rdx、rcx、r8)传
   0x00005555555546ea <+132>:	mov    r8d,DWORD PTR [rbp-0x18]
   0x00005555555546ee <+136>:	mov    edi,DWORD PTR [rbp-0x14]
   0x00005555555546f1 <+139>:	mov    ecx,DWORD PTR [rbp-0x10]
   0x00005555555546f4 <+142>:	mov    edx,DWORD PTR [rbp-0xc]
   0x00005555555546f7 <+145>:	mov    esi,DWORD PTR [rbp-0x8]
   0x00005555555546fa <+148>:	mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555546fd <+151>:	mov    r9d,r8d
   0x0000555555554700 <+154>:	mov    r8d,edi
   0x0000555555554703 <+157>:	mov    edi,eax
   0x0000555555554705 <+159>:	call   0x55555555464b <fun6>//六个参数用edi、esi、edx、ecx、r8、r9(rdi、rsi、rdx、rcx、r8、r9)传

 

<think>嗯,用户想了解GCC生成的静态库(.a文件)在x86x64架构之间的差异。我需要先回忆一下静态库的基本结构。静态库其实就是多个目标文件(.o)的归档,使用ar命令打包的。所以,差异可能主要在于目标文件的架构不同。 首先,目标文件的格式应该不同,x86是32位,而x6464位。这会影响指令集、寄存器大小、调用约定等。比如,x86使用像eax这样的32位寄存器,而x64使用rax这样的64位寄存器,并且参数传递的方式也不同,x64可能会用更多的寄存器来传递参数,而不是堆栈。 然后,ABI(应用程序二进制接口)的不同也是一个关键点。ABI涉及函数调用约定、结构体对齐、异常处理等。比如,x86x64在函数调用时参数传递的顺序和方式不同,这会导致同样的代码编译出的目标文件不兼容。比如,x64通常用rdi, rsi, rdx等寄存器传递前几个参数,而x86可能通过堆栈传递。 接下来,内存寻址方式也不同。x64支持更大的地址空间,指针大小是8字节,而x86是4字节。如果库中有指针操作或数据结构依赖指针大小,就会导致问题。比如,一个在x86上编译的库处理指针时可能截断高32位,导致在x64上运行出错。 符号的重定位也可能不同。不同架构的目标文件在链接时需要正确的重定位信息,如果混合使用会导致链接失败。比如,尝试将x86的.o文件链接到x64程序中,链接器会报错关于架构不匹配。 还有,工具链的兼容性。编译静态库时使用的gcc版本和选项必须与目标架构一致。比如,使用-m32选项生成x86库,而默认可能是x64。如果交叉编译的话,可能需要指定目标平台。 另外,用户提供的引用中提到NDK不同版本处理libgcc的情况,这可能涉及到运行时库的依赖。不过静态库一般是编译时链接,所以可能更多是ABI和指令集的兼容性问题。比如,如果静态库使用了特定架构的指令(如SSE扩展),在另一架构上无法运行。 最后,需要总结如何区分和处理这两种库。比如,使用file命令检查库的架构,编译时正确指定目标平台,避免混合链接等。</think>### GCC静态库(.a)在x86x64架构的差异 #### 1. 目标文件格式差异 静态库文件`.a`本质上是多个`.o`目标文件的归档集合。x86(32位)和x6464位)架构的目标文件具有不同的机器指令编码和寄存器结构: - **x86**:使用32位指令集(如`mov eax, 1`),寄存器命名如`eax/ebx/ecx` - **x64**:使用64位指令集(如`mov rax, 1`),寄存器扩展为`rax/rbx/rcx`并新增`r8-r15`寄存器[^1] #### 2. ABI兼容性问题 不同架构的ABI(应用程序二进制接口)差异显著: | 特性 | x86 | x64 | |----------|--------------|--------------------| | 调用约定 | `cdecl`(栈传参) | `System V AMD64`(寄存器优先) | | 指针大小 | 4字节 | 8字节 | | 结构体对齐规则 | 4字节对齐 | 16字节对齐(SSE相关) | ```bash # 查看目标文件架构 file libexample.a # 输出示例:x86: "ELF 32-bit LSB relocatable, Intel 80386" # x64: "ELF 64-bit LSB relocatable, x86-64" ``` #### 3. 内存寻址差异 - x64支持48位虚拟地址空间(理论最大256TB),x86仅支持4GB线性地址 - 混合链接不同架构库会导致`relocation truncated to fit`错误[^4] #### 4. 工具链要求 编译时需明确指定目标架构: ```bash # x86编译 gcc -m32 -c source.c ar rcs libx86.a source.o # x64编译 gcc -m64 -c source.c ar rcs libx64.a source.o ``` #### 5. 符号冲突问题 同一静态库若包含混合架构目标文件,链接时会产生`skipping incompatible`警告: ``` ld: warning: libexample.a(x.o): skipping incompatible archive ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值