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 ; 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