如何解决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,这比不熟悉时更有意义)函数头具有变量size 函数名称等后面是不一定要对齐的实际代码。
我通过为函数名称留出固定大小来解决这个问题,并确保代码在对齐的地址上再次启动。我还在每个函数的开头发出 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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。