Can't find out how to "compile" and link several files into one exe

Started by rotten, April 25, 2009, 09:49:42 PM

Previous topic - Next topic

rotten

I'm new to the forum and asm. I have written some basic programs and procedures and now want to start making some simple libraries.
For example a math library with functions like fib and fac.

So I have a file called math.asm and a file called test.asm. test.asm uses fac from math.asm.
if i try to include math.asm like this:
include C:\masm32\progs\math.asm
I get an error:
test.asm(18) : fatal error A1000: cannot open file : C:\masm32\progs\math.asm


I have also tried commenting out everything besides the procedures in math.asm(ie all the includes) but then I get:
Assembling: math.asm
math.asm(20) : error A2034: must be in segment block : fac
math.asm(21) : error A2085: instruction or register not accepted in current CPU
mode
math.asm(22) : error A2085: instruction or register not accepted in current CPU
mode
math.asm(23) : error A2034: must be in segment block
math.asm(24) : error A2085: instruction or register not accepted in current CPU
mode
math.asm(25) : error A2034: must be in segment block : $$$00001
math.asm(25) : error A2034: must be in segment block
math.asm(26) : error A2034: must be in segment block : $$$00001
math.asm(26) : error A2034: must be in segment block
math.asm(27) : fatal error A1010: unmatched block nesting : fac

C:\masm32\progs\libs>



So:
1. should libraries just contain the procedure implementations or also stuff like .386, .model etc?
2. how do I import and link together files?

Code is here:
http://hpaste.org/fastcgi/hpaste.fcgi/view?id=4232#a4232

Comments on the actual code quality is always welcome but most importantly I want to know how to assemble and link several files together.

And btw:
asm is fun!

Slugsnack

I have no idea why you commented out a bunch of the lines cause when you uncomment it it assembles and links fine.  Just put it into QEditor then Project >> Console Assemble & Link

http://pastebin.com/m1712b032

Ooops I misread.. if you want a DLL then try Code >> Create New DLL.  The comment at the bottom describes how you can add procedures that can be exported and used by other executables.  The auto-generated LibMain is the entry point of the DLL that is called in various instances such as DLL load, DLL unloading, etc.  The code there allows you to do different things in each of the cases.

rotten

well math.asm assembles for me if I have the stuff uncommented. But test.asm doesnt, it doesn't find the file.

edit:
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: C:\masm32\progs\libs\test.asm
C:\masm32\progs\libs\test.asm(18) : fatal error A1000: cannot open file : C:\mas
m32\progs\math.asm
_
Assembly Error
Press any key to continue . . .

rotten

solved this problem. the only problem I have left is that it doesn't find the dll unless it is in the same dir.

jj2007

Quote from: rotten on April 25, 2009, 10:19:38 PM
solved this problem. the only problem I have left is that it doesn't find the dll unless it is in the same dir.

You have four options:
1. Put it in the same dir (easy)
2. Put it in some dir that is in The Path (ugly)
3. Use a hardcoded full path such \myfolder\mydlls\myfile.dll (works but is not everybody's taste)
4. Use a relative path such as mydlls\myfile.dll (easy and elegant)

rotten

Quote from: jj2007 on April 26, 2009, 05:36:31 AM
Quote from: rotten on April 25, 2009, 10:19:38 PM
solved this problem. the only problem I have left is that it doesn't find the dll unless it is in the same dir.

You have four options:
1. Put it in the same dir (easy)
2. Put it in some dir that is in The Path (ugly)
3. Use a hardcoded full path such \myfolder\mydlls\myfile.dll (works but is not everybody's taste)
4. Use a relative pyath such as mydlls\myfile.dll (easy and elegant)



In the same dir works.

Didn't try 2 but 3 and 4 doesn't work. At least importing directly into the file.

Should I somehow pass the dll to the linker if it is not in the same dir?

C:\masm32\progs>\masm32\bin\ml /c /Zd /coff test.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: test.asm
C:\masm32\libs\math\math.dll(1) : error A2044: invalid character in file
C:\masm32\libs\math\math.dll(2) : error A2044: invalid character in file
C:\masm32\libs\math\math.dll(2) : error A2039: line too long

C:\masm32\progs>


; #########################################################################

   .386
   .model flat, stdcall
   option casemap :none

; #########################################################################

   include \masm32\include\windows.inc
   include \masm32\include\user32.inc
   include \masm32\include\kernel32.inc
   include \masm32\include\masm32.inc

   include C:\masm32\libs\math\math.dll
   
   includelib \masm32\lib\user32.lib
   includelib \masm32\lib\kernel32.lib
   includelib \masm32\lib\masm32.lib

   includelib C:\masm32\libs\math\math.lib


; #########################################################################

fac PROTO N : DWORD
fib PROTO N : DWORD
   
.data
    S db "Result is: ", 0
    N sdword 5
    Acc sdword 0
    ;IntArray        dword 8 dup (?)

.code
start:

invoke fac, 5
invoke fib, 12
   
utoa:
   mov ebx, 10 ; we'll divide by this
   xor ecx, ecx ; use as digit-counter
pushloop:
   xor edx, edx ;
   div ebx ; quotient in eax, remainder in edx
   push edx ; store it for later
   inc ecx
   cmp eax, 0
   jnz pushloop
poploop:
   pop eax ; get digit back
   add al, '0' ; convert to character
   mov Acc, eax
   push ecx
   invoke StdOut, eax ;; addr Acc   
   pop ecx
   loop poploop
   ret

;; mov Acc, 1
;; add Acc, 48
;; invoke StdOut, addr Acc
;; invoke StdOut, addr Acc
   
invoke ExitProcess, 0
   
end start





Trying to link like this:

C:\masm32\progs>\masm32\bin\Link /DLL /SUBSYSTEM:CONSOLE C:/masm32/libs/math/DEF
:math.def /LIBPATH:c:\masm32\libs test.obj
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

LINK : fatal error LNK1181: cannot open input file "C:/masm32/libs/math/DEF:math
.def"

C:\masm32\progs>

MichaelW

See Dynamic-Link Library Search Order for a description of the search order that the system uses to find a DLL. I would use the directory of the application, unless I had a very good reason for doing otherwise.

http://msdn.microsoft.com/en-us/library/ms811694.aspx

eschew obfuscation

rotten

;; C:\masm32\progs>\masm32\bin\Link /DLL /SUBSYSTEM:CONSOLE /DEF:C:\masm32\math\mat
;; h.def /LIBPATH:c:\masm32\lib test.obj


is that correct? I get a warning when I assemble but it assembles still and thne it loops forever. I will post ithe error later when I have time.

dedndave

of course, the modern way of declaring extrnals in a file is much better, but
in the old days we also linked OBJ's together like this...

LINK objfile1.obj+objfile2.obj......

MichaelW

rotten,

Assuming that math.asm is the source for a DLL, why are you including it in the source for test.asm? Math.asm should be separately assembled and linked to produce the DLL and an import library. There are two methods of using the functions in a DLL, see Load-Time Dynamic Linking and Run-Time Dynamic Linking here. The import library is used for Load-Time Dynamic Linking.

math.asm:

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    .386
    .model flat, stdcall
    option casemap :none

    ;----------------------------------------------------
    ; This is necessary only for the "reason" constants.
    ;----------------------------------------------------

    include \masm32\include\windows.inc

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    ; -------------------------------------------
    ; Build this DLL with the provided MAKEIT.BAT
    ; -------------------------------------------

      .data?

        hInstance dd ?

      .code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

LibMain proc instance:DWORD,reason:DWORD,unused:DWORD

    .if reason == DLL_PROCESS_ATTACH
      push instance                 ; copy local to global
      pop hInstance
      mov eax, TRUE                 ; return TRUE so DLL will start

    .elseif reason == DLL_PROCESS_DETACH

    .elseif reason == DLL_THREAD_ATTACH

    .elseif reason == DLL_THREAD_DETACH

    .endif

    ret

LibMain endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

  comment * -----------------------------------------------------
          You should add the procedures your DLL requires AFTER
          the LibMain procedure. For each procedure that you
          wish to EXPORT you must place its name in the "math.def"
          file so that the linker will know which procedures to
          put in the EXPORT table in the DLL. Use the following
          syntax AFTER the LIBRARY name on the 1st line.
          LIBRARY math
          EXPORTS YourProcName
          EXPORTS AnotherProcName
          ------------------------------------------------------- *

Fac proc N : sdword
    mov ecx, N
    mov eax, 1
  _fac:
    mul ecx
    loop _fac
    ret
Fac endp

;---------------------------
; Modified to preserve EBX.
;---------------------------

Fib proc N : sdword
    push ebx
    xor eax, eax
    mov ebx, 1
    mov ecx, N
  _fib:
    mov edx, eax
    add eax, ebx
    mov ebx, edx
    loop _fib
    pop ebx
    ret
Fib endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end LibMain


math.def:

LIBRARY math
EXPORTS Fac
EXPORTS Fib


test.asm:

; #########################################################################

    .386
    .model flat, stdcall
    option casemap :none

; #########################################################################

    include \masm32\include\windows.inc
    include \masm32\include\user32.inc
    include \masm32\include\kernel32.inc
    include \masm32\include\masm32.inc

    ;------------------------------------------------------------
    ; The includelib directive causes ML to place information in
    ; the object module that will allow the linker to set up the
    ; EXE for Load-Time Dynamic Linking. An alternative would be
    ; to list the libraries on the linker command line.
    ;------------------------------------------------------------

    includelib \masm32\lib\user32.lib
    includelib \masm32\lib\kernel32.lib
    includelib \masm32\lib\masm32.lib

    ;-----------------------------------------------
    ; This assumes that the import library math.lib
    ; is in the current directory.
    ;-----------------------------------------------

    includelib math.lib

    ;---------------------------------------------------------------
    ; These prototypes are necessary so MASM will know that Fac and
    ; Fib are defined in another file (instead of in the current
    ; file), what name to place in the object module (with the
    ; STDCALL calling convention the name depends on the size of
    ; the parameters), and how to invoke the procedures.
    ;---------------------------------------------------------------

    Fac PROTO N:sdword
    Fib PROTO N:sdword

; #########################################################################

.data
    S     db "Result is: ", 0
    crlf  db 13,10,0
    N     sdword 5
    Acc   sdword 0

.code

  utoa:
    mov ebx, 10 ; we'll divide by this
    xor ecx, ecx ; use as digit-counter
  pushloop:
    xor edx, edx ;
    div ebx ; quotient in eax, remainder in edx
    push edx ; store it for later
    inc ecx
    cmp eax, 0
    jnz pushloop
  poploop:
    pop eax ; get digit back
    add al, '0' ; convert to character
    mov Acc, eax
    push ecx
    invoke StdOut, addr Acc
    pop ecx
    loop poploop
    ret

start:

    invoke Fac, 5
    call utoa
    invoke StdOut, addr crlf
    invoke Fib, 5
    call utoa
    invoke StdOut, addr crlf

    invoke Sleep, 2000    ; delay so output will be visible

    invoke ExitProcess, 0

end start


makeit.bat:


: This batch file will first create the DLL and
: import library, and then the test app.

@echo off

if exist mmfdll.obj del math.obj
if exist mmfdll.dll del math.dll

\masm32\bin\ml /c /coff math.asm

pause

\masm32\bin\Link /SUBSYSTEM:CONSOLE /DLL /DEF:math.def math.obj

pause

: This simply lists the files.

dir math.*

pause

\masm32\bin\ml /c /coff test.asm

pause

\masm32\bin\Link /SUBSYSTEM:CONSOLE test.obj

pause

dir test.*

pause

eschew obfuscation