如何在堆栈上创建大小为 x 的数组并将 scanf 值放入其中
How can you create an array of size x on stack and scanf values into it
假设整数数组的大小存储在eax中。我想你可以像这样为数组分配内存:
subl (%eax), %esp
但是,eax 中的大小由用户提供,每次执行程序时大小都会不同。鉴于此,如何使用用户通过 scanf 提供的整数初始化每个 4 字节内存地址?我们如何确保如果提供的整数多于数组的大小,我们不会覆盖任何内存?
subl (%eax), %esp
读取eax
.
的值表示的地址的内容
在这种情况下,这很可能是您不想做的事情。
如果 eax
是数组的字节大小,那么 subl %eax, %esp
将为它分配足够的内存。
如果 eax
是数组的 32 位整数的个数,那么 leal (,%eax,4), %esp
就是正确的指令。
None 上面的指令说明了堆栈的对齐方式。
为了从您的程序中正确 return 您必须能够正确撤消上述步骤 - 跟踪执行此操作所需的数量。
您可以通过帧指针(如果有)或直接作为 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 , %ebx ;Inc counter
addl , %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 中不是强制性的,并且没有真正映射 one-to-one 到汇编程序员成长和发展的能力缩小堆栈。
假设整数数组的大小存储在eax中。我想你可以像这样为数组分配内存:
subl (%eax), %esp
但是,eax 中的大小由用户提供,每次执行程序时大小都会不同。鉴于此,如何使用用户通过 scanf 提供的整数初始化每个 4 字节内存地址?我们如何确保如果提供的整数多于数组的大小,我们不会覆盖任何内存?
subl (%eax), %esp
读取eax
.
的值表示的地址的内容
在这种情况下,这很可能是您不想做的事情。
如果 eax
是数组的字节大小,那么 subl %eax, %esp
将为它分配足够的内存。
如果 eax
是数组的 32 位整数的个数,那么 leal (,%eax,4), %esp
就是正确的指令。
None 上面的指令说明了堆栈的对齐方式。
为了从您的程序中正确 return 您必须能够正确撤消上述步骤 - 跟踪执行此操作所需的数量。
您可以通过帧指针(如果有)或直接作为 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 , %ebx ;Inc counter
addl , %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 中不是强制性的,并且没有真正映射 one-to-one 到汇编程序员成长和发展的能力缩小堆栈。