是汇编语言 堆栈里边的,“堆栈”又表示什么

相关文章推荐
版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:】
只要并发的多个执行单元存在对共享资源的访问,竞态就可能发生。在 Linux 内...
【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:】
上一节说到proc文件系统,这是用户态和内核态通信的一种方法,本节将要说到另外...
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
正如C语言一样,编写所有语言程序一样会出现一些一些错误,发生...
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
和高级语言一样,汇编语言在多个项目之间可能会编写相同的过程和...
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
汇编语言和C一样,可以通过使用库来简化阻止大量函数的目标文件...
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
在前面章节我们已经看到,启动系统调用需要使用INT指令。l...
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
字符串的存储与加载是指,将字符串的值加载到寄存器和将其传回内...
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
汇编语言程序由定义好的段构成,每个段有各自的目的。三个最常...
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
在高级语言中,我们经常操作字符串,比如字符串拷贝、比较、查找...
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途】
cmps指令用于比较字符串值,cmps指令有三种格式:cm...
他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)汇编中 中断中的堆栈的作用是什么?_汇编吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:34,257贴子:
汇编中 中断中的堆栈的作用是什么?收藏
破不了啊&.&求各路高手解答
作为一个资深的酱油党,我们需要做的不仅仅是路过,在路过的同时还要帮助楼主,在这个冷漠的时代,给予楼主温暖。
人!工!置!顶!
楼主你太高大上了,不会,帮顶&.&
保护作案现场!
上帝的骑宠,上古时期世界的霸主。┏┛┻━━━┛┻┓┃|||||||┃┃   ━   ┃┃ ┳┛  ┗┳  ┃┃       ┃┃   ┻   ┃┃       ┃┗━┓   ┏━┛  ┃ 史 ┃    ┃ 诗 ┃    ┃ 之 ┃    ┃ 宠 ┃  ┃   ┗━━━┓  ┃经验与我同在 ┣┓  ┃攻楼专用宠物 ┃  ┗┓┓┏━┳┓┏┛   ┃┫┫ ┃┫┫   ┗┻┛ ┗┻┛要不是3倍经验,我也不会带着我宝贵的宠物来。汉语:我是来打酱油的。英语: I'm going to buy some soy sauce.  韩语: 나는 간장 소스.德语: ich gehe Sojasosse kaufen. 法语: je me suis prend que sauce de soja. 俄语: Я пришла за соевым соусом.荷兰语:kwam ik tot een sojasaus 西班牙语:me vino a un salsa de soja 意大利语:venuta solo a comprare la salsa di soia.你每到一个帖子就粘贴这句话,十五天就到了11级”......我彻底恍然大悟,吧主再也不用担心我的经验了!!!假如你每天签到拿4经验,18级=75000天,如果从1岁开始签到,那100 年=36500天,你差不多要活200年保持每天签到(谁知道200年后尼玛还有没有签到这玩意), 如果你每天再水4经验,时间减半,但考虑现实,你不可能再活100年,取50年吧,你就要每天水16经验,可能你是个勤快的人,每天水32经验,那就需要25年!!!再如果你是个大水怪,每天水64经验,那就只要12.5年!!!还如果你个心急的人,每天水128经验,你只要6.25年!!!!假如你已经急不可耐了,每天水256经验,那你碉堡了,只要3.125年!!!当然,你会觉得3年还是太远了,每天你闲的蛋疼,忙忙碌碌的水512经验,碉堡了, 你只需要1.5625年,只比1年半多一点!!!什么!!你还不满意?那你觉得你可能一天水1024经验吗,可能吗?可能吗??可能!!!据说回复100字或者一百字以上可以得到11~30经验,真的很棒......那么,按照队形,点击复制,把我的话复制一片,拿经验
上帝的骑宠,上古时期世界的霸主。┏┛┻━━━┛┻┓┃|||||||┃┃   ━   ┃┃ ┳┛  ┗┳  ┃┃       ┃┃   ┻   ┃┃       ┃┗━┓   ┏━┛  ┃ 史 ┃    ┃ 诗 ┃    ┃ 之 ┃    ┃ 宠 ┃  ┃   ┗━━━┓  ┃经验与我同在 ┣┓  ┃攻楼专用宠物 ┃  ┗┓┓┏━┳┓┏┛   ┃┫┫ ┃┫┫   ┗┻┛ ┗┻┛要不是3倍经验,我也不会带着我宝贵的宠物来。汉语:我是来打酱油的。英语: I'm going to buy some soy sauce.  韩语: 나는 간장 소스.德语: ich gehe Sojasosse kaufen. 法语: je me suis prend que sauce de soja. 俄语: Я пришла за соевым соусом.荷兰语:kwam ik tot een sojasaus 西班牙语:me vino a un salsa de soja 意大利语:venuta solo a comprare la salsa di soia.你每到一个帖子就粘贴这句话,十五天就到了11级”......我彻底恍然大悟,吧主再也不用担心我的经验了!!!假如你每天签到拿4经验,18级=75000天,如果从1岁开始签到,那100 年=36500天,你差不多要活200年保持每天签到(谁知道200年后尼玛还有没有签到这玩意), 如果你每天再水4经验,时间减半,但考虑现实,你不可能再活100年,取50年吧,你就要每天水16经验,可能你是个勤快的人,每天水32经验,那就需要25年!!!再如果你是个大水怪,每天水64经验,那就只要12.5年!!!还如果你个心急的人,每天水128经验,你只要6.25年!!!!假如你已经急不可耐了,每天水256经验,那你碉堡了,只要3.125年!!!当然,你会觉得3年还是太远了,每天你闲的蛋疼,忙忙碌碌的水512经验,碉堡了, 你只需要1.5625年,只比1年半多一点!!!什么!!你还不满意?那你觉得你可能一天水1024经验吗,可能吗?可能吗??可能!!!据说回复100字或者一百字以上可以得到11~30经验,真的很棒......那么,按照队形,点击复制,把我的话复制一片,拿经验
应该是保存数据吧 我也是新手
登录百度帐号推荐应用在讲解堆栈之前,我们先要来说说其实我们常说的堆栈是两种数据结构。那么什么是堆什么又是栈呢?
&&&&&&&栈,是硬件。主要作用表现为一种数据结构,是只能在某一端插入和删除的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。 栈也称为先进后出表。栈可以用来在函数调用的时候存储断点,做递归时要用到栈!
  以上定义是在经典计算机科学中的解释。
  在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。在i386机器中,栈顶由称为esp的寄存器进行定位。压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大。
  栈在程序的运行中有着举足轻重的作用。最重要的是栈保存了一个函数调用时所需要的维护信息,这常常称之为堆栈帧或者活动记录。堆栈帧一般包含如下几方面的信息:
  1. 函数的返回地址和参数
  2. 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量。
