1. 程式人生 > >匯編筆記

匯編筆記

asm

匯編筆記
?
1.調用約定
調用方式
應用
參數入棧順序
回收堆棧
內外平棧
cdecl
C 語言
從右到左
調用者負責
外平棧
thiscall
C++語言 函數調用是ecx保存this指針
從右到左
被調用者負責
內平棧
stdcall
Windows Api函數
從右到左
被調用者負責
內平棧
fastcall
寄存器傳參 ECX EDX 剩下參數入棧
從右向左
被調用者負責
內平棧
fastcallX64
寄存器傳參 RCX,RDX,R8,R9 剩下參數入棧
從右向左
被調用者負責
內平棧
Pascal
?
從左到右
被調用者負責
內平棧
2.尋址方式
? 立即尋址方式 MOV EAH,1(直接給寄存器賦值)
? 寄存器尋址方式 MOV EAX,EBX
? 直接尋址 MOV EAX,DWORD PTR [0X42000] 取出地址中的值給EAX
? 寄存器間接尋址 MOV EAX,[ECX] MOV EAX,[ESI]
? 寄存器相對尋址 MOV EAX,[ESI+10H]
? 基址加變址尋址 MOV EAX,[EBX+ESI]
? 相對基址加變址 MOV EAX,[EBX+ESI+10H]
3.數據類型
類型
偽指令
數據寬度
?
整數
db
字節
BYTE
?
dw

WORD
?
dd
雙字
DWORD
?
dq
四字
LONGLONG
浮點數
dt
10 bytes
80位
?
do
16 bytes
128位
4.寄存器
EAX:
? 累加寄存器,是很多加法乘法指令的缺省寄存器
? 存放函數返回值
? 大數運算時保存結果的低位
ECX:
? 計數器 重復指令REP 和LOOP 指令的內定計數器
EDX:
? 整數除法產生的余數
? 大數運算時保存結果的高位
EBX:
? 基地址寄存器
EBP:
? 保存棧底指針
? 尋找函數返回地址 [ebp+4]
? 尋找函數參數 [ebp+8],[ebp+12] 等
? 尋找函數局部變量 [ebp-4], [ebp-8] 等
ESP:
? 棧頂寄存器
ESI: 用於高速存儲器傳輸指令,串操作常用,指向源串
EDI:用於高速存儲傳器輸指令,串操作常用,指向目的串
X64 寄存器:
?

  1. 標誌寄存器

? ZF 是不是0 是0 為True
? PF 奇偶標誌位: 記錄相關指令執行後,其結果的所有二進制位中1的個數是否為偶數。如果1的個數為偶數,PF=1,如果為奇數,那麽PF=0。

?x
mov al,1
?
add al,10
?
執行後,結果為00001011B,其中有3(奇數)個1,則PF=0。
? SF 符號標誌位:它記錄相關指令執行後,其結果是否為負。如果結果為負,SF=1,如果非負,SF=0。

xxxxxxxxxx
mov al,10000001B
?
add al,1
?
執行後,結果為10000010B,符號位為1,則SF=1。
? CF 進位標誌位:一般情況下,在進行了無符號運算的時候,它記錄了運算結果的最高有效位向更高位的進位值,或從更高位的借位值。表示無符號數運算是否超出範圍,結果仍然正確

xxxxxxxxxx
mov al,0ff
add al,1 ? ? ? ? ;執行後,(al) = 0, CF=1, CF記錄了從最高有效位向更高位的進位值 OF =0
?
?
mov al,2
sub al,3 ? ? ? ? ? ;執行後,(al) = FFH, CF=1, CF記錄了向更高位的借位值
?
? OF 溢出標誌位。一般情況下,OF記錄了有符號數運算的結果是否發生了溢出。如果發生溢出,OF=1,如果沒有,OF=0。表示有符號數結果是否超出範圍,運算結果已經不正確。

xxxxxxxxxx
mov al,7f ;127
add al,10 ;
add指令執行後:CF=0,OF=1。
? DF 方向標誌位:決定串處理指令控制每次操作後si、di的增減。df=0,則每次操作後si、di遞增,否則遞減。

