2

I'm getting an error message when assembling code in which an instruction references a label in a different procedure.

This code generates two errors, assembler is JWasmR v2.12pre:

single segment stack                                                      
assume cs:single,ds:single,ss:single 

start:
    mov ax, cs 
    mov ds, ax                   
    mov ax, 4c00h
    int 21h

func1 proc
label1:
    jmp label2
func1 endp

func2 proc
label2:
    call label1
func2 endp

align 2                          
s16 db 256 dup (0ffh)            
single ends                             
end start

Error messages:

test1.asm(13) : Error A2102: Symbol not defined : label2
test1.asm(20) : Error A2102: Symbol not defined : label1

I think each label symbol is local to it's respective procedure. I would like to disable this functionality globally, or bypass it on an individual basis. I've tried using the -Zf option which makes all symbols public. Documentation can be found here.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
bad
  • 939
  • 6
  • 18
  • 1
    You could tell the assembler that your whole program is one big `proc`, and defined your functions as `func1:` and `func2:`. That might stop you from making the function entry points visible to the linker, though. IDK, NASM doesn't have this problem, it doesn't use `proc` at all, just labels which you can mark as global or not. – Peter Cordes May 28 '20 at 20:31
  • You know what, you're right. The solution here is just don't use the `proc` keyword at all. That local symbol thing is probably the whole point of using `proc` in newer assemblers. I'm migrating code from Masm 5.10. – bad May 28 '20 at 21:06
  • Not the *whole* point. `proc` in MASM can also magically emit code to save/restore registers if you do `proc using ebx` or something, I think. `proc` may also be necessary if you want to call a function from C or another asm source file (i.e. make the symbol visible to the linker, like NASM `global foo`.) That's why I didn't post that comment as an answer. – Peter Cordes May 28 '20 at 21:11

1 Answers1

3

In MASM 5.1x if you aren't using a .MODEL directive with a language type then code labels inside a PROC are globally scoped. This is why your code assembles in MASM 5.1x. In JWASM and MASM 6.1+ it is a bit different because code labels that are followed by a : are always locally scoped in a PROC. This results in the errors you are seeing. The MASM 6.1 documentation covers this issue:

MASM 5.1 considers code labels defined with a single colon inside a procedure to be local to that procedure if the module contains a .MODEL directive with a language type

The solution is to use :: following a label rather than : to mark a code label as globally defined. The documentation goes on to say:

You can use the double colon operator to define a non-scoped label

Using :: should make your code assemble with MASM 5.1+, 6.1+, and JWASM. This code:

func1 proc
label1:
    jmp label2
func1 endp

func2 proc
label2:
    call label1
func2 endp

Should work if written as:

func1 proc
label1::
    jmp label2
func1 endp

func2 proc
label2::
    call label1
func2 endp

You can use the -Zm option (not to be confused with -mz) enables MASM 5.1 compatibility. Running JWASM this way should allow your code to assemble without any changes:

jwasm -Zm filename.asm

Using this method will make locally scoped labels in a PROC globally scoped. The other changes that occur are:

Option -Zm (or setting OPTION M510) will do:
- set OPTION OLDSTRUCTS
- set OPTION DOTNAME
- set OPTION SETIF2:TRUE
- set OPTION OFFSET:SEGMENT (if no model is set)
- set OPTION NOSCOPED (if no model with language specifier is set)
- allow to define data items behind code labels
- allow "invalid" use of REP/REPE/REPNE instruction prefixes
- change precedence of [] and () operator from 1 to 9. Hence expression
  -5[bx] is parsed as (-5)[bx], while without -Zm it is
  parsed as -(5[bx]), which generates an error.

For JWASM and MASM 6.1+ you can also specify the no scope option at the top of an assembly module with this directive:

OPTION NOSCOPED

This option doesn't exist in MASM 5.1x as this is the behaviour for that assembler. You would have to remove this directive from your assembly code if assembling with MASM 5.1x. The MASM 6.1 documentation describes this option as:

The information in this section applies only if the .MODEL directive in your MASM 5.1 code does not specify a language type. Without a language type, MASM 5.1 assumes code labels in procedures have no “scope” — that is, the labels are not local to the procedure. When not in compatibility mode, MASM 6.1 always gives scope to code labels, even without a language type. To force MASM 5.1 behavior, specify either OPTION M510 or OPTION NOSCOPED in your code

Michael Petch
  • 46,082
  • 8
  • 107
  • 198