News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Global function(-s)

Started by physix, October 11, 2018, 03:32:33 AM

Previous topic - Next topic

physix

Hello together,

I searched straight for ~2 hours on google and msdn but wasn't that successful about finding a answer to my question.

I am coming from C++ but found my passion in masm, mostly 32-bit but slowly working and reading in 64-bit.

But anyways, my question is how am I able to define a function which is accessible for a another file?

I found out I can create my own library and include this in the source file - which will be using the functions - and use the PROTO directive to declare the skeletons. Well this isn't what I want to do because I want my code easy changeable and I don't want to compile a library each time when the code changes.

After this I found the EXTERNDEF directive which is pretty handsome as it's replacing the public and extern directives. And here I am stuck for now.

I know the header and source file principle from C++, include a header file and use these functions in the source file.

I know that the include directive in masm inserts the content of the included file. How am I able to include a function ?

I am able to include macros with this but I really don't know how I can make a function which I can easily include and use it with call/ invoke. Yes the macro's are defined in a XXX.inc file, so are the functions.

May have mercy with me, I searched my fingers to the bones but didn't find anything. I looked into very old threads here on the forum etc but I found nothing which could me help understand.

I would be very thankful for any input! :)

Regards, Physix.

hutch--

Well, let see if we can respond to the question. An assembler can produce an object module which can be used by either another assembler program or a C program as long as they use compatible object module formats. If you have an independent module, you have to pass data to it from the caller if you need things like Window handles or an instance handle.

As far as includes, in MASM you have two types, the "include" directory for header files and the "includelib" operator to include a library. You can also include a single OBJ module in your linker command line as well. Making a library is not all that complicated, as long as each object module is built correctly, you just bundle a whole pile of them together and you have a library that you can call and re-use.

Show us a bit more of what you are doing and we can probably point you in the right direction.

jj2007

Hi Physix,

Here is an example which I hope answers your question:
include \masm32\include\masm32rt.inc ; plain Masm32 for the fans of pure assembler

.Data
AppName db "Masm32:", 0

include myfuncs.asm    ; attached, contains HelloWorld proc

txWork db "Did it work?", 0

.code
start: call HelloWorld
MsgBox 0, addr txWork, addr AppName, MB_OK
exit

end start


Note that, careless as I am, I inserted the file in the .DATA section :P

physix

Quote from: jj2007 on October 11, 2018, 04:44:49 AM
Hi Physix,

Here is an example which I hope answers your question:
include \masm32\include\masm32rt.inc ; plain Masm32 for the fans of pure assembler

.Data
AppName db "Masm32:", 0

include myfuncs.asm    ; attached, contains HelloWorld proc

txWork db "Did it work?", 0

.code
start: call HelloWorld
MsgBox 0, addr txWork, addr AppName, MB_OK
exit

end start


Note that, careless as I am, I inserted the file in the .DATA section :P

First of all thank you and @hutch !

This is going where I wanna be but this won't compile with visual studio 2018, ml.exe and link.exe are the latest.

My Code:

Main.asm

.386

.model flat, stdcall

option casemap:none


.code


include C:\masm32_x86\include\masm32rt.inc

include Functions.asm

main proc

call HelloWorld

invoke ExitProcess, 1

main endp

end main


Functions.asm

% ThisSeg equ <@CurSeg>
.code
HelloWorld proc
mov eax, 1
ret
HelloWorld endp
% echo The previous segment was ThisSeg
ifidn ThisSeg, <_DATA>
  .DATA
elseifidn ThisSeg, <_DATA?>
  .DATA?
endif


The error log shows the following:


@hutch

I know what you are telling me. I was maybe to unspecific. I want a file which contains all functions which I can simply include in other files which can use the functions from the included one. The snippet from jj2007 was pretty much the thing I wanted. But as always things aren't that easy. ^^ Now I have to figure out why the code won't compile in this way.

Regards, Physix.

