2014-05-22 4 views
3

저는 CodeProject here에있는 기사를 읽음으로써 C와 GCC에서 AT & T 스타일 인라인 어셈블리를 소량 사용하려고합니다. 이 작업을 수행하려는 주된 이유는 내 코드에서 신뢰할 수있는 명령어 주소를 가질 수 있도록 EIP 레지스터의 기존 값을 찾는 것입니다. 나는 지금까지이 개념에 대한 이해를 보여주기 위해 간단한 예제 프로그램을 작성했습니다 :C에서 함수의 반송 주소를 찾는 방법은 무엇입니까?

#include <stdio.h> 
#include <stdlib.h> 

int mainReturnAddress = 0; 

int main() 
{ 
    asm volatile (
     "popl %%eax;" 
     "pushl %%eax;" 
     "movl %%eax, %0;" 
     : "=r" (mainReturnAddress) 
     ); 

    printf("Address : %d\n", mainReturnAddress); 
    return 0; 
} 

이 특정 예제의 목적은에서 저장된 32 비트 리턴 어드레스를 나타내는 스택의 상단에서 4 바이트를 팝업하는 것입니다 EIP 레지스터에 넣고 스택에 다시 밀어 넣습니다. 그 다음, 나는 그것을 글로벌 변수 mainReturnAddress 변수에 저장한다. 마지막으로 mainReturnAddress에 저장된 값을 인쇄합니다.

이 코드의 출력은 4200560입니다.

이 코드는 앞서 언급 한 목적을 달성합니까? 이것이 Windows 플랫폼 32 비트의 교차 프로세서입니까?

+1

무엇이 스택에 있는지는 구현에 따라 다릅니다. 로컬 스택 변수를 가지고 있다면, 스택 상에도 존재할 것이므로, 스택의 최상위를 터뜨려도 원하는 것을 얻을 수 있다고 보장 할 수는 없습니다. 그런데 왜 귀국 주소가 필요한가요? 만약 당신이 어떤 명령의 "신뢰할 수있는"주소를 얻길 원한다면'int mainAddress = (int) main;'그냥'main' 자체의 주소를 얻을 수 있습니다. 어떤 사람들은'(int) & main'을하고 싶지만 그렇게 할 필요는 없습니다. –

+4

Mark와 Carl이 만든 좋은 점 이외에,이 asm은 gcc에게 그렇게하지 않고 eax를 수정합니다. 이것은 매우 이상한 버그를 소개하는 좋은 방법입니다. 더 나은 해결책은 pushl/popl %% eax를 % 0을 사용하도록 변경하고 movl을 제거하는 것입니다. 아, 64 비트를 지원하려고한다면 포인터를 int로 취급하는 것은 나쁜 생각입니다. 어쨌든 나쁜 습관. –

답변

5

GCC의 경우 인라인 어셈블리를 사용하지 말고 __builtin_return_address을 사용해야합니다.

+0

Visual C++는 비슷한 내장 함수 인'_ReturnAddress()'를 가지고 있습니다. –

+0

http://intackoverflow.com/questions/23838410/interrupts-instruction-pointer-and-instruction-queue-in-8086 – GLES

관련 문제