Site banner

Using Win32 in NASM with MinGW

(Alternatively, how to link assembly code to Win32 on Windows without MSVC)

Preface

This was something tricky I figured out a while ago that doesn't have any good resources online. This writing is pretty messy at the moment and I should clean it up, but better to have it up messy than to not have it at all.

This guide also assumes you already have basic familiarity with using NASM and MinGW.


Include the Win32 functions you want to import like this at the top of your assembly file:

extern _ExitProcess@4
extern _GetStdHandle@4
extern _CreateFileA@28

And so on. The number after the @ is the total size of the arguments in bytes.

Then to use this function in the assembly, just call it with the same name:

push dword 0x16000
push ebx
push eax
call _HeapAlloc@12

(If you're unfamiliar with Win32 calling conventions, you just push the arguments starting with the last. Return value is put in eax. Look at Microsoft's documentation for specifics for each function.)

You also will need to put a `_main:` in your assembly at the start of your code, along with a global declaration:

SECTION .text
global _main
_main:
	; start of code here

NOTE: If you want to write a .dll, you need to have a export main line too.

To actually link the code, first create an object file through NASM:

nasm.exe -fwin32 example.s

Then link the object using MinGW.

NOTE: -fwin32 outputs a 32-bit object file, so you will have to use the 32-bit version of MinGW. This also means the output executable will be 32-bit.

gcc.exe example.obj -o example.exe

I haven't tried 64-bit assembling/linking yet, but if I had to guess it's just using -fwin64 in nasm and 64-bit MinGW. Also have not tried linking multiple .objs yet. I'd guess it's just assembling the individual sources then listing all of them in the linking step.

Other Resources

This was what I learned from, but it's pretty long and doesn't cover MinGW: https://bitcodersblog.wordpress.com/2017/05/10/win32-in-nasm-part-1/