如何在Assembly中更新字符串的字符?

pra*_*dhe 0 assembly fasm x86-16

我已经完成了我的研究,并偶然发现了许多解决方案来更改字符串的某些字符。我正在尝试以字符串形式打印十六进制代码。但我已经尝试了所有的解决方案,但它不会在“平面汇编器”上编译。以下是我的代码:

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
Run Code Online (Sandbox Code Playgroud)

在编译时它只显示无效的表达式错误。

fcd*_*cdt 5

flatassembler 板

  1. FASM 抱怨“用作符号的保留词”

MOV AX、[CX] 或 JMP WORD [AX] 等指令会导致此错误 - FASM 错误?

你的BUG。只有 BX、BP、SI 和 DI 可用于 16 位代码的索引。FASM的报告不好,但源于内部设计。这是8086设计和16位代码的“问题”。使用更多的寄存器(如 EAX 等)进行寻址是 80386 和更高版本 CPU 上 32 位代码的特权。

并非每个寄存器 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]
Run Code Online (Sandbox Code Playgroud)

代替或使用允许的寄存器之一:

mov di, HEXi
mov al, [di]
Run Code Online (Sandbox Code Playgroud)

此处不必使用 指定寄存器大小byte,因为它已由目标寄存器明确指定。


如何操作 HEXi 字符串的字符?

假设要输出的值是 indx并且应该写为字符串中的十六进制数HEXi。和

  mov [bx+HEXi], al
Run Code Online (Sandbox Code Playgroud)

寄存器中的一个字符al可以写到 的bx第 -th 个位置HEXi,从零开始。由于字符串已经开始0x并且不应被覆盖,因此使用跳过前两个字符

  mov [bx+HEXi+2], al
Run Code Online (Sandbox Code Playgroud)

该值HEXi+2被编码为上面提到的立即数。现在应该将 4 位每个都转换为十六进制数字,即字符

  • 09(字符代码0x300x39)和
  • AF(字符代码0x41到 0x46`)。这是通过以下步骤完成的:

第一的低4位dx被分离并转换成字符代码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
Run Code Online (Sandbox Code Playgroud)

字符代码0x3Ato0x3F必须转移到0x41to 0x46。为此,首先检查值是否在其中,以便在必要时进行移位:

    cmp  al, 0x39
    jbe  noShiftNeeded
    add  al, 7
noShiftNeeded:
Run Code Online (Sandbox Code Playgroud)

这应该发生的所有在16位值的4位半字节dx。在每一步之后,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
Run Code Online (Sandbox Code Playgroud)