本文共 3415 字,大约阅读时间需要 11 分钟。
汇编笔记
1.调用约定调用方式应用参数入栈顺序回收堆栈内外平栈cdeclC 语言从右到左调用者负责外平栈thiscallC++语言 函数调用是ecx保存this指针从右到左被调用者负责内平栈stdcallWindows 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浮点数dt10 bytes80位 do16 bytes128位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,1add al,10执行后,结果为00001011B,其中有3(奇数)个1,则PF=0。• SF 符号标志位:它记录相关指令执行后,其结果是否为负。如果结果为负,SF=1,如果非负,SF=0。xxxxxxxxxx
mov al,10000001Badd al,1执行后,结果为10000010B,符号位为1,则SF=1。• CF 进位标志位:一般情况下,在进行了无符号运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。表示无符号数运算是否超出范围,结果仍然正确xxxxxxxxxx
mov al,0ffadd al,1 ;执行后,(al) = 0, CF=1, CF记录了从最高有效位向更高位的进位值 OF =0mov al,2sub al,3 ;执行后,(al) = FFH, CF=1, CF记录了向更高位的借位值• OF 溢出标志位。一般情况下,OF记录了有符号数运算的结果是否发生了溢出。如果发生溢出,OF=1,如果没有,OF=0。表示有符号数结果是否超出范围,运算结果已经不正确。xxxxxxxxxx
mov al,7f ;127add al,10 ;add指令执行后:CF=0,OF=1。• DF 方向标志位:决定串处理指令控制每次操作后si、di的增减。df=0,则每次操作后si、di递增,否则递减。xxxxxxxxxx
带补例子cld ; 将DF置为0std ; 将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.013110708.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) 常见指针和数组的反汇编(x86)
转载于:https://blog.51cto.com/haidragon/2097436