王爽汇编语言第六章程序6.3单步调试看不懂

时间:2021-10-21 19:22:35

assume cs:code
code segment
     dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
     dw 0,0,0,0,0,0,0,0
start: mov ax,cs
     mov ss,ax
     mov sp,32h
     mov bx,0
     mov cx,8
    s:push cs:[bx]
     add bx,2
     loop s
     mov bx,0
     mov cx,8
   s0:pop cs:[bx]
     add bx,2
     loop s0
        mov ax,4c00h
        int 21h
code ends
end  start

执行完 mov ss,ax后,下一步执行ADC  AX,[BX+SI] 下一步应该执行mov sp,32h啊?接着后面的单步调试就更看不懂了,这就不一一细说了,而且从S循环和S0循环看,应该循环了3*8+3*8次,也就是至少要单步调试50次 程序才结束的啊!而我没按几个T就执行结束了,这里到底是什么原因?

7 个解决方案

#1


1.程序循环次数是s——8次,s0——8次,总共16次
2.mov ss,ax
     mov sp,32h是连续执行的,避免中断干扰堆栈初始化;
3.程序代码段的可执行代码对应的偏移地址范围是0--48H,而SP=32h,恰处于这一范围,所以堆栈初始化完成后,2EH、2FH、30H、31H的原有代码就被入栈的“0DFEH”和堆栈段段地址覆盖了。也就是堆栈初始化后中间的几个字节的代码因为数据入栈而被破坏了。如果想避免这种情况的话,就把SP设大些。

#2


引用 1 楼  的回复:
1.程序循环次数是s——8次,s0——8次,总共16次
2.mov ss,ax
  mov sp,32h是连续执行的,避免中断干扰堆栈初始化;
3.程序代码段的可执行代码对应的偏移地址范围是0--48H,而SP=32h,恰处于这一范围,所以堆栈初始化完成后,2EH、2FH、30H、31H的原有代码就被入栈的“0DFEH”和堆栈段段地址覆盖了。也就是堆栈初始化后中间的几个字节的代码因为数据入栈……

第一 我说的是单步调试的次数,循环8次,那么每次都要调试三次才能完成一个循环。所以其实都一样
第二 你说的我认可。
第三 经测试,应该把SP设置为20H才能正常单步调试,所以应该缩小SP(20H=32)一共16个字单元,相当于32个字节,用16位进制表示就是从0到20H才对。

下面有请大神来看看我说的是否正确?

#3


我觉得二楼的第三个答案楼主要注意理解下
首先举个例子
例如0000:0010到0000:0000首先设置为0
你设置ss为0000
而sp为0010
则0000:0010h到0000:0000之间由于设置了sp会导致0000:0010之前的某些数据(10h前8个字节)会被修改(可以在DEBUG用d命令来查看,在d 0000:0000 - 0000:0010 会被设置成其他数据,我也不知道为啥^^..不过应该是计算机内的一种机制吧^^)

然后在看看代码段
前面设置了8 * 2 * 2 byte = 36 byte
设置了ss为cs
sp为32h = 3 * 16 + 2 = 48 + 2 = 50
又因为设置sp的前八个数据会被修改
因此50 - 8 = 42(也就是说第四十二个字节开始的数据会被修改)
由于前36个字节是用来存储数据的
     mov ax,cs
     mov ss,ax
     mov sp,32h
占了3 * 2 = 6 byte的数据
36 + 6 = 42
mov bx,0这条指令就是在42之后开始的
而由于修改了指令
因此这条指令也被修改成了mov bx,29E6
后面的数据也就乱了
也因此后面的调试步骤乱了

#4


有点晕····

#5


你把32后面多加了个h  原本的32会被编译器编译成20h的。我也在看这本书,你比我看的快点,我刚看到这里。

#6


assume cs:code
code segment
start: mov ax,cs
     mov ss,ax
     mov sp,32h
     mov bx,0
     mov cx,8
    s:push cs:[bx]
     add bx,2
     loop s
     mov bx,0
     mov cx,8
   s0:pop cs:[bx]
     add bx,2
     loop s0
        mov ax,4c00h
        int 21h
code ends
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
dw 0,0,0,0,0,0,0,0
end  start

你这样试试撒 

#7


原因:堆栈数据在代码段数据的前面,堆栈初始化后, 堆栈数据因为入栈,破坏了后面的代码段的数据,导致代码段数据改变,程序指令改变。
so easy ,将代码段放在堆栈数据的前面就能解决这个问题。

#1


1.程序循环次数是s——8次,s0——8次,总共16次
2.mov ss,ax
     mov sp,32h是连续执行的,避免中断干扰堆栈初始化;
3.程序代码段的可执行代码对应的偏移地址范围是0--48H,而SP=32h,恰处于这一范围,所以堆栈初始化完成后,2EH、2FH、30H、31H的原有代码就被入栈的“0DFEH”和堆栈段段地址覆盖了。也就是堆栈初始化后中间的几个字节的代码因为数据入栈而被破坏了。如果想避免这种情况的话,就把SP设大些。

#2


引用 1 楼  的回复:
1.程序循环次数是s——8次,s0——8次,总共16次
2.mov ss,ax
  mov sp,32h是连续执行的,避免中断干扰堆栈初始化;
3.程序代码段的可执行代码对应的偏移地址范围是0--48H,而SP=32h,恰处于这一范围,所以堆栈初始化完成后,2EH、2FH、30H、31H的原有代码就被入栈的“0DFEH”和堆栈段段地址覆盖了。也就是堆栈初始化后中间的几个字节的代码因为数据入栈……

第一 我说的是单步调试的次数,循环8次,那么每次都要调试三次才能完成一个循环。所以其实都一样
第二 你说的我认可。
第三 经测试,应该把SP设置为20H才能正常单步调试,所以应该缩小SP(20H=32)一共16个字单元,相当于32个字节,用16位进制表示就是从0到20H才对。

下面有请大神来看看我说的是否正确?

#3


我觉得二楼的第三个答案楼主要注意理解下
首先举个例子
例如0000:0010到0000:0000首先设置为0
你设置ss为0000
而sp为0010
则0000:0010h到0000:0000之间由于设置了sp会导致0000:0010之前的某些数据(10h前8个字节)会被修改(可以在DEBUG用d命令来查看,在d 0000:0000 - 0000:0010 会被设置成其他数据,我也不知道为啥^^..不过应该是计算机内的一种机制吧^^)

然后在看看代码段
前面设置了8 * 2 * 2 byte = 36 byte
设置了ss为cs
sp为32h = 3 * 16 + 2 = 48 + 2 = 50
又因为设置sp的前八个数据会被修改
因此50 - 8 = 42(也就是说第四十二个字节开始的数据会被修改)
由于前36个字节是用来存储数据的
     mov ax,cs
     mov ss,ax
     mov sp,32h
占了3 * 2 = 6 byte的数据
36 + 6 = 42
mov bx,0这条指令就是在42之后开始的
而由于修改了指令
因此这条指令也被修改成了mov bx,29E6
后面的数据也就乱了
也因此后面的调试步骤乱了

#4


有点晕····

#5


你把32后面多加了个h  原本的32会被编译器编译成20h的。我也在看这本书,你比我看的快点,我刚看到这里。

#6


assume cs:code
code segment
start: mov ax,cs
     mov ss,ax
     mov sp,32h
     mov bx,0
     mov cx,8
    s:push cs:[bx]
     add bx,2
     loop s
     mov bx,0
     mov cx,8
   s0:pop cs:[bx]
     add bx,2
     loop s0
        mov ax,4c00h
        int 21h
code ends
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
dw 0,0,0,0,0,0,0,0
end  start

你这样试试撒 

#7


原因:堆栈数据在代码段数据的前面,堆栈初始化后, 堆栈数据因为入栈,破坏了后面的代码段的数据,导致代码段数据改变,程序指令改变。
so easy ,将代码段放在堆栈数据的前面就能解决这个问题。