Es gibt zwei Arbeitsweisen: #ASM-Blöcke innerhalb von BASIC und eigenständige .asm-Quelldateien. Das erste Beispiel nutzt einen BASIC-Rahmen; die weiteren Beispiele den separaten ASM-Eingang.
Es gibt zwei Arbeitsweisen: #ASM-Blöcke innerhalb von BASIC und eigenständige .asm-Quelldateien. Das erste Beispiel nutzt einen BASIC-Rahmen; die weiteren Beispiele den separaten ASM-Eingang. Grafik in voller Größe öffnen

ASM: Beispiele und Erklärung

Es gibt zwei Arbeitsweisen: #ASM-Blöcke innerhalb von BASIC und eigenständige .asm-Quelldateien. Das erste Beispiel nutzt einen BASIC-Rahmen; die weiteren Beispiele den separaten ASM-Eingang.

Zwölf Kurzbeispiele und ein größeres Programm. Wählen Sie ein Thema oder arbeiten Sie die Beispiele der Reihe nach durch.

1. 1 + 2 + 3 + 4 + 5 = 15

Die Zahlen 1 bis 5 werden zu 15 addiert. Der Rückgabewert 15 wird als Prozess-Exitcode geprüft.

FUNCTION PBMAIN() AS LONG
    LOCAL sum AS LONG
    #ASM
        xor eax, eax      ; sum = 0
        mov ecx, 5        ; counter = 5
    add_loop:
        add eax, ecx      ; sum += counter
        dec ecx           ; counter--
        jnz add_loop      ; loop until 0
        mov %sum, eax     ; store result
    #ENDASM
    FUNCTION = sum        ' = 15
END FUNCTION

Erwarteter Exitcode: 15

PBXB64.exe sum15-asm.pb -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Nativ geprüft mit dem V22-Kandidaten vom 30.09.2026; Prüfung mit dem finalen Compiler noch ausstehend.

2. Eigenständiges ASM: EAX als Ergebnis

global main markiert den Einstieg. mov eax, 42 setzt das Ergebnisregister; ret kehrt zurück. Das ist eine .asm-Datei und kein eingebetteter #ASM-Block.

// Test: Basic ASM syntax and compilation
section .data
    msg db "Test", 0

text section .text
global main

main:
    mov eax, 42
    ret

Erwarteter Exitcode: 42

PBXB64.exe test_basic_asm.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Kanonischer Testfall mit erwartetem Ergebnis; hier keine neue native V22-Prüfung. Finale Ausführung noch ausstehend.

3. Einen Wert aus der Datensektion laden

value dd 123 legt einen 32-Bit-Wert an. mov eax, [value] liest diesen Speicherwert, während mov eax, 123 eine unmittelbare Zahl verwenden würde. Der erwartete Exitcode ist 123.

// Test: ASM data sections and global symbols
section .data
    value dd 123
    msg db "Hello", 0

text section .text
global main

main:
    mov eax, [value]
    ret

Erwarteter Exitcode: 123

PBXB64.exe test_data_sections.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Kanonischer Testfall mit erwartetem Ergebnis; hier keine neue native V22-Prüfung. Finale Ausführung noch ausstehend.

4. Makroparameter und Wiederholung beim Assemblieren

Ablauf Schritt für Schritt

  1. MAGIC ist die Konstante 40; SETEAX setzt eax auf diesen Wert.
  2. .rep 4 vervielfacht die add-Anweisung bereits beim Assemblieren: eax wird 44.
  3. Das parametrisierte ADDI32 zieht 2 ab. PROLOG und leave bilden den Rahmen für den Rückgabewert 42.
// Wave-6 slice 6-assembler: macro assembler (.macro/.endm with params,
// .equ equates, .rep/.endr repeat) — asm_macro.c port
// Expected exit code: 42
.equ MAGIC, 40

.macro PROLOG
    push rbp
    mov rbp, rsp
.endm

.macro SETEAX val
    mov eax, \val
.endm

.macro ADDI32 reg, amount
    add \reg, \amount
.endm

section .text
global main
main:
    PROLOG
    SETEAX MAGIC
    .rep 4
    add eax, 1
    .endr
    ADDI32 eax, -2
    leave
    ret

Erwarteter Exitcode: 42

PBXB64.exe asm-w6_macro.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

5. Bedingtes Kopieren mit CMOV

Ablauf Schritt für Schritt

  1. cmp setzt die Flags; cmovl übernimmt 20, weil 10 kleiner als 20 ist.
  2. Beim anschließenden Gleichvergleich unterbleibt cmovne; cmove liest dagegen den DWORD-Wert 7 aus der Daten-Sektion.
  3. 7 + 35 ergibt 42. Die CMOV-Bedingung hängt jeweils vom unmittelbar vorherigen Vergleich ab.
