Search code examples
assemblytasmx86-16

How to connect extern files in TASM x64


I cannot connect external files to my program. I am trying to connect a file filled with macros. I have all the files in the same folder. So, HOW DO I PROPERLY EXTERN THESE FILES SO THAT I CAN CALL THE MACROS THAT ARE IN THEM ?

CODE:

include PCMAC.INC
    .model small
    .stack 100h

    .data
Prompt_a DB 'Enter A:$'
Prompt_b DB 'Enter B:$'
Output  db  'The sum is $'
CR  EQU 0dh ;13 \r moves the cursor to begginig of current row
LF  EQU 0ah ;10 new line  

    .code
   EXTERN GETDEC:NEAR, PUTDEC:NEAR 
   main proc 
        mov ax, @data
        mov ds, ax

        _PutStr Prompt_a
        call    GETDEC  ;number in AX after
        mov bx, ax
        _PutStr Prompt_b
        call GETDEC ; still in AX
        add bx, ax
        _PutStr Output
        mov ax, bx
        call   PUTDEC   ;Print num in AX
        _PUTCH 13, 10

        _exit 0 ; Finished/return to dos 
        main endp
        end main

ERROR MESSAGE:

  Assembling file:   test.asm
**Error** test.asm(13) Illegal instruction
**Error** test.asm(19) Undefined symbol: GETDEC
**Error** test.asm(22) Undefined symbol: GETDEC
**Error** test.asm(26) Undefined symbol: PUTDEC
  Error messages:    4
  Warning messages:  None
  Passes:            1
  Remaining memory:  455k

Solution

  • Simply INCLUDE the file and use the macros.

    The EXTRN directive, note the missing E, is used to declare a symbol, like a function, defined in another object file1 that is usually the result of a separate source file (this is typical when mixing C and assembly).

    Note
    The INCLUDE directive is like a copy-paste of the content of the included file in place of the directive.
    Make sure that the included content is compatible with the "surrounding" - i.e. make sure that copy-pasting the content of the file will generate a correct source.

    To use a macro, by its nature of meta-code2, the assembler needs to have access to its code, so INCLUDE is the right directive3 since it copies the source code of the macro in the current file.

    Example

    macros.asm

    exit MACRO
    
      mov ax, 4c00h
      int 21h
    
    ENDM
    

    program.asm

    .8086
    .MODEL SMALL
    .STACK 100h
    
    ;Macros are fine here
    INCLUDE mc2.asm
    
    _CODE SEGMENT PARA PUBLIC 'CODE' USE16
     ASSUME CS:_CODE, DS:_CODE
    
     ORG 100h
    
    __START__:
    
     ;This is the macro in the macros.asm file
     exit
    
    
    _CODE ENDS
    
    END __START__
    

    Note that you have to assemble and link program.asm, the other file, macros.asm is a satellite file (like the headers in C).


    EXTERN is not a valid directive and generates the error reported

    1 For the tech-savvy, it will create an entry 8Ch in the OMF object file .OBJ generated by TASM.

    2 It's code that reason about, and generate, code.

    3 For the tech-savvy, EXTRN makes no sense here since external symbols reduce to a 2/4 bytes offset and a (type) index that contains debug information in the Object Module Format (OMF) used by DOS Object files.


    Appendix

    This is a bit off-topic and not necessary to answer the question, the reader can stop reading, if it feels overwhelmed, without any loss.

    To better grasp the difference between the INCLUDEing a symbol and EXTRNing it, here is presented the same program that uses an externally defined exit function instead of a macro.

    Library.asm

    .8086
    .MODEL SMALL  
    
    PUBLIC exit
    
    _CODE SEGMENT PARA PUBLIC 'CODE' USE16
     ASSUME CS:_CODE, DS:_CODE
    
     exit:
       mov ax, 4c00h
       int 21h
    
       ;No need to ret
    
    _CODE ENDS
    
    ;No need for an entry-point
    END
    

    Program.asm

    .8086
    .MODEL SMALL
    .STACK 100h
    
    ;The type PROC is necessary or TASM will interpret the symbol
    ;as a variable generating an indirect call! e.g. call [exit]
    EXTRN exit:PROC
    
    
    _CODE SEGMENT PARA PUBLIC 'CODE' USE16
     ASSUME CS:_CODE, DS:_CODE
    
     ORG 100h
    
    __START__:
    
     call exit
    
    
    _CODE ENDS
    
    END __START__
    

    This time both Library.asm and Program.asm must be assembled and the resulting object files must be linked together with TLINK.