在 x86 程序集中打印十六进制值

Posted

技术标签:

【中文标题】在 x86 程序集中打印十六进制值【英文标题】:Printing hex values in x86 assembly 【发布时间】: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

【问题讨论】:

您有问题吗? Printing Hexadecimal Digits with Assembly的可能重复 How to convert a binary integer number to a hex string? - 简单且高效的 32 位循环转换整个 32 位数字,以及非常高效的 SIMD 版本。 【参考方案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?

【讨论】:

以上是关于在 x86 程序集中打印十六进制值的主要内容,如果未能解决你的问题,请参考以下文章

拼命尝试使用 wprintf 在 64 位 NASM x86 程序集中打印 unicode

为啥`add cl, 2`以x86 hex打印`80 c1 02`?

x86汇编编程中如何表示FFFFFFBB等十六进制值?

x86汇编编程中如何表示FFFFFFBB等十六进制值?

如何在 x86 程序集中按值传递结构

如何在打印十六进制值时让Python使用大写字母?