2016-10-31 5 views
0

私は初心者です。私は、メモリARMのメモリマップを理解することが困難です。ARMアセンブリのソート

私は、単純なソートアルゴリズム

AREA ARM, CODE, READONLY 

    CODE32 
    PRESERVE8 

    EXPORT __sortc 
    ; r0 = &arr[0] 
    ; r1 = length 

__sortc 
    stmfd sp!, {r2-r9, lr} 

    mov r4, r1     ; inner loop counter 
    mov r3, r4 
    sub r1, r1, #1 
    mov r9, r1     ; outer loop counter       

outer_loop 
    mov r5, r0 
    mov r4, r3 

inner_loop 
    ldr r6, [r5], #4 
    ldr r7, [r5] 
    cmp r7, r6 

    ; swap without swp 
    strls r6, [r5] 
    strls r7, [r5, #-4] 

    subs r4, r4, #1 
    bne inner_loop 

    subs r9, r9, #1 
    bne outer_loop 

    ldmfd sp!, {r2-r9, pc}^ 

    END 

の例を発見したと、このアセンブリは、私の知る限り、このコードは上の整数の配列を作成し、理解するよう

#define MAX_ELEMENTS 10 

extern void __sortc(int *, int); 

int main() 
{ 
     int arr[MAX_ELEMENTS] = {5, 4, 1, 3, 2, 12, 55, 64, 77, 10}; 

    __sortc(arr, MAX_ELEMENTS); 

    return 0; 
} 

Cコードからこの方法で呼び出されなければなりませんアセンブリに実装された_sortc関数を呼び出します。この関数はスタックからこの値を取り出し、ソートしてスタックに戻します。私は正しい?

この例ではアセンブリのみを使用して実装することができますか? DCDは、変数を宣言整数BTW

DCD 3, 7, 2, 8, 5, 7, 2, 6

のアレイを画定例えば

は、メモリに格納されています?

このように宣言された値を使って、どのように操作できますか?どのようにスタックを使わなくても、生データだけでCコードなしでアセンブリを使用してこれを実装する方法を説明してください。私はARM7TDMIアーキテクチャ

答えて

0

AREA ARM, CODE, READONLYのために書いています

- これはソースでコードのセクションの開始をマーク。それはdata1 DCD 1,2,3のようなデータを定義することが可能ですどこに類似AREA myData, DATA, READWRITE

あなたはセクションを開始することができ、これは、最初の単語の最初のバイトを指すラベルdata1で、連続したバイトの値1、2、3と3つの単語としてコンパイルされます。 (GoogleのAREAドキュメント)。

実行可能ファイルのロード後に物理メモリに格納される場所は、実行ファイルのリンク方法によって異なります(リンカは、実行可能なローダーによって、リンカー・スクリプトを編集することによって、コードとデータの場所を調整できますが、通常はその必要はありません)。

また、リンカスクリプトおよびアセンブラディレクティブは、使用可能なスタックのサイズや物理メモリにマップされている場所に影響する可能性があります。特定のプラットフォームのためにそう

:(スタートのためだけのコードとデータが土地を対象としている場所を確認するために、.MAPファイルを生成するために、リンカオプションを使用します)ウェブ上のメモリマッピングのためのGoogleとリンカスクリプトを確認してください。

したがって、配列をあるデータ領域に宣言してから使用するには、シンボルdata1をレジスタ(「load1 of data1」)にロードし、そのアドレスからメモリ内容をフェッチするために使用します。

または、すべての数値をスタックに入れることができます(実行可能ファイルのOSローダーによって妥当なものに設定されている可能性があります)。スタックポインタを使用してそのコード内の数値にアクセスします。

さらにDCDの値をCODEに設定することもできます。これらのワードは、実行可能なローダによって読み取り専用としてマップされたメモリの命令間で終了します。それらのデータを読むことはできますが、それらに書き込むとクラッシュする可能性があります。そしてもちろん、あなたは、事故の指示(先行DCDのいくつかのRET /ジャンプ命令を置くことを忘れる)としてそれらを実行してはいけません。


スタックなし

さてこの1つはトリッキーで、あなたは任意のコールは/ etcを使用しないように注意する必要があります。スタックを必要とする基本的に何か。

人々はブートローダをコーディングする場合、通常、彼らは最初のいくつかの指示にできるだけ早くいくつかの一時的なスタックを設定するので、彼らは基本的な適切全体の環境を設定する前に、スタック機能、またはロードOSを使用することができます。その一時的なスタックのためのスペースは、コードの中または後のどこかに予約されていることが多く、リセット後に定義されたマシン状態に応じて未使用のメモリスペースです。

OSなしの場合は、通常はリセット後にすべてのメモリに書き込み可能なので、コードやデータを混在させることができます(データを飛び越え、偶然実行するのではなく) AREAの定義。

しかし、OSのユーザー空間にアプリケーションを作成している(スタックやデータ領域がよく定義されているので、利便性のために使用できる)か、ブートローダを作成しているか(より困難自身のためにすべてをセットアップしているので、私は最初のいくつかのOSのユーザー地に行くのに示唆し、初期化CLIBと周りのCラッパーを持つことがあまりにも頻繁に便利ですので、あなたはASMからprintfのようなものを呼び出すことができますコード便利な出力)。私は値が宣言された方法で、マシンコードには関係ありません。このよう

で宣言された値で動作することができますどのように


。重要なのは、メモリのアドレスを知っていて、構造を知っていれば、そこにデータがどのように格納されているかです。それからあなたは、あなたが望む任意の指示を使って、あなたが望むどんな方法ででも彼らと一緒に作業することができます。 ASMでデータを割り当てると、Cと同じようにポインタを引数として渡します。


編集:テストを行わずに盲目的に行わいくつかの例は、(それがなかったなら、私はコメントで知らせて、または多分いくつかのバグがありますし、それがすべてでは動作しません)OPのために働くために、さらに構文固定が必要になる場合があります。

AREA myData, DATA, READWRITE 

SortArray 
    DCD  5, 4, 1, 3, 2, 12, 55, 64, 77, 10 
SortArrayEnd 

    AREA ARM, CODE, READONLY 

    CODE32 
    PRESERVE8 

    EXPORT __sortasmarray 

__sortasmarray 
    ; if "add r0, pc, #SortArray" fails (code too far in memory from array) 
    ; then this looks like some heavy weight way of loading any address 
    ; ldr r0, =SortArray 
    ; ldr r1, =SortArrayEnd 

    add r0, pc, #SortArray ; address of array 
    ; calculate array size from address of end 
    ; (as I couldn't find now example of thing like "equ $-SortArray") 
    add r1, pc, #SortArrayEnd 
    sub r1, r1, r0 
    mov r1, r1, lsr #2 
    ; do a direct jump instead of "bl", so __sortc returning 
    ; to lr will actually return to called of this 
    b  __sortc 

    ; ... rest of your __sortc assembly without change  

あなたはとしてCコードからそれを呼び出すことができます。私は私の腕のASMのメモリをリフレッシュするために他の人の間でこのIntroducing ARM assembly languageを使用し、私はまだこれがあると動作しないことが心配です

extern void __sortasmarray(); 

int main() 
{ 
    __sortasmarray(); 
    return 0; 
} 

ご覧のとおり、の内容は__sortcに変更されませんでした。スタックメモリや "dcd"メモリへのアクセスに違いはないので、同じコンピュータメモリです。特定の単語へのアドレスを取得したら、そのアドレスでldr/str値を設定できます。 __sortcは、配列の最初の単語のアドレスを受け取って両方の場合に並べ替えます。そこから、そのメモリだけです。コンテキストがなく、メモリがソースでどのように定義され、割り当てられ、初期化されましたか? __sortc。

私の唯一の "dcd"関連のものは、配列アドレスをロードすることです。ARMのサンプルのクイック検索では、いくつかの方法でこれを行うことができます。add rX, pc, #labelウェイは最適ですが、+ 4kレンジ?また、同じことをする擬似命令ADR rX, #labelがあり、レンジの問題の場合は他のものに切り替えるかもしれませんか?どの範囲であれば、ldr rX, = labelフォームが使用されているようですが、疑似命令かどうかは分かりませんが、チュートリアルと逆アセンブリをチェックしてコンパイル方法を確認してください。

すべてのARMアセンブリの特質と、配列のアドレスをロードする方法については、あなたに任せます。私は現時点ではARM ASMは必要ありません。そのため、詳細を掘り下げませんでした。

さらに、最終アドレスのコードで計算する代わりに、配列の長さを定義するには、equの方法が必要ですが、例は見つかりませんでした。詳細については、アセンブラのドキュメントを読んでいません。すべての指示(のgas私はArrayLength equ ((.-SortArray)/4)が動作すると思う)。

+0

お返事ありがとうございます!あなたは 'READWRITE'配列の書き込みをどのようにして動作させることができ、どのように値を入れ替えるかをソートの観点から読むことができますか? – fyfdzbgz

+0

@fyfdzbgz私はあなたがどのアセンブラを使用しているか知っていませんし、どんなプラットフォームであっても、もし私がしていても、私はアクティブなAndroid NDKの形式で 'gas'アセンブラを使っていますが、 MDK-ARMから私はそのドキュメントをリンクしています。そして、私は〜10yのARMアセンブリを作成していませんでしたが、それほど多くはありませんでした(私はGameBoy Advanceのゲームを行っていましたが、99%のコードはC++でしたが、コンパイラの出力をチェックしてコンパイラが混乱した場合過度に)。だから私は答えのいくつかの例を追加しようとしますが、私はテストせずに彼らを盲目的にやります、申し訳ありません。 – Ped7g

+0

@fyfdzbgz私は何かを追加しましたが、あなたが求めているものの全体的なほとんどが既にオリジナルのソースにありますので、サンプルやドキュメントをもっと深く掘り下げ、数回読み返してください。すでに読んだドキュメントを体験することは、おそらくあなたが求めていることを説明するより意味をなさないかもしれません。また、デバッガが単一の命令をステッピングしてCPU状態の変化を監視し、各命令の命令リファレンスガイドと比較して、その動作の「感触」を得るのに時間を費やします。そして、それらのことを知るために、時々指示の全リストを読み返してください。 – Ped7g

関連する問題