鱼C论坛

 找回密码
 立即注册
查看: 2422|回复: 13

为什么这个代码非自然退出了

[复制链接]
发表于 2013-8-24 22:01:38 | 显示全部楼层 |阅读模式
1鱼币
assume cs:codesg,ss:stacksg

stacksg segment
        dw 5,6,7,8
stacksg ends

codesg segment
        start :        mov ax,stacksg
                        mov ss,ax
                        mov sp,8
                       
                        mov ax,1
                        mov bx,2
                        mov cx,3
                        mov dx,4
                       
                        push ax
                        push bx
                        push cx
                        push dx  ;这条语句还未执行程序就退出来了
                       
                        pop dx
                        pop cx
                        pop bx
                        pop ax
                       
                        mov ax,4C00H
                        int 21h
                       
codesg ends

end start

调试结果:
---------------------------------------
c:\XJY\asm>debug 14.exe-t
AX=14F2  BX=0000  CX=0031  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=0003   NV UP EI PL NZ NA PO NC14F3:0003 8ED0          MOV     SS,AX-t
AX=14F2  BX=0000  CX=0031  DX=0000  SP=0008  BP=0000  SI=0000  DI=0000DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=0008   NV UP EI PL NZ NA PO NC14F3:0008 B80100        MOV     AX,0001-t
AX=0001  BX=0000  CX=0031  DX=0000  SP=0008  BP=0000  SI=0000  DI=0000DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=000B   NV UP EI PL NZ NA PO NC14F3:000B BB0200        MOV     BX,0002-t
AX=0001  BX=0002  CX=0031  DX=0000  SP=0008  BP=0000  SI=0000  DI=0000DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=000E   NV UP EI PL NZ NA PO NC14F3:000E B90300        MOV     CX,0003-t
AX=0001  BX=0002  CX=0003  DX=0000  SP=0008  BP=0000  SI=0000  DI=0000DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=0011   NV UP EI PL NZ NA PO NC14F3:0011 BA0400        MOV     DX,0004-t
AX=0001  BX=0002  CX=0003  DX=0004  SP=0008  BP=0000  SI=0000  DI=0000DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=0014   NV UP EI PL NZ NA PO NC14F3:0014 50            PUSH    AX-t
AX=0001  BX=0002  CX=0003  DX=0004  SP=0006  BP=0000  SI=0000  DI=0000DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=0015   NV UP EI PL NZ NA PO NC14F3:0015 53            PUSH    BX-t
AX=0001  BX=0002  CX=0003  DX=0004  SP=0004  BP=0000  SI=0000  DI=0000DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=0016   NV UP EI PL NZ NA PO NC14F3:0016 51            PUSH    CX-tc:\XJY\asm>


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-8-24 22:05:52 | 显示全部楼层
同时,在调试过程中 mov sp,8 这条语句debug中也是不会显示的执行。

还有stacksg 赋初值是不是没有用啊,怎么查询内存 14f2:0处的值看不到5,6,7,8这几个数据啊?

AX=14F2  BX=0000  CX=0031  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=0003   NV UP EI PL NZ NA PO NC
14F3:0003 8ED0          MOV     SS,AX
-t

AX=14F2  BX=0000  CX=0031  DX=0000  SP=0008  BP=0000  SI=0000  DI=0000
DS=14E2  ES=14E2  SS=14F2  CS=14F3  IP=0008   NV UP EI PL NZ NA PO NC
14F3:0008 B80100        MOV     AX,0001
-t
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 10:18:22 | 显示全部楼层
测试栈内有代码被覆盖导出错,具体为什么会这样,我也不清楚
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 10:45:19 | 显示全部楼层
你在1楼那代码里的注释是发现问题前还是后才加的?那注释符分号要用英文的。把注释符改下我试了是没有问题的,运行正常,结果也可以理解。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 10:54:58 | 显示全部楼层
至于你在2楼的问题:
1、单步调试t遇见mov ss,  XX语句会自动把下一句一并执行
2、在debug把代码加载进去后你用d查看  d ss:0 f是可以看到5678的,因为这时候还没有作为栈段。而当执行到mov ss,XX/mov sp,XX后已经将其设为栈段,并且逻辑上的栈在此时为空(也就是说系统可以把未用的栈空间作为它用),所以你这时候查看的话,该段可能就不是5678了。
一样的道理,到你4条push进去后你查看,是可以看到1234的,但4条pop后对应的栈空间又为空了,系统又可以拿作它用了,你就可能看不到1234了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 12:08:12 | 显示全部楼层

我测试把注释去掉,执行到push cx的时候debug会报错,你那里不会报错么?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 12:38:42 | 显示全部楼层
小咒 发表于 2013-8-25 12:08
我测试把注释去掉,执行到push cx的时候debug会报错,你那里不会报错么?

