学 Win32 汇编[17]: 关于压栈(PUSH)与出栈(POP) 之一
记得刚学多线程的时候, 碰到一个结构:
//Delphi 的语法描述 PContext = ^TContext; _CONTEXT = recordContextFlags: DWORD;Dr0: DWORD;Dr1: DWORD;Dr2: DWORD;Dr3: DWORD;Dr6: DWORD;Dr7: DWORD;FloatSave: TFloatingSaveArea;SegGs: DWORD;SegFs: DWORD;SegEs: DWORD;SegDs: DWORD;Edi: DWORD;Esi: DWORD;Ebx: DWORD;Edx: DWORD;Ecx: DWORD;Eax: DWORD;Ebp: DWORD;Eip: DWORD;SegCs: DWORD;EFlags: DWORD;Esp: DWORD;SegSs: DWORD; end;
从这个结构中可以基本洞察多线程的基本原理:
1、在切换到另一个线程之前, 先把当前线程在寄存器中的数据保存在这个结构;
2、重新切回线程时, 再才这个结构中读出相关数据到寄存器, 从而继续运行...
压栈、出栈也是类似的道理.
一个程序包含若干子程序, 子程序中一般会有自己的参数或局部变量.
在执行这个子程序前, 应该先把寄存器中的相关数据暂存一下(子程序也要使用寄存器), 这就是所谓的压栈(PUSH);
等子程序执行完毕, 再把之前压到栈中的数据取回(而让程序继续执行), 这就是所谓的出栈(POP).
什么是 "栈"?
程序把内存划分了若干区域, 其中有 "全局数据区" 和 "局部数据区".
全局数据所在的位置叫 "堆";
局部数据(局部变量、局部常量、子程序参数)所在的位置叫 "栈", 也叫 "堆栈".
对 "堆" 和 "栈", 前人给出了不同的使用规则:
"堆" 中的数据一般是由下到上排列;
"栈" 的数据则完全相反, 是由下到上排列.
验证 "堆" 与 "栈" 不同的数据排列方式:
; Test17_1.asm .386 .model flat, stdcallinclude windows.inc include kernel32.inc include masm32.inc include debug.inc includelib kernel32.lib includelib masm32.lib includelib debug.lib.data?GlobalVal1 dd ?GlobalVal2 dd ?GlobalVal3 dd ? .codemain procLOCAL LocalVal1:dword, LocalVal2:dword, LocalVal3:dword;获取全局变量地址(地址是顺序递增的):PrintHex offset GlobalVal1 ;00403054PrintHex offset GlobalVal2 ;00403058PrintHex offset GlobalVal3 ;0040305C;获取局部变量地址(地址是顺序递减的):lea eax, LocalVal1PrintHex eax ;0012FFBClea eax, LocalVal2PrintHex eax ;0012FFB8lea eax, LocalVal3PrintHex eax ;0012FFB4ret main endp end main
压栈与出栈的顺序:
.386 .model flat, stdcallinclude windows.inc include kernel32.inc include masm32.inc include debug.inc includelib kernel32.lib includelib masm32.lib includelib debug.lib.dataval1 dd 111val2 dd 222val3 dd 333 .code main procpush val1push val2push val3;压栈完毕, 接着出栈pop val1pop val2pop val3;查看取回的数据:PrintDec val1 ;333PrintDec val2 ;222PrintDec val3 ;111;怎么反了? 这就是常说的 "栈中的数据是先进后出"! 让后进的先出就好了.ret main endp end main
根据 "栈" 先进后出的特点, 写一个变量换值的程序:
; Test17_3.asm .386 .model flat, stdcallinclude windows.inc include kernel32.inc include masm32.inc include debug.inc includelib kernel32.lib includelib masm32.lib includelib debug.lib.dataval1 dd 111val2 dd 999 .codemain procpush val1push val2pop val1pop val2;现在 val1 和 val2 的值已经交换PrintDec val1 ;999PrintDec val2 ;111ret main endp end main
如果仅是交换变量的值, 可以使用 XCHG 指令:
; Test17_4.asm .386 .model flat, stdcallinclude windows.inc include kernel32.inc include masm32.inc include debug.inc includelib kernel32.lib includelib masm32.lib includelib debug.lib.dataval1 dd 111val2 dd 999 .codemain proc;xchg va1, val2 ;指令都不支持对两个变量直接操作, 需要用个寄存器中转下mov eax, val1xchg eax, val2mov val1, eaxPrintDec val1 ;999PrintDec val2 ;111ret main endp end main
根据上面的原理, 也可以方便写出一个翻转字符串的函数:
; Test17_5.asm .386 .model flat, stdcallinclude windows.inc include kernel32.inc include masm32.inc include debug.inc includelib kernel32.lib includelib masm32.lib includelib debug.lib.dataszText db 'Hello World!', 0 .codemain proc;把字符串中的字符逐个压入栈中mov ecx, sizeof szText - 1 ;把字符串长度(将要反复的次数)给 ecx, 没包括结束记号xor esi, esi ;清空 esi, 准备用作数组索引 @@: movzx eax, szText[esi] ;循环读出并压栈push eaxinc esiloop @B;从栈中逐个取出并写入字符串mov ecx, sizeof szText - 1xor esi, esi @@: pop eaxmov szText[esi], alinc esiloop @BPrintString szText ;!dlroW olleHret main endp end main ;做这个程序也有更好的方案, 譬如用 movs
学 Win32 汇编[17]: 关于压栈(PUSH)与出栈(POP) 之一相关推荐
- 根据入栈顺序判断出栈顺序的合法性
这道题不管是面试还是笔试的选择题都非常爱出的一道题 题目描述: 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4 ...
- 数据结构实验之栈七:出栈序列判定
题目描述 给一个初始的入栈序列,其次序即为元素的入栈次序,栈顶元素可以随时出栈,每个元素只能入栈依次.输入一个入栈序列,后面依次输入多个序列,请判断这些序列是否为所给入栈序列合法的出栈序列. 例如序列 ...
- 栈的弹出函数pop()实现方案探讨
多日前,我在blog发表了对<多任务下的数据结构与算法>一书的评论,在与作者的探讨中,我们就栈的弹出函数设计有比较大的分歧,详见http://blog.csdn.net/lanphaday ...
- 根据入栈顺序判断出栈顺序是否合理
def is_pop_order(push, pop):"""根据入栈顺序判断出栈顺序是否合理:param push: 入栈顺序:param pop: 出栈顺序:retu ...
- 有苦有乐的算法 --- 自定义一个栈,实现压栈(push)、弹栈(pop)、获取站内最小值(getmin)
题目 自己定义一个栈的class,要求此栈有三个方法push.pop.getmin push:往栈中压入一个数据 pop:从栈中弹出一个数据 gitmin:过去这个栈中最小的数据单不弹出 解析 准备两 ...
- 数据结构栈(顺序栈、链栈、插入push、删除pop)、队(循环队,链队、入队push,出队pop)知识点梳理
数据结构栈知识点梳理 一 栈的定义 栈(stack)是限定仅在表尾进行插入和删除操作的线性表 不含任何元素的栈称为空栈 允许插入和删除的一端成为栈顶(top),另一端称为栈底(bottom) 具有LI ...
- 【数据结构与算法】栈的基本运算(出栈、入栈、销毁栈等)及源码(顺序栈和链式栈)
一.顺序栈 .h文件 #include <iostream> using namespace std;#define STACKSIZE 100 typedef int DataType; ...
- (学习日记)关于a1,a2,a3,...,an共n个元素依次入栈其可能出栈的排列数的计算(catalan数)...
常规分析(如果对下面的分析感觉比较迷惑的,可以看看下面这个分析http://blog.csdn.net/wind__fantasy/article/details/5398358) 首先,我们设f(n ...
- 学 Win32 汇编[27] - 乘除指令: MUL、IMUL、DIV、IDIV
MUL: 无符号乘 ;影响 OF.CF 标志位 ;指令格式: ;MUL r/m ;参数是乘数;如果参数是 r8/m8, 将把 AL 做乘数, 结果放在 AX ;如果参数是 r16/m16, 将把 AX ...
最新文章
- vs2010设置boost开发环境
- 架构师实践日 · 6.30 杭州站 | 视觉 AI 技术如何助力行业提升?来西子湖畔与业内大咖面对面交流!
- iphone XCode调试技巧之EXC_BAD_ACCESS中BUG解决
- 检索出现次数的SQL语句
- JAVA中的Font
- CVPR 2017论文集锦
- boost::python::detail::is_string_literal相关的测试程序
- android 格式化代码
- 中科院计算机学院研究生招生名额,中科院研究生招生
- 10 行代码判定色*情*图片
- 堪称神级的Spring Boot手册,从基础入门到实战进阶
- 【ubuntu】出现device not managed连接不上网络
- 小米note2鸿蒙ROM,小米Note2官方原版系统rom线刷刷机包_小米Note2线刷官方包
- 大学生职业生涯规划计划与路径_大学生职业生涯的规划路径
- 透镜成像、眼球成像、小孔成像原理
- ubuntu gnome桌面农历日历显示
- 计算机考研360能去哪里,计算机专业考研,有什么好的211院校推荐?
- 贝塞尔曲线想到的--真的很美,但是有时很丑
- 服务器温度显示过高,服务器机房温度过高
- 硬件知识:电源开关上的“1“和“0“分别是什么意思