首页 > 编程语言 >编译AM程序

编译AM程序

时间:2024-11-15 17:00:21浏览次数:1  
标签:src 程序 nemu riscv32 abstract AM machine 编译 build

编译AM程序

am-kernels/tests/am-tests下运行下面命令,探究下基于riscv32-nemu上的AM程序的编译流程

make ARCH=riscv32-nemu mainargs = 'i' -nB

编译am-test的用户程序

# Building amtest-image [riscv32-nemu]
mkdir -p $AM_TEST/build/riscv32-nemu/src/ && echo + CC src/main.c
($CROSS_COMPILE)gcc -std=gnu11 -O2 -MMD -Wall -Werror
    -I$AM_TEST/include
    -I/abstract-machine/am/include/
    -I/abstract-machine/klib/include/ 
-D__ISA__=\"riscv32\" -D__ISA_RISCV32__ -D__ARCH__=riscv32-nemu -D__ARCH_RISCV32_NEMU -D__PLATFORM__=nemu -D__PLATFORM_NEMU -DARCH_H=\"arch/riscv.h\" -fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector -Wno-main -U_FORTIFY_SOURCE -fvisibility=hidden -DBATCH_MODE -fno-pic -march=rv64g -mcmodel=medany -mstrict-align -march=rv32im_zicsr -mabi=ilp32    -static -fdata-sections -ffunction-sections -DMAINARGS=\"i\"
    -I/abstract-machine/am/src/platform/nemu/include -DISA_H=\"riscv/riscv.h\" -c -o $TEST/build/riscv32-nemu/src/main.o $TEST/src/main.c

分类一下amtest的编译选项$COMPILE_CONFIG$CROSS_COMPILE

$COMPILE_CONFIG = 
-std=gnu11 -O2 -MMD -Wall -Werror
-D__ISA__=\"riscv32\" 
-D__ISA_RISCV32__ 
-D__ARCH__=riscv32-nemu 
-D__ARCH_RISCV32_NEMU 
-D__PLATFORM__=nemu 
-D__PLATFORM_NEMU 
-DARCH_H=\"arch/riscv.h\" 
-fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector -Wno-main 
-U_FORTIFY_SOURCE -fvisibility=hidden -DBATCH_MODE -fno-pic 
-march=rv64g -mcmodel=medany -mstrict-align -march=rv32im_zicsr -mabi=ilp32    
-static -fdata-sections -ffunction-sections 
-DMAINARGS=\"i\"
$CROSS_COMPILE := riscv64-linux-gnu-

这样就简化为

mkdir -p $TEST/build/riscv32-nemu/src/ && echo + CC src/main.c
($CROSS_COMPILE)gcc -std=gnu11 -O2 -MMD -Wall -Werror
    -I$AM_TEST/include
    -I/abstract-machine/am/include/
    -I/abstract-machine/klib/include/
    $COMPILE_CONFIG
    -I/abstract-machine/am/src/platform/nemu/include -DISA_H=\"riscv/riscv.h\" 
-c -o $AM_TEST/build/riscv32-nemu/src/main.o $AM_TEST/src/main.c

此步骤就是将用户程序只编译不链接为一个目标文件main.o

编译AM文件

普通AM模块编译

将AM的普通模块(TRM+IOE+VME + MPE)编译为对应的目标文件(这里以trm.c代表的TRM模块为例)

mkdir -p /abstract-machine/am/build/riscv32-nemu/src/platform/nemu/ && echo + CC src/platform/nemu/trm.c
($CROSS_COMPILE)gcc -std=gnu11 -O2 -MMD -Wall -Werror
    -I/abstract-machine/am/src
    -I/abstract-machine/am/include
    -I/abstract-machine/am/include/
    -I/abstract-machine/klib/include/ 
	$COMPILE_CONFIG
    -I/abstract-machine/am/src/platform/nemu/include 
    -DISA_H=\"riscv/riscv.h\" 
-c -o /abstract-machine/am/build/riscv32-nemu/src/platform/nemu/trm.o /abstract-machine/am/src/platform/nemu/trm.c
#COMPILE_CONFIG信息
$COMPILE_CONFIG = 
-D__ISA__=\"riscv32\" 
-D__ISA_RISCV32__ 
-D__ARCH__=riscv32-nemu 
-D__ARCH_RISCV32_NEMU 
-D__PLATFORM__=nemu 
-D__PLATFORM_NEMU 
-DARCH_H=\"arch/riscv.h\" 
-fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector -Wno-main -U_FORTIFY_SOURCE -fvisibility=hidden 
-DBATCH_MODE 
-fno-pic 
-march=rv64g -mcmodel=medany -mstrict-align -march=rv32im_zicsr -mabi=ilp32    
-static 
-fdata-sections 
-ffunction-sections 
-DMAINARGS=\"i\"

CTE模块的编译

包含三个文件的编译:

  • start.S
  • cte.c
  • trap.S

在编译CTE之前,首先将源文件 start.S 编译为目标文件 start.o

mkdir -p /abstract-machine/am/build/riscv32-nemu/src/riscv/nemu/ && echo + AS src/riscv/nemu/start.S
($CROSS_COMPILE)gcc -MMD
    -I/abstract-machine/am/src
    -I/abstract-machine/am/include
    -I/abstract-machine/am/include/
    -I/abstract-machine/klib/include/ 
    -fno-pic -march=rv64g -mcmodel=medany -mstrict-align -march=rv32im_zicsr -mabi=ilp32    -O0 
-c -o /abstract-machine/am/build/riscv32-nemu/src/riscv/nemu/start.o /abstract-machine/am/src/riscv/nemu/start.S

编译完毕start.S后,随后继续编译AM文件cte.c,执行流程与上面普通AM模块编译参数相同。

生成cte.o后,将trap.S编译为目标文件trap.o

mkdir -p /abstract-machine/am/build/riscv32-nemu/src/riscv/nemu/ && echo + AS src/riscv/nemu/trap.S
($CROSS_COMPILE)gcc -MMD
    -I/abstract-machine/am/src
    -I/abstract-machine/am/include
    -I/abstract-machine/am/include/
    -I/abstract-machine/klib/include/ 
    -fno-pic -march=rv64g -mcmodel=medany -mstrict-align -march=rv32im_zicsr -mabi=ilp32    -O0 
-c -o /abstract-machine/am/build/riscv32-nemu/src/riscv/nemu/trap.o /abstract-machine/am/src/riscv/nemu/trap.S

打包AM库

最终将AM所有模块的目标文件打包为一个静态库文件am-riscv32-nemu.a

echo + AR "->" build/am-riscv32-nemu.a
($CROSS_COMPILE)ar rcs /abstract-machine/am/build/am-riscv32-nemu.a 
/abstract-machine/am/build/riscv32-nemu/src/platform/nemu/trm.o 
/abstract-machine/am/build/riscv32-nemu/src/platform/nemu/ioe/ioe.o 
/abstract-machine/am/build/riscv32-nemu/src/platform/nemu/ioe/timer.o 
/abstract-machine/am/build/riscv32-nemu/src/platform/nemu/ioe/input.o 
/abstract-machine/am/build/riscv32-nemu/src/platform/nemu/ioe/gpu.o 
/abstract-machine/am/build/riscv32-nemu/src/platform/nemu/ioe/audio.o 
/abstract-machine/am/build/riscv32-nemu/src/platform/nemu/ioe/disk.o 
/abstract-machine/am/build/riscv32-nemu/src/platform/nemu/mpe.o 
/abstract-machine/am/build/riscv32-nemu/src/riscv/nemu/start.o 
/abstract-machine/am/build/riscv32-nemu/src/riscv/nemu/cte.o 
/abstract-machine/am/build/riscv32-nemu/src/riscv/nemu/trap.o 
/abstract-machine/am/build/riscv32-nemu/src/riscv/nemu/vme.o

编译klib文件

klib/src/stdio.c为例,看下如何获取klib的目标文件。$COMPILE_CONFIG与编译AM时的参数相同。

mkdir -p /abstract-machine/klib/build/riscv32-nemu/src/ && echo + CC src/stdio.c
($CROSS_COMPILE)gcc -std=gnu11 -O2 -MMD -Wall -Werror
    -I/abstract-machine/klib/include
    -I/abstract-machine/am/include/
    $COMPILE_CONFIG
    -I/abstract-machine/klib/include/                                       
    -I/abstract-machine/am/src/platform/nemu/include 
    -DISA_H=\"riscv/riscv.h\" 
-c -o /abstract-machine/klib/build/riscv32-nemu/src/stdio.o /abstract-machine/klib/src/stdio.c

编译好所有klib的目标文件后,将klib打包为一个静态链接库klib-riscv32-nemu.a

echo + AR "->" build/klib-riscv32?
($CROSS_COMPILE)ar rcs /abstract-machine/klib/build/klib-riscv32-nemu.a
    /abstract-machine/klib/build/riscv32-nemu/src/stdio.o
    /abstract-machine/klib/build/riscv32-nemu/src/int64.o
    /abstract-machine/klib/build/riscv32-nemu/src/string.o
    /abstract-machine/klib/build/riscv32-nemu/src/cpp.o
    /abstract-machine/klib/build/riscv32-nemu/src/stdlib.o
    /abstract-machine/klib/build/riscv32-nemu/src/test.o   

打包用户程序am-test到ELF

这样am-test用户程序,和提供运行环境的AM的库(AM和klib)均已完成,下面就是将所有目标文件链接为一个ELF文件了。

echo + LD "->" build/amtest-riscv32-nemu.elf
($CROSS_COMPILE)ld -z noexecstack -melf64lriscv 
-T /abstract-machine/scripts/linker.ld 
	--defsym=_pmem_start=0x80000000 
	--defsym=_entry_offset=0x0 --gc-sections 
	-e _start 
	-melf32lriscv                                                                                                     -o $TEST/build/amtest-riscv32-nemu.elf
    --start-group
    $TEST/build/riscv32-nemu/src/main.o
    $TEST/build/riscv32-nemu/src/tests/video.o                                                                                   	 $TEST/build/riscv32-nemu/src/tests/mp.o
    $TEST/build/riscv32-nemu/src/tests/hello.o
    $TEST/build/riscv32-nemu/src/tests/devscan.o
    $TEST/build/riscv32-nemu/src/tests/audio/audio-data.o
    $TEST/build/riscv32-nemu/src/tests/audio.o
    $TEST/build/riscv32-nemu/src/tests/keyboard.o
    $TEST/build/riscv32-nemu/src/tests/intr.o
    $TEST/build/riscv32-nemu/src/tests/rtc.o
    $TEST/build/riscv32-nemu/src/tests/vm.o
    /abstract-machine/am/build/am-riscv32-nemu.a
    /abstract-machine/klib/build/klib-riscv32-nemu.a 
    --end-group

其中STFM(man ld)比较有意思的ld的链接选项:

  • -e _start:设置符号entry作为程序执行的开头。如果没有entry这个符号,连接器将会解析entry为一个数字,并将其作为入口地址
  • -T .../linker.ld :用自定义的链接脚本linker.ld 来连接程序
  • --defsys=expression:在链接时定义符号(如变量或标签)及其值。而且此参数与-T有顺序关系。
    • --defsym-T 之前:链接器在处理链接脚本时会首先处理 --defsym 定义的符号。这意味着在链接脚本中引用的符号(比如用来设置段地址或进行内存布局)将是可用的。
    • --defsym-T 之后:链接脚本中的表达式不能使用这些符号

下面就是生成反汇编文本文件:

echo \# Creating image [riscv32-nemu]
($CROSS_COMPILE)objdump -d $TEST/build/amtest-riscv32-nemu.elf > $TEST/build/amtest-riscv32-nemu.txt

生成二进制镜像文件

通过 objcopy 将 ELF 文件转换为 .bin 格式的二进制镜像文件。

echo + OBJCOPY "->" build/amtest-riscv32-nemu.bin
($CROSS_COMPILE)objcopy
  -S
  --set-section-flags
  .bss=alloc,contents
  -O binary
$TEST/build/amtest-riscv32-nemu.elf
$TEST/build/amtest-riscv32-nemu.bin
  • objcopy 是 GNU 工具链中的另一个工具,用于修改目标文件格式,这里用于将 ELF 格式的可执行文件转换为二进制文件(即 .bin 格式)

