Hallo! Ich versuche mich gerade mit x86-Assembler auf einem 8086 (bare metal chip; kein PC mit BIOS, sondern der nackte 8086). Ich habe an Adresse 0xC0000 - 0xFFFFF mein ROM (2 MBit/ 128k x 16). Nun beginnt der 8086 nach einem Reset an Adresse 0xFFFF0 den Code ausführen. Ich habe als erstes ein simples Programm geschrieben, welches einen Wert an I/O-Adresse 0 ausgibt (dort habe ich ein Latch mit 8 LEDs): <code> .intel_syntax .code16 .globl _start _start: cli movb %al, 0xaa mov %dx, 0x0 outb %dx, %al </code> Wenn ich das jetzt übersetze mit <code> as -32 -o test.o test.s ld -m elf_i386 --oformat binary test.o -o test.bin </code> dann kommt folgendes heraus: <code> hexdump test.bin 0000000 b0fa baaa 0000 f4ee 0000008 </code> Wenn ich das jetzt manuell in der EPROM-Programmiersoftware an die Adresse 3FFF0 (da das EPROM bei C0000 beginnt ist die Adresse im System dann 0xFFFF0) kopiere und das EPROM brenne, dann funktioniert es wie gedacht und die CPU schreibt 0xaa an I/O-Adresse 0. Nun habe ich am Reset-Vektor 0xFFFF0 nur noch 16 Bytes bis zum Ende des ROMs Platz. Daher würde ich gerne von da zum Anfang des ROM springen. Wie bekomme ich meine Assembler-Datei hin, so dass das Ergebnis (Binärdatei) so groß wie das ROM wird (256kB), der Code bei 0xC0000 beginnt und ich bei 0xFFFF0 einem jmp zu einem Label am Anfang meines Codes habe? Ich habe folgendes probiert: <code> .intel_syntax .code16 .org 0xc0000 .section .text .globl _start _start: cli movb %al, 0xaa mov %dx, 0x0 outb %dx, %al hlt .org 0xffff0 jmp _start .org 0xfffff .byte 0 </code> Dann wird aber das Object-File und das gelinkte Binary 1MiB groß...
Ich bin alles andere als ein 8086-BIOS-Experte (habe selbst einige FPGA-8086er-Systeme mit vergleichbaren Problemen), in solchen Fällen zerlege ich den Code in zwei Teilen: 1. den ab FFFF0, der idR 16 Bytes mit einer Sprunganweisung umfasst 2. den eigentliche Code Daraus ergeben sich dann 2 BIN-Files. Die musst Du dann an deinen EPROM-Brenner weiterreichen. Und Btw: die 16 Bytes sind eiglich ja immer gleich, evtl. bis auf die Zieladresse, die je nach Wunsch manuell ohne Übersetzung angepasst werden kann.
Das ist das Problem an den *.bin-Dateien. Diese repräsentieren den gesamten Speicher. Wenn das Program also bei 0xc0000 anfängt enthält die Datei auch Daten von Adresse 0 an. Das macht bis 0xFFFFF eben genau 1MByte. So kannst du das auch nicht in den ROM schreiben, weil die Daten vor 0xc0000 müll sind. Das Problem ist, dass man die org direktive nicht weglassen kann, sonst werden die Adressen vom Assembler falsch berechnet. Wenn du unbedingt ein Binärfile brauchst, dann könntest du als schlimmen Workaround einfach die ersten 0xc0000 Bytes der 1MByte Datei entfernen/abschneiden. Du kannst auch 2 Quellcodes erzeugen, das ist richtig. Aber dazu musst du das ROM Byteweise bzw. in maximal 16 Byte Blöcken beschreiben können. Sonst überschreibst du Teile der jeweils anderen Datei. Ein weiteres Problem ist, dass der Assembler nicht meckert, wenn dein Program ab Adresse 0xc0000 so groß wird, dass es in den Speicher ab 0xf0000 reicht.
Sascha schrieb: > Dann wird aber das Object-File und das gelinkte Binary 1MiB groß... Dann mach da kein BIN File draus sondern ein Intel-HEX File. Da stehen dann die Ladeaddressen mit drin. Wenn dein Programmer keine Offsetverschiebung bei Intel-HEX Files zulaesst must du dir dann noch eben ein kleines Hex-File Verschiebeprogramm schreiben. Beispiel: Du erzeugst das HEX-File direkt aus deinem Code: Dann wird da drin stehen: :020C0000..... Die Addresse ist dann C00000 (zu Hoch fuer das EPROM) Dann must du in deinem Programmer einen Offset angeben der von dieser Ladeaddresse abgezogen wird damit es ins EPROM passt. Kann dein Programmer das nicht dann must du dir ein Programmchen schreiben das die HEX Zeile einliest und das Addressfeld umrechnet. Also im Beispiel muesste dann C0000H abgezogen werden. An deinem eigentlichen Code aendert das nichts, lediglich die Ladeaddresse wird geaendert.
Sebastian Hepp schrieb: > Das ist das Problem an den *.bin-Dateien. Diese repräsentieren den > gesamten Speicher. Einfache Lösung: Von der Bin-Datei den nicht benötigten Teil abschneiden und nur den Rest weiterverarbeiten.
Ich bin 8086 Experte. Das Segment Register muss auch noch betrachtet werde. Ueblicherweise ist ja die Interrupt Tabelle auf Null, und man springt an den Begin des Bios, zB auf F000:0000 = F0000. Also entweder steht das CSEG schon auf F000, oder man muss es so setzen. Du hast das Instruction manual ? Am Anfang des BIOS, oder wie auch immer man diesen Code nennt, muss man erst mal alle Segment Regiter setzen.
:
Bearbeitet durch User
Oh D. schrieb: > Ueblicherweise ist ja die Interrupt Tabelle auf Null, und man springt > an den Begin des Bios, zB auf F000:0000 = F0000. Also entweder steht das > CSEG schon auf F000, oder man muss es so setzen. Es geht um den Resetvektor. Für den muss kein Segmentregister gesetzt werden.
das wär auch plöd ;) Namaste
Danke für die vielen Tips! Ich habe inzwischen einen passenden Blog-Artikel gefunden: http://pete.akeo.ie/2011/06/crafting-bios-from-scratch.html
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.