Ok, I hope this is the last major question I have here after putting low of rudimentary question. I tried to do a correct usage of extern and public in two different files and both of them compiles and generates obj files but during link the proc declared as public (lib.asm) and imported into second file (asmfile.asm) with extern directive is causing issue. I re-checked everything and corrected but still it is giving a grief. Can someone help on this?
After compilation, I am not sure if the code segment of lib.asm were included in the binary (need to check that) but for sure, data segment of lib.asm was included by dumping the area with debugger.
Thanks in advance!
C:\git\minix.dev>dir
Volume in drive C has no label.
Volume Serial Number is FC76-C34F
Directory of C:\git\minix.dev
09/17/2015 10:43 PM <DIR> .
09/17/2015 10:43 PM <DIR> ..
09/18/2015 12:05 AM <DIR> exp
0 File(s) 0 bytes
3 Dir(s) 46,058,704,896 bytes free
C:\git\minix.dev>cdexp
C:\git\minix.dev\exp>dir
Volume in drive C has no label.
Volume Serial Number is FC76-C34F
Directory of C:\git\minix.dev\exp
09/18/2015 12:05 AM <DIR> .
09/18/2015 12:05 AM <DIR> ..
09/17/2015 11:53 PM 941 asmfile.asm
09/18/2015 12:05 AM 882 asmfile.exe
09/18/2015 12:05 AM 3,750 asmfile.lst
09/18/2015 12:05 AM 320 asmfile.map
09/18/2015 12:05 AM 718 asmfile.obj
09/17/2015 10:43 PM 240 cfile.c
09/17/2015 10:43 PM 44 del1.bat
09/17/2015 11:50 PM 524 lib.asm
09/17/2015 10:43 PM 239 lib.inc
09/18/2015 12:05 AM 1,844 lib.lst
09/18/2015 12:05 AM 537 lib.obj
09/17/2015 10:43 PM 599 macros.inc
09/17/2015 11:37 PM 194 masm.cmpl.bat
13 File(s) 10,832 bytes
2 Dir(s) 46,058,704,896 bytes free
C:\git\minix.dev\exp>typeasmfile.asm
.586
;.model flat, stdcall
include macros.inc
extern extFnc:near
;extrn extFcn1:near
sta segment para stack use16 'stack'
db 100h dup(0)
sta ends
data segment para public 'data'
str0 db 'test string in asmfile.asm$'
str1 db 'str1$'
data ends
code segment para public use16 'code'
assume cs:code, ds:data,ss:sta
main proc far
mov ax, DATA
mov ds, ax
; PRINTF "macrostring"
; PRINTF "2ndMacroString"
; call extFcn
; lea bp, str0
; call printStr
mov ax, 4c00h
int 21h
main endp
; input
; DS:BP - pointer to string ($) terminated.
printStr proc far
printLoop:
mov dl, ds:[bp]
cmp dl, '$'
je quit
mov ah, 02h
int 21h
inc bp
jmp printLoop
quit:
ret
printStr endp
code ends
end main
C:\git\minix.dev\exp>typelib.asm
.586
public extFcn, extFcn1
sta segment para stack use16 'stack'
sta ends
data segment para public 'data'
str1 db 'test string in lib.asm'
data ends
code segment para public use16 'code'
assume cs:code, ds:code, ss:sta
extFcn1 proc near
xor dl, dl
mov dl, 36h
mov ah, 02h
int 21h
ret
extFcn1 endp
extFcn proc near
xor dh, dh
mov dl, 35h
mov ah, 02h
int 21h
ret
extFcn endp
code ends
end
C:\git\minix.dev\exp>del1.bat
C:\git\minix.dev\exp>del *.obj
C:\git\minix.dev\exp>del *.exe
C:\git\minix.dev\exp>del *.lst
C:\git\minix.dev\exp>del *.map
C:\git\minix.dev\exp>masm.cmpl.bat
C:\git\minix.dev\exp>del *.exe
Could Not Find C:\git\minix.dev\exp\*.exe
C:\git\minix.dev\exp>del *.obj
Could Not Find C:\git\minix.dev\exp\*.obj
C:\git\minix.dev\exp>del *.lst
Could Not Find C:\git\minix.dev\exp\*.lst
C:\git\minix.dev\exp>del *.map
Could Not Find C:\git\minix.dev\exp\*.map
C:\git\minix.dev\exp>rem ml /c /coff /Cp /Fm /Fl asmfile.asm
C:\git\minix.dev\exp>rem ml /omf /c /Fl /Zi /Zd lib.asm
C:\git\minix.dev\exp>ml /c /Fl /Zi /Zd asmfile.asm lib.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.
Assembling: asmfile.asm
sta segment para stack use16 'stack'ends data segment para public 'data' str1 db 'test string in lib.asm'data ends code segment para public use16 'code'assume cs:code, ds:code, ss:sta extFcn1 proc near xor dl, dl mov dl, 36hah, 02int 21h ret extFcn1 endp extFcn proc near xor dh, dh mov dl, 35hah, 02int 21h ret extFcn endpcode ends end C:\git\minix.dev\exp>del1.bat C:\git\minix.dev\exp>del *.obj C:\git\minix.dev\exp>del *.exe C:\git\minix.dev\exp>del *.lst C:\git\minix.dev\exp>del *.map C:\git\minix.dev\exp>masm.cmpl.bat C:\git\minix.dev\exp>del *.exeould Not Find C:\git\minix.dev\exp\*.exe C:\git\minix.dev\exp>del *.objould Not Find C:\git\minix.dev\exp\*.obj C:\git\minix.dev\exp>del *.lstould Not Find C:\git\minix.dev\exp\*.lst C:\git\minix.dev\exp>del *.mapould Not Find C:\git\minix.dev\exp\*.map C:\git\minix.dev\exp>rem ml /c /coff /Cp /Fm /Fl asmfile.asm C:\git\minix.dev\exp>rem ml /omf /c /Fl /Zi /Zd lib.asm C:\git\minix.dev\exp>ml /c /Fl /Zi /Zd asmfile.asm lib.asmMicrosoft (R) Macro Assembler Version 6.14.8444 Copyright (C) Microsoft Corp 1981-1997. All rights reserved. Assembling: asmfile.asmlib.asm
C:\git\minix.dev\exp>link16 asmfile.obj lib.obj,,,,,
Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994
Copyright (C) Microsoft Corp 1984-1993. All rights reserved.
asmfile.obj(asmfile.asm) : error L2029: 'extFnc' : unresolved external
There was 1 error detected
C:\git\minix.dev\exp>
ok - i don't have any experience using masm 6.x + with 16-bit libraries - lol
the last time i wrote libs/eternal objs for 16-bit, i was using masm 5.10 and a linker from the same era
but, i have written a little static library example using 6.x, for 32-bit code
seems like the directives should also work for 16-bit code
first, i notice that you are creating your own segments, like we did in the old days
that's a lot of work - lol
but, it should be do-able
easier to use:
.STACK 4096 for 4 KB stack (as an example)
.DATA for initialized data
.DATA? for uninitialized data
.CONST for read-only initialized data
.CODE for code
@Data to load DGROUP into a register
no more text segment para blah blah blah
no more ENDS, either - when you open another segment, the current one is closed
that having been said, i will find the 32-bit example for you to look at
you can throw out EXTRN and PUBLIC, and just use EXTERNDEF for both :P
PROC's are public, by default (unless you specify PRIVATE on the PROC line)
http://masm32.com/board/index.php?topic=2743.msg29054#msg29054 (http://masm32.com/board/index.php?topic=2743.msg29054#msg29054)
one thing i see....
if you are assembling 16-bit code, you want an OMF format object module
ml /c /omf .......
yes this is the way i have been coding with half decado ago and moved to something else.
Now my skillset is stuck with this old way programmiing.
For the project, it does not matter which one you use.
Quote from: dedndave on September 18, 2015, 06:31:07 AM
ok - i don't have any experience using masm 6.x + with 16-bit libraries - lol
the last time i wrote libs/eternal objs for 16-bit, i was using masm 5.10 and a linker from the same era
but, i have written a little static library example using 6.x, for 32-bit code
seems like the directives should also work for 16-bit code
first, i notice that you are creating your own segments, like we did in the old days
that's a lot of work - lol
but, it should be do-able
easier to use:
.STACK 4096 for 4 KB stack (as an example)
.DATA for initialized data
.DATA? for uninitialized data
.CONST for read-only initialized data
.CODE for code
@Data to load DGROUP into a register
no more text segment para blah blah blah
no more ENDS, either - when you open another segment, the current one is closed
that having been said, i will find the 32-bit example for you to look at
you can throw out EXTRN and PUBLIC, and just use EXTERNDEF for both :P
will externdef will work for both in the current style of programming? I will give it a try. thanks., ;)
what you have may work - but the OBJ is not recognized because it's not OMF format
great, using externdef it worked. I had to declare inside the cseg in order for it work. I am not sure why public and extern did not work.
Tutorial says externdef will either act like extern or public depending whether the symbol exists in the file or not.
If so, only logical reason it did not work is might be public/extern was declared outside the cseg. That is what the online tutorial shows. Might that was typo?
Who knows.
saying that have good idea: macro the crap out of extern statements so that when the files to be compiled reached dozens or hundreds no forgotten external reference compile error:
EXTERN1 MACRO
EXTERNDEF Var1
EXTERNDEF Var2
EXTERNDEF ...
EXTERNDEF Var100
ENDM
so that any functions needs to be externalized just include in this macro.
Good?
if EXTERNDEF refers to something external, you should provide a type
EXTERNDEF wSomeWord:WORD
EXTERNDEF bSomeByte:BYTE
EXTERNDEF sSomeStruct:STRUCTNAME
EXTERNDEF fSomeProc:NEAR ;or FAR
if the symbol is internal, just the symbol name is required
yes i noticed, however i just included in the macro as externdef proc1:near etc., it does not seem to hurt (compiler did not complain) when used as a public statement too.
So the potential benefit seems to outweight to avoid maintenance nightmare of keeping track of all externdef variable, functions etc.,
Just declare the macro in your new module and every externdef is included.
Anything add to be used externally, just add to macro.
Might not be a big deal when having a few files, but when you have 100 files.
hi ggmasm32,
FWIW, there's no particular reason to use a macro. Normally we just put all the externdef's in an include file, and include that file at the top of each module. Using a macro as you do, it still must be in an include file, which still must be included, plus you then have to invoke the macro. Only advantage, if you want to include the file for other reasons, but not the externdef's, you can not invoke the macro; but that doesn't seem too useful. So, you can just skip the "EXTERN1" macro definition
You can also have more than one per line
EXTERNDEF proc1:near, var1:dword
bringing up this old thread, the externdef has worked great with functions. However, I am having issue with making serial byte string as external
externdef does not work.
if variable is declared as
var1 db 10h dup (?)
i could not figure out how to make it external??
so far tried with 2 ways:
1. externdef var1:byte in all files. (does not work)
2. public var1 in file in which it is declared
and extrn var1:byte in which it is used.
For both instances, I got fixup overflow during link. ?? thx
perhaps the name "var1" is used elsewhere ?
i haven't written any 16-bit libraries for years, so don't have to ready example
but, the one you tried looks ok
in the file where SomeBytes is defined:
public SomeBytes
in the file where SomeBytes is referenced:
extrn SomeBytes:BYTE
it would be helpful if you posted examples
i don't have time to create a 16-bit lib example from scratch
it is huge code and several files. May be I will put the beginning sections where most important declarations are:
disk.asm where it (int13fnc38Buf) is declared
include macros.inc
include video.inc
include disk.inc
public int13fnc38Buf
sta segment para stack use16 'stack'
sta ends
data segment para public 'data'
dap db 16 dup(31h)
bufSectorRead db 512 * 16 dup(33h)
int13fnc38Buf db 30h dup (34h)
data ends
code segment para public use16 'code'
assume cs:code, ds:data, ss:sta
M_EXTERNDEF
; Display drive params for drive information stored in DS:SI
; input DS:SI=pointer to drive parameter area.
; output CX=0 if success
; CX=1 if if failure
; destroys: CX
diskShowDiskParamMem proc far
M_PUSH <ax, dx, ds, si>
M_PRINTF "\nIn
dskclone.asm where it is being used.
.686p
include macros.inc
include mbr.inc
include dskclone.inc
include disk.inc
; experimental asm file to test out anything in this file.
; past tests can be de-activated using DISABLE_<TESTNAME> software switch in
; exp.inc
sta segment para stack use16 'stack'
db 100h dup(0)
sta ends
extrn int13fnc38Buf:byte
data segment para public 'data'
; disk address packet.
dap db 16 dup(31h)
; declare 16-sectors buffer.
; bufSectorRead db (512 * 16) dup(33h)
; testString db 'test String $'
srcDrvNo db ?
dstDrvNo db ?
LowDrvNo db 0 ; (Lowest disk No found)
HiDrvNo db 0 ; (highets disk No found)
counter db 0
srcDrvParams db 30h dup (35h)
dstDrvParams db 30h dup (36h)
remSectors db ? ; number of sectors remainder if not multiple of 16.
data ends
code segment para public use16 'code'
assume cs:code, ds:data,ss:sta
M_EXTERNDEF
I got by doing so that the var is only used inside disk.asm. any other module access will have to go through one of the api calls and not directly access the variable. Thanks.