在Turbo Debugger中单步执行时,LOOP只执行一次

时间:2018-06-06 22:59:53

标签: debugging assembly x86-16

代码必须输出' ccb'但仅输出' c',LOOP只进行一次,我已在TD中校准,但为什么{{1只做过一次?

我认为我必须减少STRING_LENGTH,所以我WROTE

LOOP

但是它不起作用,所以我很喜欢

DEC STRING_LENGTH

我知道你现在正在思考什么,这是不正确的,你是对的)))

我可以使用C ++,但我只想在大会上这样做,

MOV SP,STRING_LENGTH
DEC SP
MOV STRING_LENGTH,SP

1 个答案:

答案 0 :(得分:5)

在Turbo Debugger(TD.EXE)中, F8 “F8步骤”将完全执行loop,直到cx变为零(甚至可以创建无限循环)通过将cx更新回某个值,防止其达到1 - > 0步骤。

要从loop指令中“单步”,请使用 F7 “F7 trace” - 这将导致cx从6变为5 ,并且代码指针将跟随循环开始时的跳转。

关于代码的其他一些问题:

MOV SP,STRING_LENGTH
DEC SP
MOV STRING_LENGTH,SP

sp不是通用寄存器,不要像这样用于计算。只要某个指令隐式使用堆栈(push, pop, call, ret, ...),就会在ss:sp寄存器对寻址的存储区中写入和读取值,因此通过操作正在修改的sp值目前的“堆积”。

同样在16位x86实模式下,所有中断(键盘,定时器......)发生时,标志寄存器和代码地址的当前状态存储到堆栈中,然后将控制权交给中断处理程序代码通常会将其他值推送到堆栈中,因此在16位x86实模式下,当前ss:sp以下地址的内存中的任何内容都是不安全的,并且内存内容会随着所有中断而“随机”地改变同时执行(TD.EXE本身在每一步后都使用了这个堆栈内存的一部分)。

算术使用其他寄存器,而不是sp。一旦你对“堆栈”了解得足够多,你就会明白什么样的sp操作是常见的以及为什么(比如sub sp,40在函数开头需要额外的“本地”内存空间),以及如何将堆栈恢复到预期状态。

还有一件事:

MOV SP,STRING_LENGTH
DEC SP
MOV STRING_LENGTH,SP

STRING_LENGTHEQU定义,这使得它编译时间常数,并且只编译时间。它不是“变量”(内存分配),与someLabel dw 1345之类的东西相反,它导致汇编器发出值为0100_0001B, 0000_0101B的两个字节(当以小端方式读取为16位字时,这是值为1345编码),第一个字节地址具有符号名someLabel,可以在进一步的指令中使用,如dec word ptr [someLabel]在运行时将内存中的值从1345递减到1344。

EQU不同,它会将符号STRING_LENGTH指定为最终值,例如14。

所以你的代码可以读作:

mov sp,14   ; makes almost sense, (practically destroys stack setup)
dec sp      ; still valid
mov 14,sp   ; doesn't make any sense, constant can't be destination for MOV