1. 程式人生 > >常見函式呼叫約定(x86、x64、arm、arm64)

常見函式呼叫約定(x86、x64、arm、arm64)

我學習逆向,整理的一些常見的函式呼叫約定反彙編筆記。由於我是新手,肯定有一些疏漏不完善的,我遇到了會實時更新的。

X86 函式呼叫約定

X86 有三種常用呼叫約定,cdecl(C規範)/stdcall(WinAPI預設)/fastcall 函式呼叫約定。

cdecl 函式呼叫約定

引數從右往左一次入棧,呼叫者實現棧平衡,返回值存放在 EAX 中。

20:       int cdecl_sum = cdecl_add(1, 2, 3, 4, 5, 6, 7);
00401138   push        7
0040113A   push        6
0040113
C push 5 0040113E push 4 00401140 push 3 00401142 push 2 00401144 push 1 00401146 call @ILT+5(_cdecl_add) (0040100a) 0040114B add esp,1Ch # 棧平衡 0040114E mov dword ptr [ebp-4],eax # 返回值 3: int __cdecl cdecl_add(int a, int b, int c, int d, int e, int f, int g) 4
: { 00401030 push ebp 00401031 mov ebp,esp 00401033 sub esp,44h 00401036 push ebx 00401037 push esi 00401038 push edi 00401039 lea edi,[ebp-44h] 0040103C mov ecx,11h 00401041 mov eax,0CCCCCCCCh 00401046 rep stos dword ptr [edi] 5: int sum = a+b+c+d+e+f+g;
00401048 mov eax,dword ptr [ebp+8] 0040104B add eax,dword ptr [ebp+0Ch] 0040104E add eax,dword ptr [ebp+10h] 00401051 add eax,dword ptr [ebp+14h] 00401054 add eax,dword ptr [ebp+18h] 00401057 add eax,dword ptr [ebp+1Ch] 0040105A add eax,dword ptr [ebp+20h] 0040105D mov dword ptr [ebp-4],eax 6: return sum; 00401060 mov eax,dword ptr [ebp-4] # 存放返回值 7: } 00401063 pop edi 00401064 pop esi 00401065 pop ebx 00401066 mov esp,ebp 00401068 pop ebp 00401069 ret

stdcall 函式呼叫約定

引數從右往左一次入棧,被呼叫者實現棧平衡,返回值存放在 EAX 中。

21:       int stdcall_sum = stdcall_add(1, 2, 3, 4, 5, 6, 7);
00401151   push        7
00401153   push        6
00401155   push        5
00401157   push        4
00401159   push        3
0040115B   push        2
0040115D   push        1
0040115F   call        @ILT+15(_stdcall_add@28) (00401014)
00401164   mov         dword ptr [ebp-8],eax    # 返回值

9:    int __stdcall stdcall_add(int a, int b, int c, int d, int e, int f, int g)
10:   {
00401080   push        ebp
00401081   mov         ebp,esp
00401083   sub         esp,44h
00401086   push        ebx
00401087   push        esi
00401088   push        edi
00401089   lea         edi,[ebp-44h]
0040108C   mov         ecx,11h
00401091   mov         eax,0CCCCCCCCh
00401096   rep stos    dword ptr [edi]
11:       int sum = a+b+c+d+e+f+g;
00401098   mov         eax,dword ptr [ebp+8]
0040109B   add         eax,dword ptr [ebp+0Ch]
0040109E   add         eax,dword ptr [ebp+10h]
004010A1   add         eax,dword ptr [ebp+14h]
004010A4   add         eax,dword ptr [ebp+18h]
004010A7   add         eax,dword ptr [ebp+1Ch]
004010AA   add         eax,dword ptr [ebp+20h]
004010AD   mov         dword ptr [ebp-4],eax
12:       return sum;
004010B0   mov         eax,dword ptr [ebp-4]    # 存放返回值
13:   }
004010B3   pop         edi
004010B4   pop         esi
004010B5   pop         ebx
004010B6   mov         esp,ebp
004010B8   pop         ebp
004010B9   ret         1Ch  # 棧平衡(等價於先 add esp, 1Ch 再 ret)

fastcall 函式呼叫約定

引數1、引數2分別儲存在 ECX、EDX ,剩下的引數從右往左一次入棧,被呼叫者實現棧平衡,返回值存放在 EAX 中。

25:       int fastcall_sum = fastcall_add(1, 2, 3, 4, 5, 6, 7);
00401167   push        7
00401169   push        6
0040116B   push        5
0040116D   push        4
0040116F   push        3
00401171   mov         edx,2
00401176   mov         ecx,1
0040117B   call        @ILT+0(@fastcall_add@28) (00401005)
00401180   mov         dword ptr [ebp-0Ch],eax  # 返回值

15:   int __fastcall fastcall_add(int a, int b, int c, int d, int e, int f, int g)
16:   {
004010D0   push        ebp
004010D1   mov         ebp,esp
004010D3   sub         esp,4Ch
004010D6   push        ebx
004010D7   push        esi
004010D8   push        edi
004010D9   push        ecx
004010DA   lea         edi,[ebp-4Ch]
004010DD   mov         ecx,13h
004010E2   mov         eax,0CCCCCCCCh
004010E7   rep stos    dword ptr [edi]
004010E9   pop         ecx
004010EA   mov         dword ptr [ebp-8],edx
004010ED   mov         dword ptr [ebp-4],ecx
17:       int sum = a+b+c+d+e+f+g;
004010F0   mov         eax,dword ptr [ebp-4]
004010F3   add         eax,dword ptr [ebp-8]
004010F6   add         eax,dword ptr [ebp+8]
004010F9   add         eax,dword ptr [ebp+0Ch]
004010FC   add         eax,dword ptr [ebp+10h]
004010FF   add         eax,dword ptr [ebp+14h]
00401102   add         eax,dword ptr [ebp+18h]
00401105   mov         dword ptr [ebp-0Ch],eax
18:       return sum;
00401108   mov         eax,dword ptr [ebp-0Ch]  # 存放返回值
19:   }
0040110B   pop         edi
0040110C   pop         esi
0040110D   pop         ebx
0040110E   mov         esp,ebp
00401110   pop         ebp
00401111   ret         14h  # 棧平衡(等價於先 add esp, 14h 再 ret)

X64 函式呼叫約定

X64只有一種 fastcall 函式呼叫約定

fastcall 函式呼叫約定

引數1、引數2、引數3、引數4分別儲存在 RCX、RDX、R8D、R9D ,剩下的引數從右往左一次入棧,被呼叫者實現棧平衡,返回值存放在 RAX 中。

# 該程式碼是 msvc 2017 x64 生成的彙編程式碼
    int fastcall_sum = fastcall_add(1, 2, 3, 4, 5, 6, 7); 
00007FF6577A366E  mov         dword ptr [rsp+30h],7
00007FF6577A3676  mov         dword ptr [rsp+28h],6  
00007FF6577A367E  mov         dword ptr [rsp+20h],5  
00007FF6577A3686  mov         r9d,4  
00007FF6577A368C  mov         r8d,3  
00007FF6577A3692  mov         edx,2  
00007FF6577A3697  mov         ecx,1  
00007FF6577A369C  call        fastcall_add (07FF6577A11C2h)  
00007FF6577A36A1  mov         dword ptr [fastcall_sum],eax  # 返回值

int __fastcall fastcall_add(int a, int b, int c, int d, int e, int f, int g)
{
00007FF6D22D1790  mov         dword ptr [rsp+20h],r9d  
00007FF6D22D1795  mov         dword ptr [rsp+18h],r8d  
00007FF6D22D179A  mov         dword ptr [rsp+10h],edx  
00007FF6D22D179E  mov         dword ptr [rsp+8],ecx  
00007FF6D22D17A2  push        rbp  
00007FF6D22D17A3  push        rdi  
00007FF6D22D17A4  sub         rsp,0E8h  
00007FF6D22D17AB  mov         rbp,rsp  
00007FF6D22D17AE  mov         rdi,rsp  
00007FF6D22D17B1  mov         ecx,3Ah  
00007FF6D22D17B6  mov         eax,0CCCCCCCCh  
00007FF6D22D17BB  rep stos    dword ptr [rdi]  
00007FF6D22D17BD  mov         ecx,dword ptr [rsp+108h]  
    int sum = a + b + c + d + e + f + g;
00007FF6D22D17C4  mov         eax,dword ptr [b]  
00007FF6D22D17CA  mov         ecx,dword ptr [a]  
00007FF6D22D17D0  add         ecx,eax  
00007FF6D22D17D2  mov         eax,ecx  
00007FF6D22D17D4  add         eax,dword ptr [c]  
00007FF6D22D17DA  add         eax,dword ptr [d]  
00007FF6D22D17E0  add         eax,dword ptr [e]  
00007FF6D22D17E6  add         eax,dword ptr [f]  
00007FF6D22D17EC  add         eax,dword ptr [g]  
00007FF6D22D17F2  mov         dword ptr [sum],eax  
    return sum;
00007FF6D22D17F5  mov         eax,dword ptr [sum]       # 存放返回值
}
00007FF6D22D17F8  lea         rsp,[rbp+0E8h]  
00007FF6D22D17FF  pop         rdi  
00007FF6D22D1800  pop         rbp  
00007FF6D22D1801  ret                                   # 沒做棧平衡

C++ 函式呼叫約定

thiscall用於C++中類成員函式(方法)的呼叫

thiscall 函式呼叫約定

暫時不懂C++,等學了C++類了再更新

ARM/ARM64 函式呼叫約定

ARM和ARM64使用的是ATPCS(ARM-Thumb Procedure Call Standard/ARM-Thumb過程呼叫標準)的函式呼叫約定。

ATPCS 函式呼叫約定

ARM

引數1~引數4 分別儲存到 R0~R3 暫存器中 ,剩下的引數從右往左一次入棧,被呼叫者實現棧平衡,返回值存放在 R0 中。

; 該程式碼是 arm-linux-androideabi-gcc + IDA PRO 生成的反彙編程式碼
.text:00008438                 MOV             R3, #5
.text:0000843C                 STR             R3, [SP,#0x1C+e] ; e
.text:00008440                 MOV             R3, #6
.text:00008444                 STR             R3, [SP,#0x1C+f] ; f
.text:00008448                 MOV             R3, #7
.text:0000844C                 STR             R3, [SP,#0x1C+g] ; g
.text:00008450                 MOV             R0, #1  ; a
.text:00008454                 MOV             R1, #2  ; b
.text:00008458                 MOV             R2, #3  ; c
.text:0000845C                 MOV             R3, #4  ; d
.text:00008460                 BL              add
.text:00008464                 STR             R0, [R11,#sum]

.text:000083C4                 EXPORT add
.text:000083C4                 STR             R11, [SP,#-4+var_s0]!
.text:000083C8                 ADD             R11, SP, #0
.text:000083CC                 SUB             SP, SP, #0x1C
.text:000083D0                 STR             R0, [R11,#a]
.text:000083D4                 STR             R1, [R11,#b]
.text:000083D8                 STR             R2, [R11,#c]
.text:000083DC                 STR             R3, [R11,#d]
.text:000083E0                 LDR             R2, [R11,#a]
.text:000083E4                 LDR             R3, [R11,#b]
.text:000083E8                 ADD             R2, R2, R3
.text:000083EC                 LDR             R3, [R11,#c]
.text:000083F0                 ADD             R2, R2, R3
.text:000083F4                 LDR             R3, [R11,#d]
.text:000083F8                 ADD             R2, R2, R3
.text:000083FC                 LDR             R3, [R11,#e]
.text:00008400                 ADD             R2, R2, R3
.text:00008404                 LDR             R3, [R11,#f]
.text:00008408                 ADD             R2, R2, R3
.text:0000840C                 LDR             R3, [R11,#g]
.text:00008410                 ADD             R3, R2, R3
.text:00008414                 STR             R3, [R11,#sum]
.text:00008418                 LDR             R3, [R11,#sum]
.text:0000841C                 MOV             R0, R3          ; R0返回值
.text:00008420                 SUB             SP, R11, #0
.text:00008424                 LDR             R11, [SP+var_s0],#4
.text:00008428                 BX              LR
ARM64

引數1~引數8 分別儲存到 X0~X7 暫存器中 ,剩下的引數從右往左一次入棧,被呼叫者實現棧平衡,返回值存放在 X0 中。

; 該程式碼是 aarch64-linux-android-gcc + IDA PRO 生成的反彙編程式碼
.text:0000000000400684                 MOV             W0, #9
.text:0000000000400688                 STR             W0, [SP,#0x40+i] ; i
.text:000000000040068C                 MOV             W0, #10
.text:0000000000400690                 STR             W0, [SP,#0x40+j] ; j
.text:0000000000400694                 MOV             W0, #11
.text:0000000000400698                 STR             W0, [SP,#0x40+k] ; k
.text:000000000040069C                 MOV             W0, #12
.text:00000000004006A0                 STR             W0, [SP,#0x40+l] ; l
.text:00000000004006A4                 MOV             W0, #1  ; a
.text:00000000004006A8                 MOV             W1, #2  ; b
.text:00000000004006AC                 MOV             W2, #3  ; c
.text:00000000004006B0                 MOV             W3, #4  ; d
.text:00000000004006B4                 MOV             W4, #5  ; e
.text:00000000004006B8                 MOV             W5, #6  ; f
.text:00000000004006BC                 MOV             W6, #7  ; g
.text:00000000004006C0                 MOV             W7, #8  ; h
.text:00000000004006C4                 BL              add
.text:00000000004006C8                 STR             W0, [X29,#0x20+sum]

.text:00000000004005E8                 EXPORT add
.text:00000000004005E8
.text:00000000004005E8                 SUB             SP, SP, #0x30
.text:00000000004005EC                 STR             W0, [SP,#0x30+a]
.text:00000000004005F0                 STR             W1, [SP,#0x30+b]
.text:00000000004005F4                 STR             W2, [SP,#0x30+c]
.text:00000000004005F8                 STR             W3, [SP,#0x30+d]
.text:00000000004005FC                 STR             W4, [SP,#0x30+e]
.text:0000000000400600                 STR             W5, [SP,#0x30+f]
.text:0000000000400604                 STR             W6, [SP,#0x30+g]
.text:0000000000400608                 STR             W7, [SP,#0x30+h]
.text:000000000040060C                 LDR             W1, [SP,#0x30+a]
.text:0000000000400610                 LDR             W0, [SP,#0x30+b]
.text:0000000000400614                 ADD             W1, W1, W0
.text:0000000000400618                 LDR             W0, [SP,#0x30+c]
.text:000000000040061C                 ADD             W1, W1, W0
.text:0000000000400620                 LDR             W0, [SP,#0x30+d]
.text:0000000000400624                 ADD             W1, W1, W0
.text:0000000000400628                 LDR             W0, [SP,#0x30+e]
.text:000000000040062C                 ADD             W1, W1, W0
.text:0000000000400630                 LDR             W0, [SP,#0x30+f]
.text:0000000000400634                 ADD             W1, W1, W0
.text:0000000000400638                 LDR             W0, [SP,#0x30+g]
.text:000000000040063C                 ADD             W1, W1, W0
.text:0000000000400640                 LDR             W0, [SP,#0x30+h]
.text:0000000000400644                 ADD             W1, W1, W0
.text:0000000000400648                 LDR             W0, [SP,#0x30+i]
.text:000000000040064C                 ADD             W1, W1, W0
.text:0000000000400650                 LDR             W0, [SP,#0x30+j]
.text:0000000000400654                 ADD             W1, W1, W0
.text:0000000000400658                 LDR             W0, [SP,#0x30+k]
.text:000000000040065C                 ADD             W1, W1, W0
.text:0000000000400660                 LDR             W0, [SP,#0x30+l]
.text:0000000000400664                 ADD             W0, W1, W0
.text:0000000000400668                 STR             W0, [SP,#0x30+sum]
.text:000000000040066C                 LDR             W0, [SP,#0x30+sum]   ;X0 返回值
.text:0000000000400670                 ADD             SP, SP, #0x30
.text:0000000000400674                 RET

相關推薦

常見函式呼叫約定(x86x64armarm64)

我學習逆向,整理的一些常見的函式呼叫約定反彙編筆記。由於我是新手,肯定有一些疏漏不完善的,我遇到了會實時更新的。 X86 函式呼叫約定 X86 有三種常用呼叫約定,cdecl(C規範)/stdcall(WinAPI預設)/fastcall

2018/10/03-函式呼叫約定cdeclstdcallfastcall- 《惡意程式碼分析實戰》

  cdecl是最常用的約定之一,引數是從右到左按序被壓入棧,當函式完成時由呼叫者清理棧,並且將返回值儲存在EAX中。   stdcall約定是被呼叫函式負責清理棧,其他和cdecl非常類似。   fastcall呼叫約定跨編譯器時變化最多,但是它總體上在所有情況下的工作方式都是相似的。在fastcall

cdeclstdcallfastcallthiscall函式呼叫約定區別 (轉)

 在C語言中,假設我們有這樣的一個函式:    int function(int a,int b)    呼叫時只要用result = function(1,2)這樣的方式就可以使用這個函式。但是,當高階語言被編譯成計算機可以識別的機器碼時,有一個問題就凸現出來:在CPU中,計算機沒有辦法知道一個函式呼叫需要

cdeclstdcallfastcall函式呼叫約定區別

論函式呼叫約定   在C語言中,假設我們有這樣的一個函式:      int function(int a,int b)      呼叫時只要用result = function(1,2)這樣的方式就可以使用這個函式。但是,當高階語言被編譯成計算機可以識別的機器碼時,有一個問題就凸現出來:在CPU中

pushpop及函式呼叫約定

push: 把一個32位的運算元壓入堆疊中。這個操作導致esp被減4。esp被形象地稱為棧頂。我們認為頂部是地址小的區域,那麼,壓入堆疊中資料越多,這個堆疊也就越堆越高,esp也就越來越小。在32位平臺,esp每次減少4位元組。 pop: 相反,esp被加4,一個數據

x64函式呼叫約定——MSVC & GCC

傳參 MSVC 前4個引數使用rcx、rdx、r8、r9,剩下的引數用棧 GCC 前6個引數使用rdi、rsi、rdx、rcx、r8、r9,剩下的引數用棧。注意rdx、rcx的順序和MSVC上不一樣 caller saved registers 這類暫存器可由子函式自由使用,

x86 常見呼叫約定(cdecl,fastcall,stdcall) & x86ARM呼叫約定的棧幀分析 & ARM ATPCS(ARM-THUMB procedure call standard)

#PS:要轉載請註明出處,本人版權所有 #PS:這個只是 《 我自己 》理解,如果和你的 #原則相沖突,請諒解,勿噴 由於某些工作的需要,我需要掌握X86以及ARM的一些呼叫規則,讓自己可以大致看懂ASM程式碼。於是,我總結了一下我需要的東西

Windows x64彙編函式呼叫約定

最近在寫一些字串函式的優化,用到x64彙編,我也是第一次接觸,故跟大家分享一下。 x86:又名 x32 ,表示 Intel x86 架構,即 Intel 的32位 80386 彙編指令集。 x64:表示 AMD64 和 Intel 的 EM64T ,而不包括 IA6

從彙編角度檢視C語言函式呼叫約定【非常有用】

轉自:https://blog.csdn.net/Holmofy/article/details/76094986   為了防止出現不必要的程式碼影響組合語言的檢視,所以程式中不使用任何庫函式,以保持彙編程式碼的簡潔。 這裡所使用的彙編是VC的MASM。 預設函式呼叫方式_

【軟體開發底層知識修煉】二十五 ABI之函式呼叫約定二之函式返回值為結構體時的約定

上一篇文章學習了幾種函式呼叫約定的區別,點選連結檢視上一篇文章:【軟體開發底層知識修煉】二十四 ABI之函式呼叫約定 本篇文章繼續學習函式呼叫約定中,關於函式返回值的問題。當函式返回值為結構體時,函式返回值是如何來傳給呼叫者的。

【軟體開發底層知識修煉】二十四 ABI之函式呼叫約定

上一篇文章學習了Linux環境下的函式棧幀的形成與摧毀。點選連結檢視相關文章:軟體開發底層知識修煉】二十三 ABI-應用程式二進位制介面三之深入理解函式棧幀的形成與摧毀 本篇文章繼續學習ABI介面相關的內容。函式呼叫約定

名字修飾約定函式呼叫約定

所謂名字修飾約定,就是指變數名、函式名等經過編譯後重新輸出名稱的規則。   比如原始碼中函式名稱為int Func(int a,int b),經過編譯後名稱可能為[email protected]@[email protected]、[email&#

函式呼叫約定函式名稱修飾規則(一)

    作者:星軌(oRbIt)    E_Mail:[email protected]    轉載請註明原作者,否則請勿轉載       使用C/C++語言開發軟體的程式設計師經常碰到這樣的問題:有時候是程式編譯沒有問題,但是連結的時候總是報告函式不存在(經典的L

函式呼叫約定函式名修飾規則

函式呼叫約定:是指當一個函式被呼叫時,函式的引數會被傳遞給被呼叫的函式和返回值會被返回給呼叫函式。函式的呼叫約定就是描述引數是怎麼傳遞和由誰平衡堆疊的,當然還有返回值。 幾種型別:__stdcall,__cdecl,__fastcall,__thiscall,__n

函式呼叫約定

在C語言中,假設我們有這樣的一個函式: int function(int a,int b) 呼叫時只要用result = function(1,2)這樣的方式就可以使用這個函式。但是,當高階語言被編譯成計算機可以識別的機器碼時,有一個問題就凸現出來:在CPU中,計算機沒有辦法

ARM函式呼叫約定

1、函式呼叫約定主要涉及引數如何傳遞、返回值如何傳遞、返回地址如何儲存以及不要破壞呼叫函式的上下文。那麼在ARM中,這些約定規則是什麼樣呢? 2、測試程式如下: static int fun_a(uint32_t a, uint32_t b, uint32_t c) {

Iperf使用教程移植到ARM移植時遇到的問題解決。

iperf是一個基於Client/Server的網路效能測試工具,可以測試TCP、UDP和SCTP頻寬質量,能夠提供網路吞吐率資訊,以及震動、丟包率,最大段和最大傳輸單元大小等統計資訊,幫助我們測試網路效能,定位網路瓶頸。其中抖動和丟包率適應於UDP測試,二頻寬測試適應於TC

x86armmips架構函式呼叫例項分析

原文網址:http://nieyong.github.com/wiki_cpu/ 在看過了上面的幾節之後,在潛意識中你想記住的東西肯定很多了。這個時候,你需要靜下心來休息一下在沉澱一下。 "Now is a good point to take a break to l

檢查.net dll構建的目標平臺是any cpux86x64

example out exe 使用 mic ons tar ima target 有時候,需要檢查構建的dll是否針對正確的平臺 可以使用CorFlags.exe(它是.NET Framework SDK的一部分)從dll中查找此信息。運行CorFlags.exe將產生以

python函式呼叫順序高階函式巢狀函式閉包詳解

  一:函式呼叫順序:其他高階語言類似,Python 不允許在函式未宣告之前,對其進行引用或者呼叫錯誤示範: def foo(): print 'in the foo' bar() foo() 報錯: in the foo Traceback (most re