2017-02-28 1 views
0

Ich versuche herauszufinden, wie Arrays in ARM-Assembly arbeiten, aber ich bin nur überwältigt. Ich möchte ein Array der Größe 20 auf 0, 1, 2 und so weiter initialisieren.ARM Assembly Arrays

A[0] = 0 
A[1] = 1 

Ich kann nicht einmal herausfinden, wie zu drucken, was ich zu sehen habe, wenn ich es richtig gemacht habe. Das ist, was ich habe, so weit:

.data 
.balign 4  @ Memory location divisible by 4 
     string: .asciz "a[%d] = %d\n" 
     a:  .skip 80  @ allocates 20 
.text 
.global main 
.extern printf 

main: 
     push {ip, lr}  @ return address + dummy register 
     ldr  r1, =a   @ set r1 to index point of array 
     mov  r2, #0   @ index r2 = 0 
loop: 
     cmp  r2, #20   @ 20 elements? 
     beq  end    @ Leave loop if 20 elements 
     add  r3, r1, r2, LSL #2  @ r3 = r1 + (r2*4) 
     str  r2, [r3]  @ r3 = r2 
     add  r2, r2, #1  @ r2 = r2 + 1 
     b  loop   @ branch to next loop iteration 
print: 
     push {lr}   @ store return address 
     ldr  r0, =string  @ format 
     bl  printf   @ c printf 
     pop  {pc}   @ return address 

ARM mich verwirrt genug, wie es ist, ich weiß nicht, was ich falsch mache. Wenn jemand mir helfen könnte, besser zu verstehen, wie das funktioniert, würde das sehr geschätzt werden.

+1

Verwenden Sie einen Debugger und Sie werden sehen, ob Sie es richtig machen. Ihr Array-Handling sieht gut aus, der Druckteil ist jedoch falsch. Überprüfen Sie, wie printf in Ihrer Plattform verwendet wird. –

+0

'str r2, [r3] @ r3 = r2' Der Kommentar ist falsch, es ist nicht das' r3' wird sich ändern, aber der Speicherinhalt wird sich ändern. Bei der Adresse, auf die der Wert "r3" zeigt. Auch 'mov r2, # 0 @ index r2 = 0 'ist ein bisschen ... Sie verwenden' r2' sowohl als Index als auch als Wert, was eigentlich nett ist, aber ich würde das Wort "index" aus dem Kommentar dann weglassen. 'ldr r1, = a @ set r1 zum Indexpunkt des Arrays' 'r1' ist die Adresse des Arrays (des ersten Elements), nicht index. (Rest wie Sami oben geschrieben hat, Array-Code sieht gut aus, printf ist komplett durchgebrannt und benutzt den Debugger, um den Speicherinhalt zu überprüfen und Inhalt zu registrieren) – Ped7g

+0

wolltest du ein Array von Wörtern oder ein Array von Bytes machen? du hast eine Reihe von Wörtern gemacht und das ist in Ordnung, wenn du das wolltest. –

Antwort

0

Wie bereits erwähnt, hat Ihr printf Probleme, Sie können die Toolchain selbst verwenden, um zu sehen, was die Aufrufkonvention ist, und sich dann daran halten.

#include <stdio.h> 
unsigned int a,b; 
void notmain (void) 
{ 
    printf("a[%d] = %d\n",a,b); 
} 

00001008 <notmain>: 
    1008: e59f2010 ldr r2, [pc, #16] ; 1020 <notmain+0x18> 
    100c: e59f3010 ldr r3, [pc, #16] ; 1024 <notmain+0x1c> 
    1010: e5921000 ldr r1, [r2] 
    1014: e59f000c ldr r0, [pc, #12] ; 1028 <notmain+0x20> 
    1018: e5932000 ldr r2, [r3] 
    101c: eafffff8 b 1004 <printf> 
    1020: 0000903c andeq r9, r0, ip, lsr r0 
    1024: 00009038 andeq r9, r0, r8, lsr r0 
    1028: 0000102c andeq r1, r0, ip, lsr #32 

Disassembly of section .rodata: 

0000102c <.rodata>: 
    102c: 64255b61 strtvs r5, [r5], #-2913 ; 0xb61 
    1030: 203d205d eorscs r2, sp, sp, asr r0 
    1034: 000a6425 andeq r6, sl, r5, lsr #8 

Disassembly of section .bss: 

00009038 <b>: 
    9038: 00000000 andeq r0, r0, r0 

0000903c <a>: 
    903c: 

die Aufrufkonvention gibt, ist im allgemeinen in erster Parameter r0, r1 in zweiten, der dritten in r2 bis r3 dann den Stapel verwenden. Es gibt viele Ausnahmen, aber wir können hier sehen, dass der Compiler, der normalerweise mit einem printf-Aufruf funktioniert, die Adresse der Formatzeichenkette in r0 haben möchte. der Wert von a dann der Wert von b in r1 bzw. r2.

Ihr printf hat die Zeichenfolge in r0, aber ein printf-Aufruf mit dieser Formatzeichenfolge benötigt drei Parameter.

Der obige Code verwendet eine Tail-Optimierung und verzweigt zu printf, anstatt es aufgerufen und zurückgegeben von. Der Arm Konvention zieht es in diesen Tagen der Stapel auf 64-Bit-Grenzen ausgerichtet werden, so können Sie einige Register setzen, müssen Sie nicht unbedingt kümmern auf dem Push/Pop, um zu bewahren, die Ausrichtung zu halten

push {r3,lr} 
... 
pop {r3,pc} 

sicherlich gewohnt weh tun Sie dies, es kann oder kann nicht schaden, es nicht zu tun, abhängig davon, was Downstream annimmt.

Ihr Setup und die Schleife sollten gut funktionieren, vorausgesetzt, dass r1 (label a) eine wortausgerichtete Adresse ist. Was es sein mag oder nicht, wenn Sie sich mit Ihrer Zeichenkette anlegen, sollten Sie zuerst eine Zeichenkette oder eine andere Zeichenkette setzen, bevor Sie sicherstellen, dass das Array ausgerichtet ist. Es gibt Befehlssatz-Funktionen, die einfach den Code enthalten können, aber so wie er funktioniert.