.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:
#...
我不知道如何将“scanf”值转换为数组。我认为如果我计算每个索引的地址,将地址指向的值压入堆栈并调用scanf,它就会工作。但是我得到了内存访问错误。
那么,有没有办法像这样做?
答案 0 :(得分:0)
如果我使用%edi而不是%ecx作为我的索引,我无法判断它是否有效。
我仍然不知道如何使用调试器,因此我在每次迭代中打印出我的索引以查看错误。问题是%ecx从未超过1,这使得程序陷入无限循环。
但是,使用%edi,增量效果非常好。
PS:出于好奇,我也尝试了其他寄存器,即%esi和%ebx。它也适用于他们。如果我找到原因,我会回顾这篇文章。编辑:好的,错误是一个愚蠢的错误。我没有遵守召集惯例。
所以scanf
与printf
一样,显然会改变寄存器值。按照惯例,%eax
,%ecx
和%edx
来电保存,而%ebx
,%edi
和%esi
是被调用者保存。
因为作为来电者,我在调用%ecx
之前未保存scanf
,因此我在%ecx
中收到了不需要的值。
它适用于%edi
,%esi
和%ebx
,因为它们是被调用者保存的,因此保证不会被被调用的函数更改。因此,如果我尝试过%eax
或%edx
,那么它很可能也不会有效。
是的,如果我在调用scanf之前在堆栈上按%ecx
,它的工作完全正常。
EDIT2: 哦,通过使自己成为一个全局变量来解决访问问题,我在其中扫描一个数字,并将该数字移动到所需的索引中:
.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
#...