我有一个C函数,它将一些内存分配给一个数组,该数组将填充自然数字达到某个N.
让我们说,
N = 10;
array = calloc(N, sizeof(int));
然后我调用了我编写的汇编函数,但是我似乎无法访问数组字段。我设法找到N的值,它位于8(%ebp),我已经用GDB检查它确实等于C代码中的N.
但是,当我尝试访问数组中的第一个元素并将其移动到例如%esi时,该值不应为零。
我通过使用以下代码
movl 12(%ebp), %esi
EDIT;在调用汇编函数之前,我当然用自然数填充数组。我只是不想在这里输入for循环。
据我了解,括号取消了数组的第一个元素,并将其复制到esi,但是,当我在GDB中的此代码之后的断点上使用信息寄存器时,esi只包含一个巨大的负数。
那么,我如何访问事先被调用的数组并传递给汇编函数?是不是可以降低,并复制那个单一元素?
这是调用汇编函数的C函数
int main(int argc, char *argv[]){
int n = 10;
int *array = calloc(n, sizeof(int));
int i, j;
// Populate array up to N
for(i = 0; i < n; i++){
array[i] = 2 + i;
}
printf("Array: %d \n", sizeof(array));
// Run sievs
sievs_assembly(n, array);
// print prime
print_prime(array, n);
// Free mem
free(array);
return EXIT_SUCCESS;
}
我不想整体发布汇编文件,因为它是一个学校项目,我不是要求帮助解决评估,只是具体问题。如何降级数组项。
函数原型是
extern void sievs_assembly(int n, int *a);
我认为既然指针* a是一个int数组,并且第一个参数N位于8(%ebp),那么第一个数组元素将是12(%ebp)。
如果不足以执行movl 12(%ebp),%esi
,我如何实际获得该值答案 0 :(得分:2)
当你这样做时:
movl 12(%ebp), %esi
您已将阵列的内存地址移至%esi。第一个元素的值是这个地址所指向的。为此,你可以使用:
movl (%esi), %eax
这会将第一个元素移动到%eax中。括号基本上是指&#34;%esi指向&#34;。 int的大小可能是4个字节(您可以使用&#39; sizeof(int)&#39;)进行检查。因此,要访问您可以使用的下一个元素:
movl 4(%esi), %eax
将下一个元素移动到%eax。
我还制作了一个示例程序,它从数组中打印出2个值。注意:我是为windows制作的。
.macro print str #macro name is 'print'. 1 argument: 'str'
pushl \str #argument names are escaped
call _printf
addl $4, %esp #pop the arguments
.endm
.macro printf str fs #can't overload macro names, so let's call this one 'printf'
pushl \str
pushl \fs #printing numbers requires a format srting
call _printf
addl $8, %esp
.endm
.text
.global _main
_main: #actual program, '_main' becomes 'WinMain@16'
pushl %ebp #push frame
movl %esp, %ebp
movl $array, %esi #Move array pointer to $esi.
#print what %esi is pointing to
printf (%esi), $fs
#print a newline
print $nl
#print what %esi+4 is pointing to. Since a long is 4 bytes
#The next element of the array is 4 bytes further than the first
printf 4(%esi), $fs
movl $0, %eax #move 0 to return register
leave #pop frame
ret #return
.data
fs: .string "%i" #Format string
nl: .string "\n" #New Line
array: #Some array
.long 1,2
该程序打印输出:
1
2
修改强>: 由于这引起了一些关注,我想我会用一些宏更新答案。
并解释c库调用_
前缀和main
;我正在使用MinGW在Windows上进行编译,这需要这些前缀以避免出现未定义的引用错误。在Linux上,他们不需要。
答案 1 :(得分:0)
稍微修改一下。通过gcc -m32 -g -o foo foo.s
编译它.data
fs: .string "%i" #Format string
nl: .string "\n" #New Line
array: .long 1,2
.text
.global main
main:
pushl %ebp #push frame
movl %esp, %ebp
movl $array, %esi #Move array pointer to $esi.
pushl (%esi) #Push what %esi is pointing to
pushl $fs #push the format string
call printf #call printf
addl $8, %esp #pop the arguments
pushl $nl #print a new line
call printf
addl $4, %esp
pushl 4(%esi) #push what %esi+4 is pointing to. Since a long is 4 bytes
pushl $fs #The next element is 4 bytes further than the first
call printf
addl $8, %esp
pushl $nl #print a new line
call printf
addl $4, %esp
pushl $0
call exit