xxxxxxxxxx
帶補例子
cld ; 將DF置為0
std ; 將DF置為1
? IF 中斷標誌位 決定CPU是否響應外部可屏蔽中斷請求。IF為1時,CPU允許響應外部的可屏蔽中斷請求
? TF 陷阱標誌位 TF被設置位1時,CPU進入單步模式,所謂單步模式就是CPU在每執行一步指令後都產生一個單步中斷。主要用於程序的調試。
? AF 輔助進位標誌位 在字節操作時低半字節向高半字節進位或借位。字操作時低字節向高字節進位或借位,AF置1,否則置0。
?
6.JCC
近跳轉 - 跳轉到當前代碼段(CS 寄存器當前指向的段)內的指令,有時稱為段內跳轉。64k範圍
短跳轉 - 跳轉範圍限制為距當前 EIP 值 -128 到 +127 單位:字節, 的近跳轉。
遠跳轉 - 跳轉到當前代碼段以外的段(但特權級別相同)中的指令,有時稱為段間跳轉。
註 JCC 指令不支持遠跳轉 ,

xxxxxxxxxx
遠跳轉可使用組合跳轉
JNZ BEYOND;
JMP FARLABEL;
BEYOND:
?
? J : 表示 jump 轉移
? E: 表示 equal 等於
? NE: 表示 not equal 不等於
? B: 表示 below 小於
? NB:表示 not below 不小於
? L: 表示 low 小於
? NL:表示 not low 不小於
? A: 表示 above 大於
? NA:表示 not above 不大於
? G :表示 大於
? NG:表示 不大於

?
?
7.幾個 指令
LEA: 取地址

xxxxxxxxxx
lea eax,dword ptr[num] ? ;eax 中是num 的地址

mov ebx,num
lea ecx,[ebx] ? ;ebx 中是什麽就是什麽
[ ] : 間接取操作數方式 限於寄存器 , 在8086中 [ ] 只能 si di bx bp ,但在win32中好像並沒有做限制

xxxxxxxxxx
? lea esi,dword ptr [num] ? ;num 地址放入 esi 中
? mov eax,num ? ? ? ? ? ?
? mov edx,20d
? mov [esi],edx ? ? ? ? ? ? ;edx 的值 放入esi指向的內存中
? mov esi,edx ? ? ? ? ? ? ? ;esi=edx
?
? lea esi,dword ptr [num] ? ;num 地址放入 esi 中
? mov eax,[esi] ? ? ? ? ? ? ;取esi內容 放到eax中 eax=10h
? mov ecx,esi
? mov edx,[ecx] ? ? ? ? ? ? ;取ecx內容 放到edx中 edx=10h
? mov ecx,[num1] ? ? ? ? ? ;ecx 存放 num1 的值
?
offset : 偽指令, 取偏移 在編譯時確定,不能用於局部變量
addr : 偽指令, invoke 偽指令 中用到 取 地址
?
8.框架識別
?
8.1 VS 201X RELEASE 版 控制臺 MAIN 函數識別 三個push 一個call
註:其他自己總結

xxxxxxxxxx
int main( int argc, char argv[], char envp[] )
?

xxxxxxxxxx
0131127C ? . 50 ? ? ? ? ? PUSH EAX ? ? ? ? ? ? ? ;整數, 為傳給main()的命令行參數個數。
?
0131127D ? . FF37 ? ? ? ? PUSH DWORD PTR DS:[EDI];字符串數組
?
0131127F ? . FF36 ? ? ? ? PUSH DWORD PTR DS:[ESI];envp是系統的環境變量(也是字符串)
?
01311281 ? . E8 EAFDFFFF ? CALL ConsoleA.01311070
?
8.2 while 循環

xxxxxxxxxx
? char*str = "HelloBoy";
int i = 0;
while (i < strlen(str))
{
printf("%c",str[i]);
i++;
}

?
8.2.1 指針

?
8.3 doWhile

xxxxxxxxxx
do
{
printf("%c", str1[k]);
k++;
} while (k < strlen(str1));
?

?
8.4 switch

?
8.5 擴展
常見表達式語句的反匯編(x86) https://bbs.pediy.com/thread-224347.htm
常見指針和數組的反匯編(x86) https://bbs.pediy.com/thread-224346.htm
技術分享圖片

匯編筆記