NASM 本地标签差异化

NASM local label differentiation

据我了解,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 较早的 实例肯定仍然处于活动状态并且它会跳转到错误的位置。

或者 NASM 是否比这更聪明并使用其他方法来决定在任何给定时间哪个标签处于活动状态?

根据YASM's docs on NASM local labels,局部标签与全局标签相关联。所以我认为如果没有全局标签分隔 .fin.

的两个实例,你的示例实际上会发生冲突

实际上,这种理解并不完全正确。本地标签不是独立的项目,它们实际上与最近的非本地标签相关联。

NASM manual section 3.9 Local Labels

所以第二个代码示例实际上变成了:

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 内的某处。在 part1 中使用 .fin 是行不通的,因为那样会 select part1.fin,但是完全限定的 part2.fin 就可以了。

At the point where jz .fin in the second loop is assembled, surely the earlier instance of .fin would still be active and it would jump to the wrong location.

Or is NASM smarter than that and uses some other method to decide which label is active at any given time?

让我们一探究竟!

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的第二个实例。