Diskussion:Assembler-Programmierung für x86-Prozessoren/ Das erste Assemblerprogramm
Unterschied zwischen Com und Exe
BearbeitenIch bin ein ASM-Anfänger und ich verstehe nicht warum bei der EXE Version folgende Zeilen steht:
mov ax, data mov ds, ax
Und es wird auch nirgends erklärt.. Wird damit das Daten-Segment des Programms im DS gespeichert? Warum reicht nicht ein
mov ds, data
? --Anonym001 14:25, 27. Feb 2006 (UTC)
Auf dem Intelprozessor der x86-Familie ist DS, eines der Segmentregister. DS ist das Standard-Register, wenn ein Speicherinhalt angefordert wird. Bei einer EXE Datei wird das Datenregister nicht reloziert, da eine Exedatei über mehrere Datensegmente verfügen kann und der Compiler schlicht und ergreifend nicht in der Lage ist, das richtige Segment auszuwählen. Selbst beim Linken einer EXE-Datei können weitere Datensegement dazugelinkt werden. Damit muss der Programmierer die Voraussertungen für einen korrekten Datenzugriff schaffen. Das erledigen die ersten beiden Zeilen.
Das Problem mit der letzten Zeile ist, dass die FA Intel ihre Prozessorfamilie so speezifiziert hat, dass ein direktes beschreiben des DS mit einem Wert nicht möglich ist. Es ist stets der Umweg über ein Register oder über den sog. Stack zu nehmen, dazu müssen der Stackpointer (SP) und das Stack-Segmentregister (SS). korrekt initialisiert sein, dann geht auch, das hat den Vorteil, den Registerinhalt nicht zu zerstören. HTH. Vielleicht kannst Du den Text diesbezüglich erweitern.
push data pop ds
-- ThePacker 18:25, 27. Feb 2006 (UTC)
Physische Adresse
BearbeitenIch bin ebenfalls Anfänger und verstehe die Berechnung der physikalischen Adresse nicht. Wie komme ich auf 4F28?
- Hmm das Ergebnis 4F28 scheint falsch zu sein. Korrekt wäre: 0x0CDC * 16 +0x0100 = 0xCDC0 + 0x0100 = 0xCEC0. -- ThePacker 15:10, 7. Aug 2006 (UTC)
Was soll man mit einem 64bit Windows 7 system tun?
Fehler beim Umwandeln in obj-Datei
BearbeitenIch habe den Code exakt so abgeschrieben, wie er dort steht, und zuletzt sogar einfach rauskopiert, aber nasm.exe gibt bei mir immer folgende Fehlermeldung aus --> error: symbol 'data' undefined. --84.141.222.236 15:55, 3. Sep 2006 (CEST)
Oh, tut mir Leid, mein Fehler. Ich habe immer noch die alten Argumente für nasm.exe verwendet, und nicht -fobj. --84.141.222.236 15:59, 3. Sep 2006 (CEST)
Schritt 3 : Analyse
BearbeitenUnter Schritt 3 : Analyse steht "Physikalische Adresse = 0100 + 0CDC * 16 = 4F28". Müsste das Ergebnis nicht
0100 + 0CDC0
0CEC0
sein??
- Einfach mal weiter 2 Beiträge weiter oben schauen.. -- ThePacker 11:40, 12. Jan. 2007 (CET)
- ups... Nicht gesehen. sorry. Dann kann der Beitrag wieder gelöscht werden
- Trotzdem Danke für deinen Vorschlag. Ich ändere das jetzt gleich. -- Klaus 19:06, 12. Jan. 2007 (CET)
- ups... Nicht gesehen. sorry. Dann kann der Beitrag wieder gelöscht werden
Hello World-Programm
BearbeitenEs ist ja inzwischen fast üblich geworden ein Hello World-Programm in einer Einführung in eine Sprache zu entwickeln. Dem wollen wir natürlich folgen:
org 100h start: mov dx,hello_world mov ah,09h int 21h mov ah,4Ch int 21h section .data hello_world: db 'hello, world', 13, 10, '$'
Nachdem Sie das Programm übersetzt und ausgeführt haben starten Sie es mit dem Debugger:
-r AX=0000 BX=0000 CX=001B DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0CDC ES=0CDC SS=0CDC CS=0CDC IP=0100 NV UP EI PL NZ NA PO NC 0CDC:0100 BA0C01 MOV DX,010C - q
Wie Sie erkennen können, hat der Assembler hello_world
durch die Offsetadresse 010C ersetzt.
Vielleicht könnte man an dieser Stelle nochmals erklären, wie sich die Offsetadresse zusammensetzt, da ich momentan selbst nicht nachvollziehen kann, woher das kommen soll. Auch in der Vorseite (Prozessor) konnte ich das nicht erörtern. Zum Beispiel ist bei mir "MOV DX,110" zu sehen, was mich sehr verwirrt.
Da ich mich nicht auskenne, kann ich die Änderung leider nicht selbst durchführen... -- Daniel 28. Aug. 2007, 14:30 (CEST)
- Ich bin mir nun nicht mehr so sicher, ob es doch an meinem Verständnis liegt, oder nicht. Liegt die Lösung in den Absätzen drunter? Ein Problem ist, daß ich ganz andere Adressen in den Registern stehen habe, und das verwirrt. Mal abwarten, vielleicht kommt die Erleuchtung noch... -- Daniel 23:46, 28. Aug. 2007 (CEST)
Diese Adresse zusammen mit dem CS-Register entspricht der Stelle im Speicher, in der sich der Text befindet. Wir müssen diese der Betriebssystemfunktion 9h des Interrupts 21 übergeben, die dafür sorgt, dass der Text auf dem Bildschirm ausgegeben wird. Wie kommt der Assembler auf diese Adresse?
Da sich der Text am Ende des Programms befindet, ermittelt er die Größe des Programms: Der Opcode von mov dx,010C
hat eine Größe von 4 Byte, der Opcode von mov ah,09
und mov ah, 4Ch
jeweils 2 Byte der Opcode der Interruptaufrufe nochmals jeweils 2 Byte. Der Programmcode hat somit eine Größe von 12 Byte dezimal oder C Byte hexadezimal.
Hier liegt meiner Meinung nach ein Fehler vor. Der Befehl mov dx,010C hat nur eine Größe von 3 Byte und nicht 4 wie oben steht. Dadurch ergibt sich allerdings eine Differenz zwischen der Summe der Bytes bis zum string 'hello, world' (müsste eigentlich 11 Bytes also 010B sein) und dem Wert der ins Register DX geladen wird (010C). Ich hab dann mal manuell den Wert 010B in DX geladen und die Ausgabe mit dem ursprünglichen Programm verglichen.
Bei 010C: 'hello, world'
Bei 010B: ' hello, world'
Es wird also nur das Leerzeichen weggelassen. Die Frage ist, wo kommt das Leerzeichen überhaupt her?
Eine weitere Anweisung in diesem Programm ist die DB - Anweisung. Durch sie wird ein Byte Speicherplatz reserviert. Der NASM kennt darüber hinaus noch weitere Anweisungen, um Speicherplatz zu reservieren.
Lässt sich die Differenz vielleicht durch das 1 Byte erklären, das mit der DB-Anweisung reserviert wird?
Bin selber noch Anfänger was Assembler betrifft, deshalb meine Bitte:
Kann das mal ein Experte nachvollziehen und korrigieren? Hat mich jetzt doch ziemlich verwirrt der Fehler.
Hello World-Programm
BearbeitenDu hast mein Posting gestern offenbar leicht misinterpretiert. Der Befehl mov dx,hello_world hat eine Länge von 3 Byte. Das hast du jetzt korrigiert. Aber der Befehl lautet (beim Debuggen) trotzdem: mov dx,010c
D.h. also, dass der string 'hello, world' 12 Byte (= C) nach Programmstart im Programmcode steht. Die Summe aller Befehle ergibt aber nur 11 Byte. Und genau hier liegt das Problem.
Ich hatte ja geschrieben, dass das evtl. an der db-Anweisung liegt, die 1 Byte Speicher reserviert. Genau weiß ich das aber nicht, bin ja selber noch Anfänger.
Es fällt jedoch auf, dass die Ausgabe mit Leerzeichen vor 'hello, world' erfolgt, wenn man im Programmcode den mov-Befehl in mov dx,10bh ändert. Damit wird ja die Adresse ins Register dx geladen, die genau 11 Byte (= B) nach Programmstart liegt.
Wenn man allerdings die Marke hello_world ins Register dx lädt, ist das genauso wie wenn ich im Programmcode schreibe: mov dx,10ch
In diesem Fall erfolgt die Ausgabe ohne das Leerzeichen vor 'hello, world'.
Den Grund dafür kenne ich allerdings nicht. Würde mich aber sehr interessieren, wo das Leerzeichen herkommt bzw. wie die Differenz von 1 Byte entsteht. Am besten mal selbst ausprobieren, einmal mit mov dx,10bh und einmal mit mov dx,10ch im Progammcode. Denke dann wird klar, was ich meine.
- Es könnte an den Voreinstellungen des NASM liegen, dass die Speicherzuweisung immer an einer geraden Adresse beginnt. Ich kann das nicht testen, habe keinen NASM installiert. Füge mal ein oder zwei NOP ein und sieh mal, was passiert. -- Klaus 10:08, 22. Feb. 2007 (CET)
- Ja, du hast Recht. Es liegt tatsächlich an der Speicherausrichtung. Die erfolgt an Doppelwort-Grenzen, also 4-byteweise. Kannst Du das vielleicht noch in einem Satz im Text erwähnen, damit andere auch Bescheid wissen? Schreib aber statt 'mov dx,010bh' wieder 'mov dx,010ch' hin, das hat ja gestimmt. Es sollte eben nur hervorgehen, dass die Differenz von 1 Byte (C - B = 1) von der Doppelwort-Ausrichtung herrührt. Danke. -- Andi 16:21, 22. Feb. 2007
linux user
Bearbeitenich habe assembler hier das erste mal wirklich verstanden(und ich habe schon 2 tuts gelesen). was mich allerdings sehr enttäuscht ist die reduzierung auf windows/msdos. ich nutze seit langer zeit GNU/Linux und würde auch hier gerne den ersten code assemblieren. ich habe auch schon nasm heruntergeladen (ja, den gibts auch für linux) und versucht den code damit in eine binärdatei umzuwandeln - erfolgslos. ich kann weder eine lauffähige executable erstellen, noch diese mit gdb debuggen, bzw. disassemblieren.
über eine ergänzung würde ich (und auch ganz sicher viele andere) mich sehr freuen.
mfG Neme
- Das Buch ist leider verwaist. Wenn du es rausgekriegt hast, wie es mit Linux geht, dann schreib doch deine Erkenntnisse dazu! -- Klaus 08:53, 8. Jul. 2007 (CEST)
Es gibt noch den Flatassembler, siehe http://flatassembler.net/download.php
Hello World EXE
BearbeitenFolgende Ausgabe bekomme ich:
C:\Temp\asm\002_HE~1>debug HELLO_EX.exe -r AX=0000 BX=FFFF CX=FE7F DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 DS=154B ES=154B SS=155B CS=155B IP=0000 NV UP EI PL NZ NA PO NC 155B:0000 B85D15 MOV AX,155D -t AX=155D BX=FFFF CX=FE7F DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 DS=154B ES=154B SS=155B CS=155B IP=0003 NV UP EI PL NZ NA PO NC 155B:0003 8ED8 MOV DS,AX -t AX=155D BX=FFFF CX=FE7F DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 DS=155D ES=154B SS=155B CS=155B IP=0005 NV UP EI PL NZ NA PO NC 155B:0005 BA0000 MOV DX,0000 -quit
Bei mir kommt DS(155Dh)-CS(155Bh)=2 raus. Warum? Was ist bei mir anders? -- Daniel 28. Aug. 2007, 15:22 (CEST)
- Ich kann dir nicht sagen, was anders ist. Das hängt vermutlich vom verwendeten Assembler, Linker oder dessen Voreinstellungen zusammen. Fakt ist: Das EXE-Programm ist 18d = 12h Byte lang. Weil die Anfangsadressen jedes Segments vom Linker üblicherweise auf Adressen gelegt werden, die durch 16d = 10h teilbar sind, ergibt das genau den von dir beobachteten Abstand von 2. Falls dein Programm funktioniert, ist der Buchtext falsch. Was meinst du dazu? -- Klaus 20:28, 28. Aug. 2007 (CEST)
- Das Programm funktioniert einwandfrei. Ich habe den NASM Assembler, und den hier empfohlenen ALINK Linker verwendet. Betriebssystem ist MS Windows XP Pro SP2. Leider kann ich das im Moment nicht noch einmal nachvollziehen, da ich daheim kein Windows habe. Werde es gleich nochmal unter Linux versuchen, und berichten. -- Daniel 22:56, 28. Aug. 2007 (CEST)
- Da es bei dir funktioniert, ändere ich jetzt das Buch. -- Klaus 00:07, 29. Aug. 2007 (CEST)
- Habe noch den Text angepasst, hoffe dass die Änderung der Richtigkeit entspricht... -- Daniel 10:44, 29. Aug. 2007 (CEST)
- Da es bei dir funktioniert, ändere ich jetzt das Buch. -- Klaus 00:07, 29. Aug. 2007 (CEST)
- Man benutze
- Das Programm funktioniert einwandfrei. Ich habe den NASM Assembler, und den hier empfohlenen ALINK Linker verwendet. Betriebssystem ist MS Windows XP Pro SP2. Leider kann ich das im Moment nicht noch einmal nachvollziehen, da ich daheim kein Windows habe. Werde es gleich nochmal unter Linux versuchen, und berichten. -- Daniel 22:56, 28. Aug. 2007 (CEST)
nasm hello.asm -g -f elf
- anstatt
nasm hello.asm -f elf
- (zusätzlich -g (siehe nasm --help)) und bekomme Debuginformationen in das Programm geschrieben. Nun kann man mit
ld hello.o -o hello gdb hello
- den Debugger starten. Bei mir konnte ich mit einem "break 5" und anschließendem "run" das Programm bis zur fünften Zeile ausgeführen (und dann pausieren). Schrittweise geht es mit "stepi" weiter und ein "info registers" zwischen den Schritten liest die Register aus.
(gdb) list 1 section .text 2 global _start 3 _start: 4 mov ecx, hello 5 mov edx, length 6 mov ebx, 1 ; Dateinummer der Standard-Ausgabe 7 mov eax, 4 ; Funktionsnummer: Ausgabe 8 int 80h 9 mov ebx, 0 10 mov eax, 1 ; Funktionsnummer: Programm beenden (gdb) break 4 Breakpoint 1 at 0x8048080: file hello.asm, line 4. (gdb) break 5 Breakpoint 2 at 0x8048085: file hello.asm, line 5. (gdb) run Starting program: /home/spitfire/projects/assembler/002_hello_world/hello Breakpoint 2, _start () at hello.asm:5 5 mov edx, length (gdb) info registers eax 0x0 0 ecx 0x80490a4 134516900 edx 0x0 0 ebx 0x0 0 esp 0xbf9e6140 0xbf9e6140 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x8048085 0x8048085 <_start+5> eflags 0x200292 [ AF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0 (gdb) stepi _start () at hello.asm:6 6 mov ebx, 1 ; Dateinummer der Standard-Ausgabe (gdb) info registers eax 0x0 0 ecx 0x80490a4 134516900 edx 0xd 13 ebx 0x0 0 esp 0xbf9e6140 0xbf9e6140 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x804808a 0x804808a <_start+10> eflags 0x200292 [ AF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0 (gdb) stepi _start () at hello.asm:7 7 mov eax, 4 ; Funktionsnummer: Ausgabe (gdb) info registers eax 0x0 0 ecx 0x80490a4 134516900 edx 0xd 13 ebx 0x1 1 esp 0xbf9e6140 0xbf9e6140 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x804808f 0x804808f <_start+15> eflags 0x200292 [ AF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0 (gdb) stepi _start () at hello.asm:8 8 int 80h (gdb) info registers eax 0x4 4 ecx 0x80490a4 134516900 edx 0xd 13 ebx 0x1 1 esp 0xbf9e6140 0xbf9e6140 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x8048094 0x8048094 <_start+20> eflags 0x200292 [ AF SF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0 (gdb) stepi Hello World!
- Leider bin ich momentan mit der Ausgabe der Register überfordert. Werde mich morgen selbst nochmal hinsetzen, oder du findest gleich heraus, was nun der Fehler ist. (Programm oder Text) Eventuell wäre ja auch eine Erweiterung der Linux Sektion sinnvoll? BTW: Falls meine Eingaben hier nicht den Regeln entsprechen, sei so gut und entferne sie. Ich kenne mich nicht wirklich mit Wikipedia/WikiBooks aus... -- Daniel 00:10, 29. Aug. 2007 (CEST)
- Du kennst dich nicht mit Wikibooks aus? Macht nichts, der Inhalt ist stets wichtiger als die Form, und die Diskussionsseiten sind für Diskussionen da. Und: Ich beschäftige mich wirklich nicht mit Linux, und der ursprüngliche Autor des Buches ist fort... Vielleicht kriegen wir es trotzdem hin. -- Klaus 00:24, 29. Aug. 2007 (CEST)
- Das Programm unter Linux ist zu anders, als das EXE Programm. Ich kann das somit nicht nachvollziehen. Aber: wenn ich soweit bin, werde ich versuchen das sonst sehr gute Buch mit ein paar Tips zu Linux spicken... -- Daniel 09:54, 29. Aug. 2007 (CEST)
- Du kennst dich nicht mit Wikibooks aus? Macht nichts, der Inhalt ist stets wichtiger als die Form, und die Diskussionsseiten sind für Diskussionen da. Und: Ich beschäftige mich wirklich nicht mit Linux, und der ursprüngliche Autor des Buches ist fort... Vielleicht kriegen wir es trotzdem hin. -- Klaus 00:24, 29. Aug. 2007 (CEST)
- Leider bin ich momentan mit der Ausgabe der Register überfordert. Werde mich morgen selbst nochmal hinsetzen, oder du findest gleich heraus, was nun der Fehler ist. (Programm oder Text) Eventuell wäre ja auch eine Erweiterung der Linux Sektion sinnvoll? BTW: Falls meine Eingaben hier nicht den Regeln entsprechen, sei so gut und entferne sie. Ich kenne mich nicht wirklich mit Wikipedia/WikiBooks aus... -- Daniel 00:10, 29. Aug. 2007 (CEST)
Fehler beim Download des Assemblers
BearbeitenIch habe ein Problem. Ich kann den Assembler, den ich downloaden soll nicht finden. Wenn ich auf den Link klicke sehe ich nur eine lange Liste mit Versionen. Wenn ich eine davon Downloade, bekomme ich eine ganz tolle Hilfedatei, die keine Verbindung zum Internet aufbauen kann und deshalb nicht mal funktioniert. Kamm mir jemand sagen, wo genau ich das downloaden kann?
- Wenn du Windows hast, geh mal auf diese Seite. :) -- heuler06 12:07, 2. Mai 2008 (CEST)
Zum Teil unverständlich
BearbeitenFür mich als Anfänger im Bereich Assembler ist diese Einführung doch etwas unverständlich. So wurden zwar die Register der 8086/8088-CPU erklärt, jedoch hat man erst danach erfahren warum man das brauch - Ich persönlich hasse so etwas.
Warum gibt es überhaupt verschiedene Register oder sind das nur Konventionen und man kann mit dem CX-Register rechnen und das AX-Register für Schleifen nutzen. mfg Nozdrum
- Mehr zu den Registern findest du hier. Warum das mit den Registern so und nicht anders ist, werde ich jetzt aufschreiben, sieh Morgen mal hier hin. -- Klaus 19:15, 25. Jun. 2008 (CEST)
Problem mit alink
BearbeitenJetzt habe ich noch ein konkretes Problem für Exe-Datein soll ich die Befehle nutzen: nasm hworld.asm -fobj -o hworld.obj alink hworld.obj Wenn ich in der Kommandobox ( WinXP ) das eingebe erhalte ich beim 2. Befehl die Fehlermeldung: "Der Befehl "alink" ist entweder falsch geschrieben oder konnte nicht gefunden werden." mfg Nozdrum
- Wechsle mal in das Verzeichnis, in dem sich die Programme nasm und alink befinden. Wenn das nicht hilft, erläutere dein Problem genau. -- Klaus 19:15, 25. Jun. 2008 (CEST)
- Ahh alink ist schon wieder ein Programm. Liegt aber nicht in der zip-Datei die man sich herunterladen soll, mal schaun ob ich es finde. Danke für die Antwort. mfg Nozdrum
debug firstp.com unter Vista
BearbeitenBis zu disem Punkt funktioniert alles einwandfrei. Bei "debug firstp.com" ist dann nur noch schwarz in der Konsole zu sehen... Was muss man unter Vista anders machen? mfg ika
16 und 32 bit Register
BearbeitenIch war etwas verwundert, warum im DOS-Beispiel z.B. das Register AX und bei Linux EAX benutzt werden. Dass dies die entsprechenden 32 bit Register sind sollte vielleicht irgendwo stehen, oder im Artikel zum Prozessor benannt werden. Dazu könnte man vielleicht ne Grafik oder Tabelle machen wie diese hier: http://www.cs.virginia.edu/~evans/cs216/guides/x86-registers.png (achtung, vermutlich nicht frei).--85.179.23.38 12:30, 5. Aug. 2008 (CEST) .. hab grad gesehen, dass es ja schon als Anmerkung da steht
erste EXE (Speicherplatz reservieren)
BearbeitenIch (blutiger Anfänger) hab mich gefragt, wie genau die verschiedenen Breiten bei der Speicherreservierung zustande kommen. Eine kleine Erklärung wäre vielleicht sehr hilfreich. Grüße Oruborus 04:41, 26. Jan. 2009 (CET)