【问题标题】:Printing hex values in x86 assembly在 x86 程序集中打印十六进制值
【发布时间】:2013-09-23 15:38:55
【问题描述】:

我需要创建一个将内存地址转换为字节串的例程。然后该字符串将成为打印以空字符结尾的字符串(我已经能够制作)的函数的输入。例如,如果我有一个地址 0x1bf9,我需要将文本“1bf9”打印到屏幕上。这本书还没有进入 32 位模式,但它暗示我们也需要它。这是我到目前为止所拥有的:

TABLE:
db "0123456789ABCDEF", 0

STRING:
db 0

hex_to_char:
    lea bx, TABLE
    mov ax, dx

    mov ah, al ;make al and ah equal so we can isolate each half of the byte
    shr ah, 4 ;ah now has the high nibble
    and al, 0x0F ;al now has the low nibble
    xlat ;lookup al's contents in our table
    xchg ah, al ;flip around the bytes so now we can get the higher nibble 
    xlat ;look up what we just flipped
    inc STRING
    mov [STRING], ah ;append the new character to a string of bytes
    inc STRING
    mov [STRING], al ;append the new character to the string of bytes

    ret

【问题讨论】:

标签: assembly printing x86 hex


【解决方案1】:

如果您将字节拆分替换为未记录的“AAM 10h”(D4 10),则可以进一步优化此大小。

【讨论】:

  • aam 0x10 已记录在案。 Intel's manual entry for it 文档格式的立即数不是 0x0a(十进制),但错误地表示汇编程序无法识别它。事实上,NASM 将组装aam 10h 就好了。但是与将一个字节分成两个半字节的 shift / AND 相比,它非常慢;它和div 一样慢。 AAM 会以牺牲大量速度为代价优化代码大小。 (虽然使用 xchgxlat 已经在优化大小,但在实际的旧 CPU 上速度很快。)
【解决方案2】:

这试图增加一个文字标签,这是不正确的。此外,您的 STRING 内存位置仅分配一个字节 (char) 而不是更大的数字来容纳您想要的字符串大小。

STRING:
    db 0

    inc STRING   ;THIS WON'T WORK
    mov [STRING], ah ;append the new character to a string of bytes
    inc STRING   ;THIS WON'T WORK
    mov [STRING], al ;append the new character to the string of bytes

中性评论:用于xlat 的字符表不需要以零结尾。

我还建议保存和恢复一些寄存器作为良好的 asm 编程实践。这样,调用函数就不必担心寄存器在“背后”被更改。最终,你可能想要这样的东西:

TABLE:
    db "0123456789ABCDEF", 0

hex_to_char:
    push bx

    mov   bx, TABLE
    mov   ax, dx

    mov   ah, al            ;make al and ah equal so we can isolate each half of the byte
    shr   ah, 4             ;ah now has the high nibble
    and   al, 0x0F          ;al now has the low nibble
    xlat                    ;lookup al's contents in our table
    xchg  ah, al            ;flip around the bytes so now we can get the higher nibble 
    xlat                    ;look up what we just flipped

    mov   bx, STRING
    xchg  ah, al
    mov   [bx], ax          ;append the new character to the string of bytes

    pop bx
    ret

    section .bss

STRING:
    resb  50                ; reserve 50 bytes for the string

编辑:根据 Peter Cordes 的意见进行一些理想的调整。

【讨论】:

  • 甚至mov [bx], ah; mov [bx+1], al
  • @mbratch 我尝试使用您的解决方案,但没有将 STRING 的有效地址加载到 bx 中,而是将其加载到 cx 中。在我将每个字节插入 [cx] 和 [cx + 1] 的行上,这给了我一个错误。 nasm 说它们是无效的有效地址。
  • @mbratch 好的。那么为什么我不能使用lea 呢?不就是为了这个吗?
  • 如果您要使用xlat 优化代码大小,请使用mov bx, OFFSET TABLE 节省另一个字节。 (或者如果这是 NASM,则没有偏移量)。如果您要针对 xchg + 一个字存储而不是两个字节存储进行优化,mov [STRING], ax 将保存一条指令而不是将地址放入 BX 中
  • 另外,让 AX 被呼叫破坏通常是可以的;让函数将其用作临时注册。不过,保留 BX 是有道理的。
【解决方案3】:

请查看我在此页面上的答案,以便将 EAX 中的 32 位值转换为 8 个十六进制 ASCII 字节:Printing out a number in assembly language?

【讨论】:

    猜你喜欢
    • 2016-01-11
    • 2019-01-27
    • 2017-06-22
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    相关资源
    最近更新 更多