汇编笔记
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 寄存器:
- 标志寄存器
• 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
转载于:https://blog.51cto.com/haidragon/2097436