7

From what I understand, NASM (like all good assemblers) allows you to define local labels by prefixing them with a period, and it allows later definitions to override previous ones.

The code I've seen demonstrating this looks like:

part1  mov   ax, 10
.loop  ; do something
       dec   ax
       jnz   .loop 

part2  mov   ax, 50
.loop  ; do something
       dec   ax
       jnz   .loop 

In this case, the later definition overrides the earlier one so that the correct label is selected.

However, I can't see how this works in the following scenario.

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

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?

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953

3 Answers3

7

Actually, the understanding of which label is selected isn't quite correct. The local labels are not actually stand-alone items, they associate themselves with the most recent non-local label, as per NASM manual section 3.9 Local Labels. So the second code example effectively becomes:

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

In other words, local labels are scoped to the immediately preceding non-local label and the problem then disappears.

In fact, you can actually refer to local labels in their non-local form. For example, if you wanted to skip part2 while processing part1, you could use something like the check_something processing below:

part1  mov   ax, 10
.loop  jz    .fin

       ; do something else

       call  check_something ; bx=42 means stop everything,
       cmp   bx, 42          ;  so we'll break from part 1
       jz    part2.fin       ;  and skip part 2 entirely.

       dec   ax
       jmp   .loop
.fin
    
part2  mov   ax, 50
.loop  jz    .fin

       ; do something else

       dec   ax
       jmp   .loop
.fin

Using .fin from within part1 wouldn't work since that would select part1.fin, but the fully qualified part2.fin will do the trick.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I think it is prudent to note that "non-local labels" to use as base labels are actually labels that do not start with `.` or `..@` (this excludes mmacro-local labels specified with a `%%` prefix in the source), and that are also not equates. This means that the one and only difference between `foo:` (alone on a line) and `foo: equ $` is that the latter is not a base for local labels. I use this sometimes, eg https://hg.pushbx.org/ecm/ldebug/file/3f5f15b26986/source/expr.asm#l373 or https://hg.pushbx.org/ecm/ldebug/file/3f5f15b26986/source/ints.asm#l131 – ecm Sep 02 '23 at 11:44
1

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?

Let's find out!

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:

So the first jz .fin jumps to the first instance of .fin, and the second jz .fin jumps to the second instance of .fin.

Michael
  • 57,169
  • 9
  • 80
  • 125
0

According to YASM's docs on NASM local labels, a local label is associated with a global label. So I think your example would actually have a conflict if there wasn't a global label separating the two instances of .fin.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847