&&&&&&& 堆,是一种动态存储结构,实际上就是数据段中的自由存储区,它是C语言中使用的一种名称,常常用于动态数据的存储分配。堆中存入一数据,总是以2字节的整数倍进行分配,地址向增加方向变动。堆可以不断进行分配直到没有堆空间为止,也可以随时进行释放、再分配,不存在次序问题。
&&&&&&&&&堆和栈在使用时相向生长,栈向上生长,即向小地址方向生长,而堆向下增长,即向大地址方向,其间剩余部分是自由空间。使用过程中要防止增长过度而导致覆盖。
一般的程序我们都是使用小内存模式。
&&&&&&&&明白了堆和栈的概念之后我们来看一个面试的c语言题目。代码要相关要求如下所示:
#include &iostream&
void print()
&&& //这里进行打印arr数组,print不准传参数
int main()
&&& int s=0;
&&& int ss=0;
&&& char *str=&fdsafdsafdsafdsafdsafdsafdsa&;
&&& char fdsa='f';
&&& char srt[8];
&&& int arr[]={32,43,3,567,987,21,56};//数值随即
&&& print();
&&& return 0;
刚刚一开始看到这个题目时,你可能有点发懵,心想可能在不传递参数的情况下打印arr数组的内容,但是看看我们的标题就应该知道该题跟栈有关系,在做之前我们先来回顾几个知识点。
push操作先修改指针,后将信息入栈。
ESP为堆栈指针,栈顶有ESP寄存器来定位。压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大。
EBP是32位的BP,EBP是基址指针,EBP与BP的关系就像AX与AL、AH的关系一样。BP为基指针寄存器,用它课直接存取堆栈中的数据,他的作用在调用函数时保存ESP,使函数结束时可以正确返回。
c的默认函数压栈操作为:
参数是从右向左压栈的,默认四字节对齐,函数里面定义的变量是默认对齐方式----变量首地址是自身结构体里边最大标准数据类型字节的整数倍。
我们先来看看上面这段代码的汇编语句:
//*******************************************start*********************************************//
&.file&&push.c&
.globl print
&.type&print, @function
&pushl&%ebp
&movl&%esp, %ebp
&popl&%ebp
&.size&print, .-print
&.section&.rodata
&.string&&fdsafdsafdsafdsafdsafdsafdsa&
.globl main
&.type&main, @function
&pushl&%ebp
&movl&%esp, %ebp
&andl&$-16, %esp
&subl&$64, %esp
&movl&%gs:20, %eax
&movl&%eax, 60(%esp)
&xorl&%eax, %eax
&movl&$0, 44(%esp)
&movl&$0, 40(%esp)
&movl&$.LC0, 36(%esp)
&movb&$102, 51(%esp)
&movl&$32, 8(%esp)
&movl&$43, 12(%esp)
&movl&$3, 16(%esp)
&movl&$567, 20(%esp)
&movl&$987, 24(%esp)
&movl&$21, 28(%esp)
&movl&$56, 32(%esp)
&call&print
&movl&$0, %eax
&movl&60(%esp), %edx
&xorl&%gs:20, %edx
&call&__stack_chk_fail
&.size&main, .-main
&.ident&&GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2&
&.section&.note.GNU-stack,&&,@progbits
//*******************************************end*********************************************//
看看上面的汇编代码,我们的重点放在红色字体部分,在函数的开头部分都有这么两行代码:
&pushl&%ebp&&&&&&&&&&&& &&---------------------------&保存上一个函数的栈底
&movl&%esp, %ebp&& &---------------------------&用来保存当前堆栈指针的值
ebp存放当前函数栈低的地址,就是说ebp可以看做一个指针,指向栈顶,而其实栈顶存放的数据就是上一个函数的ebp的值,即就是main函数的栈底。
明白了上面的内容,那么我们就可以实现题目的要求了。代码如下所示:
#include &iostream&
void print()
&&& //这里进行排序,print不准传参数
&& unsigned int _
&&& __asm{
&&&&&&& mov _ebp,ebp
&&& int *p=(int *)(*(int *)_ebp-4-4-4-4-8-7*4);
&&& for(int i=0;i&7;i++)
&&&&&&& cout&&p[i]&&
int main()
&int ss=0;
&char *str=&fdsafdsafdsafdsafdsafdsafdsa&;
&char fdsa='f';
&char srt[8];
&&& int arr[]={32,43,3,567,987,21,56};//数值随即
&&& print();
&&& return 0;
其中用红色标记的部分是一个重点,用汇编语句mov _ebp,ebp;来获得ebp寄存器的值,存放在_ebp中,ebp存放当前函数栈底的地址,就是说ebp可以看做一个指针,指向栈顶,因为&pushl&%ebp,所以栈顶存放的数据就是上一个函数的ebp的值,即就是main函数的栈底。由此可知*(int*)_ebp意思就是取出栈顶的数据,即main函数的栈底。栈中数据的存储方式是根据声明的先后顺序来的,所以了为了能够对arr数组进行打印,我们要计算出数组首地址的存储地址,由于变量的压栈方式默认是四字节对齐,所以我们使用一句int *p=(int *)(*(int *)_ebp-4-4-4-4-8-7*4);来得到数组的首地址,有人可能很疑惑了,为什么这句&char *str=&fdsafdsafdsafdsafdsafdsafdsa&;声明的变量只是占了四字节呢?!这里要注意了,因为指针变量的地址在32位的计算机中占用四个字节,他的内容并不存储在栈中,而是在堆中,栈中仅仅是保存了指向堆的指针。讲到这儿基本上都豁然开朗了吧。看看下面的运行结果吧!
为了强调默认的字节对齐概念,我们再来修改下代码得到的运行结果可以上面得做一个比较。
代码如下,红色部分为修改代码。
#include &iostream&
void print()
&&& //这里进行排序,print不准传参数
&& unsigned int _
&&& __asm{
&&&&&&& mov _ebp,ebp
&&& int *p=(int *)(*(int *)_ebp-4-4-4-4-8-7*4);
&&& for(int i=0;i&7;i++)
&&&&&&& cout&&p[i]&&
int main()
&int ss=0;
&char *str=&fdsafdsafdsafdsafdsafdsafdsa&;
&char fdsa='f';
&char srt[6];
&&& int arr[]={32,43,3,567,987,21,56};//数值随即
&&& print();
&&& return 0;
运行结果为:
如果我们修改了&char srt[6];之后去把int *p=(int *)(*(int *)_ebp-4-4-4-4-8-7*4);修改为int *p=(int *)(*(int *)_ebp-4-4-4-4-6-7*4);,注意红色部分的对比,运行结果就变为了:
显然对比可知运行结果出错了。在此多次一举的给出对比无非是为了大家能够对字节的对齐方式加以重视。当然以上内容难免有错,毕竟c语言博大精深,如果有不正确的地方,请纠正。&
与非门科技(北京)有限公司 All Rights Reserved.
京ICP证:070212号
北京市公安局备案编号: 京ICP备:号汇编中参数的传递和堆栈修正(转载罗云彬) - wanghj_dz - 博客园
随笔 - 192, 文章 - 0, 评论 - 3, 引用 - 0
&在 Win32汇编中,我们经常要和 Api 打交道,另外也会常常使用自己编制的类似于 Api 的带参数的子程序,本文要讲述的是在子程序调用的过程中进行参数传递的概念和分析。一般在程序中,参数的传递是通过堆栈进行的,也就是说,调用者把要传递给子程序(或者被调用者)的参数压入堆栈,子程序在堆栈取出相应的值再使用,比如说,如果你要调用 SubRouting(Var1,Var2,Var3),编译后的最终代码可能是&&&push Var3&&&push Var2&&&push Var1&&&call SubRouting&&&add esp,12&&&也就是说,调用者首先把参数压入堆栈,然后调用子程序,在完成后,由于堆栈中先前压入的数不再有用,调用者或者被调用者必须有一方把堆栈指针修正到调用前的状态。参数是最右边的先入堆栈还是最左边的先入堆栈、还有由调用者还是被调用者来修正堆栈都必须有个约定,不然就会产生不正确的结果,这就是我在前面使用&可能&这两个字的原因:各种语言中调用子程序的约定是不同的,它们的不同点见下表:
参数从左到右
参数从右到左
调用者清除堆栈
允许使用:VARARG
&&&VARARG 表示参数的个数可以是不确定的,有一个例子就是 C 中的 printf 语句,在上表中,StdCall 的定义有个要说明的地方,就是如果 StdCall 使用 :VARARG 时,是由调用者清除堆栈的,而在没有:VARARG时是由被调用者清除堆栈的。在 Win32 汇编中,约定使用 StdCall 方式,所以我们要在程序开始的时候使用 .model stdcall 语句。也就是说,在 API 或子程序中,最右边的参数先入堆栈,然后子程序在返回的时候负责校正堆栈,举例说明,如果我们要调用 MessageBox 这个 API,因为它的定义是 MessageBox(hWnd,lpText,lpCaption,UType) 所以在程序中要这样使用:&&&push MB_OK&&&push offset szCaption&&&push offset szText&&&push hWnd&&&call MessageBox&&&...&&&我们不必在 API 返回的时候加上一句 add sp,4*4 来修正堆栈,因为这已经由 MessageBox 这个子程序做了。在 Windows API 中,唯一一个特殊的 API 是 wsprintf,这个 API 是 C 约定的,它的定义是 wsprintf(lpOut,lpFormat,Var1,Var2...),所以在使用时就要:&&&push 1111&&&push 2222&&&push 3333&&&push offset szFormat&&&push offset szOut&&&call wsprintf&&&add esp,4*5
&&&下面要讲的是子程序如何存取参数,因为缺省对堆栈操作的寄存器有 ESP 和 EBP,而 ESP是堆栈指针,无法暂借使用,所以一般使用 EBP 来存取堆栈,假定在一个调用中有两个参数,而且在 push 第一个参数前的堆栈指针 ESP 为 X,那么压入两个参数后的 ESP 为 X-8,程序开始执行 call 指令,call 指令把返回地址压入堆栈,这时候 ESP 为 X-C,这时已经在子程序中了,我们可以开始使用 EBP 来存取参数了,但为了在返回时恢复 EBP 的值,我们还是再需要一句 push ebp 来先保存 EBP 的值,这时 ESP 为 X-10,再执行一句 mov ebp,esp,根据上图可以看出,实际上这时候 [ebp + 8] 就是参数1,[ebp + c]就是参数2。另外,局部变量也是定义在堆栈中的,它们的位置一般放在 push ebp 保存的 EBP 数值的后面,局部变量1、2对应的地址分别是 [ebp-4]、[ebp-8],下面是一个典型的子程序,可以完成第一个参数减去第二个参数,它的定义是:&&&MyProc proto Var1,Var2 ;有两个参数&&&local lVar1,lVar2 ;有两个局部变量&&&注意,这里的两个 local 变量实际上没有被用到,只是为了演示用,具体实现的代码是:MyProc proc&&&push ebp&&&mov ebp,esp&&&sub esp,8&&&mov eax,dword ptr [ebp + 8]&&&sub eax,dword ptr [ebp + c]&&&add esp,8&&&pop ebp&&&ret 8MyProc endp&&&现在对这个子程序分析一下,push ebp/mov ebp,esp 是例行的保存和设置 EBP 的代码,sub esp,8 在堆栈中留出两个局部变量的空间,mov /add 语句完成相加,add esp,8 修正两个局部变量使用的堆栈,ret 8 修正两个参数使用的堆栈,相当于 ret / add esp,8 两句代码的效果。可以看出,这是一个标准的 Stdcall 约定的子程序,使用时最后一个参数先入堆栈,返回时由子程序进行堆栈修正。当然,这个子程序为了演示执行过程,使用了手工保存 ebp 并设置局部变量的方法,实际上,386 处理器有两条专用的指令是完成这个功能用的,那就是 Enter 和 Leave,Enter 语句的作用就是 push ebp/mov ebp,esp/sub esp,xxx,这个 xxx 就是 Enter 的,Leave 则完成 add esp,xxx/pop ebp 的功能,所以上面的程序可以改成:MyPorc proc&&&enter 8,0&&&mov eax,dword ptr [ebp + 8]&&&sub eax,dword ptr [ebp + c]&&&leave&&&ret 8MyProc endp&&&好了,说到这儿,参数传递的原理也应该将清楚了,还要最后说的是,在使用 Masm32 编 Win32 汇编程序的时候,我们并不需要记住 [ebp + xx] 等麻烦的地址,或自己计算局部变量需要预留的堆栈空间,还有在 ret 时计算要加上的数值,Masm32 的宏指令都已经把这些做好了,如在 Masm32 中,上面的程序只要写成为:MyProc proc Var1,Var2&&&local lVar1,lVar2&&&mov eax,Var1&&&sub eax,Var2&&&retMyProc endp&&&编译器会自动的在 mov eax,Var1 前面插上一句 Enter 语句,它的参数会根据 local 定义的局部变量的多少自动指定,在 ret 前会自动加上一句 Leave,同样,编译器会根据参数的多少把 ret 替换成 ret xxx,把 mov eax,Var1 换成 mov eax,dword ptr [ebp + 8] 等等。&&&最后是使用 Masm32 的 invoke 宏指令,在前面可以看到,调用带参数的子程序时,我们需要用 push 把参数压入堆栈,如果不小心把参数个数搞错了,就会使堆栈不平衡,从而使程序从堆栈中取出错误的返回地址引起不可预料的后果,所以有必要有一条语句来完成自动检验的任务,invoke 就是这样的语句,实际上,它是自动 push 所有参数,检测参数个数、类型是否正确,并使用 call 来调用的一个宏指令,对于上面的 push/push/call MyProc 的指令,可以用一条指令完成就是:invoke MyProc,Var1,Var2当然,当程序编译好以后你去看机器码会发现它被正确地换成了同样的 push/push/call 指令。但是,在使用 invoke 之前,为了让它进行正确的参数检验,你需要对函数进行申明,就象在 C 中一样,申明的语句是:MyProc proto :DWORD,:DWORD语句中 proto 是关键字,表示申明,:DWORD 表示参数的类型是 double word 类型的,有几个就表示有几个参数,在 Win32 中参数都是 double word 型的,申明语句要写在 invoke 之前,所以我们一般把它包括在 include 文件中,好了,综合一下,在 Masm32 中使用一个带参数的子程序或者 Api ,我们只需用:&&&...&&&MyProc proto :dword,:dword&&&...&&&.data&&&x dd ?&&&y dd ?&&&dwResult dd ?&&&...&&&mov x,1&&&mov y,2&&&invoke MyProc x,y&&&mov dwResult,eax&&&...就行了,如何,是不是很简单啊?不过我可苦了,这篇文章整整花了我一个晚上 ... ##%$^&(*&^(*&(^&(*PLC编程中“堆栈”是什么意思?_百度知道
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。
PLC编程中“堆栈”是什么意思?
堆栈是什么定义?
跟所有汇编语言一样,PLC的堆栈也是用于处理用户程序过程的中间数据的。1、当电路块串联或并联时,用于存储中间运算结果。2、当触点与线圈,或触点与其他输出类指令组成多分支电路时,用来保存分支点的运算结果在堆栈的存取过程中,PLC有专门的先进先出指令和后进先出指令。
高级工程师
就像装弹夹,一个子弹一个子弹的往里边装,子弹代表数据,每装一个子弹最下边的子弹就会往下一格,直到装满。此时如果再往里装一个子弹,则最下边的子弹会被挤出去。将子弹改为数据即可理解
本回答被提问者采纳
堆栈说通俗一点就是一个数据的临时存放区域,它遵循先进后出的原则即最先压入的数据最后一个取出。它不仅用在PLC编程,所有计算机的编程都有堆栈,都遵循先进后出的规则。
什么叫堆?你用十几个麻将牌竖直叠成一摞这叫堆,你可以从上面、下面、中间任意抽出一张牌,也可以任意插入一张。什么叫栈?AK-47的弹匣就是一个栈,在上面的子弹没被取出之前,你无法取出下面的子弹——尽管你可以从边上的透明部分读出里面装的是什么型号、颜色的子弹。
堆栈是一种存储部件}

我要回帖

更多关于 汇编语言堆栈损坏 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信