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
|