在程序集中使用堆栈反转字符串,程序冻结

reversing string using stack in assembly, program freezes

我正在尝试编写汇编代码以通过将字符串传递到堆栈来反转字符串,然后使用循环将其弹出。

我得到 dlrow oll 然后程序冻结。我不知道为什么。我该如何解决这个问题?

%include "io.mac"
.STACK 100H 
.DATA

    string     db 'Hello world'
    stringLen  equ $-string

   .CODE
        .STARTUP



mov ecx, stringLen
mov edx, ecx ;save string length
mov eax, string
mov esi, eax  ; esi points to start of string
add eax, ecx
mov edi, eax
dec edi       ; edi points to end of string
jz done       ; if string is 0 or 1 characters long, done
reverseLoop:
mov  al, [esi] ; load characters
mov ah,0
push ax
inc esi       ; adjusdt pointers
dec edi
dec ecx       ; and loop
jnz reverseLoop


done:
call reverseString
.EXIT

call reverseString

reverseString:
enter 0,0 ;save EBP

mov cx, dx


Lp1:
pop ax
mov ah,0
PutCh al
loop Lp1

  leave
  ret 8

真正的问题是你把弹出放在了一个子程序中!这样 return 地址就会妨碍正确弹出字符。
这是一个不使用子例程的解决方案,但仍然遵守要求:

    jcxz    Ready
    mov     dx, cx    ; Copy for latter
PushLoop:
    mov     al, [si]  ; load characters
    push    ax        ; Don't care about AH
    inc     si        ; adjust pointers
    dec     cx
    jnz     PushLoop
PopLoop:
    pop     ax
    PutCh   al        ; PutCh does not depend on AH
    dec     dx
    jnz     PopLoop
Ready:
    .EXIT

不需要使用 32 位寄存器(或者选择 16 位或 32 位,但不要两者混合)。此外,您根本不使用 EDI 寄存器。为什么要设置呢?


另一种方法是将所有反转字符串的代码放在一个单独的过程中,并让它调用传递堆栈上的地址和字符串长度。

    push    word stringLen
    push    word string
    call    ReverseString
    .EXIT

ReverseString:
    push    bp
    mov     bp, sp
    ... push any registers you need to preserve
    mov     cx, [bp+6]  ;2nd parameter is length
    jcxz    Ready
    mov     si, [bp+4]  ;1st parameter is address
  PushLoop:
    mov     al, [si]    ; load characters
    push    ax          ; Don't care about AH
    inc     si          ; adjust pointers
    dec     cx
    jnz     PushLoop
    mov     cx, [bp+6]  ;2nd parameter is length
  PopLoop:
    pop     ax
    PutCh   al          ; PutCh does not depend on AH
    dec     cx
    jnz     PopLoop
  Ready:
    ... pop any registers that you preserved
    pop     bp
    ret     4         ; Returns AND removes both parameters from the stack