函数运行多次,但只调用一次

时间:2015-06-23 18:03:34

标签: assembly nasm

我正在编写一个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中执行的。

2 个答案:

答案 0 :(得分:2)

english_to_morse开头,你有一个pusha,但popa之前没有相应的ret

答案 1 :(得分:2)

我发现您的代码有两个问题。

  • 正如Michael所指出的,pushapopa
  • 不匹配
  • 过早推送SI寄存器。

    1. jl .nextjg .next都会继续推送一个永远不会弹出的额外SI寄存器!
    2. 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],这种习惯会给您带来麻烦。更好地使用jbja