Share via


Pseudo-Register 구문

디버거는 특정 값을 보유하는 여러 의사 레지스터를 지원합니다.

디버거는 자동 의사 레지스터를 특정 유용한 값으로 설정합니다. 사용자 정의 의사 레지스터 는 쓰거나 읽을 수 있는 정수 변수입니다.

모든 의사 레지스터는 달러 기호($)로 시작합니다. MASM 구문을 사용하는 경우 달러 기호 앞에 at sign( @ )을 추가할 수 있습니다. 이 기호는 다음 토큰이 기호가 아닌 레지스터 또는 의사 레지스터임을 디버거에 알릴 수 있습니다. at 기호를 생략하면 디버거가 전체 기호 테이블을 검색해야 하므로 더 느리게 응답합니다.

예를 들어 다음 두 명령은 동일한 출력을 생성하지만 두 번째 명령은 더 빠릅니다.

0:000> ? $exp
Evaluate expression: 143 = 0000008f
0:000> ? @$exp
Evaluate expression: 143 = 0000008f

의사 레지스터와 이름이 같은 기호가 있는 경우 at 기호를 추가해야 합니다.

C++ 식 구문을 사용하는 경우 at sign( @ )이 항상 필요합니다.

r(레지스터) 명령은 이 규칙의 예외입니다. 디버거는 항상 첫 번째 인수를 레지스터 또는 의사 레지스터로 해석합니다. (서명 시 은 필요하지 않거나 허용되지 않습니다.) r 명령에 대한 두 번째 인수가 있는 경우 기본 식 구문에 따라 해석됩니다. 기본 식 구문이 C++인 경우 다음 명령을 사용하여 $t 2 의사 등록을 $t 1 의사 레지스터에 복사해야 합니다.

0:000> r $t1 = @$t2

자동 Pseudo-Registers

디버거는 다음 의사 레지스터를 자동으로 설정합니다.

의사 레지스터 Description

$ea

실행된 마지막 명령의 유효 주소입니다. 이 명령에 유효 주소가 없으면 디버거에 "잘못된 레지스터 오류"가 표시됩니다. 이 명령에 두 개의 유효 주소가 있는 경우 디버거는 첫 번째 주소를 표시합니다.

$ea 2

실행된 마지막 명령의 두 번째 유효 주소입니다. 이 명령에 두 개의 유효 주소가 없으면 디버거에 "잘못된 레지스터 오류"가 표시됩니다.

$exp

계산된 마지막 식입니다.

$ra

현재 스택에 있는 반환 주소입니다.

이 주소는 실행 명령에서 특히 유용합니다. 예를 들어 g @$ra 반환 주소가 발견될 때까지 계속됩니다( gu(Go Up) 는 현재 함수의 "단계별 실행"을 보다 정확하게 수행하는 방법이지만).

$ip

명령 포인터 레지스터입니다.

x86 기반 프로세서:eip와 동일합니다. Itanium 기반 프로세서:iip과 관련이 있습니다. (자세한 내용은 이 표 다음의 참고 사항을 참조하세요.) x64 기반 프로세서:rip과 동일합니다.

$eventip

현재 이벤트 시의 명령 포인터입니다. 이 포인터는 일반적으로 스레드를 전환하거나 명령 포인터의 값을 수동으로 변경하지 않는 한 $ip 일치합니다.

$previp

이전 이벤트 당시의 명령 포인터입니다. (디버거에 침입하는 것은 이벤트로 계산됩니다.)

$relip

현재 이벤트와 관련된 명령 포인터입니다. 분기 추적을 수행할 때 이 포인터는 분기 원본에 대한 포인터입니다.

$scopeip

현재 로컬 컨텍스트(scope라고도 함)에 대한 명령 포인터입니다.

$exentry

현재 프로세스의 첫 번째 실행 파일 진입점 주소입니다.

$retreg

기본 반환 값 레지스터입니다.

x86 기반 프로세서:eax와 동일합니다. Itanium 기반 프로세서:ret0과 동일합니다. x64 기반 프로세서:rax와 동일합니다.

$retreg 64

기본 반환 값 레지스터(64비트 형식)입니다.

x86 프로세서:edx:eax 쌍과 동일합니다.

$csp

현재 호출 스택 포인터입니다. 이 포인터는 호출 스택 깊이를 가장 많이 나타내는 레지스터입니다.

x86 기반 프로세서:esp와 동일합니다. Itanium 기반 프로세서:bsp와 동일합니다. x64 기반 프로세서:rsp와 동일합니다.

$p

마지막 d*(메모리 표시) 명령이 인쇄한 값입니다.

$proc

현재 프로세스의 주소(즉, EPROCESS 블록의 주소)입니다.

$thread

현재 스레드의 주소입니다. 커널 모드 디버깅에서 이 주소는 ETHREAD 블록의 주소입니다. 사용자 모드 디버깅에서 이 주소는 TEB(스레드 환경 블록)의 주소입니다.

$peb

현재 프로세스의 PEB(프로세스 환경 블록)의 주소입니다.

$teb

현재 스레드의 TEB(스레드 환경 블록)의 주소입니다.

$tpid

현재 스레드를 소유하는 프로세스의 PID(프로세스 ID)입니다.

$tid

현재 스레드의 스레드 ID입니다.

$dtid

$dpid

$dsid

$bp번호

해당 중단점의 주소입니다. 예를 들어 $bp 3 (또는 $bp 03)은 중단점 ID가 3인 중단점을 참조합니다. number 는 항상 10진수입니다. 중단점의 ID가 Number인 경우 $bp번호 는 0으로 평가됩니다. 중단점에 대한 자세한 내용은 중단점 사용을 참조하세요.

$frame

현재 프레임 인덱스입니다. 이 인덱스는 .frame(로컬 컨텍스트 설정) 명령이 사용하는 것과 동일한 프레임 번호입니다.

$dbgtime

디버거가 실행 중인 컴퓨터에 따라 현재 시간입니다.

$callret

.call(호출 함수)이 호출되거나 .fnret /s 명령에 사용되는 마지막 함수의 반환 값입니다. $callret 데이터 형식은 이 반환 값의 데이터 형식입니다.

$extret

$extin

$clrex

$lastclrex

관리되는 디버깅만: 마지막으로 발견된 CLR(공용 언어 런타임) 예외 개체의 주소입니다.

$ptrsize

포인터의 크기입니다. 커널 모드에서 이 크기는 대상 컴퓨터의 포인터 크기입니다.

$pagesize

메모리의 한 페이지에 있는 바이트 수입니다. 커널 모드에서 이 크기는 대상 컴퓨터의 페이지 크기입니다.

$pcr

$pcrb

$argreg

$exr_chance

현재 예외 레코드의 확률입니다.

$exr_code

현재 예외 레코드에 대한 예외 코드입니다.

$exr_numparams

현재 예외 레코드의 매개 변수 수입니다.

$exr_param0

현재 예외 레코드의 매개 변수 0 값입니다.

$exr_param1

현재 예외 레코드의 매개 변수 1 값입니다.

$exr_param2

현재 예외 레코드의 매개 변수 2 값입니다.

$exr_param3

현재 예외 레코드의 매개 변수 3 값입니다.

$exr_param4

현재 예외 레코드의 매개 변수 4 값입니다.

$exr_param5

현재 예외 레코드의 매개 변수 5 값입니다.

$exr_param6

현재 예외 레코드의 매개 변수 6 값입니다.

$exr_param7

현재 예외 레코드의 매개 변수 7 값입니다.

$exr_param8

현재 예외 레코드의 매개 변수 8 값입니다.

$exr_param9

현재 예외 레코드의 매개 변수 9 값입니다.

$exr_param10

현재 예외 레코드의 매개 변수 10 값입니다.

$exr_param11

현재 예외 레코드의 매개 변수 11 값입니다.

$exr_param12

현재 예외 레코드의 매개 변수 12 값입니다.

$exr_param13

현재 예외 레코드의 매개 변수 13 값입니다.

$exr_param14

현재 예외 레코드의 매개 변수 14 값입니다.

$bug_code

버그 검사 발생한 경우 버그 코드입니다. 라이브 커널 모드 디버깅 및 커널 크래시 덤프에 적용됩니다.

$bug_param1

버그 검사 발생한 경우 매개 변수 1의 값입니다. 라이브 커널 모드 디버깅 및 커널 크래시 덤프에 적용됩니다.

$bug_param2

버그 검사 발생한 경우 매개 변수 2의 값입니다. 라이브 커널 모드 디버깅 및 커널 크래시 덤프에 적용됩니다.

$bug_param3

버그 검사 발생한 경우 매개 변수 3의 값입니다. 라이브 커널 모드 디버깅 및 커널 크래시 덤프에 적용됩니다.

$bug_param4

버그 검사 발생한 경우 매개 변수 4의 값입니다. 라이브 커널 모드 디버깅 및 커널 크래시 덤프에 적용됩니다.

이러한 의사 레지스터 중 일부는 특정 디버깅 시나리오에서 사용할 수 없을 수 있습니다. 예를 들어 사용자 모드 미니덤프 또는 특정 커널 모드 덤프 파일을 디버깅할 때는 $peb, $tid$tpid 사용할 수 없습니다. ~(스레드 상태)에서 스레드 정보를 학습할 수 있지만 $tid 학습할 수 없는 상황이 있습니다. 첫 번째 디버거 이벤트에서 는 $previp 의사 등록을 사용할 수 없습니다. 분기 추적이 아니면 $relip 의사 등록을 사용할 수 없습니다. 사용할 수 없는 의사 레지스터를 사용하는 경우 구문 오류가 발생합니다.

