17

I have the following simple C code:

   void main(){
    int A = 333;
    int B=244;
    int sum;
    sum = A + B;  
}

When I compile this with

$riscv64-unknown-elf-gcc code.c -o code.o

If I want to see the assembly code I use

$riscv64-unknown-elf-objdump -d code.o 

But when I explore the assembly code I see that this generates a lot of code which I assume is for Proxy Kernel support (I am a newbie to riscv). However, I do not want that this code has support for Proxy kernel, because the idea is to implement only this simple C code within an FPGA.

I read that riscv provides three types of compilation: Bare-metal mode, newlib proxy kernel and riscv Linux. According to previous research, the kind of compilation that I should do is bare metal mode. This is because I desire a minimum assembly without support for the operating system or kernel proxy. Assembly functions as a system call are not required.

However, I have not yet been able to find as I can compile a C code for get a skeleton of a minimal riscv assembly program. How can I compile the C code above in bare metal mode or for get a skeleton of a minimal riscv assembly code?

4

3 回答 3

18

警告:这个答案在最新的 RISC-V Privileged Spec v1.9 中有些过时,其中包括删除tohost控制/状态寄存器(CSR),它是非标准主机目标的一部分接口 (HTIF) 已被删除。当前(截至 2016 年 9 月)riscv-tests改为对tohost内存位置执行内存映射存储,在 tethered 环境中由front-end server.


如果您真的需要/想要运行RISC -V 代码裸机,那么这里是执行此操作的说明。你会丢失一堆有用的东西,比如 riscv-pk(代理内核)提供的 printf 或 FP-trap 软件仿真。

首先要做的事情 - Spike 在 0x200 启动。由于 Spike 是黄金 ISA 模拟器模型,您的内核也应该在 0x200 启动。

咳咳,截至 2015 年 7 月 13 日,riscv-tools 的“master”分支(https://github.com/riscv/riscv-tools)正在使用较旧的 pre-v1.7 特权 ISA,因此从 0x2000 开始. 这篇文章将假设您使用的是 v1.7+,这可能需要使用 riscv-tools 的“new_privileged_isa”分支)。

所以当你反汇编你的裸机程序时,最好从 0x200 开始!!!如果你想在代理内核上运行它,最好从 0x10000 开始(如果是 Linux,它会更大……)。

现在,如果你想运行裸机,你就强迫自己编写处理器启动代码。呸。但是,让我们对此进行抨击并假装这没有必要。

(您还可以查看 riscv-tests/env/p,以获取物理寻址机器的“虚拟机”描述。您会找到所需的链接描述文件和一些用于描述一些初始设置代码的宏。或者更好然而,在 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

和链接.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 = .;
 }

现在编译这个…</p>

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 开始,然后将 #1 写入控制/状态寄存器“tohost”,这告诉 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运行裸机的启动和支持代码。

于 2015-07-13T21:32:57.507 回答
6

“额外”代码由 gcc 放在那里,是任何程序都需要的东西。代理内核被设计为运行这些东西所需的最低限度的支持。一旦你的处理器开始工作,我建议你在 pk 而不是裸机上运行东西。

同时,如果您想查看简单的组装,我建议您使用“-c”跳过链接阶段:

riscv64-unknown-elf-gcc code.c -c -o code.o
riscv64-unknown-elf-objdump -d code.o

对于没有 pk 或 linux 的运行代码示例,我会查看riscv-tests

于 2015-07-13T20:15:18.423 回答
0

我很惊讶没有人提到gcc -S它完全跳过汇编和链接并输出汇编代码,尽管有一堆样板,但只是四处逛逛可能很方便。

于 2020-12-14T16:14:00.790 回答