qemuディレクトリを参照してください。あなたは、命令セット・リファレンスを見れば、あなたはARMおよびThumb状態の間で切り替えるようにBXまたはBLXを使用する必要があることがわかります
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
ここ
が腕から腕や親指を呼び出すの例のカップルです。 BLXはBXほど広くサポートされていません。
定義の観点からは、プログラムカウンタpcは、命令実行中の2命令先です。アーム8バイトの場合は4バイトのサムについて。いずれの場合も2つの命令。状態を変更するのに使用できないblをシミュレートするには、リンクレジスタに戻りアドレスをロードし、bxを使用してアドレスのlsbitに応じて関数変更状態に分岐する必要があります。そう
mov lr,pc
bx r1
here:
MOV LRが、PCは上記ここのアドレスロード:私達のリターンアドレスで、状態に依存しない方法でBX r1が関数を呼び出します。コンパイラは関数を呼び出すためのBL命令を割り当てLRアドレスの最下位ビットがに戻るにはモードを示し、あなたは常に
pre_thumb:
ldr pc,lr
thumb_capable:
bx lr
を返すためにBXを使用する必要があり、それはあまりにもあれば、リンカは、後の残りの部分を埋め遠いところにはリンカーが追加しているトランポリン機能が必要です。同様に、モードを変更する必要がある場合、blはトランポリン機能を呼び出します。私は上記のうちの1つを模倣して、それは少し無駄であることがわかります。blのスペースを割り当てるだけのコンパイラについての私の説明は、より明確で無駄なことは常にモード変更を計画することですコードの大部分の関数呼び出しにnopを挿入する必要があります。
コードもアセンブラで親指から腕への呼び出しが含まれています
.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に開くことができますが、私はそれがモードを切り替え思ういけません、あなたはそれを使用することはできませんので、再び予備のレジスタが必要です。もちろん、あなたが使用することができます登録するかを知るために呼び出し規則を知っておく必要があります。また、プッシュの別のセットをラップすることができますし、親指またはあなただけのBLを使う武装させるアーム親指
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
LR以外のすべてを維持するためにポップあなたが達することができるならば。 ldr pc、あなたが傾けていない場合のアドレス。
このコンパイラから提示されましたか? –
kernel.o :(。ARM.exidx + 0x0):未定義の参照__aeabi_unwind_cpp_pr1 make:*** [kernel.elf]エラー1 –
あなたはアームのLinuxアプリケーションを構築しようとしていますか?または組み込み型(オペレーティングシステムなし)のアプリケーションですか? Linuxアプリケーションの場合は、スタートアップコードを必要としないので、toolchainはすべてのことを行う必要があります。main()についてはエントリーポイントとして心配してください。 –