2011-08-21 4 views
5

Linux에서 인라인 어셈블러에 대한 몇 가지 사항을 이해하려고합니다. 값 대신 VAR 값을 등록 EAX에ASM 인라인 의심

.globl test_func 
.type test_func, @function 
test_func: 
     pushl %ebp 
     movl %esp, %ebp 
#APP 
# 336 "opers.c" 1 
     addl 8(%ebp), %eax 
# 0 "" 2 
#NO_APP 
     popl %ebp 
     ret 
     .size test_func, .-test_func 

그것은 요약 var에 MEM 주소 :

void test_func(Word32 *var){ 
    asm(" addl %0, %%eax" : : "m"(var)); 
    return; 
} 

것은 그것은 어셈블러 코드 다음 생성 : 나는 다음과 같은 기능을 사용하고 있습니다.

var mem 주소 대신 var mem 주소를 레지스터에 복사하지 않고 addl 명령에 var value를 사용하도록 지시 할 수 있습니까?

감사합니다.

+0

당신의 인라인 어셈블리는 EAX에 있어야하는데 무엇을 정의하지 않습니다 시도? – servn

답변

3

var 값 대신에 var mem 주소와 eax 레지스터 값의 합계입니다.

예. gcc 인라인 어셈블리의 구문은 매우 정교합니다. GCC Inline Assembly HOWTO"m"에있는 관련 섹션에서 바꾸어 말하면 대략 C 변수의 메모리 위치를 알 수 있습니다.

쓰기 또는 쓰기가 가능한 주소를 원할 때 사용합니다. 알림 C 변수의 위치를 ​​알려 주었으므로 이 Word32 *var의 주소로 설정되어 있습니다. 포인터에 대한 포인터가 있습니다. "m" 제약 조건이 암시 적으로 C 변수의 주소를 가져와 주소 표현식을 제공한다고 말할 수 있으므로 인라인 어셈블리 블록의 C 변환은 에 추가되므로 EAX += *(&var)처럼 보일 수 있습니다.

var mem 주소 대신 var mem address를 레지스터에 복사하지 않고 addl 명령을 사용하여 알 수있는 방법이 있습니까?

귀하의 의미에 따라 다릅니다. 당신은 누군가가 역 참조 메모리가 있도록 (@Bo Perssons 대답을 참조)하지만, @fazo 제안대로 (

제약이 "m"(*var) 할 필요가 인라인 어셈블리에서 그것을 할 필요가 없습니다, 스택에서 var를 얻을 필요). 그러면 메모리 위치가 가리키는 메모리 위치가 아닌 var이을 가리키는 값의 메모리 위치 이됩니다.

생성 된 코드

는 지금 :

약간의 의심을하지만, 당신은 사방이 GCC에게 잊었으로 그 이해할 수
test_func: 
    pushl %ebp 
    movl %esp, %ebp 
    movl 8(%ebp), %eax 
#APP 
# 2 "test.c" 1 
    addl (%eax), %eax 
# 0 "" 2 
#NO_APP 
    popl %ebp 
    ret 

%eax를 (입력/출력 목록에없이 수정). asm("addl %0, %%eax" : : "m"(*var) : "%eax")가 생성하는 고정되지 않은 : 더 나은 이상 올바른 경우이지만, 항상 기억하는 것이 좋습니다

movl 8(%ebp), %edx 
    addl (%edx), %eax 

합니다. clobber list 섹션을 참조하고 인라인 조립품의 고급 사용법에 대해서는 "memory" 파쇄기에 특히주의하십시오.

메모리 주소를 레지스터에로드하고 싶지는 않지만 간단히 설명하겠습니다. "r""m"에서 제약 조건을 변경하면 거의 관련 부분이 변경됩니다 작동하는 것 같다 (우리는 소지품 목록에 %eax 포함하는 경우) :

거의 정확
movl 8(%ebp), %edx 
    addl %edx, %eax 

, 우리는 포인터 값 var에 넣은를 레지스터이지만, 이제는 메모리에서로드한다는 것을 명시해야합니다. 제약 조건과 일치하는 코드를 변경 (일반적으로 바람직하지 않은, 난 단지 완성도를 보여주는거야)

asm("addl (%0), %%eax" : : "r"(var) : "%eax"); 

가 제공합니다 :

movl 8(%ebp), %edx 
addl (%edx), %eax 

"m"와 동일합니다.

3

네, 왜냐하면 그에게 주소가 var이기 때문입니다. 그에게 * var.

좋아 :

void test_func(Word32 *var){ 
    asm(" addl %0, %%eax" : : "m"(*var)); 
    return; 
} 

내가 정확히 기억하지 않는다, 그러나 당신은 "R"과 "M"을 교체해야합니까?

메모리 피연산자는 해당 주소에서 가치가 있다는 것을 의미합니다. 포인터 일뿐입니다.

+0

var 값을 얻기 위해 % eax 값을 var address로 덮어 씁니다. – LooPer

1

아니요, 2 단계 간접적 인 x86 프로세서의 주소 지정 모드는 없습니다.

먼저 메모리 주소에서 포인터를로드 한 다음 포인터에서 간접적으로로드해야합니다.

0

는 GCC가 아무것도 넣을 수 있도록 ... 당신이 실제로 일을하려고하는,

void test_func(Word32 *var){ 
    asm(" mov %0, %%edx; \ 
    addl (%%edx), %%eax" : : "m"(var));  

    return; 
}