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

时间:2017-11-12 14:59:42

标签: assembly x86 nasm

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

我得到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

1 个答案:

答案 0 :(得分:1)

真正的问题是你把弹出放在一个子程序中!这样,返回地址阻碍了角色的正确弹出。
这是一个不使用子程序但仍遵循要求的解决方案:

    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