通过 scanf 获取值到数组中

Getting values into an array via scanf

.data
arr: .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
arr_size: .long 10
in: .string "%d"

.text
.global main
main:

#scanf
movl [=10=], %ecx # index i
scanloop:
  cmpl arr_size, %ecx 
  je endscan # if ecx == 10 -> break
  leal arr(, %ecx, 4), %eax # load the address of arr[i] into eax
  pushl (%eax) # push the value that is being pointed at onto the stack
  pushl $in
  call scanf
  addl , %esp 
  incl %ecx
  jmp scanloop
#endscanf

endscan:
#...

我不知道如何将值 "scanf" 放入数组中。我认为如果我计算每个索引的地址,将地址指向的值压入堆栈并调用 scanf 就可以了。但是我遇到内存访问错误。

那么,有没有办法做到这一点?

由于某些原因,如果我使用 %edi 而不是 %ecx 作为我的索引,我无法判断它是否有效。

我仍然不知道如何使用调试器,所以我在每次迭代中打印出我的索引以查看问题所在。问题是 %ecx 从未超过 1,这使得程序陷入无限循环。

然而,使用 %edi,增量工作得很好。

PS:出于好奇,我也尝试了其他寄存器,即 %esi 和 %ebx。它也适用于他们。如果我找出原因,我会回过头来参考这个post。

编辑:好的,这个错误很愚蠢。我没有遵守调用约定。

所以 scanf,就像 printf,显然改变了寄存器值。按照惯例,%eax%ecx%edxcaller-save,而 %ebx%edi%esicallee-save。 因为作为调用者,我在调用 scanf 之前没有保存 %ecx,所以我在 %ecx 中得到了一个不需要的值。 它适用于 %edi%esi%ebx,因为它们是被调用方保存的,因此保证不会被调用函数更改。因此,如果我尝试 %eax%edx,它很可能也不会起作用。

是的,如果我在调用 scanf 之前将 %ecx 压入堆栈,它会工作得很好。

编辑2: 哦,通过使自己成为一个全局变量来解决访问问题,我在其中扫描一个数字,并将该数字移动到所需的索引中:

.data
num: .long 0
#...
scanloop:
  cmpl arr_size, %ecx 
  je endscan # if ecx == 10 -> break

  pushl %ecx #caller-save
  pushl $num
  pushl $in
  call scanf
  addl , %esp
  popl %ecx #restore
  movl num, %eax #in order to avoid two memory arguments to movl

  leal arr(, %ecx, 4), %edx #calculate address of index
  movl %eax, (%edx) #store num in that index

  incl %ecx
  jmp scanloop
#endscanf
#...