Benutzer-Werkzeuge

Webseiten-Werkzeuge


coding:nasm

Dies ist eine alte Version des Dokuments!


NASM (Netwide Assembler) ist ein beliebter Assembler für die x86-Architektur, der für seine Portabilität, Flexibilität und Effizienz bekannt ist. NASM wird häufig für die Entwicklung von Betriebssystemen, Treibern und anderen Systemsoftwarekomponenten verwendet, bei denen niedrige Latenz und direkter Zugriff auf die Hardware erforderlich sind.

  • Plattformunabhängigkeit: NASM kann auf verschiedenen Betriebssystemen wie Linux, Windows und macOS verwendet werden.
  • Modularität: NASM unterstützt verschiedene Ausgabeformate wie ELF, COFF, Mach-O und mehr, was die Erstellung von plattformübergreifender Software erleichtert.
  • Leichtgewicht: NASM ist ein schlankes und effizientes Werkzeug, das schnell und ressourcenschonend arbeitet.
  • Flexibilität: NASM unterstützt eine Vielzahl von x86- und x86-64-Instruktionen und bietet viele Direktiven zur Steuerung der Assemblerausgabe.

Linux

Hello World

section .data
    hello db 'Hello, World!', 0    ; Null-terminierte Zeichenkette

section .text
    global _start                  ; Der Entry-Point für das Programm

_start:
    ; Syscall zum Schreiben (write)
    mov eax, 4                     ; Syscall-Nummer für sys_write
    mov ebx, 1                     ; File-Descriptor 1 - stdout
    mov ecx, hello                 ; Pointer auf die Zeichenkette
    mov edx, 13                    ; Länge der Zeichenkette
    int 0x80                       ; Interrupt um den Syscall auszuführen

    ; Syscall zum Beenden (exit)
    mov eax, 1                     ; Syscall-Nummer für sys_exit
    xor ebx, ebx                   ; Rückgabewert 0
    int 0x80                       ; Interrupt um den Syscall auszuführen

Kompilieren

nasm -f elf32 -o hello.o hello.asm
ld -m elf_i386 -s -o hello hello.o
./hello

Addition

section .data
    num1 db '5', 0    ; Null-terminierte Zeichenkette
    num2 db '7', 0    ; Null-terminierte Zeichenkette
    result db 'Result: 12', 0

section .bss
    temp resb 1

section .text
    global _start

_start:
    ; Zahl 1 laden
    mov al, [num1]
    sub al, '0'      ; ASCII zu Integer konvertieren

    ; Zahl 2 laden
    mov bl, [num2]
    sub bl, '0'      ; ASCII zu Integer konvertieren

    ; Addition
    add al, bl

    ; Ergebnis in ASCII umwandeln
    add al, '0'
    mov [temp], al

    ; Ergebnis ausgeben
    mov edx, 9       ; Länge der Zeichenkette "Result: "
    mov ecx, result  ; Pointer auf die Zeichenkette
    mov ebx, 1       ; File-Descriptor 1 - stdout
    mov eax, 4       ; Syscall-Nummer für sys_write
    int 0x80         ; Interrupt um den Syscall auszuführen

    ; Temp-Wert ausgeben
    mov edx, 1       ; Länge der Zeichenkette (1 Zeichen)
    mov ecx, temp    ; Pointer auf die Zeichenkette
    mov ebx, 1       ; File-Descriptor 1 - stdout
    mov eax, 4       ; Syscall-Nummer für sys_write
    int 0x80         ; Interrupt um den Syscall auszuführen

    ; Programm beenden
    mov eax, 1       ; Syscall-Nummer für sys_exit
    xor ebx, ebx     ; Rückgabewert 0
    int 0x80         ; Interrupt um den Syscall auszuführen
nasm -f elf32 -o addition.o addition.asm
ld -m elf_i386 -s -o addition addition.o
./addition

Loops

section .data
    msg db 'Counting: ', 0
    newline db 10, 0

section .bss
    counter resb 1

section .text
    global _start

_start:
    mov ecx, 10              ; Anzahl der Wiederholungen