Edit:

If I modify Functions.asm like this:

.model flat, stdcall
.code
% ThisSeg equ <@CurSeg>
HelloWorld proc
mov eax, 1
ret
HelloWorld endp
% echo The previous segment was ThisSeg
ifidn ThisSeg, <_DATA>
  .DATA
elseifidn ThisSeg, <_DATA?>
  .DATA?
endif

end


The .model and the end directive was "needed" from visual studio. But thanks to the end directive I got an unresolved external error..



Kind of strange that 'end' is really needed here because I don't need a entrypoint right?

Adamanteus

Looks like something wrong with you ml.exe or masm32rt.inc - as it must have .model directive, and .code directive better to put after it included.

hutch--


> Kind of strange that 'end' is really needed here because I don't need a entrypoint right?

Not really, the "end" directive is to tell the assembler where the source file ends.

This is the batch file that builds the entire MASM32 library. You need to do something like this to build a library from your own object modules.

@echo off

copy masm32.inc \masm32\include\masm32.inc

del masm32.lib                      : delete any existing MASM32 Library

dir /b *.asm > ml.rsp               : create a response file for ML.EXE
\masm32\bin\ml.exe /c /coff @ml.rsp
if errorlevel 0 goto okml

echo ASSEMBLY ERROR BUILDING LIBRARY MODULES
pause
goto theend

:okml
\masm32\bin\link -lib *.obj /out:masm32.lib
if exist masm32.lib goto oklink

echo LINK ERROR BUILDING LIBRARY
echo The MASM32 Library was not built
goto theend

:oklink
copy masm32.lib \masm32\lib\masm32.lib

:theend
if exist masm32.lib del *.obj

dir \masm32\lib\masm32.lib
dir \masm32\include\masm32.inc

jj2007

Your problem seems to be Visual Studio - I don't post code that doesn't build OK:
*** Assemble using \masm32\bin\mlv614 /c /coff  tmp_file.asm ***
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: tmp_file.asm

***********
ASCII build
***********

The previous segment was _DATA

*** Link  NewWin32.obj rsrc.res  using polink, sub WINDOWS ***
*** NewWin32.exe: 3584 bytes ***

***  build all took 1009 ms  ***
« OK »


It builds equally fine with
- Microsoft (R) Macro Assembler Version 14.00.23026.0
- UAsm
- AsmC

I suggest you try \Masm32\qEditor.exe (I use RichMasm, but that's another long story).

P.S.:
Quote from: physix on October 11, 2018, 04:55:46 AMvisual studio 2018, ml.exe and link.exe are the latest.
That might explain something - the latest ML.exe versions are buggy. But I suspect it is some VS setting that prevents your code from building. Drop VS.

hutch--

Here is the right way to build a working library. You will need to have the MASM32 SDK installed and this will need to be put in a separate directory on the same partition.

@echo off

@echo -------------------------
@echo building %1.lib now
@echo -------------------------

del %1.lib                                  : delete any existing Library

dir /b *.asm > ml.rsp                       : create a response file for ML.EXE
\masm32\bin\ml.exe /c /coff @ml.rsp
if errorlevel 0 goto okml

echo ASSEMBLY ERROR BUILDING LIBRARY MODULES
pause
goto theend

:okml
\masm32\bin\link -lib *.obj /out:%1.lib
if exist %1.lib goto oklink

echo LINK ERROR BUILDING LIBRARY
echo The Library was not built
goto theend

:oklink
@echo --------------
@echo build seems OK
@echo --------------

:theend
if exist %1.lib del *.obj

dir %1.lib
del *.rsp

pause


The build looks like this. With this batch file you must use the name you want from the command line. "makeit mylib".

K:\asm32\makelib>makeit testlib
-------------------------
building testlib.lib now
-------------------------
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: szappend.asm
Assembling: szcatstr.asm
Assembling: szcmp.asm
Assembling: szcmpi.asm
Assembling: szcopy.asm
Assembling: szleft.asm
Assembling: szlen.asm
Assembling: szlower.asm
Assembling: szltrim.asm
Assembling: szmid.asm
Assembling: szmonosp.asm
Assembling: szmulcat.asm
Assembling: szremove.asm
Assembling: szreplac.asm
Assembling: szrev.asm
Assembling: szright.asm
Assembling: szrtrim.asm
Assembling: sztrim.asm
Assembling: szupper.asm
Assembling: szwcnt.asm
Microsoft (R) Library Manager Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

--------------
build seems OK
--------------
Volume in drive K is disk3_k
Volume Serial Number is 68C7-4DBB

Directory of K:\asm32\makelib

11/10/2018  06:01 AM             9,020 testlib.lib
               1 File(s)          9,020 bytes
               0 Dir(s)  723,128,303,616 bytes free
Press any key to continue . . .

physix

@jj2007 and @hutch - Thank you very much for your help!

As jj2007 said Visual Studio is the problem here. It is so frustrating to have a issue because of the 'modern' IDE, oh my. I created the object file and linked it manually and voilá it compiles and it is working! :-)


