2017-02-02 6 views
0

GNU LDコマンドラインオプションのみを使用して、ベアメタルのアセンブリブートアップ/スタートアッププログラムを作成することは可能ですか? Cortex-M4ターゲット用の慣習的な-Tスクリプトファイルの代わりに?GNU LDコマンドラインオプションのみを使用して、ベアメタルのアセンブリブートアップ/スタートアッププログラムを作成することは可能ですか?

私はGNU LDのドキュメントを見直し、このサイトを含むさまざまな場所を検索しました。しかし、私は、GNUリンカーのコマンドラインオプションの排他的使用が可能であるかどうかを示唆する情報は見当たりませんでした。

* .ldスクリプトファイルは、純粋に学術的なものです。これは宿題ではない。私はスタートアップのアセンブリコードを書くための助けを要求していません。私は決定的な答えやさらなるリソースの方向性を探しているだけです。

$ arm-none-eabi-ld bootup.o -o bootup @bootup.ld.cli.file 

サンプルbootup.ld.cli.fileコンテンツ

--entry 0x0 
--Ttext=0x0 
--section-start .isr_vector=0x0 
--section-start _start=0x4 
--section-start .MyCode=0x8c 
--Tdata=0x20000000 
--Tbss=0x20000000 
-M=bootup.map 
--print-gc-sections 
+0

