x32 x64的不同傳參方式


x64匯編第三講,64位調用約定與函數傳參.

一丶復習X86傳參

在x86下我們匯編的傳參如下:


push eax call xxx xxx fun proc push ebp 保存棧底 mov ebp,esp 設置ebp sub esp,0C0h 開辟局部變量空間 push ebx 保存寄存器環境 push esi push edi pop edi 恢復寄存器環境 pop esi pop ebx mov esp,ebp 釋放局部變量空間 pop ebp 恢復棧底 ret 返回,平展, 如果是 C在外平展 add esp,xxx stdcall 則內部平展 ret 4 

看到上面這段代碼.我們就應該在腦海中有一個示意圖.

我們可以根據上圖可以看到.在調用函數的時候做了那些事情.

1.往棧中存放參數
2.將返回地址入棧
3.保存棧底

4.棧內部進行自己的 申請空間 保存環境 以及釋放.

二丶x64匯編

2.1匯編詳解

在x64下,萬變不離其宗.大部分跟x86一樣.

如匯編代碼為:

sub rsp,0x28 mov r9,1 mov r8,2 mov rdx,3 mov rcx,4 call xxx add rsp,0x28 

1.傳參方式
首先說明一下,在X64下,是寄存器傳參. 前4個參數分別是 rcx rdx r8 r9進行傳參.多余的通過棧傳參.從右向左入棧.
2.申請參數預留空間
在x64下,在調用一個函數的時候,會申請一個參數預留空間.用來保存我們的參數.比如以前我們通過push壓棧
參數的值.相應的棧就會抬高.其實x64下,一樣會申請.只不過這個地方在進函數的時候並沒有值.進入函數之后才會將寄存器的值在拷貝到這個棧中.其實就相當於你還是push了.只不過我是外邊申請空間,內部進行賦值.

如下:


sub rsp,0x28 //申請的棧空間為0x28,就相當於我們push rcx rdx r8 r9.只不過只是申請. call xxxx add rsp,0x28 xxx //函數內部 mov [rsp - 8],rcx mov [rsp - 0x10],rdx mov [rsp - 0x18],r8 mov [rsp - 0x20],r9 xxx 

如下圖:

我們編寫一個簡單的x64程序.對其反匯編進行查看.

首先開辟我們的參數空間,以及返回地址空間.我們單步一下查看

可以看大開辟了 5*8個字節大小的空間.
然后下方的匯編對其寄存器賦值.進行傳參.說明我們只有4個參數.

此時進入Call內部.看下棧.

3.棧按照16字節對齊

現在我們應該明白了.在調用一個函數的時候. 使用 *sub rsp,xxx**進行抬棧,函數內部則進行參數賦值.
其實也是相當於push了參數.只不過它不像x86一樣.在里面進行平棧了.而是外面進行平棧了.

那么有個疑問.比如說我們就4個參數. 通過上面來說.我們應該申請 sub rsp,0x20個字節才對.在CALL的時候
x86 x64都是一樣的會將返回地址入棧. 那為什么要rsp,0x28.這樣的話會多申請一個參數的值哪.

原因是這樣的.棧要按照16字節對齊進行申請.

那么還有人會說.按照16字節對齊,那么我們的參數已經是16字節對齊了.比如為我們4個寄存器申請預留空間. rsp,0x20. (4 * 8 = 32 = 16j進制的 0x20)

那為什么還是會申請 rsp,0x28個字節,並且不對齊.

其實是這樣的.當我們在 Call函數的時候.返回地址會入棧.如果按照我們之前申請的rsp,0x20個字節的話.那么當
返回地址入棧之后,現在總共抬棧大小是 0x28個字節.並不是16進制對齊. 但是當我們一開始就申請0x28個字節.
當返回地址入棧.那么就是0x28+8 = 0x30個字節. 0x30個字節不是正好跟16字節對齊嗎.

所以我們的疑問也就沒有了.

所以申請了0x28個字節,其實多出了的8字節是要跟返回地址一樣.進行棧對齊使用.

那么申請的這個8字節空間,是沒有用的.只是為了對齊使用.

所以x64匯編其實也就搞明白了.

1.在調用函數之前,會申請參數預留空間.(rcx,rdx,r8,r9)
2.函數內部,會將寄存器傳參的值(rcx,rdx,r8,r9)保存到我們申請的預留空間中.
上面這兩步其實就相當於x86下的 push r9 push r8 push rdx,push rcx
3.調用約定是__fastcall.傳參有rcx rdx,平棧是按照c調用約定平棧. 也就是調用者平棧.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM