2013-07-07 9 views
12

함수 호출이 프로그램에 의해 만들어지면 호출 된 함수는 호출자에게 반환하는 방법을 알아야한다는 것을 알게되었습니다.호출 된 후 호출 된 함수는 호출 된 함수로 어떻게 복귀합니까?

제 질문은 : 호출 된 함수가 호출자에게 어떻게 복귀하는지 어떻게 알 수 있습니까? 컴파일러를 통해 뒤에서 작동하는 메커니즘이 있습니까?

+1

당신은 [this] (http://en.wikipedia.org/wiki/Call_stack#Structure)를 읽어야합니다. 이것은 매우 좋은 답변입니다 : [Chapter 11 - Procedures] (http : //pages.cs.wisc. edu/~ smoler/x86text/lect.notes/procedures.html) 그리고 비디오 : [해커들을위한 어셈블리 입문 (파트 11) 함수 스택] (http://www.progamercity.net/code-tut/168- assembly-language-primer-hackers-video-series.html)에서 모든 비디오를 좋아할 것입니다. –

답변

12

컴파일러는 사용자가 타겟팅하는 ABI의 일부로 정의 된 특정 "호출 규칙"을 따릅니다. 해당 전화 협약에는 시스템이 반환 할 주소를 알 수있는 방법이 포함됩니다. 호출 규칙은 일반적으로 프로 시저 호출에 대한 하드웨어의 지원을 이용합니다.

... 프로세서합니다 (CALL 명령어 다음 명령어의 오프셋을 포함)을 EIP 레지스터의 값을 푸시 인텔에서, 예를 들면, 리턴 어드레스가 스택으로 푸시 (나중에 복귀 명령 포인터로 사용하기 위해).

은 ... 상기 프로세서는 상기 EIP 레지스터 스택의 꼭대기로부터의 복귀 명령 포인터 (오프셋)를 나타나고 시작 : 함수에서 복귀

ret 명령을 통해 수행 새로운 명령 포인터에서 프로그램 실행. lr (

BLBLX 설명은 다음 명령의 주소를 복사 :

는 콘트라스트, ARM에 리턴 어드레스는 링크 레지스터에 넣어 r14, 링크 레지스터).

반환은 일반적으로 movs pc, lr을 실행하여 링크 레지스터의 주소를 프로그램 카운터 레지스터에 다시 복사함으로써 수행됩니다.

참고 :이 (특히 인텔과 같은 시스템) 스택에 의해 가능하게된다

  1. Intel Software Developers Manual
  2. ARM Information Center
4

. 예를 들어 로컬로 유지하는 int을 포함하는 caller 메서드가 있다고 가정 해 보겠습니다.

caller(target( 인 경우 int를 저장해야합니다. 이 주소는 호출이 이루어진 주소와 함께 스택에 배치됩니다. target(은 논리를 수행하고 자체 로컬 변수를 만들고 다른 메소드를 호출 할 수 있습니다. 로컬 변수는 호출 주소와 함께 스택에 배치됩니다.

target(이 끝나면 스택은 "펼쳐집니다".target(의 로컬 변수를 포함하는 스택 맨이 제거됩니다.

메서드가 너무 많이 반복 될 경우 스택이 너무 커질 수 있으며 "스택 오버플로"가 발생할 수 있습니다.

8
  1. 컴파일러는 함수를 호출하는 방법과 호출 규칙을 알고 있습니다. 예를 들어 C에서는 함수에 대한 인수가 스택에 푸시됩니다. 호출자는 스택 지우기를 담당하므로 호출 된 함수는 인수를 제거 할 필요가 없습니다. 다른 호출 규칙은 인수를 스택에 푸시하는 것을 포함 할 수 있으며 호출 된 함수는 인수를 정리해야합니다. 이 경우, 생성 된 코드는 함수가 리턴하기 전에 스택을 정정합니다. 오히려 호출 규칙은 레지스터에 인수를 전달할 수 있으므로 호출 된 함수도 신경 쓸 필요가 없습니다.

  2. CPU에는 서브 루틴을 호출하는 메커니즘이 있습니다. 그러면 현재 실행 주소가 스택에 저장되고 처리가 새 주소로 전송됩니다. 함수가 완료되면 return 문을 실행하여 호출자 주소를 가져오고 거기에서 실행을 다시 시작합니다.

스택이 제대로 정리되지 않았거나 메모리를 덮어 쓰지 않아서 반송 주소가 손상된 경우 정의되지 않은 동작이 발생합니다. 물론 정확한 구현 세부 사항은 사용되는 플랫폼에 따라 다릅니다.

4

피 호출자와 호출자가 협력해야합니다.

호출자는 호출 수신자가 수신자에게 반환해야하는 주소를 알려주는 데 동의합니다 (일반적으로 호출자를 스택에 올려 놓거나 레지스터에 전달 함). 호출 수신자는 호출이 완료되면 해당 주소로 돌아 오는 것에 동의합니다 실행 중.