I am currently learning assembly language for a custom compiler project. However, i wasn't able to make a single working assembly program. I have an AMD CPU with a 64 bit operating system and a x64 based processor. I am using Windows 11.
I don't want to use c libraries as it kind of destroys the purpose of coding as low level as possible which is my objective.
I already tried a lot of different programs and linkers.
Assembly Syscalls in 64-bit Windows This doesn't contain any working code.
Hello world using nasm in windows assembly I think this is for 32 bit systems, but i don't know what i need to change. I changed "eax" to "rax" and this compiled and run but didn't print anything. I was also able to add random letters to thecode without any errors and still an exit code of 0. (Just one GoLink warning)
Setting Exit Status in NASM for Windows Same problem here. I always get an exit code of one and the compiler doesn't care about any syntax errors.
I also tried using gcc and ld without success.
What am i doing wrong?
Edit I tried this: How to write hello world in assembly under Windows? but link.exe seems to be only for visual studio (i am using vscode). When i use GoLink, i get the following error:
Error!
The following symbol was not defined in the object file or files:-
MessageBoxA
Output file not made
Edit 2 When im using gcc, i get the following error:
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-
mingw32/13.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
out.obj:out.asm:(.text+0x1e): undefined reference to `MessageBoxA'
collect2.exe: error: ld returned 1 exit status
If i remove the message printing code, it works fine and i finally get an exit code of my choice! Is the MessageBoxA function in another library or something? How can i fix this?
Edit 3 I found this code and copied it, but again, it doesn't work. (editor's note: it's 32-bit code for the 32-bit calling convention.)
global _main
extern GetStdHandle
extern WriteFile
extern ExitProcess
section .text
_main:
; DWORD bytes;
mov ebp, esp
sub esp, 4
; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
push -11
call GetStdHandle
mov ebx, eax
; WriteFile( hstdOut, message, length(message), &bytes, 0);
push 0
lea eax, [ebp-4]
push rax
push (message_end - message)
push message ; ERROR
push rbx
call WriteFile
; ExitProcess(0)
xor rcx, rcx
call ExitProcess
; never here
hlt
message: db "Hello, World", 8
message_end:
When i run this with the following command:
nasm -f win64 out.asm && gcc -o out.exe out.obj -nostdlib -lkernel32
... i get a truncation error (idk what that means)
out.obj:out.asm:(.text+0x18): relocation truncated to fit:
IMAGE_REL_AMD64_ADDR32 against `.text'
collect2.exe: error: ld returned 1 exit status
I am a bit irritated why it's so hard to execut such a simple program. I just need a hello world program for nasm, x64_64 windows with visual studio code and without c librarys.
link.exe
. I don't know about Windows linkers.push message ; ERROR
is trying to use a symbol address as a 32-bit immediate.lea
the address into a register and push that, likegcc -fPIE
would do. (Linux PIE has similar requirements to Windows LargeAddressAware executables, that any absolute addresses have to be 64-bit, but preferably you use only relative addressing so ASLR to anywhere in virtual address space (including outside the low 32 bits) doesn't even take any runtime fixups, especially not in read-only pages like .text.) 32-bit absolute addresses no longer allowed in x86-64 Linux?MessageBoxA
example. Oh, butGetStdHandle
andWriteFile
are defined inkernel32.dll
, vs.MessageBoxA
inuser32.dll
, according to learn.microsoft.com/en-us/windows/win32/api/winuser/… and learn.microsoft.com/en-us/windows/console/getstdhandle. Anyway, a google search forsite:stackoverflow.com windows x64 assembly getstdhandle
found Jester's answer on How To Properly call 64 Bit Windows API In Assembly as the third hit for me. I fixed one remaining bug with an edit.