// Wave-6 slice 6-assembler: cmovcc + [rel] data access (encoder expansion group)
// Expected exit code: 42
section .data
seven: dd 7

section .text
global main
main:
    mov eax, 10
    mov ecx, 20
    cmp eax, ecx
    cmovl eax, ecx        ; 10 < 20 -> eax = 20
    cmp eax, ecx
    cmovne eax, dword [rel seven]  ; equal -> no move, eax stays 20
    cmp eax, ecx
    cmove eax, dword [rel seven]   ; equal -> eax = 7
    add eax, 35           ; 7 + 35 = 42
    ret

Erwarteter Exitcode: 42

PBXB64.exe asm-w6_enc_cmovcc.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

6. Zählschleife, Funktionsaufruf und Sprungmarken

Ablauf Schritt für Schritt

  1. loop verringert den Zähler und führt zehn Erhöhungen von eax aus.
  2. call add_seven erhöht 10 auf 17; bei rcx = 0 nimmt jrcxz den nächsten Pfad.
  3. Weitere Additionen von 9 und 16 ergeben 42; falsche Zwischenwerte führen zum Fehlerpfad.
// Wave-6 slice 6-assembler: branch group (loop/loope/loopne, jrcxz/jecxz,
// short jcc, call rel32, jcxz) — encoder expansion group
// Expected exit code: 42
section .text
global main

add_seven:
    add eax, 7
    ret

main:
    xor eax, eax
    ; loop: count down from 10, eax += 1 each time
    mov ecx, 10
count_loop:
    add eax, 1
    loop count_loop        ; 10 iterations -> eax = 10
    cmp eax, 10
    jne fail
    ; call rel32 through a local function
    call add_seven         ; eax = 17
    ; jrcxz: rcx is 0 here -> taken
    jrcxz rcxz_taken
    jmp fail
rcxz_taken:
    add eax, 9             ; eax = 26
    ; short forward jump (rel8)
    cmp eax, 26
    je short_target
    jmp fail
short_target:
    add eax, 16            ; eax = 42
    ret
fail:
    mov eax, 1
    ret

Erwarteter Exitcode: 42

PBXB64.exe asm-w6_enc_branch.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

7. Bytes, String-Endzeichen und UTF-16-Daten

Ablauf Schritt für Schritt

  1. Die Direktiven legen AB ohne Abschluss sowie HI und YO mit Nullabschluss ab; .unicode erzeugt UTF-16LE-Daten.
  2. movzx liest einzelne Bytes ohne Vorzeichenerweiterung; die geprüften Nullbytes tragen 0 zur Summe bei.
  3. 65 + 66 + 77 + 78 ergibt 286. Erst nach diesem Vergleich wird der Erfolgswert 42 zurückgegeben.
// Wave-6 slice 6-assembler: .ascii/.asciz/.string/.unicode directives
// Expected exit code: 42
section .data
a_bytes:  .ascii "AB"        // 2 bytes, no terminator
z_bytes:  .asciz "HI"        // 3 bytes incl NUL
s_bytes:  .string "YO"       // 3 bytes incl NUL
u_bytes:  .unicode "MN"      // UTF-16LE: 4D 00 4E 00 00 00

section .text
global main
main:
    xor ebx, ebx
    movzx eax, byte [rel a_bytes]      ; 'A' = 65
    add ebx, eax
    movzx eax, byte [rel a_bytes+1]    ; 'B' = 66
    add ebx, eax
    movzx eax, byte [rel z_bytes+2]    ; NUL terminator of .asciz
    add ebx, eax                       ; +0
    movzx eax, byte [rel s_bytes+2]    ; NUL terminator of .string
    add ebx, eax                       ; +0
    movzx eax, byte [rel u_bytes]      ; 0x4D = 77 ('M')
    add ebx, eax
    movzx eax, byte [rel u_bytes+1]    ; 0x00 high byte
    add ebx, eax                       ; +0
    movzx eax, byte [rel u_bytes+2]    ; 0x4E = 78 ('N')
    add ebx, eax
    movzx eax, byte [rel u_bytes+4]    ; NUL16 low byte
    add ebx, eax                       ; +0
    ; ebx = 65 + 66 + 77 + 78 = 286
    cmp ebx, 286
    jne fail
    mov eax, 42
    ret
fail:
    mov eax, 1
    ret

Erwarteter Exitcode: 42

PBXB64.exe asm-w6_directives.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

8. Bitpositionen, Bitanzahl und XADD

Ablauf Schritt für Schritt

  1. BTS, BT, BTR und BTC setzen, lesen, löschen und invertieren einzelne Bits; BSF/BSR finden die Position 3.
  2. POPCNT zählt die vier gesetzten Bits von 0xF0; SHRD und SHLD bilden hier jeweils 16.
  3. XADD macht aus 2 und 3 die Werte 5 und 2. Die folgenden Additionen ergeben 42; dieses Programm setzt eine CPU mit POPCNT voraus.
