안녕하세요. 펜티엄에는 CPU를 디버깅하기위한 내부카운터가 있다는것을
들어보셨을겁니다. 바로 RDTSC라는 레지스터고 코드 시퀸스는 0x0f31 입니다.
원래는 문서화 되지 않았고, 폭로(?)하지 않는다는 서약서에 서명하는 개발자들에게만 알려주었던 내용이죠. 하지만 결국 사람들이 발견해 내었었죠. 상당히 오래된 이야기인데, 저는 이것을 도스상에서 사용했었습니다.
RING 0 레벨의 명령어라서 윈도우즈95 상에서 크래쉬를 일으키기도 했었는데 지금 윈도우즈(2000포함)에서 아무문제없이 잘 되네요.
사용하고 있는 CPU의 클럭속도로 증가하는 카운터의 현재값을 읽어내는 함수입니다. 가장 빠르고 정확한 카운터라고 할 수 있겠죠.
함수의 원형은 아래와 같이 간단합니다.
unsigned __int64 snapshot_rdtsc()
{
static unsigned __int64 tick;
static unsigned __int32 lo, hi;
_asm _emit 0x0f
_asm _emit 0x31
_asm mov lo, eax
_asm mov hi, edx
tick = hi;
tick <<= 32;
tick |= lo;
return tick;
}
64비트 정수형을 지원하는 컴파일러에서 사용할 수 있습니다.
_emit을 지원하지 않으면 어셈블리 명령어인 db를 대신해서 사용하면 될겁니다.
돌려주는 값이 CPU의 클럭이므로 돌려주는 값을 CPU주파수로 나누면 CPU에 전원이 들어오고나서부터의 시간(초)이 나오게됩니다.
예) printf("%I64u\n", snapshot_rdtsc() / 466000000); // 466Mhz인경우
466Mhz인경우 466*100000 값을 넣었지만, 실제로 정확히 466은 아니겠죠..
펜티엄에는 RDTSC말고도 상당히 많은 디버깅 카운터 레지스터들이 있습니다.
뭐 code execution이 일어날때마다 증가하는 카운터, 인터럽트가 발생할때마다 증가하는 카운터 등등 말이에요. 이 내용은 97년인가에 BYTE잡지에 실린적이 있습니다. Terje Mathisen라는 분이 Pentium Secrets라는 제목으로 BYTE ARTICLES에 기고했었습니다.
그리고 CPU의 주파수를 동적으로 알아내시려면 현재의 priority class를 REALTIME_PRIORITY_CLASS로 thread priority를 THREAD_PRIORITY_TIME_CRITICAL로 설정하시고 (물론 나중에 원상복구해야겠죠) 현재 클럭 얻어내고 Sleep(5000) 으로 5초간 기다리고 다시 현재 클럭 얻어내어 그 두 값의 차이를 5000으로 나누면 상당히 정확한 주파수를 알 수 있을겁니다.
그리고 여담인데,
VC Watch윈도우에 @CLK 라고 넣으면 현재의 클럭값을 돌려주는군요.
이 값은 QueryPerformanceCounter의 값인것 같은데 아주 정확하지는
않아도 디버깅중에 이것을 응용할 수 있습니다.
들어보셨을겁니다. 바로 RDTSC라는 레지스터고 코드 시퀸스는 0x0f31 입니다.
원래는 문서화 되지 않았고, 폭로(?)하지 않는다는 서약서에 서명하는 개발자들에게만 알려주었던 내용이죠. 하지만 결국 사람들이 발견해 내었었죠. 상당히 오래된 이야기인데, 저는 이것을 도스상에서 사용했었습니다.
RING 0 레벨의 명령어라서 윈도우즈95 상에서 크래쉬를 일으키기도 했었는데 지금 윈도우즈(2000포함)에서 아무문제없이 잘 되네요.
사용하고 있는 CPU의 클럭속도로 증가하는 카운터의 현재값을 읽어내는 함수입니다. 가장 빠르고 정확한 카운터라고 할 수 있겠죠.
함수의 원형은 아래와 같이 간단합니다.
unsigned __int64 snapshot_rdtsc()
{
static unsigned __int64 tick;
static unsigned __int32 lo, hi;
_asm _emit 0x0f
_asm _emit 0x31
_asm mov lo, eax
_asm mov hi, edx
tick = hi;
tick <<= 32;
tick |= lo;
return tick;
}
64비트 정수형을 지원하는 컴파일러에서 사용할 수 있습니다.
_emit을 지원하지 않으면 어셈블리 명령어인 db를 대신해서 사용하면 될겁니다.
돌려주는 값이 CPU의 클럭이므로 돌려주는 값을 CPU주파수로 나누면 CPU에 전원이 들어오고나서부터의 시간(초)이 나오게됩니다.
예) printf("%I64u\n", snapshot_rdtsc() / 466000000); // 466Mhz인경우
466Mhz인경우 466*100000 값을 넣었지만, 실제로 정확히 466은 아니겠죠..
펜티엄에는 RDTSC말고도 상당히 많은 디버깅 카운터 레지스터들이 있습니다.
뭐 code execution이 일어날때마다 증가하는 카운터, 인터럽트가 발생할때마다 증가하는 카운터 등등 말이에요. 이 내용은 97년인가에 BYTE잡지에 실린적이 있습니다. Terje Mathisen라는 분이 Pentium Secrets라는 제목으로 BYTE ARTICLES에 기고했었습니다.
그리고 CPU의 주파수를 동적으로 알아내시려면 현재의 priority class를 REALTIME_PRIORITY_CLASS로 thread priority를 THREAD_PRIORITY_TIME_CRITICAL로 설정하시고 (물론 나중에 원상복구해야겠죠) 현재 클럭 얻어내고 Sleep(5000) 으로 5초간 기다리고 다시 현재 클럭 얻어내어 그 두 값의 차이를 5000으로 나누면 상당히 정확한 주파수를 알 수 있을겁니다.
그리고 여담인데,
VC Watch윈도우에 @CLK 라고 넣으면 현재의 클럭값을 돌려주는군요.
이 값은 QueryPerformanceCounter의 값인것 같은데 아주 정확하지는
않아도 디버깅중에 이것을 응용할 수 있습니다.
최근 댓글