summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/DEBUG/DEBCOM3.ASM
blob: 21e971cda4ad5d38a6064b7d5918e34dbaedfcdb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
	PAGE	80,132 ;
	TITLE	DEBCOM3.ASM - PART3 DEBUGGER COMMANDS
; ROUTINES TO PERFORM DEBUGGER COMMANDS

	IF1
	    %OUT COMPONENT=DEBUG, MODULE=DEBCOM3
	ENDIF
.XLIST
.XCREF
	INCLUDE DOSSYM.INC
	INCLUDE DEBEQU.ASM
	INCLUDE DPL.ASM
.CREF
.LIST
CODE	SEGMENT PUBLIC BYTE
CODE	ENDS

CONST	SEGMENT PUBLIC BYTE
	EXTRN	USER_PROC_PDB:WORD,RSTACK:WORD,STACK:BYTE
	EXTRN	DSSAVE:WORD,CSSAVE:WORD,IPSAVE:WORD,axSAVE:WORD,dxSAVE:WORD
	EXTRN	SSSAVE:WORD,SPSAVE:WORD,FLSAVE:WORD
	EXTRN	NEXTCS:WORD,NEXTIP:WORD, RSETFLAG:BYTE
CONST	ENDS

CSTACK	SEGMENT STACK
CSTACK	ENDS

DATA	SEGMENT PUBLIC BYTE
	EXTRN	BRKCNT:WORD,TCOUNT:WORD,SWITCHAR:BYTE,BPTAB:BYTE
	EXTRN	BP_ERROR:BYTE,COMP_ARG1:WORD,COMP_ARG2:WORD,COMP_ARG3:WORD
	EXTRN	COMP_ARG4:WORD,COMP_ARG5:WORD,COMP_ARG6:WORD,COMP_PTR:BYTE
	EXTRN	ARG_BUF:BYTE,ARG_BUF_PTR:BYTE
	EXTRN	FZTRACE:BYTE, SYNERR_PTR:BYTE
	EXTRN	BEGSEG:WORD
	IF	IBMVER
	    EXTRN   OLD_MASK:BYTE
	ENDIF
	EXTRN	SAVESTATE:BYTE
DATA	ENDS

DG	GROUP	CODE,CONST,CSTACK,DATA

CODE	SEGMENT PUBLIC BYTE
ASSUME	CS:DG,DS:DG,ES:DG,SS:DG
	PUBLIC	COMPARE,INPUT,OUTPUT,GO
	PUBLIC	TRACE,ZTRACE,SKIP_FILE
	EXTRN	GETHEX:NEAR,GETEOL:NEAR,CRLF:NEAR,ERR:NEAR, PERR:NEAR
	EXTRN	HEX:NEAR,DIGIT:NEAR,SCANP:NEAR,DISPREG:NEAR
	EXTRN	COMMAND:NEAR,DABORT:NEAR,DELIM1:NEAR,DELIM2:NEAR
	EXTRN	NMIINT:NEAR,NMIINTEND:NEAR,PRINTF_CRLF:NEAR
	EXTRN	ADDRESS:NEAR,HEXIN:NEAR,DSRANGE:NEAR
; just like trace except skips OVER next INT or CALL.
DEBCOM3:
ZTRACE:
	MOV	FZTRACE,-1
	CALL	SETADD
	CALL	SCANP
	CALL	HEXIN
	MOV	DX,1
	JC	ZSTOCNT
	MOV	CX,4
	CALL	GETHEX
	CALL	CHECKNONE
ZSTOCNT:
	MOV	[TCOUNT],DX
	CALL	GETEOL
	MOV	DX,NEXTCS
	MOV	CSSAVE,DX
	MOV	DX,NEXTIP
	MOV	IPSAVE,DX
ZSTEP:
	MOV	ES,[CSSAVE]		; point to instruction to execute
	MOV	DI,[IPSAVE]		; include offset in segment
	XOR	DX,DX			; where to place breakpoint
get_opcode:
	MOV	AL,ES:[DI]		; get the opcode
	cmp	al,0f0h 		; lock
	je	is_override
	cmp	al,26h			; es:
	je	is_override
	cmp	al,2eh			; cs:
	je	is_override
	cmp	al,36h			; ss:
	je	is_override
	cmp	al,3eh			; ds:
	jne	not_override
