2010-12-27 3 views
5

는 GNU 프로젝트의 일부 소스 코드를 읽는 동안, 나는 인라인 어셈블리의이 비트를 건너 왔어요 : 여기도움말 이해 DIV 명령이

__asm__ (
    "divq %4" 
    : "=a" (q), "=d" (r) 
    : "0" (n0), "1" (n1), "rm" (d) 
); 

변수 q, r, n0, n1하고, d은 64 비트 정수입니다. 나는이 일의 요지를 잡을 수있는 충분한 모임을 알고 있지만, 확실하지 않은 몇 가지 세부 사항이 있습니다.

는 이해가 무엇 : 우리는 d하여 RAX 레지스터의 내용을 나누어 q의 몫을 배치하고, r에 나머지를 배치하고

. 내가 왜 입력이 여기에있다

  1. 을 이해하지 못하는 어떤

    ? 우리는 단지 배당과 제수를 입력하면되기 때문에, 3 입력에 대해 을 사용할 수 있습니까?

  2. 어떤 입력이 배당인지 알 수 없습니다. 더 일반적으로, 나는 실제로 아무 것도 보지 못합니다. RAX 레지스터에로드됩니다. 그래서 어떻게 분할해야 하는지를 어떻게 알 수 있습니까?
+1

+1 형식이 잘 지정된 질문입니다. 나는 "이해하는 것"과 "이해할 수없는 것"섹션을 좋아합니다. –

답변

4

:

: "0" (n0), "1" (n1), "rm" (d) 

레지스터 "0"과 "1"로 인해 출력 사양 rax에 강제 rdx된다

: "=a" (q), "=d" (r) 

그리고 div 지시 가족 싶어 분자는 RDX:RAX입니다. 제수는 범용 레지스터 (그렇지 않으면 사용되지 않습니다. 즉, RAX 또는 RDX이 아님) 또는 "rm"제약 조건에 의해 지정된 메모리에있을 수 있습니다. 레지스터 RDX, RAX 및 제수 피연산자가 3 개의 입력을 구성합니다.

이렇게하면 n1:n0/d이됩니다. 여기서 n1:n0rdx:rax에로드 된 수량입니다.

+0

이것을 정확히 사용하면 128 비트 정수를 64 비트 정수로 나눌 수 있습니다. 나는 이것이 32 비트 레지스터 버전에서 가능하다는 것을 알았지 만 64 비트 버전에서도 그렇게 생각하지는 못했다. –

+1

@Jens : 맞습니다.그러나 몫이'rax' 목적지 레지스터에 비해 너무 커지면 (작은 피연산자 나눗셈 연산과 같이) 나누기 예외가 생깁니다. –

+1

이 경우를 테스트하는 가장 빠른 방법은'rdx'가 제수보다 작은 지 확인하는 것입니다.이 경우 나누기가 안전합니다. –

0

올바르게 div 가족이 고정 레지스터 ad, raxdivq에 대한 rdx에서 작동 관찰. a 레지스터는 입력을 n0에서 가져오고,이 레지스터는 0 번째 레지스터에 앨리어싱되어 있습니다 (즉, a). n1d으로 앨리어싱 된 더미 입력입니다. 아마도이 레지스터가 다른 용도로 사용되지 않도록하기 위해서입니다. 입력 피연산자 사양