assembly - RISC V 装配对齐错误
问题描述
我正在尝试使用 Spike RISC-V 仿真器和 pk 内核构建类似 Forth 的线程解释语言 (TIL)。我正在使用 riscv64-unknown-elf-gcc 来构建 ELF。
我在对齐方面遇到了很多问题 - 我相信代码应该是八字节对齐的,有一段时间我通过在头生成宏中添加一个 nop 来解决这个问题(对于那些不知道 TIL 的人,命令通常是由具有标准结构的组装块构建 - 我正在使用宏来生成结构。
我刚刚扩展了很多代码 - 添加了更多关键字等 - 对齐问题又回来了。例如:
riscv64-unknown-elf-gcc -o riscyforth riscyforth.S
...... /../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/bin/ld: /tmp/ccpobhjr.o(.text+0x679): 7 bytes required for alignment to 8-byte boundary, but only 6 present
..... /../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/bin/ld: can't relax section: bad value
collect2: error: ld returned 1 exit status
这是生成函数头的宏:
.macro CODEHEADER Name, PrevName, flags
.balign 8
TIL_\Name:
.4byte \flags
.4byte \Name
ptr_\PrevName:
.4byte TIL_\PrevName
length_ASCII_\Name:
.4byte end_\Name - beg_\Name
beg_\Name:
.ascii "\Name"
end_\Name:
.balign 8
\Name:
.endm
可执行代码从 \Name 开始,这是我试图保证 8 字节对齐的地方 - 例如,一个典型的函数可能看起来像(这个在堆栈上放置一个 1):
CODEHEADER 1, DOT
li t0, 1
PUSH t0
tail NEXT
并且li t0, 1
将\Name
在 Name 所在的位置找到1
。
有没有办法保证这种对齐?我在在线文档中找不到任何内容,但想知道是否有任何用户在这里有启发式方法?
解决方案
这是我解决这个问题的方法:
.balign 8
似乎工作正常,但它不能保证我的 FORTH 中的所有指令都正确对齐,因为(如果你熟悉 FORTH/TIL,这比你不熟悉更有意义)函数头有可变大小的函数名称因此后面是不一定对齐的实际代码。
我通过为函数名称留出固定大小并确保代码在对齐的地址上再次启动来解决此问题。我还在每个函数的开头发出一个 nop,以确保每个函数都从一个对齐的地址开始。这是宏:
.macro CODEHEADER Name, PrevName, flags
nop
TIL_\Name:
.4byte \flags
.4byte \Name
ptr_\PrevName:
.4byte TIL_\PrevName
length_ASCII_\Name:
.4byte (end_\Name - beg_\Name) + 1
beg_\Name:
.ascii "\Name"
end_\Name:
.fill (24 - (end_\Name - beg_\Name)), 1, 0xFF
\Name:
.endm
推荐阅读
- python - 比较句子字符串的两个数据帧列并为第三帧创建新值
- html - Flexbox:所有列高度相同,文本居中
- ffmpeg - 展平 360 度鱼眼视频
- mysql - MySQL:向查询中添加列以汇总来自另一个表的顺序数据
- javascript - 如果您已经访问过页面,则分页不会获取数据
- python - 在 django 网站上使用 Matplotlib
- javascript - 追加不将项目添加到列表
- sql - 在sql apex中连接表?
- html - 我想在视频顶部的“文本叠加”所以我可以调整它们的大小/位置
- swiftui - SwiftUI ObservableObject 和已发布问题