C / C ++에서 함수 호출의 스택 프레임을 이해하고 있습니까?


19

스택 프레임이 어떻게 작성되고 어떤 변수 (매개 변수)가 어떤 순서로 쌓 이도록 푸시되는지 이해하려고합니까? 일부 검색 결과에 따르면 C / C ++ 컴파일러는 함수 내에서 수행 된 작업을 기반으로 결정합니다. 예를 들어, 함수가 전달 된 int 값을 1 (++ 연산자와 유사)만큼 증가시키고 리턴하면 함수의 모든 매개 변수와 로컬 변수를 레지스터에 넣습니다.

반환하거나 값 매개 변수로 전달하는 데 사용되는 레지스터가 궁금합니다. 참조는 어떻게 반환됩니까? 컴파일러는 eax, ebx, ecx 및 edx 중에서 어떻게 선택합니까?

함수 호출 중에 레지스터, 스택 및 힙 참조가 사용, 빌드 및 소멸되는 방법을 이해하려면 무엇을 알아야합니까?


이것은 읽기 어렵습니다 (텍스트의 벽). 게시물을 더 나은 형태로 편집 하시겠습니까 ?
gnat

1
이 질문은 나에게 광범위하게 보인다. 또한 이것은 플랫폼에 따라 다르지 않습니까?
Kazark


답변:


11

Dirk가 말한 것 외에도 스택 프레임의 중요한 용도는 함수 호출 후에 복원 할 수 있도록 레지스터의 이전 값을 저장하는 것입니다. 따라서 레지스터를 사용하여 매개 변수를 전달하고 값을 리턴하며 리턴 주소를 저장하는 프로세서에서도 해당 레지스터의 값은 함수 호출 전에 스택에 저장되므로 호출 후에 복원 할 수 있습니다. 이것은 하나의 함수가 자신의 매개 변수를 덮어 쓰거나 자신의 리턴 주소를 잊지 않고 다른 함수를 호출 할 수있게합니다.

따라서 일반적인 "일반"시스템에서 함수 A에서 함수 B를 호출하면 다음 단계가 필요할 수 있습니다.

  • 기능 A :
    • 반환 값에 대한 공간을 밀어
    • 푸시 파라미터
    • 반송 주소를 푸시
  • 기능 B로 이동
  • 기능 B :
    • 이전 스택 프레임의 주소를 푸시
    • 이 함수가 사용하는 레지스터 값을 푸시합니다 (따라서 복원 가능)
    • 지역 변수를위한 푸시 공간
    • 필요한 계산을 수행
    • 레지스터를 복원
    • 이전 스택 프레임을 복원
    • 기능 결과 저장
    • 반송 주소로 이동
  • 기능 A :
    • 매개 변수를 팝
    • 반환 값을 팝

이것은 함수 호출이 작동 할 수있는 유일한 방법은 아니며 (1 ~ 2 단계의 순서가 틀릴 수도 있음) 스택이 프로세서가 중첩 된 함수 호출을 처리하도록하는 방법에 대한 아이디어를 제공해야합니다.


여기서 "푸시"는 정확히 무엇을 의미합니까? 무엇을 만들어야할지 모르겠습니다.
Tomáš Zato-복원 모니카

2
@ TomášZato pushpop스택의 두 가지 기본 작업입니다. 스택은 책 스택과 같은 FIRST (first-in-first-out) 구조입니다. 때 당신이 push, 당신은 스택의 상단에 새로운 객체를 옮기고; pop스택 맨 위에서 물체를 가져갈 때 중간에 객체를 삽입하거나 제거 할 수 없으며 스택 맨 위에서 만 작업 할 수 있습니다. 일반적으로 스택 및 특히 위키 백과에서 스택 에 대한 자세한 내용을 읽을 수 있습니다 .
Caleb

11

사용중인 호출 규칙에 따라 다릅니다. 그러나 호출 규칙을 정의한 사람은 원하는대로이 결정을 내릴 수 있습니다.

x86에서 가장 일반적인 호출 규칙에서 레지스터는 매개 변수를 전달하는 데 사용되지 않습니다. 매개 변수는 가장 오른쪽 매개 변수부터 시작하여 스택으로 푸시됩니다. 리턴 값은 eax에 위치하며 추가 공간이 필요한 경우 edx를 사용할 수 있습니다. 참조와 포인터는 모두 eax의 주소 형식으로 반환됩니다.


5

스택을 잘 이해하면 프로그램에서 메모리가 작동하는 방식을 이해하고 프로그램에서 메모리가 작동하는 방식을 이해하면 프로그램에서 함수가 저장되는 방식을 이해하고 프로그램에서 함수가 저장되는 방식을 이해하면 재귀 함수가 작동하는 방식을 이해할 수 있습니다. 재귀 함수의 작동 방식을 이해하면 컴파일러의 작동 방식을 이해하고 컴파일러의 작동 방식을 이해하면 마음이 컴파일러로 작동하며 프로그램을 매우 쉽게 디버깅합니다.

스택 작동 방식을 설명하겠습니다.

먼저 함수가 어떻게 스택에 저장되는지 알아야합니다.

힙 저장소 동적 메모리 할당 값 스택 저장소 자동 할당 및 삭제 값

여기에 이미지 설명을 입력하십시오

예를 들어 이해합시다.

def hello(x):
    if x==1:
        return "op"
    else:
        u=1
        e=12
        s=hello(x-1)
        e+=1
        print(s)
        print(x)
        u+=1
    return e

hello(4)

이제이 프로그램의 일부를 이해하십시오.

여기에 이미지 설명을 입력하십시오

이제 스택이 무엇이고 스택 부분이 무엇인지 살펴 보겠습니다.

여기에 이미지 설명을 입력하십시오

스택 할당 :

모든 로컬 변수를로드했거나 스택에서 즉시 반환되는 모든 것이 스택 프레임에 반환 되더라도 함수가 "반환"되는 경우 한 가지만 기억하십시오. 그것은 재귀 함수가 기본 조건을 얻고 기본 조건 이후에 리턴을 놓을 때 기본 조건이 프로그램의 "else"부분에 위치한 로컬 변수를로드하기를 기다리지 않고 스택에서 현재 프레임을 즉시 반환하고 하나의 프레임이면 다음 프레임 리턴은 활성화 레코드에 있습니다. 실용적으로 이것을보십시오 :

여기에 이미지 설명을 입력하십시오

블록의 할당 해제 :

따라서 함수가 return 문을 찾을 때마다 스택에서 현재 프레임을 삭제합니다.

스택 값에서 반환하는 동안 스택에 할당 된 순서의 역순으로 반환됩니다.

여기에 이미지 설명을 입력하십시오

이것들은 매우 짧은 설명이며 스택 및 이중 재귀에 대해 더 깊이 알고 싶다면이 블로그의 두 게시물을 읽으십시오.

단계별 스택에 대한 추가 정보

스택과 함께 단계별 재귀에 대한 자세한 내용


3

당신이 찾고있는 것은 Application Binary Interface -ABI입니다.

ABI를 설명하는 각 컴파일러에 대한 사양이 있습니다.

각 플랫폼은 일반적으로 컴파일러 간의 상호 운용성을 지원하기 위해 ABI를 지정합니다. 예를 들어, x86 호출 규칙은 x86 및 x86-64에 대한 일반적인 호출 규칙을 설명합니다. 그러나 Wikipedia보다 공식적인 문서가 필요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.