至此,am-test的编译流程结束。

标签:src,程序,nemu,riscv32,abstract,AM,machine,编译,build
From: https://www.cnblogs.com/shangshankandashu/p/18548262

相关文章

  • 未能加载文件或程序集 “项目名称对应的程序集,Version=1.0.0.0.culture=neutral.Publi
    VisualStudio2022,AutoCAD开发,wpf项目,因viewmodel中代码出现问题,造成窗体设计器中无法预览(这个问题通过修改viewmodel代码解决), 删除项目路径下的obj及bin文件夹后,重新生成项目,出现新的错误:窗体能够显示了,但个别控件无法正常显示,以为是visualstudio出了问题,修复、......
  • 一文掌握:java编译器:跑通helloworld并了解核心原理
    本文旨在详细介绍Java编译器的工作原理及其在Windows系统下的具体使用方法,包括安装步骤、常用命令介绍以及大致原理。通过本文,你可以全面掌握从编写代码到生成可执行文件的全过程,为Java开发奠定坚实的基础。Windows下Java环境的搭建与程序编译为了在Windows环境下运行Jav......
  • 163邮箱发送邮件通知异常 org.springframework.mail.MailAuthenticationException: Au
    从腾讯企业邮箱切换成163邮箱,邮箱配置经过检查未作调整,网络检查均是正常,但发送邮件时一直报错org.springframework.mail.MailAuthenticationException:Authenticationfailed。解决办法:1.检查smtp服务是否打开(若未打开需要开启)2.客户端授权码需打开3.检查邮箱配置 ......
  • 学期2024-2025 20241308 《计算机基础与程序设计》第八周学习总结
    作业信息这个作业属于哪个课程 <班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接>(如2024-2025-1计算机基础与程序设计第一周作业)这个作业的目标 <写上具体方面>功能设计与面向对象设计,面向对象设计过程,面向对象语言三要素,汇编、编译、解释......
  • 微信公众号商家收银台小程序系统存在前台SQL注入漏洞
    免责声明:本文旨在提供有关特定漏洞的深入信息,帮助用户充分了解潜在的安全风险。发布此信息的目的在于提升网络安全意识和推动技术进步,未经授权访问系统、网络或应用程序,可能会导致法律责任或严重后果。因此,作者不对读者基于本文内容所采取的任何行为承担责任。读者在使用本......
  • 2024-2025-1 20241322《计算机基础与程序设计》第八周学习总结
    2024-2025-120241322《计算机基础与程序设计》第八周学习总结作业信息这个作业属于哪个课程https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP这个作业要求在哪里https://www.cnblogs.com/rocedu/p/9577842.html#WEEK08这个作业的目标功能设计与面向对象......
  • SSM冷链物流管理系统的设计与开发90b3l 程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统内容:用户,站点信息,司机,车辆信息,商品信息,订单信息,配送信息开题报告内容一、研究背景随着全球经济的飞速发展和人们生活水平的日益提高,冷链食品的市场......
  • 【微信小程序毕业设计】茶室预约小程序的设计与实现
    概述:某211院校在校计算机导师,让我成为您的校外毕业指导老师。为您的毕业之旅保驾护航,专业为大家做好毕业选题,课外辅导等工作。文章末尾处有资料的获取方式。点击获取即可。技术描述:后端实现-使用node.js作为开发语言,koa2作为接口开发框架数据库-mysql管理端-vue2.0编写管......
  • 【C++源码编译】
    C++源码到二进制可执行文件的过程与C语言类似,包括四个过程:预编译、编译、汇编、链接1、预编译C/C++编译过程中的第一个阶段,主要目的是对源代码进行处理和准备工作。下面是预编译的主要步骤:去除宏定义:将所有的#define删除,并展开所有的宏定义,将宏替换为具体的值或表达......
  • Stream流统计集合元素出现次数并降序
    使用Arrays.stream()结合Collectors.groupingBy()和Collectors.counting()来统计数组中每个元素出现个数,按照出现次数降序排列后获取前五个元素及其出现次数的示例代码:importjava.util.*;importjava.util.stream.Collectors;publicclassArrayElementCountTopFive{......