- UID
- 1
- 精华
- 积分
- 76361
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
push、pop是用于在栈上操作内存的指令,通常有以下的主观作用:
1、临时存储某个寄存器的值,以便于使用完这个寄存器后,恢复它原先的值。
2、分配、释放栈空间。
3、将函数的调用参数压入栈,供函数使用(通常见于C语言的_cdecl、C++类成员“方法”的thiscall、Windows API的stdcall等调用约定)
4、取得一些特殊寄存器的值,比如pushfd用于取得、暂存eflags寄存器的值(其它版本的有16位的pushf,x64的pushfr)
5、ShellCode中用于取得当前指令的内存地址。例:db 0xe8,0,0,0,0;pop ebx(取得pop ebx这条指令的地址并存入ebx)
6、绝对地址跳转,例:push 绝对地址;ret
push指令相当于,先将esp的值减去4,然后将要入栈的值存入[ss:esp]。16位的时候是sp的值减去2然后将值存入[ss:sp],x64则是rsp减去8然后存储值到[rsp]。
pop指令则是做相反的操作,先读取[ss:esp],然后将esp的值加上4。16位的时候先读取[ss:sp]然后将sp的值加上2,x64则是先读取[rsp]的值然后将rsp加上8。
push指令的一些额外说明:
1、push寄存器的指令,32位的指令只有1个字节,64位的指令则是两个字节。
2、push立即数的时候,无论你push的立即数有多长,它都是按照位数对齐的(16位2字节对齐,32位4字节对齐,64位8字节对齐)
3、push立即数的指令,如果你push的立即数只有1个字节,指令会短一些(0x6A,值)但是这个值会被认定为有符号整数。因此会有符号扩展。
4、x64的情况下,如果有很多东西需要出入栈,更推荐先将栈空间大小设置好然后用mov来操作栈内存,而不是用push、pop。 |
|