print_msg:
    mov eax, 4               ; Syscall-Nummer für sys_write
    mov ebx, 1               ; File-Descriptor 1 - stdout
    mov edx, 10              ; Länge der Zeichenkette "Counting: "
    mov ecx, msg             ; Pointer auf die Zeichenkette
    int 0x80                 ; Interrupt um den Syscall auszuführen

    mov al, byte [counter]
    add al, '0'              ; Integer zu ASCII konvertieren
    mov [counter], al

    ; Ausgabe des Zählers
    mov eax, 4               ; Syscall-Nummer für sys_write
    mov ebx, 1               ; File-Descriptor 1 - stdout
    mov ecx, counter         ; Pointer auf die Zeichenkette
    mov edx, 1               ; Länge der Zeichenkette (1 Zeichen)
    int 0x80                 ; Interrupt um den Syscall auszuführen

    ; Neue Zeile ausgeben
    mov eax, 4               ; Syscall-Nummer für sys_write
    mov ebx, 1               ; File-Descriptor 1 - stdout
    mov ecx, newline         ; Pointer auf die Zeichenkette
    mov edx, 1               ; Länge der Zeichenkette (1 Zeichen)
    int 0x80                 ; Interrupt um den Syscall auszuführen

    ; Zähler erhöhen
    inc byte [counter]

    ; Schleife
    loop print_msg

    ; Programm beenden
    mov eax, 1               ; Syscall-Nummer für sys_exit
    xor ebx, ebx             ; Rückgabewert 0
    int 0x80                 ; Interrupt um den Syscall auszuführen
nasm -f elf32 -o loop.o loop.asm
ld -m elf_i386 -s -o loop loop.o
./loop

Windows

Input/Output

;;Assemble and link with
;nasm -fwin32 hello.asm
;gcc -o hello hello.obj
 
global _main 
extern _scanf 
extern _printf     
 
segment .data
 
    msg: db "String eingeben", 0xA, 0xD, 0  ; null terminator.
    formatin: db "%s", 0                  ; for scanf.
 
segment .bss
    id resb 10
 
segment .text
 
_main:
 
   push msg
   call _printf
   add esp, 4 
 
   push id  ; address of number1 (second parameter)
   push formatin ; arguments are pushed right to left (first parameter)
   call _scanf
   add esp, 8 
 
 
   push id
   call _printf
   add esp,4              
 
   ret  

Calculator

; Assemble and link with:
; nasm -f win32 calc.asm
; gcc -o calc calc.obj
 
global _main
extern _scanf
extern _printf
 
segment .data
    msg1 db "Enter first number: ", 0xA, 0
    msg2 db "Enter second number: ", 0xA, 0
    msg3 db "Enter operation (+, -, *, /): ", 0xA, 0
    formatint db "%d", 0
    formatchar db " %c", 0       ; Beachte das Leerzeichen für scanf, damit Whitespaces ignoriert werden
    formatout db "Result: %d", 0xA, 0
 
segment .bss
    num1 resd 1
    num2 resd 1
    result resd 1
    operation resb 1
 
segment .text
 
_main:
 
    ; Eingabe erste Zahl
    push msg1
    call _printf
    add esp, 4
 
    push num1
    push formatint
    call _scanf
    add esp, 8
 
    ; Eingabe zweite Zahl
    push msg2
    call _printf
    add esp, 4
 
    push num2
    push formatint
    call _scanf
    add esp, 8
 
    ; Eingabe Rechenoperation
    push msg3
    call _printf
    add esp, 4
 
    push operation
    push formatchar
    call _scanf
    add esp, 8
 
    ; Rechnen
    mov eax, [num1]
    mov ebx, [num2]
 
    movzx ecx, byte [operation]   ; Lade operation in ecx (mit zero extension)
 
    cmp ecx, '+'
    je addieren
 
    cmp ecx, '-'
    je subtrahieren
 
    cmp ecx, '*'
    je multiplizieren
 
    cmp ecx, '/'
    je dividieren
 
    ; Unbekannte Operation -> abbrechen
    jmp ende
 
addieren:
    add eax, ebx
    jmp speichern
 
