首页 > 解决方案 > 如何在程序集中更新字符串的字符?

问题描述

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

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

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

标签: assemblyx86-16fasm

解决方案


平面组装板

  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]

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

mov di, HEXi
mov al, [di]

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


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

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

  mov [bx+HEXi], al

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

  mov [bx+HEXi+2], al

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

  • 0to 9(字符代码0x30to 0x39)和
  • 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

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

    cmp  al, 0x39
    jbe  noShiftNeeded
    add  al, 7
noShiftNeeded:

这应该发生在所有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

推荐阅读