これはリンカファイルで行うことができます([出力セクションデータ]を使用してセクションデータを定義します(https://sourceware.org/binutils/ docs/ld/Output-Section-Data.html)を 'BYTE'、' SHORT'、 'LONG'、' QUAD'と組み合わせて使用​​することもできます。これらのステートメント( 'BYTE、SHORT、LONG、QUAD')は、他のシステムローダー(おそらくSOC ROMコード)のヘッダー情報を提供するために主に役立ちます。 –

+0

@artlessnoise - ありがとうございます。しかし、現時点では、私はリンカファイルを避けようとしています;少なくとも直接。 – InfinitelyManic

+0

あなたの 'bootup.ld.cli'はリンクのようなものですそれは技術的なものではありません。あなたがブート可能/実行可能ファイルを作るためにコードをコンパイル/アセンブルしたくないと思った。あなたのタイトルは私を誤解します。 –

答えて

2

あなたはすぐそこに答え-Ttext =数-Tdata =番号を持っているように、彼らはGNUです何GNUリンカスクリプト項目はありませんコマンドライン項目。コマンドラインのat記号に注意してください。

gnuリンカースクリプトはこれに似ています(ただし、ほとんどの場合、必要がなくてもかなり複雑です)。あなたは-Ttext =アドレスアプローチを使用する場合、GNUリンカは少し面白いこと

MEMORY 
{ 
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000 
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000 
} 

SECTIONS 
{ 
    .text : { *(.text*) } > rom 
    .rodata : { *(.rodata*) } > rom 
    .bss : { *(.bss*) } > ram 
} 

注意、時にはそれはあなただけで直線的にし、代わりにそのプログラムの数キロバイトを持っているように、アドレスでそれを置くかもしれないギャップを挿入しますそれはいくつかのデッドスペースを埋める必要がありますし、さらにいくつかを置く必要がありますが、非常に限られたターゲットのためにリンカスクリプト(コマンドライン対)他のすべての要因が一定に保たれ、出力にギャップを入れません。

EDIT:

so.s

.cpu cortex-m0 
.thumb 

.thumb_func 
.global _start 
_start: 
stacktop: .word 0x20001000 
.word reset 
.word hang 
.word hang 
.word hang 
.word hang 

.thumb_func 
reset: 
    b hang 
.thumb_func 
hang: b . 

flash.s

.cpu cortex-m0 
.thumb 

.thumb_func 
.global _start 
_start: 
stacktop: .word 0x20001000 
.word reset 
.word hang 
.word hang 
.word hang 
.word hang 
.word hang 

.thumb_func 
reset: 
    bl notmain 
    b hang 

.thumb_func 
hang: b . 

.thumb_func 
.globl dummy 
dummy: 
    bx lr 

はflash.ld

MEMORY 
{ 
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000 
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000 
} 

SECTIONS 
{ 
    .text : { *(.text*) } > rom 
    .rodata : { *(.rodata*) } > rom 
    .bss : { *(.bss*) } > ram 
} 

blinker02.c

void dummy (unsigned int); 

int notmain (void) 
{ 
    unsigned int ra; 
    for(ra=0;ra<100;ra++) dummy(ra); 
    return(0); 
} 

はMakefileの

ARMGNU = arm-none-eabi 

AOPS = --warn -mcpu=cortex-m0 
COPS = -Wall -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0 

all : blinker02.bin sols.bin socl.bin 

clean: 
    rm -f *.bin 
    rm -f *.o 
    rm -f *.elf 
    rm -f *.list 

so.o : so.s 
    $(ARMGNU)-as $(AOPS) so.s -o so.o 

flash.o : flash.s 
    $(ARMGNU)-as $(AOPS) flash.s -o flash.o 

blinker02.o : blinker02.c 
    $(ARMGNU)-gcc $(COPS) -mthumb -c blinker02.c -o blinker02.o 

blinker02.bin : flash.ld flash.o blinker02.o 
    $(ARMGNU)-ld -o blinker02.elf -T flash.ld flash.o blinker02.o 
    $(ARMGNU)-objdump -D blinker02.elf > blinker02.list 
    $(ARMGNU)-objcopy blinker02.elf blinker02.bin -O binary 

sols.bin : so.o 
    $(ARMGNU)-ld -o sols.elf -T flash.ld so.o 
    $(ARMGNU)-objdump -D sols.elf > sols.list 
    $(ARMGNU)-objcopy sols.elf sols.bin -O binary 

socl.bin : so.o 
    $(ARMGNU)-ld -o socl.elf -Ttext=0x08000000 -Tbss=0x20000000 so.o 
    $(ARMGNU)-objdump -D socl.elf > socl.list 
    $(ARMGNU)-objcopy socl.elf socl.bin -O binary 

コマンドラインとリンカスクリプトのSOClとゾルリストファイルの違いの名前

diff sols.list socl.list 
2c2 
< sols.elf:  file format elf32-littlearm 
--- 
> socl.elf:  file format elf32-littlearm 

は、あなたがダウンして見ることができるの違いを実証を気にするつもりはありません道路。

アセンブリの場合は、起動ファイルがないことと、gccのその他のコマンドラインオプションについて心配する必要はありません。 Cオブジェクトを使用します。リンカーがas-built/configured toolchains(またはCライブラリと言う)ブートストラップコードを使用できないようにすることで、特定のオブジェクトファイルが呼び出された時点でリンカスクリプトを複雑にしないと、コードを提供する必要がありますあなたがフラッシュを交換する場合、コマンドライン上のオブジェクトの重要性。oとblinker02.oをmakefileのldコマンドラインで実行すると、バイナリは動作しません。あなたはエントリーポイントを自由に設定することができますが、これはローダー用です。エントリーポイントが無意味であるように見えるベアメタルであれば、ハードウェアは起動方法をブートします。この場合は、cortex-mアドレスゼロスタックポインタにロードする値です。アドレス4はリセットベクトルのアドレスです(lsbitは親指のマシンなので、ツールはgnuアセンブラ固有のthumb_funcを使って次のラベルを指示します)分岐先アドレス)。

私はこのコードを元のarmv4tとarmv5tから、またはより新しいarm docs "all thumb variants"で呼び出されたので、私はこのコードを約1つ撒いたので、最も移植性の高いアーム命令です腕の芯。あなたのcortex-m4を使って、それを取り除くか、おそらく-m3または-m4にしてarmv7-m thumb2拡張を引っ張ることができます。

ので、短い答えは

arm-none-eabi-ld -o so.elf -Ttext=0x08000000 -Tbss=0x20000000 so.o 

では、あなたが.DATAを必要といけないと仮定すると、作業バイナリを作るための十分以上です。

。データには、より多くのもの、リンカスクリプト、より複雑なブートストラップなどが必要です。それはコピージャンプのことですが、REALプログラムをsramのみで実行するようにコンパイルします(別のエントリポイントのフルサイズのアームスタイルしかし、RAMベースのアドレスで)、そのバイナリを取って、それを言葉に変換するアドホックツールを書いて、フラッシュからコピーしてREALプログラム全体をブランクにコピーするプログラムのエントリを0xabcdefにします。 .dataも.bssもなく、コマンドラインを使うことができるので、REAL ramのみのプログラムが可能です。そしておそらく私はあなたをすでに失ってしまったでしょう。

同様に、コマンドラインを使用すると、.bssがゼロに設定されていると仮定することはできません。また、ブートストラップもそれを行う必要があります。もしあなたが.bssと.dataを持っていないなら、少なくとも1つの古いコンパイラが不要なゴミを追加したので、あなたはCプログラムのエントリーポイントに分岐する前に、盲目的にすべてのRAMを0にすることができます。 main()関数を見て、main()という名前の関数について何も魔法がないということを強調するなら、バイナリです。

リンカスクリプトはツールチェーン固有のものなので、gnuリンカスクリプトがKielに移植してARMに移植する必要はありません(そうです、私はARMがKielを所有していることを知っています。最初の.data/.bssの問題。理想的には、あなたのツールで作業をしたいので、.dataと.bssのビットがどのようになっているかを知ることができます。リンカスクリプトを正しく作っていることを伝える方法は(少なくともldでは)難しいしかし、それはあなたが.bssの開始アドレス、.bssの終了アドレス、それらを減算して長さを得るいくつかの数え方のようなものを定義することができるなら変数を作成します。同様に.dataのために、その後ブートストラップアセンブリ言語でゼロ開始アドレスと長さ、および/または開始アドレスと終了アドレスを使用した.bssメモリ。 .dataには2つのアドレスが必要です。そこにはフラッシュ(より多くのリンカースクリプトfoo)と、RAMに入れたい場所と、ブートストラップのコピーの長さが入ります。

あなたはこのコード

unsigned int x=5; 
unsigned int y; 

を書いて、あなたは、コマンドラインリンカスクリプトを使用している場合ので、基本的には、最初のC関数が入力されたときに0にxが5またはyであることを期待する一切理由はありませんこれらの変数を使用します。 xが5になると仮定すると、プログラムは失敗します。あなたがこれを行う場合

代わり

unsigned int x; 
unsigned int y; 
void myfun (void) 
{ 
    x=5; 
    y=0; 
} 

は今、それらの割り当ては、.textセクションの指示ではなく値がです。データは常にコマンドラインで動作するか、単純なリンカースクリプトでも複雑でもないなどです。

+0

マップファイルobjdumpとreadelfを使って表示すると、レイアウトがうまくいくように見えます。しかし、私はResetHandlerを踏み越えることができません。 PCは進まない。これは、コマンドラインのみのアプローチが完全で適切なレイアウトに十分であるかどうかを尋ねている理由です。私はそれが動作するはずだと思うので、私はあなたの答えに応じてマークします。 – InfinitelyManic

+1

はい、何年もリンカスクリプトを使ってビルドしていますが、主な違いはこのGNU ldの奇妙なことです... –

+0

あなたはそのオブジェクトをアセンブリ言語ですか、ツールチェーンのブートストラップに頼っていますか? (これは、それに合ったリンカースクリプトと一致することなく動作しません)。 –

関連する問題