2010-06-11 4 views
1

다음 함수는이 페이지 안에있는 주소의 페이지의 기본 주소를 가져 오는 데 사용됩니다 :얻을 수있는 페이지의 기본 주소

void* GetPageAddress(void* pAddress) 
{ 
    return (void*)((ULONG_PTR)pAddress & ~(PAGE_SIZE - 1)); 
} 

하지만를 그것을 얻지 못했습니다. 여기에서 어떤 트릭이 나옵니까?

결론 :
개인적으로 Amardeep의 설명과 Alex B의 예가 가장 좋은 대답이라고 생각합니다. Alex B의 답변이 이미 투표 된대로, Amardeep의 대답을 공식적인 답변으로 받아들이고 싶습니다! 다 감사합니다.

답변

6

페이지 크기로 생성 된 마스크에 맞는 주소의 비트를 지 웁니다. 효과적으로 블록의 첫 번째 유효한 주소를 가져옵니다.

PAGE_SIZE는 2의 거듭 제곱이어야하며 주소에 설정된 단일 비트로 표시됩니다.

마스크는 PAGE_SIZE에서 1을 뺀 값으로 생성됩니다. 이는 효과적으로 페이지 크기 비트보다 낮은 모든 비트를 설정합니다. 그런 다음 ~은 모든 비트를 0으로 보완하고 마스크보다 높은 순서 인 모든 비트를 설정합니다. 그러면 &은 효과적으로 모든 하위 비트를 제거하고 원래 주소를 포함하는 페이지의 실제 기본 주소를 남겨 둡니다.

+0

"~은 모든 비트를 0으로 보완하고 마스크보다 높은 모든 비트를 설정합니다."---- 왼쪽 핸들 피연산자의 크기와 일치시겠습니까? –

+0

~는 피연산자와 동일한 크기를 반환합니다. 이 경우 PAGE_SIZE가 리터럴 숫자로 정의 된 매크로 일 경우 대상 플랫폼에있는 'int'가 기본 값으로 설정됩니다 (32 비트). 코드 예제는 64 비트 시스템에서는 작동하지 않습니다.리턴 (void *) ((ULONG_PTR) pAddress & ~ (void *) (PAGE_SIZE - 1)); –

4

PAGE_SIZE가 2의 거듭 제곱 (예 : 4096) 일 때 페이지를 지정하는 비트보다 낮은 비트가 모두 지워집니다.

+0

네, PAGE_SIZE는 2의 제곱이어야합니다. 그렇지 않으면 결과가 잘못되었습니다. 그렇다면 왜 ~ (PAGE_SIZE-1)일까요? PAGE_SIZE 만 사용할 수 있다고 생각합니다. –

+2

@Dbger : PAGE_SIZE, 2의 거듭 제곱이 표시되면 단일 비트로. 올바른 크기의 마스크를 만들려면 그보다 낮은 순서로 설정된 모든 비트가 필요합니다. –

+0

PAGE_SIZE가 2의 거듭 제곱 인 경우이를 보완하면 0 비트가 하나만있는 마스크가 제공되므로 도움이되지 않습니다. – TMN

14

이 함수는 지정된 주소의 하위 비트를 지우고 해당 주소를 생성합니다. 예를 들어

, PAGE_SIZE가 4096 인 경우, 32 비트 이진수로 : 만약 비트-하고 32 비트 주소와,이 제로에 하위 비트를 설정한다면, 는 반올림

PAGE_SIZE  = 00000000000000000001000000000000b 
    PAGE_SIZE - 1 = 00000000000000000000111111111111b 
~(PAGE_SIZE - 1) = 11111111111111111111000000000000b 

가장 가까운 4096 바이트 페이지 주소로 주소 지정.

~(PAGE_SIZE - 1)    = 11111111111111111111000000000000b 
        pAddress = 11010010100101110110110100100100b 
~(PAGE_SIZE - 1) & pAddress = 11010010100101110110000000000000b 

그래서, 십진수, 원래 주소가 3533139236, 페이지 어드레스 (박리 낮은 비트 어드레스)이다 3533135872 = 862582 x 4096이다 4096의 배수이다.

+1

숫자 예제로 잘 작동합니다. – mskfisher

1

이것은 하위 비트를 지우는 까다로운 방법입니다.

또 다른 방법은 알고리즘을 보여 비트, 당신이 종류를 조금 캐스트 필요로 아마, 컴파일되지 않습니다

void* GetPageAddress(void* pAddress) 
{ 
    return pAddress - pAddress%PAGE_SIZE; 
} 

수 있습니다 구현합니다.

효과적으로 pAddress보다 작은 PAGE_SIZE의 배수가 점점 커지고 있습니다.

관련 문제