2014-06-13 59 views
0

當我試圖運行調用非常簡單的ARM彙編函數的C程序時,我目前有一個奇怪的問題。這裏是我的C代碼:ARM Assembly - 爲什麼我的應用在調零r7時崩潰?

#include <stdio.h> 
#include <stdlib.h> 

extern void getNumber(int* pointer); 

int main() 
{ 
    int* pointer = malloc(sizeof(int)); 

    getNumber(pointer); 

    printf("%d\n", *pointer); 

    return 0; 
} 

這是我的彙編代碼:

.section .text 
.align 4 
.arm 
.global getNumber 
.type getNumber STT_FUNC 

getNumber: 
    mov r1, #0 
    str r1, [r0] 
    bx lr 

到目前爲止好。但是,如果我在getNumber的頂部添加了一行mov r7, #0,則在嘗試訪問pointer時程序會發生段錯誤。用gdb檢查它之後,我發現指針本身存儲在一個非常低的地址,如0xa。

現在,我做了一些研究,顯然r7是THUMB代碼的幀指針(根據this)。但是,我明確指出我不想在我的彙編代碼中的.arm行中使用THUMB指令。爲什麼它失敗了?

我使用arm-linux-gnueabihf-gcc編譯.c和.s文件,並且在基於Cortex-A8的運行Arch Linux的主板上運行該程序。

編輯:如果我使用-fomit-frame-pointer標誌編譯,程序運行良好。但是,我仍然想知道爲什麼它使用r7作爲幀指針。

編輯2:即使我使用.code 32而不是.arm,它仍然失敗。

回答

-2

我終於明白了:做$ arm-linux-gnueabihf-gcc -v給我看我的編譯器是使用默認選項。其中有:--with-mode=thumb

用-marm編譯固定它。現在它按預期工作!

編輯:在閱讀這裏的評論後,我意識到我錯了。我應該保存/恢復R7,這樣它不會搞砸我的程序的其餘部分。好東西,我現在用一個玩具項目瞭解了這一點,而不是在真正的事情上工作!

+0

所以你的問題應該是「如何禁用GCC中的Thumb ISA擴展?」不知道你在這裏試圖做什麼,你正在用GCC創建彙編代碼,然後向它添加一行彙編? –

+0

我不知道它默認啓用了Thumb,它會忽略我的'.arm'指令。請再讀一遍我的問題。 – Martin

+0

幾乎每個ARM芯片都默認啓用Thumb。如果在不瞭解ISA的情況下向寄存器寫入值就會遇到麻煩,這就是您遇到的情況。另外,.arm指令默認使用Thumb,因爲它是一個幾乎普遍接受的擴展。 –

0

您正在崩潰程序,因爲您正在破壞幀指針,就像您提到的那樣。大會確實沒有任何押韻或理由。只是ARM爲某些事情保留了某些寄存器。有點像在x86 esp是堆棧指針。

這裏是一個不錯的參考的寄存器來避免: http://msdn.microsoft.com/en-us/library/ms253599(v=vs.80).aspx

+0

r7是16位THUMB代碼的幀指針,而不是32位ARM代碼。但是,我發現它爲什麼會崩潰,請看我自己的答案。非常感謝! – Martin

10

ARM Procedure Call Standard指定以下內容:

子程序必須保存寄存器r4-R8,R10,R11和SP中的內容(在PCS和R9變體候R9爲V6)。

所以你的彙編語言子程序必須保存&如果它使用它恢復r7。

通過不編譯Thumb模式,您可能會避免小測試程序出現問題,但您只是意外地避免了這個問題。任何與你的彙編程序相關的東西都有權期望保留r7。

+4

這。一千次這個。在沒有透徹理解所使用的ABI的情況下,將組件與高級語言混合在一起就是爲了解決問題。 – Notlikethat

+0

確實你是對的。在開始編碼之前,我應該想到這種方式。我很好奇,但是:如果我已經像我應該保存/恢復r7一樣,除非我使用-marm編譯它,否則程序仍會崩潰? – Martin

+0

@Phil:我相信即使拇指代碼與臂碼混合,它也能正常工作。 ARM ABI規定應使用ARM與Thumb模式之間的互操作。但是,我認爲可以強制編譯器(通過選項或配置)將* not * default設置爲使用interwork,所以我認爲可能會有非常奇怪的情況/配置,其中調用您的函數的Thumb代碼將不起作用,因爲編譯器可能會不會產生必要的互通電話。 –

相關問題