The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: NoCforMe on November 03, 2011, 06:22:46 PM

Title: Need basic help creating a library
Post by: NoCforMe on November 03, 2011, 06:22:46 PM
Another (somewhat) n00b question here:

I want to create a library for some routines I plan on using in several programs. I used to do this, long ago and far away in a land of 16-bit words.

But things are different now, and I can't get this simple thing to work.

Here's my test routine for the library:


INCLUDE \techstuff\masm32\include\my_masm32rt.inc
PUBLIC Test1

.data

testmsg DB "libtest.asm here", 0

.code

Test1 PROC
INVOKE MessageBox, 0, ADDR testmsg, NULL, MB_OK
RET
Test1 ENDP

END


and here's the main program I'm using to test it (I took "minimum" from the MASM32 examples and cut it down even further):


include /techstuff/masm32/include/my_masm32rt.inc
includelib mylib.lib

extrn Test1:NEAR

.code

start:
call Test1
push 0
call ExitProcess

end start


(See Note 1 below)

Here are the commands I used to put things together:



ml /c /coff libtest.asm
lib /out:mylib.lib libtest

ml /c /coff minimum.asm
link /subsystem:windows minimum


(See Note 2 below)

When  I try to link the test program, I get this error message:


minimum.obj : error LNK2001: unresolved external symbol _Test1
minimum.exe : fatal error LNK1120: 1 unresolved externals


Help! I understand what's happening here: in high-level-language convention, function names are being prefixed with underscores. (In 16-bit land things were so much simpler: if you called a function "foo", that's what it looked like all through the assemble/link process.) So somewhere along the line there's a mismatch.

I thought that putting the "includelib" statement in the main (calling) program should make everything work. Can't figure out why this reference to the subroutine isn't getting resolved. Everything--both source files, both object files and the library file--is in the same folder.

What magic incantation am I missing here? Please tell me it's something simple ...

Note 1: Yes, that's where I like to park the MASM32 package (not in the root), since, well,  since it's MY computer and I'll do as I please. Don't like that? Tough.
Note 2: Tools (ml.exe, lib.exe & link.exe) load just fine; no need for that "[path]\.ml.exe" nonsense, since I have my PATH properly set to point to the MASM32\bin folder.
Title: Re: Need basic help creating a library
Post by: NoCforMe on November 03, 2011, 06:33:59 PM
Something about the LIB program (Microsoft Library Manager Version 5.12.8078) that bugs me: when I run it from the command line, it seems to be waiting for more input (from STDIN) after it executes whatever command I give it, so I'm never sure what it's really doing. Is this normal? Is it meant to be run from a script or batch file, but not "by hand"?

Another thing: when I look at the library I created (with a hex file viewer), I see that the module name is actually "_Test1@0". Is this correct?
Title: Re: Need basic help creating a library
Post by: dedndave on November 03, 2011, 07:00:34 PM
a while back, i wanted to do the same thing
under masm 5.10, i used PUBLIC and EXTRN (or EXTERN), just like you
now days, they are both replaced by EXTERNDEF - lol
you may want to browse through the entire thread, but the first post has the attachment...
http://www.masm32.com/board/index.php?topic=15480.0

PROC's are public by nature, unless you specify PRIVATE on the PROC line
DATA is private by nature, and must be made public to be externally visible
Title: Re: Need basic help creating a library
Post by: fearless on November 03, 2011, 07:02:38 PM
Link can output library files as well, have a look at masm32 library to give you an idea how it was compiled, the folder has some batch files in it for assembling and will give you an idea what to specify.

Also you probably want to have your own .inc file for your library to has the functions that are available for use.

So in other asm programs you use you would add the following:
include mylib.inc
includelib mylib.lib


(also remember to copy the .lib to your masm32\lib folder and the .inc file to masm32\include for ease of use)

In your mylib.inc you woudl probably have the definitions like so:

Test1    PROTO

obviously coz you only have one function with no parameters there is nothing else to declare.

