2013-03-27 6 views
5

アセンブリに書かれたベアメタルARM用のブートアップコードがありますが、その動作方法を理解しようとしています。バイナリはいくつかの外部フラッシュで書かれており、起動時にRAMの中に自分自身の一部をコピーしています。私はこの文脈で移転の概念を正確には得ていませんでしたが、私はこれを読んでいましたが、wikipedia entryです。 RAMは低アドレスウィンドウにマップされ、高アドレスウィンドウにフラッシュされます。誰かがここで私たちがなぜリンクレジスタの価値をテストするのかを私に説明することはできますか?アセンブリでのリロケーション

/* Test if we are running from an address, we are not linked at */ 
     bl check_position 
check_position: 
     mov  r0, lr     
     ldr  r1, =check_position 
     cmp  r0, r1     /* ; don't relocate during debug */ 
     beq  relocated_entry 
+0

2つの優秀な回答ありがとうございました!コードの目的(JTAGプログラムローダの仮定が正しいこと)とそれが正確に動作する方法の2つを説明したので、私がうまくいけば両方を受け入れます。 –

答えて

5

私の推測では、ラムからアプリケーションを実行して、アプリケーションをデバッグするときに、この著者は、おそらく(したがって、RAMに直接テストアプリケーションをロードするためにコピーして実行する理由をいくつかのブートローダの種類及びまたはJTAGを使用していませんクラッシュを引き起こす可能性があります)。

このようなことを行うもう1つの理由は、無限ループを回避するためです。たとえば、フラッシュから起動したい(通常は持っている)が、RAMから実行したい場合、最も簡単な方法は、フラッシュ全体または一部のフラッシュ全体をラムにコピーし、ラムの先頭にブランチするだけです。これは、あなたが「ラムとブランチにアプリケーションをコピーする」というループをもう一度打つことを意味し、2回目(クラッシュする可能性がある)を避けるために、フラッシュからこのループを実行しているかテストしていません。

3

誰でも私たちにここでリンクレジスタの価値をテストする理由を説明することはできますか?

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のアドレスにリンクされている場合、R0R1は同じです。これはblの場合はpseudo codeです。

mov lr,pc    ; pc is actually two instruction ahead. 
add pc,pc,#branch_offset-8 

キーはBLlrの更新を含む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疑似オペレーションは頻繁には使用されていないので、人々はそれに精通していないかもしれません。