source: vendor/emx/current/src/dos/debug.asm

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 99.8 KB
Line 
1;
2; DEBUG.ASM -- Built-in debugger
3;
4; Copyright (c) 1991-1996 by Eberhard Mattes
5;
6; This file is part of emx.
7;
8; emx is free software; you can redistribute it and/or modify it
9; under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2, or (at your option)
11; any later version.
12;
13; emx is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16; GNU General Public License for more details.
17;
18; You should have received a copy of the GNU General Public License
19; along with emx; see the file COPYING. If not, write to
20; the Free Software Foundation, 59 Temple Place - Suite 330,
21; Boston, MA 02111-1307, USA.
22;
23; See emx.asm for a special exception.
24;
25
26 INCLUDE EMX.INC
27 INCLUDE EXCEPT.INC
28 INCLUDE OPRINT.INC
29 INCLUDE DISASM.INC
30 INCLUDE SEGMENTS.INC
31 INCLUDE SYMBOLS.INC
32 INCLUDE SIGNAL.INC
33 INCLUDE PROCESS.INC
34 INCLUDE PAGING.INC
35 INCLUDE PMINT.INC
36 INCLUDE TABLES.INC
37 INCLUDE PMIO.INC
38 INCLUDE SWAPPER.INC
39 INCLUDE FILEIO.INC
40 INCLUDE UTILS.INC
41
42 PUBLIC STEP_FLAG, DEBUG_AVAIL, DEBUG_SER_FLAG, DEBUG_SER_PORT
43 PUBLIC DEBUG_EXCEPTION, SET_BREAKPOINT, INS_BREAKPOINTS
44 PUBLIC DEBUG_RESUME, DEBUG_STEP, DEBUG_QUIT, DEBUG_INIT
45
46BP_INACTIVE = 0 ; Entry unused
47BP_BREAKPOINT = 1 ; Code breakpoint
48BP_WATCHPOINT_R = 2 ; R/W watchpoint
49BP_WATCHPOINT_W = 3 ; W watchpoint
50BP_WATCHPOINT_X = 4 ; X watchpoint
51
52BREAKPOINT STRUCT
53BP_TYPE DB ? ; Breakpoint type (see above)
54BP_LEN DB ? ; Watchpoint length
55BP_SEL DW ? ; Selector
56BP_OFF DD ? ; Offset
57BP_ADDR DD ? ; Linear address
58BP_VAL DD ? ; Watchpoint: initial value
59BREAKPOINT ENDS
60
61SV_DATA SEGMENT
62
63DEBUG_SER_PORT DW 02F8H ; COM2
64DEBUG_SER_FLAG DB FALSE
65
66STEP_FLAG DB FALSE
67DEBUG_AVAIL DB NOT FALSE
68
69DEBUG_SHOW_PC DB NOT FALSE
70DEBUG_STOP DB NOT FALSE
71GO_FLAG DB FALSE
72DEBUG_COUNT DB 0
73FATAL DB ?
74DA_SYM_FLAG DB ?
75DA_EMPTY_FLAG DB ?
76NEXT_CS DW ?
77NEXT_EIP DD ?
78
79B_NEXT DB 0
80B_COLUMN DB 0
81
82 TALIGN 2
83BREAKPOINTS BREAKPOINT 4 DUP (<BP_INACTIVE>)
84
85 TALIGN 2
86GCHAR DW B_CHAR
87GTEXT DW B_TEXT
88GDWORD DW B_DWORD
89GWORD DW B_WORD
90GBYTE DW B_BYTE
91GCRLF DW B_CRLF
92GINCHAR DW B_INCHAR
93DA_SYM_ADDR DD ?
94RANGE_SEL DW ?
95RANGE_OFF DD ?
96ADDR_LIN DD ?
97ADDR_ARG DD ?
98SEARCH_SEL DW ?
99SEARCH_OFF DD ?
100SEARCH_LEN DD ?
101SEARCH_SIZE DD ?
102ADDR_SEL DW ?
103ADDR_OFF DD ?
104ADDR_COUNT DD ?
105SEL_SEL DW ?
106SEL_COUNT DW ?
107U_LAST_SEL DW 0
108U_LAST_OFF DD ?
109D_LAST_SEL DW 0
110D_LAST_OFF DD ?
111WP_LEN DB ?
112WP_TYPE DB ?
113SKIP_FLAG DB FALSE
114WATCH_FAILURES DB ?
115XOFF DB FALSE
116LOOK_AHEAD DB 0
117LIST_ALL DB FALSE
118
119SEARCH_BUF DB 64 DUP (?)
120
121FLAG_TAB DW 0001H
122 DB "NCCY"
123 DW 0004H
124 DB "PEPO"
125 DW 0010H
126 DB "NAAC"
127 DW 0040H
128 DB "NZZR"
129 DW 0080H
130 DB "PLNG"
131 DW 0200H
132 DB "DIEI"
133 DW 0400H
134 DB "UPDN"
135 DW 0800H
136 DB "NVOV"
137 DW 0000H
138
139R8 = 0
140R16 = 1
141R32 = 2
142
143REGISTER MACRO @NAME, @SIZE, @OFFSET
144 DB @NAME, @SIZE, @OFFSET
145 ENDM
146
147REG_TAB LABEL BYTE
148 REGISTER "EFLAGS", R32, 52
149 REGISTER "EAX", R32, 36
150 REGISTER "EBX", R32, 24
151 REGISTER "ECX", R32, 32
152 REGISTER "EDX", R32, 28
153 REGISTER "ESI", R32, 12
154 REGISTER "EDI", R32, 8
155 REGISTER "EBP", R32, 16
156 REGISTER "ESP", R32, 56 ; See GET_REG
157 REGISTER "EIP", R32, 44
158 REGISTER "AX", R16, 36
159 REGISTER "BX", R16, 24
160 REGISTER "CX", R16, 32
161 REGISTER "DX", R16, 28
162 REGISTER "SI", R16, 12
163 REGISTER "DI", R16, 8
164 REGISTER "BP", R16, 16
165 REGISTER "SP", R16, 56 ; See GET_REG
166 REGISTER "IP", R16, 44
167 REGISTER "AL", R8, 36
168 REGISTER "BL", R8, 24
169 REGISTER "CL", R8, 32
170 REGISTER "DL", R8, 28
171 REGISTER "AH", R8, 37
172 REGISTER "BH", R8, 25
173 REGISTER "CH", R8, 33
174 REGISTER "DH", R8, 29
175 REGISTER "CS", R16, 48
176 REGISTER "DS", R16, 6
177 REGISTER "ES", R16, 4
178 REGISTER "FS", R16, 2
179 REGISTER "GS", R16, 0
180 REGISTER "SS", R16, 60 ; See GET_REG
181 REGISTER 0FFH, 0FFH, 0FFH
182
183$EXCEPT DB "Exception ", 0
184$CR2 DB " CR2=", 0
185$ERRCD DB "ERRCD=", 0
186$BREAKPOINT DB "Breakpoint ", 0
187$WATCHPOINT DB "Watchpoint ", 0
188$INPUT_ERROR DB "Input error", CR, LF, 0
189$INVALID_SEL DB "Invalid selector", CR, LF, 0
190$BEYOND_LIMIT DB "Offset beyond segment limit", CR, LF, 0
191$ALIGNMENT DB "Address not correctly aligned", CR, LF, 0
192$ADDR_FAILURE DB "GET_LIN failed", CR, LF, 0
193$PAGE_DIR DB "Page table not present", CR, LF, 0
194$PHYSICAL DB "physical=", 0
195$LINEAR DB "linear=", 0
196$EXTERNAL DB "external=", 0
197$LINE DB " line ", 0
198$RPL DB ": RPL=", 0
199$TI_GDT DB " GDT ", 0
200$TI_LDT DB " LDT ", 0
201$SEL_INVALID DB "invalid selector", 0
202$DPL DB " DPL=", 0
203$DATA DB "data segment", 0
204$CODE DB "code segment", 0
205$BASE DB " base=", 0
206$LIMIT DB " limit=", 0
207$SEL_16 DB "16-bit ", 0
208$SEL_32 DB "32-bit ", 0
209$INT DB "int gate", 0
210$TRAP DB "trap gate", 0
211$TSS DB "TSS", 0
212$CALL DB "call gate", 0
213$TASK DB "task gate", 0
214$LDT DB "LDT", 0
215$NULL DB "null", 0
216
217$INSBRK DB "INS_BREAKPOINTS", CR, LF, 0
218$CONTINUE DB "CONTINUE", CR, LF, 0
219$DO_STEP DB "DO_STEP", CR, LF, 0
220$DO_CALL DB "DO_CALL", CR, LF, 0
221$DEBUG_EXCEPTION DB "DEBUG_EXCEPTION ", 0
222$RUN DB "RUN", CR, LF, 0
223
224$EMPTY DB "empty", 0
225$INFINITY DB "invalid or infinity", 0
226$ZERO DB "zero", 0
227$CW DB "CW=", 0
228$SW DB " SW=", 0
229$C3210 DB " C3210=", 0
230
231$SWAP_FAULTS DB CR, LF
232 DB "Swapper statistics: F=", 0
233$SWAP_READS DB " R=", 0
234$SWAP_WRITES DB " W=", 0
235$SNATCH_COUNT DB " N=", 0
236$SWAP_SIZE DB " S=", 0
237
238$INFO_TITLE DB "idx pid ppid file handles", CR, LF, 0
239; xx* xxxxxxxx xxxxxxxx xx
240
241INPUT_BUF LABEL BYTE
242DISASM_BUF DB 80 DUP (?)
243SYMBOL_BUF DB 80 DUP (?)
244
245SV_DATA ENDS
246
247SV_CODE SEGMENT
248
249 .386P
250
251 ASSUME CS:SV_CODE, DS:NOTHING
252
253;
254; Set EFLAGS for resuming current process (without stepping)
255;
256; In: SS:BP Interrupt/exception stack frame
257;
258 ASSUME BP:PTR ISTACKFRAME
259DEBUG_RESUME PROC NEAR
260 AND I_EFLAGS, NOT FLAG_TF
261 OR I_EFLAGS, FLAG_RF
262 RET
263 ASSUME BP:NOTHING
264DEBUG_RESUME ENDP
265
266
267;
268; Set EFLAGS for single stepping current process
269;
270; In: SS:BP Interrupt/exception stack frame
271;
272 ASSUME BP:PTR ISTACKFRAME
273DEBUG_STEP PROC NEAR
274 OR I_EFLAGS, FLAG_TF
275 RET
276 ASSUME BP:NOTHING
277DEBUG_STEP ENDP
278
279
280;
281; Exception 1 (debug)
282;
283 ASSUME DS:SV_DATA
284 ASSUME BP:PTR ISTACKFRAME
285 TALIGN 2
286DEBUG_EXCEPTION PROC NEAR
287 XOR EAX, EAX
288 MOV DR7, EAX ; Disable break points
289 MOV EBX, DR6 ; Copy DR6 to EBX
290 MOV DR6, EAX ; DR6 never cleared by 386
291 MOV ECX, CR2 ; Copy CR2 to ECX
292 STI
293 CMP DEBUG_FLAG, FALSE
294 JE SHORT DEX0
295 LEA EDX, $DEBUG_EXCEPTION
296 CALL GTEXT
297 MOV AX, I_CS
298 CALL GWORD
299 MOV AL, ":"
300 CALL GCHAR
301 MOV EAX, I_EIP
302 CALL GDWORD
303 CALL GCRLF
304DEX0: MOV AL, EXCEPT_NO ; Get exception number
305 CMP AL, 1 ; Debugging exception?
306 JE SHORT REASON1 ; Yes -> check for reason
307;
308; Fatal exception or breakpoint instruction
309;
310 LEA EDX, $EXCEPT
311 CALL GTEXT
312 CALL GBYTE
313 MOV AL, ":"
314 CALL GCHAR
315 MOV AL, " "
316 CALL GCHAR
317 MOV AL, EXCEPT_NO
318 CALL EXCEPT_NAME
319 CALL GTEXT
320 CALL GCRLF
321 MOV FATAL, NOT FALSE
322 CMP EXCEPT_NO, 3 ; INT 3
323 JNE SHORT DEX1
324 MOV FATAL, FALSE
325DEX1: CMP EXCEPT_NO, 8
326 JB SHORT DEX9
327 CMP EXCEPT_NO, 14
328 JA SHORT DEX9
329 LEA EDX, $ERRCD
330 CALL GTEXT
331 MOV EAX, I_ERRCD
332 CALL GDWORD
333 CMP EXCEPT_NO, 14 ; Page fault?
334 JNE SHORT DEX8
335 LEA EDX, $CR2
336 CALL GTEXT
337 MOV EAX, ECX
338 CALL GDWORD
339DEX8: CALL GCRLF
340DEX9: MOV AL, 1 ; New disassembly
341 JMP SHOW
342
343;
344; Debugging exception
345;
346REASON1: MOV FATAL, FALSE ; Not a fatal exception
347;
348; Check for X type watchpoints
349;
350 LEA SI, BREAKPOINTS
351 ASSUME SI:PTR BREAKPOINT
352 MOV CX, 4
353 MOV WATCH_FAILURES, 0
354 MOV EDX, 0001H ; B0
355CHECK_WP: CMP [SI].BP_TYPE, BP_WATCHPOINT_X
356 JNE SHORT CHECK_WP9 ; Skip other entries
357 CALL WATCH_GET ; Read memory
358 CMP EAX, [SI].BP_VAL ; Changed?
359 JNE SHORT CHECK_WP1 ; Yes -> hit
360 INC WATCH_FAILURES ; Increment number of non-hits
361 JMP SHORT CHECK_WP9 ; Next entry
362CHECK_WP1: OR EBX, EDX ; Set Bx bit of DR6
363CHECK_WP9: SHL EDX, 1 ; Next Bx bit
364 ADD SI, SIZE BREAKPOINT
365 LOOP CHECK_WP
366 ASSUME SI:NOTHING
367 TEST EBX, 0FH ; Any breakpoints or wpx hits?
368 JNZ SHORT SHOW_BP ; Yes -> display breakpoints
369 CMP WATCH_FAILURES, 0 ; Any X watchpoint?
370 JNE SHORT WATCH1 ; Yes -> continue?
371 MOV AL, FALSE ; Continue disassembly
372 JMP SHOW ; Stop
373
374WATCH1: CMP GO_FLAG, FALSE ; GO command?
375 JE SHOW ; No -> stop
376 JMP CONTINUE ; Continue program
377;
378; Display breakpoints
379;
380SHOW_BP: LEA SI, BREAKPOINTS
381 ASSUME SI:PTR BREAKPOINT
382 MOV CX, 4
383SHOW_BP1: SHR EBX, 1 ; Test in turn B0, B1, B2, B3
384 JNC SHORT SHOW_BP9 ; Not set -> skip
385 CMP [SI].BP_TYPE, BP_INACTIVE ; B1 seems to be inaccurate
386 JE SHORT SHOW_BP9
387 LEA EDX, $BREAKPOINT ; Breakpoint
388 CMP [SI].BP_TYPE, BP_BREAKPOINT
389 JE SHORT SHOW_BP2
390 LEA EDX, $WATCHPOINT ; Watchpoint
391SHOW_BP2: CALL GTEXT ; Display breakpoint type
392 MOV AL, "4"
393 SUB AL, CL
394 CALL GCHAR ; Display breakpoint number
395 CALL GCRLF
396SHOW_BP9: ADD SI, SIZE BREAKPOINT ; Next breakpoint
397 LOOP SHOW_BP1
398 ASSUME SI:NOTHING
399 MOV AL, 1 ; New disassembly
400;
401; Show disassembled instruction
402;
403SHOW: CMP DEBUG_SHOW_PC, FALSE ; Disassemble?
404 JE SHORT DEBUG_01 ; No -> skip
405 CALL TRACE_DISASM ; Show current instruction
406DEBUG_01: CMP FATAL, FALSE ; Fatal exception?
407 JNE STOP1 ; Yes -> stop
408 CMP DEBUG_STOP, FALSE ; Non-stop mode?
409 JE DO_STEP ; Yes -> continue
410 CMP DEBUG_COUNT, 0 ; Multiple steps?
411 JE SHORT STOP1 ; No -> stop
412 DEC DEBUG_COUNT ; Another step?
413 JNZ DO_STEP ; Yes -> continue
414;
415; Stop program, wait for command
416;
417STOP1: MOV DEBUG_COUNT, 0 ; Disable multiple steps
418 MOV DEBUG_STOP, NOT FALSE ; Disable non-stop mode
419 MOV DEBUG_SHOW_PC, NOT FALSE ; Enable disassembly
420 MOV BREAKPOINTS[0].BP_TYPE, BP_INACTIVE ; Delete bp 0
421 MOV GO_FLAG, FALSE ; No GO command active
422;
423; Wait for command
424;
425KEY: CALL GINCHAR
426 OR AL, AL ; Extended key code?
427 JZ FKEY ; Yes ->
428;
429; Check for digits
430;
431 MOV AH, 10
432 CMP AL, "0" ; 10 steps?
433 JE CMD_MULT ; Yes ->
434 JB SHORT KEY1
435 MOV AH, AL
436 SUB AH, "0"
437 CMP AL, "9" ; Multiple steps (1-9) ?
438 JBE CMD_MULT ; Yes ->
439;
440; Check for other commands
441;
442KEY1: CALL UPPER ; Convert to upper case
443 CMP AL, "." ; Registers
444 JE CMD_DOT
445 CMP AL, ":" ; Silent
446 JE CMD_SILENT
447 CMP AL, "A" ; Address
448 JE CMD_ADDR
449 CMP AL, "B" ; Breakpoint
450 JE CMD_BREAK
451 CMP AL, "C" ; Call
452 JE CMD_CALL
453 CMP AL, "D" ; Display
454 JE CMD_DISPLAY
455 CMP AL, "F" ; 387 status
456 JE CMD_387
457 CMP AL, "G" ; Go
458 JE CMD_GO
459 CMP AL, "I" ; Info
460 JE CMD_INFO
461 CMP AL, "K" ; Kill
462 JE CMD_KILL
463 CMP AL, "L" ; Selector
464 JE CMD_SELECTOR
465 CMP AL, "N" ; Non-stop
466 JE SHORT CMD_NONSTOP
467 CMP AL, "Q" ; Quit
468 JE CMD_QUIT
469 CMP AL, "R" ; Register
470 JE CMD_REG
471 CMP AL, "S" ; Search
472 JE CMD_SEARCH
473 CMP AL, "U" ; Unassemble
474 JE CMD_UNASSEMBLE
475 CMP AL, "V" ; Virtual
476 JE CMD_VIRT
477 CMP AL, "W" ; Watchpoint
478 JE CMD_WATCH
479 CMP AL, "X" ; Symbol
480 JE CMD_SYM
481 CMP AL, " " ; Step
482 JE CMD_STEP
483BAD_KEY: MOV AL, 07H
484 CALL GCHAR
485 JMP KEY ; Wait for another command
486
487FKEY: CALL GINCHAR ; Get second code
488 CMP AL, 3CH ; F2
489 JE CMD_DOT
490 CMP AL, 3FH ; F5?
491 JE CONTINUE ; Yes -> continue program
492 CMP AL, 42H ; F8
493 JE DO_STEP
494 CMP AL, 44H ; F10
495 JE DO_CALL
496 JMP SHORT BAD_KEY ; Ring bell
497
498;
499; Non-stop single stepping mode
500;
501CMD_NONSTOP: MOV DEBUG_STOP, FALSE ; Set non-stop mode
502 JMP DO_STEP ; Continue program
503
504;
505; Display registers
506;
507CMD_DOT: CALL GCRLF ; New line
508 CALL REG_DUMP ; Display registers
509 MOV AL, 1 ; New disassembly
510 JMP SHOW ; Display current instruction
511
512;
513; Multiple steps
514;
515CMD_MULT: MOV DEBUG_COUNT, AH ; Set number of steps
516 JMP DO_STEP ; Continue program
517
518;
519; Silent command
520;
521CMD_SILENT: NOT DEBUG_SHOW_PC ; Toggle silent flag
522 JMP KEY ; Command loop
523
524;
525; Go command
526;
527CMD_GO: CALL INPUT ; Input arguments
528 JC INPUT_ERROR
529 CALL END_OF_LINE
530 JZ SHORT CONTINUE
531 MOV DX, I_CS
532 CALL GET_ADDR
533 JC INPUT_ERROR
534 CALL END_OF_LINE
535 JNZ INPUT_ERROR
536;
537; Breakpoint 0 at DX:EAX and continue program
538;
539 CALL SET_BREAKPOINT ; Set breakpoint 0 at DX:EAX
540 JNZ INPUT_ERROR ; Error -> display message
541;
542; Insert breakpoints and continue program
543;
544CONTINUE: CMP DEBUG_FLAG, FALSE
545 JE SHORT CONT_0
546 LEA EDX, $CONTINUE
547 CALL GTEXT
548CONT_0: MOV GO_FLAG, NOT FALSE ; GO command executing
549 CALL DEBUG_RESUME ; Resume program, don't step
550 CALL INS_BREAKPOINTS ; Insert breakpoints
551 JMP RUN ; Continue program
552
553
554;
555; Watchpoint command
556;
557CMD_WATCH: CALL INPUT ; Input arguments
558 JC INPUT_ERROR
559 CALL END_OF_LINE ; Any arguments?
560 JZ CMD_BREAK_SHOW ; No -> display breakpoints
561 CALL FETCH ; Fetch character (length)
562 JZ INPUT_ERROR ; End of line -> error
563 MOV AH, 00H
564 CMP AL, "B"
565 JE SHORT CMD_WATCH_1
566 MOV AH, 01H
567 CMP AL, "W"
568 JE SHORT CMD_WATCH_1
569 MOV AH, 03H
570 CMP AL, "D"
571 JNE INPUT_ERROR
572CMD_WATCH_1: MOV WP_LEN, AH
573 CALL FETCH ; Fetch character (type)
574 JZ INPUT_ERROR
575 MOV AH, BP_WATCHPOINT_R
576 CMP AL, "R"
577 JE SHORT CMD_WATCH_2
578 MOV AH, BP_WATCHPOINT_W
579 CMP AL, "W"
580 JE SHORT CMD_WATCH_2
581 MOV AH, BP_WATCHPOINT_X
582 CMP AL, "X"
583 JNE INPUT_ERROR
584CMD_WATCH_2: MOV WP_TYPE, AH
585 CALL SKIP
586 MOV DX, I_DS
587 CALL GET_ADDR ; Get address
588 JC INPUT_ERROR
589 CALL END_OF_LINE
590 JNZ INPUT_ERROR
591 MOV BH, WP_LEN
592 MOV BL, WP_TYPE
593 TEST AL, BH
594 JNZ ALIGNMENT_ERROR
595 CALL SET_WATCHPOINT ; Set watchpoint
596 JNZ INPUT_ERROR
597 CALL SHOW_BREAKPOINT
598 JMP KEY ; Command loop
599
600;
601; Breakpoint command
602;
603CMD_BREAK: CALL INPUT ; Input arguments
604 JC INPUT_ERROR
605 CALL END_OF_LINE ; Any arguments?
606 JZ CMD_BREAK_SHOW ; No -> display breakpoints
607 MOV DX, I_CS
608 CALL GET_ADDR ; Get address
609 JC INPUT_ERROR
610 CALL END_OF_LINE
611 JNZ INPUT_ERROR
612 MOV BH, 0
613 MOV BL, BP_BREAKPOINT
614 CALL SET_WATCHPOINT ; Set breakpoint
615 JNZ INPUT_ERROR
616 CALL SHOW_BREAKPOINT
617 JMP KEY ; Command loop
618
619CMD_BREAK_SHOW: LEA SI, BREAKPOINTS
620 MOV CX, 4
621CBS_1: CALL SHOW_BREAKPOINT
622 ADD SI, SIZE BREAKPOINT
623 LOOP CBS_1
624 JMP KEY
625
626;
627; Delete breakpoint
628;
629CMD_KILL: CALL INPUT ; Input arguments
630 JC INPUT_ERROR
631 CALL END_OF_LINE ; Any arguments?
632 JZ CMD_BREAK_SHOW ; No -> display breakpoints
633 CALL FETCH ; Fetch character (number)
634 JZ INPUT_ERROR ; End of line -> error
635 SUB AL, "0"
636 CMP AL, 3
637 JA INPUT_ERROR
638 MOV AH, SIZE BREAKPOINT
639 MUL AH
640 LEA SI, BREAKPOINTS
641 ADD SI, AX
642 CALL SKIP
643 CALL END_OF_LINE
644 JNZ INPUT_ERROR
645 MOV (BREAKPOINT PTR [SI]).BP_TYPE, BP_INACTIVE
646 JMP KEY
647
648
649;
650; Display breakpoint entry
651;
652; In: DS:SI Pointer to breakpoint entry
653;
654 ASSUME SI:PTR BREAKPOINT
655SHOW_BREAKPOINT PROC NEAR
656 CMP [SI].BP_TYPE, BP_INACTIVE
657 JE SBP_RET
658 LEA AX, BREAKPOINTS
659 SUB AX, SI
660 NEG AX
661 MOV BX, SIZE BREAKPOINT
662 XOR DX, DX
663 DIV BX
664 ADD AL, "0"
665 CALL GCHAR
666 MOV AL, " "
667 CALL GCHAR
668 MOV AL, "B"
669 CMP [SI].BP_TYPE, BP_BREAKPOINT
670 JE SHORT SBP_1
671 MOV AL, "R"
672 CMP [SI].BP_TYPE, BP_WATCHPOINT_R
673 JE SHORT SBP_1
674 MOV AL, "W"
675 CMP [SI].BP_TYPE, BP_WATCHPOINT_W
676 JE SHORT SBP_1
677 MOV AL, "X"
678 CMP [SI].BP_TYPE, BP_WATCHPOINT_X
679 JE SHORT SBP_1
680 MOV AL, "?"
681SBP_1: CALL GCHAR
682 CMP AL, "B"
683 MOV AL, " "
684 JE SHORT SBP_2
685 MOV AL, "B"
686 CMP [SI].BP_LEN, 00H
687 JE SHORT SBP_2
688 MOV AL, "W"
689 CMP [SI].BP_LEN, 01H
690 JE SHORT SBP_2
691 MOV AL, "D"
692 CMP [SI].BP_LEN, 03H
693 JE SHORT SBP_2
694 MOV AL, "?"
695SBP_2: CALL GCHAR
696 MOV AL, " "
697 CALL GCHAR
698 MOV AX, [SI].BP_SEL
699 CALL GWORD
700 MOV AL, ":"
701 CALL GCHAR
702 MOV EAX, [SI].BP_OFF
703 CALL GDWORD
704 MOV AL, " "
705 CALL GCHAR
706 MOV EAX, [SI].BP_ADDR
707 CALL GDWORD
708 CALL GCRLF
709SBP_RET: RET
710 ASSUME SI:NOTHING
711SHOW_BREAKPOINT ENDP
712
713
714;
715; Unassemble
716;
717CMD_UNASSEMBLE: CALL INPUT
718 JC INPUT_ERROR
719 MOV DX, U_LAST_SEL
720 OR DX, DX
721 JZ SHORT UAS01
722 CALL END_OF_LINE
723 MOV EAX, U_LAST_OFF
724 JZ UAS02
725UAS01: MOV DX, I_CS
726 CALL GET_ADDR
727 JC INPUT_ERROR
728 CALL END_OF_LINE
729 JNZ INPUT_ERROR
730UAS02: VERR DX
731 JNZ INVALID_SEL
732 MOV FS, DX
733 MOV ESI, EAX
734 MOV CX, 16
735 MOV DA_EMPTY_FLAG, FALSE
736UAS1: CMP DA_EMPTY_FLAG, FALSE
737 JE SHORT UAS2
738 MOV DA_EMPTY_FLAG, FALSE
739 CALL GCRLF
740 JMP SHORT UAS3
741UAS2: PUSH CX
742 CALL SHOW_DISASM
743 POP CX
744UAS3: LOOP UAS1
745 MOV U_LAST_SEL, FS
746 MOV U_LAST_OFF, ESI
747 JMP KEY
748
749CMD_DISPLAY: CALL INPUT
750 JC INPUT_ERROR
751 MOV DX, D_LAST_SEL
752 OR DX, DX
753 JZ SHORT DISP00
754 CALL END_OF_LINE
755 MOV EAX, D_LAST_OFF
756 MOV ECX, 16
757 JZ SHORT DISP02
758DISP00: MOV DX, I_DS
759 CALL GET_ADDR
760 JC INPUT_ERROR
761 CALL END_OF_LINE
762 JZ SHORT DISP01
763 CALL GET_RANGE_MORE
764 JC ERROR
765 CALL END_OF_LINE
766 JNZ INPUT_ERROR
767 ADD ECX, 15
768 SHR ECX, 4
769 JMP SHORT DISP02
770DISP01: VERR DX
771 JNZ INVALID_SEL
772 MOV ECX, 16
773DISP02: MOV FS, DX
774 MOV ESI, EAX
775DISP10: CALL SHOW_DATA
776 ADD ESI, 16
777 DEC ECX
778 JNZ DISP10
779 MOV D_LAST_SEL, FS
780 MOV D_LAST_OFF, ESI
781 JMP KEY
782
783CMD_REG: CALL INPUT
784 JC INPUT_ERROR
785 CALL END_OF_LINE
786 JZ CMD_DOT
787 PUSH BX
788 CALL FETCH
789 JZ SHORT REG10
790 MOV AH, AL
791 CALL FETCH
792 JZ SHORT REG10
793 CALL SKIP
794 CALL END_OF_LINE
795 JNZ SHORT REG10
796 XCHG AL, AH
797 LEA BX, FLAG_TAB
798REG01: MOV CX, [BX+0]
799 JCXZ REG10
800 CMP AX, [BX+2]
801 JE SHORT REG02
802 CMP AX, [BX+4]
803 JE SHORT REG03
804 ADD BX, 6
805 JMP SHORT REG01
806
807REG02: NOT CX
808 AND WORD PTR I_EFLAGS, CX
809 JMP SHORT REG04
810
811REG03: OR WORD PTR I_EFLAGS, CX
812REG04: POP BX
813 JMP KEY
814
815REG10: POP BX
816 PUSH BX
817 CALL GET_REG
818 JC SHORT REG20
819 MOV CL, AL
820 MOV DI, DX
821 CMP BYTE PTR [BX], " "
822 JNE SHORT REG20
823 CALL SKIP
824 CALL GET_NUMBER
825 JC SHORT REG20
826 CALL SKIP
827 CALL END_OF_LINE
828 JNZ SHORT REG20
829;
830; CL = R8, R16, R32
831; DI = pointer to register in stack
832; EAX = value
833;
834 CMP CL, R8
835 JE SHORT REG10_8
836 CMP CL, R16
837 JE SHORT REG10_16
838 CMP CL, R32
839 JNE SHORT REG20
840REG10_32: MOV SS:[DI], EAX
841 JMP SHORT REG11
842REG10_16: TEST EAX, NOT 0FFFFH
843 JNZ SHORT REG10_ERROR
844 MOV SS:[DI], AX
845 JMP SHORT REG11
846REG10_8: TEST EAX, NOT 0FFH
847 JNZ SHORT REG10_ERROR
848 MOV SS:[DI], AL
849REG11: POP BX
850 JMP KEY
851
852REG10_ERROR: POP BX
853 JMP SHORT INPUT_ERROR
854
855REG20: POP BX
856 JMP SHORT INPUT_ERROR
857
858ALIGNMENT_ERROR:
859 LEA EDX, $ALIGNMENT
860 JMP SHORT ERROR
861
862BEYOND_LIMIT: LEA EDX, $BEYOND_LIMIT
863 JMP SHORT ERROR
864
865INVALID_SEL: LEA EDX, $INVALID_SEL
866 JMP SHORT ERROR
867
868INPUT_ERROR: LEA EDX, $INPUT_ERROR
869ERROR: CALL GTEXT
870 JMP KEY
871
872
873 IF FLOATING_POINT
874CMD_387: MOV SI, PROCESS_PTR
875 CMP SI, NO_PROCESS
876 JE BAD_KEY
877 ASSUME SI:PTR PROCESS
878 DB 66H
879 FNSAVE DWORD PTR [SI].P_CW ; Save FPU context, initialize
880 FWAIT
881 MOV DX, [SI].P_TW
882 MOV CX, [SI].P_SW
883 SHR CX, 11
884 AND CX, 7
885 ROR DX, CL
886 ROR DX, CL
887 LEA DI, [SI].P_FST
888 MOV CX, 8
889FPU_1: PUSH DX
890 MOV AL, "S"
891 CALL GCHAR
892 MOV AL, "T"
893 CALL GCHAR
894 MOV AL, "("
895 CALL GCHAR
896 MOV AL, "8"
897 SUB AL, CL
898 CALL GCHAR
899 MOV AL, ")"
900 CALL GCHAR
901 MOV AL, "="
902 CALL GCHAR
903 MOV AX, DX
904 AND AX, 3
905 LEA EDX, $ZERO
906 DEC AX
907 JZ SHORT FPU_2
908 LEA EDX, $INFINITY
909 DEC AX
910 JZ SHORT FPU_2
911 LEA EDX, $EMPTY
912 DEC AX
913 JZ SHORT FPU_2
914 PUSH CX
915 PUSH DI
916 MOV CX, 10
917 ADD DI, CX
918FPU_VALID_1: DEC DI
919 MOV AL, [DI]
920 CALL GBYTE
921 LOOP FPU_VALID_1
922 POP DI
923 POP CX
924 JMP SHORT FPU_3
925FPU_2: CALL GTEXT
926FPU_3: CALL GCRLF
927 POP DX
928 ROR DX, 2
929 ADD DI, 10
930 LOOP FPU_1
931 LEA EDX, $CW
932 CALL GTEXT
933 MOV AX, [SI].P_CW
934 CALL GWORD
935 LEA EDX, $SW
936 CALL GTEXT
937 MOV AX, [SI].P_SW
938 CALL GWORD
939 LEA EDX, $C3210
940 CALL GTEXT
941 MOV DX, 4000H
942 CALL FPU_C
943 MOV DX, 0400H
944 CALL FPU_C
945 MOV DX, 0200H
946 CALL FPU_C
947 MOV DX, 0100H
948 CALL FPU_C
949 MOV AX, [SI].P_SW
950 AND AX, 4500H
951 MOV DL, ">"
952 JZ SHORT FPU_4
953 CMP AX, 0100H
954 MOV DL, "<"
955 JE SHORT FPU_4
956 CMP AX, 4000H
957 JNE SHORT FPU_5
958 MOV DL, "="
959FPU_4: MOV AL, " "
960 CALL GCHAR
961 MOV AL, DL
962 CALL GCHAR
963FPU_5: CALL GCRLF
964 DB 66H
965 FRSTOR DWORD PTR [SI].P_CW
966 JMP KEY
967
968FPU_C PROC NEAR
969 MOV AL, "0"
970 TEST [SI].P_SW, DX
971 JZ SHORT FPU_C_1
972 INC AL
973FPU_C_1: CALL GCHAR
974 RET
975FPU_C ENDP
976
977 ASSUME SI:NOTHING
978
979 ELSE
980
981CMD_387: JMP BAD_KEY
982
983 ENDIF
984
985
986CMD_STEP: MOV FS, I_CS
987 MOV ESI, I_EIP
988 CALL GET_INST
989 CMP AL, 0CCH ; INT 3
990 JNE SHORT CMD_STEP_1
991 MOV I_EIP, ESI ; Skip INT 3
992 CALL GET_INST
993CMD_STEP_1: CMP AL, 0CDH ; INT n
994 JE SHORT DO_CALL
995;
996; Single-step program
997;
998DO_STEP: CMP DEBUG_FLAG, FALSE
999 JE SHORT DO_STEP_0
1000 LEA EDX, $DO_STEP
1001 CALL GTEXT
1002DO_STEP_0: CALL DEBUG_STEP ; Set single step mode
1003 MOV SKIP_FLAG, NOT FALSE ; Ignore breakpoint at CS:EIP
1004 CALL INS_BREAKPOINTS ; Insert breakpoints
1005 MOV SKIP_FLAG, FALSE ; Restore original value
1006 JMP RUN ; Continue program
1007
1008;
1009; Set breakpoint after current instruction, continue program
1010;
1011CMD_CALL: MOV FS, I_CS
1012 MOV ESI, I_EIP
1013 CALL GET_INST
1014 CMP AL, 0CCH ; INT 3
1015 JNE SHORT CMD_CALL_1
1016 MOV I_EIP, ESI ; Skip INT 3
1017 CALL GET_INST
1018CMD_CALL_1: CMP AL, 0C2H ; RETN immed
1019 JE SHORT DO_STEP
1020 CMP AL, 0C3H ; RETN
1021 JE SHORT DO_STEP
1022 CMP AL, 0CAH ; RETF immed
1023 JE SHORT DO_STEP
1024 CMP AL, 0CBH ; RETF
1025 JE SHORT DO_STEP
1026 CMP AL, 0CFH ; IRET/IRETD
1027 JE SHORT DO_STEP
1028 CMP AL, 0E9H ; JMP NEAR
1029 JE SHORT DO_STEP
1030 CMP AL, 0EAH ; JMP FAR
1031 JE SHORT DO_STEP
1032 CMP AL, 0EBH ; JMP SHORT
1033 JE SHORT DO_STEP
1034 CMP AL, 0FFH
1035 JE SHORT CMD_CALL_FF ; JMP reg/mem ?
1036DO_CALL: CMP DEBUG_FLAG, FALSE
1037 JE SHORT DO_CALL_0
1038 LEA EDX, $DO_CALL
1039 CALL GTEXT
1040DO_CALL_0: MOV FS, I_CS
1041 MOV ESI, I_EIP
1042 MOV ECX, ESI ; No relocation
1043 LEA DI, DISASM_BUF
1044 CALL GET_MODE
1045 CALL DISASM
1046 MOV DX, I_CS
1047 MOV EAX, ESI
1048 CALL SET_BREAKPOINT
1049 JMP CONTINUE
1050
1051CMD_CALL_FF: MOV AL, FS:[ESI] ; Get mod reg r/m byte
1052 AND AL, 7 SHL 3
1053 CMP AL, 4 SHL 3 ; JMP DWORD PTR reg/mem
1054 JE DO_STEP
1055 CMP AL, 5 SHL 3 ; JMP FWORD PTR reg/mem
1056 JE DO_STEP
1057 JMP SHORT DO_CALL
1058
1059CMD_SEARCH: CALL INPUT
1060 JC INPUT_ERROR
1061 CALL END_OF_LINE
1062 JZ INPUT_ERROR ; Future expansion: cont.
1063 MOV DX, I_DS
1064 CALL GET_RANGE
1065 JC ERROR
1066 MOV SEARCH_SEL, DX
1067 MOV SEARCH_OFF, EAX
1068 MOV SEARCH_LEN, ECX
1069 MOV SEARCH_SIZE, 0
1070 LEA DI, SEARCH_BUF
1071CMD_SEARCH_01: CALL END_OF_LINE
1072 JZ SHORT CMD_SEARCH_09
1073 CMP SEARCH_SIZE, LENGTH SEARCH_BUF
1074 JAE INPUT_ERROR
1075 CMP BYTE PTR [BX], "'"
1076 JE SHORT CMD_SEARCH_02
1077 CALL GET_NUMBER
1078 JC INPUT_ERROR
1079 TEST EAX, NOT 0FFH
1080 JNZ INPUT_ERROR
1081 MOV [DI], AL
1082 INC DI
1083 INC SEARCH_SIZE
1084 CALL SKIP
1085 JMP SHORT CMD_SEARCH_01
1086
1087CMD_SEARCH_02: INC BX
1088 MOV AL, [BX]
1089 CMP AL, "'"
1090 JE SHORT CMD_SEARCH_04
1091CMD_SEARCH_03: CALL END_OF_LINE
1092 JZ INPUT_ERROR
1093 MOV AL, [BX]
1094 INC BX
1095 CMP AL, "'"
1096 JE SHORT CMD_SEARCH_05
1097CMD_SEARCH_04: CMP SEARCH_SIZE, LENGTH SEARCH_BUF
1098 JAE INPUT_ERROR
1099 MOV [DI], AL
1100 INC DI
1101 INC SEARCH_SIZE
1102 JMP SHORT CMD_SEARCH_03
1103
1104CMD_SEARCH_05: CALL DELIM
1105 JNZ INPUT_ERROR
1106 CALL SKIP
1107 JMP SHORT CMD_SEARCH_01
1108
1109CMD_SEARCH_09: CMP SEARCH_SIZE, 0
1110 JE INPUT_ERROR
1111CMD_SEARCH_10: MOV ES, SEARCH_SEL
1112CMD_SEARCH_11: MOV EDI, SEARCH_OFF
1113 MOV ECX, SEARCH_LEN
1114 MOV AL, SEARCH_BUF[0]
1115 REPNE SCAS BYTE PTR ES:[EDI]
1116 JNE SHORT CMD_SEARCH_99
1117 MOV SEARCH_OFF, EDI
1118 MOV SEARCH_LEN, ECX
1119 INC ECX
1120 CMP ECX, SEARCH_SIZE
1121 JB SHORT CMD_SEARCH_99
1122 MOV ECX, SEARCH_SIZE
1123 DEC ECX
1124 JZ SHORT CMD_SEARCH_12
1125 LEA ESI, SEARCH_BUF+1
1126 REPE CMPS BYTE PTR DS:[ESI], ES:[EDI]
1127 JNE SHORT CMD_SEARCH_11
1128CMD_SEARCH_12: MOV ESI, SEARCH_OFF
1129 DEC ESI
1130 MOV FS, SEARCH_SEL
1131 CALL SHOW_DATA
1132 JMP SHORT CMD_SEARCH_10
1133
1134CMD_SEARCH_99: JMP KEY
1135
1136;
1137; A command
1138;
1139CMD_ADDR: CALL INPUT
1140 JC INPUT_ERROR
1141 CALL END_OF_LINE
1142 JZ INPUT_ERROR
1143 MOV DX, I_DS
1144 CALL GET_ADDR
1145 JC INPUT_ERROR
1146 MOV ADDR_COUNT, 0
1147 CALL END_OF_LINE
1148 JZ SHORT ADDR_1
1149 CALL GET_RANGE_MORE
1150 JC INPUT_ERROR
1151 CALL END_OF_LINE
1152 JNZ INPUT_ERROR
1153 MOV ADDR_COUNT, ECX
1154ADDR_1: MOV ADDR_SEL, DX
1155 MOV ADDR_OFF, EAX
1156 VERR DX
1157 JNZ INVALID_SEL
1158ADDR_LOOP: MOVZX EDX, ADDR_SEL
1159 LSL ECX, EDX
1160 CMP EAX, ECX
1161 JA BEYOND_LIMIT
1162 MOV AX, ADDR_SEL
1163 CALL GWORD
1164 MOV AL, ":"
1165 CALL GCHAR
1166 MOV EAX, ADDR_OFF
1167 CALL GDWORD
1168 MOV AL, " "
1169 CALL GCHAR
1170 MOV AX, ADDR_SEL
1171 MOV EBX, ADDR_OFF
1172 CALL GET_LIN
1173 LEA EDX, $ADDR_FAILURE
1174 JC SHORT ADDR_MSG
1175 MOV ADDR_LIN, EBX
1176 LEA EDX, $LINEAR
1177 CALL GTEXT
1178 CALL SHOW_LIN
1179ADDR_NEXT: ADD ADDR_OFF, 1000H
1180 SUB ADDR_COUNT, 1000H
1181 JA ADDR_LOOP
1182 JMP KEY
1183
1184ADDR_MSG: CALL GTEXT
1185 JMP SHORT ADDR_NEXT
1186
1187;
1188; V command
1189;
1190CMD_VIRT: CALL INPUT
1191 JC INPUT_ERROR
1192 CALL END_OF_LINE
1193 JZ INPUT_ERROR
1194 MOV AL, [BX]
1195 CALL UPPER
1196 LEA DI, V_PHYS
1197 CMP AL, "P"
1198 JE VIRT_SCAN
1199 LEA DI, V_EXT
1200 CMP AL, "X"
1201 JE VIRT_SCAN
1202 CALL GET_NUMBER
1203 JC INPUT_ERROR
1204 MOV ADDR_LIN, EAX
1205 MOV ADDR_COUNT, 0
1206 CALL SKIP
1207 CALL END_OF_LINE
1208 JZ SHORT VIRT_LOOP
1209 CALL GET_NUMBER
1210 JC INPUT_ERROR
1211 CALL END_OF_LINE
1212 JNZ INPUT_ERROR
1213 SUB EAX, ADDR_LIN
1214 JB INPUT_ERROR
1215 INC EAX
1216 MOV ADDR_COUNT, EAX
1217VIRT_LOOP: CALL SHOW_LIN
1218 ADD ADDR_LIN, 1000H
1219 SUB ADDR_COUNT, 1000H
1220 JA VIRT_LOOP
1221 JMP KEY
1222
1223;
1224; VP and VX commands
1225;
1226VIRT_SCAN: MOV LIST_ALL, NOT FALSE
1227 MOV ADDR_COUNT, 0
1228 INC BX
1229 CALL SKIP
1230 CALL END_OF_LINE
1231 JZ SHORT VSCAN_1
1232 MOV LIST_ALL, FALSE
1233 CALL GET_NUMBER
1234 JC INPUT_ERROR
1235 MOV ADDR_ARG, EAX
1236 CALL SKIP
1237 CALL END_OF_LINE
1238 JZ SHORT VSCAN_1
1239 CALL GET_NUMBER
1240 JC INPUT_ERROR
1241 CALL END_OF_LINE
1242 JNZ INPUT_ERROR
1243 SUB EAX, ADDR_ARG
1244 JB INPUT_ERROR
1245 INC EAX
1246 MOV ADDR_COUNT, EAX
1247VSCAN_1: AND ADDR_ARG, NOT 0FFFH
1248VSCAN_LOOP: CALL SCAN_PAGE_TABLES
1249 ADD ADDR_ARG, 1000H
1250 SUB ADDR_COUNT, 1000H
1251 JA VSCAN_LOOP
1252 JMP KEY
1253
1254V_PHYS PROC NEAR
1255 TEST AX, PAGE_PRESENT OR PAGE_ALLOC
1256 JZ SHORT V_PHYS_RET
1257 CMP LIST_ALL, FALSE
1258 JNE SHORT V_PHYS_SHOW
1259 AND EAX, NOT 0FFFH
1260 CMP EAX, ADDR_ARG
1261 JNE SHORT V_PHYS_RET
1262V_PHYS_SHOW: CALL SHOW_LIN
1263V_PHYS_RET: RET
1264V_PHYS ENDP
1265
1266V_EXT PROC NEAR
1267 TEST DX, SWAP_ALLOC
1268 JNZ SHORT V_EXT_CMP
1269 MOV AX, DX
1270 AND AX, SRC_MASK
1271 CMP AX, SRC_EXEC
1272 JNE SHORT V_EXT_RET
1273V_EXT_CMP: CMP LIST_ALL, FALSE
1274 JNE SHORT V_EXT_SHOW
1275 AND EDX, NOT 0FFFH
1276 CMP EDX, ADDR_ARG
1277 JNE SHORT V_EXT_RET
1278V_EXT_SHOW: CALL SHOW_LIN
1279V_EXT_RET: RET
1280V_EXT ENDP
1281
1282
1283
1284SEL_TAB DW SEL_INVALID ; 0000 undefined
1285 DW SEL_TSS ; 0001 16-bit TSS
1286 DW SEL_LDT ; 0010 LDT
1287 DW SEL_TSS ; 0011 16-bit TSS (busy)
1288 DW SEL_CALL ; 0100 16-bit call gate
1289 DW SEL_TASK ; 0101 task gate
1290 DW SEL_INT ; 0110 16-bit interrupt gate
1291 DW SEL_TRAP ; 0111 16-bit trap gate
1292 DW SEL_INVALID ; 1000 undefined
1293 DW SEL_TSS ; 1001 32-bit TSS
1294 DW SEL_INVALID ; 1010 undefined
1295 DW SEL_TSS ; 1011 32-bit TSS (busy)
1296 DW SEL_CALL ; 1100 32-bit call gate
1297 DW SEL_INVALID ; 1101 undefined
1298 DW SEL_INT ; 1110 32-bit interrupt gate
1299 DW SEL_TRAP ; 1111 32-bit trap gate
1300
1301CMD_SELECTOR: CALL INPUT
1302 JC INPUT_ERROR
1303 CALL END_OF_LINE
1304 JZ INPUT_ERROR
1305 CALL GET_NUMBER
1306 JC INPUT_ERROR
1307 TEST EAX, NOT 0FFFFH
1308 JNZ INPUT_ERROR
1309 MOV SEL_SEL, AX
1310 MOV SEL_COUNT, 0
1311 CALL SKIP
1312 CALL END_OF_LINE
1313 JZ SHORT SEL_1
1314 CALL GET_NUMBER
1315 JC INPUT_ERROR
1316 SUB AX, SEL_SEL
1317 JB INPUT_ERROR
1318 SHR AX, 3
1319 INC AX
1320 MOV SEL_COUNT, AX
1321 CALL SKIP
1322 CALL END_OF_LINE
1323 JNZ INPUT_ERROR
1324SEL_1:
1325SEL_LOOP: MOV AX, SEL_SEL
1326 CALL GWORD
1327 LEA EDX, $RPL
1328 CALL GTEXT
1329 MOV AX, SEL_SEL
1330 AND AL, 03H
1331 ADD AL, "0"
1332 CALL GCHAR
1333 MOV AX, SEL_SEL
1334 LEA EDX, $TI_GDT
1335 MOV DI, G_GDT_MEM_SEL
1336 LEA SI, GDT
1337 TEST AX, 04H
1338 JZ SHORT SEL_2
1339 SLDT DI
1340 MOV SI, DI
1341 AND SI, NOT 07H
1342 SUB SI, G_LDT_SEL
1343 IMUL SI, LDT_ENTRIES
1344 LEA SI, LDTS[SI]
1345 LEA EDX, $TI_LDT
1346SEL_2: CALL GTEXT
1347 AND DI, NOT 07H
1348 MOV AX, WORD PTR GDT[DI] ; ... ignore limit 16..19, G
1349 MOV BX, SEL_SEL
1350 OR BX, 07H
1351 CMP BX, AX
1352 JA SEL_INVALID
1353 AND BX, NOT 07H
1354 JZ SEL_NULL
1355 ADD SI, BX
1356 MOV BX, [SI+5]
1357 TEST BX, 10H ; D1
1358 JNZ SHORT SEL_SEG
1359 MOV DI, BX
1360 AND DI, 0FH
1361 SHL DI, 1
1362 JMP SEL_TAB[DI]
1363
1364SEL_LDT: LEA EDX, $LDT
1365 CALL GTEXT
1366 CALL SEL_DPL_P
1367 JMP SHORT SEL_SEG_1
1368
1369;
1370; It's a segment
1371;
1372SEL_SEG: TEST BX, 08H ; Code segment?
1373 JNZ SHORT SEL_CODE
1374 LEA EDX, $DATA
1375 CALL GTEXT
1376 CALL SEL_DPL_P
1377 MOV AL, "A"
1378 TEST BX, 01H ; Accessed
1379 CALL SHOW_BIT
1380 MOV AL, "W"
1381 TEST BX, 02H ; Writable?
1382 CALL SHOW_BIT
1383 MOV AL, "E"
1384 TEST BX, 04H ; Expand down?
1385 CALL SHOW_BIT
1386 MOV AL, "B"
1387 TEST BX, 4000H ; Big?
1388 CALL SHOW_BIT
1389SEL_SEG_1: MOV AL, "G"
1390 TEST BX, 8000H ; Granularity?
1391 CALL SHOW_BIT
1392 LEA EDX, $BASE
1393 CALL GTEXT
1394 MOV AH, [SI+7]
1395 MOV AL, [SI+4]
1396 SHL EAX, 16
1397 MOV AX, [SI+2]
1398 CALL GDWORD
1399 LEA EDX, $LIMIT
1400 CALL GTEXT
1401 MOV AL, [SI+6]
1402 AND AX, 0FH
1403 SHL EAX, 16
1404 MOV AX, [SI+0]
1405 TEST BX, 8000H ; Granularity
1406 JZ SHORT SEL_LIMIT_1
1407 SHL EAX, 12
1408 OR EAX, 0FFFH
1409SEL_LIMIT_1: CALL GDWORD
1410 JMP SEL_DONE
1411
1412SEL_CODE: LEA EDX, $CODE
1413 CALL GTEXT
1414 CALL SEL_DPL_P
1415 MOV AL, "A"
1416 TEST BX, 01H ; Accessed
1417 CALL SHOW_BIT
1418 MOV AL, "R"
1419 TEST BX, 02H ; Readable?
1420 CALL SHOW_BIT
1421 MOV AL, "C"
1422 TEST BX, 04H ; Conforming?
1423 CALL SHOW_BIT
1424 MOV AL, "D"
1425 TEST BX, 4000H ; Default?
1426 CALL SHOW_BIT
1427 JMP SEL_SEG_1
1428
1429SEL_TRAP: LEA EDX, $TRAP
1430 JMP SHORT SEL_INT_1
1431
1432SEL_INT: LEA EDX, $INT
1433SEL_INT_1: CALL SEL_16_32
1434 CALL GTEXT
1435 CALL SEL_DPL_P
1436 MOV AX, [SI+2]
1437 CALL GWORD
1438 MOV AL, ":"
1439 CALL GCHAR
1440 XOR EAX, EAX
1441 TEST BX, 08H
1442 JZ SHORT SEL_INT_2
1443 MOV AX, [SI+6]
1444 SHL EAX, 16
1445SEL_INT_2: MOV AX, [SI+0]
1446 CALL GDWORD
1447 JMP SEL_DONE
1448
1449SEL_TSS: CALL SEL_16_32
1450 LEA EDX, $TSS
1451 CALL GTEXT
1452 CALL SEL_DPL_P
1453 MOV AL, "B"
1454 TEST BX, 02H ; Busy
1455 CALL SHOW_BIT
1456 JMP SEL_SEG_1
1457
1458SEL_CALL: CALL SEL_16_32
1459 LEA EDX, $CALL
1460 CALL GTEXT
1461 CALL SEL_DPL_P
1462 MOV AX, [SI+2]
1463 CALL GWORD
1464 MOV AL, ":"
1465 CALL GCHAR
1466 XOR EAX, EAX
1467 TEST BX, 08H
1468 JZ SHORT SEL_CALL_1
1469 MOV AX, [SI+6]
1470 SHL EAX, 16
1471SEL_CALL_1: MOV AX, [SI+0]
1472 CALL GDWORD
1473 MOV AL, " "
1474 MOV AL, [SI+4]
1475 AND AL, 0FH
1476 CALL GBYTE
1477 JMP SHORT SEL_DONE
1478
1479SEL_TASK: LEA EDX, $TASK
1480 CALL GTEXT
1481 CALL SEL_DPL_P
1482 MOV AX, [SI+2]
1483 CALL GWORD
1484 JMP SHORT SEL_DONE
1485
1486SEL_NULL: LEA EDX, $NULL
1487 CALL GTEXT
1488 JMP SHORT SEL_DONE
1489
1490SEL_INVALID: LEA EDX, $SEL_INVALID
1491 CALL GTEXT
1492SEL_DONE: CALL GCRLF
1493 ADD SEL_SEL, 8
1494 SUB SEL_COUNT, 1
1495 JA SEL_LOOP
1496 JMP KEY
1497
1498
1499SEL_16_32 PROC NEAR
1500 PUSH EDX
1501 LEA EDX, $SEL_32
1502 TEST BX, 08H
1503 JNZ SHORT SEL_16_32_1
1504 LEA EDX, $SEL_16
1505SEL_16_32_1: CALL GTEXT
1506 POP EDX
1507 RET
1508SEL_16_32 ENDP
1509
1510SEL_DPL_P PROC NEAR
1511 PUSH EDX
1512 LEA EDX, $DPL
1513 CALL GTEXT
1514 MOV AX, BX
1515 SHR AX, 5
1516 AND AL, 03H
1517 ADD AL, "0"
1518 CALL GCHAR
1519 MOV AL, " "
1520 CALL GCHAR
1521 MOV AL, "P"
1522 TEST BX, 80H
1523 CALL SHOW_BIT
1524 MOV AL, " "
1525 CALL GCHAR
1526 POP EDX
1527 RET
1528SEL_DPL_P ENDP
1529
1530;
1531; Quit
1532;
1533CMD_QUIT: CALL INPUT
1534 JC INPUT_ERROR
1535 CALL END_OF_LINE
1536 MOV AL, 0
1537 JZ CMD_QUIT_0
1538 CALL GET_NUMBER
1539 JC INPUT_ERROR
1540 TEST EAX, NOT 0FFH
1541 JNZ INPUT_ERROR
1542CMD_QUIT_0: MOV AH, 4CH
1543 INT 21H
1544 JMP SHORT $
1545
1546
1547;
1548; Symbol
1549;
1550CMD_SYM: CALL INPUT
1551 JC INPUT_ERROR
1552 CALL GET_NUMBER
1553 JC INPUT_ERROR
1554 MOV EDX, EAX
1555 CALL END_OF_LINE
1556 JNZ INPUT_ERROR
1557 MOV DI, PROCESS_PTR
1558 CALL SYM_BEFORE
1559 JC KEY
1560 CALL GDWORD
1561 MOV AL, " "
1562 CALL GCHAR
1563 CALL PRINT_SYM
1564 CALL GCRLF
1565 JMP KEY
1566
1567;
1568; Info
1569;
1570CMD_INFO: CALL INPUT
1571 JC INPUT_ERROR
1572 CALL END_OF_LINE
1573 JNZ INPUT_ERROR
1574 LEA EDX, $INFO_TITLE
1575 CALL GTEXT
1576 LEA BX, PROCESS_TABLE
1577 ASSUME BX:PTR PROCESS
1578 MOV CX, MAX_PROCESSES + 1
1579INFO_10: CMP [BX].P_STATUS, PS_NONE ; Empty slot?
1580 JE SHORT INFO_19
1581 MOV AL, [BX].P_PIDX
1582 CALL GBYTE
1583 MOV AL, " "
1584 CMP BX, PROCESS_PTR
1585 JNE SHORT INFO_13
1586 MOV AL, "*"
1587INFO_13: CALL GCHAR
1588 MOV AL, " "
1589 CALL GCHAR
1590 MOV EAX, [BX].P_PID
1591 CALL GDWORD
1592 MOV AL, " "
1593 CALL GCHAR
1594 MOV EAX, [BX].P_PPID
1595 CALL GDWORD
1596;
1597; File handles
1598;
1599 MOV SI, 0
1600INFO_LOOP_HANDLE:
1601 MOV AL, " "
1602 CALL GCHAR
1603 MOV AX, [BX].P_HANDLES[SI]
1604 CMP AX, NO_FILE_HANDLE
1605 JE SHORT INFO_NO_HANDLE
1606 AAM
1607 XCHG AL, AH
1608 ADD AL, "0"
1609 CALL GCHAR
1610 XCHG AL, AH
1611 ADD AL, "0"
1612 CALL GCHAR
1613 JMP SHORT INFO_NEXT_HANDLE
1614
1615INFO_NO_HANDLE: MOV AL, "-"
1616 CALL GCHAR
1617 CALL GCHAR
1618INFO_NEXT_HANDLE:
1619 ADD SI, 2
1620 CMP SI, 2 * 19
1621 JB SHORT INFO_LOOP_HANDLE
1622 CALL GCRLF
1623;
1624; Next process table entry
1625;
1626INFO_19: ADD BX, SIZE PROCESS
1627 DEC CX
1628 JNZ INFO_10
1629 ASSUME BX:NOTHING
1630 CALL CHECK_HANDLES
1631 JMP KEY
1632
1633;
1634; Continue program
1635;
1636RUN: CMP DEBUG_FLAG, FALSE
1637 JE SHORT RUN_0
1638 LEA EDX, $RUN
1639 CALL GTEXT
1640RUN_0: JMP EXCEPT_RET
1641 ASSUME BP:NOTHING
1642DEBUG_EXCEPTION ENDP
1643
1644
1645;
1646; Get next instruction opcode byte, skip prefix bytes
1647;
1648; In: FS:ESI Pointer to code
1649;
1650; Out: AL Opcode byte
1651; ESI Points to next opcode byte
1652;
1653GET_INST PROC NEAR
1654GINST1: MOV AL, FS:[ESI]
1655 INC ESI
1656 CMP AL, 26H ; ES prefix
1657 JE SHORT GINST1
1658 CMP AL, 2EH ; CS prefix
1659 JE SHORT GINST1
1660 CMP AL, 36H ; SS prefix
1661 JE SHORT GINST1
1662 CMP AL, 3EH ; DS prefix
1663 JE SHORT GINST1
1664 CMP AL, 64H ; FS prefix
1665 JE SHORT GINST1
1666 CMP AL, 65H ; GS prefix
1667 JE SHORT GINST1
1668 CMP AL, 66H ; Operand size prefix
1669 JE SHORT GINST1
1670 CMP AL, 67H ; Adress size prefix
1671 JE SHORT GINST1
1672 CMP AL, 0F0H ; LOCK prefix
1673 JE SHORT GINST1
1674 CMP AL, 0F2H ; REP/REPNE prefix
1675 JE SHORT GINST1
1676 CMP AL, 0F3H ; REPE prefix
1677 JE SHORT GINST1
1678 RET
1679GET_INST ENDP
1680
1681;
1682; In: AL=0 Display empty line if jumped
1683; AL!=0 Don't display empty line
1684;
1685 ASSUME BP:PTR ISTACKFRAME
1686TRACE_DISASM PROC NEAR
1687 OR AL, AL ; Stopped?
1688 MOV AX, I_CS ; Get CS:EIP
1689 MOV ESI, I_EIP
1690 JNZ SHORT TDA2 ; Yes -> no empty line
1691 CMP AX, NEXT_CS ; Are we at next instruction?
1692 JNE SHORT TDA1 ; No -> empty line
1693 CMP ESI, NEXT_EIP
1694 JE SHORT TDA2 ; Yes -> no empty line
1695TDA1: CALL GCRLF ; Display empty line
1696TDA2: MOV FS, AX
1697 CALL SHOW_DISASM ; One line of disassembly
1698 MOV NEXT_CS, FS ; Remember address of
1699 MOV NEXT_EIP, ESI ; next instruction
1700 RET
1701 ASSUME BP:NOTHING
1702TRACE_DISASM ENDP
1703
1704
1705SHOW_DISASM PROC NEAR
1706 XOR EAX, EAX
1707 MOV AX, FS
1708 LSL EAX, EAX
1709 CMP ESI, EAX
1710 JA SDIS_RET
1711 PUSH ESI
1712 MOV ECX, ESI ; No relocation
1713 LEA DI, DISASM_BUF
1714 CALL GET_MODE
1715 CALL DISASM
1716 MOV DA_SYM_FLAG, AL
1717 MOV DA_EMPTY_FLAG, AH
1718 MOV DA_SYM_ADDR, EDX
1719 MOV AX, FS
1720 CMP AX, L_CODE_SEL ; Symbols only for L_CODE_SEL
1721 JNE SHORT SDIS_S9
1722 POP EDX
1723 PUSH EDX
1724 MOV AL, SYM_LINE
1725 MOV DI, PROCESS_PTR
1726 CALL SYM_BY_ADDR
1727 JC SHORT SDIS_S2
1728 POP EAX
1729 PUSH EAX
1730 PUSH DX
1731 MOV EDX, EAX
1732 CALL SYM_MODULE
1733 JC SHORT SDIS_S1
1734 CALL PRINT_SYM
1735SDIS_S1: LEA EDX, $LINE
1736 CALL GTEXT
1737 POP AX
1738 MOVZX EAX, AX
1739 CALL DECIMAL
1740 MOV AL, ":"
1741 CALL GCHAR
1742 CALL GCRLF
1743SDIS_S2: POP EDX
1744 PUSH EDX
1745 MOV AL, SYM_TEXT
1746 CALL SYM_BY_ADDR
1747 JC SHORT SDIS_S9
1748 CALL PRINT_SYM
1749 MOV AL, ":"
1750 CALL GCHAR
1751 CALL GCRLF
1752SDIS_S9: POP EBX
1753 MOV AX, FS
1754 CALL GWORD
1755 MOV AL, ":"
1756 CALL GCHAR
1757 MOV EAX, EBX
1758 CALL GDWORD
1759 MOV AL, " "
1760 CALL GCHAR
1761 MOV CX, 8
1762 LEA EDX, DISASM_BUF
1763SDIS1: CMP EBX, ESI
1764 JAE SHORT SDIS5
1765 OR CX, CX
1766 JNZ SHORT SDIS4
1767 CALL SDIS_DIS
1768 MOV AL, " "
1769 MOV CX, 14
1770SDIS2: CALL GCHAR
1771 LOOP SDIS2
1772 MOV CX, 8
1773SDIS4: MOV AL, FS:[EBX]
1774 CALL GBYTE
1775 INC EBX
1776 DEC CX
1777 JMP SHORT SDIS1
1778
1779SDIS5: JCXZ SDIS7
1780 MOV AL, " "
1781SDIS6: CALL GCHAR
1782 CALL GCHAR
1783 LOOP SDIS6
1784SDIS7: CALL SDIS_DIS
1785SDIS_RET: RET
1786
1787SDIS_DIS PROC NEAR
1788 PUSH EBX
1789 OR EDX, EDX
1790 JZ SHORT SDIS_DIS9
1791 MOV AL, " "
1792 CALL GCHAR
1793 CALL GTEXT
1794 MOV AX, FS
1795 CMP AX, L_CODE_SEL ; Symbols only for L_CODE_SEL
1796 JNE SHORT SDIS_DIS9
1797 MOV AL, DA_SYM_FLAG
1798 CMP AL, SYM_NONE
1799 JE SHORT SDIS_DIS9
1800 MOV EDX, DA_SYM_ADDR
1801 CMP EDX, 2
1802 JB SHORT SDIS_DIS9 ; Avoid symbols for 0, 1
1803 MOV DI, PROCESS_PTR
1804 CALL SYM_BY_ADDR
1805 JC SHORT SDIS_DIS9
1806 MOV AL, " "
1807 CALL GCHAR
1808 CALL GCHAR
1809 MOV AL, ";"
1810 CALL GCHAR
1811 MOV AL, " "
1812 CALL GCHAR
1813 CALL PRINT_SYM
1814SDIS_DIS9: CALL GCRLF
1815 XOR EDX, EDX
1816 POP EBX
1817 RET
1818SDIS_DIS ENDP
1819
1820SHOW_DISASM ENDP
1821
1822;
1823; Display a symbol
1824;
1825; In: ES:EBX Name of symbol
1826;
1827PRINT_SYM PROC NEAR
1828 PUSH EDX
1829 PUSH DI
1830 LEA DI, SYMBOL_BUF
1831PSYM1: MOV AL, ES:[EBX]
1832 MOV [DI], AL
1833 INC EBX
1834 INC DI
1835 OR AL, AL
1836 JNZ SHORT PSYM1
1837 LEA EDX, SYMBOL_BUF
1838 CALL GTEXT
1839 POP DI
1840 POP EDX
1841 RET
1842PRINT_SYM ENDP
1843
1844
1845;
1846; Get 16/32 mode for disassembler
1847;
1848; In: FS Segment register
1849;
1850; Out: AL 0:16, 1:32
1851; EAX Changed
1852;
1853GET_MODE PROC NEAR
1854 XOR EAX, EAX
1855 MOV AX, FS
1856 LAR EAX, EAX ; Ignore flags
1857 TEST EAX, 1 SHL 22
1858 SETNZ AL
1859 RET
1860GET_MODE ENDP
1861
1862
1863;
1864; Display the status of a bit: upper case if set, lower case if clear
1865;
1866; In: NZ Bit is set
1867; AL Upper case character
1868;
1869SHOW_BIT PROC NEAR
1870 JNZ SHORT SHOW_BIT_1
1871 ADD AL, "a" - "A"
1872SHOW_BIT_1: CALL GCHAR
1873 RET
1874SHOW_BIT ENDP
1875
1876
1877
1878
1879;
1880; Bug: pages protected by swapper cause exception 0EH (and dump)
1881;
1882SHOW_DATA PROC NEAR
1883 PUSHAD
1884 MOV AX, FS
1885 CALL GWORD
1886 MOV AL, ":"
1887 CALL GCHAR
1888 MOV EAX, ESI
1889 CALL GDWORD
1890 MOV AL," "
1891 CALL GCHAR
1892 XOR EDX, EDX
1893 MOV DX, FS
1894 LSL EDX, EDX
1895 MOV CX, 16
1896SDATA11: CMP ESI, EDX
1897 JA SHORT SDATA12
1898 MOV AL, FS:[ESI]
1899 CALL GBYTE
1900 JMP SHORT SDATA13
1901SDATA12: MOV AL, " "
1902 CALL GCHAR
1903 CALL GCHAR
1904SDATA13: MOV AL, " "
1905 CALL GCHAR
1906 INC ESI
1907 LOOP SDATA11
1908 MOV AL, " "
1909 CALL GCHAR
1910 SUB ESI, 16
1911 MOV CX, 16
1912SDATA21: CMP ESI, EDX
1913 JA SHORT SDATA29
1914 MOV AL, FS:[ESI]
1915 INC ESI
1916 CMP AL, 20H
1917 JB SHORT SDATA22
1918 CMP AL, 7FH
1919 JB SHORT SDATA23
1920SDATA22: MOV AL, "."
1921SDATA23: CALL GCHAR
1922 LOOP SDATA21
1923SDATA29: CALL GCRLF
1924 POPAD
1925 NOP ; Avoid 386 bug
1926 RET
1927SHOW_DATA ENDP
1928
1929
1930 ASSUME BP:PTR ISTACKFRAME
1931REG_DUMP PROC NEAR
1932 MOV AL, "D"
1933 MOV DX, I_DS
1934 CALL RD_SEG
1935 MOV AL, "E"
1936 MOV DX, I_ES
1937 CALL RD_SEG
1938 MOV AL, "F"
1939 MOV DX, I_FS
1940 CALL RD_SEG
1941 MOV AL, "G"
1942 MOV DX, I_GS
1943 CALL RD_SEG
1944 MOV DX, SS
1945 TEST I_CS, 3 ; RPL=0?
1946 JZ SHORT RD_1
1947 MOV DX, I_SS
1948RD_1: MOV AL, "S"
1949 CALL RD_SEG
1950 MOV AL, " "
1951 CALL GCHAR
1952 LEA BX, FLAG_TAB
1953 MOV EDX, I_EFLAGS
1954RD_F1: MOV CX, [BX+0]
1955 JCXZ RD_F9
1956 MOV AL, " "
1957 CALL GCHAR
1958 MOV AX, [BX+2]
1959 TEST DX, CX
1960 JZ SHORT RD_F2
1961 MOV AX, [BX+4]
1962RD_F2: CALL GCHAR
1963 MOV AL, AH
1964 CALL GCHAR
1965 ADD BX, 6
1966 JMP SHORT RD_F1
1967RD_F9: CALL GCRLF
1968
1969 MOV BL, "X"
1970 MOV AH, "A"
1971 MOV EDX, I_EAX
1972 CALL RD_GEN
1973 MOV AH, "B"
1974 MOV EDX, I_EBX
1975 CALL RD_GEN
1976 MOV AH, "C"
1977 MOV EDX, I_ECX
1978 CALL RD_GEN
1979 MOV AH, "D"
1980 MOV EDX, I_EDX
1981 CALL RD_GEN
1982 CALL GCRLF
1983 MOV BL, "I"
1984 MOV AH, "S"
1985 MOV EDX, I_ESI
1986 CALL RD_GEN
1987 MOV AH, "D"
1988 MOV EDX, I_EDI
1989 CALL RD_GEN
1990 MOV BL, "P"
1991 MOV AH, "B"
1992 MOV EDX, I_EBP
1993 CALL RD_GEN
1994 LEA EDX, I_ESP
1995 TEST I_CS, 3 ; RPL=0?
1996 JZ SHORT RD_2
1997 MOV EDX, I_ESP
1998RD_2: MOV AH, "S"
1999 CALL RD_GEN
2000 CALL GCRLF
2001 RET
2002 ASSUME BP:NOTHING
2003REG_DUMP ENDP
2004
2005RD_SEG PROC NEAR
2006 CALL GCHAR
2007 MOV AL, "S"
2008 CALL GCHAR
2009 MOV AL, "="
2010 CALL GCHAR
2011 MOV AX, DX
2012 CALL GWORD
2013 MOV AL, " "
2014 CALL GCHAR
2015 RET
2016RD_SEG ENDP
2017
2018RD_GEN PROC NEAR
2019 MOV AL, "E"
2020 CALL GCHAR
2021 MOV AL, AH
2022 CALL GCHAR
2023 MOV AL, BL
2024 CALL GCHAR
2025 MOV AL, "="
2026 CALL GCHAR
2027 MOV EAX, EDX
2028 CALL GDWORD
2029 MOV AL, " "
2030 CALL GCHAR
2031 RET
2032RD_GEN ENDP
2033
2034
2035;
2036; In: DI Address of routine to be called
2037;
2038; Routine pointed to by DI:
2039;
2040; In: EAX Page table entry
2041; EDX Swap table entry
2042; ADDR_LIN Linear address
2043;
2044SCAN_PAGE_TABLES PROC NEAR
2045 MOV ADDR_LIN, 0
2046 MOV AX, G_PAGEDIR_SEL
2047 MOV FS, AX
2048 MOV ESI, 0
2049SPT_10: MOV EBX, FS:[ESI]
2050 TEST BL, PAGE_PRESENT
2051 JZ SHORT SPT_18
2052 MOV EAX, FS:[ESI+4096]
2053 OR EAX, EAX
2054 JZ SHORT SPT_18
2055 PUSH ESI
2056 MOV ESI, EAX
2057 AND EBX, NOT 0FFFH
2058 MOV AX, G_PHYS_SEL
2059 MOV ES, AX
2060 MOV CX, 1024
2061SPT_11: MOV EAX, ES:[EBX]
2062 MOV EDX, ES:[ESI]
2063 PUSH ES
2064 PUSH FS
2065 PUSH EBX
2066 PUSH ESI
2067 PUSH CX
2068 PUSH DI
2069 CALL DI
2070 POP DI
2071 POP CX
2072 POP ESI
2073 POP EBX
2074 POP FS
2075 POP ES
2076 ADD EBX, 4
2077 ADD ESI, 4
2078 ADD ADDR_LIN, 4096
2079 LOOP SPT_11
2080 POP ESI
2081 JMP SHORT SPT_19
2082
2083SPT_18: ADD ADDR_LIN, 1024 * 4096
2084SPT_19: ADD ESI, 4
2085 CMP ESI, 4096
2086 JB SPT_10
2087 RET
2088SCAN_PAGE_TABLES ENDP
2089
2090
2091;
2092; Display info about linear address (ADDR_LIN)
2093;
2094SHOW_LIN PROC NEAR
2095 MOV EAX, ADDR_LIN
2096 CALL GDWORD
2097 MOV AL, " "
2098 CALL GCHAR
2099 MOV AX, G_PAGEDIR_SEL
2100 MOV ES, AX
2101 MOV EAX, ADDR_LIN
2102 SHR EAX, 22 ; Compute page directory index
2103 MOV ESI, ES:[4*EAX+0] ; Get page directory entry
2104 MOV EDI, ES:[4*EAX+4096] ; Get swap directory entry
2105 TEST ESI, PAGE_PRESENT ; Page table present?
2106 JNZ SHORT SL_1 ; Yes -> continue
2107 LEA EDX, $PAGE_DIR ; Display message
2108 CALL GTEXT
2109 JMP SL_RET ; Done
2110SL_1: MOV AX, G_PHYS_SEL
2111 MOV ES, AX
2112 AND ESI, NOT 0FFFH ; Page table address
2113 MOV EAX, ADDR_LIN ; Get linear address
2114 SHR EAX, 12
2115 AND EAX, 03FFH ; Page table index
2116 LEA ESI, [ESI+4*EAX] ; Address of page table entry
2117 OR EDI, EDI
2118 JZ SHORT SL_2
2119 LEA EDI, [EDI+4*EAX] ; Address of swap table entry
2120SL_2: LEA EDX, $PHYSICAL
2121 CALL GTEXT
2122 MOV EBX, ADDR_LIN
2123 MOV EAX, ES:[ESI]
2124 AND EAX, NOT 0FFFH
2125 AND EBX, 0FFFH
2126 OR EAX, EBX
2127 CALL GDWORD
2128 MOV AL, " "
2129 CALL GCHAR
2130 MOV EBX, ES:[ESI]
2131 MOV AL, "P"
2132 TEST EBX, PAGE_PRESENT
2133 CALL SHOW_BIT
2134 MOV AL, "A"
2135 TEST EBX, PAGE_ACCESSED
2136 CALL SHOW_BIT
2137 MOV AL, "D"
2138 TEST EBX, PAGE_DIRTY
2139 CALL SHOW_BIT
2140 TEST EBX, PAGE_USER
2141 JNZ SHORT SL_P1
2142 MOV AL, "-"
2143 CALL GCHAR
2144 JMP SHORT SL_P2
2145SL_P1: MOV AL, "W"
2146 TEST EBX, PAGE_WRITE
2147 CALL SHOW_BIT
2148SL_P2: MOV AL, "L"
2149 TEST EBX, PAGE_LOCKED
2150 CALL SHOW_BIT
2151 MOV AL, "X"
2152 TEST EBX, PAGE_ALLOC
2153 CALL SHOW_BIT
2154 MOV AL, " "
2155 CALL GCHAR
2156 OR EDI, EDI ; Swapper info table present?
2157 JZ SHORT SL_3 ; No -> skip
2158 MOV AL, ES:[EDI] ; Get process index
2159 CALL GBYTE ; Display process index
2160 MOV AL, " "
2161 CALL GCHAR
2162 MOV BX, ES:[EDI]
2163 AND BX, SRC_MASK
2164 MOV AL, "N"
2165 CMP BX, SRC_NONE
2166 JE SHORT SL_SRC
2167 MOV AL, "Z"
2168 CMP BX, SRC_ZERO
2169 JE SHORT SL_SRC
2170 MOV AL, "E"
2171 CMP BX, SRC_EXEC
2172 JE SHORT SL_SRC
2173 MOV AL, "S"
2174 CMP BX, SRC_SWAP
2175 JE SHORT SL_SRC
2176 MOV AL, "?"
2177SL_SRC: CALL GCHAR
2178 TEST WORD PTR ES:[EDI], SWAP_ALLOC
2179 MOV AL, "X"
2180 CALL SHOW_BIT
2181 JMP SHORT SL_4
2182
2183SL_3: MOV AL, " "
2184 CALL GCHAR
2185 CALL GCHAR
2186 CALL GCHAR
2187 CALL GCHAR
2188 CALL GCHAR
2189SL_4: MOV AL, " "
2190 CALL GCHAR
2191 MOV BX, ES:[EDI] ; Get swapper info table entry
2192 TEST BX, SWAP_ALLOC ; Swap space allocated?
2193 JNZ SL_EXT ; Yes -> show address
2194 AND BX, SRC_MASK ; Extract SRC field
2195 CMP BX, SRC_EXEC ; Load from exec file?
2196 JNE SHORT SL_NS ; No -> don't show address
2197SL_EXT: LEA EDX, $EXTERNAL
2198 CALL GTEXT
2199 MOV EAX, ES:[EDI]
2200 AND EAX, NOT 0FFFH
2201 CALL GDWORD
2202 MOV AL, " "
2203 CALL GCHAR
2204SL_NS: CALL GCRLF
2205SL_RET: RET
2206SHOW_LIN ENDP
2207
2208
2209
2210;
2211; Set breakpoint 0 at address DX:EAX
2212;
2213; In: DX:EAX Address of breakpoint
2214;
2215; Out: NZ Error
2216;
2217SET_BREAKPOINT PROC NEAR
2218 PUSH EAX
2219 PUSH EBX
2220 VERR DX
2221 JNZ SHORT SB1
2222 MOV BREAKPOINTS[0].BP_TYPE, BP_BREAKPOINT
2223 MOV BREAKPOINTS[0].BP_SEL, DX
2224 MOV BREAKPOINTS[0].BP_OFF, EAX
2225 MOV EBX, EAX
2226 MOV AX, DX
2227 CALL GET_LIN
2228 MOV BREAKPOINTS[0].BP_ADDR, EBX
2229 XOR EAX, EAX
2230SB1: POP EBX
2231 POP EAX
2232 RET
2233SET_BREAKPOINT ENDP
2234
2235
2236;
2237; Set watchpoint (or breakpoint)
2238;
2239; In: DX:EAX Address
2240; BL Type (BP_BREAKPOINT, BP_WATCHPOINT_?)
2241; BH Length:
2242; 0 BYTE
2243; 1 WORD
2244; 3 DWORD
2245;
2246; Out: SI Pointer to breakpoint table entry (0 if table full)
2247; NZ Error
2248;
2249SET_WATCHPOINT PROC NEAR
2250 PUSH EAX
2251 PUSH CX
2252 VERR DX
2253 JNZ SHORT SET_WP9
2254 LEA SI, BREAKPOINTS
2255 ASSUME SI:PTR BREAKPOINT
2256 MOV CX, 3
2257SET_WP1: ADD SI, SIZE BREAKPOINT
2258 CMP [SI].BP_TYPE, BP_INACTIVE
2259 JE SHORT SET_WP2
2260 LOOP SET_WP1
2261 XOR SI, SI ; Table full
2262 OR CL, 1 ; Set NZ
2263 JMP SHORT SET_WP9
2264SET_WP2: PUSH EBX
2265 MOV [SI].BP_TYPE, BL
2266 MOV [SI].BP_LEN, BH
2267 MOV [SI].BP_SEL, DX
2268 MOV [SI].BP_OFF, EAX
2269 MOV EBX, EAX
2270 MOV AX, DX
2271 CALL GET_LIN
2272 MOV [SI].BP_ADDR, EBX
2273 POP EBX
2274 XOR EAX, EAX
2275SET_WP9: POP CX
2276 POP EAX
2277 RET
2278 ASSUME SI:NOTHING
2279SET_WATCHPOINT ENDP
2280
2281
2282;
2283; Insert breakpoints
2284;
2285 ASSUME BP:PTR ISTACKFRAME
2286INS_BREAKPOINTS PROC NEAR
2287 PUSH ESI
2288 PUSH EDI
2289 PUSH EBX
2290 CMP DEBUG_FLAG, FALSE
2291 JE SHORT INSBP_0
2292 LEA EDX, $INSBRK
2293 CALL GTEXT
2294INSBP_0: MOV EDI, 0 ; DR7
2295 LEA SI, BREAKPOINTS
2296 ASSUME SI:PTR BREAKPOINT
2297 MOV DX, 4
2298 MOV CL, 0
2299INSBP_1: CMP [SI].BP_TYPE, BP_BREAKPOINT ; Code breakpoint?
2300 JNE SHORT INSBP_3 ; No -> inactive or watchpoint
2301 CMP SKIP_FLAG, FALSE ; Skipping breakpoint?
2302 JE SHORT INSBP_2 ; No -> don't check address
2303 MOV EAX, [SI].BP_OFF
2304 CMP EAX, I_EIP ; Breakpoint at CS:EIP?
2305 JNE SHORT INSBP_2 ; No -> set breakpoint
2306 MOV AX, [SI].BP_SEL
2307 CMP AX, I_CS
2308 JE SHORT INSBP_9 ; Yes -> ignore breakpoint
2309INSBP_2: MOV BL, 0
2310 MOV BH, 00H ; Instruction execution only
2311 JMP SHORT INSBP_5
2312INSBP_3: MOV BL,[SI].BP_LEN
2313 MOV BH, 03H ; Data reads or writes only
2314 CMP [SI].BP_TYPE, BP_WATCHPOINT_R
2315 JE SHORT INSBP_4
2316 MOV BH, 01H ; Data writes only
2317 CMP [SI].BP_TYPE, BP_WATCHPOINT_W
2318 JE SHORT INSBP_4
2319 CMP [SI].BP_TYPE, BP_WATCHPOINT_X
2320 JNE SHORT INSBP_9
2321INSBP_4: CALL WATCH_GET
2322 MOV [SI].BP_VAL, EAX
2323INSBP_5: CMP DEBUG_FLAG, FALSE
2324 JE SHORT INSBP_6
2325 PUSHAD
2326 CALL SHOW_BREAKPOINT
2327 POPAD
2328INSBP_6: SHL BL, 2
2329 OR BL, BH
2330 MOVZX EAX, BL
2331 SHL EAX, 16
2332 SHL EAX, CL
2333 OR EAX, 01H ; L0
2334 SHL EAX, CL
2335 OR EDI, EAX
2336 OR EDI, 100H ; LE
2337 MOV EAX, [SI].BP_ADDR
2338 CMP DX, 4
2339 JE SHORT INSBP_ADDR_0
2340 CMP DX, 3
2341 JE SHORT INSBP_ADDR_1
2342 CMP DX, 2
2343 JE SHORT INSBP_ADDR_2
2344INSBP_ADDR_3: MOV DR3, EAX
2345 JMP SHORT INSBP_9
2346INSBP_ADDR_1: MOV DR1, EAX
2347 JMP SHORT INSBP_9
2348INSBP_ADDR_2: MOV DR2, EAX
2349 JMP SHORT INSBP_9
2350INSBP_ADDR_0: MOV DR0, EAX
2351INSBP_9: ADD SI, SIZE BREAKPOINT
2352 ADD CL, 2
2353 DEC DX
2354 JNZ INSBP_1
2355 ASSUME SI:NOTHING
2356 MOV DR7, EDI
2357 POP EBX
2358 POP EDI
2359 POP ESI
2360 RET
2361 ASSUME BP:NOTHING
2362INS_BREAKPOINTS ENDP
2363
2364;
2365; Read watch area
2366;
2367; In: DS:SI Pointer to breakpoint table entry
2368;
2369; Out: EAX Contents
2370;
2371 ASSUME SI:PTR BREAKPOINT
2372WATCH_GET PROC NEAR
2373 PUSH ES
2374 PUSH EDI
2375 MOV ES, [SI].BP_SEL
2376 MOV EDI, [SI].BP_OFF
2377 CMP [SI].BP_LEN, 0
2378 JE SHORT WATCH_GET_1
2379 CMP [SI].BP_LEN, 1
2380 JE SHORT WATCH_GET_2
2381 MOV EAX, ES:[EDI]
2382WATCH_GET_RET: POP EDI
2383 POP ES
2384 RET
2385WATCH_GET_1: MOVZX EAX, BYTE PTR ES:[EDI]
2386 JMP SHORT WATCH_GET_RET
2387WATCH_GET_2: MOVZX EAX, WORD PTR ES:[EDI]
2388 JMP SHORT WATCH_GET_RET
2389 ASSUME SI:NOTHING
2390WATCH_GET ENDP
2391
2392
2393;
2394; Input command line
2395;
2396; In: AL First character
2397;
2398; Out: BX Pointer to first non-blank character (DS=SV_DATA)
2399; CY Error (never)
2400;
2401INPUT PROC NEAR
2402 CALL GCHAR
2403 LEA BX, INPUT_BUF
2404 MOV CL, 0
2405INPUT_LOOP: CALL GINCHAR
2406 CMP AL, " "
2407 JAE SHORT INPUT_PUT
2408 CMP AL, LF
2409 JE SHORT INPUT_END
2410 CMP AL, CR
2411 JE SHORT INPUT_END
2412 CMP AL, 08H ; ^H
2413 JE SHORT INPUT_BACK
2414 CMP AL, 7FH ; DEL
2415 JE SHORT INPUT_BACK
2416 CMP AL, 15H ; ^U
2417 JE SHORT INPUT_KILL
2418 CMP AL, 18H ; ^X
2419 JE SHORT INPUT_KILL
2420INPUT_BEEP: MOV AL, 07H
2421 CALL GCHAR
2422 JMP SHORT INPUT_LOOP
2423
2424
2425INPUT_PUT: CMP CL, 64
2426 JAE SHORT INPUT_BEEP
2427 MOV [BX], AL
2428 INC BX
2429 INC CL
2430 CALL GCHAR
2431 JMP SHORT INPUT_LOOP
2432
2433INPUT_BACK: CMP CL, 0
2434 JE SHORT INPUT_LOOP
2435 CALL INPUT_DEL
2436 JMP SHORT INPUT_LOOP
2437
2438INPUT_END: MOV BYTE PTR [BX], 0
2439 CALL GCRLF
2440 LEA BX, INPUT_BUF
2441 CALL SKIP
2442 CLC
2443 RET
2444
2445INPUT_KILL: CMP CL, 0
2446 JE SHORT INPUT_LOOP
2447 CALL INPUT_DEL
2448 JMP SHORT INPUT_KILL
2449
2450INPUT ENDP
2451
2452
2453INPUT_DEL PROC NEAR
2454 DEC CL
2455 DEC BX
2456 MOV AL, 08H
2457 CALL GCHAR
2458 MOV AL, " "
2459 CALL GCHAR
2460 MOV AL, 08H
2461 CALL GCHAR
2462 RET
2463INPUT_DEL ENDP
2464
2465
2466;
2467; Fetch next character
2468;
2469; In: BX Pointer to input (DS=SV_DATA)
2470;
2471; Out: AL Character (uppercase)
2472; ZR End of line
2473; BX Advanced to next character
2474;
2475FETCH PROC NEAR
2476FETCH1: MOV AL, [BX]
2477 CALL END_OF_LINE
2478 JZ SHORT FETCH9
2479 INC BX
2480 CALL UPPER
2481 OR AL, AL
2482FETCH9: RET
2483FETCH ENDP
2484
2485;
2486; Skip blanks and TABs
2487;
2488; In: BX Pointer to input (DS=SV_DATA)
2489;
2490; Out: BX Next character
2491;
2492SKIP PROC NEAR
2493SKIP1: CMP BYTE PTR [BX], " "
2494 JE SHORT SKIP2
2495 CMP BYTE PTR [BX], TAB
2496 JNE SHORT SKIP9
2497SKIP2: INC BX
2498 JMP SHORT SKIP1
2499SKIP9: RET
2500SKIP ENDP
2501
2502
2503;
2504; Check for argument delimiter
2505;
2506; In: BX Pointer to input (DS=SV_DATA)
2507;
2508; Out: ZR Delimiter
2509;
2510DELIM: CMP BYTE PTR [BX], TAB
2511 JE SHORT EOL9
2512 CMP BYTE PTR [BX], " "
2513 JE SHORT EOL9
2514;
2515; Check for end of line
2516;
2517; In: BX Pointer to input (DS=SV_DATA)
2518;
2519; Out: ZR End of line
2520;
2521END_OF_LINE: CMP BYTE PTR [BX], 00H
2522 JE SHORT EOL9
2523 CMP BYTE PTR [BX], LF
2524 JE SHORT EOL9
2525 CMP BYTE PTR [BX], CR
2526EOL9: RET
2527
2528
2529;
2530; Parse an address range
2531;
2532; In: BX Pointer to input (DS=SV_DATA)
2533; DX Default selector
2534;
2535; Out: CY Error
2536; DX Selector
2537; EAX Offset
2538; ECX Size
2539; EDX Error message
2540;
2541GET_RANGE PROC NEAR
2542 CALL GET_ADDR
2543 JC SHORT GRNG_INPUT_ERROR
2544GET_RANGE_MORE::VERR DX
2545 JNZ SHORT GRNG_INVALID_SEL
2546 MOV RANGE_SEL, DX
2547 MOV RANGE_OFF, EAX
2548 CALL GET_ADDR ; Keep DX
2549 JC SHORT GRNG_INPUT_ERROR
2550 CMP DX, RANGE_SEL
2551 JNE SHORT GRNG_INPUT_ERROR
2552 AND EDX, 0FFFFH
2553 LSL ECX, EDX
2554 CMP EAX, ECX
2555 JA SHORT GRNG_BEYOND_LIMIT
2556 SUB EAX, RANGE_OFF
2557 JB SHORT GRNG_INPUT_ERROR
2558 INC EAX
2559 MOV ECX, EAX
2560 MOV EAX, RANGE_OFF
2561 CLC
2562 RET
2563
2564GRNG_BEYOND_LIMIT:
2565 LEA EDX, $BEYOND_LIMIT
2566 JMP SHORT GRNG_ERROR
2567
2568GRNG_INVALID_SEL:
2569 LEA EDX, $INVALID_SEL
2570 JMP SHORT GRNG_ERROR
2571
2572GRNG_INPUT_ERROR:
2573 LEA EDX, $INPUT_ERROR
2574GRNG_ERROR: STC
2575 RET
2576GET_RANGE ENDP
2577
2578
2579;
2580; Parse an address
2581;
2582; In: BX Pointer to input (DS=SV_DATA)
2583; DX Default selector
2584;
2585; Out: CY Error
2586; DX Selector
2587; EAX Offset
2588;
2589GET_ADDR PROC NEAR
2590 PUSH BX
2591 CALL GET_NUMBER
2592 JC SHORT GET_ADDR_1
2593 CMP BYTE PTR [BX], ":"
2594 JNE SHORT GET_ADDR_END
2595 INC BX
2596 MOV DX, AX
2597 CALL GET_NUMBER
2598 JC SHORT GET_ADDR_1
2599GET_ADDR_END: CALL DELIM
2600 JZ SHORT GET_ADDR_OK
2601GET_ADDR_1: POP BX
2602 PUSH BX
2603 PUSH DI
2604 LEA DI, SYMBOL_BUF
2605 MOV BYTE PTR [DI], "_"
2606 INC DI
2607GET_ADDR_S1: MOV AL, [BX]
2608 CMP AL, " "
2609 JE SHORT GET_ADDR_S2
2610 CMP AL, TAB
2611 JE SHORT GET_ADDR_S2
2612 CALL END_OF_LINE
2613 JZ SHORT GET_ADDR_S2
2614 MOV [DI], AL
2615 INC DI
2616 INC BX
2617 JMP SHORT GET_ADDR_S1
2618GET_ADDR_S2: MOV BYTE PTR [DI], 0
2619 PUSH BX
2620 MOV DI, PROCESS_PTR
2621 LEA BX, SYMBOL_BUF
2622 CALL SYM_BY_NAME
2623 JNC GET_ADDR_S3
2624 POP BX
2625 POP DI
2626 JMP SHORT GET_ADDR_ERROR
2627GET_ADDR_S3: POP BX
2628 POP DI
2629 PUSH EAX
2630 CALL DELIM
2631 POP EAX
2632 JNZ SHORT GET_ADDR_ERROR
2633 XCHG EAX, EDX
2634 CMP DL, SYM_TEXT
2635 MOV DX, L_CODE_SEL
2636 JE SHORT GET_ADDR_OK
2637 MOV DX, L_DATA_SEL
2638GET_ADDR_OK: CALL SKIP
2639 CLC
2640 JMP SHORT GET_ADDR_RET
2641GET_ADDR_ERROR: STC
2642GET_ADDR_RET: ADD ESP, 2 ; Remove BX
2643 RET
2644GET_ADDR ENDP
2645
2646;
2647; Parse a value (number or register or character constant)
2648;
2649; In: BX Pointer to input (DS=SV_DATA)
2650;
2651; Out: CY Error
2652; BX Points to next character
2653; EAX Value
2654;
2655GET_NUMBER PROC NEAR
2656 PUSH EDX
2657 PUSH CX
2658 CMP BYTE PTR [BX], "'"
2659 JE SHORT GNUM_CHR
2660 CALL GET_REG
2661 JNC SHORT GNUM_REG
2662GNUM0: XOR EDX, EDX
2663 MOV CX, 0
2664GNUM1: MOVZX EAX, BYTE PTR [BX]
2665 SUB AL, "0"
2666 JB SHORT GNUM_END
2667 CMP AL, 10
2668 JB SHORT GNUM2
2669 ADD AL, "0"-"A"+10
2670 CMP AL, 10
2671 JB SHORT GNUM_END
2672 CMP AL, 16
2673 JB SHORT GNUM2
2674 ADD AL, "A"-"a"
2675 CMP AL, 10
2676 JB SHORT GNUM_END
2677 CMP AL, 16
2678 JAE SHORT GNUM_END
2679GNUM2: SHL EDX, 4
2680 ADD EDX, EAX
2681 INC BX
2682 INC CX
2683 JMP SHORT GNUM1
2684GNUM_END: JCXZ GNUM_ERROR
2685 MOV EAX, EDX
2686GNUM_OK: CLC
2687 JMP SHORT GNUM_RET
2688
2689GNUM_REG: XCHG BX, DX
2690 CMP AL, R8
2691 JE SHORT GNUM_REG_R8
2692 CMP AL, R16
2693 JE SHORT GNUM_REG_R16
2694GNUM_REG_R32: MOV EAX, SS:[BX]
2695 JMP SHORT GNUM_REG2
2696GNUM_REG_R16: MOVZX EAX, WORD PTR SS:[BX]
2697 JMP SHORT GNUM_REG2
2698GNUM_REG_R8: MOVZX EAX, BYTE PTR SS:[BX]
2699GNUM_REG2: XCHG BX, DX
2700 JMP SHORT GNUM_OK
2701
2702GNUM_CHR: INC BX
2703 CALL END_OF_LINE
2704 JZ SHORT GNUM_ERROR
2705 MOVZX EAX, BYTE PTR [BX]
2706 INC BX
2707 CMP BYTE PTR [BX], "'"
2708 JNZ SHORT GNUM_ERROR
2709 INC BX
2710 JMP SHORT GNUM_RET
2711
2712GNUM_ERROR: STC
2713GNUM_RET: POP CX
2714 POP EDX
2715 RET
2716GET_NUMBER ENDP
2717
2718;
2719; Parse a register name
2720;
2721; In: BX Pointer to input (DS=SV_DATA)
2722;
2723; Out: CY Error
2724; DX Pointer to register (offset into stack segment; SS:DX)
2725; AX Register size (R8, R16, R32)
2726;
2727 ASSUME BP:PTR ISTACKFRAME
2728GET_REG PROC NEAR
2729 PUSH SI
2730 PUSH DI
2731 MOV DI, BX
2732 LEA SI, REG_TAB
2733 CLD
2734GREG1: LODS REG_TAB
2735 CMP AL, 0FFH
2736 JE SHORT GREG_LOSE
2737 CMP AL, R32
2738 JBE SHORT GREG10
2739 MOV AH, AL
2740 CALL FETCH
2741 CMP AL, AH
2742 JE SHORT GREG1
2743GREG2: LODS REG_TAB
2744 CMP AL, R32
2745 JA SHORT GREG2
2746GREG3: INC SI
2747 MOV BX, DI
2748 JMP SHORT GREG1
2749
2750GREG10: MOVZX DX, BYTE PTR [SI]
2751 CMP DX, 56 ; ESP, SS
2752 JB SHORT GREG11
2753 TEST I_CS, 3 ; RPL=0?
2754 JZ SHORT GREG3
2755GREG11: ADD DX, BP
2756 XOR AH, AH
2757 JMP SHORT GREG_RET
2758
2759GREG_LOSE: MOV BX, DI
2760 STC
2761GREG_RET: POP DI
2762 POP SI
2763 RET
2764 ASSUME BP:NOTHING
2765GET_REG ENDP
2766
2767
2768;
2769; Display a number in decimal notation
2770;
2771; In: EAX Number
2772;
2773DECIMAL PROC NEAR
2774 PUSH EDX
2775 PUSH ECX
2776 CALL DECIMAL2
2777 POP ECX
2778 POP EDX
2779 RET
2780
2781DECIMAL1: OR EAX, EAX
2782 JZ SHORT DECIMAL9
2783DECIMAL2: XOR EDX, EDX
2784 MOV ECX, 10
2785 DIV ECX
2786 PUSH EDX
2787 CALL DECIMAL1
2788 POP EAX
2789 ADD AL, "0"
2790 CALL GCHAR
2791DECIMAL9: RET
2792DECIMAL ENDP
2793
2794
2795 ASSUME DS:SV_DATA
2796DEBUG_INIT PROC NEAR
2797 CMP DEBUG_SER_FLAG, FALSE
2798 JE SHORT DEBUG_INIT_RET
2799 MOV GDWORD, OFFSET SV_CODE:S_DWORD
2800 MOV GWORD, OFFSET SV_CODE:S_WORD
2801 MOV GBYTE, OFFSET SV_CODE:S_BYTE
2802 MOV GTEXT, OFFSET SV_CODE:S_TEXT
2803 MOV GCRLF, OFFSET SV_CODE:S_CRLF
2804 MOV GCHAR, OFFSET SV_CODE:S_CHAR
2805 MOV GINCHAR, OFFSET SV_CODE:S_INCHAR
2806DEBUG_INIT_RET: RET
2807DEBUG_INIT ENDP
2808
2809
2810 ASSUME DS:SV_DATA
2811DEBUG_QUIT PROC NEAR
2812 CMP STEP_FLAG, FALSE
2813 JE SHORT DQ_RET
2814 LEA EDX, $SWAP_FAULTS
2815 CALL GTEXT
2816 MOV EAX, SWAP_FAULTS
2817 CALL DECIMAL
2818 LEA EDX, $SWAP_READS
2819 CALL GTEXT
2820 MOV EAX, SWAP_READS
2821 CALL DECIMAL
2822 LEA EDX, $SWAP_WRITES
2823 CALL GTEXT
2824 MOV EAX, SWAP_WRITES
2825 CALL DECIMAL
2826 LEA EDX, $SNATCH_COUNT
2827 CALL GTEXT
2828 MOV EAX, SNATCH_COUNT
2829 CALL DECIMAL
2830 LEA EDX, $SWAP_SIZE
2831 CALL GTEXT
2832 MOV EAX, SWAP_SIZE
2833 CALL DECIMAL
2834 CALL GCRLF
2835 CALL CHECK_HANDLES
2836DQ_RET: RET
2837DEBUG_QUIT ENDP
2838
2839
2840 ASSUME DS:SV_DATA
2841B_DWORD PROC NEAR
2842 ROR EAX, 16
2843 CALL B_WORD
2844 ROR EAX, 16
2845 CALL B_WORD
2846 RET
2847B_DWORD ENDP
2848
2849 ASSUME DS:SV_DATA
2850B_WORD PROC NEAR
2851 XCHG AL, AH
2852 CALL B_BYTE
2853 XCHG AL, AH
2854 CALL B_BYTE
2855 RET
2856B_WORD ENDP
2857
2858
2859 ASSUME DS:SV_DATA
2860B_BYTE PROC NEAR
2861 PUSH AX
2862 SHR AL, 4
2863 CALL B_NIBBLE
2864 POP AX
2865 PUSH AX
2866 CALL B_NIBBLE
2867 POP AX
2868 RET
2869B_BYTE ENDP
2870
2871 ASSUME DS:SV_DATA
2872B_NIBBLE PROC NEAR
2873 AND AL, 0FH
2874 ADD AL, 30H
2875 CMP AL, 3AH
2876 JB SHORT SNIB1
2877 ADD AL, 7
2878SNIB1: CALL B_CHAR
2879 RET
2880B_NIBBLE ENDP
2881
2882
2883 ASSUME DS:SV_DATA
2884B_TEXT PROC NEAR
2885 PUSH AX
2886B_TEXT1: MOV AL, DS:[EDX]
2887 CMP AL, 0
2888 JE SHORT B_TEXT9
2889 CALL B_CHAR
2890 INC EDX
2891 JMP SHORT B_TEXT1
2892B_TEXT9: POP AX
2893 RET
2894B_TEXT ENDP
2895
2896 ASSUME DS:SV_DATA
2897B_CHAR PROC NEAR
2898 PUSH AX
2899 PUSH BX
2900 CMP AL, TAB
2901 JE SHORT BC_TAB
2902 INC B_COLUMN
2903 CMP AL, CR
2904 JNE SHORT BC_1
2905 MOV B_COLUMN, 0
2906BC_1: MOV BX, 0007H
2907 MOV AH, 0EH
2908 INT 10H
2909BC_RET: POP BX
2910 POP AX
2911 RET
2912
2913BC_TAB: MOV AH, B_COLUMN
2914 NOT AH
2915 AND AH, 7
2916 INC AH
2917 MOV AL, " "
2918BC_TAB_1: CALL B_CHAR
2919 DEC AH
2920 JNZ SHORT BC_TAB_1
2921 JMP SHORT BC_RET
2922B_CHAR ENDP
2923
2924 ASSUME DS:SV_DATA
2925B_CRLF PROC NEAR
2926 PUSH AX
2927 MOV AL, CR
2928 CALL B_CHAR
2929 MOV AL, LF
2930 CALL B_CHAR
2931 POP AX
2932 RET
2933B_CRLF ENDP
2934
2935 ASSUME DS:SV_DATA
2936B_INCHAR PROC NEAR
2937 XOR AL, AL
2938 XCHG AL, B_NEXT
2939 TEST AL, AL
2940 JNZ SHORT B_INCHAR_RET
2941B_INCHAR_LOOP: MOV AH, 0
2942 INT 16H
2943 TEST AL, AL
2944 JNZ SHORT B_INCHAR_RET
2945 TEST AH, AH
2946 JZ SHORT B_INCHAR_LOOP
2947 MOV B_NEXT, AH
2948B_INCHAR_RET: RET
2949B_INCHAR ENDP
2950
2951 ASSUME DS:SV_DATA
2952S_DWORD PROC NEAR
2953 ROR EAX, 16
2954 CALL S_WORD
2955 ROR EAX, 16
2956 CALL S_WORD
2957 RET
2958S_DWORD ENDP
2959
2960 ASSUME DS:SV_DATA
2961S_WORD PROC NEAR
2962 XCHG AL, AH
2963 CALL S_BYTE
2964 XCHG AL, AH
2965 CALL S_BYTE
2966 RET
2967S_WORD ENDP
2968
2969
2970 ASSUME DS:SV_DATA
2971S_BYTE PROC NEAR
2972 PUSH AX
2973 SHR AL, 4
2974 CALL S_NIBBLE
2975 POP AX
2976 PUSH AX
2977 CALL S_NIBBLE
2978 POP AX
2979 RET
2980S_BYTE ENDP
2981
2982 ASSUME DS:SV_DATA
2983S_NIBBLE PROC NEAR
2984 AND AL, 0FH
2985 ADD AL, 30H
2986 CMP AL, 3AH
2987 JB SHORT SNIB1
2988 ADD AL, 7
2989SNIB1: CALL S_CHAR
2990 RET
2991S_NIBBLE ENDP
2992
2993
2994 ASSUME DS:SV_DATA
2995S_TEXT PROC NEAR
2996 PUSH AX
2997S_TEXT1: MOV AL, DS:[EDX]
2998 CMP AL, 0
2999 JE SHORT S_TEXT9
3000 CALL S_CHAR
3001 INC EDX
3002 JMP SHORT S_TEXT1
3003S_TEXT9: POP AX
3004 RET
3005S_TEXT ENDP
3006
3007 ASSUME DS:SV_DATA
3008S_CHAR PROC NEAR
3009 PUSH AX
3010 PUSH DX
3011 MOV AH, AL
3012S_CHAR0: MOV DX, DEBUG_SER_PORT
3013 ADD DX, 4
3014 MOV AL, 3
3015 OUT DX, AL
3016 INC DX
3017S_CHAR1: IN AL, DX ; Read line status
3018 TEST AL, 01H ; Input character ready?
3019 JZ SHORT S_CHAR2 ; No -> check for output
3020 SUB DX, 5 ; Receiver register
3021 IN AL, DX ; Read input character
3022 CMP AL, 13H ; ^S (XOFF)?
3023 JE SHORT S_CHAR_XOFF ; Yes -> stop
3024 CMP AL, 11H ; ^Q (XON)?
3025 JE SHORT S_CHAR_XON ; Yes -> continue
3026 CMP LOOK_AHEAD, 0 ; Input buffer full?
3027 JNE SHORT S_CHAR0 ; Yes -> discard, repeat
3028 MOV LOOK_AHEAD, AL ; Save input character
3029 JMP SHORT S_CHAR0 ; (if non-zero)
3030
3031S_CHAR2: TEST AL, 20H ; Transmitter empty?
3032 JZ SHORT S_CHAR1 ; No -> repeat
3033 CMP XOFF, FALSE ; Stopped?
3034 JNE SHORT S_CHAR1 ; Yes -> repeat
3035 SUB DX, 5 ; Transmitter register
3036 MOV AL, AH ; Write character
3037 OUT DX, AL ; to transmitter register
3038 POP DX
3039 POP AX
3040 RET
3041
3042S_CHAR_XON: MOV XOFF, FALSE
3043 JMP SHORT S_CHAR1
3044
3045S_CHAR_XOFF: MOV XOFF, NOT FALSE
3046 JMP SHORT S_CHAR1
3047
3048S_CHAR ENDP
3049
3050 ASSUME DS:SV_DATA
3051S_CRLF PROC NEAR
3052 PUSH AX
3053 MOV AL, CR
3054 CALL S_CHAR
3055 MOV AL, LF
3056 CALL S_CHAR
3057 POP AX
3058 RET
3059S_CRLF ENDP
3060
3061
3062 ASSUME DS:SV_DATA
3063S_INCHAR PROC NEAR
3064 PUSH DX
3065 XOR AL, AL
3066 XCHG AL, LOOK_AHEAD ; Examine input buffer
3067 OR AL, AL ; Non-empty?
3068 JNZ SHORT S_INCHAR_RET ; Yes -> use buffered character
3069S_INCHAR1: MOV DX, DEBUG_SER_PORT
3070 ADD DX, 4
3071 MOV AL, 3
3072 OUT DX, AL
3073 INC DX ; Line status register
3074S_INCHAR2: IN AL, DX ; Read line status
3075 TEST AL, 01H ; Input character ready?
3076 JZ SHORT S_INCHAR2 ; No -> repeat
3077 SUB DX, 5 ; Receiver register
3078 IN AL, DX ; Read input character
3079 OR AL, AL ; NUL?
3080 JZ SHORT S_INCHAR2 ; Yes -> discard, repeat
3081 CMP AL, 13H ; ^S (XOFF)?
3082 JE SHORT S_INCHAR_XOFF ; Yes -> stop
3083 CMP AL, 11H ; ^Q (XON)?
3084 JE SHORT S_INCHAR_XON ; Yes -> continue
3085S_INCHAR_RET: POP DX
3086 RET
3087
3088S_INCHAR_XON: MOV XOFF, FALSE
3089 JMP SHORT S_INCHAR1
3090
3091S_INCHAR_XOFF: MOV XOFF, NOT FALSE
3092 JMP SHORT S_INCHAR1
3093
3094
3095S_INCHAR ENDP
3096
3097
3098
3099SV_CODE ENDS
3100
3101 END
Note: See TracBrowser for help on using the repository browser.