X64寄存器:
X64系统通用寄存器的名曾,第1个字母从“E”改为“R” (RAX)大小扩展到64位。数量增加了8个(R8~R15),使用WORD\BYTE\DWORD后缀。
调用约定:如果参数既有浮点类型,又有政署类型,例如“void fun(float,int,float,int)”,那么参数传递顺序为第1个参数(XMM0)、第二个参数(RDX)、第三个参数(XMM2)、第四个参数(R9)。
参数传递
两个例子 参数小于4时
#include "stdafx.h"
int Add(int nNum1, int nNum2) {
return nNum1 + nNum2;
}
int _tmain(int argc, _TCHAR* argv[]) {
printf("%d\r\n", Add(1, 2));
return 0;
}
用IDA Pro查看反汇编
.text:0000000140001040 main_0 proc near ; CODE XREF: mainj
.text:0000000140001040 ; DATA XREF: .pdata:000000014000A00Co
.text:0000000140001040
.text:0000000140001040 arg_0 = dword ptr 8
.text:0000000140001040 arg_8 = qword ptr 10h
.text:0000000140001040
.text:0000000140001040 mov [rsp+arg_8], rdx ;参数2
.text:0000000140001045 mov [rsp+arg_0], ecx ;参数1
.text:0000000140001049 push rdi ;保护环境
.text:000000014000104A sub rsp, 20h ;申请预留
.text:000000014000104E mov rdi, rsp ;初始化为0xcc
.text:0000000140001051 mov ecx, 8
.text:0000000140001056 mov eax, 0CCCCCCCCh
.text:000000014000105B rep stosd
.text:000000014000105D mov ecx, [rsp+28h+arg_0]
.text:0000000140001061 mov edx, 2 ;参数2:nNUM2
.text:0000000140001066 mov ecx, 1 ;参数1:nNUM1
.text:000000014000106B call sub_140001005 ;ADD函数
.text:0000000140001070 mov edx, eax
.text:0000000140001072 lea rcx, Format ; "%d\r\n"
.text:0000000140001079 call cs:printf
.text:000000014000107F xor eax, eax
.text:0000000140001081 add rsp, 20h
.text:0000000140001085 pop rdi
.text:0000000140001086 retn
.text:0000000140001086 main_0 endp
.text:0000000140001086
参数大于4时
#include "stdafx.h"
int Add(int nNum1, int nNum2, int nNum3, int nNum4, int nNum5, int nNum6) {
return nNum1 + nNum2 + nNum3 + nNum4 + nNum5 + nNum6;
}
int _tmain(int argc, _TCHAR* argv[]) {
printf("%d\r\n", Add(1, 2, 3, 4, 5, 6));
return 0;
}
.text:0000000140001060
.text:0000000140001060 mov [rsp+arg_8], rdx
.text:0000000140001065 mov [rsp+arg_0], ecx
.text:0000000140001069 push rdi
.text:000000014000106A sub rsp, 30h
.text:000000014000106E mov rdi, rsp
.text:0000000140001071 mov ecx, 0Ch
.text:0000000140001076 mov eax, 0CCCCCCCCh
.text:000000014000107B rep stosd
.text:000000014000107D mov ecx, [rsp+38h+arg_0]
.text:0000000140001081 mov [rsp+38h+var_10], 6
.text:0000000140001089 mov [rsp+38h+var_18], 5
.text:0000000140001091 mov r9d, 4
.text:0000000140001097 mov r8d, 3
.text:000000014000109D mov edx, 2
.text:00000001400010A2 mov ecx, 1
.text:00000001400010A7 call sub_140001005
.text:00000001400010AC mov edx, eax
.text:00000001400010AE lea rcx, Format ; "%d\r\n"
.text:00000001400010B5 call cs:printf
.text:00000001400010BB xor eax, eax
.text:00000001400010BD add rsp, 30h
.text:00000001400010C1 pop rdi
.text:00000001400010C2 retn
ADD反汇编
.text:0000000140001020 arg_0 = dword ptr 8
.text:0000000140001020 arg_8 = dword ptr 10h
.text:0000000140001020 arg_10 = dword ptr 18h
.text:0000000140001020 arg_18 = dword ptr 20h
.text:0000000140001020 arg_20 = dword ptr 28h
.text:0000000140001020 arg_28 = dword ptr 30h
.text:0000000140001020
.text:0000000140001020 mov [rsp+arg_18], r9d
.text:0000000140001025 mov [rsp+arg_10], r8d
.text:000000014000102A mov [rsp+arg_8], edx
.text:000000014000102E mov [rsp+arg_0], ecx
.text:0000000140001032 push rdi
.text:0000000140001033 mov eax, [rsp+8+arg_8]
.text:0000000140001037 mov ecx, [rsp+8+arg_0]
.text:000000014000103B add ecx, eax
.text:000000014000103D mov eax, ecx
.text:000000014000103F add eax, [rsp+8+arg_10]
.text:0000000140001043 add eax, [rsp+8+arg_18]
.text:0000000140001047 add eax, [rsp+8+arg_20]
.text:000000014000104B add eax, [rsp+8+arg_28]
.text:000000014000104F pop rdi
.text:0000000140001050 retn
如果参数多于4个,前4个参数同福哦寄存器传递,从第五个参数开始使用栈传递。
对于参数为结构体则是如果参数结构体小于8字节,在传递结构体参数是,应直接吧整个结构体的内容放在寄存器中。在函数里,通过访问寄存器的高32为和低32为来分别访问结构体的成员。
如果参数结构体大于8字节的,在传递参数时,会先把结构内容复制到栈空间中,再把结构体地址当成函数的参数来传递。