Von
|
Das erweiterte Hunkformat (EHF)Unter spezieller Beachtung der Assemblerprogrammierung1. EinleitungDas erweiterte Hunkformat wurde entwickelt, damit PPC-Software auf dem AMIGA möglichst optimal in das bestehende Betriebssystem integriert werden kann. Deswegen wurde das bestehende Hunkformat des AMIGA mit einigen wenigen Erweiterungen versehen, um es PPC- tauglich zu machen. Die Erweiterungen beziehen sich alle auf Objekt-Dateien. Das Format der Executables hat sich nicht verändert. 2. Neue Hunk-Kennungen:HUNK_PPC_CODE = $4e9 Dies entspricht genau dem bereits bestehenden HUNK_CODE, nur enthält ein Hunk mit der Kennung HUNK_PPC_CODE PowerPC-Code. Es kann auch jeder andere HUNK_CODE Maschinencode für den PPC enthalten, aber der StormLINK prüft anhand dieser Kennung nach, ob es sich um PPC-Code handelt, der ja in vielen Fällen anders behandelt werden muß als Code für den 68k. HUNK_RELRELOC26 = $4ec Dies entspricht im Wesentlichen dem bestehenden HUNK_RELRELOC16 (derselbe Aufbau). Der zu korrigierende Wert ist hier 4 Bytes groß, wobei nur die niederwertigsten 26 Bits korrigiert werden dürfen, da die obersten 6 Bits zum Opcode gehören (der nicht überschrieben werden darf). Dieser Hunk wird dann verwendet, wenn mittels dem PowerPC-Befehl 'bx' in eine andere Code- Sektion verzweigt wird (ist ohnehin nur im Smallcode-Modus möglich). Der 'bx'-Befehl ist ein Branch-Befehl, dessen Displacement 26 Bit groß ist. EXT_RELREF26 = 229 Dies entspricht dem bestehenden EXT_RELREF16. Das heißt, diese Kennung kann nur in einem HUNK_EXT vorkommen. Das zu korrigierende Displacement ist ebenfalls 26 Bit groß (siehe auch HUNK_RELRELOC26). Diese Kennung wird dann verwendet, wenn mittels dem PowerPC-Befehl 'bx' an eine externe Adresse verzweigt wird (ist nur im Smallcode-Modus möglich). Im Ausführbaren Programm werden keine der hier aufgelisteten Kennungen mehr auftauchen. Die einzige Ausnahme ist der HUNK_PPC_CODE, der unter p.OS/PPC eine gültige Kennung sein wird. 3. DatenmodelleDa alle PowerPC-Befehle 4 Bytes lang sind, ist es nicht möglich, absolut auf Variablen oder sonstigen Speicher zuzugreifen. Alle Speicherzugriffe müssen relativ, bezogen auf eine Basis, geschehen. Für Variablenzugriffe ist die Basis definitionsgemäß das Register r2. Es gibt grundsätzlich zwei Datenmodelle: SmallData und LargeData. Es ist allerdings zu beachten, daß selbst im großen Datenmodell Speicherzugriffe relativ geschehen. Es folgt eine Beschreibung der beiden Datenmodelle: SmallData:Ein Programm, welches im SmallData-Modus erstellt wurde, enthält nur noch einen Data-BSS- Hunk. Das ausführbare Programm bekommt beim Programmstart in r2 die Startadresse dieses Hunks übergeben. Alle Variablen können dann relativ zu dieser Basis geladen/gespeichert werden. Die Größe des SmallData-Hunks muß kleiner 64KByte sein. LargeData:Ein Programm, welches im LargeData-Modus erstellt wurde, kann beliebig viele Data- und BSS- Hunks enthalten. Um auf Variablen zugreifen zu können, wird ein zusätzlicher Data-Hunk benötigt (der sogenannte TOC-Hunk). Für jede Variable, die im Programm existiert, wird ein Zeiger auf die Variable im TOC-Hunk plaziert. Beim Programmstart erhält das ausführbare Programm in r2 die Startadresse des TOC-Hunks. Um eine Variable zu laden, muß zunächst der entsprechende Zeiger aus dem TOC-Hunk gelesen werden und danach der Inhalt der Variablen. Die Variablenzugriffe sind im LargeData-Modell natürlich langsamer, da zwei Speicherzugriffe benötigt werden. 4. Zugriff auf Variablen in AssemblerIm kleinen Datenmodell ist es NICHT möglich, auf Daten in Code-Sektionen zuzugreifen. Deshalb wird dringend empfohlen, selbst im großen Datenmodell keine Daten aus Code- Sektionen zu lesen. Wenn beispielsweise die Adresse einer PPC-Funktion ermittelt werden soll, sollte das mit Hilfe eines Hilfszeigers in einer Data-Sektion geschehen. Die Adresse einer Variablen wird in Assembler mittels dem 'la'-Befehl (erweitertes Mnemonic) ermittelt. Je nach Datenmodell wird der la-Befehl unterschiedlich assembliert. Der Befehl la r3,label wird im kleinen Datenmodell zu addi r3,r2,disp ;disp ist der Offset von 'label' zum HunkStart und im großen Datenmodell zu lwz r3,disp(r2) ;disp ist der Offset des Zeigers auf 'label' von der Startadresse der TOC-Sektion assembliert. Deswegen ist es sehr komfortabel, mit dem 'la'-Befehl zu arbeiten, da der Assembler die Unterscheidung macht, nicht der Programmierer. Das direkte Auslesen einer Variablen oder das direkte Schreiben auf eine Variable ist weitaus problematischer. Im kleinen Datenmodell genügt hier z.B. ein einfacher 'lwz'-Befehl, während im großen Datenmodell zwei Lade- bzw. Speicher-Befehle benötigt werden. Es ist nun für den Programmierer unakzeptabel, daß er sich bei der Erstellung einer Software auf ein Datenmodell festlegen muß. Auch hier sollte die Unterscheidung vom Assembler gemacht werden. Der Storm-PowerASM-Assembler unterstützt eine ganze Reihe von Pseudo-Mnemonics, die genau diese Unterscheidung automatisch vornehmen. Diese Befehle können sowohl als Makros wie auch als zusätzliche Direktiven implementiert werden. Es ist sehr wichtig, daß die Syntax und die Funktionen dieser Pseudo-Befehle von anderen Assemblern exakt gleich implementiert werden! Es folgt eine Uebersicht über alle Pseudo-Mnemonics zum Laden und Speichern von Variablen: lw rx,variable ;Laden einer Langwort-Variablen lh rx,variable ;Laden einer Wort-Variablen (vorzeichenlos) lhs rx,variable ;Laden einer Wort-Variablen (vorzeichenbehaftet) lb rx,variable ;Laden einer Byte-Variablen (vorzeichenlos) lbs rx,variable ;Laden einer Byte-Variablen (vorzeichenbehaftet) lf fx,variable ;Laden einer Fließkomma-Variablen (Double) ls fx,variable ;Laden einer Fließkomma-Variablen (Single) sw rx,variable ;Speichern einer Langwort-Variablen sh rx,variable ;Speichern einer Wort-Variablen sb rx,variable ;Speichern einer Byte-Variablen sf fx,variable ;Speichern einer Fließkomma-Variablen (Double ) ss fx,variable ;Speichern einer Fließkomma-Variablen (Single ) Wichtig: Das Datenregister darf NIE r0 sein. Diese Pseudo-Mnemonics funktionieren definitionsgemäß nicht im großen Datenmodell, wenn r0 verwendet wird. Einige Beispiele zu den Pseudo-Mnemonics: section code lw r5,var1 ;r5 = $abcdabcd lh r5,var2 ;r5 = $00001234 lhs r5,var3 ;r5 = $fffffedc lf f3,fvar ;f3 = 3.141 ls f0,fvar2 ;f0 = 1.6666 sw r5,var4 ;$fffffedc wird nach 'var4' geschrieben sb r5,var5 ;$dc wird nach 'var5' geschrieben section data var1 dc.l $abcdabcd var2 dc.w $1234 var3 dc.w $fedc fvar dc.d 3.141 fvar2 dc.s 1.6666 var4 dc.l 0 var5 dc.b 0 |
|