CH8
INVOKE, ADDR, PROC, and PROTO
Advanced Use of Parameters
Creating Multimodule Programs
Stack Frames
Recursion
Register Parameters
存取堆疊參數
32-Bit Calling Conventions
區域變數 : local variable通常在EBP的下面
參考參數 : reference parameter被load到暫存器中,供間接運算元使用
LEA指令
ENTER及LEAVE指令
LOCAL Directive
The Microsoft x64 Calling Convention (好像不考?)
Intro
又被稱為激活記錄
創建Stack Frame的步驟
1.傳遞參數,有參數就通通push到stack中
2.子程序被呼叫時,將子程序的return address push到stack 中
3.當子程序開始執行時,把EBP push到stack中
4.設定EBP = ESP, 使EBP成為子程序參數的base reference
5.如果有區域變數的話,則ESP遞減以保留變數在Stack中的空間
6.如果有暫存器需要被儲存,將被push到stack中
優點
速度 : 傳進暫存器中(快) > push到stack中(慢)
缺點
必須儲存與恢復暫存器中的值
傳遞方式
傳值 : push 變數
傳址 : push 變數OFFSET
Pass Array
calling program先把陣列的位址push到stack中,子程序再從stack中取得參數位址,並存取之。
方法
在呼叫function時,初始化、存取之
步驟
- push ebp ;儲存ebp
- mov ebp,esp ;把stack的top2丟到ebp中
- code.
- pop ebp ;還原ebp
ESP通常指向stack的last element
用途 : 清理stack
方式
C Calling Convention
STDCALL Calling Convention
在ret後面加上一個數字
Base-Offset Addressing
用途 : 存取stack 參數
說明
EBP是base register
ESP的值可能會改變,但EBP不會
OFFSET是一個常數 (可能為正或負)
RET指令
說明
從子程序中return
語法
ret
ret n (表示EIP+n)
說明
return 間接運算元的address
含有stack parameter、local variable的OFFSET時,必須用到LEA。
ENTER
用途
替被呼叫的procedure創建stack frame
步驟
PUSH EBP 到stack中
把EBP設為stack frame 的base
保留local variable的space
語法 : ENTER numbytes, nestinglevel
numbytes : 要替local variable在stack space 中預留多少空間
nestinglevel : 在我們的程式中,通常為0
LEAVE : 替procedure終止stack frames
說明
宣告一個local variable的list
等同 " ENTER + LEAVE " 但不指定預留空間大小
下面緊接著PROCdirective
每一個變數後面都要加上TYPE
語法 : LOCAL varlist
CALL使RSP-8 (64bits = 8 Bytes)
前4個傳遞給子程序的參數被放置於RCX, RDX, R8, R9。 其餘則由左到右被放進stack
長度小於64bits的參數"不"做zero extended
說明
一個會呼叫自己的子程序
每個遞迴程式都應該要有一個終止條件,否則會造成無止盡的遞迴
當終止條件成立時,stack展開,執行全部的RET
預留stack空間 for
要被傳遞的參數
子程序的return address
區域變數
被儲存的暫存器
- ret
在子程序return後,在esp + value
把stack Top POP掉, 放進EIP中
範例
mov esi, OFFSET [ebp-8] -> error
lea esi, [ebp-8] ->ok
範例
ENTER
push ebp
mov ebp,esp
sub esp,8 ; 2 local DWORDs
LEAVE
mov esp,ebp ; free local space
pop ebp