他にも無数のサイトや例があります。数万とは言わないまでも数千。リンカースクリプトとブーストラップコードを備えたよく知られたCライブラリ、特にnewlib、glibcがありますが、他にも見つけることができます。CでCをブートストラップしても意味がありません。
正確でない可能性のあるものを正確に比較しようとしている、既知の境界で開始されていない、または既知の境界で終了していない可能性があるという質問に回答しました。したがって、より少ないことを行うことができますが、コードが正確な比較で機能しなかった場合は、.bssを過ぎて次のセクションにゼロ設定されているため、問題が発生する場合と発生しない場合があります。ソリューション。
TLはここにあり、DRは問題ありません。あなたはその言語で言語をブートストラップしないでください、あなたはそれを確実に逃れることができます、しかしあなたがそれをするときあなたは火で遊んでいます。あなたがこれを行う方法を学んでいるだけの場合、あなたは注意を怠る必要があります。運やまだ明らかにしていない事実を馬鹿にしないでください。
リンカスクリプトとブートストラップコードは非常に親密な関係にあり、それらは結婚していて、ヒップで結合されています。大規模な障害につながる他の1つなしで1つを開発することはできません。残念ながら、リンカースクリプトはリンカーによって定義され、アセンブリー言語はアセンブラーによって定義されているため、ツールチェーンを変更すると、両方を書き直す必要があると予想されます。なぜアセンブリ言語なのか?ブートストラップは必要ありませんが、コンパイルされた言語は一般的に必要です。Cは、言語の使用を制限したくない場合は、最小限のツールチェーン固有の要件を持つ非常にシンプルなものから始めます。.bss変数がゼロであると想定しないでください(変数がその言語で初期化されない場合、コードが読みにくくなります) 、これを回避しようとしますが、ローカル変数には当てはまりません。そのため、それを使用するときはボールに乗っている必要があります。では、なぜ.bssと.dataについて話しているのですか?(グローバルはこのレベルの作業には適していますが、これは別のトピックです))簡単な解決策のもう1つのルールは、宣言で変数を初期化しないで、コードで初期化することです。はい、より多くのフラッシュを燃やします。一般的には十分ですが、すべての変数が定数で初期化されるわけではなく、結果として命令を消費することになります。
cortex-mの設計から、ブートストラップコードはまったくないため、.dataも.bssもサポートされていないと考えていたことがわかります。グローバルを使用するほとんどの人々は、これがないと生きていけません。
gnuツールチェーンを使用して、すべてのcortex-msのこれをより最小限に抑えた機能的な例にすることができます。現在の9.xxからどのバージョンを始めればよいか覚えていません。私がより多くを学び、gnuが私の最初のものを壊した何かを変更したとき、xxまたは4.xx。
ブートストラップ:
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done
.thumb_func
reset:
bl centry
b done
.thumb_func
done: b .
.thumb_func
.globl bounce
bounce:
bx lr
Cコードへのエントリポイント:
void bounce ( unsigned int );
unsigned int a;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
リンカースクリプト。
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
これらはすべて小さくても機能する可能性があり、実際に動作することを確認するために、ここにいくつか追加の要素を追加しました。
最適化されたビルドとリンク。
00000000 <_start>:
0: 20001000
4: 00000015
8: 0000001b
c: 0000001b
10: 0000001b
00000014 <reset>:
14: f000 f804 bl 20 <centry>
18: e7ff b.n 1a <done>
0000001a <done>:
1a: e7fe b.n 1a <done>
0000001c <bounce>:
1c: 4770 bx lr
...
00000020 <centry>:
20: 2207 movs r2, #7
22: b510 push {r4, lr}
24: 4b04 ldr r3, [pc, #16] ; (38 <centry+0x18>)
26: 2007 movs r0, #7
28: 601a str r2, [r3, #0]
2a: f7ff fff7 bl 1c <bounce>
2e: 2000 movs r0, #0
30: bc10 pop {r4}
32: bc02 pop {r1}
34: 4708 bx r1
36: 46c0 nop ; (mov r8, r8)
38: 20000000 andcs r0, r0, r0
Disassembly of section .bss:
20000000 <a>:
20000000: 00000000 andeq r0, r0, r0
一部のベンダーでは、フラッシュがそこにマップされ、一部のブートモードで0x00000000にミラーリングされるため、0x08000000または0x01000000または他の同様のアドレスを使用する必要があります。フラッシュの多くが0x00000000でミラーリングされているものもあるので、ベクターテーブルがゼロではなくアプリケーションのフラッシュスペースを指すようにする必要があります。ベクターテーブルベースであるため、すべて機能します。
最初に、cortex-msは親指専用のマシンであり、何らかの理由で親指機能アドレスを適用したことに注意してください。これは、lsbitが奇数であることを意味します。ツールを知って、.thumb_funcディレクティブは、次のラベルがつまみ関数のアドレスであることをgnuアセンブラーに伝えます。テーブルで+1を実行すると失敗します。実行しようとしないで、正しく実行してください。関数を宣言する他のgnuアセンブラーの方法があります。これは最小のアプローチです。
4: 00000015
8: 0000001b
c: 0000001b
10: 0000001b
ベクトルテーブルが正しくない場合は起動しません。
おそらく、スタックポインターベクトル(自分でコードにスタックポインターを設定したい場合は、そこに何かを置くことができます)とリセットベクトルのみが必要です。特に理由はありませんが、ここに4つ入れました。通常は16を入れますが、この例を短くしたいと思いました。
では、Cブートストラップが行う必要のある最小限のことは何でしょうか。1.スタックポインターを設定する2.ゼロ.bss 3. .dataをコピーする4. Cエントリポイントに分岐するか呼び出す
Cエントリポイントは通常main()と呼ばれます。しかし、一部のツールチェーンはmain()を参照し、コードに余分なゴミを追加します。意図的に別の名前を使用しています。YMMV。
これがすべてRAMベースの場合、.dataのコピーは必要ありません。cortex-mマイクロコントローラーであることは技術的には可能ですが、そうではないため、.dataコピーが必要です。
私の最初の例とコーディングスタイルは、この例のように、.dataや.bssに依存しないことです。Armがスタックポインタを処理するため、残っているのはエントリポイントを呼び出すことだけです。私はそれがエントリーポイントが戻ることができるように持っているのが好きです、多くの人々はあなたがそれをするべきではないと主張します。次に、これを行うことができます:
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word centry
.word done
.word done
.word done
centry()から返されず、リセットハンドラコードもありません。
00000020 <centry>:
20: 2207 movs r2, #7
22: b510 push {r4, lr}
24: 4b04 ldr r3, [pc, #16] ; (38 <centry+0x18>)
26: 2007 movs r0, #7
28: 601a str r2, [r3, #0]
2a: f7ff fff7 bl 1c <bounce>
2e: 2000 movs r0, #0
30: bc10 pop {r4}
32: bc02 pop {r1}
34: 4708 bx r1
36: 46c0 nop ; (mov r8, r8)
38: 20000000 andcs r0, r0, r0
Disassembly of section .bss:
20000000 <a>:
20000000: 00000000
リンカは私たちが尋ねたところに物事を置きました。そして全体として、完全に機能するプログラムがあります。
したがって、最初にリンカースクリプトを作成します。
MEMORY
{
bob : ORIGIN = 0x00000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > ted AT > bob
__data_end__ = .;
__data_size__ = __data_end__ - __data_start__;
.bss : {
__bss_start__ = .;
*(.bss*)
} > ted
__bss_end__ = .;
__bss_size__ = __bss_end__ - __bss_start__;
}
romとramの名前には意味がないことを強調し、セクション間のリンカのドットを接続するだけです。
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done
.thumb_func
reset:
bl centry
b done
.thumb_func
done: b .
.thumb_func
.globl bounce
bounce:
bx lr
.align
.word __data_rom_start__
.word __data_start__
.word __data_end__
.word __data_size__
ツールが何をしたかを確認できるように、いくつかの項目を追加します
void bounce ( unsigned int );
unsigned int a;
unsigned int b=4;
unsigned char c=5;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
これらのセクションに配置するアイテムを追加します。そして得る
Disassembly of section .text:
00000000 <_start>:
0: 20000800 andcs r0, r0, r0, lsl #16
4: 00000015 andeq r0, r0, r5, lsl r0
8: 0000001b andeq r0, r0, r11, lsl r0
c: 0000001b andeq r0, r0, r11, lsl r0
10: 0000001b andeq r0, r0, r11, lsl r0
00000014 <reset>:
14: f000 f80c bl 30 <centry>
18: e7ff b.n 1a <done>
0000001a <done>:
1a: e7fe b.n 1a <done>
0000001c <bounce>:
1c: 4770 bx lr
1e: 46c0 nop ; (mov r8, r8)
20: 0000004c andeq r0, r0, r12, asr #32
24: 20000000 andcs r0, r0, r0
28: 20000008 andcs r0, r0, r8
2c: 00000008 andeq r0, r0, r8
00000030 <centry>:
30: 2207 movs r2, #7
32: b510 push {r4, lr}
34: 4b04 ldr r3, [pc, #16] ; (48 <centry+0x18>)
36: 2007 movs r0, #7
38: 601a str r2, [r3, #0]
3a: f7ff ffef bl 1c <bounce>
3e: 2000 movs r0, #0
40: bc10 pop {r4}
42: bc02 pop {r1}
44: 4708 bx r1
46: 46c0 nop ; (mov r8, r8)
48: 20000008 andcs r0, r0, r8
Disassembly of section .data:
20000000 <c>:
20000000: 00000005 andeq r0, r0, r5
20000004 <b>:
20000004: 00000004 andeq r0, r0, r4
Disassembly of section .bss:
20000008 <a>:
20000008: 00000000 andeq r0, r0, r0
ここで私たちはその実験で探しているものです(実際にコードをロードしたり実行したりする理由はありません...あなたのツールを知って、それらを学んでください)
1c: 4770 bx lr
1e: 46c0 nop ; (mov r8, r8)
20: 0000004c andeq r0, r0, r12, asr #32
24: 20000000 andcs r0, r0, r0
28: 20000008 andcs r0, r0, r8
2c: 00000008 andeq r0, r0, r8
ここで学んだことは、変数の位置はgnuリンカースクリプトでは非常に敏感であることです。位置に注意data_rom_start対data_startをしかし、なぜDATA_ENDの仕事は?それを理解させましょう。リンカスクリプトをいじって単純なプログラミングに取りたくない理由をすでに理解している...
したがって、ここで学んだもう1つのことは、リンカーが配置したdata_rom_startをALIGN(4)にする必要がなかったことです。私たちはそれが常にうまくいくと思いますか?
途中でパディングされたことにも注意してください。5バイトの.dataがありますが、8にパディングされています。ALIGN()がなければ、単語を使用してコピーを実行できます。今日の私のコンピューター上のこのツールチェーンで見たものに基づくと、それは過去と未来に当てはまるのでしょうか?ALIGNが定期的にチェックして、新しいバージョンで問題が発生しなかったことを確認する必要がある場合でも、時々それを実行することは誰にもわかりません。
その実験から、安全のためにこれに移りましょう。
MEMORY
{
bob : ORIGIN = 0x00000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
. = ALIGN(4);
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
. = ALIGN(4);
__data_end__ = .;
} > ted AT > bob
__data_size__ = __data_end__ - __data_start__;
. = ALIGN(4);
.bss : {
__bss_start__ = .;
*(.bss*)
. = ALIGN(4);
__bss_end__ = .;
} > ted
__bss_size__ = __bss_end__ - __bss_start__;
}
端を内側に移動して、他の人が行うことと一致させます。そしてそれはそれを変えませんでした:
0000001c <bounce>:
1c: 4770 bx lr
1e: 46c0 nop ; (mov r8, r8)
20: 0000004c andeq r0, r0, r12, asr #32
24: 20000000 andcs r0, r0, r0
28: 20000008 andcs r0, r0, r8
2c: 00000008 andeq r0, r0, r8
もう1つの簡単なテスト:
.globl bounce
bounce:
nop
bx lr
与える
0000001c <bounce>:
1c: 46c0 nop ; (mov r8, r8)
1e: 4770 bx lr
20: 0000004c andeq r0, r0, r12, asr #32
24: 20000000 andcs r0, r0, r0
28: 20000008 andcs r0, r0, r8
2c: 00000008 andeq r0, r0, r8
バウンスと.alignの間を埋める必要はありません
ああ、そうですね、_end__を中に入れない理由を今覚えています。それは機能しないので。
MEMORY
{
bob : ORIGIN = 0x00000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
. = ALIGN(4);
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > ted AT > bob
. = ALIGN(4);
__data_end__ = .;
__data_size__ = __data_end__ - __data_start__;
. = ALIGN(4);
.bss : {
__bss_start__ = .;
*(.bss*)
} > ted
. = ALIGN(4);
__bss_end__ = .;
__bss_size__ = __bss_end__ - __bss_start__;
}
このリンカスクリプトと連携するいくつかの単純ですが非常に移植可能なコード
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done
.thumb_func
reset:
ldr r0,blen
cmp r0,#0
beq bss_zero_done
ldr r1,bstart
mov r2,#0
bss_zero:
stmia r1!,{r2}
sub r0,#4
bne bss_zero
bss_zero_done:
ldr r0,dlen
cmp r0,#0
beq data_copy_done
ldr r1,rstart
ldr r2,dstart
data_copy:
ldmia r1!,{r3}
stmia r2!,{r3}
sub r0,#4
bne data_copy
data_copy_done:
bl centry
b done
.thumb_func
done: b .
.thumb_func
.globl bounce
bounce:
nop
bx lr
.align
bstart: .word __bss_start__
blen: .word __bss_size__
rstart: .word __data_rom_start__
dstart: .word __data_start__
dlen: .word __data_size__
与える
Disassembly of section .text:
00000000 <_start>:
0: 20000800 andcs r0, r0, r0, lsl #16
4: 00000015 andeq r0, r0, r5, lsl r0
8: 0000003d andeq r0, r0, sp, lsr r0
c: 0000003d andeq r0, r0, sp, lsr r0
10: 0000003d andeq r0, r0, sp, lsr r0
00000014 <reset>:
14: 480c ldr r0, [pc, #48] ; (48 <blen>)
16: 2800 cmp r0, #0
18: d004 beq.n 24 <bss_zero_done>
1a: 490a ldr r1, [pc, #40] ; (44 <bstart>)
1c: 2200 movs r2, #0
0000001e <bss_zero>:
1e: c104 stmia r1!, {r2}
20: 3804 subs r0, #4
22: d1fc bne.n 1e <bss_zero>
00000024 <bss_zero_done>:
24: 480b ldr r0, [pc, #44] ; (54 <dlen>)
26: 2800 cmp r0, #0
28: d005 beq.n 36 <data_copy_done>
2a: 4908 ldr r1, [pc, #32] ; (4c <rstart>)
2c: 4a08 ldr r2, [pc, #32] ; (50 <dstart>)
0000002e <data_copy>:
2e: c908 ldmia r1!, {r3}
30: c208 stmia r2!, {r3}
32: 3804 subs r0, #4
34: d1fb bne.n 2e <data_copy>
00000036 <data_copy_done>:
36: f000 f80f bl 58 <centry>
3a: e7ff b.n 3c <done>
0000003c <done>:
3c: e7fe b.n 3c <done>
0000003e <bounce>:
3e: 46c0 nop ; (mov r8, r8)
40: 4770 bx lr
42: 46c0 nop ; (mov r8, r8)
00000044 <bstart>:
44: 20000008 andcs r0, r0, r8
00000048 <blen>:
48: 00000004 andeq r0, r0, r4
0000004c <rstart>:
4c: 00000074 andeq r0, r0, r4, ror r0
00000050 <dstart>:
50: 20000000 andcs r0, r0, r0
00000054 <dlen>:
54: 00000008 andeq r0, r0, r8
00000058 <centry>:
58: 2207 movs r2, #7
5a: b510 push {r4, lr}
5c: 4b04 ldr r3, [pc, #16] ; (70 <centry+0x18>)
5e: 2007 movs r0, #7
60: 601a str r2, [r3, #0]
62: f7ff ffec bl 3e <bounce>
66: 2000 movs r0, #0
68: bc10 pop {r4}
6a: bc02 pop {r1}
6c: 4708 bx r1
6e: 46c0 nop ; (mov r8, r8)
70: 20000008 andcs r0, r0, r8
Disassembly of section .data:
20000000 <c>:
20000000: 00000005 andeq r0, r0, r5
20000004 <b>:
20000004: 00000004 andeq r0, r0, r4
Disassembly of section .bss:
20000008 <a>:
20000008: 00000000 andeq r0, r0, r0
私たちはそこで停止するか、続行します。リンカスクリプトと同じ順序で初期化する場合は、まだ行っていないため、次の手順に進んでもかまいません。とstm / ldmはワードアラインされたアドレスを使用するためにのみ必要/望ましいので、次のように変更した場合:
ldr r0,blen
cmp r0,#0
beq bss_zero_done
ldr r1,bstart
mov r2,#0
mov r3,#0
mov r4,#0
mov r5,#0
bss_zero:
stmia r1!,{r2,r3,r4,r5}
sub r0,#16
ble bss_zero
bss_zero_done:
リンカスクリプトの最初にbssを使用し、はい、blsではなくbleを使用します。
Disassembly of section .text:
00000000 <_start>:
0: 20000800 andcs r0, r0, r0, lsl #16
4: 00000015 andeq r0, r0, r5, lsl r0
8: 00000043 andeq r0, r0, r3, asr #32
c: 00000043 andeq r0, r0, r3, asr #32
10: 00000043 andeq r0, r0, r3, asr #32
00000014 <reset>:
14: 480d ldr r0, [pc, #52] ; (4c <blen>)
16: 2800 cmp r0, #0
18: d007 beq.n 2a <bss_zero_done>
1a: 490b ldr r1, [pc, #44] ; (48 <bstart>)
1c: 2200 movs r2, #0
1e: 2300 movs r3, #0
20: 2400 movs r4, #0
22: 2500 movs r5, #0
00000024 <bss_zero>:
24: c13c stmia r1!, {r2, r3, r4, r5}
26: 3804 subs r0, #4
28: ddfc ble.n 24 <bss_zero>
0000002a <bss_zero_done>:
2a: 480b ldr r0, [pc, #44] ; (58 <dlen>)
2c: 2800 cmp r0, #0
2e: d005 beq.n 3c <data_copy_done>
30: 4907 ldr r1, [pc, #28] ; (50 <rstart>)
32: 4a08 ldr r2, [pc, #32] ; (54 <dstart>)
00000034 <data_copy>:
34: c978 ldmia r1!, {r3, r4, r5, r6}
36: c278 stmia r2!, {r3, r4, r5, r6}
38: 3810 subs r0, #16
3a: ddfb ble.n 34 <data_copy>
0000003c <data_copy_done>:
3c: f000 f80e bl 5c <centry>
40: e7ff b.n 42 <done>
00000042 <done>:
42: e7fe b.n 42 <done>
00000044 <bounce>:
44: 46c0 nop ; (mov r8, r8)
46: 4770 bx lr
00000048 <bstart>:
48: 20000000 andcs r0, r0, r0
0000004c <blen>:
4c: 00000004 andeq r0, r0, r4
00000050 <rstart>:
50: 20000004 andcs r0, r0, r4
00000054 <dstart>:
54: 20000004 andcs r0, r0, r4
00000058 <dlen>:
58: 00000008 andeq r0, r0, r8
0000005c <centry>:
5c: 2207 movs r2, #7
5e: b510 push {r4, lr}
60: 4b04 ldr r3, [pc, #16] ; (74 <centry+0x18>)
62: 2007 movs r0, #7
64: 601a str r2, [r3, #0]
66: f7ff ffed bl 44 <bounce>
6a: 2000 movs r0, #0
6c: bc10 pop {r4}
6e: bc02 pop {r1}
70: 4708 bx r1
72: 46c0 nop ; (mov r8, r8)
74: 20000000 andcs r0, r0, r0
Disassembly of section .bss:
20000000 <a>:
20000000: 00000000 andeq r0, r0, r0
Disassembly of section .data:
20000004 <c>:
20000004: 00000005 andeq r0, r0, r5
20000008 <b>:
20000008: 00000004 andeq r0, r0, r4
これらのループはより高速になります。現在、私はahbバスが64ビット幅であるかどうかわからないが、フルサイズのアームの場合、これらのものを64ビット境界に揃えたいと思う。64ビット境界ではなく32ビット境界の4つのレジスタldm / stmは、3つの独立したバストランザクションになります。64ビット境界で整列すると、1つのトランザクションで1命令あたり数クロックを節約できます。
私たちはベアメタルをやっていて、私たちが置くことができるすべてのものに対して完全に責任があるので、最初にbss、次にデータ、次にヒープがある場合はスタックが上から下に成長するので、bssをゼロにして、私たちはまだそのメモリを使用していません。次に、.dataをコピーして、ヒープ、ヒープ、またはスタックのための十分な余地がない場合に流出する可能性があるため、誰も/何も踏んでいない(リンカースクリプトで確認している限り)。懸念がある場合は、ALIGN()を大きくして、これらの塗りつぶしのために常にスペース内に収まるようにします。
だから私の簡単な解決策は、それを取るか、そのままにするかです。バグの修正を歓迎します。ハードウェアでもシミュレータでも実行しませんでした...
MEMORY
{
bob : ORIGIN = 0x00000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > bob
.rodata : { *(.rodata*) } > bob
. = ALIGN(8);
.bss : {
__bss_start__ = .;
*(.bss*)
} > ted
. = ALIGN(4);
__bss_end__ = .;
__bss_size__ = __bss_end__ - __bss_start__;
. = ALIGN(8);
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > ted AT > bob
. = ALIGN(4);
__data_end__ = .;
__data_size__ = __data_end__ - __data_start__;
}
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20000800
.word reset
.word done
.word done
.word done
.thumb_func
reset:
ldr r0,blen
cmp r0,#0
beq bss_zero_done
ldr r1,bstart
mov r2,#0
mov r3,#0
mov r4,#0
mov r5,#0
bss_zero:
stmia r1!,{r2,r3,r4,r5}
sub r0,#16
ble bss_zero
bss_zero_done:
ldr r0,dlen
cmp r0,#0
beq data_copy_done
ldr r1,rstart
ldr r2,dstart
data_copy:
ldmia r1!,{r3,r4,r5,r6}
stmia r2!,{r3,r4,r5,r6}
sub r0,#16
ble data_copy
data_copy_done:
bl centry
b done
.thumb_func
done: b .
.thumb_func
.globl bounce
bounce:
nop
bx lr
.align
bstart: .word __bss_start__
blen: .word __bss_size__
rstart: .word __data_rom_start__
dstart: .word __data_start__
dlen: .word __data_size__
void bounce ( unsigned int );
unsigned int a;
unsigned int b=4;
unsigned char c=5;
int centry ( void )
{
a = 7;
bounce(a);
return(0);
}
arm-none-eabi-as --warn --fatal-warnings flash.s -o flash.o
arm-none-eabi-ld -o hello.elf -T flash.ld flash.o centry.o
arm-none-eabi-objdump -D hello.elf > hello.list
arm-none-eabi-objcopy hello.elf hello.bin -O binary
すべてをまとめると、次のようになります。
Disassembly of section .text:
00000000 <_start>:
0: 20000800 andcs r0, r0, r0, lsl #16
4: 00000015 andeq r0, r0, r5, lsl r0
8: 00000043 andeq r0, r0, r3, asr #32
c: 00000043 andeq r0, r0, r3, asr #32
10: 00000043 andeq r0, r0, r3, asr #32
00000014 <reset>:
14: 480d ldr r0, [pc, #52] ; (4c <blen>)
16: 2800 cmp r0, #0
18: d007 beq.n 2a <bss_zero_done>
1a: 490b ldr r1, [pc, #44] ; (48 <bstart>)
1c: 2200 movs r2, #0
1e: 2300 movs r3, #0
20: 2400 movs r4, #0
22: 2500 movs r5, #0
00000024 <bss_zero>:
24: c13c stmia r1!, {r2, r3, r4, r5}
26: 3810 subs r0, #16
28: ddfc ble.n 24 <bss_zero>
0000002a <bss_zero_done>:
2a: 480b ldr r0, [pc, #44] ; (58 <dlen>)
2c: 2800 cmp r0, #0
2e: d005 beq.n 3c <data_copy_done>
30: 4907 ldr r1, [pc, #28] ; (50 <rstart>)
32: 4a08 ldr r2, [pc, #32] ; (54 <dstart>)
00000034 <data_copy>:
34: c978 ldmia r1!, {r3, r4, r5, r6}
36: c278 stmia r2!, {r3, r4, r5, r6}
38: 3810 subs r0, #16
3a: ddfb ble.n 34 <data_copy>
0000003c <data_copy_done>:
3c: f000 f80e bl 5c <centry>
40: e7ff b.n 42 <done>
00000042 <done>:
42: e7fe b.n 42 <done>
00000044 <bounce>:
44: 46c0 nop ; (mov r8, r8)
46: 4770 bx lr
00000048 <bstart>:
48: 20000000 andcs r0, r0, r0
0000004c <blen>:
4c: 00000004 andeq r0, r0, r4
00000050 <rstart>:
50: 20000008 andcs r0, r0, r8
00000054 <dstart>:
54: 20000004 andcs r0, r0, r4
00000058 <dlen>:
58: 00000008 andeq r0, r0, r8
0000005c <centry>:
5c: 2207 movs r2, #7
5e: b510 push {r4, lr}
60: 4b04 ldr r3, [pc, #16] ; (74 <centry+0x18>)
62: 2007 movs r0, #7
64: 601a str r2, [r3, #0]
66: f7ff ffed bl 44 <bounce>
6a: 2000 movs r0, #0
6c: bc10 pop {r4}
6e: bc02 pop {r1}
70: 4708 bx r1
72: 46c0 nop ; (mov r8, r8)
74: 20000000 andcs r0, r0, r0
Disassembly of section .bss:
20000000 <a>:
20000000: 00000000 andeq r0, r0, r0
Disassembly of section .data:
20000004 <c>:
20000004: 00000005 andeq r0, r0, r5
20000008 <b>:
20000008: 00000004 andeq r0, r0, r4
これは、ghee whizが使用されなかったため、arm-none-eabi-およびarm-linux-gnueabiと他のバリアントで動作することに注意してください。
あなたが周りを見回すと、人々は彼らのリンカースクリプトのギーウィズのもの、巨大な巨大なキッチンシンクのものに夢中になるでしょう。他の人のものに頼るのではなく、それを行う方法(またはツールを習得して、何が起こっているかを制御できる方法)を理解し、理解していない、または調査したいためにどこで壊れるのかを知らない方が良いそれ。
原則として、同じ言語の言語をブートストラップしないでください(この意味でのブートストラップは、実行中のコードが同じコンパイラーでコンパイラーをコンパイルしないことを意味します)、ブートストラップの少ない単純な言語を使用します。そのため、Cはアセンブリで実行され、リセット後に最初の命令から開始するだけのブートストラップ要件はありません。JAVA、Cでjvmを作成し、そのCをasmでブートストラップし、Cで実行する場合はJAVAをブートストラップして、JavaをCでも実行することを確認してください。
これらのコピーループの仮定を制御しているため、手動で調整したmemcpy / memsetよりも定義が厳密でクリーンです。
他の問題はこれでした:
unsigned int * bss_start_p = &_BSS_START;
unsigned int * bss_end_p = &_BSS_END;
これらがローカルで問題ない場合、問題ありません。これらがグローバルである場合、最初に.dataを初期化してから機能させる必要があります。そのトリックを.dataにしようとすると、失敗します。ローカル変数、うまくいくでしょう。何らかの理由で静的ローカル(私が呼び出したいローカルグローバル)を作成することにした場合は、再び問題が発生します。あなたはそれについて考える必要がありますが、宣言で割り当てを行うたびに、それはどのように実装され、安全ですか?宣言されていないときに変数がゼロであると想定するたびに、同じことですが、ローカル変数がゼロであると想定されていない場合、グローバルの場合はゼロです。それらがゼロであると決して想定しない場合は、心配する必要はありません。