// Wave-6 slice 6-assembler: bit-manipulation group (bt/bts/btr/btc, bsf/bsr,
// popcnt, shld/shrd, xadd) — encoder expansion group
// Expected exit code: 42
section .text
global main
main:
    xor eax, eax
    bts rax, 5            ; rax = 32
    bt rax, 5             ; CF = 1
    setc cl               ; cl = 1
    btr rax, 5            ; rax = 0, CF = 1
    btc rax, 3            ; rax = 8
    bsf rdx, rax          ; rdx = 3 (index of lowest set bit)
    bsr rdx, rax          ; rdx = 3 (index of highest set bit)
    mov r8, 0xF0
    popcnt r9, r8         ; r9 = 4
    ; shrd dest, src, n: dest = (dest >> n) | (src << (64-n))
    mov r10, 0
    mov r11, 1
    shrd r10, r11, 60     ; r10 = 0 | (1 << 4) = 16
    ; shld dest, src, n: dest = (dest << n) | (src >> (64-n))
    mov r14, 1
    xor r15, r15
    shld r14, r15, 4      ; r14 = 16 | 0 = 16
    cmp r14, 16
    jne fail
    mov r12, 2
    mov r13, 3
    xadd r12, r13         ; r12 = 5, r13 = 2
    add eax, edx          ; 8 + 3 = 11
    add eax, r9d          ; 15
    add eax, r10d         ; 31
    add eax, r12d         ; 36
    add eax, r13d         ; 38
    movzx ecx, cl         ; ecx = 1 (from setc cl)
    add eax, ecx          ; 39
    add eax, 3            ; 42
    ret
fail:
    mov eax, 1
    ret

Erwarteter Exitcode: 42

PBXB64.exe asm-w6_enc_bitops.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

9. Fünf Argumente nach Win64-Konvention

Ablauf Schritt für Schritt

  1. INVOKE übergibt die ersten vier Integerargumente über ecx, edx, r8d und r9d.
  2. Das fünfte Argument wird im aufgerufenen Code an [rsp + 40] geprüft.
  3. main reserviert 40 Byte und gibt sie nach dem Aufruf wieder frei; check_args liefert 42 bei den erwarteten Werten.
; Help-backed INVOKE contract: Win64 register and stack argument placement.
section .text
global main

check_args:
    cmp ecx, 1
    jne fail
    cmp edx, 2
    jne fail
    cmp r8d, 3
    jne fail
    cmp r9d, 4
    jne fail
    cmp dword [rsp + 40], 5
    jne fail
    mov eax, 42
    ret
fail:
    mov eax, 1
    ret

main:
    sub rsp, 40
    invoke check_args, 1, 2, 3, 4, 5
    add rsp, 40
    ret

Erwarteter Exitcode: 42

PBXB64.exe asm-w7_invoke_abi.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

10. GAS-Direktiven mit Intel-Operanden

Ablauf Schritt für Schritt

  1. .intel_syntax noprefix verbindet Intel-Operanden mit GAS-Direktiven und COFF-Symbolangaben.
  2. Die vier RIP-relativen Bytezugriffe lesen 65, 66, 77 und 78; die Summe muss 286 sein.
  3. Ein Semikolon trennt mov eax, 40 und add eax, 2. Der resultierende Exitcode ist 42.
.intel_syntax noprefix
/* Wave-9 GAS Intel-syntax acceptance contract for the runtime .S closure
   work: block comments, ';' statement separators, the COFF symbol
   definition family, and quoted .section flags. The same file assembles
   under host GNU as, so the script lane compares emitted COFF symbol
   records against the host reference. Expected exit code: 42. */

.section .rdata,"dr"
table_bytes: .byte 65, 66, 77, 78

.text
.globl main
.def main; .scl 2; .type 32; .endef
main:
    xor ebx, ebx
    movzx eax, byte ptr [rip+table_bytes]
    add ebx, eax
    movzx eax, byte ptr [rip+table_bytes+1]
    add ebx, eax
    movzx eax, byte ptr [rip+table_bytes+2]
    add ebx, eax
    movzx eax, byte ptr [rip+table_bytes+3]
    add ebx, eax
    # 65 + 66 + 77 + 78 = 286
    cmp ebx, 286
    jne fail
    mov eax, 40; add eax, 2
    ret
fail:
    mov eax, 1; ret

Erwarteter Exitcode: 42

PBXB64.exe asm-w9_gas_intel_syntax.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

11. Zu einer anderen Stelle derselben Code-Sektion springen

