我正在尝试编写汇编代码,通过将字符串传递给堆栈来反转字符串,然后使用循环将其弹回。
我得到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
答案 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