Hi,
I have this code:
option casemap:none
includelib user32.lib
includelib kernel32.lib
ExitProcess PROTO :DWORD
MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD
.data
title db "Hello!", 0
message db "This is raw assembly!", 0
.code
start:
invoke MessageBoxA, NULL, offset message, offset title, MB_OK
invoke ExitProcess, 0
end start
and I try compiling it with:
Quotecc test.asm
It gives me test.obj, but doesn't link it into a binary, despite me not providing the /a option. What gives?
Hi Quin,
Kindly, instead of cc, can you use Poasm allowing to set the specific options? That is much more easy.
I modified your code as some equates were missing :
Batch file to build the project :
\Pellesc\bin\poasm /AIA32 Test.asm
\Pellesc\bin\polink /SUBSYSTEM:WINDOWS /LIBPATH:\Pellesc\Lib\Win Test.obj
The updated source code :
[code].386
.model flat,stdcall
option casemap:none
includelib user32.lib
includelib kernel32.lib
ExitProcess PROTO :DWORD
MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD
MB_OK equ 0
NULL equ 0
.data
title db "Hello!", 0
message db "This is raw assembly!", 0
.code
start:
invoke MessageBoxA,NULL,ADDR message,ADDR title,MB_OK
invoke ExitProcess, 0
END start
About preferring ADDR instead of OFFSET while invoking functions :
QuoteAn OFFSET in MASM is a location (literally an OFFSET) from the front of the file where an address using the keyword ADDR can be either a stack local OR an OFFSET. ADDR is usually restricted to higher level INVOKE syntax.
https://masm32.com/board/index.php?msg=53727
VOrtex,
You're the man! This fully works!
What if I want to compile as x64 though? I assume I don't need .386 or .model flat, stdcall, but when removing /AIA32 and those two lines and recompiling with the win64 lib folder, the binary is generated, but instantly crashes. Is this mostly meant for generating 32-bit code, or do I just have some mismatched protos (e.g. DWORD instead of QWORD or similar)?
It is raw assembly so maybe 32-bit is just easier/better, but I enjoy having all the memory available to me :D
Hi Quin,
The calling convention of 64-asm is different, it's the 64-bit fastcall convention : the first four parameters passed to rcx,rdx,r8 and r9. The following ones are passed to the stack. Also, the stack alignment is very strict, it must be always 16-bit.
Here is the example code :
MessageBoxA PROTO :QWORD,:QWORD,:QWORD,:QWORD
MessageBox EQU <MessageBoxA>
ExitProcess PROTO :QWORD
MB_OK equ 0
NULL equ 0
.data
msg db 'Hello!',0
title db 'MsgBox',0
.code
main PROC PARMAREA=4*SIZEOF QWORD
invoke MessageBox,NULL,ADDR msg,ADDR title,MB_OK
invoke ExitProcess,0
main ENDP
END
Poasm takes care of the stack alignment.
Batch file to build the project :
\PellesC\bin\poasm /AAMD64 Hello.asm
\PellesC\bin\polink /SUBSYSTEM:WINDOWS /LIBPATH:\PellesC\Lib\Win64 /ENTRY:main Hello.obj kernel32.lib user32.lib
About PARMAREA :
QuoteThe optional PARMAREA = expression specifies the size of the parameter area. It must be specified if the procedure is calling other procedures, and must be the size of the largest parameter area passed to any procedure. It can be larger (will just waste space), but it may not be smaller. The expression must be a constant expression.
A nice introduction to x64 Assembly :
https://www.codeproject.com/Articles/17263/Moving-to-Windows-Vista-x64
Hi Vortex,
Ah, I see! The woes of Assembly programming, I suppose :D
Doable for sure, but I can now see why you prefer /AIA32. Much cleaner
Thanks for your help!
Hi Quin,
With thanks to Pelle, Poasm makes easier 64-bit assembly coding. The assembler handles all the stack organization including alignment to 16 bytes.
Hi Vortex,
Yes, I saw that topic. Very cool stuff! I love this toolchain :)