subtrahieren:
    sub eax, ebx
    jmp speichern
 
multiplizieren:
    imul eax, ebx
    jmp speichern
 
dividieren:
    cmp ebx, 0
    je ende        ; Division durch Null verhindern
    cdq            ; Vorzeichen erweitern für idiv
    idiv ebx
    jmp speichern
 
speichern:
    mov [result], eax
 
    ; Ausgabe
    push dword [result]
    push formatout
    call _printf
    add esp, 8
 
ende:
    ret

Hello World

section .data
    hello db 'Hello, World!', 0    ; Null-terminierte Zeichenkette

section .text
    global _start                  ; Der Entry-Point für das Programm

_start:
    ; Syscall zum Schreiben (write)
    mov eax, 4                     ; Syscall-Nummer für sys_write
    mov ebx, 1                     ; File-Descriptor 1 - stdout
    mov ecx, hello                 ; Pointer auf die Zeichenkette
    mov edx, 13                    ; Länge der Zeichenkette
    int 0x80                       ; Interrupt um den Syscall auszuführen

    ; Syscall zum Beenden (exit)
    mov eax, 1                     ; Syscall-Nummer für sys_exit
    xor ebx, ebx                   ; Rückgabewert 0
    int 0x80                       ; Interrupt um den Syscall auszuführen
nasm -f win32 -o hello.obj hello.asm
gcc -o hello.exe hello.obj
hello.exe

Addition

section .data
    num1 db '5', 0    ; Null-terminierte Zeichenkette
    num2 db '7', 0    ; Null-terminierte Zeichenkette
    result db 'Result: 12', 0

section .bss
    temp resb 1

section .text
    global _start

_start:
    ; Zahl 1 laden
    mov al, [num1]
    sub al, '0'      ; ASCII zu Integer konvertieren

    ; Zahl 2 laden
    mov bl, [num2]
    sub bl, '0'      ; ASCII zu Integer konvertieren

    ; Addition
    add al, bl

    ; Ergebnis in ASCII umwandeln
    add al, '0'
    mov [temp], al

    ; Ergebnis ausgeben
    mov edx, 9       ; Länge der Zeichenkette "Result: "
    mov ecx, result  ; Pointer auf die Zeichenkette
    mov ebx, 1       ; File-Descriptor 1 - stdout
    mov eax, 4       ; Syscall-Nummer für sys_write
    int 0x80         ; Interrupt um den Syscall auszuführen

    ; Temp-Wert ausgeben
    mov edx, 1       ; Länge der Zeichenkette (1 Zeichen)
    mov ecx, temp    ; Pointer auf die Zeichenkette
    mov ebx, 1       ; File-Descriptor 1 - stdout
    mov eax, 4       ; Syscall-Nummer für sys_write
    int 0x80         ; Interrupt um den Syscall auszuführen

    ; Programm beenden
    mov eax, 1       ; Syscall-Nummer für sys_exit
    xor ebx, ebx     ; Rückgabewert 0
    int 0x80         ; Interrupt um den Syscall auszuführen
nasm -f win32 -o addition.obj addition.asm
gcc -o addition.exe addition.obj
addition.exe

Loops

section .data
    msg db 'Counting: ', 0
    newline db 10, 0

section .bss
    counter resb 1

section .text
    global _start

_start:
    mov ecx, 10              ; Anzahl der Wiederholungen