确实,直接g命令运行没问题,但单步的话到push cx就报错。
按实际想法,stacksg作为栈段,段空间大小为16字节,要使得该段作为栈段使用并且栈初始为空,在mov ss,ax后栈顶sp应设为10h.这样单步就没有问题。
这里面的原因我也不知道。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 13:01:57 | 显示全部楼层
tsembrace 发表于 2013-8-25 12:38
确实,直接g命令运行没问题,但单步的话到push cx就报错。
按实际想法,stacksg作为栈段,段空间大小为1 ...

我debug的时候发现运行到push cx的时候栈内03地址u命令查看变成了push cx前面的话也有数据写入了,具体为什么这样我也没搞明白,如果dw 8 dup(0),sp指向10h的话确实没问题,其中的道理看来只能等高人来解答了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 13:27:17 | 显示全部楼层
小咒 发表于 2013-8-25 13:01
我debug的时候发现运行到push cx的时候栈内03地址u命令查看变成了push cx前面的话也有数据写入了,具体为 ...

非但如此,你用debug加载,用g命令执行到4条push之后,再用d查看压入栈空间的数据,都是没有问题的(1234都是存放正确的)。
用g执行到最后,也是正常的(没有报错);只是这时候栈段已经空了,栈段数据可能发生了变化。
另外楼主这里stacksg段,虽然只定义了5,6,7,8四个字型数据,但实际分配给stacksg的空间也是16字节。
哪怕只是db 1这样的,至少都是分配16字节。
所以,对于这里,sp设为10h不是没问题,而就是“应该如此”。
当sp设为8后,按我们的想法,从stacksg段空间起始到栈顶还有8字节的空间,理论上在这里存放4字的数据是刚好,也没有问题的;我个人之前也是这么认为的。但单步调试就确实是报错了,是不是,栈段空间不能用足?要给他预留多些空间?但这又咋解释t和g分别调试的差异?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 14:09:30 | 显示全部楼层
tsembrace 发表于 2013-8-25 13:27
非但如此,你用debug加载,用g命令执行到4条push之后,再用d查看压入栈空间的数据,都是没有问题的(1234 ...

确实如果小于16个字节的大小也会是16个字节
另外我把代码改了一下
  1. assume cs:codesg,ss:stacksg

  2. stacksg segment
  3.         dw 8 dup(0)
  4. stacksg ends

  5. codesg segment
  6.         start:       mov ax,stacksg
  7.                         mov ss,ax
  8.                         mov sp,10h
  9.                        
  10.                         mov ax,1
  11.                         mov bx,2
  12.                         mov di,3
  13.                         mov dx,4
  14.                         mov cx,2
  15.                         
  16.                         
  17.                         s:push ax
  18.                         push bx
  19.                         push di
  20.                         push dx  ;这条语句还未执行程序就退出来了
  21.                         loop s
复制代码
单步调试,当第二次执行到push di的时候相同的也报错了,栈地址报错的地方是相同的,目前感觉我们只能认定为栈是需要预留空间的,以单步调试来说最起码要预留4个字节的空间?


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 14:48:18 | 显示全部楼层
小咒 发表于 2013-8-25 14:09
确实如果小于16个字节的大小也会是16个字节
另外我把代码改了一下
单步调试,当第二次执行到push di的时 ...

感觉上确实如此,你loop第一次到push dx的时候没有报错?因为那时候设定的栈空间还没有被push满。第二次到push dx的时候已经push8次,把栈弄满了,所以报错了?
你提到的“单步调试来说最起码...”这句对我是个核心语句,虽然无法得知确切的原因,但也大致可知,单步调试时候会利用设定的栈空间(即任何时候的ss:sp指向区域)保护该步骤时的某些数据?而g命令就不需要。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-8-25 15:03:45 | 显示全部楼层
tsembrace 发表于 2013-8-25 14:48
感觉上确实如此,你loop第一次到push dx的时候没有报错?因为那时候设定的栈空间还没有被push满。第二次到 ...

不是,没有全部入栈就出错了,出错的位置和原本的代码相同,第二次di入栈就报错。

反正总结下来我们定义的16个字节的栈内会出现目前我们“未知的数据”而导致入栈出错,栈到底是否需要预留空间?想来想去以我目前的知识还是一个未知数吧,而另外发现一个问题就算我们直接以G命令可以顺利执行完毕后,定义的栈内还是会出现一些“未知的数据”
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2013-8-26 01:43:48 | 显示全部楼层
感谢楼上的各位分析,仔细又看了下小甲鱼的第30集视频,段的大小必须为16的倍数,即最小必须为16.

但是如果sp没有设置为16的倍数会发生什么情况?跟踪了下代码,发现在mov ss,ax后,原来栈处的内容会被改写,具体情况见附件。
q1.PNG
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-11 00:02

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表