Arrays 通过scanf将值获取到数组中
我不知道如何“扫描”数组中的值。我想,如果我计算每个索引的地址,将地址指向的值推送到堆栈上并调用scanf,它就会起作用。但是我得到了一个内存访问错误Arrays 通过scanf将值获取到数组中,arrays,assembly,x86,scanf,Arrays,Assembly,X86,Scanf,我不知道如何“扫描”数组中的值。我想,如果我计算每个索引的地址,将地址指向的值推送到堆栈上并调用scanf,它就会起作用。但是我得到了一个内存访问错误 那么,有没有办法做到这一点呢?由于某些原因,如果我使用%edi而不是%ecx作为索引,我无法判断它是否有效 我仍然不知道如何使用调试器,所以我在每次迭代中都打印出我的索引,看看哪里出了问题。问题是%ecx从未超过1,这使得过程陷入无限循环 然而,使用%edi时,增量工作得非常好 PS:出于好奇,我还尝试了其他寄存器,即%esi和%ebx。这也适用
那么,有没有办法做到这一点呢?由于某些原因,如果我使用%edi而不是%ecx作为索引,我无法判断它是否有效 我仍然不知道如何使用调试器,所以我在每次迭代中都打印出我的索引,看看哪里出了问题。问题是%ecx从未超过1,这使得过程陷入无限循环 然而,使用%edi时,增量工作得非常好 PS:出于好奇,我还尝试了其他寄存器,即%esi和%ebx。这也适用于他们。如果我能找到原因,我会回到这篇文章 编辑:好吧,这个错误很愚蠢。我没有遵守通话惯例 所以
scanf
,就像printf
,显然改变了寄存器值。按照惯例,%eax
、%ecx
和%edx
是调用方保存,而%ebx
、%edi
和%esi
是调用方保存。
因为我作为调用者在调用scanf
之前没有保存%ecx
,所以我在%ecx
中得到了一个不需要的值。
它适用于%edi
、%esi
和%ebx
,因为它们是被调用方保存的,因此保证不会被调用函数更改。因此,如果我尝试使用%eax
或%edx
替代,它很可能也不会起作用
是的,如果我在调用scanf之前在堆栈上按下%ecx
,它会工作得非常好
编辑2:
哦,通过使自己成为一个全局变量,扫描一个数字,并将该数字移动到所需的索引中,解决了访问问题:
.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 $0, %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 $8, %esp
incl %ecx
jmp scanloop
#endscanf
endscan:
#...
.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 $8, %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
#...