print_msg:
    mov eax, 4               ; Syscall-Nummer für sys_write
    mov ebx, 1               ; File-Descriptor 1 - stdout
    mov edx, 10              ; Länge der Zeichenkette "Counting: "
    mov ecx, msg             ; Pointer auf die Zeichenkette
    int 0x80                 ; Interrupt um den Syscall auszuführen

    mov al, byte [counter]
    add al, '0'              ; Integer zu ASCII konvertieren
    mov [counter], al

    ; Ausgabe des Zählers
    mov eax, 4               ; Syscall-Nummer für sys_write
    mov ebx, 1               ; File-Descriptor 1 - stdout
    mov ecx, counter         ; Pointer auf die Zeichenkette
    mov edx, 1               ; Länge der Zeichenkette (1 Zeichen)
    int 0x80                 ; Interrupt um den Syscall auszuführen

    ; Neue Zeile ausgeben
    mov eax, 4               ; Syscall-Nummer für sys_write
    mov ebx, 1               ; File-Descriptor 1 - stdout
    mov ecx, newline         ; Pointer auf die Zeichenkette
    mov edx, 1               ; Länge der Zeichenkette (1 Zeichen)
    int 0x80                 ; Interrupt um den Syscall auszuführen

    ; Zähler erhöhen
    inc byte [counter]

    ; Schleife
    loop print_msg

    ; Programm beenden
    mov eax, 1               ; Syscall-Nummer für sys_exit
    xor ebx, ebx             ; Rückgabewert 0
    int 0x80                 ; Interrupt um den Syscall auszuführen
nasm -f win32 -o loop.obj loop.asm
gcc -o loop.exe loop.obj
loop.exe

Win32 API

Hello World

section .data
    hello db 'Hello, World!', 0

section .bss
    hStdOut resd 1

section .text
    extern _GetStdHandle@4, _WriteFile@20, _ExitProcess@4
    global _main

_main:
    ; GetStdHandle(STD_OUTPUT_HANDLE)
    push dword -11
    call _GetStdHandle@4
    mov [hStdOut], eax  ; HANDLE hFile

    ; WriteFile(hFile, hello, 13, NULL, NULL)
    push dword 0          ; LPOVERLAPPED lpOverlapped
    push dword 0          ; LPDWORD lpNumberOfBytesWritten
    push dword 13         ; DWORD nNumberOfBytesToWrite
    push dword hello      ; LPCVOID lpBuffer
    mov eax, [hStdOut]    ; HANDLE hFile
    push eax
    call _WriteFile@20

    ; ExitProcess(0)
    push dword 0
    call _ExitProcess@4
nasm -f win32 -o hello.obj hello.asm
gcc -o hello.exe hello.obj -lkernel32
hello.exe

Addition

section .data
    num1 db '5', 0    ; Null-terminierte Zeichenkette
    num2 db '7', 0    ; Null-terminierte Zeichenkette
    result db 'Result: ', 0
    res resb 2

section .bss
    hStdOut resd 1

section .text
    extern _GetStdHandle@4, _WriteFile@20, _ExitProcess@4
    global _main

_main:
    ; Zahl 1 laden
    mov al, [num1]
    sub al, '0'      ; ASCII zu Integer konvertieren

    ; Zahl 2 laden
    mov bl, [num2]
    sub bl, '0'      ; ASCII zu Integer konvertieren

    ; Addition
    add al, bl

    ; Ergebnis in ASCII umwandeln
    add al, '0'
    mov [res], al
    mov byte [res+1], 0

    ; GetStdHandle(STD_OUTPUT_HANDLE)
    push dword -11
    call _GetStdHandle@4
    mov [hStdOut], eax  ; HANDLE hFile

    ; Result ausgeben
    push dword 0          ; LPOVERLAPPED lpOverlapped
    push dword 0          ; LPDWORD lpNumberOfBytesWritten
    push dword 9          ; DWORD nNumberOfBytesToWrite
    push dword result     ; LPCVOID lpBuffer
    mov eax, [hStdOut]    ; HANDLE hFile
    push eax
    call _WriteFile@20

    ; Ergebnis ausgeben
    push dword 0          ; LPOVERLAPPED lpOverlapped
    push dword 0          ; LPDWORD lpNumberOfBytesWritten
    push dword 2          ; DWORD nNumberOfBytesToWrite
    push dword res        ; LPCVOID lpBuffer
    mov eax, [hStdOut]    ; HANDLE hFile
    push eax
    call _WriteFile@20

    ; Programm beenden
    push dword 0
    call _ExitProcess@4
nasm -f win32 -o addition.obj addition.asm
gcc -o addition.exe addition.obj -lkernel32
addition.exe
coding/nasm.1745858776.txt.gz · Zuletzt geändert: 2025/04/28 18:46 von admin