2017-02-28 599 views
0

我想弄清楚在ARM程序集中數組是如何工作的,但我只是不知所措。我想初始化一個大小爲20的數組爲0,1,2等等。ARM彙編數組

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

我什至不知道如何打印什麼,我必須看看,如果我做得正確。這是我到目前爲止:

.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迷惑了我,因爲它是,我不知道我做錯了什麼。如果任何人都可以幫助我更好地理解這種工作方式,將不勝感激。

+1

使用調試器,你會看到如果你做得對。你的數組處理看起來不錯,但打印部分是錯誤的。檢查如何在您的平臺上使用printf。 –

+0

'str r2,[r3] @ r3 = r2'該評論是錯誤的,不是'r3'會改變,但內存內容會改變。在由'r3'值指向的地址處。 'mov r2,#0 @ index r2 = 0'有點......你用'r2'作爲索引和值,這實際上是很好的,但是我會從註釋中忽略單詞「index」。 'ldr r1,= a @ r1給數組的索引點'r1'是數組(第一個元素)的地址,而不是索引。 (其餘部分如上面薩米寫過的,數組代碼看起來不錯,printf完全是borked,並使用調試器來檢查內存內容並註冊內容) – Ped7g

+0

是你想要創建一個單詞數組還是字節數組?你做了一連串的單詞,如果那是你想要的,那很好。 –

回答

0

如上所述,您的printf有問題,您可以使用工具鏈本身來查看調用約定是什麼,然後符合這一點。

#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: 

調用約定通常爲R0第一參數,第二中R1,第三在R2到R3然後使用堆棧。有很多例外,但我們可以在這裏看到,printf調用通常可以正常工作的編譯器需要r0格式字符串的地址。 a的值分別爲r1和r2中b的值。

您的printf在r0中有字符串,但帶有該格式字符串的printf調用需要三個參數。

上面的代碼使用了尾部優化和分支來printf,而不是調用它並返回。臂慣例,這些天更喜歡堆在64位邊界對齊,這樣你就可以把一些寄存器,你不要一定注意保留的推/流行,以保持該路線

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

它肯定不會傷害你這樣做,它可能會也可能不會傷害,不取決於下游的假設。

假設r1(標籤a)是一個字對齊的地址,您的設置和循環應該正常工作。如果你弄亂了你的字符串,它可能會也可能不會,如果你把字符串放在首位,那麼應該先放置一個字符串,或者在放置一個對齊語句之前先確保數組是對齊的。有指令集功能,可以簡單的代碼,但它看起來功能。