堆内存(堆栈)
1、是自己向系统要的一片的空间
2、是反向增长,地址是从高位到地位,加到的时候是减小地位地址
3、堆栈数据是先进后出
4、如果函数有参数,参数由右往左逐个依次放入堆栈栈顶,通过PUSH指令
PUSH 指令可以拆解为下面两条指令
第一步 sub exp.0x4 //增加4个字节
mov [esp],数据
第二步 再call函数的时候
push 返回地址
jmp 到函数头部
5、进入函数后堆栈顶部会传入返回下一个执行代码的地址(32位程序和64位程序都是这样执行的)
6、x64 前四个参数分别是通过RCX,RDX,R8,R9四个寄存器传递的,后面的参数还是通过堆栈来传递,只不过不是用PUSH指令。
7、puSH 入栈,pop出栈,本质是在移动esp指针。
8、通过其他方式入栈,就可以不用PUSH入栈,不用POP出栈 , 起到隐藏函数入口的假象,增加别人逆向的难度·,代码如下两个图片:
虽然64位程序使用寄存器来传递参数,但是函数的调用者依旧会为被调用的函数开辟对应的参数栈空间,只不过没有使用PUSH指令,而是用MOV来转移
结论:
6、栈空间数据清理:
__fastcall
栈空间
1、局部变量存放在栈空间
2、当进行一个函数调用,刚进入函数的时候堆栈的栈顶存放的是返回值
数据段
编译器把字符默认存放在数据段,但是不一定放在数据段,也可以放在栈空间
idata 代码区
rdata 常量区
data 数据区–全局变量放在数据段
数据存放地址在: 0x7A7B30
存放在rdata常量区,常量区开始地址是007A7000
数据存放地址=常量区起始地址+便宜
0x7A7B30=007A7000+B30
寄存器ECX
1、在循环计数的时候一般是用ECX来保存循环计数器
寄存器EDI和ESI
1、在操作内存的时候,edi和esi一般是用来保存内存的起始地址
寄存器ESP
1、始终指向的是当前运行环境的栈顶
函数传一个参数,每次扩充了4个字节
ESP=0xDEF900 981248
ESP=0xDEF8FC 981244
ESP=0xDEF8F8 981240
2、
寄存器EBP (栈帧)
1、EBP代表局部变量的分界线,
栈帧EBP往高处走,也就是减少的方向放的是局部变量
栈帧EBP往底处走,也就是增加的方向放的是参数返回值
2、x64位程序没有栈帧
标志寄存器(运算语句会修改标志寄存器,MOV语句不会修改标志寄存器)
C 最高位进位标志位
(最高位由数据的宽度决定 )
A 辅助中间位进位标志位
下图箭头位置 是 32位 的个情况
P标志位 ,奇偶标志位,只看最低有效字节,也就是最后一个字节的二进制1的个数,奇数个置0,偶数个置1
Z 零标志位
S标志位
最高位存的什么值S位里面存的就是什么值