2016-03-06 26 views
0

我想爲Raspberry Pi B +版本編寫一個非常基本的交叉編譯器來構建簡單的裸機程序。我的編譯器能夠使用ARM指令集數據表將簡單命令翻譯成相應的機器語言指令。ARMv6在裸機編程分支(樹莓派B +)

打開發光二極管(定位自己在烘烤pi當然,http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/)工作正常。

但現在我希望做一些分支指令,而這正是似乎沒有任何工作了:

首先,我想跳轉到絕對addresse,沒有相對分支使用B/BL指令。

要測試一個分支,我使用下面的反彙編代碼(使用料斗拆裝V3測試版拆解),至極開啓與GPIO 16 AND22連接的LED:

00000000 mov r0, #0x20000000  ;Load the GPIO Base Address into R0 
00000004 orr r0, r0, #0x200000 
00000008 mov r1, #0x40   ;Load the Set Function Mask (for GPIO 22) into r1 
0000000c str r1, [r0, #0x8]  ;Store the Set Function Mask into the GPFSEL2 
00000010 mov r1, #0x400000  ;Move the Set Output Mask (for GPIO 22) into r1 
00000014 str r1, [r0, #0x1c]  ;Store the Set Output Mask into GPSET0 

00000018 mov r0, #0x20000000  ;Load the GPIO Base Address into R0 
0000001c orr r0, r0, #0x200000 
00000020 mov r1, #0x40000  ;Load the Set Function Mask (for GPIO 16) into r1 
00000024 str r1, [r0, #0x4]  ;Store the Set Function Mask into the GPFSEL2 
00000028 mov r1, #0x10000  ;Move the Set Output Mask (for GPIO 16) into r1 
0000002c str r1, [r0, #0x1c]  ;Store the Set Output Mask into GPSET0 

00000030 b 0x30     ;Infinity Loop to keep the processor up 

現在我想在代碼的開頭添加一個分支,跳過第一部分,這樣只有第二個LED被激活。

我試了一下這樣的:

mov r15, #0x1c 

但唯一的效果是兩個LED留下暗。

我的第二次嘗試是這樣的:

mov r2, #0x20 
bx r2 

但是,無論是作品。

所以我的問題是:

  • 如何執行這樣的分支?
  • 我是否正確使用地址?
+0

這可能是一個有趣的學習練習,gcc有一個'-white'選項來構建不依賴任何庫的代碼。我假設GNU彙編程序可以將ARM asm組裝成一個扁平的二進制文件,所以你可以使用它來編寫啓動代碼,以便運行你的編譯器輸出函數。據我瞭解,這基本上是如何構建Linux內核的:大多數是C語言,其中包含一些用於設置的asm,以及一個構建內核映像而不是ELF可執行文件的構建過程。 –

回答

0

感謝來自@TimothyBaldwin提示我現在已經得到了答案(我希望它好,如果我寫了自己的答案提供更多細節而不是簡單地接受他的一個)。

正如@TimothyBaldwin所提到的那樣,問題在於Programm在0x8000處加載,正如您在https://raspberrypi.stackexchange.com/questions/10442/what-is-the-boot-sequence的圖表中看到的那樣。

正如所解釋的存在,在我的情況下,它完美的作品很好,如果我添加到我的config.txt以下行:

disable_commandline_tags=1 

,因爲這樣的代碼是在爲0x0加載,一切都按預期工作。

0

您正在分支到錯誤的地址,您的程序在0x8000加載。如果你使用標籤,鏈接器應該爲你計算地址。

+0

你從哪裏得到這些信息?我目前沒有使用匯編器/鏈接器,因爲我想自己做這些東西來學習。 – Marben

+0

最好的學習場所是從工作的工具。使用gnu binutils進行組裝,然後拆卸,並看看指令是如何構建的,如果是好的,不要總是爲每種情況繪製精確的圖片。 –

+0

或者如果你拒絕使用工作的彙編器,那麼至少應該使用反彙編器來檢查你創建的代碼。 –

0

雖然我不知道Raspbery皮寄存器,我覺得有幾個問題,在此代碼:

  • 這個程序似乎點亮LED,不脫。所以,即使你分支,它也不會眨眼。您需要一個寄存器,在該寄存器中反轉該值,以便在環路期間LED處於開/關狀態。
  • 沒有一些延遲,看到LED閃爍將非常快。你可以添加一個延遲(庫函數),一個來自定時器的中斷,或者只是一個for循環(這將是一個分支)。

順便說一句,在for循環的延遲可能是這樣的:

 MOV r0, #1000 ; Start of the counter 
loop: SUBS r0, #1  ; Decrement the counter (Sets the flags for the branch) 
     BNE loop  ; Branch to loop label until r0 is 0 
+0

也許我在配方中有點不清楚,我的目標是不讓LED閃爍,代碼只是通過跳過一個LED的代碼來測試分支是否實際工作,因此,那裏只是一個LED發光。 – Marben

1

Bx的或BLX應該是你的第一選擇的說明。你可以彈出到電腦,但爲什麼設置註冊表,推,和流行,只是BX。還有一些其他的可以正確修改電腦,不知道如果mov是一個,但手臂文件會告訴你。

如果bx不適合你,那麼你要麼編碼bx錯誤,要麼你不把地址放在寄存器右邊。

mov r3,#0x12000000 
orr r3,r3,#0x00340000 
orr r3,r3,#0x00005600 
orr r3,r3,#0x00000078 
bx r3 

產生

0: e3a03412 mov r3, #301989888 ; 0x12000000 
    4: e383370d orr r3, r3, #3407872 ; 0x340000 
    8: e3833c56 orr r3, r3, #22016 ; 0x5600 
    c: e3833078 orr r3, r3, #120 ; 0x78 
    10: e12fff13 bx r3 

,將跳轉到地址爲0x12345678

+0

,你可以根據需要混淆條件字段。 –