ml.exe > ml.exe /c /coff "<PATH_TO_ILE>"
link.exe > link.exe /SUBSYSTEM:CONSOLE <NAME_OF_FILE>.obj


I am using the latest ml.exe and link.exe from visual studio, it is very funny that it is working manually but not in the IDE.

So I may prefer to use Notepad++ and a small bat - which I will create for myself - to code in masm.

For other people the code which compiles and suits me - and my problem lol - perfect( thank you @jj2007 ):

Main.asm

.386

.model flat, stdcall

option casemap:none

include C:\masm32_x86\include\masm32rt.inc

.data

include Functions.asm

.code

main proc

call HelloWorld

invoke ExitProcess, 1

main endp

end main


Functions.asm

include C:\masm32_x86\include\masm32rt.inc

.code
HelloWorld proc
invoke MessageBoxA, 0, 0, 0, 0
ret
HelloWorld endp



I know the include is duplicated here. ^^ May I ask you @jj2007 for what the segment code was? To check if the current segment is the data segment?

I wish everyone a nice day! :D

Regards, Physix.

hutch--

If you want to use later instructions, replace the .386 with this


    .686p                           ; create 32 bit code
    .mmx
    .xmm
    .model flat, stdcall            ; 32 bit memory model
    option casemap :none            ; case sensitive


physix

Thank you hutch!

I am not using SSE/ SIMD at the moment, I am fine with usage of the fpu. ^^
But any help is very appreciated.

Regards, Physix.

jj2007

Quote from: physix on October 11, 2018, 06:52:42 AMMay I ask you @jj2007 for what the segment code was? To check if the current segment is the data segment?

You wanted a "function" (a proc) that you could just insert somewhere. The @CurSeg macro generates a string describing the current segment. The string gets stored:
% ThisSeg equ <@CurSeg>   ; preceded by % to force expansion

... and after the inserted proc .. endp, we restore the current segment using ThisSeq. As shown in the example above, with this trick you can insert the file even in the .data segment.

Glad to see that it finally worked - welcome to the forum  :icon14:

physix

Oh well, that was a overkill but thank you very much! I was to unclear, it should be a function which can be in every file included and usable and not anywhere in the file includable but this was my fault, excuse my not so decent english in this situation. ^^

Also thank you for your welcome, I am in love with asm and specially with masm. So I maybe annoy you in the future with a question or two but I do my best to solve everything myself. :)

Regards, Physix.

Caché GB

Hi physix
Welcome to the forum.

This:
include Functions.asm
is nonsense, wait until you have to include "Functions.asm" in another module file in the same project.

I don't know about VS18, still stuck on 15 (If it ant broken). So you have only one "MAIN" Module File
which you have added to your project, it looks like this:


TITLE Main.asm By Caché GB

