. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->汇编语言学习交流区
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  学习中几个不明白的地方,请求解答。  [待解决] 回复[ 7次 ]   点击[ 326次 ]  
sbjcm33
[帖 主]   [ 发表时间:2012-11-29 21:32 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2012-11-13 22:06
1.如果将10000H~1FFFFH当作栈段,SS=1000H,SP=0时,我怎么知道它是栈满还是栈空?
2.首先从栈操作指令所完成的功能的角度上来看,push、pop等 指令在执行的进修只修改SP,所以栈顶的变化范围是0~FFFFH,从栈空时候的SP=0,一直压栈,直到栈满时SP=0;如果再次压栈,栈顶将环绕,覆盖了原来栈中的内容。
   问题:当栈满时,再次压栈,栈顶环绕,覆盖了原来栈中的内容。此时SP=0002H,那么是否意味着以前栈中的64K内容都丢失了。
3.将10010H~1001FH当作栈空间,该栈空间容量为16字节(8字),初始状态为空,SS=1000H、SP=0020H,SS:SP指向10020H;在执行8次push ax后,向栈中压入8个字,栈满,SS:SP指向10010H;再次执行push ax:sp=sp-2,SS:SP指向1000EH,栈顶超出了栈空间,AX中的数据送入1000EH单元处,将栈空间外的数据覆盖?(P61)
   问题:栈满,SS:SP指向10010H;再次执行push ax:sp=sp-2,SS:SP指向1000EH,这时SP=-2?这允许吗?如果允许的话是否会和问题2中的栈满环绕相冲突?还有是否意味着当给定栈段SS=1000H时,栈空间的表达范围变成了1000:-FFFF到1000:FFFF。另外我在调试程序时,发现当一段空间被当作栈段时,系统自动向栈顶之上输入几个字节(10个),也就是说当所谓的栈满SS:SP=10010时,栈早就覆盖了前面几个字了。
4.assume假设某一段寄存器和程序中的某一个用segment...ends定义的段相关联。通过assume说明这种关联,在需要的情况下,编译程序可以将段寄存器和某一个具体的段相联系。
   问题:在需要的情况下指的是什么情况?还有在编程的时候发现有时用segment...ends定义的段不用assume假设也不影响程序运行,那到底是什么时候必须要,什么时候可要可不要,什么时候不能要?还有就是一个段寄存器在一个程序中可以“假设”给几个定义的段?
5.一般说来,程序在编译时被编译器发现的错误是语法错误,在源程序编译后,在运行时发生的错误是逻辑错误。
   问题:哪些错误是会被编译器发现。是指指令写错吗?那漏写一些伪指令是不是也属于语法错误。我以前对逻辑错误的理解是程序本身没有错误,但执行的结果达不到预期的效果。而那些比较明显的错误应该编译器能发现,比如:mov ax,4c00h ;int 21h。可实际上这个被定义成逻辑错误。
chinatree
[第1楼]   [ 回复时间:2012-11-30 23:29 ]   [引用]   [回复]   [ top ] 
荣誉值:118
信誉值:0
注册日期:2011-07-07 22:59
1,栈满或栈空是由当前栈顶<->栈底的这部分空间大小决定的,但是还是有些意外情况:
1)当Mov sp,0后,表示栈空间为64k大。(当一直Push直到sp为0时,再次的push会发生2)的情况,猜测)。
2)当mov sp,2后,表示栈空间为2字节大,然后执行2次push后sp=0fffeh,此时发生栈顶回绕,然后cpu遇到无效指令而杀死进程。
2,不会丢失,但是栈顶回绕会引发cpu错误从而杀死进程。
3,栈底只是我们自己的一个约定,需要我们自己的维护。但是0是分界线,当sp为20h时Cpu会认为栈空间为32字节,所以当sp=10h时再次push有效。至于调试时发现栈空间被改变是因为调试器会使用被调试程序的栈保存现场(就是寄存器环境,学名 线程上下文)。
4,assume是伪指令,它是用来给编译器看的,它的具体使用方法还得你自己去看编译器帮助文档或者网上资料,我不是很熟,但是我只知道一点,当程序中没有使用这个伪指令定义关联时,push cs/pop ds编译器会报错。至于需要的情况,我猜测类似开始标号那样cs自动关联那个段。
5,我认为,编译器无法正确解析的语句就是语法错误,比如mov [bx],1这句,编译器无法判断源/目的操作数的大小。而程序过了语法检测这关,在执行时无法达到我们要求的结果,都可以认为是逻辑错误,比如你示例的意外注释掉int 21h导致程序无法退出而跑飞。
sbjcm33
[第2楼]   [ 回复时间:2012-12-01 23:09 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2012-11-13 22:06
首先谢谢楼上的解答。不过还有以下几个地方不是很明白:
第2个问题,我的意思是指会不会从栈中丢失,而不是指从内存丢失。因为(sp)=2时,那些以前的数据已经在栈顶之外。
第3个问题,我大意了,没注意所谓的栈满时(sp)=10h,以为是(SP)=0.或者我应该认为是作者的误导。但问题还是存在,就如你说的"调试器会使用被调试程序的栈保存现场(就是寄存器环境,学名 线程上下文)",那就是说这些保存的现场会提前覆盖栈外那些内容,根本就不会等到栈满时才会覆盖栈外内容。
第5个问题,“编译器无法正确解析的语句就是语法错误”那是不是说如果漏写ends和end也不属于语法错误?
chinatree
[第3楼]   [ 回复时间:2012-12-02 01:05 ]   [引用]   [回复]   [ top ] 
荣誉值:118
信誉值:0
注册日期:2011-07-07 22:59
第二个问题,这段内存会一直存在于内存中,不会丢失,压栈操作只会减sp,栈在哪是由ss指定,和sp无关。
第三个问题,这种情况只发生在调试时,cpu认为栈以0做为边界,所谓的把10h-20h做栈是我们的约定,这需要我们自己维护。
第五个问题,漏写end不是语法错误,编译器会认为可以从第一个段的0偏移位置执行,而ends却不行,因为它是segment/struct等伪指令的一部分,缺少它,编译器不知道这些伪指令的作用范围。且个人认为语法错误和逻辑错误并没有严格的分界线。
sbjcm33
[第4楼]   [ 回复时间:2012-12-02 10:32 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2012-11-13 22:06
谢谢chinatree,比以前明白了不少。
第二个问题,也说是说完成了POP出栈后,出栈的内容实际还是在栈内。虽然不能再用出栈读这个数,但可以用BP指向读这个数。我记得在书中某处说过出栈后,内容已经不在栈中,但还在内存中。
第三个问题,原来只是在调试时才会出现,一直都用的是调试,被误导了。为什么我们在人为约定10h-20h做栈,而不是与CPU一样以0做边界。这在实际应用中有什么好处。我想如果没有什么好处的话我们也不会这么约定的吧。
chinatree
[第5楼]   [ 回复时间:2012-12-02 12:49 ]   [引用]   [回复]   [ top ] 
荣誉值:118
信誉值:0
注册日期:2011-07-07 22:59
好处肯定有啊,在Win32保护模式下,一般都会开启内存分页,这样栈就不能以0做边界,以为4g的低64k是系统空间。
出栈后内容没被覆盖肯定还在内存中呀。
sbjcm33
[第6楼]   [ 回复时间:2012-12-03 23:05 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2012-11-13 22:06
原来关系到内存分页的知识,既然知道它确实有存在的必要那就用着先。
出栈后内容还在内存中我知道。我只是不明白在这段内存中的内容还算不算栈段内。其实在不在栈内只是我们自己的理解,并不影响计算机,也不会影响编程。只是有时做选择题时有些麻烦。
chinatree
[第7楼]   [ 回复时间:2012-12-04 15:16 ]   [引用]   [回复]   [ top ] 
荣誉值:118
信誉值:0
注册日期:2011-07-07 22:59
一个约定而已。
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved