=============================================================================== From: Ingo Rohloff Refer: 0 Subject: WRITING YOUR OWN DEBUGGER 1: 80xxx Status: Public ------------------------------------------------------------------------------- > AM> So, my question is: > AM> Does anyone have an example of using the registers as > AM> an aid in setting a break point and looking at what the machine state > AM> is??? Well I coded something with Debug-registers so here are some explanations first: - The debug registers are all 32-Bit. - DR0-DR3 store the physical break addresses (so you can use only 4 break addresses at the same time). e.g. 01c00h:0200h becomes 01c200h - DR4-DR5 are reserved for other new processors just ignore them - DR6 is the status register. It is set when the interrupt is triggered. It has the following structure: 1111111111111111 Bit FEDCBA9876543210 FEDCBA9876543210 0000000000000000 TSI000000000RRRR SSC 3210 R0 set means the address in dr0 was accessed R1 means the same for dr1 and so on IC means In-Circuit-Emulator is active => Debug registers are ignored SS Single-Step Mode => TF is set in EFLAGS TS TaskSwitch => happens if the T-Bit is set in the new TSS of the new task - DR7 is the control register for the four break adress registers DR0-DR3. Structure: 1111111111111111 Bit FEDCBA9876543210 FEDCBA9876543210 RRMMRRMMRRMMRRMM 000000GLGLGLGLGL 3333222211110000 SS33221100 Rx means range. The field can be set to: 00 = Interrupt, if the exact byte-address in the corresponding DRx Register is accessed. 01 = Interrupt, if some part of the word-address in the corredponding DRx Register is accessed. The address in the DRx register must be even 10 = reserved 11 = Interrupt, if some part of the Dword-address in the corresponding DRx Register is accessed. DRx mod 4 must be zero. Mx means mode. The field can be set to: 00 = Rx must be 00 for this mode. An interrupt is triggered if the FIRST byte of a command is read from the address stored in DRx 01 = Interrupt if something is written to the corresponding address 10 = reserved 11 = Interrupt if something is written or read to or from the corresponding address The Gx and Lx define if an interrupt is triggered or not. If both of them are set to zero for one address the processor changes the bits in DR6 but doesn't trigger an interrupt. If Gx is set the processor ignores the corresponding Lx bit. The interrupt is triggered every time the break address is accessed. The Lx bits are cleared with every Task switch, so it is possible to code a breakpoint for one specific task. To do that, you have to set the T-Flag in the TS-Segment for the task you want to debug. If the OS switches to that task an interrupt is triggered, so that the debugger can set the Lx bits properly. It is complicated and I don't think you'll need it for your purpose. Just set the corresponding Gx bit. The GS bit means global securety. If it isn't set the processor doesn't store the correct return address on the stack, if an debug-interrupt is triggered. (It has something to do with the parallel-technics in the processor. Setting the GS bit means slowing down the machine, but not much...) The LS bit does the same, but it is cleared with every task switch, just like the Lx bits.... here's some sample code: TESTED: ----------------------snip--------------------------------- ; Use TASM... or MASM ;-) .386P masm code segment para use16 assume cs:code,ds:code org 0100h start: mov ax,03501h ; Get&Save old Int_1 Segment and Offset int 021h mov Old_Se,Es mov Old_Of,Bx mov ax,02501h ; Set new Int_1 mov dx,offset new_int1 int 021h xor eax,eax ; calculate DR0-Break address mov ax,cs shl eax,4 add eax,offset BREAK mov dr0,eax ; set GS and G1 bit in DR7 ; R0=0 M0=0 => interrupt if ; command is read at DR0. mov eax,00000000000000000000001000000010b mov dr7,eax xor cx,cx wait1: loop wait1 ;wait a little break: ; there the break happens mov dx,offset endstr ; output message mov ax,0900h int 021h mov dx,old_of ; Get&Set old Int_1 Handler mov ds,CS:[old_se] mov ax,02501h int 021h mov ax,04C00h ; Exit... int 021h new_int1: xor eax,eax mov dr7,eax ; Reset Dr7, nothing will happen anymore... mov ax,0900h mov dx,offset outstr ; Output message int 021h iret outstr db 0Dh,0Ah db "Hello this program was breaked with the Debug-Registers" db 0Dh,0Ah,0Dh,0Ah,"$" endstr db "Ok, back from break...",0Dh,0Ah,"$" old_se dw 0 old_of dw 0 code ends end start -------------------------snip------------------------------ BTW: It looks like the DR0 Registers are not protected... That means that you can use them under EMM386.EXE under DOS... I don't know if this works with other memory managers too... have fun and stay tuned Ingo --- FMail 0.96â * Origin: Pascal and C are fast... but ASM IS FASTER !! (2:2480/36.7) ===============================================================================