Windows Assembly Toolchain: The Native MASM Guide
Set up the Windows native assembly toolchain with Visual Studio. Learn ml64.exe (MASM) for x64 and armasm64.exe for ARM64, plus key syntax differences from GNU tools.
Windows assembly development requires the native Microsoft toolchain—Windows does NOT include GNU tools like as and ld by default. This guide covers the essential tools you need to start writing low-level code using MASM (ml64.exe) for x64 and armasm64.exe for ARM64 architectures.
Unlike Unix-like systems where GNU assembler is standard, Microsoft provides completely different tools distributed through Visual Studio. Whether you’re doing kernel development or security research, understanding these tools is essential.
Default Tools via Visual Studio
The toolchain consists of assemblers and linkers provided by Microsoft. These tools produce PE (Portable Executable) format binaries.
For x64 (AMD64):
ml64.exe— Microsoft Macro Assembler (MASM) for 64-bit x64 development.link.exe— Microsoft Linker that creates executables from object files.
For ARM64 (AArch64):
armasm64.exe— Microsoft ARM64 Assembler for ARM-based systems like Surface Pro X.link.exe— Microsoft Linker (same tool, targeting ARM64).
Where to get the tools?
- Download Visual Studio 2019/2022 (Community edition is free)
- Select “Desktop development with C++” workload
- For ARM64: Also install “MSVC v143 - VS 2022 C++ ARM64 build tools”
Toolchain Comparison: MASM vs GNU
Understanding the differences between MASM and GNU assembler is crucial for cross-platform developers.
| Feature | MASM (ml64) | GNU (as/ld) |
|---|---|---|
| Assembler | ml64.exe | as |
| Linker | link.exe | ld |
| Syntax | Intel | AT&T (default) |
| Object Format | COFF/PE | ELF |
Basic Differences
MASM differs from GAS not just in syntax, but in its fundamental approach to directives and macro expansion. For instance, MASM is case-insensitive by default for instructions but case-sensitive for certain symbols if configured.
; MASM Syntax
mov rax, [rbp + 16] ; Source is on the right
push rbp
mov rbp, rsp
# GAS Syntax (AT&T)
movq 16(%rbp), %rax # Source is on the left
pushq %rbp
movq %rsp, %rbp Key Syntax Differences
| Aspect | MASM | GNU AS |
|---|---|---|
| Register | rax | %rax |
| Immediate | mov rax, 5 | movq $5, %rax |
| Operand order | dest, src | src, dest |
| Memory | [rax+8] | 8(%rax) |
MASM Directive Comparison
| Feature | MASM64 | GNU AS |
|---|---|---|
| Code section | .code | .text |
| Data section | .data | .data |
| External | EXTERN | .extern |
| Public | PUBLIC | .global |
| Procedure | PROC/ENDP | Labels only |
Key Takeaways
The Microsoft toolchain takes a distinctly different approach. While GNU tools use AT&T syntax by default, MASM uses Intel syntax which many find more readable.
- Use Developer Command Prompt to ensure tools are in your PATH.
- MASM uses Intel syntax while GNU uses AT&T.
- PE/COFF format instead of ELF.
- armasm64.exe for ARM64 targets.
For calling conventions, see my Calling Conventions guide. Ready to code? Check out my Hello World tutorial.