X86汇编
这两天在看《老码识途》, 感觉x86汇编比较好玩, 随写一篇文章准备记录一下
寄存器
本质上就是存储数据的地方, 寄存器 - cache - 内存 - 硬盘 - 网络上的介质
不过寄存器存储的确实很少, 32位或者说是64位数,这里主要先考虑32位的
通用寄存器
在32位的寄存器下, 主要是由以下寄存器比较重要
- EAX: 多数情况下是传入参数, 参数的第一个或者说直接是返回值放在EAX上
- ECX: 传入参数
- EDX: 传入参数
- EBX: 传入参数
- EBP: 函数寻址的情况下, EBP是保存栈的base的
- ESP: 维护函数栈的情况下, ESP是栈顶
- ESI
- EDI:
- EIP: PC寄存器, 是保存吓一条寄存器的地址的, 非常重要
其中, EIP这样的寄存器, 保存的是下一条指令的地址, 不过EIP寄存器是线性的, 是线性增长的
- 传入参数按照规定的参数传入方式进行传入,比如说WINAPI的形式,或者说是fastcall的形式,这里比较重要的,因为传入参数的顺序决定了参数在栈里面的分布式怎么分布的,
- C++规定了传入参数遵循WINAPI,fastcall这样的传入方式,但是没有规定怎么使用这个参数,
- 使用参数的顺序式未定义的
如下图:
High
| ... |
+---------+
+24| Arg 1 |
+---------+
+16| Arg 2 |
+---------+
+ 8| Return |
+---------+
EBP+--> |Saved EBP|
+---------+
- 8| Var 1 |
+---------+
ESP+--> | Var 2 |
+---------+
| ... |
Low
- 先按照从右往左压栈传入参数,然后保存EBP这个指针,然后开始是局部变量,压栈的过程中,ESP这个指针式往下走的,所以可以大致分布是上图
- 因为参数是固定的,那么就可以直接得到指针,然后+8+8这样的得到对应的参数,然后显示出来。
- WinDbg调试得到参数比较常用这个信息
内存地址
下面是相关例子
# ds:[xxx]是段存储,因为内存就是一段一段的,这里直接就是0x12FFC4这个地址的数据,
# mov 到eax这个寄存器上
# dword是双字,就是从这个0x13FFC4这个地方,四个字节,放到eax上
mov eax, dword ptr ds:[0x13FFC4]
# 同理,eax的数值存储到ds[0X13FFC4]上
// eax的数值往eax上写入数据,同样,dword是双字,也就是四字节
mov dword ptr ds:[0X13FFC4], eax
- 程序中的内存地址很多都是按照基地址 + 偏移量存储的,比如说全局变量,数组,switch这样的关键字,都是base + offset这样存储的
- Windows上按照0x40000这样base地址,但是offset不会变,base地址可能会发生偏移,但是大差不差,所以这里是用offset比较多