Der Martin: Zwei Zahlen mit Assembler addieren und ausgeben

Beitrag lesen

Hallo Markus,

ich kenne mich zwar mit den Systemaufrufen unter Linux nicht aus, kann aber aus deinen Codebeispielen gewisse Schlüsse ziehen. Deswegen versuche ich jetzt zuerst mal das HelloWorld-Beispiel vorzuziehen und zu kommentieren.

Offensichtlich ist der int 0x80 ein allgemeiner Betriebssystemaufruf. Die Technik, Systemaufrufe über einen Software-Interrupt zu machen, ist uralt. So werden viele BIOS-Funktionen aufgerufen, und auch das gute alte DOS hat diese Technik verwendet (da war's der int 0x21).
In EAX wird dabei wohl eine Funktionsnummer erwartet, und aus dem Beispiel schließe ich:
Funktion #1: Prozess beenden
Funktion #4: String ausgeben
In weiteren Prozessorregistern werden dann, soweit nötig, zusätzliche Parameter übergeben.

section .data                       ; Beginn des Datensegments ("Variablenbereich")
msg   db    "Hello World", 0x0A     ; String mit abschließendem LF
len   equ   $ - msg                 ; Stringlänge ($ steht für aktuelle Adresse)

section .text                       ; Beginn des Codesegments
global _start                       ; _start wird extern aufrufbar deklariert

_start:

mov edx,len                         ; Länge des Strings in EDX
mov ecx,msg                         ; Zeiger auf den String in ECX
mov ebx,1                           ; File-Handle (stdout) in EBX
mov eax,4                           ; Funktionsnummer (Stringausgabe) in EAX
int 0x80                            ; Betriebssystemfunktion aufrufen

mov eax,1                           ; Funktionsnummer (exit) in EAX
int 0x80                            ; Betriebssystemfunktion aufrufen

In Pseudocode geschrieben macht dieser Abschnitt also das hier:

fwrite(stdout, msg, len(msg))
 exit()

So, jetzt zu deinem Beispiel.

section .data
zahl1 db 1000
zahl2 db 1500

Das geht schonmal nicht. "db" steht für "define byte", danach darf eine Sequenz von Bytes (z.B. 40,173,3,104) stehen oder auch ein String, der ja auch nur eine Folge von bytes ist. Du schreibst Zahlen hin, die nicht in den Zahlenbereich eines Bytes passen. Was dein Assembler _daraus_ macht, kann ich nicht sagen. Richtig wäre hier eher "dw" für "define word" oder gar "dd" für "define doubleword", je nachdem welchen Zahlenbereich du nutzen willst. Da du den Wert nachher in ein 32bit-Register laden willst, kommt eigentlich nur dd in Frage.

section .text
global _start

_start:

mov eax, [zahl1]   ;Zahl1 in Accumulator schieben
add eax, [zahl2]   ;Zahl2 dazuaddieren

Gut. EAX enthält jetzt zahl1+zahl2.

mov edx, eax       ;Bekomme ich so den Wert aus dem Accumulator?

Das kopiert den Inhalt von EAX (das Ergebnis der Addition) nach EDX.

mov  ebx,1         ;

Sieht aus wie die Vorbereitung (Parameter laden) für die Stringausgabe, die du dann aber gar nicht ausführst: Der int 0x80 mit EAX=4 kommt nirgends mehr.

mov eax,1         ;
int 0x80          ;

Damit beendest du schließlich dein Programm, ohne dass mit dem Additionsergebnis noch irgendwas geschehen wäre.

Das Programm lässt sich zwar problemlos kompilieren und linken, aber es gibt einfach nichts aus.

Genau. Du scheiterst im Moment noch am Verständnis für den Aufruf von Betriebssystemfunktionen. Nochmal: Mit int 0x80 wird eine Systemfunktion aufgerufen. Welche das ist, entscheidet der Inhalt von EAX. Da muss es in irgendeiner Doku ein Verzeichnis der Systemfunktionen geben, in der die möglichen Funktionen je nach dem Wert von EAX aufgelistet sind, und was die übrigen Register dann für Werte/Parameter enthalten müssen. Das solltest du mal suchen und dir zu Gemüte führen. Denn egal ob DOS, Windows, Linux, oder welches OS auch immer: Ohne Betriebssystemfunktionen wird kein Programm auskommen. Die sind das A und O.

Wann muss eigentlich immer der Kernel aufgerufen werden?

Immer dann, wenn du eine Funktion des OS benutzen willst.
Es ist ein langer, steiniger Weg. Aber wenn man die ersten Steine überwunden hat und die ersten Blasen an den Füßen verheilt sind, macht es entweder mächtig Spaß, oder man hat die Schnauze voll und möchte nie wieder so einen primitiven Kram machen.

Schönen Abend noch,

Martin

--
Das Gehirn ist schon eine tolle Sache: Es fängt ganz von allein an zu arbeiten, wenn man morgens aufsteht, und hört erst damit auf, wenn man in der Schule ankommt.
  (alte Schülererkenntnis)
Schon Urlaubspläne für 2006?