Is_override:
;	inc	dx			; this seemed to put us in an endless
	inc	di			; loop, try this.
	jmp	get_opcode
Not_override:
	CMP	AL,11101000B		; direct intra call
	JZ	ZTRACE3 		; yes, 3 bytes
	CMP	AL,10011010B		; direct inter call
	JZ	ZTRACE5 		; yes, 5 bytes
	CMP	AL,11111111B		; indirect?
	JZ	ZTRACEMODRM		; yes, go figure length
	CMP	AL,11001100B		; short interrupt?
	JZ	ZTRACE1 		; yes, 1 byte
	CMP	AL,11001101B		; long interrupt?
	JZ	ZTRACE2 		; yes, 2 bytes
	CMP	AL,11100010B		; loop
	JZ	ZTRACE2 		; 2 byter
	CMP	AL,11100001B		; loopz/loope
	JZ	ZTRACE2 		; 2 byter
	CMP	AL,11100000B		; loopnz/loopne
	JZ	ZTRACE2 		; 2 byter
	AND	AL,11111110B		; check for rep
	CMP	AL,11110010B		; perhaps?
	JZ	FOO1
	JMP	STEP			; can't do anything special, step
FOO1:
	MOV	AL,ES:[DI+1]		; next instruction
	AND	AL,11111110B		; ignore w bit
	CMP	AL,10100100B		; MOVS
	JZ	ZTRACE2 		; two byte
	CMP	AL,10100110B		; CMPS
	JZ	ZTRACE2 		; two byte
	CMP	AL,10101110B		; SCAS
	JZ	ZTRACE2 		; two byte
	CMP	AL,10101100B		; LODS
	JZ	ZTRACE2 		; two byte
	CMP	AL,10101010B		; STOS
	JZ	ZTRACE2 		; two byte
	JMP	STEP			; bogus, do single step

ZTRACEMODRM:
	MOV	AL,ES:[DI+1]		; get next byte
	AND	AL,11111000B		; get mod and type
	CMP	AL,01010000B		; indirect intra 8 bit offset?
	JZ	ZTRACE3 		; yes, three byte whammy
	CMP	AL,01011000B		; indirect inter 8 bit offset
	JZ	ZTRACE3 		; yes, three byte guy
	CMP	AL,10010000B		; indirect intra 16 bit offset?
	JZ	ZTRACE4 		; four byte offset
	CMP	AL,10011000B		; indirect inter 16 bit offset?
	JZ	ZTRACE4 		; four bytes
	CMP	AL,11010000B		; indirect through reg?
	JZ	ZTRACE2 		; two byte instruction
	JMP	STEP			; can't figger out what this is!
ZTRACE5:
	INC	DX
ZTRACE4:
	INC	DX
ZTRACE3:
	INC	DX
ZTRACE2:
	INC	DX
ZTRACE1:
	INC	DX
	ADD	DI,DX			; offset to breakpoint instruction
	MOV	WORD PTR [BPTAB],DI	; save offset
	MOV	WORD PTR [BPTAB+2],ES	; save segment
	MOV	AL,ES:[DI]		; get next opcode byte
	MOV	BYTE PTR [BPTAB+4],AL	; save it
	MOV	BYTE PTR ES:[DI],0CCH	; break point it
	MOV	[BRKCNT],1		; only this breakpoint
	JMP	DEXIT			; start the operation!

; Trace 1 instruction or the number of instruction specified
; by the parameter using 8086 trace mode. Registers are all
; set according to values in save area
TRACE:
	MOV	FZTRACE,0
	CALL	SETADD
	CALL	SCANP
	CALL	HEXIN
	MOV	DX,1
	JC	STOCNT
	MOV	CX,4
	CALL	GETHEX
	CALL	CHECKNONE
STOCNT:
	MOV	[TCOUNT],DX
	CALL	GETEOL
	MOV	DX,NEXTCS
	MOV	CSSAVE,DX
	MOV	DX,NEXTIP
	MOV	IPSAVE,DX
STEP:
	MOV	[BRKCNT],0
; The 286 has a problem with trace mode and software interrupt instructions;
; it treats them as atomic operations.	We simulate the operation in software.
	MOV	ES,[CSSAVE]		; Get next instruction pointer
	MOV	DI,[IPSAVE]
	MOV	AL,ES:[DI]		; get next opcode
	cmp	al,0e4h 		; check for 'IN' opcode
	jne	not_inal_op
	cmp	es:byte ptr[di+1],21h
	jne	not_mask_op
	add	[ipsave],2
	JMP	SETalmask

