One assembler, many targets: Windows on Intel and ARM, DOS, ARM Linux and the Raspberry Pi Pico.
Three lines at the start of a source file say what a program is for: .format (the kind of file), .arch (the instruction set) and, for a board, .target. They also decide where the debugger starts the program: on this computer, in a helper process, on a second computer, in QEMU or on the board behind a debug probe. Under Debug > Debug targets you set this up once per target.
| Target | Source | Result | Runs and is debugged | Dismonite |
|---|---|---|---|---|
| Windows, Intel 32 bit | .format pe.arch i386 | PE32 (.exe) | on this computer | disassemble, debug |
| Windows, Intel 64 bit | .format pe.arch x64 | PE32+ (.exe) | on this computer through the helper process asmodbgx64 | disassemble, debug |
| Windows on ARM, 32 bit | .format pe.arch thumb | PE32, Thumb-2 | on a Windows on ARM computer (debug server asmodbg) | disassemble, debug |
| Windows on ARM, 64 bit | .format pe.arch arm64 | PE32+, AArch64 | on a Windows on ARM computer (debug server asmodbg64) | disassemble, debug |
| DOS | .format binary.arch x86_real | .COM or .EXE (MZ) | in QEMU with FreeDOS | disassemble (MZ), debug |
| ARM Linux | – | ELF (from other tools) | in QEMU (Raspberry Pi OS) | disassemble, debug |
| Raspberry Pi Pico | .target pico.arch thumb | binary, UF2 | on the board over a debug probe | – |
| Raspberry Pi Pico 2 | .target pico2.arch thumb or riscv32 | binary, UF2 | on the board over a debug probe | – |
With .format pe the assembler writes a finished Windows file: DOS stub, PE header, sections and import table. The source holds only code (.code), data (.data) and the functions it needs from DLLs (.import). No linker is needed.
| 32 bit | 64 bit | |
|---|---|---|
| Intel | .arch i386: PE32, machine 0x014C; arguments on the stack (stdcall, cdecl) | .arch x64: PE32+, machine 0x8664; arguments in rcx, rdx, r8, r9 |
| ARM | .arch thumb: PE32, machine 0x01C4 (ARMNT, Thumb-2); arguments in r0…r3 | .arch arm64: PE32+, machine 0xAA64; arguments in x0…x7 |
examples\windows_intel\hello_i386.asm).format pe console .arch i386 .import msvcrt.dll printf, exit .code start: push dword msg ; the argument on the stack call [printf] ; through the import table add esp, 4 ; printf does not clean up push 0 call [exit] .data msg db 'Hello, World!', 10, 0
examples\windows_intel\hello_x64.asm).format pe console .arch x64 .import msvcrt.dll printf, exit .code start: sub rsp, 40 ; shadow space, stack aligned lea rcx, [msg] ; first argument in rcx call [printf] xor ecx, ecx call [exit] .data msg db 'Hello, World!', 10, 0
The same for ARM, with an explanation, is on the page Windows on ARM. .format pe gui makes a window program instead of a console program (messagebox_*.asm, window_*.asm).
Debugging. Asmonite debugs a 32-bit Intel program itself, on this computer. An x64 program runs under the helper process asmodbgx64, because Asmonite itself is a 32-bit program; this too happens on this computer (or on another one with the same debug server). ARM programs run on a Windows on ARM computer with the debug server asmodbg or asmodbg64, connected over ssh or directly on the network; on the ARM computer itself also locally. Before each start Asmonite checks the file it made: header, sections, entry point and whether the imported DLLs and functions really exist.
With .format binary and .arch x86_real Asmonite writes 16-bit code for real mode, byte by byte as it stands in the source.
.COM | No header, only code. DOS loads the file at offset 0x100 of a segment; section 0x100 counts the labels from there. Code, data and stack share 64 KB. Example examples\dos\hello_com.asm. |
.EXE (MZ) | The MZ header is in the source, written with dw: size, memory needed, start (CS:IP) and stack (SS:SP); several segments with segment. Example examples\dos\hello_exe.asm, with every field explained. |
Debugging. F9 puts the program on a hard disk image and starts QEMU with FreeDOS; the helper dbgload.com loads it there, and the debugger stops at the first line. Breakpoints, steps, registers and memory work as for Windows programs; a second run needs no new boot. qemu\run_freedos.bat gets the FreeDOS floppy once, QEMU itself is set up with qemu\install_qemu.bat. Dismonite opens finished DOS programs (MZ), finds code, data, jump tables and the end of the program and lets you mark regions by hand.
This target belongs to Dismonite: it reads ELF files for 32-bit ARM, as GCC or another compiler makes them on Linux, and debugs them in a Raspberry Pi OS that runs in QEMU.
qemu\run_buster.bat starts the guest system; the debugger reaches it over ssh and gdbserver, copies the program into it and stops at the entry point. If the guest is not running, Dismonite asks whether to start it.With .target pico (RP2040, Cortex-M0+) or .target pico2 (RP2350, Cortex-M33 or RISC-V Hazard3) Asmonite writes the bytes for the board and checks them: the allowed instructions, RAM and flash, the boot2 block on the Pico, the IMAGE_DEF block on the Pico 2. F7 puts the program into the RAM or the flash over a CMSIS-DAP debug probe and stops at _start, without OpenOCD and without an SDK. Without a probe it goes onto the BOOTSEL drive as a UF2 file.