寄存器, 堆栈, 汇编指令详解
目录
- 什么是寄存器?
- 内存区域
- 初识堆栈push和pop
- mov和lea
- jmp, call和retn以及汇编运算
- 浮点数汇编指令
什么是寄存器?
1.寄存器是用来存储数据和地址的, 和变量的定义很像, 但是寄存器不能取地址, 你取地址就相当于取的是物理地址,是固定的,没有意义, 对比我们变量的取地址都是虚拟地址, 是可变的
如eax = 0xfffffff eax = 100;
2.变量是在内存上的, 而寄存器是在CPU上的, 基于这个特点, 所以CPU的访问速度很快
3. 32位的通用寄存器有8个, eax, ecx, edx, ebx, esp, ebp, esi, edi. 64位有更多的寄存器,
4.
- eax的低16位寄存器, 如ax(你对ax赋值就相当于对eax赋值),
- ax的低8位寄存器, al(你对al赋值就相当于对ax的低8位赋值),
- ax的高8位寄存器, 如ah(你对ah赋值就相当于的对ax的高8位赋值)
- 这里的高8位和低8位是相对于ax的16位而言的
可以这样表示:
Union 寄存器
{DWORD EAX;WORD AX;struct {BYTE AL;BYTE AH;};
};
5.eax, ecx, edx, ebx叫做数据寄存器
- 如果函数有返回值的时候, 一般用eax作为返回值
- ecx通常用作参数传递. 用作计数
- edx也会用作传递参数. 在乘除法运算的时候作为结果来传递, 如溢出部分, 余数等
- ebx没有什么很特别的作用
6.esi和edi是指针寄存器, 在传递指针的时候用的比较多, 如汇编代码
rep movs dword ptr[edi], dword ptr[esi]
7.esp只能表示栈顶指针, ebp表示栈底指针也可以表示其他的
内存区域
1.一个程序启动, CPU会将他的资源和代码加载到虚拟内存中, 而这个虚拟内存就可以分为多个区域
2.内存在比较专业的角度可以分为很多个区域, 但是在这里, 我们就简单的分为3个区域, 堆, 栈, 模块区(代码区, 数据段(常量, 全局变量), 资源段)
3.将一个程序加载进来的时候, 会加载很多东西, 如exe文件, dll文件(包括引擎dll, windows提供库的dll, 图形dll,第三方dll…), 其他的资源文件等, 这里每个单独的都是一个模块
初识堆栈push和pop
- 栈, 每push一次一个DWORD, esp都会-4字节, 每pop一次, esp都会+4字节
- push和pop都有参数, push是输入型参数, pop是输出型参数
mov和lea
- 高级语言经过预处理形成.i文件, 再编译形成汇编语言.s, 再通过汇编形成二进制机器语言.o, 最后链接形成可执行程序
- 反编译就是将可执行程序翻译成机器语言, 再翻译成汇编语言
- mov指令有两个操作数, mov 操作数1 操作数2, 意思就是 操作数1 = 操作数2
在vs编译器的反汇编中你或许能看到mov dword ptr[a], 100
首先要声明一点, vs编译器的反汇编为了人类易于阅读而进行了一些反汇编的视觉优化, 所以这里的a其实真正代表的是a的地址, 并不是a这个变量,如果你想看到原汁原味的, 你可以右键将显示符号名给勾掉
1.dword ptr 表示一个声明,我们接下来要访问的是一个指向4字节内存区域的地址 2. [a] 表示取a的解引用
- lea也是有两个操作数, lea 操作数1, 操作数2, 意思是 把操作数1 = 操作数2的地址
lea eax, [a]
意思是 [a]的地址给eax
jmp, call和retn以及汇编运算
jmp
和 goto 相似, 不做过多解释CALL
指令, 就是调用函数. 等价于
1.push eip 先保存eip执行的地址(接下来要执行的语句)到栈里
2.jmp xxxx(函数地址)
3.pop eip 将栈内的值取出来, 赋值给eipretn
和return相似, 等价于 pop eipadd esp, 4
等价于 esp += 4sub esp, 4
等价于 esp -= 4inc ecx
等价于 ecx++dec eax
等价于 eax–imul
乘法运算,div
除法运算
浮点数汇编指令
浮点栈一般在整数和浮点数的转换时会用到
fld [esp]
表示把esp解引用的浮点数压入到浮点栈
fld st0
把浮点栈的栈顶的值压入到浮点栈
fld1
把1压入浮点栈
fldz
把0压入浮点栈
fldpi
把3.1415926…压入浮点栈
fild [esp]
表示把esp解引用的整数值压入到浮点栈(整数就变为了浮点数)
fstp [esp]
表示把浮点栈的栈顶的值(一定是浮点数)给esp地址所指向的位置
fstp [esp]
将浮点栈的栈顶值赋值给esp地址所指向的位置, 但是不pop浮点栈
fistp [esp]
把浮点栈的栈顶值转换为整数赋值给esp地址所指向的位置