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.
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.
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
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:
(https://gyazo.com/e588eada807ba23dd8f96a81f8dc0c38.png)
@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..
(https://gyazo.com/eecac3c6dd478f0c8f0e4516e71d834a.png)
Kind of strange that 'end' is really needed here because I don't need a entrypoint right?
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.
> 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
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 (http://masm32.com/board/index.php?topic=5314.0), 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.
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 . . .
@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.
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
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.
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:
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.
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 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.