博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学 Win32 汇编[18]: 关于压栈(PUSH)与出栈(POP) 之二
阅读量:7040 次
发布时间:2019-06-28

本文共 3547 字,大约阅读时间需要 11 分钟。

  hot3.png

由于 "栈" 是由高到低使用的, 所以新压入的数据的位置更低.
ESP 中的指针将一直指向这个新位置, 所以 ESP 中的地址数据是动态的.
每次 PUSH, ESP = ESP - x; 每次 POP, ESP = ESP + x;
其中的 x 只能是 4 或 2, 因为 Win32 的 PUSH 只可以压入 32 位(默认)或 16 位的数据.
ESP 有个名字叫 "栈顶", 其实它指向的是栈中最低位置的数据.

实例查看 ESP 的变化:

; Test18_1.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data    ddVal1 dd 1    ddVal2 dd 2    dwVal1 dw 3    dwVal2 dw 4.codemain proc    PrintHex esp  ;0012FFA4        push ddVal1    PrintHex esp  ;0012FFA0    push ddVal2    PrintHex esp  ;0012FF9C    push dwVal1    PrintHex esp  ;0012FF9A    push dwVal2    PrintHex esp  ;0012FF98        pop dwVal2    PrintHex esp  ;0012FF9A    pop dwVal1    PrintHex esp  ;0012FF9C    pop ddVal2    PrintHex esp  ;0012FFA0    pop ddVal1    PrintHex esp  ;0012FFA4    retmain endpend main
使用参数压栈的方式调用函数, 同时揭示 invoke 的本质:

; Test18_2.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.inc;include    masm32.inc;include    debug.incincludelib kernel32.lib;includelib masm32.lib;includelib debug.libinclude    user32.incincludelib user32.lib.data    szMsg     db 'Hello World!', 0    szCaption db 'Hi', 0.codemain proc    ;invoke MessageBox, NULL, addr szMsg, addr szCaption, MB_OK    ;用压栈的方式调用 MessageBox 函数; 本来就是如此, invoke 只是简化了这个步骤    push MB_OK ;C 函数和系统函数读取参数的顺序是: 从右到左; 最左边的参数最后使用, 要先压入    push offset szCaption    push offset szMsg    push NULL  ;一个常数会默认当作 32 位数据压入    call MessageBox    pop edx    ;随便出栈到一个地方, 已经没用了, 相当于进回收站    pop edx    ;尽管没用, 不出是不行的, 因为 push 和 pop 要成对出现    pop edx    pop edx        ;invoke ExitProcess, NULL    ;用压栈的方式调用 ExitProcess 函数    push NULL    call ExitProcess    pop edxmain endpend main
从上面的例子看出, 函数调用是需要先压栈(PUSH)参数的;
PUSH 另一重要作用是保护数据, 调用函数前, 最先需要保护的就是 EIP, 这是执行完函数后的下一条指令的地址.
call 指令会先把 EIP 传给 ESP; ret 指令最后把 ESP 恢复给 EIP. 所以, 压栈出栈保护的是 ESP.
但因 ESP 是动态的, 所以一般先 mov ebp, esp, 然后 push ebp ... 像这样:

mov ebp, esppush ebp;...函数或子过程pop ebpmov esp, ebp;leave ;可以使用 leave 指令代替上面两行, 它是对上面两行的简化
从调试器中查看编译器添加的保护 ESP 的代码:

; Test18_3.asm; 这是用于调试的例子.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.code;求和函数sumProc proc v1:dword, v2:dword, v3:dword    mov eax, v1    add eax, v2    add eax, v3    retsumProc endp;main proc    invoke sumProc, 11, 22, 33    PrintDec eax ;66    retmain endpend main;--------------------------;Ctrl + T 是设置或取消断点;Ctrl + D 是调试运行;从调试器中看到 sumProc 函数的代码变成了:PUSH EBPMOV EBP,ESPMOV EAX,DWORD PTR SS:[EBP+8]ADD EAX,DWORD PTR SS:[EBP+C]ADD EAX,DWORD PTR SS:[EBP+10]LEAVE;看来保护 ESP 的工作是由编译器做的;从这里也看出了 EBP 寄存器的主要用途就是中转 ESP 中的数据
利用 ESP 的地址偏移读取栈中的数据:

; Test18_4.asm.386.model flat, stdcallinclude    windows.incinclude    kernel32.incinclude    masm32.incinclude    debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.codemain proc    push 111    push 222    push 333    push 444        mov eax, [esp]    PrintDec eax     ;444    mov eax, [esp+4]    PrintDec eax     ;333    mov eax, [esp+12]    PrintDec eax     ;111        pop edx    pop edx    pop edx    pop edx    retmain endpend main
总结 PUSH 和 POP 的主要用途: 1、暂存与恢复数据; 2、处理函数参数.

压栈、出栈指令汇总:

PUSH(PUSHW、PUSHD)  / POP   ;进出 16 位或 32 位操作数, 默认 32 位PUSHAD              / POPAD ;进出 EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDIPUSHA               / POPA  ;进出  AX、 CX、 DX、 BX、 SP、 BP、 SI、 DIPUSHFD              / POPFD ;进出 EFLAGSPUSHF               / POPF  ;进出 EFLAGS 的低 16 位

转载于:https://my.oschina.net/hermer/blog/320081

你可能感兴趣的文章
黑客“纵横”全球金融系统 中国公司被盯上
查看>>
“光伏贷”推动分布式光伏进入百姓家
查看>>
探究电气设计系统中计算机的应用
查看>>
洛龙区:加快布局大数据产业
查看>>
看不见的"频谱"助力智慧城市建设
查看>>
软件测试文档写作——测试方案
查看>>
大数据的商业化:从数据、模型到业务逻辑
查看>>
Junit在MyEclipse上怎么用?
查看>>
能测试知多少--系统计数器与硬件分析
查看>>
颠覆传统 移动CRM成企业应用热点
查看>>
适合应用RFID的六大领域介绍
查看>>
《Web测试囧事》——2.6 时区不一致造成邮件发送异常
查看>>
需求管理是需求开发的基础
查看>>
干货:模板网站SEO优化技巧!
查看>>
CB Insights:2017年Q1网络安全领域共实现140宗投资
查看>>
安捷伦2016 Q2收入较去年增长6% 调升全年收入指导范围
查看>>
最新 Chrome 可让本地文件在网页应用中打开
查看>>
《Python地理空间分析指南(第2版)》——1.10 GIS中矢量数据的基本概念
查看>>
MySQL自动化运维工具 Inception
查看>>
QGraphicsItem如何使用信号/槽
查看>>