===== Beispiele =====
==== Hallo Welt reloaded ====
section .data
msg db 'Displaying 9 stars',0xa ;Message, Aneinanderreihung von "byte" (db) Bereichen
len equ $ - msg ;Laenge der Message
s2 times 9 db '*' ; 9 x ein byte (db) mit dem Inhalt "*"
section .text
global _start ;must be declared for linker
_start: ;startadresse
mov edx,len ;Laenge nach edx
mov ecx,msg ;Message nach ecx
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov edx,9 ;message length
mov ecx,s2 ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
Hier kommt wieder der **Linux-Systemaufruf** ''4'' zum Einsatz. Linux-Systemaufrufe funktionieren grob folgendermaßen:
* Lege die Nummer des Systemaufrufs in das EAX-Register
* Speichere die Argumente für den Systemaufruf in den Registern EBX, ECX, usw.
* Rufe den Interrupt (80h) auf
* Das Ergebnis des Systemaufrufs wird normalerweise im EAX-Register zurückgegeben.
Um das erfolgreich zum Einsatz zu bringen, muss man wissen, was ein Systemaufruf in welchem Register erwartet, damit er funktioniert, beim System-Call 4 (Write) ist es folgendermaßen:
^ Name ^ %eax ^ %ebx ^ %ecx ^ %edx ^ %esx ^ %edi ^
| Write | 4 | unsigned int (Output Stream) | const char * (Inhalte) | size_t (Länge) | - | - |
Das kann man sich ein wenig wie eine Funktion/Methode mit Argumenten vorstellen: Man befüllt zunächst die Register mit den Argumenten und ruft dann den Systemaufruf auf.
----
{{:aufgabe.png?nolink |}}
=== (A1) ===
* Gib 12 Sterne aus
* Gib 4 Sterne aus
* Sorge dafür, dass das Eingabeprompt in der Zeile unter den Sternen angezeigt wird
=== Weitere System-Calls: ===
^ Name ^ %eax ^ %ebx ^ %ecx ^ %edx ^ %esx ^ %edi ^
| Exit | 1 | int (Exit Code) | - | - | - | - |
| Fork | 2 | struct pt_regs | - | - | - | - |
| Read | 3 | unsigned int | char * | size_t | - | - |
| Write | 4 | unsigned int (Output Stream) | const char * (Inhalte) | size_t (Länge) | - | - |
| Open | 5 | const char * | int | int | - | - |
| Close | 6 | unsigned int | - | - | - | - |
==== Benutzereingabe ====
Mit dem Sys-Call 3 lässt sich also eine Eingabe realisieren - "Read".
Damit das funktioniert muss man mehrere Dinge beachten:
* Man benötigt einen reservierten, beschreibbaren Speicherbereich im .bss-Abschnitt des Programms
* Ins Register eax muss der Wert 3 geschrieben werden
* Ins Regsiter ebx muss der Filedescriptor, von dem gelesen werden soll. Wenn man das in einer Shell ausführt: 0, 1 oder 2.
* Ins Register ecx muss die Adresse des in .bss reservierten Bereichs
* Ins Register edx muss die Länge der zu lesenden Informationen
* Dann wird der Syscall durch den Interrupt 0x80 ausgelöst
section .data ;.data Abschnitt
userMsg db 'Bitte Zahl eingeben: ' ; Eingabeprompt
lenUserMsg equ $-userMsg ; Laenge
dispMsg db 'Du hast die folgende Zahl eingegeben: ' ; Ausgabeprompt
lenDispMsg equ $-dispMsg ; Laenge
section .bss ; Beschreibbarer Speicher, vobelegt mit 0-en
antwort resb 5 ; 5 Byte
section .text ; coe Abschnitt
global _start
_start:
;User prompt ausgeben
mov eax, 4
mov ebx, 0
mov ecx, userMsg
mov edx, lenUserMsg
int 80h
;Neu: Benutzereingabe lesen
mov eax, 3 ; syscall Nummer: 3
mov ebx, 0 ; lesen von stdin
mov ecx, antwort ; antwort adresse in ecx
mov edx, 5 ; 5 bytes lang
int 80h ; Syscall!
;Ausgabe
mov eax, 4
mov ebx, 0
mov ecx, dispMsg
mov edx, lenDispMsg
int 80h
;Ausgabe der eingegebenen Zahl
mov eax, 4
mov ebx, 0
mov ecx, antwort
mov edx, 5
int 80h
; Exit code
mov eax, 1
mov ebx, 0
int 80h
----
{{:aufgabe.png?nolink |}}
=== (A2) ===
Übersetze und teste das Programm. Was passiert, wenn man weniger/mehr als 5 Ziffern eingibt? Beobachte genau.