Ablauf Schritt für Schritt

  1. jmp verweist auf target, obwohl zwischen den beiden Textabschnitten eine Daten-Sektion steht.
  2. Das Datenbyte gehört zu .data und wird nicht als Code ausgeführt.
  3. Nach der Rückkehr zu .text setzt target eax auf 48 und beendet das Programm.
.intel_syntax noprefix
/* A branch resumes in .text after intervening .data bytes.  The object
   builder owns the section-relative fixup.  Expected exit code: 48. */
.text
.globl main
main:
    jmp target
.data
.byte 1
.text
target:
    mov eax, 48
    ret

Erwarteter Exitcode: 48

PBXB64.exe asm-w9_interleaved_section_relax.asm -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

12. Die Wirkung eines ASM-Blocks beschreiben

Ablauf Schritt für Schritt

  1. #ASM EFFECTS macht die angegebenen Register-, Flag- und Speicherwirkungen ausdrücklich sichtbar.
  2. STACK PRESERVE und CONTROL FALLTHROUGH beschreiben den erwarteten Ablauf des Blocks.
  3. mov rax, rax verändert den Wert nicht. Die Metadaten werden nicht automatisch zum Beweis für beliebig eingesetzten ASM-Code.
' Explicit ASM EFFECTS metadata is opt-in. Ordinary #ASM remains opaque.
FUNCTION PBMAIN() AS LONG
  #ASM EFFECTS
  READ RAX
  WRITE RAX
  CLOBBER R10
  FLAGS_WRITE ZF, CF
  MEMORY READWRITE
  STACK PRESERVE
  CONTROL FALLTHROUGH
  FEATURES SSE2
  CODE
    mov rax, rax
  #ENDASM
  FUNCTION = 0
END FUNCTION

Erwarteter Exitcode: 0

PBXB64.exe asm-test_inline_asm_effects.pb -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

Großes Beispiel: Zwei ASM-Blöcke mit BASIC-Variablen

Ablauf Schritt für Schritt

  1. {a}, {b} und {c} binden Speicheroperanden an die Adressen lokaler BASIC-Variablen.
  2. Der erste Block berechnet 7 + 100 + 5 = 112 in c; der zweite verdoppelt c zu a = 224.
  3. DWORD-Operationen bearbeiten 32 Bit, QUAD-Zugriffe 64 Bit. Die Werte sind hier positiv und die LONG-Variable war vollständig initialisiert; die BASIC-Prüfung erwartet c = 112, a = 224 und b = 100.
' Wave-1 inline-asm slice: `{ var }` binding plus multi-block temp-name race.
' Two inline asm blocks read and write LOCAL variables via { var }. Each
' bound variable's address is passed in a Win64 argument register (rcx, rdx,
' r8, r9 in order of first appearance within the block) and { var } becomes
' a memory operand on that register. Both blocks are assembled to per-block
' unique temp objects (_inline_asm_0.obj, _inline_asm_1.obj, ...) so neither
' overwrites the other. Expected exit code: 0
FUNCTION PBMAIN() AS LONG
  LOCAL a AS LONG
  LOCAL b AS QUAD
  LOCAL c AS DWORD

  a = 7
  b = 100
  c = 5

  ' Block 1 (#ASM): c = a + b + c = 7 + 100 + 5 = 112
  #ASM
    mov eax, {a}
    add rax, {b}
    add eax, {c}
    mov {c}, eax
  #ENDASM

  ' Block 2 (#ASM): a = c * 2 = 224
  #ASM
    mov eax, {c}
    add eax, eax
    mov {a}, eax
  #ENDASM

  IF c = 112 AND a = 224 AND b = 100 THEN
    PRINT "inline asm binding OK"
    PBMAIN = 0
  ELSE
    PRINT "inline asm binding FAIL: a="; a; " b="; b; " c="; c
    PBMAIN = 1
  END IF
END FUNCTION

Erwarteter Exitcode: 0

Kanonisches Ausgabe-Prüfmuster (Regex)
inline asm binding OK
PBXB64.exe asm-test_inline_asm_binding.pb -O2 -o example.exe
.\example.exe
$LASTEXITCODE

Quelltext herunterladen

Ergebnisvertrag aus tests/validate.toml. Keine neue native Compilerprüfung in dieser Website-Erweiterung. Finale Ausführung mit dem freigegebenen Compiler steht aus.

Alle Quellen dieser Lernseite

Jedes Beispiel hat einen eigenen Ordner; die README nennt die jeweiligen Compileraufrufe. Enthaltene Includes behalten ihre passenden Pfade.

Alle 13 Beispiele als ZIP

Bridging

Mit global wird ein Symbol sichtbar; extern bezeichnet ein anderswo definiertes Symbol. Ein gemeinsamer Compileraufruf verbindet ASM und BASIC. Datenbreite und Speicherlayout bleiben Teil des Vertrags.

Vollständige Quellenpaare ansehen