.686p
.xmm
.model flat, stdcall
option casemap:none
option scoped
option dotname
option proc:private


ifndef _UNICODE_
       _UNICODE_ equ 1
endif

include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib


include MyModule.inc


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

.const

      ID_XXX01                 equ  12345
      ID_XXX02                 equ  12346

.data

      MyString                 db  "I know what you did last summer", 0
      MsgBoxTitle              db  "From Main.asm .................", 0

.data?

      hInst                    dd ?

.code
;#############################################################################################################
;#############################################################################################################

EntryPoint:

       FNINIT
       invoke  GetModuleHandle, 0h
          mov  hInst, eax
       invoke  GetCommandLine
       invoke  wWinMain, hInst, 0h, eax, SW_NORMAL
       invoke  ExitProcess, 0

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

wWinMain proc hInstance:dword, hPrevInst:dword, CmdLine:ptr word, CmdShow:dword ; proto in windows.inc

   local TheStringsLen:dword


       invoke  MessageBoxA, null, addr MyString, addr MsgBoxTitle, MB_OK

       invoke  HelloWorld

       invoke  lszLen, addr MyString
          mov  TheStringsLen, eax

          ret

wWinMain endp

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

end EntryPoint

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


Now you add the following Module File (MyModule.asm) to your project :

Solution Explorer => On Project Name right-click => select Add > Existing Item.
Navigate to the File MyModule.asm and select it. Click Add.
It looks like this:


TITLE MyModule.asm By Caché GB


.686p
.xmm
.model flat, stdcall
option casemap:none
option scoped
option dotname
;; option proc:private

ifndef _UNICODE_
       _UNICODE_ equ 1
endif

include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib

.LIST
;#############################################################################################################

.const

      ID_XXX01                 equ  12345
      ID_XXX02                 equ  12346

.data

      MyDword                  dd  54321

      MyString                 db  "In HelloWorld function ....", 0
      MsgBoxTitle              db  "From MyModule.asm .........", 0

.data?

      ThePTR                   dd ?

.code
;#############################################################################################################
;#############################################################################################################

HelloWorld proc

       invoke  MessageBoxA, null, addr MyString, addr MsgBoxTitle, MB_OK

          mov  eax, 1
          ret

HelloWorld endp

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

lszLen proc pString:ptr byte

          mov  eax, dword ptr[pString]   
          lea  ecx, [eax+1]
     @@:
          mov   dl, byte ptr[eax] 
          add  eax, 1
         test   dl, dl 
          jne  @B
          sub  eax, ecx
          ret

lszLen endp

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

END ; MyModule.asm

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


Now you need the Include File (MyModule.inc).


.XCREF
.NOLIST

IFNDEF _MYMODULE_INC_
       _MYMODULE_INC_ EQU 1


TITLE  MyModule.inc By Caché GB

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

       HelloWorld            proto

       lszLen                proto  pString:ptr byte


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

ENDIF ; _MYMODULE_INC_

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


Place MyModule.inc  in a folder called " Includes". This folder "should" reside in the project's root.
Then right-click on the project in the Solution Explorer and select Properties.
"Configuration Properties->Microsoft Macro Assembler->General=>Include Paths->Edit..
Past this line:
$(SolutionDir)Includes
Click OK. Click Apply.
That's it you good to go.
Caché GB's 1 and 0-nly language:MASM

physix

@Caché GB Wow! This was exactly the solution I searched for. It works with VS 17 perfect.. Thank you very much, you have a very nice 'style'! I need to read more about some defines etc but this is the best and comfortable solution! Now I can debug easily with vs and code, thank you again!

Am I missing something or why is it extremly difficult to find something about this problem online? I found nothing which was so 'clear' and understandable like your example on the internet.   :bgrin:

I wish everyone here a nice day and thank you very much for your help! I am now satisfied and able to code calm my memory management in masm.  :biggrin:

Regards, Physix.