X86 디버그 레지스터

디버그 레지스터(Debug Register)는 프로그램 디버깅을 목적으로 프로세서에 의해 사용되는 레지스터이다. x86 아키텍처에서는 DR0~DR7으로 명명되어 있다. 디버그 레지스터는 4개의 Debug 주소들을 조합해 다양한 디버그 상태를 프로그래머가 선택하도록 허용한다. 이러한 레지스터들중 6개는 디버그 제어기능으로 사용한다. 이러한 레지스터들은 MOV 명령어에 의해 접근이 가능하다. 디버그 레지스터는 Source Operand나 Destination Operand로 사용된다. Debug Register는 특별한(privileged) 리소스들이다. 예를 들어 그 디버그 레지스터에 접근가능한 MOV명령어는 오직 Privileged level0 에서만 실행된다. 다른 Privileged level에서 디버그 레지스터를 읽기 또는 쓰기를 했을 때 일반적으로 protection fault를 야기시킨다.

DR0 to DR3
이 각각의 레지스터는 4개의 Breakpoint 상태중 하나의 선형 주소를 갖고 있다. 각 breakpoint 상태는 DR7에서 Bit로 정의되어 있다. Debug Address Registers는 페이징 유무에 상관없이 효과적이다. Register내부의 주소들이 선형주소이기 때문이다. 만약 페이징이 일어난다면 선형주소들은 프로세서의 페이징 메커니즘에 의해 물리주소로 변환된다. 만약 일어나지 않는다면 선형주소들은 물리주소와 동일하다. 페이징이 일어날 때, 또 다른 작업은 선형주소와 물리주소간의 매핑이다. 매핑이 일어날 때 debug address register내의 주소는 변환과 관련된 주소이다. 이러한 이유로 x86에서는 DR7내의 global과 local bit가 활성화 된다. 이 비트들은 주어진 debug address가 global인지 또는 local인지 가리킨다.

DR7 - Debug Control 
DR7의 하위 8비트 (0~7까지)는 4개의 Address Breakpoint상태를 선택적으로 활성화시킨다. 활성화가 가능한 2개의 계층은 local(0,2,4,6)과 global(1,3,5,7)레벨이다. local 활성화 비트들은 원치 않는 breakpoint를 피하기 위해 task switch시 프로세서에 의해 자동으로 리셋된다. global 활성화 비트들은 task switch에 리셋되지 않는다. 그러므로 그것들은 모든 task에서 global한 상태로 사용된다.

16-17번(DR0) , 20-21번(DR1) , 24-25번(DR2) , 28-29번(DR3)은 breakpoint 일으킬 시점(trigger)를 정의한다. 각 breakpoint는 두 비트로 되어 있으며 실행중 breakpoint(00b) , 데이터쓰기(01b) , 데이터 읽고 쓰기(11b)등에 대해 의미한다. 10b는 I/O 읽고 쓰기시 break를 의미한다.(현재는 Reserved되어있다.) 그러나 hardware breakpoint는 지원하지 않는다. 18-19번(DR0) , 22-23번(DR1) , 26-27번(DR2) , 30-31번(DR3)는 거대한 메모리 영역에서 브레이크포인트에 의해 보이는 곳을 의미한다. 결론적으로 breakpoint는 각각 2 bit로 되어 있으며 그것들은 one(00b) , two(01b) , eight(10b) , four(11b)바이트에 의해 정의된다.

DR6 - Debug Status
디버그 상태 레지스터(Debug Status Register)는 디버그 상태를 발생시키는 목적으로 디버거를 허용한다. 프로세서가 활성화되어 있는 디버거 예외처리를 보호하고 있을 때 디버거 예외처리 핸들러를 실행하기 이전에 DR6 레지스터의 하위 bit들(0,1,2,3)을 활성화시킨다.
DR6의 비트들은 결코 프로세서에 의해 초기화되지 않는다. 다음 디버그 예외처리 확인시 다른 문제점을 피하기 위해 디버거 핸들러는 반환하기 전에 DR6를 즉시 0으로 채운다.

각주 

Intel 80386 Programmer's Reference

운영체제 기술
디지털 레지스터
X86 명령어
디버깅