ARM Assembler-Frage

Gast #258687
Lesenswert?

so einen Befehl gibt es nicht,
jedenfalls nicht im "ARM Instruction Set Quick Reference Card v2.1"
('QRC0001H_rvct_v2.1_arm.pdf' von
<http://www.arm.com/documentation/Instruction_Set/index.html>;)

dort gibt es "LDR{cond} Rd,<a_mode2>" (Seite 4)
und in der Tabele "Addressing Mode 2" (Seite 5) gibts kein
32Bit-Wert

schein auch logisch da die Befehle ja offensichtlich nur 32Bit gross
sind

Also wie bekomme ich eine 32Bit-Konstante in ein Register ??

Grüße
Erik
Gast #258690
Lesenswert?

> Ein LDR kann also zu zwei 32 Bit Wörtern führen.
> Der Opcode selbst und die Konstante.
also so ein Doppel-Word-Befehl wie bei AVR oder PIC üblich?
Braucht der dann auch 2 Tackte für seine Abarbeitung?
Ich kann mir das noch nicht so richtig vorstellen weil in der
"Quick Reference" sowas einfach nicht drin steht,
gibts da vielleicht was besseres (mit mehr als 6 Seiten) ??

Grüße
Erik the Vikinger
Persönliche Seite #258693
Lesenswert?

Hi

das ist kein klasicher 2 Zyklen Befehl wie man ihn von anderen
Prozossoren kennt. ARMs sind näher am RISC-Konzept als z.B. die AVRs
und haben wirklich nur eine Befehlswortlänge von 32 Bit.

Mit "richtigen" ARM Assemblerbefehlen kannst du keine beliebigen 32
Bit Konstanten in ein Register laden. Du mußt im Prinzip das Verhalten
des ARM-Assemblers imitieren und eine Konstante an einer Adresse
ablegen und diese dann mit einem Befehl laden.

Matthias
Gast #258694
Lesenswert?

> eine Konstante an einer Adresse ablegen
> und diese dann mit einem Befehl laden
aber die Adresse vor der Speicherstelle ist doch auch wieder eine
32Bit-Konstante?

für "ldr r0,[r1]" muss ich doch auch wieder r1 mit etwas sinvollem
laden

Grüße
vom grübelnden Erik
Gast #258696
Lesenswert?

Der übliche Weg: Die Konstanten werden irgendwo im Umkreis von +/- 4KB
um den aktuellen PC herum abgelegt. Geladen werden sie dann mit
        LDR Rx, [PC, #Distanz]

Um das etwas zu vereinfachen, versteht mindestens der GNU-Assembler
auch die Kurzform
        LDR Rx, =Konstante
Die Konstante (engl: literal) merkt sich der Assembler im "literal
pool" und plaziert dessen angesammelten Inhalt im Speicher, wenn das
Statement ".pool" bzw ".ltorg" kommt, oder am Ende vom Quelltext.
Gast #258697
Lesenswert?

Aha, wieder was neues gelernt.

Aber wenn ich eine Function, größer als 8kB, hab dann klappt das in der
Mitte nicht mehr, oder?? Da müsste ich dann in die Function gebenenfalls
eine Lücke, dort dann ein ".pool" rein, einbauen und diese
überspringen.

Hab ich das jetzt richtig verstanden?

Grüße
Erik
Gast #258700
Lesenswert?

Zwei Zusatzfragen hab ich dann aber doch noch zu dieser relativen
Adressierungsart :

wie kommt ihr auf die "+/- 4KB"?

im PDF steht "[Rn,#+/-<immed_12>]"
bedeutet das das im Opcode das Vorzeichen (bzw. die Info ob "+" oder
"-") zusätzlich zu dem 12Bit-Immed drin ist oder wird dafür das
oberste Bit vom Immed benutzt?

Was ist mit den unteren 2 Bits, müssen die immer 0 sein?
Wenn ja dann könnte man doch den Immed immer unm 2 Bits nach links
schieben und so den addressierbaren Bereich vervierfachen.

Grüße
Erik
Gast #1154703
Lesenswert?

ich schließ mich mal bei dem Thread an, ich hab nämlich auch gerade ein 
Problem und zwar mit dem Sprung vom Initialisierungscode zu meiner C 
main Routine. Das ASM Fragment stammt aus einem anderen Programm, wo 
=main kleiner als 12 Bit war. Nur jetzt ist im ersten Segment noch ein 
Bootloader davor und meine main Routine liegt nun auf 0x2528h, wenn ich 
das jetzt so mache wird natürlich alles über 12Bit weggeschnitten und 
ich springe auf 0x529h soweit so gut.

Irgendwie sollte das ja auch relative zum PC addressiert werden können 
dieser steht hier ca bei 0x20F0h aber wie?

Leider bin ich in Assembler nicht wirklich fit, wie könnte eine einfache 
Lösung für mein Problem aussehen?
1
        mov   r0,#0                     // no arguments (argc = 0)
2
        mov   r1,r0
3
        mov   r2,r0
4
        mov   fp,r0                     // null frame pointer
5
        mov   r7,r0                     // null frame pointer for thumb
6
        ldr   r10,=main
7
        mov   lr,pc
8
        bx    r10                       // enter main()
Persönliche Seite #1155012
Lesenswert?

Thomas wrote:
> Das ASM Fragment stammt aus einem anderen Programm, wo =main kleiner
> als 12 Bit war. Nur jetzt ist im ersten Segment noch ein Bootloader
> davor und meine main Routine liegt nun auf 0x2528h, wenn ich das
> jetzt so mache wird natürlich alles über 12Bit weggeschnitten und
> ich springe auf 0x529h soweit so gut.

Wieso natürlich ?

> Irgendwie sollte das ja auch relative zum PC addressiert werden können
> dieser steht hier ca bei 0x20F0h aber wie?
>
> Leider bin ich in Assembler nicht wirklich fit, wie könnte eine einfache
> Lösung für mein Problem aussehen?

Genauso. Die Adresse von main wird aus einem literal pool aus 
beliebigen 32bit Werten geladen. Es ist daher völlig egal wo sich main() 
befindet. Der Eintrag im pool muss sich innerhalb von +-4K (+-12bit) 
vom PC befinden. Und dafür sollte der Assembler sorgen.

Es würde möglicherweise helfen, das Disassembly zu sehen. Dann weiß man 
was wirklich aus diesem Code gemacht wurde.

Gruß
Marcus
http://www.doulos.com/arm/
Gast #1155018
Lesenswert?

>Mit "richtigen" ARM Assemblerbefehlen kannst du keine beliebigen 32
>Bit Konstanten in ein Register laden. Du mußt im Prinzip das Verhalten
>des ARM-Assemblers imitieren und eine Konstante an einer Adresse
>ablegen und diese dann mit einem Befehl laden.

Es gibt ARM-Befehle, die eine Shift-Operation enthalten. Die genaue 
Syntax habe ich jetzt nicht parat.
Aber damit kann man z.B. einen Wert wie 0x1234000 in ein Register laden.
Im Befehl codiert ist nur die Konstante 0x1234 und eine 12, um die 
Anzahl Bits die Konstante vor dem Laden nach links geschoben wird.
Damit passt der Befehl in 32 bit hinein, die Konstanten sind aber im 
Wertebereich eingeschränkt.

Gruß,
Martin
Gast #1155093
Lesenswert?

Also, wenn ich mich richtig erinnere (hab' das letzte mal ARM Assembler 
auf einem Acorn RISC PC benutzt), dann hatte der eingebaute Acorn 
Assembler einen Pseudo-Befehl oder Macro zum Laden von Konstanten in ein 
Register gehabt, und diesen in eine Sequenz von einem MOV gefolgt von 
(je nach Art der Konstante) 0-2 ORR oder AND (evtl auch ADD/SUB/RSB, ich 
weiss das nicht mehr so genau) Befehlen umgesetzt.

D.h. um z.B. &1234567 in R0 zu laden, machte der Assembler im 
schlimmsten Fall sowas wie:
MOV R0, #&12000000
ORR R0, R0, #&230000
ORR R0, R0, #&4500
ORR R0, R0, #&67

(Syntax und Befehle aus'm Kopf.)
Ich glaube, Konstanten bei "echten" ARM Befehlen waren darauf 
beschränkt, dass sie sich aus einer 8 Bit Zahl konstruiert werden, die 
um einen gerade Anzahl an Stellen in dem 32 Bit Zahlenbereich rotiert 
wird.
D.h. MOV R0, #&F000000F geht z.B. auch in einem Rutsch.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren