2017-01-30 49 views
0

假设整数数组的大小存储在eax中。我想你可以可以为数组分配存储像这样:如何在堆栈中创建大小为x的数组,并将scanf值创建到该数组中

subl (%eax), %esp 

然而,在EAX大小是由用户提供的,并且将具有不同的尺寸与每个程序的执行。鉴于此,如何初始化用户使用scanf提供的整数每个4字节的内存地址?我们如何确保如果提供的整数大于数组的大小,我们不会覆盖任何内存?

回答

2

subl (%eax), %esp读取由值eax表示的地址的内容。
这很可能是你不想在这种情况下做的事情。

如果eax是数组的字节大小,则subl %eax, %esp将为其分配足够的内存。
如果eax是该数组的32位整数的数量,那么leal (,%eax,4), %esp是正确的指令。

上述说明都没有说明栈的对齐情况。
为了正确地从您的过程中返回,您必须能够正确地撤销上述步骤 - 跟踪您需要执行此操作的数量。

您可以通过帧指针访问数组的项目(如果有的话),或直接从esp获取正数偏移量。


关于你提到的其他问题 - 那些是非常普通的C的问题,任何C教程涉及的主题。

如果您在从C切换到汇编时处于死胡同,您可以让编译器激励您。
下面是the code generated by GCC对类似于您要实现(因为我已经明白它)的一个函数:

#include <stdio.h> 

void foo(int n) 
{ 
    int arr[n]; 


    for (int i = 0; i < n; i++) 
     scanf("%d", &arr[i]); 

} 

 

.LC0: 
     .string "%d" 
foo(int): 
     pushl %ebp 
     movl %esp, %ebp     ;Prologue 

     pushl %edi 
     pushl %esi 

     movl 8(%ebp), %edi    ;EDI = n 

     pushl %ebx 

     leal 4(,%edi,4), %eax   ;EAX = n*4+4 (For alignment purpose) 

     subl %eax, %esp     ;Allocate space 

     ;Pre loop condition 
     testl %edi, %edi 
     jle  .L1 

     ;Loop init 

     movl %esp, %esi     ;ESI = ptr to first element 
     xorl %ebx, %ebx     ;EBX = Counter 
.L5: 
     ;scanf("%d", &arr[i]); 
     pushl %esi 
     pushl $.LC0 
     addl $1, %ebx     ;Inc counter 
     addl $4, %esi     ;Move pointer 
     call scanf 

     ;Loop condition 
     cmpl %ebx, %edi 
     popl %eax 
     popl %edx 
     jne  .L5 
.L1: 
     leal -12(%ebp), %esp    ;Deallocate 

     popl %ebx 
     popl %esi 
     popl %edi 
     popl %ebp 
     ret 

对于这个答案的目的,我认为存在VLAs,这在C11中不是强制性的,并且不是一对一地映射到汇编程序员扩展和缩小堆栈的能力。