2013-10-15 3 views
5

임시로 실험을 위해 자체 스택을 사용하는 코드를 작성하고 있습니다. 이것은 리터럴 인라인 어셈블리를 사용할 때 효과적입니다. 변수 위치를 ebp의 오프셋으로 하드 코딩했습니다. 그러나, 나는 내 코드가 메모리 주소를 하드 코드하지 않고 작업하기를 원했기 때문에 GCC의 확장 된 인라인 어셈블리를 살펴 보았다. 이것의

volatile intptr_t new_stack_ptr = (intptr_t) MY_STACK_POINTER; 
volatile intptr_t old_stack_ptr = 0; 
asm __volatile__("movl %%esp, %0\n\t" 
     "movl %1, %%esp" 
     : "=r"(old_stack_ptr) /* output */ 
     : "r"(new_stack_ptr) /* input */ 
     ); 

점 먼저 변수 old_stack_ptr에 스택 포인터를 저장하는 것입니다 : 내가 가지고있는 것은 다음과 같다. 다음으로 스택 포인터 (% esp)는 new_stack_ptr에 저장 한 주소로 덮어 씁니다.

그래도 나는 GCC가 % esp를 old_stack_ptr에 저장하고 있지만 % esp를 new_stack_ptr로 바꾸지 않는 것을 발견했다. 나는 그것을 명시 적으로 선언하지 않기 때문에,

mov -0x14(%ebp),%eax 
mov %esp,%eax 
mov %eax,%esp 
mov %eax,-0x18(%ebp) 

내가 GCC는 ESP는 %를 유지하기 위해 노력하고있다 생각 : 깊은 검사 후, 나는 실제로 내 어셈블리를 확장하고 다음과 같다 그 자체 지침을 추가 발견 "출력"피연산자 ... 나는 완전히 이것에 틀릴 수 있었다 ...

나는 그것을하기 위하여 진짜로 확장 인라인 집합을 사용하고 싶었다, 왜냐하면 그렇지 않으면, 나가 "단단한 부호"위치 어셈블리에 % ebp를 오프셋하고, 다음과 같은 변수 이름을 사용하고 싶습니다 ... 특히이 코드는 여러 변수에서 다르게 오프셋 된 것처럼 보이는 여러 시스템에서 작동해야하기 때문에 확장 된 인라인 어셈블리를 사용합니다 내가 명시 적으로 허용 y는 변수 위치를 말하지만 ... 왜 여분의 물건을하고 내가 전에 확장 된 어셈블리를 사용하여 시작한 이후로 스택 포인터를 덮어 쓰지 못하게 이해가 안 돼,이 일을하고있다.

나는 어떤 도움을 주셔서 감사합니다 !!!

+0

이것이 도움이 될지 모르지만'-fomit-frame-pointer' ('-O1' 이상으로 활성화 됨)는'% ebp'에 대해 걱정할 필요를 없애줍니다. – DaoWen

+0

디버그 (최적화 없음) 빌드를하고 있으며 GCC가 잠재적 인 오류를 잡기 위해 기본적으로 수행하기 때문에 여분의 것들이있을 것입니다. GCC가 제공하는 옵션을 보려면 "GCC Stack Frame Checks"를 검색하십시오. – Skizz

답변

8

문제는 gcc가 입출력을 동일한 레지스터 eax에 할당하는 것입니다. 입력을 사용하기 전에 출력을 clobbering하고 있다고 gcc에게 알리고 싶다. "초창기".

asm __volatile__("movl %%esp, %0\n\t" 
     "movl %1, %%esp" 
     : "=&r"(old_stack_ptr) /* output */ 
     : "r"(new_stack_ptr) /* input */ 
     ); 

출력에는 & 기호가 표시되어 있습니다. 이렇게하면 코드가 수정됩니다.

업데이트는 : 양자 택일로, 당신과 같이, 같은 레지스터를하고 xchg를 사용하여 입력과 출력을 강제로 수 :

asm __volatile__("xchg %%esp, %0\n\t" 
     : "=r"(old_stack_ptr) /* output */ 
     : "0"(new_stack_ptr) /* input */ 
     ); 

공지 사항 는 인수와 같은 레지스터에이를 넣어 "라는 "0" 0 ".

+0

soooo 많은 감사합니다! 전에는 일찍부터 들어 본 적이 없었습니다. 우수 답변. 정말 감사. 그것은 그것을 고쳤다. – Chad

+1

나는 택일 적으로'xchg'를 사용하고 입력과 출력을 같은 레지스터에 넣을 수 있다고 가정한다. – Jester