Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 通过.data变量或寄存器访问数组_Assembly_X86_Gnu Assembler_Att - Fatal编程技术网

Assembly 通过.data变量或寄存器访问数组

Assembly 通过.data变量或寄存器访问数组,assembly,x86,gnu-assembler,att,Assembly,X86,Gnu Assembler,Att,我有一个数组,正在将该数组的基址加载到%esi寄存器中。我可以访问数组中的第一个元素,例如:pushl0(%esi),第二个元素:pushl4(%esi),等等。但是,如果用.data部分的变量替换(%esi)之前的数字,则会出现分段错误: .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

我有一个数组,正在将该数组的基址加载到%esi寄存器中。我可以访问数组中的第一个元素,例如:
pushl0(%esi)
,第二个元素:
pushl4(%esi)
,等等。但是,如果用.data部分的变量替换
(%esi)
之前的数字,则会出现分段错误:

.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

有人能给我解释一下为什么这不起作用,以及是否有可能以这种方式访问数组中的元素吗?

首先,您的函数main的顶部有:

第一个问题是使用索引寻址(带位移),将ESI中的值作为地址。因此,内存地址ESI+0处的值相等。问题是您没有初始化ESI。您应该使用数组的地址初始化它。因此,将代码更改为:

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
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
输出如下所示:

out: 1
out: 2
out: 2
out: 1
out: 2
out: 5
从您的代码来看,不确定k是在数组中保存一个元素号,还是只是数组中的一个字节偏移量。如果希望访问数组中的第k个元素(基于0),则需要在基于索引的寻址模式上使用比例因子,如下所示:

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
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
这将打印出数组中的第四个元素(基于0)或您的案例中的值
5
。输出如下所示:

out: 1
out: 2
out: 2
out: 1
out: 2
out: 5

您在任何地方初始化过esi吗?对不起。我赶时间,忘了加行。现在更正了!非常感谢。我尝试使用基于索引的寻址模式来实现这一点,但我不知道使用哪个寄存器作为基址寄存器。这适用于32位代码(不适用于更有限的16位代码)