internen Umzug nicht behoben
ich habe vor kurzem angefangen assembler-Programmierung für arm-cores. Meine erste kleine demos, die nur mit den .text-Abschnitt, lief ohne Probleme.
Als eine logische Erweiterung wollte ich die Struktur der assembler-code in die üblichen Abschnitte: .text .Daten .bss .
Also schrieb ich das folgende einfache Programm:
.globl _start
.section .text
_start:
b main
b .
b .
b .
b .
b .
b .
b .
main:
ldr r0, x
nop
.section .data
x: .word 0xf0f0f0f0
.end
Aber
/opt/arm/bin/arm-as -ggdb -mcpu=arm7tdmi demo.s -o demo.o
beendet sich mit dem Fehler
prog.s: Assembler messages:
prog.s:17: Error: internal_relocation (type: OFFSET_IMM) not fixed up
make: *** [prog.o] Error 1
Ich habe keine Ahnung, warum der assembler meckert über den Umzug, weil ich dachte, das ist die Aufgabe des Linkers. Ich könnte mir vorstellen, dass ich muss sagen, das assembler das meine .data-Abschnitt ist nicht sich an die Letzte Erinnerung postion bei der Montage der Bühne, aber ich kann nicht finden, alles im Zusammenhang.
Obwohl ich einen Weg gefunden, um den code korrekt montiert, durch den Austausch
.section .data
durch
.org .
dass ist keine befriedigende Lösung. Vor allem in Anbetracht der Tatsache, dass die gas-Unterlagen highlight der Sinn dieses Abschnitts.
Vielleicht hat jemand von Euch Experten kann mir helfen, zu gewinnen einige Weisheit
Du musst angemeldet sein, um einen Kommentar abzugeben.
Scheint es der einzige Weg, Sie können es tun, indem du die Adresse der variable und Belastung einen Wert von dieser Adresse.
In einer Art und Weise, diese auch irgendwie Sinn macht. Nach allem, was ist, wenn die Adresse von x (nach Links) ist zu weit Weg für einen PC-relativen-Zugang? Da der compiler (das nicht die Verknüpfung) nicht wissen, wie weit die data-Abschnitt kann aus den text-Abschnitt, es würde sich weigern, zu kompilieren, die code just-in-Fall, dass es nicht erreichbar ist.
Durch die Nutzung dieser indirekten Art und Weise des Zugriffs auf eine variable, es ist garantiert, dass die variable erreichbar sein wird (oder zumindest der compiler sicher sein kann, ob die variable erreichbar ist oder nicht).
Code angepasst von http://www.zap.org.au/elec2041-cdrom/examples/intro/pseudo.s
Ich habe nicht die Absicht diese zu der erwünschten Antwort, aber es bietet einige weitere Einblicke und bieten auch eine unbequeme Lösung, um mit nur einer ldr-Anweisung.
Bei Verwendung dieser zwei-Stufen-ldr-Methode, der assembler fügt tatsächlich weitere 4 bytes der Daten nach dem code! In der .text Abschnitt sogar, diese 4 bytes sind die tatsächliche Adresse, zu Ihrem .Daten-variable. Der erste ldr-Anweisung dann tatsächlich Punkte an diese Adresse, Sie verwenden dann den nächsten ldr zu verwenden, die echte Adresse. Als tangrs wurde diskutiert, diese Doppel-pointer kann ein Weg, um sicherzustellen, dass Ihre Variablen/Konstanten sind erreichbar, vor allem mit der .data-Abschnitt weiter Weg (64k Weg in meinem letzten Lauf).
Blick auf einige Beispiel-code der richtige Weg, dies zu tun:
Den assembler TATSÄCHLICH produziert dies:
Den ersten ldr gerichtet ist 12 bytes nach der Programm-Zähler (als den aktuellen Befehl + acht). Diese Punkte zu Adresse 0x10088 (wie bereits von objdump), die zeigen, auf die andeq Anleitung (nicht ein richtiger Anleitung in diesem Kontext). Es ist wirklich eine Adresse, 0x0002008c, die zeigen, auf unseren die richtige Adresse in der .data-Abschnitt für unsere variable x zu. Jetzt haben wir die Adresse der variable in r0 erhalten wir mit Hilfe der ldr auf, die Adresse zu bekommen der echte Wert. Bemerkenswert ist aber, dass auch wenn der 2. operand in der Quelldatei für diese beiden ldr Anleitung sieht das ganz anders aus, die Maschine Codierung für die gleiche ldr-Codierung; Sie sind beide LDR Sofort (obwohl der erste ldr-Variante ist auch als LDR-Literal, es ist nur LDR Sofort mit 'Rn' fest auf '1111', das ist nur die pc-register sowieso).
Mit all dem im Hinterkopf, wenn es unbequem ist, wir können einen Weg finden, nur die LDR-Unmittelbare(Literal) form einmal. Alles, was wir tun müssen ist, stellen Sie sicher, um die korrekte unmittelbaren Wert (offset), das entspricht unserem realen Daten. Leichter getan als gesagt:
Andere als nur mit einem LDR-Anweisung die gleichen Ergebnisse erzielen, gibt es noch einen weiteren subtilen Unterschied in dieser version der Quelle: es gibt keine .data-Abschnitt. Diese kann getan werden, mit einem data-Abschnitt, aber es würde unsere Daten in einer viel höheren-Adresse, so dass unsere offset so viel größer, dass wir möglicherweise zusätzliche Anweisungen nur, um den offset zu korrigieren. Eine andere Randnotiz ist, weil es in der .text der (r-x) Abschnitt, Sie können nicht str auf Standard. Dies ist eine sehr kleine Barriere, verwenden Sie einfach die option-N für ld und Ihre .text Abschnitt wird nun rwx. Ich bin mir sicher, dass der Letzte Vorschlag wird Wut stackoverflow Götter, komm zu mir 😉