assembly LDR X10,[X9,#0]处的分段故障

ddhy6vgd  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(384)

我试着编写一个ARM-LEGv 8汇编程序,计算数组中某个位置的两个值的平均值,它在Raspberry Pi上运行。
伪代码应如下所示:

int average(int v[], int i){
  int average = (v[i] + v[i-1])/2;
  return average;
}

数组位于X 0,i位于X1。
我的汇编代码如下所示:

.globl _start

.data
myArray: .word 0, 1, 2, 3, 35, 5

.text

average:
  LSL X9, X1, #2
  ADD X9, X9, X0
  LDR X10, [X9, #0] // guess Segmentation Fault 
  LDUR X11, [X9, #-4]
  ADD X3, X10, X11  
  LSR X3, X3, #1 
  BR X30

_start:
  LDR X0, myArray
  MOV X1, #5
  BL mittelwert

  MOV X8, #0x5d
  MOV X0, X3
  SVC 0

我使用了以下命令来构建它:
as average.s -o average.o
gcc average.o -o average -nostdlib -static
当我运行我的程序时,我得到一个分段错误。为什么?

7xzttuei

7xzttuei1#

( 免责 声明 :以下 内容 基于 实际 的 ARMv8 - A 指令 集 。 我 不 确定 LEGv8 可能 做 了 哪些 更改 。 )
LDR X0, myArray 不会 加载 带有 标签 myArray 的 地址 的 X0 。 它 会 从 该 地址 * 加载 一 个 双 字 ( ARM 称 之 为 加载 指令 的 " 文字 " 形式 ) 。 因此 , 在 此 指令 之后 , X0 包含 0x0000000100000000 , 在 执行 LDR X10, [X9, #0] 时 , 0x0000000100000000 自然 会 导致 指针 无效 。
你 可能 指 的 是 LDR X0, =myArray , 它 会 把 一 个 指向 myArray 的 指针 放到 文本 池 中 , 然后 从 该 指针 在 文本 池 中 的 地址 组装 该 指针 的 文本 负载 。 假设 你 的 系统 可以 处理 这种 类型 的 重 定位 , 这 是 可行 的 。 但是 , 对于 常见 操作 系统 使用 的 现代 位置 无关 的 可 执行 文件 , 首选 的 方法 是

ADR X0, myArray
ADD X0, X0, #:lo12:myArray

中 的 每 一 个
第 一 条 指令 使用 myArray 地址 的 高 52 位 填充 X0 的 这些 位 ( 使用 PC 的 偏移 量 ) 。 第 二 条 指令 添加 低 12 位 。 另 请 参阅 了解 ARM 重 定位 ( 示例 :字符 串 x0 , [ 临时 , # : lo12 : zbi _ paddr ] )
其他 几 个 错误 和 备注 :

  • 你 的 LDR X10, [X9, #0]LDUR X11, [X9, #-4] 是 64 位 加载 , 因为 你 使用 了 一 个 X 寄存 器 作为 目标 。 但是 myArray 的 元素 是 用 .word 定义 的 , 32 位 。 所以 每个 寄存 器 的 高 32 位 将 包含 垃圾 。为了 与 32 位 元素 保持 一致 , 将 它们 加载 到 W 寄存 器 LDR W10, [X9, #0]LDUR W11, [X9, #-4] 中 ,然后 在 W 寄存 器 上 进行 运算 。
  • 您 将 数组 元素 视为 带 符号 的 int 类型 , 但 您 的 代码 当前 无法 正确 处理 负值 ( 提示 :LSR 中 的 L 是 什么 ? ) 。 考虑 一下 如何 修复 此 问题 , 或者 将 其 更改 为 unsigned
  • 类似 地 , i 在 C 中 声明 为 int , 但 您 访问 X1 时 将 其 作为 64 位 寄存 器 。 如果 您 从 C 中 调用 此 函数 , ARM64 ABI 允许 X1 的 高位 为 垃圾 。 您 可能 希望 将 其 声明 为 size_tunsigned long 。 如果 您 确实 将 其 保留 为 32 位 类型 ,很 可能 unsigned 就是 您 想要 的 , 然后 您 需要 在 使用 它 之前 将 W1 零 扩展 为 X1
  • 当 从 一 个 函数 返回 时 , 首选 RET 而 不是 BR X30 , 因为 前者 更 适合 于 此 目的 。 ( 尽管 LEGv8 可能 没有 RET ? )

相关问题