您的位置:首页 > 其它

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的代码:

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: