NASM本地标签差异化

时间:2015-07-30 03:59:14

标签: nasm

根据我的理解,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是否比那更聪明,并使用其他方法来决定在任何给定时间哪个标签处于活动状态?

3 个答案:

答案 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实例。