not_inal_op:
	cmp	al,0ech 		; in al,DX ?
	jne	not_mask_op
	cmp	dxsave,21h
	jne	not_mask_op
	add	[ipsave],1
SETalmask:
	mov	ax,[axsave]
	in	al,21h
	mov	[axsave],ax
	JMP	SETENVIRON

not_mask_op:
	CMP	AL,0CDH 		; trace over an interrupt?
	JZ	DOINT			; no, check for other special cases
	CMP	AL,0CEH 		; how about int overflow
	JNZ	CHECKCC
	TEST	FLSAVE,F_OVERFLOW	 ; see it overflow is present
	JZ	CHECKOP
	MOV	BX,4			; INTO = INT 4
	DEC	IPSAVE			; INTO is a singel byte
	JMP	SHORT DOVAL
CHECKCC:
	CMP	AL,0CCH
	JNZ	CHECKOP
	MOV	BX,3			; INT 3 = CC
	DEC	IPSAVE
	JMP	SHORT DOVAL
DOINT:
; We have a software interrupt.  Get destination vector
	MOV	BL,BYTE PTR ES:[DI+1]	; get vector number
	XOR	BH,BH			; clear out upper
DOVAL:
	SHL	BX,1			; word index
	SHL	BX,1			; dword index
	XOR	DI,DI			; interrupt table
	MOV	ES,DI
	MOV	AX,ES:[BX]		; point to vector
	MOV	BX,ES:[BX+2]		; point to vector
; AX:BX is the vector.	Swap it with currect CS:IP
	XCHG	AX,IPSAVE		; new CS:IP
	XCHG	BX,CSSAVE
; AX:BX is old CS:IP.  We 'PUSH' flags, oldCS and oldIP, reset flags (ifl) and
; set CS:IP to point to interrupt instruction.
	MOV	ES,SSSAVE		; point to user stack
	MOV	DI,SPSAVE
; Take old flags and PUSH the flags.
	MOV	CX,FLSAVE		 ; get flags
	SUB	DI,2			; PUSHF
	MOV	ES:[DI],CX		; rest of push
; Push the old CS
	SUB	DI,2			; PUSH CS
	MOV	ES:[DI],BX		; rest of push
; Push the old IP
	SUB	DI,2			; PUSH IP
	ADD	AX,2			; increment IP
	MOV	ES:[DI],AX		; rest of push
; Update stack
	MOV	SPSAVE,DI		; store
; Take flags and turn interrupts off and trace mode off
	AND	CX,NOT F_INTERRUPT	; CLI
	AND	CX,NOT F_TRACE		; no trace
	MOV	FLSAVE,CX		 ; rest of CLI
; Set up correct process and go to normal reentry code.
	IF	NOT SYSVER
	    MOV     BX,[USER_PROC_PDB]
	    MOV     AH,SET_CURRENT_PDB
	    INT     21H
	ENDIF
	JMP	SETENVIRON
; We need to special case the following instructions that may push a TRACE bit
; on the stack:  PUSHF (9C)

; Save the opcode in A Special place
CHECKOP:
	MOV	RSETFLAG,AL		; no bits to turn off
SETTRACE:
	OR	FLSAVE,F_TRACE		 ; Turn on trace bit
	IF	IBMVER
	    CLI
	    IN	    AL,MASK_PORT	; Get current mask
	    JMP     SHORT FOO
FOO:
	    MOV     [OLD_MASK],AL	; Save it
	    MOV     AL,INT_MASK 	; New mask
	    OUT     MASK_PORT,AL	; Set it
	    STI
	ENDIF
DEXIT:
	IF	NOT SYSVER
	    MOV     BX,[USER_PROC_PDB]
	    MOV     AH,SET_CURRENT_PDB
	    INT     21H
	ENDIF
