在 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 会以牺牲大量速度为代价优化代码大小。 (虽然使用 xchg
和 xlat
已经在优化大小,但在实际的旧 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