X64的调用约定
2012-07-23 16:40
218 查看
接触x64之后继续看PG的文章,今天开始读msdn上有关x64的解释 http://msdn.microsoft.com/zh-cn/library/7kcdt6fy
调用约定简化了:一律使用__fastcall,前四个参数用 RCX、RDX、R8 和 R9传递,除了这四个外加RAX、R10、R11,其他寄存器都是非易失的。
比如下面这段NtCreateFile的代码:
平衡堆栈的任务交给调用者来完成了,这里入参没有用push而是sub xx 调用之后再add xx
另外这里没有用rbp来存储父esp,因为这只是prolog的一个可选项
MOV [RSP+8h],RCX
MOV [RSP+10h],RDX
MOV [RSP+18h],R8
MOV [RSP+20h],R9
PUSH RBP
MOV RBP,RSP
;……
LEA RSP,[RBP]
POP RBP
RET
具体可以看http://msdn.microsoft.com/zh-cn/library/tawsa7cb
寄存器的用法:
接下来要看的是x64异常处理
参考:
http://msdn.microsoft.com/zh-cn/library/7kcdt6fy
http://bbs.pediy.com/showthread.php?t=43967
调用约定简化了:一律使用__fastcall,前四个参数用 RCX、RDX、R8 和 R9传递,除了这四个外加RAX、R10、R11,其他寄存器都是非易失的。
比如下面这段NtCreateFile的代码:
PAGE:0000000140382B8C mov r11, rsp ;r11 保存rsp PAGE:0000000140382B8F sub rsp, 88h ;开辟压栈参数空间,而不是用push,前四个参数在寄存器中所以不管 PAGE:0000000140382B96 xor eax, eax PAGE:0000000140382B98 mov [r11-10h], rax PAGE:0000000140382B9C mov [rsp+88h+var_18], 20h PAGE:0000000140382BA4 mov [rsp+88h+var_20], eax PAGE:0000000140382BA8 mov [r11-28h], rax PAGE:0000000140382BAC mov [rsp+88h+var_30], eax PAGE:0000000140382BB0 mov eax, [rsp+88h+EaLength] ;其他参数拷贝入栈 PAGE:0000000140382BB7 mov [rsp+88h+var_38], eax PAGE:0000000140382BBB mov rax, [rsp+88h+EaBuffer] PAGE:0000000140382BC3 mov [r11-40h], rax PAGE:0000000140382BC7 mov eax, [rsp+88h+CreateOptions] PAGE:0000000140382BCE mov [rsp+88h+var_48], eax PAGE:0000000140382BD2 mov eax, [rsp+88h+CreateDisposition] PAGE:0000000140382BD9 mov [rsp+88h+var_50], eax PAGE:0000000140382BDD mov eax, [rsp+88h+ShareAccess] PAGE:0000000140382BE4 mov [rsp+88h+var_58], eax PAGE:0000000140382BE8 mov eax, [rsp+88h+FileAttributes] PAGE:0000000140382BEF mov [rsp+88h+var_60], eax PAGE:0000000140382BF3 mov rax, [rsp+88h+AllocationSize] PAGE:0000000140382BFB mov [r11-68h], rax PAGE:0000000140382BFF call IopCreateFile PAGE:0000000140382C04 add rsp, 88h ;平衡堆栈返回 PAGE:0000000140382C0B retn PAGE:0000000140382C0B NtCreateFile endp NtCreateFile是直接调用IoCreateFile的,比较特殊,下面跟进IoCreateFile PAGE:0000000140377CF0 ; FUNCTION CHUNK AT PAGE:00000001403D665F SIZE 0000008C BYTES PAGE:0000000140377CF0 PAGE:0000000140377CF0 mov [rsp+arg_18], r9 ;无论是否有四个参数,函数开头都会把这四个参数入栈 PAGE:0000000140377CF5 mov [rsp+arg_10], r8 PAGE:0000000140377CFA mov [rsp+arg_8], edx PAGE:0000000140377CFE mov [rsp+arg_0], rcx PAGE:0000000140377D03 push rbx ;微软承诺的非已易失寄存器,会全部入栈,这是 PAGE:0000000140377D04 push rsi PAGE:0000000140377D05 push rdi PAGE:0000000140377D06 push r12 PAGE:0000000140377D08 push r13 PAGE:0000000140377D0A push r14 PAGE:0000000140377D0C push r15 PAGE:0000000140377D0E sub rsp, 60h PAGE:0000000140377D12 mov r14d, edx PAGE:0000000140377D15 xor r15d, r15d PAGE:0000000140377D18 mov [rsp+98h+var_54], r15d PAGE:0000000140377D1D mov rax, gs:188h PAGE:0000000140377D26 mov r13d, [rsp+98h+arg_68] PAGE:0000000140377D2E movzx r12d, byte ptr [rax+1F6h] PAGE:0000000140377D36 bt r13d, 8 PAGE:0000000140377D3B cmovb r12d, r15d PAGE:0000000140377D3F mov rsi, gs:20h PAGE:0000000140377D48 mov rbx, [rsi+800h] PAGE:0000000140377D4F inc dword ptr [rbx+14h] PAGE:0000000140377D52 mov rcx, rbx ; ListHead PAGE:0000000140377D55 call RtlpInterlockedPopEntrySList ;epilog add rsp, 60h pop r15 pop r14 pop r13 pop r12 pop rdi pop rsi pop rbx retn
平衡堆栈的任务交给调用者来完成了,这里入参没有用push而是sub xx 调用之后再add xx
另外这里没有用rbp来存储父esp,因为这只是prolog的一个可选项
MOV [RSP+8h],RCX
MOV [RSP+10h],RDX
MOV [RSP+18h],R8
MOV [RSP+20h],R9
PUSH RBP
MOV RBP,RSP
;……
LEA RSP,[RBP]
POP RBP
RET
具体可以看http://msdn.microsoft.com/zh-cn/library/tawsa7cb
寄存器的用法:
Register | 状态 | 使用 |
RAX | 易失的 | 返回值寄存器 |
RCX | 易失的 | 第一个整型参数 |
RDX | 易失的 | 第二个整型参数 |
R8 | 易失的 | 第三个整型参数 |
R9 | 易失的 | 第四个整型参数 |
R10:R11 | 易失的 | 必须根据需要由调用方保留;在 syscall/sysret 指令中使用 |
R12:R15 | 非易失的 | 必须由被调用方保留 |
RDI | 非易失的 | 必须由被调用方保留 |
RSI | 非易失的 | 必须由被调用方保留 |
RBX | 非易失的 | 必须由被调用方保留 |
RBP | 非易失的 | 可用作帧指针;必须由被调用方保留 |
RSP | 非易失的 | 堆栈指针 |
XMM0 | 易失的 | 第一个 FP 参数 |
XMM1 | 易失的 | 第二个 FP 参数 |
XMM2 | 易失的 | 第三个 FP 参数 |
XMM3 | 易失的 | 第四个 FP 参数 |
XMM4:XMM5 | 易失的 | 必须根据需要由调用方保留 |
XMM6:XMM15 | 非易失的 | 必须根据需要由被调用方保留。 |
1: kd> bp iocreatefile 1: kd> g Breakpoint 0 hit nt!IoCreateFile: fffff800`0418bf40 4c8bdc mov r11,rsp 1: kd> dq rsp fffff880`03727568 fffff960`000d8bad 00000000`00000000 fffff880`03727578 00000000`000007ff 00000000`00000000 fffff880`03727588 00000000`00000001 00000000`00000000 fffff880`03727598 fffffa80`00000080 fffff8a0`00000001 fffff880`037275a8 00000000`00000001 00000000`00000010 fffff880`037275b8 00000000`00000000 fffff8a0`00000000 fffff880`037275c8 fffff8a0`00000000 00000000`00000000 fffff880`037275d8 fffff800`00000301 00000000`00000000 1: kd> u fffff960`000d8bad win32k!bCreateSection+0x129: fffff960`000d8bad 408ace mov cl,sil fffff960`000d8bb0 8bd8 mov ebx,eax fffff960`000d8bb2 ff15c88f2300 call qword ptr [win32k!_imp_IoSetThreadHardErrorMode (fffff960`00311b80)] fffff960`000d8bb8 413bdd cmp ebx,r13d fffff960`000d8bbb 7d07 jge win32k!bCreateSection+0x140 (fffff960`000d8bc4) fffff960`000d8bbd 33c0 xor eax,eax fffff960`000d8bbf e970020000 jmp win32k!bCreateSection+0x3b0 (fffff960`000d8e34) fffff960`000d8bc4 488b4c2470 mov rcx,qword ptr [rsp+70h] 1: kd> r rax=fffff88003727688 rbx=fffff900c0081000 rcx=fffff880037275e0 rdx=00000000001200a9 rsi=0000000000000001 rdi=0000000000000000 rip=fffff8000418bf40 rsp=fffff88003727568 rbp=fffff880037277d0 r8=fffff88003727608 r9=fffff880037275f0 r10=0000000000000000 r11=fffffa800ecc6860 r12=fffff88003727740 r13=0000000000000000 r14=0000000000000001 r15=fffff88003727920 iopl=0 nv up ei pl zr na po nc cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00000246 nt!IoCreateFile: fffff800`0418bf40 4c8bdc mov r11,rsp 1: kd> dt _OBJECT_ATTRIBUTES fffff88003727608 ntdll!_OBJECT_ATTRIBUTES +0x000 Length : 0x30 +0x008 RootDirectory : (null) +0x010 ObjectName : 0xfffff880`03727688 _UNICODE_STRING "\??\C:\WINDOWS\FONTS\EUDC.TTE" +0x018 Attributes : 0x240 +0x020 SecurityDescriptor : (null) +0x028 SecurityQualityOfService : (null)
接下来要看的是x64异常处理
参考:
http://msdn.microsoft.com/zh-cn/library/7kcdt6fy
http://bbs.pediy.com/showthread.php?t=43967
相关文章推荐
- X64平台调用约定
- x64的调用约定
- Windows x64汇编函数调用约定
- x64 调用约定,参数传递以及函数返回值
- x64 调用约定概述
- x64 stack walking、调用约定、函数参数识别
- x64不同平台的调用约定
- Windows x64汇编函数调用约定
- x64 linux c 调用约定
- x86 x64下调用约定浅析
- x64的调用约定
- 名字改编(name mangling)、调用约定与对策
- [转]论调用约定
- __declspec(dllimport)和__declspec(dllexport)的区别,以及有关c/c++调用约定
- 调用约定
- 论函数调用约定
- 论调用约定
- 一般函数指针和类的成员函数指针——其实是调用约定惹的事
- 调用约定(cdecl、fastcall、、thiscall)
- 函数调用约定 stdcall,cdecl,fastcall,thiscall,naked call