我正在编写一个16位实模式汇编应用程序。
以下是代码的顶部:
org 100h
jmp start
%include "memory.asm"
str: db "aBc", 0
outstr: times 100 db 0
start:
mov si, str
mov di, outstr
call english_to_morse
jmp $
如您所见,我只拨打english_to_morse
一次。
以下是english_to_morse
功能:
english_to_morse:
pusha
call str_to_lower
pusha; BREAKPOINT
mov ah, 0Eh
mov al, 'a'
int 10h
popa
.next:
lodsb
push si; get_morse_from_alpha will trash SI
cmp al, 0
je .end
cmp al, 'a'
jl .next
cmp al, 'z'
jg .next
call get_morse_from_alpha
call print_morse_letter
pop si
jmp .next
.end:
ret
正如您在此处所看到的,此处唯一的循环是在.next
标签上;不是整个子程序。
然而,当我运行它时,这是输出:
a._ _..._._.
大约一百次(基本上,这只是一遍又一遍地打印,直到突然停止)。
我的目标是这个功能只能运行一次。
这是与NASM汇编程序组装在DOSBOX中执行的。
答案 0 :(得分:2)
在english_to_morse
开头,你有一个pusha
,但popa
之前没有相应的ret
。
答案 1 :(得分:2)
我发现您的代码有两个问题。
pusha
与popa
过早推送SI寄存器。
jl .next
和jg .next
都会继续推送一个永远不会弹出的额外SI寄存器! je .end
忘记弹出SI寄存器。 因为您知道 get_morse_from_alpha会丢弃SI ,只需将push si
直接放在它的呼叫之上。
.next:
lodsb
cmp al, 0
je .end
cmp al, 'a'
jl .next
cmp al, 'z'
jg .next
push si; get_morse_from_alpha will trash SI
call get_morse_from_alpha
call print_morse_letter
pop si
jmp .next
.end:
popa
ret
我不禁注意到您使用了签名比较。在这个小代码片段中没有造成任何伤害,但如果您想要考虑完整的ASCII范围[0,255],这种习惯会给您带来麻烦。更好地使用jb
和ja
。