2012-06-08 2 views
1

레지스터 ([ar] ax)의 값을 보존해야합니다. 함수 호출 후에 수정되지만 값은 나중에 사용해야합니다. 이렇게하는 세 가지 방법 중 I 생각 (예를 들면 64 비트에있는) :스택이나 레지스터 또는 변수를 사용해야합니까?

__asm__ ("pushq %rax\n\t" 
     "call function\n\t" 
     "popq %rax"); 

2.Save 그것을 레지스터 :

__asm__ ("movq %%rax, %%some_register\n\t" 
     "call function\n\t" 
     "movq %%some_register, %%rax" 
     : : : "%some_register"); 

스택에

으로 1.Push 그 3. 변수에 저장하십시오 :

unsigned long var; 
__asm__ ("movq %%rax, %0" : "=m" (var) : :); 
function(); 
__asm__ ("movq %0, %%rax" : : "m" (var) :); 

현재 # 1을 사용하고 있습니다. 그것은 내 특별한 경우에 의도 된대로 작동하지만, 스택에 밀어 넣는 것이 Bad Thing ™ 일 수 있다는 것에 대해 걱정이됩니다. 내 관심사의 대부분은 컴파일러가 푸시되는 것에 대해 "알지 못한다"는 것입니다. 다소 제한적인 스택 프레임의 일부 공간을 소비하는 것으로 보이므로 일반적으로 문제가 발생할 수 있습니다.

레지스터에 저장하면 컴파일러가 자체 필요에 따라 컴파일러를 사용할 수 없습니다. 이것은 x86에 비해 많은 추가 레지스터가있는 x86-64에서 그리 큰 문제는 아닙니다. 하지만 x86에서 사용해야한다면 레지스터가 훨씬 제한적이기 때문에 성능이 저하 될 수 있습니다.

변수에 저장하는 것이 가장 좋은 방법 일 수 있습니다. 그리고 컴파일러는 아마도 변수를 스택에 저장하기 때문에 & & 레지스터를 할당하기조차하지 않을 수도 있습니다. 하지만 다른 사람들이 머리를 긁을 수있는 추가 변수 하나와 함께 코드가 다소 이상하게 보입니다.

그럼 궁금한 점은 어떤 솔루션이 가장 적합한 것인지, 즉 Right Thing ™이 무엇일까요? 아니면 내가 생각하지 못했던 그것을 보존하는 방법이 더 있을지도 모른다.

주 :이 함수는 변수를 취하지 않으며 아무런 문제가없는 경우 반환합니다. 레지스터의 값은 단순히 "상위 레벨"솔루션을 통해 유지 될 수 없으므로 인라인 asm; 그것은 구체적으로 도끼이어야합니다; 세 번째 솔루션을 테스트하지 않았으므로 약간 정확하지 않을 수 있습니다.

+0

이 코드를 인라인하는 프로그래밍 언어에서 로컬 변수를 만들 수없는 이유는 무엇입니까? 그런 다음 레지스터를 저장하십시오. 당신의 언어를 범위 지정하면 함수가 반환 될 때까지 var가 유지됩니다. – kingchris

+0

또 다른 가능성은 피 호출자 저장 레지스터 인 r12 - r15를 사용하는 것입니다. 일반적으로 결과 어셈블리를 확인하는 것이 좋습니다. 인라인 asm은 매우 모호한 방식으로 컴파일러 최적화를 억제 할 수 있습니다. – horsh

+0

@kingchris 그러면 해결책 # 3이 될 것입니다. 문제는 필자가 사용하는 도끼 레지스터에 구체적으로 앉아 있어야한다는 것입니다.그리고 내가 아는 인라인 asm 없이는 레지스터가 그 값을 유지하는지 확실히 믿을 수있는 방법이 없습니다. 내가 C + +로 쓸 수 없다. (그것이 내가 사용하는 것이다.) –

답변

0

해결책 2에서 레지스터가 과장되지 않는다고 생각하는 것은 특히 최적화를 통해 대담합니다. 솔루션 1의 유일한 단점은 stackframes 사이의 유일한 링크가 push [er] bp이므로 스택을 푸는 것이 불가능하다는 것입니다 (이 경우 함수 호출 스택을 디버깅해야합니다).이 경우에는 더 이상 없습니다 [sp]와 일치한다. 분명히 해결책 3을 위해 갈 것입니다. 확실히 그것은 약간의 난독 화 된 목적을위한 지역 변수를 추가하지만 적어도 ABI를 속일 수는 없습니다!

0

올바른 방법이 없으므로 asm 문 외부의 레지스터에 무언가를 안전하게 보관할 수 없습니다. asm 문 사이에 값을 전달하려면 변수에 값을 저장해야합니다. GCC는 레지스터에 변수를 저장합니다. 그렇지 않으면 저장할 수 있습니다.