首页
社区
课程
招聘
[求助]一段汇编代码中的问题,望高手解答
发表于: 2009-4-12 23:06 5619

[求助]一段汇编代码中的问题,望高手解答

2009-4-12 23:06
5619
mov ax,2000h
mov ss,ax
mov sp,0
add sp,4
pop ax
pop bx
push ax
push bx
pop ax
pop bx
mov ax,4c00h
int 21h
这是程序段,当执行过pop ax这里的时候系统提示出错,在执行第五条命令之前,我用参数D查看了ss:sp发现堆栈中记录的栈顶数据为与CS,DS,ES中的值相同,而后面的值为0DD4,这个值不知道是什么.我想问为什么程序执行到这里会出错,难道是因为在保护模式下,还有根据堆栈入栈出栈的原理sp=sp-2,sp=sp+2当堆栈中数据存满后,为什么我的SP=0004,不是说SS:SP永远指向栈顶吗,那么,当堆栈满时,SS:SP也应该为2000:0000为什么,而我看DEBUG在SP栏中显示的是0004而不是0000

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (19)
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
------
2009-4-12 23:31
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
初步看法:
你在
mov sp,0
add sp,4
时已初始化栈顶,SP里是4(0004h)
后面接着就
pop ax     ;AV《——(SS:0004h,SS:0005h)
pop bx    ; BX《——(SS:0006h,SS:0007h)
问题应该出在这,更深更详细的回答就待大佬们了。。。
2009-4-13 12:04
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
4
2009-4-13 12:16
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
老大,我想问的是为什么是"为什么我的SP=0004,不是说SS:SP永远指向栈顶吗,那么,当堆栈满时,SS:SP也应该为2000:0000为什么,而我看DEBUG在SP栏中显示的是0004而不是0000"这个
2009-4-13 15:05
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
看你的题,好象也王爽书上的,我也才看,只能和您一起交流一下,互相学习,(讨论有时也增加自己进步)。
依我初学来看,你对王爽对堆栈的讲解没看彻底。。。
mov ax,2000h
mov ss,ax
你这里设的是堆栈段地址。究竟堆栈是多大,还要你设,(王爽的书在堆栈超界时也已说到:...8086CPU只知道栈顶在何处,而不知道我们安排的栈空间有多大。。。但也不是很详细)所以,在确定了堆栈段地址SS后,要接着设SP(即初始栈顶),一般来说下面的对栈操作都要在SS:00--SS:SP之间操作,对与你上面说的“当执行过pop ax这里的时候系统提示出错”是否属于段越界,我也不知道,或者那段内容属于保护内容,我也不知道。这些都不是我目前能掌握的。
至于你说的。"为什么我的SP=0004,。。。而不是2000:0000",当你
mov sp,0
add sp,4
时,SP被你调整为0004了,SP自然=0004,根据SP始终指向栈顶,SS:0004就是此时的新栈顶,此时2000:0004-2000:0000空间是空的,如果你在此指令后面接着来2个PUSH(如,PUSH AX   PUSH AX  )栈才会满,SS:SP才会=2000:0000,2000:0000才成为又一次新栈顶。

我也初学者,说点看法,交流一下。
错了,期望大佬门纠下。
2009-4-13 19:27
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
7
怎么这个问题是你问的啊,刚刚有人在QQ上也有人问我,应该是看到这个帖子的,我把我的回答贴下吧,诶,郁闷!
moonife 18:24:54
第一:为什么会出错:见14楼。。。。。。。。。。。

moonife 18:26:18
第二:sp是永远指向栈顶的 这个你不需要怀疑 只是什么地方你想错了而已 从你说的 我也不清楚你哪儿错了 所以还请自己探索
2009-4-13 19:36
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
堆栈段说简单也简单,说麻烦也麻烦。看到7楼说的sp是永远指向栈顶的 这个你不需要怀疑这句话,使我想起了一个到今天我还没解开的疑团,就是PUSHA或者PUSHAN时,是先调整SP指向新栈顶再寄存器陆续压栈(这样,压栈的将是调整后的SP值,是调整后的值就有问题了,起不到保护原SP的目的啊?),还是先寄存器陆续压栈再调整SP指向新栈顶(这样保存的是没调整前的旧值,但这样一来,在执行这个指令时,SP没指向栈顶啊),问了很久,都没大佬门的确切回答。。。还是一个大疑团,。。
顺便提下,看看有大佬门解答没。。。也帮帖主顶下帖。。。
2009-4-13 20:32
0
雪    币: 2110
活跃值: (21)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
9
堆栈,按照栈顶指针操作,分为“空”堆栈和“满”堆栈;按生长方向,分为“递增”堆栈和“递减”堆栈。

概念的准确解释,谷歌或百度就行。

x86的堆栈是“满递减”堆栈。

