Assembly nasm组件:Can';1004次通过后,找不到所有标签的有效值

Assembly nasm组件:Can';1004次通过后,找不到所有标签的有效值,assembly,nasm,Assembly,Nasm,我正在尝试为NASM汇编程序编写一个x86汇编代码,它将十六进制数转换成字符串并打印出来。为了简单起见,我假设我的十六进制数只包含数字(例如0x1234)。代码如下: 打印十六进制asm [组织0x7c00] mov-dx,0x1234 调用print_hex jmp$ 打印十六进制: 推bx 推送cx 推送dx 推斧 mov bx,六角头 mov-cx,0x000f mov-ax,0x0000;长度计数器 循环: 推bx;保存bx 和cx,dx,;0xabcd&0x000f 添加bx,5;在

我正在尝试为NASM汇编程序编写一个x86汇编代码,它将十六进制数转换成字符串并打印出来。为了简单起见,我假设我的十六进制数只包含数字(例如0x1234)。代码如下:

打印十六进制asm


[组织0x7c00]
mov-dx,0x1234
调用print_hex
jmp$
打印十六进制:
推bx
推送cx
推送dx
推斧
mov bx,六角头
mov-cx,0x000f
mov-ax,0x0000;长度计数器
循环:
推bx;保存bx
和cx,dx,;0xabcd&0x000f
添加bx,5;在模板中查找位置
副bx,ax
添加[bx],cl
波普bx
shr-dx,4;下一位数
mov-cx,0x000f
公司ax;增量计数器
cmp ax,4
jl环;通过数字循环
爆斧
调用打印字符串
波普dx
流行音乐
波普bx
ret
%包括“print_string.asm”
六角街:;模板字符串
数据库“0x0000”,0
乘以510-($-$$)db 0
dw 0xaa55
打印字符串.asm


打印字符串:
mov-ah,0x0e
推bx
循环:
cmp字节[bx],0
je端
mov al,[bx]
int 0x10
公司bx
jmp循环
完:
波普bx
ret
如果我试图用NASM汇编/编译
print_hex.asm
,它会给出以下错误:

print_hex.asm:错误:1004次通过后,无法找到所有标签的有效值,放弃

print_hex.asm:错误:可能原因:递归等式、宏滥用


我注意到,如果不使用任何标签(如此处的循环标签),代码工作正常。

您的实际问题是您定义了标签
循环:
两次。

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,如果它与
循环
也是指令助记符这一事实有关。不应该这样,但很难想象NASM在任何最新版本中对重复标签的处理都是如此无益。这是手写asm中很常见的错误,这也是NASM通常使用的方式。因此,也许NASM有一个bug潜入
循环
通过了通常的重复检测,并使其尝试失败

循环:
消除了行作为标签的歧义,而不是NASM的指令行。(但不是YASM:它不允许您使用
循环:
作为标签)


使用本地标签名称
.loop:
的作用域为以前的非本地标签。因此,在声明和使用中,它就像是
print_hex.loop
print_string.loop
的缩写


代码审查 顺便说一句,你的代码相当臃肿。您不需要保存/恢复每个函数中的每个寄存器;就让他们去打雷格吧

此外,您可以更高效地转换int->hex,而无需添加模板。(初始的
0x
很方便,但其余的可以用regs计算)。此外,我认为您的代码无法处理
0..9
a..f
分割:不幸的是,这些ASCII字符代码的范围彼此不相邻

有关简单的32位版本,请参阅,您可以使用查找表或条件轻松地将端口连接到16位,以处理0..9与a..f。有关带有条件分支的简单版本,请参见。(更高版本使用DAS可以节省更多的代码大小)


使用小常量作为立即数操作数,如
和al,0xf
,而不是将它们放入CX。如果需要,可以从缓冲区的末尾减量指针,或者使用十六进制,您可以使用旋转从顶部获取半字节并按打印顺序生成。

循环是一个非常糟糕的标签名称,因为它也是指令的名称。但是你可以试着将这些标签改为本地标签(即
.loop:
)哦!我不知道有一个指令
循环
!更改标签的名称有效。谢谢嗯,我想在行上加个冒号可以消除它和指令之间的歧义。所以
循环:
无疑是一个标签。您是否将其更改为
.loop
(一个本地标签,即
.print\u hex.loop:
)或保留了同一非本地标签的两个定义,如
myloop:
myloop:
?(
%include
的工作原理与C中的一样:源实际上成为同一文件的一部分。)