在程序集中使用堆栈反转字符串,程序冻结
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
我正在尝试编写汇编代码以通过将字符串传递到堆栈来反转字符串,然后使用循环将其弹出。
我得到 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