Pure x64 Microsoft Macro Assembler & Vulkan Game Engine to explore Assembly Programming.
- Visual Studio 2022 for
ml64.exe&link.exe - Vulkan SDK 1.4.313.0 for the
vulkan-1.lib
- Unofficial MASM64 SDK
.asmfound inextern\masm64 - Assembler compatible Vulkan headers found in
extern\vulkan
Warning
You must add copy the masm64 folder from extern\masm64 to C:\
- Launch
x64 Native Tools Command Prompt for VS 2022 - Run
scripts\build.bat - Run
build\main.exeordevenv build\main.exe
- MASM64 based Arena Allocator (saha.asm)
- Translated Vulkan C headers to MASM64 (using
tools\vulkan_gen.bat)
Not using the CRT at all, just pure Assembler + Win32 + Vulkan.
I don't need the full SDK so I just took the .asm files and placed them in my project.
They are hard coded to be in the C:\ root so maybe this can be fixed later.
I'm using 1.4.313.0 but it should be upgradable using vulkan-extractor.py.
I went ahead and made a Unity/Jumbo build:
- Everything is included inside
main.asm - Only assembing
main.asmis required - Modules have header guards
- Modules are used to fake private but everything is global
- Variables/Functions dumped in main are intended to be specifically global
- The MASM64 SDK comes with an
invokemacro that automates the Windows x64 calling convention - Example:
void Proc(&handle, count, NULL);->invoke Proc, ADDR handle, count, 0 - In case of stack usage, stack MUST be aligned to
0x10or 16 so make sureRSPends with a0before calling a Windows or Vulkan function. - I noticed that the
invokemacro doesn't take care of the shadow space allocation so you have tosub rsp, 32thenadd rsp, 32before a function call or else crash. This is especially true if you have to call some Windows/Vulkan function multiple times in a row such as printing otherwise its fine.
- I divided each vulkan step into its own module with each module having its own variables as I did not do any stack allocation.
- Modules look like this:
ModuleDrawFrame.asmand insideDrawFrame_render_infofor vars andDrawFrame_Executefor procs. - Everything is zeroed out since everything is allocated in the
.datasection but I don't zero anything manually which might be dangerous. - Look at
ModuleTemplate.asm
- Get the Vulkan triangle
- Fix
saha.asmarena macro - Create an arena allocator for permanent storage
- Create modules for the rest of the vulkan code
- Clean up
vulkan-extractor.py - Play with SIMD and game logic
You can regenerate the vulkan headers using python + libclang by invoking the ugly vulkan_gen.bat file from the tools directory. The generated headers are almost perfect except for a few bugs which I fixed manually. Will fully automate the process.
| 64 | 32 | 16 | 8 | name |
|---|---|---|---|---|
| rax | eax | ax | ah/al | accumulator |
| rbx | ebx | bx | bh/bl | base |
| rcx | ecx | cx | ch/cl | counter |
| rdx | edx | dx | dh/dl | data |
| rsi | esi | si | sil | source_idx |
| rdi | edi | di | dil | destination_idx |
| rbp | ebp | bp | bpl | base_pointer |
| rsp | esp | sp | spl | stack_pointer |
| r8 | r8d | r8w | r8b | general_purpose |
| r9 | r9d | r9w | r9b | general_purpose |
| r10 | r10d | r10w | r10b | general_purpose |
| r11 | r11d | r11w | r11b | general_purpose |
| r12 | r12d | r12w | r12b | general_purpose |
| r13 | r13d | r13w | r13b | general_purpose |
| r14 | r14d | r14w | r14b | general_purpose |
| r15 | r15d | r15w | r15b | general_purpose |
| Type | Registers | Responsibility |
|---|---|---|
| Volatile | rax, rcx, rdx, r8, r9, r10, r11, rsp, xmm0–xmm5 | Caller must save |
| Non-Volatile | rbx, rbp, rsi, rdi, r12, r13, r14, r15, xmm6–xmm15 | Callee must save/restore |
If you are new to x86-64 Assembly I suggest:
