私は次の簡単なCコードを持っています:
void main(){
int A = 333;
int B=244;
int sum;
sum = A + B;
}
これをコンパイルすると
$riscv64-unknown-elf-gcc code.c -o code.o
使用しているアセンブリコードを見たい場合
$riscv64-unknown-elf-objdump -d code.o
しかし、アセンブリコードを調べると、プロキシカーネルサポート用であると思われる多くのコードが生成されていることがわかります(私はriscvの初心者です)。ただし、このコードがプロキシカーネルをサポートすることは望ましくありません。これは、FPGA内にこの単純なCコードのみを実装することを目的としているためです。
Riscvは、ベアメタルモード、newlibプロキシカーネル、riscvLinuxの3種類のコンパイルを提供していることを読みました。以前の調査によると、私がすべきコンパイルの種類はベアメタルモードです。これは、オペレーティングシステムやカーネルプロキシをサポートせずに最小限のアセンブリが必要なためです。システムコールとしてのアセンブリ関数は必要ありません。
ただし、最小限のriscvアセンブリプログラムのスケルトンを取得するためにCコードをコンパイルできるため、まだ見つけることができませんでした。上記のCコードをベアメタルモードでコンパイルしたり、最小限のriscvアセンブリコードのスケルトンを取得したりするにはどうすればよいですか?
警告:この回答は、tohost
コントロールの削除を含む最新のRISC-V特権仕様v1.9の時点ではやや古くなっています。 /ステータスレジスタ(CSR)。これは非標準のホストターゲットインターフェイス(HTIF)の一部であり、その後削除されました。現在の(2016年9月現在)riscv-tests
は、代わりにtohost
メモリ位置にメモリマップされたストアを実行します。これは、テザー環境ではfront-end server
によって監視されます。
本当におよび本当にRISC-Vコードを実行する必要がある/実行したい場合ベアメタルの場合は、その手順を次に示します。 riscv-pk(プロキシカーネル)が提供するprintfやFP-trapソフトウェアエミュレーションなどの便利なものがたくさん失われます。
まず最初に-スパイクは0x200で起動します。 SpikeはゴールデンISAシミュレータモデルであるため、コアも0x200で起動する必要があります。
(cough、2015年7月13日現在、riscv-toolsの「マスター」ブランチ(- https://github.com/riscv/riscv-tools )は古いv1.7より前の特権ISAを使用しているため、0x2000から始まります。この投稿では、v1.7 +を使用していることを前提としています。 riscv-toolsの「new_privileged_isa」ブランチを使用する必要がある場合があります)。
したがって、ベアメタルプログラムを逆アセンブルするときは、0x200から開始することをお勧めします!!!プロキシカーネル上で実行する場合は、0x10000から開始することをお勧めします(Linuxの場合は、さらに大きくなります…)。
ここで、ベアメタルを実行する場合は、プロセッサのブートコードを作成する必要があります。うん。しかし、それをパントして、それが必要ではないふりをしましょう。
(物理的にアドレス指定されたマシンの「仮想マシン」の説明については、riscv-tests/env/pを調べることもできます。必要なリンカースクリプトと、初期セットアップコードを説明するためのmacros.hがいくつかあります。それでも、riscv-tests/benchmarks/common.crt.S)。
とにかく、上記の(紛らわしい)知識を武器に、それをすべて捨てて、最初から始めましょう...
hello.s:
.align 6
.globl _start
_start:
# screw boot code, we're going minimalist
# mtohost is the CSR in machine mode
csrw mtohost, 1;
1:
j 1b
およびlink.ld:
OUTPUT_Arch( "riscv" )
ENTRY( _start )
SECTIONS
{
/* text: test code section */
. = 0x200;
.text :
{
*(.text)
}
/* data: Initialized data segment */
.data :
{
*(.data)
}
/* End of uninitalized data segement */
_end = .;
}
これをコンパイルするには…
riscv64-unknown-elf-gcc -nostdlib -nostartfiles -Tlink.ld -o hello hello.s
これは(riscv64-unknown-elf-objdump -d hello)にコンパイルされます:
hello: file format elf64-littleriscv
Disassembly of section .text:
0000000000000200 <_start>:
200: 7810d073 csrwi tohost,1
204: 0000006f j 204 <_start+0x4>
そしてそれを実行するには:
spike hello
それは美しいものです。
リンクスクリプトは、コードを0x200に配置します。 Spikeは0x200から開始し、制御/ステータスレジスタ「tohost」に#1を書き込みます。これにより、Spikeは「実行を停止」します。そして、フロントエンドサーバーがメッセージを受信して私たちを殺すまで、アドレス(1:j 1b)をスピンします。
コンパイラに<_start>を0x200に移動するように指示する方法がわかれば、リンカスクリプトを破棄できる可能性があります。
他の例については、次のリポジトリを熟読することができます。
Riscv-testsリポジトリは、非常に最小限のRISC-V ISAテスト( https://github.com/riscv/riscv-tests ))を保持します。
このMakefileにはコンパイラオプションがあります: https://github.com/riscv/riscv-tests/blob/master/isa/Makefile
また、「仮想マシン」記述マクロとリンカースクリプトの多くは、riscv-tests/env( https://github.com/riscv/riscv-test-env )にあります。
(riscv-tests/isa/rv64ui-p-simple.dump
)で「最も単純な」テストを見ることができます。
また、ベアメタルを実行するためのスタートアップおよびサポートコードについてはriscv-tests/benchmarks/common
を確認できます。
「余分な」コードはgccによってそこに置かれ、あらゆるプログラムに必要な種類のものです。プロキシカーネルは、そのようなものを実行するために必要な最低限のサポートになるように設計されています。プロセッサが動作したら、ベアメタルではなくpkの上で実行することをお勧めします。
それまでの間、単純なアセンブリを見たい場合は、「-c」を使用してリンクフェーズをスキップすることをお勧めします。
riscv64-unknown-elf-gcc code.c -c -o code.o
riscv64-unknown-elf-objdump -d code.o
Pkまたはlinuxを使用せずにコードを実行する例については、 riscv-tests を参照してください。