; Unfortunately, any system call we issue will muck with the current extended
; errors.  Here we must restore the extended error state so that if the user
; program gets it, we do not interfere.
	MOV	AX,(SERVERCALL SHL 8) + 10
	MOV	DX,OFFSET DG:SAVESTATE
	INT	21H
	PUSH	DS
	XOR	AX,AX
	MOV	DS,AX
	MOV	WORD PTR DS:[12],OFFSET DG:BREAKFIX ; Set vector 3--breakpoint instruction
	MOV	WORD PTR DS:[14],CS
	MOV	WORD PTR DS:[4],OFFSET DG:REENTER ; Set vector 1--Single step
	MOV	WORD PTR DS:[6],CS
	CLI
	IF	SETCNTC
	    MOV     WORD PTR DS:[8CH],OFFSET DG:CONTC ; Set vector 23H (CTRL-C)
	    MOV     WORD PTR DS:[8EH],CS
	ENDIF
	POP	DS
	MOV	SP,OFFSET DG:STACK
	POP	AX
	POP	BX
	POP	CX
	POP	DX
	POP	BP
	POP	BP
	POP	SI
	POP	DI
	POP	ES
	POP	ES
	POP	SS
	MOV	SP,[SPSAVE]
	PUSH	[FLSAVE]
	PUSH	[CSSAVE]
	PUSH	[IPSAVE]
	MOV	DS,[DSSAVE]
	IRET
STEP1:
	CALL	CRLF
	CALL	DISPREG
	TEST	FZTRACE,-1
	JNZ	STEPZ
	JMP	STEP
STEPZ:	JMP	ZSTEP

; Re-entry point from CTRL-C. Top of stack has address in 86-DOS for
; continuing, so we must pop that off.
CONTC:
	ADD	SP,6
	JMP	SHORT REENTERREAL

; Re-entry point from breakpoint. Need to decrement instruction
; pointer so it points to location where breakpoint actually
; occured.
BREAKFIX:
	PUSH	BP
	MOV	BP,SP
	DEC	WORD PTR [BP].OLDIP
	POP	BP
	JMP	REENTERREAL

; Re-entry point from trace mode or interrupt during execution.  All registers
; are saved so they can be displayed or modified.
INTERRUPT_FRAME STRUC
OLDBP	DW	?
OLDIP	DW	?
OLDCS	DW	?
OLDF	DW	?
OLDERIP DW	?
OLDERCS DW	?
OLDERF	DW	?
INTERRUPT_FRAME ENDS

ASSUME	CS:DG,DS:NOTHING,ES:NOTHING,SS:NOTHING
; ReEnter is the main entry point for breakpoint interrupts and for trace mode
; interrupts.  We treat both of these cases identically:  save state, display
; registers and go for another command.  If we get NMI's, we skip them or if
; it turns out that we are debugging ourselves, we skip them.

; Due to bogosities in the 808x chip, Consider tracing over an interrupt and
; then setting a breakpoint to where the interrupt returns.  You get the INT 3
; and then trace mode gets invoked!  This is why we ignore interrupts within
; ourselves.
REENTER:
	PUSH	BP
	MOV	BP,SP			; get a frame to address from
	PUSH	AX
;	MOV	AX,CS
;	CMP	AX,[BP].OLDCS		; Did we interrupt ourselves?
;	JNZ	GOREENTER		; no, go reenter
	IF	IBMJAPAN
	    MOV     AX,[BP].OLDIP
	    CMP     AX,OFFSET DG:NMIINT ; interrupt below NMI interrupt?
	    JB	    GOREENTER		; yes, go reenter
	    CMP     [BP].OLDIP,OFFSET DG:NMIINTEND
	    JAE     GOREENTER		; interrupt above NMI interrupt?
	    POP     AX			; restore state
	    POP     BP
	    SUB     SP,6		; switch TRACE and NMI stack frames
	    PUSH    BP
	    MOV     BP,SP		; set up frame
	    PUSH    AX			; get temp variable
	    MOV     AX,[BP].OLDERIP	; get NMI Vector
	    MOV     [BP].OLDIP,AX	; stuff in new NMI vector
	    MOV     AX,[BP].OLDERCS	; get NMI Vector
	    MOV     [BP].OLDCS,AX	; stuff in new NMI vector
	    MOV     AX,[BP].OLDERF	; get NMI Vector
	    AND     AH,0FEH		; turn off Trace if present
	    MOV     [BP].OLDF,AX	; stuff in new NMI vector
	    MOV     [BP].OLDERF,AX
	    MOV     [BP].OLDERIP,OFFSET DG:REENTER ; offset of routine
	    MOV     [BP].OLDERCS,CS	; and CS
	    POP     AX
	    POP     BP
	    IRET			; go try again
	ENDIF