If you have another proc, lets say its called TestMe, and has four params like so:

TestMe PROC szName:DWORD, lpszOutBuffer:DWORD, fOutputType:DWORD, MiscParam:DWORD
  ... some stuff for proc
  ret
TestMe ENDP


In your .inc file (same one) you would add the definition for your new function as:
TestMe PROTO :DWORD, :DWORD, :DWORD, :DWORD

To someone reading your source code they would know what each param is and why, but to someone else they wont, so make a note somewhere, document the parameter inputs (whats expected) and any return values - more for yourself if you come back to it months later and have forgotten what exactly it does ;-)
Title: Re: Need basic help creating a library
Post by: NoCforMe on November 03, 2011, 07:13:11 PM
Well, while I really can't argue with your advice, it's all beside the point here because I can't get the library routine to be linked at all. Kind of a more pressing problem at the moment than having nice include files.

So can someone please lay out here (not in an attachment!) exactly what I need to do here, with EXTERNDEFs and all, to make this simple example work? I'm totally confused, especially about the use of this directive. (Do I use it both in the subroutine AND the calling module? Do I use it with PROTO? How the hell does this all work, anyhow?)
Title: Re: Need basic help creating a library
Post by: NoCforMe on November 03, 2011, 09:07:07 PM
Problem solved.

Turned out I needed the following statement in both the library module and the calling program:


Test1   PROTO


Seems kinda silly, but it makes it work ...

