誰でも私たちにここでリンクレジスタの価値をテストする理由を説明することはできますか?
bl check_position
は、リンクレジスタにPC+4
の値を配置し、check_position
もPC相対的に制御を転送します。 bl at ARMこれまでのところすべてはPC
です。
ldr r1,=check_position
は、リテラルプールから値を取得します。 Ref1の実際のコードが
ldr r1,[pc, #offset]
...
offset:
.long check_position # absolute address from assemble/link.
、のように見えるがそうR0
はPC相対バージョンが含まれているとR1
は絶対的に組み立てバージョンが含まれています。ここでは、それらを比較します。また、算術演算を使用して差を計算し、次に0以外の場合はブランチを使用することもできます。コードを絶対宛先にコピーすることもできます。 Ref2がのアドレスにリンクされている場合、R0
とR1
は同じです。これはbl
の場合はpseudo code
です。
mov lr,pc ; pc is actually two instruction ahead.
add pc,pc,#branch_offset-8
キーはBL
がlr
の更新を含むPC
に基づいてすべてのものをないことです。こののトリックを使用する代わりに、PC
が8バイト先であることを除いて、mov R0,PC
を使用できます。もう1つの方法は、adr R0,check_position
を使用して、アセンブラが私たちのためにすべてのアドレス計算を行うようにすることです。
/* Test if we are running from an address, we are not linked at */
check_position:
adr r0, check_position
ldr r1, =check_position
cmp r0, r1 /* ; don't relocate during debug */
beq relocated_entry
Ref1の: GNUアセンブラマニュアルに
Ref2のをArm op-codesと.ltorgを参照してください:これは、Linux head.S
がARM用にやっているまさにです。
編集:私はARMのARMとPCをチェックするコードはこのようなものだった理由を示すことを行くこれは、明らかに現在の命令+8
です。私はadr
バージョンがより直接的で読みやすいと思っていますが、adr
疑似オペレーションは頻繁には使用されていないので、人々はそれに精通していないかもしれません。
2つの優秀な回答ありがとうございました!コードの目的(JTAGプログラムローダの仮定が正しいこと)とそれが正確に動作する方法の2つを説明したので、私がうまくいけば両方を受け入れます。 –