GOREENTER:
	IF	IBMVER
	    MOV     AL,CS:[OLD_MASK]	; Recover Old mask
	    OUT     MASK_PORT,AL	; Restore it
	ENDIF
	MOV	AL,CS:[RSETFLAG]
; Determine, based on the previous instruction, what we are supposed to do
; to flags on the users stack.
	CMP	AL,09CH 		; PUSHF
	JNZ	NOFIX
; OlderIP = flags.  Turn off trace bit
	AND	[BP].OLDERIP,NOT F_TRACE
NOFIX:
	POP	AX
	POP	BP
REENTERREAL:
	MOV	CS:[SPSAVE+SEGDIF],SP
	MOV	CS:[SSSAVE+SEGDIF],SS
	MOV	CS:[FLSAVE],CS
	MOV	SS,CS:[FLSAVE]
	MOV	SP,OFFSET DG:RSTACK
	ASSUME	SS:DG

	PUSH	ES
	PUSH	DS
	PUSH	DI
	PUSH	SI
	PUSH	BP
	DEC	SP
	DEC	SP
	PUSH	DX
	PUSH	CX
	PUSH	BX
	PUSH	AX
	PUSH	SS
	POP	DS
	ASSUME	DS:DG

	MOV	SS,[SSSAVE]
	MOV	SP,[SPSAVE]
	ASSUME	SS:NOTHING

	POP	[IPSAVE]
	POP	[CSSAVE]
	POP	AX
	AND	AX,NOT F_TRACE		; TURN OFf trace mode bit
	MOV	[FLSAVE],AX
	MOV	[SPSAVE],SP
SETENVIRON:
	PUSH	DS
	POP	ES
	ASSUME	ES:DG

	PUSH	DS
	POP	SS
	ASSUME	SS:DG

	MOV	SP,OFFSET DG:STACK
	PUSH	DS
	XOR	AX,AX
	MOV	DS,AX
	ASSUME	DS:NOTHING

	IF	SETCNTC
	    MOV     WORD PTR DS:[8CH],OFFSET DG:DABORT ; Set Ctrl-C vector
	    MOV     WORD PTR DS:[8EH],CS
	ENDIF
	POP	DS
	ASSUME	DS:DG

	STI
	CLD
; Since we are about to issue system calls, let's grab the current user's
; extended error info.
	MOV	AH,GETEXTENDEDERROR
	INT	21H
	ASSUME	DS:NOTHING,ES:NOTHING

	MOV	SAVESTATE.DPL_AX,AX
	MOV	SAVESTATE.DPL_BX,BX
	MOV	SAVESTATE.DPL_CX,CX
	MOV	SAVESTATE.DPL_DX,DX
	MOV	SAVESTATE.DPL_SI,SI
	MOV	SAVESTATE.DPL_DI,DI
	MOV	SAVESTATE.DPL_DS,DS
	MOV	SAVESTATE.DPL_ES,ES
	MOV	AX,CS
	MOV	DS,AX
	MOV	ES,AX
	ASSUME	DS:DG,ES:DG

	IF	NOT SYSVER
	    MOV     AH,GET_CURRENT_PDB
	    INT     21H
	    MOV     [USER_PROC_PDB],BX
	    MOV     BX,BEGSEG
	    MOV     AH,SET_CURRENT_PDB
	    INT     21H
	ENDIF
	MOV	SI,OFFSET DG:BPTAB
	MOV	CX,[BRKCNT]
	JCXZ	SHOREG
	PUSH	ES
CLEARBP:
	LES	DI,DWORD PTR [SI]
	ADD	SI,4
	MOVSB
	LOOP	CLEARBP
	POP	ES
SHOREG:
	DEC	[TCOUNT]
	JZ	CHECKDISP
	JMP	STEP1
CHECKDISP:
	CALL	CRLF
	CALL	DISPREG
	JMP	COMMAND

; Input from the specified port and display result
INPUT:
	MOV	CX,4			; Port may have 4 digits
	CALL	GETHEX			; Get port number in DX
	CALL	GETEOL

	IN	AL,DX			; Variable port input

	PUSH	CS
	POP	ES
	MOV	DI,OFFSET DG:ARG_BUF
	CALL	HEX			; And display

	XOR	AL,AL
	STOSB
	MOV	DX,OFFSET DG:ARG_BUF_PTR
	JMP	PRINTF_CRLF

