65,186
社区成员




1、堆栈相关指令
任意时刻,SS:SP指向栈顶元素
push ax
由以下两步完成
(1) SP=SP-2,SS:SP 指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶
(2) 将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时执行新栈顶
pop ax
(1) 将SS:SP指向的内存单元处的数据送入ax中
(2) SP=SP+2,SS:SP 指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶
SUB OPRD1,OPRD2
OPRD1-OPRD2 结果放在OPRD1寄存器中
ADD OPRD1,OPRD2
OPRD1+OPRD2 结果放在OPRD1寄存器中
CALL OPRD
相当于
push 当前指令语句的下一条地址
jmp OPRD
ret
相当于
pop 把返回的地址弹出来
jmp 上面弹出的地址
2、数据传送指令
MOV OPRD1,OPRD2
将OPRD1寄存器的内容设置为OPRD2中的值
XOR OPRD1,OPRD2
实现两个操作数按位‘异或’运算,结果送至 OPRD1操作数中.
常见
xor eax,eax
功能等价于mov eax,0
xor eax,eax 机器码 33 C0
mov eax,0 机器码 B8 00 00 00 00
对比了下机器码,相同的功能xor eax,eax 少了3个字节
所以选用第一种方法清理寄存器,程序员都很精^―^
LEA OPRD1,OPRD2
将源操作数给出的有效地址传送到指定的的寄存器中.
void CMainTestDlg::OnBnClickedButton1()
{
const char *p = "12345678";
char szBuff[10];
strcpy(szBuff,p);
OutputDebugString(szBuff);
}
strcpy编译后产生的反汇编代码
ds:[4025F8] 为“12345678”常量字符串的首地址
ss:[esp] 此时执向了szBuff的首地址
随着eax的增加,直到cl为0才结束循环,执行jnz之后代码
0040115E . 33C0 xor eax,eax
00401160 > 8A88 F8254000 mov cl,byte ptr ds:[eax+4025F8]
00401166 . 880C04 mov byte ptr ss:[esp+eax],cl
00401169 . 40 inc eax
0040116A . 84C9 test cl,cl
0040116C .^ 75 F2 jnz short MainTest.00401160
#include <time.h>
#include <stdlib.h>
#include <windows.h>
int main() {
int a,b[11];//本来是b[10],为判断哪句越界,故意声明为b[11]
srand((unsigned int)time(NULL));//按两次F11,等黄色右箭头指向本行时,调试、新建断点、新建数据断点,地址:&b[10],字节计数:4,确定。
while (1) {//按F5,会停在下面某句,此时a的值为10,b[10]已经被修改为对应0..4之一。
b[(a=rand()%11)]=0;
Sleep(100);
b[(a=rand()%11)]=1;
Sleep(100);
b[(a=rand()%11)]=2;
Sleep(100);
b[(a=rand()%11)]=3;
Sleep(100);
b[(a=rand()%11)]=4;
Sleep(100);
}
return 0;
}