我正在尝试为NASM汇编器编写x86汇编代码,该代码会将十六进制数转换为字符串并打印出来。为简单起见,我假设我的十六进制数字将仅包含数字(例如0x1234)。这是代码:
print_hex.asm
[org 0x7c00]
mov dx, 0x1234
call print_hex
jmp $
print_hex:
push bx
push cx
push dx
push ax
mov bx, HEX_STR
mov cx, 0x000f
mov ax, 0x0000 ; length counter
loop:
push bx ; save bx
and cx, dx ; 0xabcd & 0x000f
add bx, 5 ; find position in the template
sub bx, ax
add [bx], cl
pop bx
shr dx, 4 ; next digit
mov cx, 0x000f
inc ax ; increment counter
cmp ax, 4
jl loop ; loop through the digits
pop ax
call print_string
pop dx
pop cx
pop bx
ret
%include "print_string.asm"
HEX_STR: ; template string
db '0x0000', 0
times 510-($-$$) db 0
dw 0xaa55
print_string.asm
print_string:
mov ah, 0x0e
push bx
loop:
cmp BYTE [bx], 0
je end
mov al, [bx]
int 0x10
inc bx
jmp loop
end:
pop bx
ret
如果我尝试print_hex.asm
使用NASM进行汇编/编译,则会出现以下错误:
print_hex.asm:error:1004通过后,找不到所有标签的有效值,放弃了。
print_hex.asm:错误:可能的原因:递归EQU,宏滥用。
我已经注意到,如果我不使用任何标签(例如此处的循环标签)的代码就可以正常工作。
您的实际问题是您loop:
两次定义了标签。
NASM 2.14.02打印出一个不错的错误消息:
$ nasm print_hex.asm
print_string.asm:5: error: label `loop' inconsistently redefined
print_hex.asm:19: note: label `loop' originally defined here
该%include
预处理指令的工作类似于C #include
:来源有效地成为同一个文件中的一部分,共享相同的命名空间的符号。
大概您有一个旧版本的NASM,它打印了疯狂而无助的错误消息。IDK(如果它与loop
也是指令助记符的事实有关)。事实并非如此,但很难想象NASM会对这样的最新版本中的重复标签造成无益的处理。在手写asm中,这是一个足够常见的错误,而NASM通常会使用这种错误。因此,也许NASM的一个漏洞会漏掉loop
通常的重复检测,并使其尝试失败。
loop:
明确将这条线消除为标签,而不是NASM的指令线。(但不是YASM:它不会让您loop:
用作标签)
.loop:
范围仅限于先前的非本地标签。因此,它像速记print_hex.loop
和print_string.loop
在声明和使用二者。
https://www.nasm.us/doc/nasmdoc3.html#section-3.9
顺便说一句,您的代码非常肿。您无需在每个函数中保存/恢复每个寄存器;只是让他们玩弄Regs。
另外,您可以更有效地转换int-> hex,而无需添加模板。(首字母0x
很方便,但是其余的您可以使用regs计算)。另外,我认为您的代码无法处理0..9
vs.a..f
拆分:不幸的是,这些ASCII字符代码范围彼此不相邻。
请参阅如何将数字转换为十六进制?对于简单的32位版本,您可以轻松地将其移植到16位,带有查找表或有条件处理0..9与a..f的条件。另请参阅https://codegolf.stackexchange.com/revisions/193842/1,了解带有条件分支的简单版本。(更高版本使用DAS节省了更多的代码大小)。
使用小常数作为即时操作数,例如and al, 0xf
,而不是将其放入CX。如果需要,可以从缓冲区的末尾减小指针,或者使用十六进制,可以使用旋转从顶部获取半字节并按打印顺序生成。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句