代码必须输出' ccb'但仅输出' c',LOOP
只进行一次,我已在TD中校准,但为什么{{1只做过一次?
我认为我必须减少STRING_LENGTH,所以我WROTE
LOOP
但是它不起作用,所以我很喜欢
DEC STRING_LENGTH
我知道你现在正在思考什么,这是不正确的,你是对的)))
我可以使用C ++,但我只想在大会上这样做,
MOV SP,STRING_LENGTH
DEC SP
MOV STRING_LENGTH,SP
答案 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_LENGTH
由EQU
定义,这使得它编译时间常数,并且只编译时间。它不是“变量”(内存分配),与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