ARM处理器支持全部4种堆栈模式。
2009-4-13 20:39
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
也知道书呆版主说的,所谓向下生长和向上生长方式。。。可这问题和那无关。。。你细看下我说的意思就明白了。。。是说这个指令在底层处理过程中,SP在何时开始调整。。。
唉。。。我自己都不想提。。。怪我自己钻了个牛角尖。。。麻烦。。。
还是先看王爽的通俗易懂些。。。
2009-4-13 21:02
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
11
8楼的问题问得很好,这是一个很正常不过的小误区,我回答一下,希望你能够解惑,指令:
push esp ;这个完成的步骤应该是这样的
1 先取esp的值进行保存,如果你要问这个值保存到什么地方去了,这个还是问intel吧,我也不知道
2 进行push操作,也就是esp-4
3 把保存的值压入esp所指的地址
2009-4-13 21:07
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
11楼也有这个看法。。。
除前期的CPU(具体哪一代开始为界,我也不确定,)如8086,PUSH  SP保存的是旧值。这好理解,先调整SP(指向栈顶),再SP压栈,保存的自然是调整后的新值,后期的凡关系到SP(或者ESP)压栈保存的都改为保存旧值,就是没调整前的值,也就是说SP里的值先不调整(当然也就没指向新栈顶了)。就开始把SP的值写入栈。写过后,再调整(也就是指向新栈顶)。这很矛盾的。先压栈再SP指向新栈顶,说不过去啊。。。
很长时间都没大佬们的完美解答。我自己只好瞎猜,有其他寄存器隐性参与了(我瞎猜的。和你的说法差不多)。。。好把自己从牛角尖里拉出。。。晕。。。
2009-4-13 21:28
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
大侠们,我想问问,寄器存有自己保存值的功能,为什么还需要系统记录到栈里,在下次执行之前,恢复数据呢,还有那么,就算记录到栈里,那么SP总应该要发生变化吧,可是我那段,SP从头到尾,他动都不动
2009-4-13 21:57
0
雪    币: 370
活跃值: (52)
能力值: ( LV13,RANK:350 )
在线值:
发帖
回帖
粉丝
14
首先我更正我在7楼错误的解释,经过跟踪发现第一个应该是这样的,
:为什么会出错:你在单步执行命令的时候,系统会在每一个中断产生的时候保护主要寄存器的值将它们压栈,执行下一步的时候在恢复,然而lz的add sp,4导致栈空间太小,保护现场的时候已经跨段了,然而不知是ms-dos的机制还是cpu的保护,跨段的压栈操作没有得到进行,至少是cs和ip的值没有得到保存,所以恢复的值肯定是错的就崩溃了
对于12楼的好问,我只能建议:自己探索,要不找intel问问!
2009-4-13 22:23
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
各位大侠们,小鸟,我终于想通了,感谢各位的顶贴,其实没有我们想的那么复杂,原因很简单就是当我们在执行T命令后,系统将数据压入栈里的最低要求就是要将CS,IP里面的值保存,这就是我将ADD SP,4改成ADD SP,5不行,当改成ADD SP,6就可以了,这也是为什么执行POP AX为什么会出错的原因,因为恢复数据时,IP的值不知道,哈哈,我想这应该是对的吧,如果有错,还望各位大侠指正.
2009-4-13 22:32
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
看你说的意思,应该合用一个段,也不知道你这样写程序和T的目的是什么,别人也不好多说啊。你最好把整个程序都帖出来(看样子也就前头没贴),T的过程也抓图更好,问人总要把问题说详细,别人才好答啊。。。
你看你那过程,栈还没进货,就先往外出货,货还不在栈内出,在栈外随便搞个货就出。。。还出出进进几次,谁知道那货是不是别的程序在用的,还是你自己CS段里的。。。那能给你用吗。(大概意思吧,我也初学,只能打比方说了)
信息多了,有时靠几个寄存器器不够用。就要保存一些,腾一些寄存器出来。。。
王爽的书还是很通俗的。。。一步步学,应该能搞定的。。。不能急躁。。。
只能这样了。。。
2009-4-13 22:33
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
谢谢你,你们的思路让我想明白了,多谢你们
2009-4-13 23:06
0
雪    币: 723
活跃值: (81)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
18
你们对 stack 的理解都太浅了,不够深入透彻

除非使用了 expand-down 类型的 data segment 作为 stack 。

否则 stack 和 普通的 data segment 是完全一致的。

--------------------------------------------------------------

绝大部分的 stack 都是使用 expand-up 类型的 data segment
也就是说:和 DS 寄存器指向的 data segment 是一致的。

在 processor REST# 后:
  SS 寄存器初始化为:SS.base = 0000, SS.limit = FFFFh. SS.attribute.type = 0010(它是 expand-up、readable/writable)

初始化后:SS 是 expand-up 类型的 data segment

对于 expand-up 的 data segment:它的 segment offset 有效范围是: 0 ~ limit,也就是 0 ~ FFFFh。
real-mode 的 stack 的 offset 取值范围是:0 ~ FFFFh。

执行:
mov ss,2000h
-------------------------
后 SS.base = 2_0000h(2000 << 4)
所以,此时 stack 的取值范围是:2_0000 ~ 2_FFFF

pop ax
-----------------
意思是: ax = [sp], sp++;
若 [sp] 不在 2_0000 ~ 2_FFFF 范围内就会出现 #SS 异常

在保护模式下:
若 G =1 时,offse 取值为:0 ~ limit * 4K + (4K -1)
-----------------------------------------------------------------

对于 expand-down 类型的 stack 来说,
它的取值范围是:

在实模式下:由于 SS.attribute.D = 0、SS.attribute.G = 0
所以:limit + 1 ~ FFFF

在保护模式下:
(1)D = 1 && G = 0:
offset 取值范围则是: limit + 1 ~ FFFF_FFFF

(2)D = 1 && G =1
offset 取值范围则是:limit * 4K + (4K -1) + 1 ~ FFFF_FFFF

(3)D = 0 && G =1
offset 取值范围则是:limit *4K + (4K -1) + 1 ~ FFFF

----------------

对于 expand-up 类型的 data segment 来说
limit 定义上限。

对于 expand-down 类型的 data segment 来说:
limit 定义下限。
2009-4-14 00:11
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
执行T命令后,系统将数据压入栈里的最低要求就是要将CS,IP里面的值保存,这就是我将ADD SP,4改成ADD SP,5不行,当改成ADD SP,6就可以了
2009-4-14 13:40
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
sp,4太小了
2009-4-14 14:28
0
游客
登录 | 注册 方可回帖
返回
//