如何在 Assembly 中更新字符串的字符?
How to update character of string in Assembly?
我进行了研究,偶然发现了许多更改字符串中某些字符的解决方案。我正在尝试以字符串形式打印十六进制代码。但我已经尝试了所有的解决方案,但它不会在“Flat assembler”上编译。以下是我的代码:
mov bx, HELLO
call print_string
mov dx, 0x1fb6
call print_hex
jmp $
print_hex:
pusha
mov cx, HEXi
mov al, byte ptr [cx]
back:
popa
ret
include "print_string.asm"
HELLO: db 'Hello, World!',0
HEXi: db '0x0000',0
times 510 -( $ - $$ ) db 0
dw 0xaa55
在编译时它只是显示无效表达式错误。
- FASM whines with "reserved word used as symbol"
Instructions like MOV AX, [CX] or JMP WORD [AX] cause this error - FASM bug ?
Your BUG. Only BX, BP, SI and DI are available for indexing in 16-bit code. FASM's report is bad, but it originates from internal design. This is a "problem" of 8086 design and 16-bit code. Using more registers like EAX etc. for addressing is a privilege of 32-bit code on 80386 and later CPU's.
不是每个寄存器16位寄存器都可以作为地址寄存器,只允许以下组合:
- 仅位移:
[displacement]
- 仅基址寄存器:
[BX+displacement]
- 只有基指针:
[BP+displacement]
- 仅变址寄存器
[SI+displacement]
或[DI+displacement]
- 基址和变址寄存器:
[BX+SI+displacement]
或[BX+DI+displacement]
- 基址指针和变址寄存器:
[BP+SI+displacement]
或[BP+DI+displacement]
位移为0时可以省略,这里可以是变量名,例如。在这种情况下你可以写
mov al, [HEXi]
改为使用允许的寄存器之一:
mov di, HEXi
mov al, [di]
寄存器大小不必在这里用byte
指定,因为它由目标寄存器明确指定。
如何操作HEXi字符串的字符?
假设要输出的值在dx
中,应该写成字符串HEXi
中的十六进制数。有
mov [bx+HEXi], al
寄存器 al
中的一个字符可以从零开始写入 HEXi
的第 bx
位置。由于字符串已经以 0x
开头并且不应被覆盖,因此使用
跳过前两个字符
mov [bx+HEXi+2], al
值HEXi+2
被编码为上面提到的立即数。现在应该将 4 位分别转换为十六进制数字,即字符
0
到9
(字符代码0x30
到0x39
)和
A
到 F
(字符代码 0x41
到 0x46`)。
这是通过以下步骤完成的:
首先将dx
的低4位分离出来,转换成字符码0x30
到0x3F
和
mov al, dl ; Copy the lower 8 bits of dx to al
and al, 0x0F ; Set the upper 4 bits of al to zero
or al, 0x30 ; Convert to charcode
字符代码0x3A
到0x3F
必须转换为0x41
到0x46
。为此,首先检查值是否在其中,以便在必要时移动它:
cmp al, 0x39
jbe noShiftNeeded
add al, 7
noShiftNeeded:
dx
中 16 位值的所有 4 位半字节都应该发生这种情况。每一步后,dx
右移 4 位,以便再次使用之前的代码。那么最后的代码是:
print_hex:
pusha
mov bx, 3 ; Start with last character
hexLoop:
mov al, dl ; Copy the lower 8 bits of dx to al
and al, 0x0F ; Set the upper 4 bits of al to zero
or al, 0x30 ; Convert to charcode
cmp al, 0x39
jbe noShiftNeeded
add al, 7
noShiftNeeded:
mov [bx+HEXi+2], al ; Write the character to HEXi
shr dx, 4 ; To be able to repeat this with the next 4-bit nibble
sub bx, 1 ; If this wasn't the forth character, repeat
jnc hexLoop
popa
ret
我进行了研究,偶然发现了许多更改字符串中某些字符的解决方案。我正在尝试以字符串形式打印十六进制代码。但我已经尝试了所有的解决方案,但它不会在“Flat assembler”上编译。以下是我的代码:
mov bx, HELLO
call print_string
mov dx, 0x1fb6
call print_hex
jmp $
print_hex:
pusha
mov cx, HEXi
mov al, byte ptr [cx]
back:
popa
ret
include "print_string.asm"
HELLO: db 'Hello, World!',0
HEXi: db '0x0000',0
times 510 -( $ - $$ ) db 0
dw 0xaa55
在编译时它只是显示无效表达式错误。
- FASM whines with "reserved word used as symbol"
Instructions like MOV AX, [CX] or JMP WORD [AX] cause this error - FASM bug ?
Your BUG. Only BX, BP, SI and DI are available for indexing in 16-bit code. FASM's report is bad, but it originates from internal design. This is a "problem" of 8086 design and 16-bit code. Using more registers like EAX etc. for addressing is a privilege of 32-bit code on 80386 and later CPU's.
不是每个寄存器16位寄存器都可以作为地址寄存器,只允许以下组合:
- 仅位移:
[displacement]
- 仅基址寄存器:
[BX+displacement]
- 只有基指针:
[BP+displacement]
- 仅变址寄存器
[SI+displacement]
或[DI+displacement]
- 基址和变址寄存器:
[BX+SI+displacement]
或[BX+DI+displacement]
- 基址指针和变址寄存器:
[BP+SI+displacement]
或[BP+DI+displacement]
位移为0时可以省略,这里可以是变量名,例如。在这种情况下你可以写
mov al, [HEXi]
改为使用允许的寄存器之一:
mov di, HEXi
mov al, [di]
寄存器大小不必在这里用byte
指定,因为它由目标寄存器明确指定。
如何操作HEXi字符串的字符?
假设要输出的值在dx
中,应该写成字符串HEXi
中的十六进制数。有
mov [bx+HEXi], al
寄存器 al
中的一个字符可以从零开始写入 HEXi
的第 bx
位置。由于字符串已经以 0x
开头并且不应被覆盖,因此使用
mov [bx+HEXi+2], al
值HEXi+2
被编码为上面提到的立即数。现在应该将 4 位分别转换为十六进制数字,即字符
0
到9
(字符代码0x30
到0x39
)和A
到F
(字符代码0x41
到 0x46`)。 这是通过以下步骤完成的:
首先将dx
的低4位分离出来,转换成字符码0x30
到0x3F
和
mov al, dl ; Copy the lower 8 bits of dx to al
and al, 0x0F ; Set the upper 4 bits of al to zero
or al, 0x30 ; Convert to charcode
字符代码0x3A
到0x3F
必须转换为0x41
到0x46
。为此,首先检查值是否在其中,以便在必要时移动它:
cmp al, 0x39
jbe noShiftNeeded
add al, 7
noShiftNeeded:
dx
中 16 位值的所有 4 位半字节都应该发生这种情况。每一步后,dx
右移 4 位,以便再次使用之前的代码。那么最后的代码是:
print_hex:
pusha
mov bx, 3 ; Start with last character
hexLoop:
mov al, dl ; Copy the lower 8 bits of dx to al
and al, 0x0F ; Set the upper 4 bits of al to zero
or al, 0x30 ; Convert to charcode
cmp al, 0x39
jbe noShiftNeeded
add al, 7
noShiftNeeded:
mov [bx+HEXi+2], al ; Write the character to HEXi
shr dx, 4 ; To be able to repeat this with the next 4-bit nibble
sub bx, 1 ; If this wasn't the forth character, repeat
jnc hexLoop
popa
ret