裸机 RISC-V CPU - 处理器如何知道从哪个地址开始获取指令?

2024-01-20

我正在设计自己的 RISC-V CPU,并且已经能够实现一些指令代码。

我已经安装了 RV32I 版本的 GCC 编译器,所以我现在有了汇编器riscv32-unknown-elf-as可用的。

我正在尝试仅用一条指令来汇编一个程序:

# simple.asm
add x5,x6,x7

我使用汇编器编译它,然后使用以下命令运行 objdump:

riscv32-unknown-elf-as simple.asm -o simple
riscv32-unknown-elf-objdump -D simple

这会打印出以下内容:

new:     file format elf32-littleriscv


Disassembly of section .text:

00000000 <.text>:
   0:   007302b3                add     t0,t1,t2

Disassembly of section .riscv.attributes:

00000000 <.riscv.attributes>:
   0:   2d41                    jal     0x690
   2:   0000                    unimp
   4:   7200                    flw     fs0,32(a2)
   6:   7369                    lui     t1,0xffffa
   8:   01007663                bgeu    zero,a6,0x14
   c:   00000023                sb      zero,0(zero) # 0x0
  10:   7205                    lui     tp,0xfffe1
  12:   3376                    fld     ft6,376(sp)
  14:   6932                    flw     fs2,12(sp)
  16:   7032                    flw     ft0,44(sp)
  18:   5f30                    lw      a2,120(a4)
  1a:   326d                    jal     0xfffff9c4
  1c:   3070                    fld     fa2,224(s0)
  1e:   615f 7032 5f30          0x5f307032615f
  24:   3266                    fld     ft4,120(sp)
  26:   3070                    fld     fa2,224(s0)
  28:   645f 7032 0030          0x307032645f

我的问题是:

  1. 这里发生了什么?我以为我会有一个简单的单行十六进制,但还有很多事情要做。
  2. 如何指示我的处理器开始读取某个内存地址处的指令?看起来 objdump 也不知道指令从哪里开始。

需要明确的是,我目前将我的处理器视为裸机。我想象我将在处理器中进行硬编码,指令从内存地址 X 开始,数据在内存地址 Y 可用,堆栈在内存地址 Z 可用。这是正确的吗?或者这是错误的方法?


@PeterCordes 的回答让我走上了正确的道路。我终于弄清楚如何生成可以使用的原始内存转储文件。

步骤如下:

  1. 修改了程序集文件以具有.text and .data部分和一个_start标签。我的simple.asm文件现在如下所示:

    .globl _start
    
    .text
    _start:
      add x5,x6,x7
    
    .data
    L1: .word 27
    
  2. 组装.asm to a .o使用以下命令创建文件:

    riscv32-unknown-elf-as simple.asm -o simple.o
    
  3. 为特定处理器创建链接描述文件。我关注了这个惊人的video https://www.youtube.com/watch?v=B7oKdUvRhQQ它演示了从头开始创建链接器脚本的过程。现在,我只需要.text and .data部分。所以我的链接器脚本(mycpu.ld)如下图所示:

    OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
    ENTRY(_start)
    
    MEMORY
    {
      DATA (rwx) : ORIGIN = 0x0, LENGTH = 0x80
      INST (rx) : ORIGIN = 0x80, LENGTH = 0x80
    }
    
    SECTIONS
    {
      .data :
      {
        *(.data)
      }> DATA
    
      .text :
      {
        *(.text)
      }> INST
    }
    
    
  4. 使用生成ELF文件riscv32-unknown-elf-gcc它会自动调用riscv32-unknown-elf-ld:

    riscv32-unknown-elf-gcc -nostdlib -T mycpu.ld -o simple.elf simple.o
    
  5. 从以下位置创建原始二进制或十六进制文件.elf我将使用它来填充内存内容的文件。

    riscv32-unknown-elf-objcopy -O binary simple.elf simple.hex
    

Final simple.hex包含以下内容(使用hexyl):

┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ 1b 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │•0000000┊00000000│
│00000010│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000020│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000030│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000040│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000050│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000060│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000070│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │00000000┊00000000│
│00000080│ b3 02 73 00             ┊                         │וs0    ┊        │
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘

where b3027300是十六进制值add x5,x6,x7.

就是这样!非常感谢@PeterCordes 的帮助! :)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

裸机 RISC-V CPU - 处理器如何知道从哪个地址开始获取指令? 的相关文章

  • 推送 64 位 intel osx

    我想将 64 位地址压入堆栈 如下所示 asm pushq 0x1122334455667788 但我得到编译错误 我只能按以下方式推送 asm pushq 0x11223344 有人可以帮助我理解我的错误吗 我是装配新手 所以如果我的问题
  • 汇编编程语言:程序仅当输入为 ESC 时退出,并在退出前要求确认(y/n),否则循环

    我只是汇编语言编程的初学者 我们的第一个任务是让程序仅在输入为 ESC 时退出 退出之前请求确认 y n 否则循环 我知道 ESC 在 ASCII 代码中具有等效值 但我对插入位置或是否需要添加更多内容感到困惑 请帮我 这是程序 model
  • 将静态链接的 elf 二进制文件转换为动态链接的

    我有一个 elf 二进制文件 它已静态链接到 libc 我无权访问其 C 代码 我想使用 OpenOnload 库 它在用户空间中实现了套接字 因此与标准 libc 版本相比提供了更低的延迟 OpenOnload 实现标准套接字 api 并
  • 在汇编中显示两位数? [复制]

    这个问题在这里已经有答案了 我对汇编编程完全陌生 在课堂作业的示例中 需要将两个数字相加并显示总和 我发现神秘的是当其是两位数时显示总和 这是我的代码 mov al num1 mov bl num2 add al bl add ax 303
  • x86-64 上这个语句有什么问题?

    该函数的目的是获取堆栈的起始地址 unsigned long find start void asm movq rsp eax 当我编译它时 出现错误 Error suffix or operands invalid for movq mo
  • 什么时候汇编比C更快? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的
  • Clang 使用 -nostdlib 生成崩溃代码

    我正在尝试为可执行文件设置自己的运行时环境 但无法使用 clang v3 4 1ubuntu1 目标 x86 64 pc linux gnu 来生成没有段错误的可执行文件 我已将问题简化为以下内容 如果我有一个文件 crt1 c 除了满足
  • 如何让c代码执行hex机器代码?

    我想要一个简单的 C 方法能够在 Linux 64 位机器上运行十六进制字节码 这是我的 C 程序 char code x48 x31 xc0 include
  • orpd等SSE2指令有什么意义?

    The orpd指令是 压缩双精度浮点值的按位逻辑或 这不是做完 全相同的事情吗por 按位逻辑或 如果是这样 拥有它还有什么意义呢 请记住 SSE1orps https www felixcloutier com x86 orps首先 实
  • 在 x86 程序集中将整数打印到控制台

    当我在 16 位汇编中添加两个值时 将结果打印到控制台的最佳方法是什么 目前我有这个代码 CODE START mov ax 1 put 1 into ax add ax 2 add 2 to ax current value mov ah
  • 为什么 Visual Studio 使用 xchg ax,ax

    我正在查看程序的反汇编 因为它崩溃了 并注意到很多 xchg ax ax 我用谷歌搜索了一下 发现它本质上是一个 nop 但是为什么 Visual Studio 会执行 xchg 而不是 noop 该应用程序是一个C NET3 5 64位应
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • 如何手动加载并执行 ELF 二进制可执行文件?

    假设二进制文件是PIC 如何将其加载到内存并执行入口点 我这样做是为了熟悉 ELF 所以execve不允许 这些是基本步骤 阅读程序头以查找 LOAD 指令并确定您需要的映射的总长度 以页为单位 将最低地址的 LOAD 指令映射到总长度 可
  • 减法进位标志

    我正在使用 MASM32 有了这个代码 mov eax 5 sub eax 10 CF 状态标志将被设置 但使用我的铅笔和纸 我实际上看到 MSB 没有任何进位 是的 我知道从较少的数字中减去大的数字集CF 但我想知道为什么 因为使用这段代
  • 为什么 RISC-V S-B 和 U-J 指令类型以这种方式编码?

    我正在读一本书 计算机组织与设计RISC V版 我遇到了 S B 和 U J 指令类型的编码 我上面提到的那些类型有奇怪的编码立即字段 S B 类型将直接字段分为两部分 这是有道理的 因为所有指令编码都必须相似 但我无法理解为什么立即字段以
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • CPU是如何做减法的?

    我有一些基本的疑问 但每次我坐下来尝试面试问题时 这些问题和我的疑问就会出现 假设 A 5 B 2 假设A和B都是4字节 那么CPU是怎么做的呢 A B添加 我知道 A 的符号位 MSB 为 0 表示正值 B 的符号位为 1 表示负整数 现
  • 68HC11计算sin(x)的汇编代码

    68HC11 使用泰勒级数或查找表计算正弦值的汇编代码是什么 显示值只能是整数 查找表如何工作 在这种情况下 如何使用它来实现泰勒级数 http en wikipedia org wiki Taylor series 如果您正在寻找浮点解决
  • “mov (%ebx,%eax,4),%eax”如何工作? [复制]

    这个问题在这里已经有答案了 一直在从事装配作业 并且在很大程度上我对装配非常了解 或者至少对于这项任务来说足够好 但这个 mov 的声明让我很困惑 如果有人能解释这个 mov 语句如何操作寄存器值 我将非常感激 mov ebx eax 4
  • 使用 NEON 优化 Cortex-A8 颜色转换

    我目前正在执行颜色转换例程 以便从 YUY2 转换为 NV12 我有一个相当快的函数 但没有我预期的那么快 主要是由于缓存未命中 void convert hd uint8 t orig uint8 t result uint32 t wi

随机推荐

  • Linux 上的 C++ 开发 Code::Blocks、EMACS 或 GVIM [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在多个项目之间共享声明式管道

    我在不同的存储库中有很多项目 它们共享相同的基本 CI 工作流程 我可以轻松地将其表达为声明式管道 pipeline agent any options buildDiscarder logRotator numToKeepStr 20 s
  • 使用相同关键字并条件 Django 查询

    我有一个带有发布模型和标签模型的 Django 应用程序 每份出版物都有一个或多个与其关联的标签 我想使用一组两个标签查询数据库 并且仅返回同时具有这两个标签的出版物 尽管我确信它很容易获得 但我似乎找不到它的语法 我想我没有使用正确的语言
  • 为什么我的应用程序没有绘制任何东西?

    我对 C 一般编程 非常陌生 阅读了 3 周的经验 从 html css 和 javascript 开始 现在开始使用 C 我正在尝试以 Windows 形式制作自己的简单 绘画 应用程序 但我遇到了一个问题 只是无法解决它 无论我阅读或遵
  • 如何在 Javascript 中替换字符串中的撇号?

    给定一个 Javascript 中的字符串 例如 var str this s kelly 我想用另一个字符替换撇号 这是我到目前为止所尝试过的 str replace quot A str replace A 这些都不起作用 我该怎么做
  • 追踪有用信息

    这里聪明的程序员如何跟踪他们在多年的经验中获得的方便的编程技巧和有用的信息 诸如有用的编译器参数 IDE 快捷方式 巧妙的代码片段等 当我查找一两年前我曾经知道的东西时 我有时会感到沮丧 我最喜欢的 IE 可能代表了 20 世纪 90 年代
  • Linq 多个 OR 与列表

    我目前正在开发一个使用 LINQ 的 C 项目 我想知道是否可以使用 Linq 创建一个 多个 OR 子句 并将列表作为 where 的条目 我的意思是这样的 var listofId var sqlQuery from T in myta
  • 加载共享库时出错:?:无法打开共享对象文件:没有这样的文件或目录

    我正在尝试诊断 并修复 位于多个组件边界上的问题 非常感谢任何有关如何获取更多信息或彻底解决问题的见解 我有一个应用程序 它作为 C 程序启动 可以启动 Java 程序 然后可以以递归方式启动相同的 C 程序 它已经在 Linux 和 Cy
  • 了解 WebSocket

    我的理解是 一个socket对应一个网络标识符 端口和TCP标识符 1 操作系统使进程能够与端口关联 IIUC 是使进程在网络上可针对入站数据进行寻址的一种方式 因此 WebSocket 服务器通常会与众所周知的用于接受和理解升级请求的 H
  • Javascript 将字符串匹配到部分匹配

    如何在 Javascript 中进行部分字符串匹配 例如匹配 阿尔夫 阿尔弗雷德 gt 正确 阿尔夫 gt 正确 alf gt 真 al gt 真 改变 gt false 一半 gt 假 gt 假 鲍勃 gt 假 https jsfiddl
  • 将单索引数据帧添加到多索引数据帧、Pandas、Python

    如何将单个数据框添加到多索引数据框 例如 我的多索引数据是 Name Code Buying Date Buying Price Buying Qty Date Code 20140117 none a 1234 20170101 5 7
  • 连接两个 Pandas 数据框

    请给出两个数据框 DF1 A B a1 b1 a2 b2 a3 b3 DF2 C1 C2 C3 0 0 1 我想做以下 DF1 DF2 产生以下结果 A B C1 C2 C3 a1 b1 0 0 1 a2 b2 0 0 1 a3 b3 0
  • 打开Refine - 将另一个文件添加到现有项目中

    我已将 CSV 文件导入到 OR Open Refine 由于我的 CSV 文件包含超过 200 000 条记录 我决定创建单独的文件 因为上传大文件在我的计算机中无法工作 需要很长时间 甚至不确定它是否真正导入 我能够从单个文件 大 中创
  • 相当于 JavaFX8 的 JGraph?

    我想将一个使用旧版本 JGraph 的旧 swing 工具移植到 JavaFX8 然而 由于 JGraph 是一个基于 Swing 的库 因此也考虑替换它 那么 是否有类似于 JGraph 的东西 但与 JavaFX8 一起使用 那么 是否
  • 将类添加到特定类名上的 .hover 功能 - jQuery

    因此 在我的整个文档中 我希望每次用户将鼠标悬停在具有特定类名称的元素上时 我都希望添加一个类 我的 CSS 看起来像这样 hotspot hover hotspothover border 4px solid fff box shadow
  • 查找并重命名所有文件扩展名不正确的图片

    我正在寻找一种方法来自动重命名所有文件扩展名错误的图像 到目前为止 我至少找到了如何获取所有这些文件的列表 find media folder name jpg exec file grep PNG GIF gt foobar txt fi
  • 在scala中玩框架表单验证

    scala 中 play 框架表单验证的工作 跟随我的 Signup 对象 它在 mapping missing 对象表单中方法映射的参数 遵循此方法与 如果你想 将其视为部分应用函数 case class UserRegistration
  • getAllCellInfo 在 android 4.2.1 中返回 null

    我的 Android 版本是 4 2 1 我正在尝试使用TelephonyManager getAllCellInfo 方法 在我的清单文件中我有ACCESS COARSE UPDATES ACCESS COARSE LOCATION AC
  • Jquery Ajax 中的函数作为参数

    是否可以将函数放入 Jquery Ajax 的参数中 如下所示 dataType 和 data 作为函数给出 如果返回类型为 JSON 则 dataType 返回 JSON 值 如果 isJson 为 false 则返回文本 dataVal
  • 裸机 RISC-V CPU - 处理器如何知道从哪个地址开始获取指令?

    我正在设计自己的 RISC V CPU 并且已经能够实现一些指令代码 我已经安装了 RV32I 版本的 GCC 编译器 所以我现在有了汇编器riscv32 unknown elf as可用的 我正在尝试仅用一条指令来汇编一个程序 simpl