2017-01-30 8 views
0

정수 배열의 크기가 eax에 저장되어 있다고 가정합니다. 나는 당신이 당신과 같이 배열을위한 메모리를 할당 할 수 있습니다 가정 :stack 및 scanf 값에 크기 x의 배열을 어떻게 만들 수 있습니까?

subl (%eax), %esp 

그러나, EAX의 크기는 사용자가 제공되며, 각 프로그램 실행과 다른 크기 일 것이다. 이 점을 감안할 때 scanf를 사용하여 사용자가 제공 한 정수로 각 4 바이트 메모리 주소를 초기화 할 수 있습니까? 배열의 크기보다 많은 정수가 제공되면 메모리를 덮어 쓰지 않도록 어떻게 보장 할 수 있습니까?

답변

2

subl (%eax), %espeax의 값으로 표시된 주소의 내용을 읽습니다.
이것은이 컨텍스트에서 원하지 않는 무언가입니다.

eax이 배열의 크기 (바이트)이면 subl %eax, %esp은 충분한 메모리를 할당합니다.
eax이 배열의 32 비트 정수의 수이면 leal (,%eax,4), %esp이 올바른 명령어입니다.

위 지침 중 스택 정렬에 대한 설명이 없습니다.
절차에서 올바르게 반환하려면 위의 단계를 올바르게 실행 취소 할 수 있어야합니다. 수행해야 할 수량을 추적하십시오.

프레임 포인터가있는 경우 배열의 항목에 액세스하거나 직접 esp의 양수 오프셋으로 배열의 항목에 액세스 할 수 있습니다.


기타 질문 - 해당 질문은 정말 일반적인 C 질문입니다. C 자습서에서는 이러한 주제를 다룹니다.

C에서 어셈블리로 전환 할 때 막 다른 길을 가고 있다면 컴파일러에서 영감을 얻도록 할 수 있습니다. 내가 가정 한이 답변의 목적

#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 

:
아래는 (내가 이해 한대로) 구현하려는 하나의 유사 기능에 대한 the code generated by GCC입니다 VLAs의 존재는 C11에서는 필수 사항이 아니며 스택을 확장하고 축소하는 데 어셈블리 프로그래머가 실제로 일대 일로 매핑하지 않습니다.