2015-01-11 11 views
3

어셈블러에서 선택한 레지스터를 제공하고 인라인 어셈블리에서 해당 레지스터를 사용할 수있게하려고합니다. 나는 아래의 프로그램과 함께 일하고 있고, 그 프로그램은 잘못하고있다. 프로그램은 g++ -O1 -g2 -m64 wipe.cpp -o wipe.exe으로 컴파일되었습니다. 내가 lldb에서 충돌을 볼 때"전체 크기 레지스터"를 제공하도록 어셈블러에 요청하는 방법은 무엇입니까?

, 난 64 비트 레지스터가 아닌 32 비트 레지스터를 얻고있다 생각합니다. 내가 레지스터를 사용하여 "말을하기 위해 노력하고있어, 위

"lea (%0, %1), %2\n" 

을, 나는 ': lea를 사용하여 내가 주소를 계산하기 위해 노력하고있어 (기본 + 오프셋) 및 어셈블러 레지스터에 결과를 저장은 선택 % 2 "로 참조합니다. I는 분해를 수행 할 때

, 난 참조 :

0x100000b29: leal (%rbx,%rsi), %edi 
-> 0x100000b2c: movb $0x0, (%edi) 

그래서 64 비트 값 (RBX 및 RSI)을 사용하여 계산하여 어드레스 생성되는 코드가 나타나지만, 32 비트 레지스터에 저장 (edi) (어셈블러가 선택한). 여기

는 충돌시의 값은 다음과 같습니다

(lldb) type format add --format hex register 
(lldb) p $edi 
(unsigned int) $3 = 1063330 
(lldb) p $rbx 
(unsigned long) $4 = 4296030616 
(lldb) p $rsi 
(unsigned long) $5 = 10 

입력에 빠른 참고 아래 피연산자. invalid operand number in inline asm string을 : 나는 "r" (2)를 떨어 뜨린 경우 내가 lea에 호출 %2를 참조 할 때, 그때는 컴파일러 오류가 발생합니다.

어떻게 어셈블러 "나에게 전체 크기의 레지스터를 제공"하고 내 프로그램에서 참조 할 말할까요?

이 인라인 어셈블리 질문에 대한 죄송합니다
int main(int argc, char* argv[]) 
{ 
    string s("Hello world"); 
    cout << s << endl; 

    char* ptr = &s[0]; 
    size_t size = s.length(); 

    if(ptr && size) 
    { 
     __asm__ __volatile__ 
     (
     "%=:\n"    /* generate a unique label for TOP */ 

     "subq $1, %1\n"  /* 0-based index */ 
     "lea (%0, %1), %2\n" /* calcualte ptr[idx] */ 
     "movb $0, (%2)\n"  /* 0 -> ptr[size - 1] .. ptr[0] */ 
     "jnz %=b\n"   /* Back to TOP if non-zero */ 

     : /* no output */ 
     : "r" (ptr), "r" (size), "r" (2) 
     : "0", "1", "2", "cc" 
     ); 
    } 

    return 0; 
} 


. 나는 이것이 마지막 것이기를 바란다. 나는 GCC에서 인라인 어셈블리를 사용하는 것에 정말 흥분하지 않는다. 왜냐하면 이것 (그리고 페이딩 메모리)과 같은 고통 포인트 때문이다. 그러나 내가 아는 그것 유일한 법적 방법은 내가 C로 규정 volatile의 GCC의 해석을 부여하고 싶은 일을하는

관심을하면, GCC는 hardware backed memory로 C의 volatile 규정을 해석하고, 다른 아무것도 남용이다 그것은 불법 프로그램을 초래합니다. 그래서 다음은 GCC에 대한 법적되지 않습니다 : - 즉, 어떤 메모리를 변경할 수 있습니다뿐만 아니라 메모리 매핑 된 하드웨어 흥미롭게

volatile void* g_tame_the_optimizer = NULL; 
... 

unsigned char* ptr = ... 
size_t size = ...; 

for(size_t i = 0; i < size; i++) 
    ptr[i] = 0x00; 

g_tame_the_optimizer = ptr; 

, 마이크로 소프트는 volatile (대부분의 프로그래머가 기대하는 것보다 관습적인 해석을 사용) 위의 코드는 허용됩니다.

답변

4

GCC 인라인 ASM은 복잡한 짐승이다. "r" (2)int 크기의 레지스터를 할당하고 값을 2으로로드하는 것을 의미합니다. 임의의 스크래치 레지스터가 필요한 경우 출력 섹션에 "=&r" (dummy)과 같이 앞부분에 선언 된 void *dummy과 같이 64 비트 조기 - 복제기 더미 출력을 선언 할 수 있습니다. 자세한 내용은 gcc manual을 참조하십시오.

링크 된 이메일에서 말한 것처럼 마지막 코드 스 니펫은 메모리 장벽을 원하는 것처럼 보입니다. manual for example을 참조하십시오.

+0

다시 한번 감사드립니다. @Jester. 그래서 나는 명확합니다 : GCC에 내게 그것을 선택하고 내 프로그램에서 사용하는 전체 크기의 레지스터를달라고 요청할 방법이 없습니까? (그렇다면이 질문은 두 번째로 잘못된 질문입니다. 스택 오버플로가 너무 좋지 않아 광범위한 "How do I .."질문을 허용하지 않고 대신 여러 개의 빈약 한 결과가 나오는 토끼 구멍으로 가야합니다. 질문). – jww

+0

내 대답은 첫 번째 단락에서 그렇게하는 방법을 보여줍니다. – Jester

+1

고정 레지스터를 사용할 수는 있지만 필자가 예제를 사용하지 않고 컴파일러에서 제공 할 수있는 방법을 알지 못합니다. 그러나 정말로 정말로 메모리 장벽을 사용해야합니다. – Jester