【问题标题】:access array through .data variable or through register通过 .data 变量或寄存器访问数组
【发布时间】:2015-11-12 12:24:21
【问题描述】:

我有一个数组,我正在将该数组的基地址加载到 %esi 寄存器中。我可以像这样访问数组中的第一个元素:pushl 0(%esi),第二个像这样:pushl 4(%esi),依此类推。但是,如果我将 (%esi) 之前的数字替换为 .data 部分中的变量,则会出现分段错误:

.data
array: .long 1,2,3,4,5
k: .long 4
out: .string "out: %d\n"

.globl main
main:

  #load array-baseaddress into %esi
  leal  array, %esi

  # Will print 1
  pushl 0(%esi)
  pushl $out
  call printf

  # Will print 2
  pushl 4(%esi)
  pushl $out
  call printf

  # Will result in segmentation fault
  pushl k(%esi)
  pushl $out
  call printf

  call exit

有人可以向我解释为什么这不起作用以及是否可以以这种方式访问​​数组的元素?

【问题讨论】:

  • 你是否真的在任何地方初始化了esi
  • 对不起。我很着急,忘记添加行了。现在已经更正了!

标签: assembly x86 gnu-assembler att


【解决方案1】:

首先你的函数顶部有这个main

main:
  # Will print 1
  pushl 0(%esi)
  pushl $out
  call printf

第一个问题是您使用索引寻址(带位移)以 ESI 中的值作为地址。所以你有相当于内存地址 ESI+0 的值。问题是您没有初始化 ESI 。您应该使用 array 的地址对其进行初始化。所以把代码改成:

main:
  mov $array, %esi    /* initialize ESI with address of array. */

  # Will print 1
  pushl 0(%esi)
  pushl $out
  call printf

在你做的最后一段代码中:

# Will result in segmentation fault
pushl k(%esi)
pushl $out
call printf

当您执行 k(%esi) 时,您希望使用变量 k 中的值作为位移。不幸的是,索引寻址(带位移)仅支持将位移作为常数。在您的情况下,k(%esi) 正在获取 k 的地址并将其添加到 ESI 并将该地址处的值推入堆栈。那不是你想要的。你不能在一次操作中做到这一点。您必须检索变量 k 中的值并将其放入空闲寄存器中,然后使用该寄存器使用基于索引的寻址模式计算地址。你可以用这样的代码做到这一点:

movl   k, %eax         /* move 32-bit value in k to temporary register */
pushl  (%esi, %eax)    /* Push 32-bit value @ memory location %esi+%eax to stack */
pushl $out
call printf

输出如下:

out: 1
out: 2
out: 2

从您的代码中,不确定 k 是否在数组中保存了一个元素编号,或者它是否只是数组中的一个字节偏移量。如果您希望访问数组中的第 k 个元素(基于 0),那么您需要在基于索引的寻址模式上使用缩放因子,如下所示:

movl   k, %eax         /* move 32-bit value in k to temporary register */
pushl  (%esi, %eax, 4) /* Push 32-bit value @ memory location %esi+(%eax*4) to stack */
pushl $out
call printf

这将打印出 array 中的第 4 个元素(基于 0)或值 5 在您的情况下。输出如下所示:

out: 1
out: 2
out: 5

【讨论】:

  • 谢谢!我尝试使用基于索引的寻址模式来实现这一点,但我不知道将哪个寄存器用作基址寄存器。
  • addressing mode list 适用于 32 位代码(不适用于更受限制的 16 位代码)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
  • 2018-10-03
  • 1970-01-01
相关资源
最近更新 更多