任何程序在CPU上执行都是通过机器语言的0和1转化而来的电信号
是电脑CPU直接读取运行的机器码,运行速度最快,但是非常晦涩难懂,同时也比较难编写;机器码就是计算机可以直接执行,并且执行速度最快的代码
字节码是一种中间状态的二进制代码,需要直译器转译后才能成为机器码
汇编语言是机器语言0和1的助记符,相当于一个封装
寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算的结果
MOV将源操作数的值给目的操作数
LEA将源操作数的地址给目的操作数
ADD 加
SUB 减
原代码
int add(int a,int b){
return a+b;
}
int main()
{
int a=1;
int b=2;
add(a,b);
return 0;
}
先执行右边的参数再执行左边的参数
push入栈
pop出栈
call函数暗含一个push
每push一下,ESP寄存器-4
最后入栈的地址是00A517E0
函数执行完后ESP栈底地址是003FFDB8
查看栈底地址存储的地址 与正常的顺序相反 因为使用的是小端存储
大小端存储数据
所谓的大端模式,就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端
所谓的小端模式,就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端
比如0x123456
大端存储:12 34 56、
小端存储:56 34 12
push与pop的顺序相反
REP的意思是重复
STOS指令的作用是将eax中的值拷贝到ES:EDI指向的地址
总的说是将栈上从ebp-0xCCh开始的位置向高地址方向的内存赋值
0CCCCCCCCh其实就是int3,断点
这段代码是初始化堆栈和分配局部变量用的
往分配好的局部变量空间放入int3中断的原因是:防止该空间里的内容被意外执行
DS和ES是段寄存器,SI和DI是变址寄存器
DS和SI组成:DS:SI
ES和DI组成:ES:DI
常用把地址的值赋值给另地址
32位寄存器:DS*32+SI
OFFSET为属性操作符
表示应该把其后跟着的符号地址的值(不是内容)作为操作数
等价于lea
JE:等于则跳转
JNE:不等于则跳转
JZ:为0则跳转
JNZ:不为0则跳转
JS:为负则跳转
JNS:不为负则跳转
PUSHAD POPAD
这两个指令的作用是把通用寄存器压栈
寄存器的入栈顺序依次是:EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI
ESP=00D7FC10 一开始
ESP=00D7FBF0 PUSHAD之后
ESP=00D7FC10 POPAD之后
相差32H,也就是8格,正好就是这八个通用寄存器
两个jmp无条件跳转,中间一个cmp比较 一个跳出指令