$thread, $proc, $teb, $peb $lastclrex 같은 구조체의 주소를 보유하는 의사 레지스터는 C++ 식 계산기의 적절한 데이터 형식에 따라 평가되지만 MASM 식 계산기에는 없습니다. 예를 들어 ? $teb 명령은 TEB의 주소를 표시하고 ?? @$teb 명령은 전체 TEB 구조를 표시합니다. 자세한 내용은 식 평가를 참조하세요.

Itanium 기반 프로세서에서 iip 레지스터는 번들 정렬됩니다. 즉, 다른 슬롯이 실행되더라도 현재 명령이 포함된 번들에서 슬롯 0을 가리킵니다. 따라서 iip 은 전체 명령 포인터가 아닙니다. $ip 의사 레지스터는 번들 및 슬롯을 포함한 실제 명령 포인터입니다. 주소 포인터($ra, $retreg, $eventip, $previp, $relip $exentry)를 포함하는 다른 의사 레지스터는 모든 프로세서에서 $ip 구조와 동일합니다.

r 명령을 사용하여 $ip 값을 변경할 수 있습니다. 이 변경 내용은 해당 레지스터도 자동으로 변경합니다. 실행이 다시 시작되면 새 명령 포인터 주소에서 다시 시작됩니다. 이 레지스터는 수동으로 변경할 수 있는 유일한 자동 의사 등록입니다.

참고 MASM 구문에서 마침표(. )사용하여 $ip 의사 레지스터를 나타낼 수 있습니다. 이 기간 전에 at sign(@)을 추가하지 않고 r 명령의 첫 번째 매개 변수로 마침표 를 사용하지 않습니다. 이 구문은 C++ 식 내에서 허용되지 않습니다.

자동 의사 레지스터는 자동 별칭과 유사합니다. 그러나 별칭 관련 토큰(예: ${ })과 함께 자동 별칭을 사용할 수 있으며 이러한 토큰에는 의사 레지스터를 사용할 수 없습니다.

사용자 정의 Pseudo-Registers

20개의 사용자 정의 의사 레지스터($t 0, $t 1, ..., $t 19)가 있습니다. 이러한 의사 레지스터는 디버거를 통해 읽고 쓸 수 있는 변수입니다. 이러한 의사 레지스터에 정수 값을 저장할 수 있습니다. 루프 변수로 특히 유용할 수 있습니다.

이러한 의사 레지스터 중 하나에 쓰려면 다음 예제와 같이 r(Registers) 명령을 사용합니다.

0:000> r $t0 = 7
0:000> r $t1 = 128*poi(MyVar)

모든 의사 레지스터와 마찬가지로 다음 예제와 같이 모든 식에서 사용자 정의 의사 레지스터를 사용할 수 있습니다.

0:000> bp $t3 
0:000> bp @$t4 
0:000> ?? @$t1 + 4*@$t2 

r 명령과 함께 ? 스위치를 사용하지 않는 한 의사 레지스터는 항상 정수로 입력됩니다. 이 스위치를 사용하는 경우 의사 레지스터는 할당된 모든 형식을 획득합니다. 예를 들어 다음 명령은 UNICODE_STRING** 형식과 0x0012FFBC 값을 $t 15에 할당합니다.

0:000> r? $t15 = * (UNICODE_STRING*) 0x12ffbc

사용자 정의 의사 레지스터는 디버거가 시작될 때 0을 기본값으로 사용합니다.

참고 별칭 $u 0, $u 1, ..., $u 9 는 비슷한 모양에도 불구하고 의사 레지스터가 아닙니다. 이러한 별칭에 대한 자세한 내용은 별칭 사용을 참조하세요.

예제

다음 예제에서는 현재 스레드가 NtOpenFile을 호출할 때마다 적중되는 중단점을 설정합니다. 그러나 다른 스레드가 NtOpenFile을 호출할 때 이 중단점은 적중되지 않습니다.

kd> bp /t @$thread nt!ntopenfile

예제

다음 예제에서는 레지스터가 지정된 값을 보유할 때까지 명령을 실행합니다. 먼저 "eaxstep"이라는 스크립트 파일에 조건부 단계별 실행을 위해 다음 코드를 입력합니다.

.if (@eax == 1234) { .echo 1234 } .else { t "$<eaxstep" }

다음으로, 다음 명령을 실행합니다.

t "$<eaxstep"

디버거는 단계를 수행한 다음 명령을 실행합니다. 이 경우 디버거는 1234 를 표시하거나 프로세스를 반복하는 스크립트를 실행합니다.