; Output a value to specified port.
OUTPUT:
	MOV	CX,4			; Port may have 4 digits
	CALL	GETHEX			; Get port number
	PUSH	DX			; Save while we get data
	MOV	CX,2			; Byte output only
	CALL	GETHEX			; Get data to output
	CALL	GETEOL
	XCHG	AX,DX			; Output data in AL
	POP	DX			; Port in DX

	OUT	DX,AL			; Variable port output

	RETURN

SETADD:
	MOV	DX,CSSAVE		; set up start addresses
	MOV	NEXTCS,DX
	MOV	DX,IPSAVE
	MOV	NEXTIP,DX
	MOV	BP,[CSSAVE]
	CALL	SCANP
	CMP	BYTE PTR [SI],"="
	RETNZ
	INC	SI
	CALL	ADDRESS
	MOV	NEXTCS,AX
	MOV	NEXTIP,DX
	RETURN

; Jump to program, setting up registers according to the
; save area. up to 10 breakpoint addresses may be specified.
GO:
	MOV	RSETFLAG,0
	CALL	SETADD
	XOR	BX,BX
	MOV	DI,OFFSET DG:BPTAB
GO1:
	CALL	SCANP
	JZ	DEXEC
	MOV	BP,[CSSAVE]
	PUSH	DI
	PUSH	BX			;AN000; DMS;SAVE BX - ADDRESS KILLS IT
	CALL	ADDRESS
	POP	BX			;AN000; DMS;RESTORE BX
	POP	DI
	MOV	[DI],DX 		; Save offset
	MOV	[DI+2],AX		; Save segment
	ADD	DI,5			; Leave a little room
	INC	BX
	CMP	BX,1+BPMAX
	JNZ	GO1
	MOV	DX,OFFSET DG:BP_ERROR	; BP ERROR
	JMP	ERR
DEXEC:
	MOV	[BRKCNT],BX
	MOV	CX,BX
	JCXZ	NOBP
	MOV	DI,OFFSET DG:BPTAB
	PUSH	DS
SETBP:
	LDS	SI,ES:DWORD PTR [DI]
	ADD	DI,4
	MOVSB
	MOV	BYTE PTR [SI-1],0CCH
	LOOP	SETBP
	POP	DS
NOBP:
	MOV	DX,NEXTCS
	MOV	CSSAVE,DX
	MOV	DX,NEXTIP
	MOV	IPSAVE,DX
	MOV	[TCOUNT],1
	JMP	DEXIT

SKIP_FILE:
	MOV	AH,CHAR_OPER
	INT	21H
	MOV	CS:[SWITCHAR],DL	; GET THE CURRENT SWITCH CHARACTER
FIND_DELIM:
	LODSB
	CALL	DELIM1
	JZ	GOTDELIM
	CALL	DELIM2
	JNZ	FIND_DELIM
GOTDELIM:
	DEC	SI
	RETURN

COMPARE:
	CALL	DSRANGE
	PUSH	CX
	PUSH	AX
	PUSH	DX
	CALL	ADDRESS 		; Same segment
	CALL	GETEOL
	POP	SI
	MOV	DI,DX
	MOV	ES,AX
	POP	DS
	POP	CX			; Length
	DEC	CX
	CALL	COMP			; Do one less than total
	INC	CX			; CX=1 (do last one)
COMP:
	REPE	CMPSB
	RETZ
; Compare error. Print address, value; value, address.
	DEC	SI
	MOV	CS:COMP_ARG1,DS
	MOV	CS:COMP_ARG2,SI
	XOR	AH,AH
	LODSB
	MOV	CS:COMP_ARG3,AX
	DEC	DI
	MOV	AL,ES:[DI]
	MOV	CS:COMP_ARG4,AX
	MOV	CS:COMP_ARG5,ES
	MOV	CS:COMP_ARG6,DI
	INC	DI
	PUSH	DS
	PUSH	CS
	POP	DS
	MOV	DX,OFFSET DG:COMP_PTR
	CALL	PRINTF_CRLF
	POP	DS
	XOR	AL,AL
	JMP	SHORT COMP

	PROCEDURE CHECKNONE,NEAR
	OR	DX,DX
	RETNZ
	MOV	DX,OFFSET DG:SYNERR_PTR ; ERROR MESSAGE
	JMP	PERR
	ENDPROC CHECKNONE

CODE	ENDS
	END	DEBCOM3