I am working on some Turbo Assembler which I was introduced to in my architecture class. The problem I am working on is using the extrn
and include
keywords to access a function/procedure from one ASM file and use it in another one. I included the respective files below and also ran the following commands:
tasm file1.asm tasm file2.asm tlink file1.obj+tlink2.obj
After tlink
I get the error about MyProcedure
being an undefined symbol in file2.asm.
file1.asm:
.MODEL SMALL
.DATA
; Data declarations go here
.CODE
; Code segment
; Define the procedure
MyProcedure PROC
; Procedure code goes here
; For example:
MOV AH, 9 ; DOS interrupt to print string
LEA DX, Msg ; Load the address of the message
INT 21h ; Call DOS interrupt
RET ; Return from the procedure
MyProcedure ENDP
; Data section
Msg DB "Hello, World!$"
END
file1.inc:
; Declare external procedure MyProcedure
EXTRN MyProcedure:NEAR
file2.asm:
.MODEL SMALL
.DATA
; Data declarations go here
.CODE
; Code segment
; Include external file
INCLUDE file1.inc
; Main program
START:
; Call the procedure defined in file1.inc
CALL MyProcedure
; Other code goes here
; End of main program
END START
I was able to figure out what I was doing. This answer is considered using Borland's 16-bit TASM 5.0 so keep that in mind. I will include two different answers and just remember to use accordingly.
First way: Using a reference from an external ASM file.
If you want to reference an external file with a specific procedure, here is an example with instructions:
file1.asm (main file)
; Simple program that will use an external call to file external.asm
; The procedure will call a system interrupt
; External procedure that will execute the system interrupt in the program
; Declare at the top here to let the assembler know that this will be referenced outside this file when creating the assembler object
EXTRN myProcedure:PROC
.model small
.stack 100h
.data
; Data declaration goes here
.code
; Code declaration goes here
_start:
CALL myProcedure ; calls the myProcedure that will execute the system interrupt
end _start
This first file is the main file that is using the externally called procedure myProcedure. Seems best practice is to place the EXTRN
command at the top so the assembler knows.
file2.asm (externally referenced file)
; Program that contains the system interrupt command procedure called myProcedure
; Will be externally referenced in main.asm
;
.MODEL small
.CODE
; This public declaration works like an interface and lets the assembler know that this procedure
; can be externally referenced and executed by the files that are tlinked with this program respectively
PUBLIC myProcedure
myProcedure PROC NEAR ; Procedure declaration with procedure code for declaration
; Procedure code here
MOV AH, 4Ch
INT 21h
RET
myProcedure ENDP
END
This file is the external file that will contain the defined procedure myProcedure. The NEAR
keyword just lets the program know to jump inside the segment. In this example, when called in the main.asm
, it will stay inside the Start segment. If you find the program begins to get larger, you may need to switch to FAR
and experiment with that keyword instead.
Instructions:
tasm file1.asm tasm file2.asm tlink file1.obj file2.obj main.exe (or whatever executable that is spit out)
Second way: Using a .INC file that will hold the procedure that will be included at run time in the main .ASM file.
file1.asm (main file)
; This program is example on how to use `INCLUDE` keyword in TASM 16-bit program to reference an external procedure, struct, obj, macro, etc
; All it does is call a system interrupt from the respective .INC file. In this case it is main2.inc
.MODEL small
.STACK 100h
.DATA
; Data section here
.CODE
INCLUDE file1.inc ; Contains the procedure I will reference
Start:
Call myProcedure ; Call the desired procedure.
END Start
This main file just has the INCLUDE
statement that is placed in the .CODE
segment. Now that the assembler knows to include the file you can see below at the Start label where I will call the procedure that is being referenced from file1.inc.
file1.inc (file to be included that contains the procedure)
; .INC file that will contain the system interrupt procedure
PUBLIC myProcedure ; Interface declaration that allows assembler to know that the procedure can be used publicly in the respective file
myProcedure PROC NEAR
; Procedure code here
MOV AH, 4Ch
INT 21h
RET
myProcedure ENDP
You can see that the .INC works the same way like a hoarder file in C or C++. You just put whatever needs to be referenced there so it can be called in any file at anytime as long as the file that wants to reference included it with the INCLUDE
statement. In this case as long as file1.asm has the INCLUDE file1.inc
we can use the procedure myProcedure.
Instructions:
tasm file1.asm tlink file1.obj main.exe (or whatever executable that is spit out)
You can see this second set of instructions differs a little bit considering we do not need to tasm or tlink a second file. You can run the program pretty straightforward.
I hope this helps anyone else on this assembler journey. Please comment and ask questions. I will do my best to get back or I hope someone is able to help.