2012-01-21 91 views
7

我試圖做一些ARM裸機編程與GCC和測試上的QEMU。每當我從C調用ARM標籤時,程序就會掛起。我有一個簡單的代碼示例,顯示https://gist.github.com/1654392處的問題 - 當我在該代碼中調用activate()時,它會掛起。調用ARM彙編

我與objdump的觀察到,當我做BL從組裝到C代碼(從_start)則產生一個小包裝器,切換到拇指的指令。看起來,C代碼全部是用拇指指令生成的,但是我的所有程序集都是在ARM(32位)指令中生成的。我無法弄清楚爲什麼這是或如何解決它。

+0

其中是該編譯器從? –

+0

kernel.o :(。ARM.exidx + 0x0):未定義對'__aeabi_unwind_cpp_pr1'的引用 make:*** [kernel.elf] Error 1 –

+0

你是在試圖構建一個arm linux應用程序嗎?或嵌入式(無操作系統)應用程序?如果一個linux應用程序那麼你不需要啓動代碼,工具鏈應該爲你做所有這些,你擔心main()作爲你的入口點。 –

回答

5

爲了從C中定義的THUMB模式函數中調用在程序集中定義的ARM模式函數,您需要在程序集中定義一個符號作爲函數,並且工具(Linaro gcc)將生成指令而不是bl

實施例:

@ Here, we suppose that this part of code is inside of .code 32 

.type fn, %function 

fn: 
    mov pc, lr 
+0

謝謝!這似乎是完美的,並允許我鏈接庫代碼! – singpolyma

3

http://github.com/dwelch67/yagbat QEMU目錄。

這裏有一對夫婦從手臂調用手臂或拇指的例子

start_vector: 
    mov sp,#0x20000 
    ;@ call an arm function from arm 
    bl notmain 

    ;@ call a thumb function frm arm 
    ldr r0,=0xAABBAABB 
    bl hexstring_trampoline 

    ;@ call a thumb function frm arm 
    ldr r0,=0x12341234 
    ldr r1,hexstring_addr 
    mov lr,pc 
    bx r1 

    ;@ call a thumb function frm arm 
    ldr r0,=0x12312344 
    bl hexstring_trampoline 

hang: 
    b hang 

hexstring_trampoline: 
    ldr r1,hexstring_addr 
    bx r1 

hexstring_addr: .word hexstring 

如果你看看指令集,你會發現你需要使用BX或BLX於ARM和Thumb狀態之間切換。 BLX並不像BX那樣得到廣泛的支持。

從定義的角度來看,程序計數器,PC是超前兩個指令的指令的執行期間。對於拇指是4字節,對於手臂8字節。兩種情況下的說明。爲了模擬一個不能用來改變狀態的BL,你需要加載帶有返回地址的鏈接寄存器,並根據地址的ls位使用bx分支到函數改變狀態。所以

mov lr,pc 
bx r1 
here: 

mov lr,pc上面加載這裏的地址:這是我們的返回地址,bx r1以獨立狀態的方式調用函數。 LR的地址LSbit表示方式返回,你需要經常使用BX返回

pre_thumb: 
ldr pc,lr 

thumb_capable: 
bx lr 

編譯器分配BL指令調用函數,鏈接器填充其餘的以後,如果太遠遠達不到,那麼它需要鏈接器自己添加的蹦牀功能。同樣,如果你需要改變模式,bl會調用一個蹦牀函數。我仿照上面的一個模擬,你可以看到它有點浪費,希望我對編譯器的解釋只是爲BL分配空間使得更清晰,浪費將是總是計劃模式更改,並且必須爲代碼中的大部分函數調用插入nops。

代碼還包括呼叫從拇指彙編手臂:

.thumb 

.thumb_func 
.globl XPUT32 
XPUT32: 
    push {lr} 
    ;@ call an arm function from thumb asm 
    ldr r2,=PUT32 
    mov lr,pc 
    bx r2 
    pop {r2} 
    bx r2 

大致相同,除了你不能彈出的拇指模式,LR,你可以彈出到PC,但我不認爲切換模式,所以你不能使用它,你需要一個備用註冊表。當然,你需要知道的調用約定知道註冊就可以使用,或者你可以換另一套推動和彈出保存所有,但LR

push {r2,lr} 
    ;@ call an arm function from thumb asm 
    ldr r2,=PUT32 
    mov lr,pc 
    bx r2 
    pop {r2} 
    mov lr,r2 
    pop {r2} 
    bx lr 

拇指以拇指或手臂武裝你只需要使用一個BL如果你能達到。 ldr pc,地址如果你不能。

0

如果您將彙編語言代碼組裝爲Thumb,則需要將該函數標記爲Thumb函數,以便鏈接器在分支給它時使用正確的指令(例如BLX或BX到設置了低位的地址)。這是完成的。thumb_func指令:

.global activate 
.thumb_func 
activate: 
    b test 

另一種選擇是明確要求彙編程序生成的ARM代碼:

.code 32 
.global activate 
activate: 
    b test 

檢查this article過,但請記住,目前的處理器並不需要在在ARMv4是必要的許多變通方法,所以你可能不應該盲目追隨它。

0

爲了消除混亂:

的問題是,Ubuntu的GCC交叉編譯爲ARM默認生成拇指(16位)的指令。正如其他答案所示,兩者之間的調用是可能的,但是雖然GNU彙編程序檢測到C代碼正在生成拇指指令,因此用bx快速生成墊片以正確設置調用 C的模式,但我無法控制通過GCC本身爲調用函數生成的內容,並且它只是用bl來調用它們,因爲我的彙編代碼需要是ARM指令(32位),因此破壞了它們。

解決方案(文檔記錄不完善)是發送gcc -marm,它至少會使所有代碼的類型相同。

如果有一個開關讓gcc爲函數生成bx調用,那可能也會起作用。

+0

gcc -marm不適用於我。我需要arm-v4t-linux-gnueabi的彙編代碼 –