在字符串中的 2 个字符之间进行装配切换
assembly switch between 2 chars in string
我想在字符串中的 2 个字符之间翻转,所以我 buily
获取指向 2 个字符的指针然后切换它们的函数。该函数可以很好地处理常规的 assmbly 字符,但是当我从字符串中将参数作为 char 传递时,它开始变得疯狂并从其他地方翻转字符。
例如,我得到这个字符串:
string db 'd', 'a', 'b', 'e', 'c', 0Dh, 0Ah, '$'
我想在 'd' 和 'e' 之间切换。
所以我这样做是为了将它们移动到函数中:
lea bx, string
lea ax, [bx] ;i use lea to get the pointer not the char
push ax
lea ax, [bx + 3]
push ax
; i know push 2 parameters.
但由于某些原因,在切换后字符串更改为:
string db 'e', 'c', 'b', 'd', 'a', 0Dh, 0Ah, '$'
所以它成功地在 2 个字符之间交换,但由于某种原因,该函数对后面的字符执行相同的操作:
[bx + 1]
和 [bx + 4]
。
这是为什么?到目前为止,这是我的代码:(print = 打印新行,print_ax_str 这是在 ax 中打印 ptr 字符串的函数。来自 inc 文件的所有内容)
org 100h
jmp main
string db 'd', 'a', 'b', 'e', 'c', 0Dh, 0Ah, '$'
length dw 3
main:
xor ax, ax
xor bx, bx
xor dx, dx
xor cx, cx
xor si, si
xor bp, bp
lea bx, string
mov ax, bx
print "Before string: "
call print_ax_str
lea ax, [bx]
push ax
lea ax, [bx + 3]
push ax
call swap ;swap the chars.
lea ax, string
print "After string: "
call print_ax_str
jmp end
swap:
push cx
push bx
push dx
push ax
push bp
mov bp, sp
mov ax, [bp + 12]; ax = ptr char 2
mov cx, [bp + 14]; cx = ptr char 1
mov bx, ax
mov ax, [bx] ;ax = char 2
mov bx, cx
mov dx, [bx] ;dx = char 1
mov [bx], ax ;char 1 = char 2
mov bx, [bp + 12]
mov [bx], dx ;char 2 = char 1
mov ax, [bx]
mov sp, bp
pop bp
pop ax
pop dx
pop bx
pop cx
retn 4
end:
mov ah, 0
int 16h
ret
include prints.inc
mov ax, [bx] ;ax = char 2
mov dx, [bx] ;dx = char 1
mov [bx], ax ;char 1 = char 2
mov [bx], dx ;char 2 = char 1
您正在处理的字符串由字节组成,但您的程序交换了字。这就是结果不理想的原因。
作为快速修复写:
mov al, [bx] ;AL = char 2
mov dl, [bx] ;DL = char 1
mov [bx], al ;char 1 = char 2
mov [bx], dl ;char 2 = char 1
如果您有兴趣编写更好的程序,请重新编写 SWAP 程序。
- 设置
BP
在压入附加寄存器之前,以便寻址参数可以使用熟悉的偏移量,例如第一个参数的[bp+4]
和[bp+6]
第二个参数。
- 将参数直接移动到地址寄存器(
BX
、SI
、DI
),这样可以避免大量移动。
新版本:
swap:
push bp
mov bp, sp
push ax
push dx
push si
push di
mov di, [bp + 4] ; ptr char 2
mov si, [bp + 6] ; ptr char 1
mov dl, [di] ; DL = char 2
mov al, [si] ; AL = char 1
mov [si], dl ; char 1 = char 2
mov [di], al ; char 2 = char 1
pop di
pop si
pop dx
pop ax
pop bp
retn 4
mov ax, [bx]
mov sp, bp
pop bp
pop ax
关于这部分代码的几点说明:
- 你能看出
mov ax,[bx]
指令后跟 pop ax
指令没有用吗?
- 您不必编写
mov sp, bp
指令,因为堆栈指针仍指向压入的寄存器。
我想在字符串中的 2 个字符之间翻转,所以我 buily 获取指向 2 个字符的指针然后切换它们的函数。该函数可以很好地处理常规的 assmbly 字符,但是当我从字符串中将参数作为 char 传递时,它开始变得疯狂并从其他地方翻转字符。 例如,我得到这个字符串:
string db 'd', 'a', 'b', 'e', 'c', 0Dh, 0Ah, '$'
我想在 'd' 和 'e' 之间切换。 所以我这样做是为了将它们移动到函数中:
lea bx, string
lea ax, [bx] ;i use lea to get the pointer not the char
push ax
lea ax, [bx + 3]
push ax
; i know push 2 parameters.
但由于某些原因,在切换后字符串更改为:
string db 'e', 'c', 'b', 'd', 'a', 0Dh, 0Ah, '$'
所以它成功地在 2 个字符之间交换,但由于某种原因,该函数对后面的字符执行相同的操作:
[bx + 1]
和 [bx + 4]
。
这是为什么?到目前为止,这是我的代码:(print = 打印新行,print_ax_str 这是在 ax 中打印 ptr 字符串的函数。来自 inc 文件的所有内容)
org 100h
jmp main
string db 'd', 'a', 'b', 'e', 'c', 0Dh, 0Ah, '$'
length dw 3
main:
xor ax, ax
xor bx, bx
xor dx, dx
xor cx, cx
xor si, si
xor bp, bp
lea bx, string
mov ax, bx
print "Before string: "
call print_ax_str
lea ax, [bx]
push ax
lea ax, [bx + 3]
push ax
call swap ;swap the chars.
lea ax, string
print "After string: "
call print_ax_str
jmp end
swap:
push cx
push bx
push dx
push ax
push bp
mov bp, sp
mov ax, [bp + 12]; ax = ptr char 2
mov cx, [bp + 14]; cx = ptr char 1
mov bx, ax
mov ax, [bx] ;ax = char 2
mov bx, cx
mov dx, [bx] ;dx = char 1
mov [bx], ax ;char 1 = char 2
mov bx, [bp + 12]
mov [bx], dx ;char 2 = char 1
mov ax, [bx]
mov sp, bp
pop bp
pop ax
pop dx
pop bx
pop cx
retn 4
end:
mov ah, 0
int 16h
ret
include prints.inc
mov ax, [bx] ;ax = char 2 mov dx, [bx] ;dx = char 1 mov [bx], ax ;char 1 = char 2 mov [bx], dx ;char 2 = char 1
您正在处理的字符串由字节组成,但您的程序交换了字。这就是结果不理想的原因。
作为快速修复写:
mov al, [bx] ;AL = char 2
mov dl, [bx] ;DL = char 1
mov [bx], al ;char 1 = char 2
mov [bx], dl ;char 2 = char 1
如果您有兴趣编写更好的程序,请重新编写 SWAP 程序。
- 设置
BP
在压入附加寄存器之前,以便寻址参数可以使用熟悉的偏移量,例如第一个参数的[bp+4]
和[bp+6]
第二个参数。 - 将参数直接移动到地址寄存器(
BX
、SI
、DI
),这样可以避免大量移动。
新版本:
swap:
push bp
mov bp, sp
push ax
push dx
push si
push di
mov di, [bp + 4] ; ptr char 2
mov si, [bp + 6] ; ptr char 1
mov dl, [di] ; DL = char 2
mov al, [si] ; AL = char 1
mov [si], dl ; char 1 = char 2
mov [di], al ; char 2 = char 1
pop di
pop si
pop dx
pop ax
pop bp
retn 4
mov ax, [bx] mov sp, bp pop bp pop ax
关于这部分代码的几点说明:
- 你能看出
mov ax,[bx]
指令后跟pop ax
指令没有用吗? - 您不必编写
mov sp, bp
指令,因为堆栈指针仍指向压入的寄存器。