根据我的理解,NASM(就像所有优秀的汇编程序一样)允许您通过在其前面添加句点来定义本地标签,并允许以后的定义覆盖以前的标签。
我见过的代码证明了这一点:
part1 mov ax, 10
.loop ; do something
dec ax
jnz .loop
part2 mov ax, 50
.loop ; do something
dec ax
jnz .loop
在这种情况下,后面的定义会覆盖前一个定义,以便选择正确的标签。
但是,我无法在以下场景中看到它是如何工作的。
part1 mov ax, 10
.loop jz .fin
; do something else
dec ax
jmp .loop
.fin
part2 mov ax, 50
.loop jz .fin
; do something else
dec ax
jmp .loop
.fin
在组装第二个循环中的jz .fin
时,.fin
的早期实例肯定仍处于活动状态,并且会跳转到错误的位置。< / p>
或NASM是否比那更聪明,并使用其他方法来决定在任何给定时间哪个标签处于活动状态?
答案 0 :(得分:2)
实际上,这种理解并非完全正确。本地标签不是独立的标签,它们实际上与最新的非本地标签相关联。
所以第二个代码示例实际上变成了:
part1 mov ax, 10
part1.loop jz part1.fin
; do something else
dec ax
jmp part1.loop
part1.fin
part2 mov ax, 50
part2.loop jz part2.fin
; do something else
dec ax
jmp part2.loop
part2.fin
然后问题就消失了。
实际上,您实际上可以将作为非本地标签引用到本地标签。换句话说,如果你想离开part1
并完全跳过part2
,你可以使用类似的东西:
jmp part2.fin
来自part1
内的某个地方。使用.fin
中的part1
无效,因为这会选择part1.fin
,但完全限定的part2.fin
可以解决问题。
答案 1 :(得分:0)
根据YASM's docs on NASM local labels,本地标签与全局标签相关联。因此,如果没有将.fin
的两个实例分隔开的全局标签,我认为您的示例实际上会发生冲突。
答案 2 :(得分:0)
在组装第二个循环中的
jz .fin
时,.fin
的早期实例肯定仍处于活动状态,并且会跳转到错误的位置。或NASM是否比那更聪明,并使用其他方法来决定在任何给定时间哪个标签处于活动状态?
让我们找出来!
C:\nasm>nasm -f bin -o locals.com locals.asm && ndisasm locals.com
00000000 B80A00 mov ax,0xa ; part1: mov ax, 10
00000003 7403 jz 0x8 ; .loop: jz .fin
00000005 48 dec ax ; dec ax
00000006 EBFB jmp short 0x3 ; jmp .loop
00000008 B83200 mov ax,0x32 ; .fin: part2: mov ax, 50
0000000B 7403 jz 0x10 ; .loop: jz .fin
0000000D 48 dec ax ; dec ax
0000000E EBFB jmp short 0xb ; jmp .loop
; .fin:
因此,第一个jz .fin
跳转到第一个.fin
实例,第二个jz .fin
跳转到第二个.fin
实例。