Still not completely clear on the use of EXTERNDEF, PROTO, etc. Damn Micro$oft! I've got a copy (printed copy) of the MASM 6.1 Programmer's Guide. While they mention both of these directives in several places, they never once clearly define them, give the exact syntax, or explain what exactly they do. Piss-poor manual, that. (If anyone knows of some better documentation out there, I'm all ears!)
Title: Re: Need basic help creating a library
Post by: fearless on November 03, 2011, 09:41:45 PM
Yep, just include your mylib.inc in your new project - which has the proto defined and it will pick it up when linking due to the includelib and include statements.
Title: Re: Need basic help creating a library
Post by: NoCforMe on November 03, 2011, 09:49:10 PM
So that last statement brings up another question that's been bugging me: what's up with using "includelib", anyhow? (Apologies if this has already been discussed on this forum.)

It doesn't make sense to me that this goes in the assembly source file; isn't this something that's handled by the linker, not the assembler? Why does the assembler care about any linked library modules, apart from the names of the symbols in those modules, which are already taken care of by use of EXTRN, EXTERNDEF, PROTO, etc.?

Even if one uses ml.exe to both assemble and link, shouldn't the library module resolution stuff be taken care of during the link phase anyhow?

I'm confused ...
Title: Re: Need basic help creating a library
Post by: Tedd on November 03, 2011, 10:47:48 PM
The assembler doesn't care about includelib, it's actually just a convenience that we can put it in there. It's inserted into the object file as a 'pragma,' which the linker processes when given the object file.
Title: Re: Need basic help creating a library
Post by: NoCforMe on November 04, 2011, 01:20:15 AM
So can I safely leave all those INCLUDELIBs out? I like to minimize program clutter ...
Title: Re: Need basic help creating a library
Post by: dedndave on November 04, 2011, 01:21:39 AM
have you tried it ?   :bg

you can probably leave them out if you specify them on the link command line
much more convenient in the assembler source

when you create your own static library, you will probably want to create an INC file to go with it
you can put the INCLUDELIB in that INC file, if desired, along with the PROTOtypes and constants (EQU) that go with the LIB
Title: Re: Need basic help creating a library
Post by: dedndave on November 04, 2011, 01:32:56 AM
just happened to think
you might try the LIB environment variable

nope - that doesn't get it
Title: Re: Need basic help creating a library
Post by: dedndave on November 04, 2011, 12:24:45 PM
first, let's make a static library
we want one public data item and one public function
for the data, we will use a string that we can display
for the function, we will use the print macro wrapped in a PROC

create a file named Module.asm...
;static library module source

        INCLUDE \masm32\include\masm32rt.inc

;------------------------------------------------

        EXTERNDEF   szTestString:BYTE  ;probably don't need the type here - just the label name

;------------------------------------------------

        .DATA

szTestString db 'Static Library Test String',13,10,0

;------------------------------------------------

        .CODE

TestFunc PROC   lpszString:LPSTR

        print   lpszString
        ret

TestFunc ENDP

;------------------------------------------------

        END


this will make one module - the library may hold many such modules
to assemble it...

ml /c /coff Module.asm

to create the library from that module...

link /lib Module.obj /out:MyLib.lib

notice that LINK does all the stuff that we used to use LIB for
there is also a LIB.exe that may be used (notice how small it is - it's a stub for LINK)
you can get all the add/remove/extract module management commands with LIB /?
Title: Re: Need basic help creating a library
Post by: dedndave on November 04, 2011, 12:25:45 PM
now, we want an INC file to go with the LIB
it can define any constants (EQUates) and PROTOtypes required to use the library
an example of such a file might come from microsoft
they give you files like kernel32.h - a C include file
we want an assembler version (INC)
the syntax is different, but the idea is the same
one of the functions in kernel32 is SetConsoleMode
that function has several constants that go with it, like ENABLE_MOUSE_INPUT
so, in kernel32.inc, we would see...
SetConsoleMode PROTO :HANDLE,:DWORD

ENABLE_MOUSE_INPUT EQU 10h

of course, there are more prototypes and constants, too
Hutch has taken all these constants and put them in windows.inc
that is why it is so large (the masm32 windows.inc is actually split in 2)
i think he did it that way so all the constant definitions could be found in one place, without searching for them

for our little library, we have one function, and no constants
as you add things to the library, you will update the INC file

so - create a file named MyLib.inc...
;INCLUDE file for MyLib.lib

        EXTERNDEF   szTestString:BYTE  ;the type is required, here

TestFunc PROTO :LPSTR
Title: Re: Need basic help creating a library
Post by: dedndave on November 04, 2011, 12:27:48 PM
finally, we want to write a little program to test the library...
        INCLUDE    \masm32\include\masm32rt.inc
        INCLUDE    MyLib.inc
        INCLUDELIB MyLib.lib

;------------------------------------------------

        .CODE

_main   PROC

        INVOKE  TestFunc,offset szTestString
        inkey
        exit

_main   ENDP

;------------------------------------------------

        END     _main


as i mentioned before, you could take the INCLUDELIB directive out of the source and put it in the INC file
Title: Re: Need basic help creating a library
Post by: NoCforMe on November 04, 2011, 07:28:47 PM
Quote from: dedndave on November 04, 2011, 12:27:48 PM
as i mentioned before, you could take the INCLUDELIB directive out of the source and put it in the INC file

Regarding this, while it obviously makes it more convenient, it seems a little silly to include the INCLUDELIB in the source file where the library module itself is being defined. So what is the effect of that: nothing? (Otherwise, it would have to be recursive or something!)
Title: Re: Need basic help creating a library
Post by: fearless on November 04, 2011, 09:08:36 PM
Its more about making the lib distributable and re-usable with ease, and since all the function prototypes are defined in your .inc makes sense to use that with the includelib. Both for your lib and for referencing the lib functions in other asm modules that you create.
Title: Re: Need basic help creating a library
Post by: NoCforMe on November 04, 2011, 09:15:01 PM
Right, I got that. I guess the answer to my question above, then, is "it doesn't hurt if you put INCLUDELIB in the file where the library module is declared".
Title: Re: Need basic help creating a library
Post by: dedndave on November 05, 2011, 03:41:51 AM
well - there are cases where you may want to build a project with different versions of a library
in that context, it makes sense to put the INCLUDELIB in the asm source, where it is clearly visible and easily changed