DOS-debug

Форк
0
/
DISASM.INC 
1788 строк · 37.1 Кб
1

2
;   Here is the start of the disassembly part of the program.
3

4
;--- flag bits preflags/preused
5

6
PRESEG	equ 1		;segment prefix
7
PREREP	equ 2		;rep prefixes
8
PREREPZ	equ 4		;f3, not f2
9
PRELOCK	equ 8		;lock prefix
10
PRE32D	equ 10h		;flag for operand size (66h)
11
PRE32A	equ 20h		;flag for address size (67h)
12
PREWAIT	equ 40h		;prefix wait (not really a prefix)
13
GOTREGM	equ 80h		;preused only: set if we have the reg/mem part
14

15
;--- equates for disflags:
16

17
DIS_F_REPT		equ 1	;repeat after pop ss, etc.
18
DIS_F_SHOW		equ 2	;show memory contents
19
DIS_I_SHOW		equ 4	;there are memory contents to show
20
DIS_I_UNUSED	equ 8	;(internal) print " (unused)"
21
DIS_I_SHOWSIZ	equ 10h	;(internal) always show the operand size
22
DIS_I_KNOWSIZ	equ 20h	;(internal) we know the operand size of instr.
23
DIS_I_MEMACC	equ 80h	;(internal) we're just accessing a mem ref ( dumpreg )
24

25
OT macro num
26
	exitm <num&h+OPTYPES_BASE>
27
endm
28

29
;--- define "general purpose register"
30
DefGPR macro regist
31
REG_&regist& equ ($ - rgnam816)/2
32
	db "&regist&"
33
endm
34

35
;--- register table
36
;---  0- 7: 8-bit registers
37
;---  8-15: 16-bit registers
38
;--- 16-23: 32-bit registers
39

40
REG_NO_GPR	equ 24
41

42
;--- define "segment register"
43
DefSR macro regist
44
REG_&regist& equ REG_NO_GPR + ($ - segrgnam)/2
45
	db "&regist&"
46
endm
47

48
_DATA segment
49

50
dis_n	dw 0		;number of bytes in instruction so far
51
		dw 0		;must follow dis_n (will always remain 0)
52
idxins	dw 0		;index of the instruction (unsqueezed)
53
addrr	dw 0		;address in mod r/m byte (16bit only)
54
sizeloc dw 0		;address of size words in output line
55

56
;--- preflags and preused must be consecutive
57
preflags db 0		;flags for prefixes found so far
58
preused  db 0		;flags for prefixes used so far
59

60
bInstr	db 0		;the main instruction byte
61
rmsize	db 0		;<0 or 0 or >0 means mod r/m is 8 or 16 or 32
62
segmnt	db 0		;segment determined by prefix (or otherwise)
63
disflags db 0		;flags for the disassembler
64
disflags2 db 0		;another copy of DIS_I_KNOWSIZ
65

66
_DATA ends
67

68
CONST segment
69

70
	include <DISTBL.INC>
71

72
;--- table of obsolete-instruction values.
73
;--- instructions are FENI, FDISI, FSETPM, MOV to/from TRx
74
obsinst	dw SFPGROUP3, SFPGROUP3+1, SFPGROUP3+4
75
		dw SPARSE_BASE+24h, SPARSE_BASE+26h
76

77
;--- Table for 16-bit mod r/m addressing.  8 = BX, 4 = BP, 2 = SI, 1 = DI.
78

79
rmtab	db 8+2, 8+1, 4+2, 4+1, 2, 1, 4, 8
80

81
;--- Tables of register names.
82
;--- rgnam816/rgnam16/segrgnam must be consecutive.
83
;--- also used by the line assembler
84

85
rgnam816 label word
86
	DefGPR AL
87
	DefGPR CL
88
	DefGPR DL
89
	DefGPR BL
90
	DefGPR AH
91
	DefGPR CH
92
	DefGPR DH
93
	DefGPR BH
94
rgnam16 label word
95
	DefGPR AX
96
	DefGPR CX
97
	DefGPR DX
98
	DefGPR BX
99
	DefGPR SP
100
	DefGPR BP
101
	DefGPR SI
102
	DefGPR DI
103
N_REGS16 equ ( $ - rgnam16 ) / 2
104
segrgnam label word
105
	DefSR ES
106
	DefSR CS
107
	DefSR SS
108
	DefSR DS
109
	DefSR FS
110
	DefSR GS
111
N_SEGREGS equ ( $ - segrgnam ) / 2
112
	DefSR ST
113
	DefSR MM
114
	DefSR CR
115
	DefSR DR
116
	DefSR TR
117
N_ALLREGS equ ( $ - rgnam816 ) / 2
118

119
;--- address of debuggee's segment registers
120
;--- used to display memory contents ( DIS_F_SHOW )
121
segrgaddr dw regs.rES,regs.rCS,regs.rSS,regs.rDS
122
if RING0	; for DebugR, we also display FS/GS contents
123
	dw regs.rFS, regs.rGS
124
endif
125

126
;--- Tables for handling of named prefixes.
127

128
prefixlist	db 26h,2eh,36h,3eh,64h,65h	;segment prefixes (in order)
129
			db 9bh,0f0h,0f2h,0f3h		;WAIT,LOCK,REPNE,REPE
130
N_PREFIX equ $ - prefixlist
131
prefixmnem	dw MN_WAIT,MN_LOCK,MN_REPNE,MN_REPE
132

133
CONST ends
134

135
disasm1:				;<--- standard entry
136
	mov al, 0
137

138
disasm proc				;<--- entry with AL=disflags ( DIS_F_REPT & DIS_F_SHOW )
139

140
	mov [disflags], al
141

142
CONST segment	; must be located inside disasm since local labels are used here
143

144
	align 2
145

146
;   Jump table for OP_IMM, OP_RM, OP_M, OP_R_MOD, OP_MOFFS, OP_R, OP_R_ADD,
147
;   and OP_AX.
148
;   See orders of asm_jmp1 and bittab.
149

150
dis_jmp1 label word
151
	dw dop_imm, dop_rm, dop_m, dop_r_mod
152
	dw dop_moffs, dop_r, dop_r_add, dop_ax
153

154
;   jump table for displaying operands
155
;   See orders of asm_jmp1 and bittab.
156

157
dis_optab label word
158
	dw dop_m64, dop_mfloat, dop_mdouble, dop_m80, dop_mxx,  dop_farmem	;00-05
159
	dw dop_farimm, dop_rel8, dop_rel1632								;06-08
160
	dw dop_st1, dop_sti,     dop_cr										;09-11
161
	dw dop_dr,   dop_tr,     dop_segreg,  dop_imms8						;12-15
162
	dw dop_imm8, dop_mmx,    dop_shosiz									;16-18
163
;--- string items OP_1 .. OP_SS
164
	db '1',0	;19
165
	db '3',0	;20
166
	db 'DX'		;21
167
	db 'CL'		;22
168
	db 'ST'		;23
169
	db 'CS','DS','ES','FS','GS','SS'	;24-29
170

171
;--- Jump table for a certain place.
172
;--- the size of this table matches OPTYPES_BASE
173

174
dis_jmp2 label word
175
	dw disbad		;illegal instruction
176
	dw da_twobyte	;two byte instruction (0F xx)
177
	dw da_insgrp	;instruction group
178
	dw da_fpuins	;coprocessor instruction
179
	dw da_fpugrp	;coprocessor instruction group
180
	dw da_insprf	;instruction prefix (including 66h/67h)
181
OPTYPES_BASE equ $ - dis_jmp2
182

183
CONST ends
184

185
if FLATSS
186
	.386
187
;	mov [savesp2],esp
188
	mov [run_sp],esp
189
else
190
;	mov [savesp2],sp
191
	mov [run_sp],sp
192
endif
193
	xor ax,ax
194
	mov [dis_n],ax
195
	mov word ptr [preflags],ax	;clear preflags and preused
196
if ?PM
197
	mov bx,[u_addr+4]
198
	call getseldefsize
199
	mov [bCSAttr],al
200
endif
201
	mov [segmnt],3			;initially use DS segment
202
	mov [rmsize],80h		;signed byte (-128): don't display any memory
203
	mov word ptr [ai.dismach],0;no special machine needed, so far
204
	call disgetbyte			;get a byte of the instruction
205
	cmp al,9bh				;wait instruction (must be the first prefix)
206
	jne da2					;if not
207

208
;   The wait instruction is actually a separate instruction as far as
209
;   the x86 is concerned, but we treat it as a prefix since there are
210
;   some mnemonics that incorporate it.  But it has to be treated specially
211
;   since you can't do, e.g., seg cs wait ... but must do wait seg cs ...
212
;   instead.  We'll catch it later if the wait instruction is not going to
213
;   be part of a shared mnemonic.
214

215
	or [preflags],PREWAIT
216

217
;   If we've found a prefix, we return here for the actual instruction
218
;   (or another prefix).
219

220
da1:
221
	call disgetbyte
222
da2:
223
	mov [bInstr],al	;save away the instruction
224
	mov ah,0
225

226
;--- Now we have the sequence number of the instruction in AX.  Look it up.
227

228
da3:
229
	mov bx,ax
230
	mov [idxins],ax	;save the compressed index
231
	cmp ax,SPARSE_BASE
232
	jb @F			;if it's not from the squeezed part of the table
233
	mov bl,[sqztab+bx-SPARSE_BASE]
234
	mov bh,0
235
	add bx,SPARSE_BASE	;bx = compressed index
236
@@:
237
	mov cl,[optypes+bx]	;cx = opcode type
238
	mov ch,0
239
	shl bx,1
240
	mov bx,[opinfo+bx]	;bx = other info (mnemonic if a true instruction)
241
	mov si,cx
242
	mov ax,bx
243
	mov cl,12
244
	shr ax,cl
245
	cmp al,[ai.dismach]
246
	jb @F				;if a higher machine is already required
247
	mov [ai.dismach],al	;set machine type
248
@@:
249
	and bh,0fh			;=and bx,0fffh - remove the machine field
250
	cmp si,OPTYPES_BASE
251
	jae da13			;if this is an actual instruction
252
	call [dis_jmp2+si]	;otherwise, do more specific processing
253
	jmp da3				;back for more
254

255
;--- dis_jmp2[1]: Two-byte instruction 0F xx: index 1E0-2DF.
256

257
da_twobyte:
258
	call disgetbyte
259
	mov [bInstr],al
260
	mov ah,0
261
	add ax,SPARSE_BASE
262
	ret
263

264
;--- dis_jmp2[2]: Instruction group.
265
;--- BX contains "instruction base": 100h, 110h, ...
266

267
da_insgrp:
268
	call getregmem_r	;get the middle 3 bits of the R/M byte
269
	cbw
270
	add ax,bx			;offset
271
	ret
272

273
;--- dis_jmp2[3]: Coprocessor instruction.
274
;--- BX contains "instruction base": 148h, 158h, ...
275

276
da_fpuins:
277
	or [disflags], DIS_I_SHOWSIZ
278
	or [ai.dmflags], DM_COPR
279
	call getregmem
280
	cmp al,0c0h
281
	jb da_insgrp	;range 00-bfh is same as an instruction group
282
	mov cl,3
283
	shr al,cl		;C0-FF --> 18-1F
284
	sub al,18h-8	;18-1F --> 08-0F
285
	cbw
286
	add ax,bx		;offset
287
	ret
288

289
;--- dis_jmp2[4]: Coprocessor instruction group.
290
;--- BX contains "instruction base": 1C8h, 1D0h, 1D8h
291

292
da_fpugrp:
293
	mov al,[ai.regmem]
294
	and al,7
295
	cbw
296
	add ax,bx
297
	ret
298

299
;--- dis_jmp2[5]: Instruction prefix.  At this point, bl = prefix bits; bh = segment
300

301
da_insprf:
302
if 0	; v2.01: removed - opsize/adrsize prefixes "toggle" just once
303
	mov al,bl
304
	and bl,not (PRE32D or PRE32A)	;these flags are XORed!
305
endif
306
	test bl,[preflags]
307
	jnz disbad0		;if there are duplicates
308
	or [preflags],bl
309
	test bl,PRESEG
310
	jz @F			;if not a segment
311
	mov [segmnt],bh	;save the segment
312
@@:
313
	pop ax			;discard return address
314
	jmp da1
315

316
disbad0:
317
	jmp disbad		;we don't allow duplicate prefixes
318

319

320
da13:
321
	sub si, OPTYPES_BASE
322

323
;--- here: si=index for opindex to scan oplists table
324

325
da13a::
326
	mov ax, word ptr [opindex][si]
327
	mov [bEndOplItem], ah
328
	mov ah, 00
329
	mov si, ax
330

331
if ?PM ; v2.01: update opsize/adrsize prefixes if D bit set AFTER prefixes have been read
332
	test [bCSAttr], CS32
333
	jz @F
334
	xor [preflags], PRE32D or PRE32A
335
@@:
336
endif
337

338
;   OK.  Here we go.  This is an actual instruction.
339
;   BX=offset of mnemonic in mnlist
340
;   SI=offset of operand list in oplists
341
;   First print the op mnemonic.
342

343
	push si
344
	lea si,[mnlist+bx]	;offset of mnemonic
345
	cmp si,offset mnlist+MN_BSWAP
346
	jne @F				;if not BSWAP
347
	call dischk32d
348
	jz disbad0			;if no operand-size prefix
349
@@:
350
	call showop			;print out the op code (at line_out+28)
351
	mov [sizeloc],0		;clear out this flag
352
	pop si				;recover list of operands
353
	add si,offset oplists
354

355
;   Loop over operands.  si -> operand type.
356
;   Fortunately the operands appear in the instruction in the same
357
;   order as they appear in the disassembly output.
358

359
da14:
360
	mov ax, si
361
	sub ax, offset oplists
362
	cmp al, [bEndOplItem]
363
	jae da21				;if we're done
364
	mov [disflags2],0		;clear out size-related flags
365
	lodsb					;get the operand type
366
	cmp al,OP_SIZE
367
	jb da18					;if it's not size dependent
368
	mov [disflags2],DIS_I_KNOWSIZ	;indicate variable size
369
	cmp al,OP_8
370
	jae da16				;if the size is fixed (8,16,32,64)
371
	cmp al,OP_1632
372
	jae da15				;if word or dword
373
	mov ah,-1
374
	test [bInstr],1
375
	jz da17					;if byte
376
da15:
377
	or [preused], PRE32D	;mark this flag as used
378
	mov ah,[preflags]
379
	and ah, PRE32D			;this will be 10h for dword, 00h for word
380
	jmp da17				;done
381

382
da16:
383
	mov ah,al		;OP_8, OP_16, OP_32 or OP_64 (we know which)
384
	and ah,0f0h		;this converts ah to <0 for byte, =0 for word,
385
	sub ah,OP_16	;and >0 for dword (byte=F0,word=0,dword=10,qword=20)
386

387
;--- Now we know the size (in ah); branch off to do the operand itself.
388

389
da17:
390
	mov bl,al
391
	and bx,0eh			;8 entries (IMM, RM, M, R_MOD, M_OFFS, R, R_ADD, AX)
392
	call [dis_jmp1+bx]	;print out the operand
393
	jmp da20			;done with operand
394

395
;--- Sizeless operands.
396

397
da18:
398
	cbw
399
	cmp al, OP_STR
400
	xchg ax,bx			; mov bx, ax
401
	mov ax,[dis_optab+bx-2]
402
	jb @F				;if it's not a string
403
	stosw
404
	cmp ah,0
405
	jnz da20			;if it's two characters
406
	dec di
407
	jmp da20			;done with operand
408
@@:
409
	call ax				;otherwise, do something else
410
da20:
411
	mov al,','
412
	stosb
413
	jmp da14			;check for another operand
414

415
;--- all operands done.
416

417
;-------------------------------------------------------------------
418
;--- now check and loop for unused prefixes:
419
;--- OPSIZE (66h), ADDRSIZE (67h), WAIT, segment, REP[N][Z], LOCK
420

421
;--- v2.50: the string instructions may have both 66h & 67h prefixes.
422
;--- a 67h prefix will now be shown as a comment behind the opcode.
423
;--- this code has been reworked.
424

425
CONST segment
426

427
txflags label byte
428
	db PREWAIT			; a WAIT prefix hanging
429
	db PRE32D			; opsize 66h
430
	db PRE32A			; adrsize 67h
431
	db PRESEG
432
	db PREREP or PREREPZ
433
	db PRELOCK
434

435
txsize label byte	; items in txtabs tables
436
	db N_WTAB
437
	db N_LTABO
438
	db N_LTABA
439
	db N_PRFXTAB
440
	db N_REPNC
441
	db N_LOCK
442

443
txtabs label word
444
	dw offset wtab1
445
	dw offset ltabo1
446
	dw offset ltaba1
447
	dw offset prfxtab	; movsb/w, outsb/w, cmpsb/w, lodsb/w, xlat
448
	dw offset replist
449
	dw offset locktab
450

451
txprocs label word
452
	dw hdl_wait
453
	dw hdl_d32
454
	dw hdl_a32
455
	dw hdl_seg
456
	dw hdl_rep
457
	dw hdl_lock
458

459
strinstr label byte
460
	db 6ch,6dh,6eh,6fh		; ins, outs
461
	db 0A4h,0A5h,0A6h,0A7h	; movs, cmps, lods, scas, stos
462
	db 0AAh,0ABh,0ACh,0ADh,0AEh,0AFh
463
szA32 db ";A32"
464
if ?PM
465
szA16 db ";A16"
466
endif
467
CONST ends
468

469
;--- preflags:
470
;--- CS 16-bit: if PRE32x == 1, a prefix has been found.
471
;--- + PRE32D == 0: nothing done
472
;--- + PRE32D == 1: CS=32: scan opc table, fnd: switch opcode, notfnd:bad prefix
473
;--- + PRE32A == 0: nothing done
474
;--- + PRE32A == 1: CS=32, scan opc table, fnd: switch opcode, notfnd: check str instr
475
;--- CS 32-bit: if PRE32x == 1, no prefix has been found.
476
;--- + PRE32D == 0, CS=16: scan opc table, fnd: exit, notfnd: bad prefix
477
;--- + PRE32D == 1, CS=32: scan opc table, fnd: switch opcodes, notfnd: exit
478
;--- + PRE32A == 0, CS=16: scan opc table, fnd: exit, notfnd: check str instr
479
;--- + PRE32A == 1, CS=32: scan opc table, fnd: switch opcodes, notfnd: check str instr
480

481
;--- note: a prefix might be marked as "used" already. In this case it must be skipped!
482

483
;--- di=current output in line_out
484
;--- may be changed by the prefix loop if a prefix has to be inserted.
485

486
da21:
487
	cmp byte ptr [di-1],','	; skip the comma behind the last operand
488
	jnz @F
489
	dec di
490
@@:
491
;	@dprintf "da21, di=%X", di
492
	xor bx, bx
493
nextflag:
494
	mov ax, word ptr [preflags]	; ah=preused
495
if ?PM
496
	test [bCSAttr], CS32
497
	jz @F
498
;--- if CS is 32bit, checks for A32 must be done in any case.
499
;--- to detect unused 66h prefixes, PRE32D is to be set as well.
500
	or al, PRE32A or PRE32D
501
@@:
502
endif
503
	not ah
504
	and al, ah			;skip flags that are set in preused
505
	test al,[bx][txflags]
506
	jz @F
507
	mov ax,[idxins]
508
	mov cl,[bx][txsize]
509
	mov ch,0
510
	push bx
511
	shl bx,1
512
	mov dx,[bx][txtabs]
513
	call [bx][txprocs]
514
	pop bx
515
	mov al,[bx][txflags]
516
	or [preused], al	;mark this prefix as used
517
@@:
518
	inc bx
519
	cmp bx, 6
520
	jb nextflag
521
;	@dprintf "da21 done: preflags=%X", word ptr preflags
522
	jmp da_done
523

524
hdl_scan_table:
525
	push di
526
	mov di, dx
527
	push cx
528
	repne scasw
529
	pop cx
530
	jnz @F
531
	dec cx
532
	shl cx, 1
533
	add di,cx		;position DI for opcode replacement
534
	mov si,[di]
535
	add si,offset mnlist
536
	xor cx, cx		;ZF=1
537
@@:
538
	pop di
539
	ret
540

541
ife ?PM
542
hdl_d32:
543
endif
544
hdl_wait:
545
	call hdl_scan_table
546
	jnz disbad2
547
	jmp hdl_showop		;copy op mnemonic, preserve di
548

549
if ?PM
550
hdl_d32:
551
	test [bCSAttr], CS32		; nothing special if CS is 16-bit
552
	jz hdl_wait
553
	@dprintf "hdl_d32, scan opcode tab, preflags=%X", word ptr [preflags]
554
	call hdl_scan_table
555
	jnz @F
556
	@dprintf "hdl_d32, CS=32: opcode found"
557
	test [preflags], PRE32D	; 66h prefix in CS32 code?
558
	jz hdl_d32_ex			; if yes: exit
559
	jmp hdl_showop			; if no: switch opcode to 32-bit
560
@@:
561
	@dprintf "hdl_d32, opcode not found"
562
	test [preflags], PRE32D	; 66h prefix in CS32 code?
563
	jz disbad2				; if yes: bad 66h prefix
564
hdl_d32_ex:
565
	ret
566
endif
567

568
hdl_a32:
569
	call hdl_scan_table		; check for the few opcodes that change with 67h prefix (LOOPx,JCXZ)
570
	jnz @F
571
	@dprintf "hdl_a32, opcode found"
572
if ?PM
573
	test [preflags], PRE32A	; CS32?
574
	jz hdl_a32_ex			; if no, do nothing
575
endif
576
	jmp hdl_showop			; switch opcode if found
577
@@:
578
	@dprintf "hdl_a32, opcode not found"
579
if ?PM
580
	test [bCSAttr], CS32
581
	jz @F
582
	test [preflags], PRE32A	; 32bit and a true 67h prefix in code stream?
583
	jnz hdl_a32_ex			; if no, do nothing
584
@@:
585
endif
586
	@dprintf "hdl_a32, true 67h prefix, testing string instr"
587
	push di
588
	mov di, offset strinstr
589
	mov cx, 14
590
	repnz scasb
591
	pop di
592
	jnz disbad2
593
	mov si,offset szA32
594
if ?PM
595
	test [bCSAttr], CS32
596
	jz @F
597
	mov si,offset szA16
598
@@:
599
endif
600
	movsw
601
	movsw
602
hdl_a32_ex:
603
	ret
604

605
disbad2:
606
	jmp disbad
607

608
hdl_seg:
609
	@dprintf "hdl_seg, ax=%X dx=%X, cx=%X", ax, dx, cx
610
	cmp ah,0
611
	jnz disbad2		;if index > 256
612
	push di
613
	mov di,dx
614
	repne scasb
615
	pop di
616
	jne disbad2		;if it's not on the list
617
	mov cx,3
618
	call moveover
619
	push di
620
	mov di,offset line_out+MNEMONOFS
621
	call showseg	;show segment register
622
	mov al,':'
623
	stosb
624
	pop di
625
;	or [preused],PRESEG		;mark it as used
626
	ret
627

628
;--- ax=instr, cx=items in table, dx=offset table
629

630
hdl_rep:
631
	cmp ah,0
632
	jnz disbad2		;if not in the first 256 bytes
633
	and al,not 1	;clear bit0 (MOVSW -> MOVSB)
634
	push di
635
	mov di,dx		;scan those for REP first
636
	repne scasb
637
	mov si,offset mnlist+MN_REP
638
	je hdl_insprf	;if one of the REP instructions
639
	mov cl,N_REPALL - N_REPNC
640
	repne scasb
641
	jne disbad2		;if not one of the REPE/REPNE instructions
642
	mov si,offset mnlist+MN_REPE
643
;	test [preused],PREREPZ		; v2.50: isn't set yet with the new code,
644
	test [preflags],PREREPZ		; but we may use [preflags].
645
	jnz hdl_insprf	;if REPE
646
	mov si,offset mnlist+MN_REPNE
647
	jmp hdl_insprf	;it's REPNE
648

649
hdl_lock:
650
	push di
651
	mov di,dx
652
	repne scasw
653
	jne disbad2		;if not in the approved list
654
	test [preused],PRESEG
655
	jz disbad2		;if memory was not accessed
656
	mov si,offset mnlist+MN_LOCK
657
;	or [preused],PRELOCK
658

659
;--- Slip in another mnemonic: REP/REPE/REPNE/LOCK.
660
;--- SI = offset of mnemonic, what should be
661
;--- DI is on the stack.
662

663
hdl_insprf:
664
	pop di
665
	mov cx,8
666
	push si
667
	call moveover
668
	pop si
669
hdl_showop:
670
	push di
671
	call showop
672
	pop di
673
	ret
674

675
;--- Done with instruction.  Erase the size indicator, if appropriate.
676

677
da_done:
678
	mov cx,[sizeloc]
679
	cmp cx,0
680
	jz da28b		;if there was no size given
681
	mov al,[disflags]
682
	test al,DIS_I_SHOWSIZ
683
	jnz da28b		;if we need to show the size
684
	test al,DIS_I_KNOWSIZ
685
	jz da28b		;if the size is not known already
686
	xchg cx,di
687
	mov si,di		;save old di
688
	mov al,' '
689
@@:
690
	scasb			;skip size name
691
	jne @B			;if not done yet
692
					;(The above is the same as repne scasb, but
693
					;has no effect on cx.)
694
	add di,4		;skip 'PTR '
695
	xchg si,di
696
	sub cx,si
697
	rep movsb		;move the line
698

699
;--- Now we're really done.  Print out the bytes on the left.
700

701
da28b:
702
	push di		;print start of disassembly line
703
	mov di,offset line_out
704
	@dispsegm [u_addr+4];print segment part of address
705
	mov al,':'
706
	stosb
707
	sizeprfX			;mov eax,[u_addr+0]
708
	mov ax,[u_addr+0]
709
	call DispOfs
710
	mov al,' '
711
	stosb
712
	mov bx,[dis_n]
713
@@:
714
	mov si,offset line_out+MNEMONOFS - 1
715
	sub si, di
716
	shr si, 1
717
	cmp bx,si
718
	jle da29		;if it's a short instruction which fits in one line
719
	sub bx,si
720
	push bx
721
	mov bx,si
722
	push di
723
	call disshowbytes
724
	call putsline
725
	pop cx
726
	pop bx
727
	mov di,offset line_out
728
	sub cx,di
729
	mov al,' '
730
	rep stosb
731
	jmp @B
732
da29:
733
	call disshowbytes
734
	mov al,' '		;pad to op code
735
	mov cx,offset line_out+MNEMONOFS
736
	sub cx,di
737
	jc @F
738
	rep stosb
739
@@:
740
	pop di
741
	test [disflags], DIS_I_UNUSED
742
	jz da32			;if we don't print ' (unused)'
743
	mov si,offset unused
744
	cmp byte ptr [di-1],' '
745
	jne @F			;if there's already a space here
746
	inc si
747
@@:
748
	call copystring	;si->di
749

750
;--- Print info. on minimal processor needed.
751

752
da32:
753
	push di
754
	mov di,offset obsinst
755
	mov cx,[idxins]
756
	call showmach	;show the machine type, if needed
757
	pop di
758
	jcxz da32f		;if no message
759

760
;--- Print a message on the far right.
761

762
	mov ax,offset line_out+79
763
	sub ax,cx
764
	push cx
765
	call tab_to		;tab out to the location
766
	pop cx
767
	rep movsb		;copy the string
768
	jmp da32z		;done
769

770
;--- Dump referenced memory location.
771
;--- v2.50: skip this if instruction is LEA!
772

773
da32f:
774
	mov al,[disflags]
775
	xor al,DIS_F_SHOW + DIS_I_SHOW
776
	test al,DIS_F_SHOW + DIS_I_SHOW
777
	jnz da32z		;if there is no memory location to show
778

779
	cmp [bInstr], 8Dh	; v2.50: don't show mem contents for lea!
780
	jz da32z
781

782
ife RING0			; for DebugR, FS/GS memory contents aren't skipped
783
	cmp [segmnt],3 
784
	ja da32z		;if FS or GS
785
endif
786
	mov ax,offset line_out+79-8	; room for ss:oooo=bb|wwww|dddddddd
787
	mov cx,2
788
	cmp [rmsize],0
789
	jl da32h		;if byte
790
	jz @F			;if word
791
	add cx, 4		; 4 more chars
792
@@:
793
	add cx, 2		; 2 more chars
794
da32h:
795
	sub ax, cx
796
	push cx
797
	call tab_to
798
	call showseg		;show segment register
799
	mov al,':'
800
	stosb
801
	mov ax,[addrr]
802
	call hexword		;show offset
803
	mov al,'='
804
	stosb
805
	mov al,[segmnt]		;segment number
806
	cbw
807
	shl ax,1
808
	xchg ax,bx			;mov bx,ax
809
	mov bx,[segrgaddr+bx] ;get address of value
810
if ?PM
811
;--- v2.0: we don't want that just msg "General Protection Fault"
812
;--- appears, without a hint what the underlying problem is.
813
;--- so display what's rendered so far...
814
	call puts
815
	or [disflags], DIS_I_MEMACC	; tell exc handler to print a crlf first
816
	mov di, offset line_out
817
endif
818
	pop cx
819
	shr cl, 1
820
;--- v2.0: just read the bytes that the instruction would
821
	push ds
822
	@movs ds, [bx]
823
ds_is_set:
824
	mov bx, cs:[addrr]
825
	add bx, cx
826
@@:
827
	dec bx
828
	mov al, [bx]
829
	call hexbyte	;display byte
830
	dec cl
831
	jnz @B
832
	pop ds
833
if ?PM
834
	and [disflags], not DIS_I_MEMACC
835
endif
836

837
da32z:
838
	call trimputs	;print (rest of) disassembled line
839
	mov al,[disflags]
840
	test al,DIS_F_REPT
841
	jz da34			;if we're not allowed to repeat ourselves
842
	test al,DIS_I_UNUSED
843
	jnz @F			;if we printed ' (unused)'
844
	mov ax,[idxins]
845
	cmp ax,17h
846
	je @F			;if it was 'pop ss'
847
	cmp ax,8eh
848
	je @F			;if it was 'mov ss,--'
849
	cmp ax,0fbh
850
	jne da34		;if it was not 'sti'
851
@@:
852
	jmp disasm1
853
da34:
854
	ret
855

856
;--- MOD R/M (OP_RM)
857

858
dop_rm:
859
	call getregmem
860
	cmp al,0c0h
861
	jb dop05
862
	jmp dop_r1			;if pure register reference
863
dop05:					;<--- used by OP_M, OP_M64, OP_M80
864
	call showsize		;print out size in AH
865
dop06:					;<--- used by OP_MOFFS, OP_MXX, OP_MFLOAT, OP_MDOUBLE
866
	or [preused],PRESEG	;needed even if there's no segment override
867
						;because handling of LOCK prefix relies on it
868
	test [preflags],PRESEG
869
	jz @F				;if no segment override
870
	call showseg		;print segment name
871
	mov al,':'
872
	stosb
873
@@:
874
	mov al,[ai.regmem]
875
	and al,0c7h
876
	or [preused], PRE32A
877
	test [preflags], PRE32A
878
	jz @F
879
	jmp dop18		;if 32-bit addressing
880
@@:
881
	or [disflags], DIS_I_SHOW	;we'd like to show this address
882
	mov [addrr],0	; zero out the address initially
883
	cmp al,6
884
	xchg ax,bx		;mov bx,ax
885
	mov al,'['
886
	stosb
887
	je dop16		;if [xxxx]
888
	and bx,7
889
	mov bl,[rmtab+bx]
890
	test bl,8
891
	jnz dop09		;if BX
892
	test bl,4
893
	jz dop11		;if not BP
894
	mov ax,'PB'		;"BP"
895
	mov cx,[regs.rBP]
896
	test [preflags],PRESEG
897
	jnz dop10		;if segment override
898
	dec [segmnt]	;default is now SS
899
	jmp dop10
900
dop09:
901
	mov ax,'XB'		;"BX"
902
	mov cx,[regs.rBX]
903

904
dop10:
905
	mov [addrr],cx	;print it out, etc.
906
	stosw
907
	test bl,2+1
908
	jz dop13		;if done
909
	mov al,'+'
910
	stosb
911
dop11:
912
	mov ax,'IS'		;"SI"
913
	mov cx,[regs.rSI]
914
	test bl,1
915
	jz @F			;if SI
916
	mov al,'D'		;"DI"
917
	mov cx,[regs.rDI]
918
@@:
919
	add [addrr],cx	; base+index ([BX+SI, ....  )
920
	stosw
921
dop13:
922
	test [ai.regmem], 0c0h
923
	jz dop17		;if no displacement
924
	test [ai.regmem], 80h
925
	jnz dop15		;if word displacement
926
	call disgetbyte
927
	cbw
928
	add [addrr],ax	; [base][+index]+byte
929
	cmp al,0
930
	mov ah,'+'
931
	jge @F			;if >= 0
932
	mov ah,'-'
933
	neg al
934
@@:
935
	mov [di],ah
936
	inc di
937
	call hexbyte	;print the byte displacement
938
	jmp dop17		;done
939
dop15:
940
	mov al,'+'
941
	stosb
942
dop16:				;<--- pure 16bit offset
943
	call disgetword
944
	add [addrr],ax
945
	call hexword    ;print word displacement
946
dop17:
947
	mov al,']'
948
	stosb
949
	ret
950

951
;--- 32-bit MOD REG R/M addressing.
952

953
dop18:
954
	cmp al,5
955
	jne @F			;if not just a disp32 address
956
;--- render "[xxxxxxxx]"
957
dop18a:
958
	mov al,'['
959
	stosb
960
	call disp32		;get & display 32bit offset
961
	jmp dop17		;last the ']'
962

963
@@:
964
	push ax
965
	and al,7
966
	cmp al,4
967
	jne @F			;if no SIB
968
	call disgetbyte	;get and save it
969
	mov [ai.sibbyte],al
970
@@:
971
	pop ax
972
	test al,80h
973
	jnz dop22		;if disp32
974
	test al,40h
975
	jz dop23		;if no disp8
976
	call disgetbyte
977
	cmp al,0
978
	jge @F			;if >= 0
979
	neg al
980
	mov byte ptr [di],'-'
981
	inc di
982
@@:
983
	call hexbyte
984
	jmp dop23		;done
985

986
;--- for 32-bit, the disassembler displays offsets first;
987
;--- example: mov ax,00001000[ebx][edi]
988

989
dop22:
990
;--- v2.50: put offset in square brackets: mov ax,[00001000][ebx][edi]
991
;    call disp32	;get and display 32bit offset
992
    call dop18a		;get and display 32bit offset
993

994
dop23:
995
	mov al,[ai.regmem]
996
	and al,7
997
	cmp al,4
998
	jne showsqreg32	;if no SIB
999
	mov al,[ai.sibbyte]
1000
if 1               ;bugfix: make 'u' correctly handle [ESP],[ESP+x]
1001
	cmp al,24h
1002
	jnz @F
1003
	mov al,4
1004
	jmp showsqreg32
1005
@@:
1006
endif
1007
	and al,7
1008
	cmp al,5
1009
	jne @F			;if not [EBP]
1010
	test [ai.regmem], 0c0h
1011
	jnz @F			;if MOD != 0
1012
	call disp32		;get and show 32-bit displacement instead of [EBP]
1013
	jmp dop25
1014

1015
@@:
1016
	call showsqreg32; render "[E&reg]"; al=reg
1017
dop25:
1018
	mov al,[ai.sibbyte]
1019
	shr al,1
1020
	shr al,1
1021
	shr al,1
1022
	and al,7
1023
	cmp al,4
1024
	je disbad1		;if illegal
1025

1026
	call showsqreg32; render "[E&reg]; al=reg
1027
	dec di			; remove "]"
1028

1029
	mov ah,[ai.sibbyte]
1030
	test ah,0c0h
1031
	jz dop27		;if SS = 0
1032
	mov al,'*'
1033
	stosb
1034
	mov al,'2'
1035
	test ah,80h
1036
	jz @F			;if *2
1037
	mov al,'4'
1038
	test ah,40h
1039
	jz @F			;if *4
1040
	mov al,'8'
1041
@@:
1042
	stosb
1043
dop27:
1044
	mov al,']'
1045
	stosb
1046
	ret
1047

1048
;--- Memory-only reference (OP_M)
1049

1050
dop_m:
1051
	call getregmem
1052
	cmp al,0c0h
1053
	jae disbad1		;if it's a register reference
1054
	jmp dop05
1055

1056
disbad1:
1057
	jmp disbad		;this is not supposed to happen
1058

1059
;--- Register reference from MOD R/M part (OP_R_MOD)
1060

1061
dop_r_mod:
1062
	call getregmem
1063
	cmp al,0c0h
1064
	jb disbad1		;if it's a memory reference
1065
	jmp dop_r1
1066

1067
;--- Memory offset reference (OP_MOFFS)
1068

1069
dop_moffs:
1070
	call showsize	;print the size and save various things
1071
	mov al,5
1072
	test [preflags], PRE32A
1073
	jnz @F			;if 32-bit addressing
1074
	inc ax
1075
@@:
1076
	mov [ai.regmem],al
1077
	jmp dop06		;don't show size
1078

1079
;--- Pure register reference (OP_R)
1080

1081
dop_r:
1082
	call getregmem_r
1083
dop_r1:					;<--- used by OP_RM, OP_R_MOD, OP_R_ADD, OP_AX
1084
	and al,7			;entry point for regs from MOD R/M, and others
1085
	mov cl,[disflags2]
1086
	or [disflags],cl	;if it was variable size operand, the size
1087
						;should now be marked as known.
1088
	cmp ah,0
1089
	jl dop_reg			;if byte register
1090
	jz dop_wordreg		;if word register
1091
	cmp ah,20h			;qword register (mmx)?
1092
	jz dop_regmmx
1093
	mov byte ptr [di],'E'
1094
	inc di
1095
dop_wordreg:
1096
	add al,8			; use the 16-bit names ( rgnam16 )
1097
dop_reg:
1098
	cbw
1099
	shl ax,1
1100
	xchg ax,bx			; mov bx,ax
1101
	mov ax,[rgnam816+bx]; get the register name
1102
	stosw
1103
	ret
1104
dop_regmmx:
1105
	push ax
1106
	mov ax,"MM"
1107
	stosw
1108
	pop ax
1109
	add al,'0'
1110
	stosb
1111
	ret
1112

1113
;--- Register number embedded in the instruction (OP_R_ADD)
1114

1115
dop_r_add:
1116
	mov al,[bInstr]
1117
	jmp dop_r1
1118

1119
;--- AL or AX or EAX (OP_AX)
1120

1121
dop_ax:
1122
	mov al,0
1123
	jmp dop_r1
1124

1125
;--- QWORD mem (OP_M64).
1126
;--- this operand type is used by:
1127
;--- + cmpxchg8b
1128
;--- + fild, fistp
1129

1130
dop_m64:
1131
;	mov ax,'Q'		;print 'Q' +'WORD'
1132
	mov ah,20h		;size QWORD
1133
	jmp dop40
1134

1135
;--- FLOAT (=REAL4) mem (OP_MFLOAT).
1136

1137
dop_mfloat:
1138
	mov ax,'LF'
1139
	stosw
1140
	mov al,'O'
1141
	stosb
1142
	mov ax,'TA'
1143
	jmp dop38c
1144

1145
;--- DOUBLE (=REAL8) mem (OP_MDOUBLE).
1146

1147
dop_mdouble:
1148
	mov ax,'OD'
1149
	stosw
1150
	mov ax,'BU'
1151
	stosw
1152
	mov ax,'EL'
1153
dop38c:
1154
	stosw
1155
	call showptr
1156
	jmp dop42a
1157

1158
;--- TBYTE (=REAL10) mem (OP_M80).
1159

1160
dop_m80:
1161
	mov ax,0ff00h+'T'	;print 't' + 'byte'
1162
	stosb
1163
dop40:
1164
	call getregmem
1165
	cmp al,0c0h
1166
	jae disbad5		;if it's a register reference
1167
	and [disflags],not DIS_F_SHOW	;don't show this
1168
	jmp dop05
1169

1170
;--- far memory (OP_FARMEM).
1171
;--- this is either a FAR16 (DWORD) or FAR32 (FWORD) pointer
1172

1173
dop_farmem:
1174
	mov ax,'AF'		;store "FAR"
1175
	stosw
1176
	mov al,'R'
1177
	stosb
1178
	mov ax,"61"		;FAR16
1179
	call dischk32d
1180
	jz @F
1181
	mov ax,"23"		;FAR32
1182
@@:
1183
	stosw
1184
	mov al,' '
1185
	stosb
1186
;	call showptr
1187

1188
;--- mem (OP_MXX).
1189

1190
dop_mxx:
1191
	and [disflags],not DIS_F_SHOW	;don't show this
1192
dop42a:
1193
	call getregmem
1194
	cmp al,0c0h
1195
	jae disbad5		;if it's a register reference
1196
	jmp dop06		;don't show size
1197

1198
disbad5:
1199
	jmp disbad
1200

1201
;--- Check for ST(1) (OP_1CHK).
1202

1203
dop_st1:
1204
	pop ax		;discard return address
1205
	mov al,[ai.regmem]
1206
	and al,7
1207
	cmp al,1
1208
	je @F		;if it's ST(1)
1209
	jmp da14	;another operand (but no comma)
1210
@@:
1211
	jmp da21	;end of list
1212

1213
;--- store segment register name (OP_SEGREG).
1214

1215
dop_segreg:
1216
	call getregmem_r
1217
	cmp al,6
1218
	jae disbad		;if not a segment register
1219
	cmp al,2
1220
	je @F			;if SS
1221
	and [disflags],not DIS_F_REPT	;clear flag:  don't repeat
1222
@@:
1223
	cmp al,4
1224
	jb @F			;if not FS or GS
1225
	mov [ai.dismach],3	;(no new 486-686 instructions involve seg regs)
1226
@@:
1227
	add al,8+8		;segreg names are behind 8-bit/16-bit regnames
1228
	jmp dop_reg		;go print it out
1229

1230
;--- Sign-extended immediate byte (OP_IMMS8). "push xx"
1231

1232
dop_imms8:
1233
	call showsizeop
1234
	call disgetbyte
1235
	cmp al,0
1236
	xchg ax,bx		;mov bl,al
1237
	mov al,'+'
1238
	jge @F			;if >= 0
1239
	neg bl
1240
	mov al,'-'
1241
@@:
1242
	stosb
1243
	xchg ax,bx		;mov al,bl
1244
	jmp dop59a		;call hexbyte and return
1245

1246
;--- Immediate byte (OP_IMM8).
1247

1248
dop_imm8:
1249
	call disgetbyte
1250
dop59a:
1251
	jmp hexbyte		;call hexbyte and return
1252

1253
;--- Set flag to always show size (OP_SHOSIZ).
1254

1255
dop_shosiz:
1256
	or [disflags],DIS_I_SHOWSIZ
1257
	pop ax			;discard return address
1258
	jmp da14		;next operand
1259

1260
disasm endp
1261

1262
;--- v2.50: return value in SI has changed 
1263
;--- up to v2.50, si returned an offset for the oplists table ( + OPTYPES_BASE )
1264
;--- since v2.50, si returns just an index (for table opindex).
1265

1266
disbad proc
1267
if FLATSS
1268
	.386
1269
	mov esp,[run_sp]	;pop junk off stack
1270
else
1271
	mov sp,[run_sp]		;pop junk off stack
1272
endif
1273
	mov ax,offset da13a	; the address where we "return" to
1274
	push ax
1275
	mov [dis_n],0
1276
	mov word ptr [preflags],0		;clear preflags and preused
1277
	mov [rmsize],80h				;don't display any memory
1278
	mov word ptr [ai.dismach],0		;forget about the machine type
1279
	and [disflags],not DIS_I_SHOW	;and flags
1280
	call disgetbyte
1281
	mov di,offset prefixlist
1282
	mov cx,N_PREFIX
1283
	repne scasb
1284
	je @F			;if it's a named prefix
1285
	dec [dis_n]		;reset cnt to 0 again
1286
	mov bx,MN_DB	;offset of 'DB' mnemonic
1287
;	mov si,OPLIST_26+OPTYPES_BASE;this says OP_IMM8
1288
	mov si,26h		;v2.50: index 26h: this says OP_IMM8
1289
	ret
1290
@@:
1291
	or [disflags],DIS_I_UNUSED	;print special flag
1292
	mov bx,N_PREFIX-1
1293
	sub bx,cx
1294
	cmp bx,6		;the first 6 items are segment prefixes
1295
	jb @F			;if SEG directive
1296
	shl bx,1		;prefix wait, lock, repe, repne
1297
	mov bx,[prefixmnem+bx-6*2]
1298
;	mov si,OPTYPES_BASE	;no operand
1299
	xor si, si			;v2.50: index 0, first item, no operand
1300
	ret
1301
@@:
1302
;--- an unused segment prefix
1303
;	lea si,[bx+OPLIST_40+OPTYPES_BASE]	;OPLIST_40 is OP_ES, size 2
1304
	lea si,[bx+40h]						;v2.50: 40h is index for OP_ES
1305
	mov bx,MN_SEG
1306
	ret
1307
disbad endp
1308

1309
;--- relative jumps
1310

1311
dop_relxx proc
1312

1313
;--- 8-bit relative jump (OP_REL8)
1314
;--- v2.50: correctly handle a 8-bit short jmp with a size prefix
1315

1316
dop_rel8::
1317
	call disgetbyte
1318
	cbw
1319
	call dischk32d
1320
	jz dop_rel16
1321
	cwd
1322
	xchg ax, dx
1323
	jmp dop_dispdwd
1324

1325
dop_rel16:			;16-bit distance ( also used for 8-bit short distances
1326
	add ax,[u_addr]
1327
	add ax,[dis_n]
1328
	jmp hexword		;call hexword and return
1329

1330
;--- 16/32-bit relative jump (OP_REL1632)
1331
;--- v2.50: a 16-bit relative call/jmp in 32-bit will clear hiword(eip)!
1332
;--- to make this evident, display a WORD only!
1333

1334
dop_rel1632::
1335
	call disgetword
1336
	call dischk32d
1337
	jz dop_rel16	;if not 32-bit distance
1338
	xchg ax, dx
1339
	call disgetword
1340
dop_dispdwd:		; relative distance in ax:dx
1341
	mov bx,[u_addr+0]
1342
	add bx,[dis_n]
1343
	add dx,bx
1344
	adc ax,[u_addr+2]
1345
	call hexword
1346
	xchg ax,dx
1347
	jmp hexword		;call hexword and return
1348

1349
dop_relxx endp
1350

1351
;--- Here are the routines for printing out the operands themselves.
1352

1353
;--- CRx (OP_CR), DRx (OP_DR), TRx (OP_TR), MMx (OP_MMX)
1354

1355
dop_cr proc
1356
	call getregmem_r
1357
	mov bx,"RC"		; "CRx"
1358
	cmp al,4
1359
	ja disbad4		;if too large
1360
	jne @F
1361
	mov [ai.dismach],5	;CR4 is new to the 586
1362
@@:
1363
	cmp [idxins],SPARSE_BASE+22h
1364
	jne dop55		;if not MOV CRx,xx
1365
	cmp al,1
1366
	jne dop55		;if not CR1
1367
disbad4:
1368
	jmp disbad		;can't MOV CR1,xx
1369

1370
;--- DRx (OP_DR).
1371

1372
dop_dr::
1373
	call getregmem_r
1374
	mov bx,"RD"		; "DRx"
1375
	mov cx,-1		; no max or illegal value (remove?)
1376
	jmp dop55
1377

1378
;--- MMx (OP_MMX)
1379

1380
dop_mmx::
1381
	call getregmem_r
1382
	mov bx,"MM"		; "MMx"
1383
	jmp dop55
1384

1385
;--- TRx (OP_TR).
1386

1387
dop_tr::
1388
	call getregmem_r
1389
	cmp al,3
1390
	jb disbad4		;if too small
1391
	cmp al,6
1392
	jae @F			;if TR6-7
1393
	mov [ai.dismach],4	;TR3-5 are new to the 486
1394
@@:
1395
	mov bx,"RT"		; "TRx"
1396
dop55:
1397
	xchg ax,bx
1398
	stosw			;store XX
1399
	xchg ax,bx
1400
	or al,'0'
1401
	stosb
1402
	ret
1403
dop_cr endp
1404

1405
;--- ST(I) (OP_STI).
1406

1407
dop_sti proc
1408
	mov al,[ai.regmem]
1409
	and al,7
1410
	xchg ax,bx		;mov bx,ax
1411
	mov ax,'TS'
1412
	stosw			;store ST(bl)
1413
	mov al,'('
1414
	stosb
1415
	mov ax,')0'
1416
	or al,bl
1417
	stosw
1418
	ret
1419
dop_sti endp
1420

1421
;--- far immediate (OP_FARIMM). Either FAR16 or FAR32
1422

1423
dop_farimm proc
1424
	mov bx, sp
1425
	call disgetword
1426
	push ax
1427
	call dischk32d
1428
	jz @F			; if not 32-bit address
1429
	call disgetword
1430
	push ax
1431
@@:
1432
	call disgetword	; get segment part
1433
	call hexword
1434
	mov al,':'
1435
	stosb
1436
@@:
1437
	pop ax
1438
	call hexword
1439
	cmp bx, sp
1440
	jnz @B
1441
	ret
1442
dop_farimm endp
1443

1444
;--- Immediate data (OP_IMM)
1445

1446
dop_imm proc
1447
	cmp ah,0
1448
	jl dop03		;if just a byte
1449
	pushf
1450
	test [disflags], DIS_I_SHOWSIZ
1451
	jz @F			;if we don't need to show the size
1452
	call showsize	;print size in AH
1453
	sub di,4		;erase "PTR "
1454
@@:
1455
	call disgetword
1456
	popf
1457
	jz @F			;if just a word
1458
	push ax
1459
	call disgetword	;print the high order word
1460
	call hexword
1461
	pop ax
1462
@@:
1463
	call hexword
1464
	ret
1465

1466
dop03:
1467
	call disgetbyte	;print immediate byte
1468
	call hexbyte
1469
	ret
1470
dop_imm endp
1471

1472
;--- 32-bit addressing without SIB
1473
;--- store "[E&reg]" at DI
1474

1475
showsqreg32 proc
1476
	cbw
1477
	shl ax,1
1478
	xchg ax,bx
1479
	mov ax, 'E['
1480
	stosw
1481
	mov ax, [rgnam16+bx]
1482
	stosw
1483
	mov al,']'
1484
	stosb
1485
	ret
1486
showsqreg32 endp
1487

1488
showsizeop proc
1489
;--- for PUSH imm8 add D/W to opcode if size differs from default (WORD/DWORD)
1490
	cmp [bInstr],6ah
1491
	jnz sso_skip
1492
	call dischk32d
1493
if ?PM
1494
	mov ah,[bCSAttr]
1495
	.286
1496
	shr ah,2		;40h -> 10h (=PRE32D)
1497
	.8086
1498
else
1499
	mov ah,0
1500
endif
1501
	mov al,'W'
1502
	test ah, PRE32D
1503
	jnz @F
1504
	mov al,'D'
1505
@@:
1506
	xor ah,[preflags]
1507
	test ah, PRE32D
1508
	jz sso_skip
1509
	mov [di-4],al
1510
sso_skip:
1511
	ret
1512
showsizeop endp
1513

1514
;--- DISCHK32D - Check for 32 bit operand size prefix (66h).
1515

1516
dischk32d proc
1517
	or [preused], PRE32D
1518
	test [preflags], PRE32D
1519
	ret
1520
dischk32d endp
1521

1522
;   GETREGMEM_R - Get the reg part of the reg/mem part of the instruction
1523
;   Uses    CL
1524

1525
getregmem_r proc
1526
	call getregmem
1527
	mov cl,3
1528
	shr al,cl
1529
	and al,7
1530
	ret
1531
getregmem_r endp
1532

1533
;--- GETREGMEM - Get the reg/mem part of the instruction
1534

1535
getregmem proc
1536
	test [preused],GOTREGM
1537
	jnz @F			;if we have it already
1538
	or [preused],GOTREGM
1539
	call disgetbyte	;get the byte
1540
	mov [ai.regmem],al	;save it away
1541
@@:
1542
	mov al,[ai.regmem]
1543
	ret
1544
getregmem endp
1545

1546
;   DISP32 - Print 32-bit displacement for addressing modes.
1547
;   Entry   None
1548
;   Exit    None
1549
;   Uses    AX
1550

1551
disp32 proc
1552
	call disgetword
1553
	push ax
1554
	call disgetword
1555
	call hexword
1556
	pop ax
1557
	call hexword
1558
	ret
1559
disp32 endp
1560

1561
;   SHOWSEG - Show the segment descriptor in SEGMNT
1562
;   Entry   DI  Where to put it
1563
;   Exit    DI  Updated
1564
;   Uses    AX, BX
1565

1566
showseg proc
1567
	mov al,[segmnt]	;segment number
1568
	cbw
1569
	shl ax,1
1570
	xchg ax,bx		;mov bx,ax
1571
	mov ax, [segrgnam+bx] ;get register name
1572
	stosw
1573
	ret
1574
showseg endp
1575

1576
;   SHOWOP  Show the op code
1577
;   Entry   SI  Null-terminated string containing the op mnemonic
1578
;   Exit    DI  Address of next available byte in output line
1579
;           (>= offset line_out + 32 due to padding)
1580
;   Uses    AL
1581

1582
showop proc
1583
	mov di,offset line_out+MNEMONOFS
1584
@@:
1585
	lodsb
1586
	mov ah,al
1587
	and al,7Fh
1588
	stosb
1589
	and ah,ah
1590
	jns @B
1591
	mov al,' '
1592
@@:
1593
	stosb
1594
	cmp di,offset line_out+MNEMONOFS+8
1595
	jb @B
1596
	ret
1597
showop endp
1598

1599
;   SHOWSIZE - Print a description of the size
1600
;   Entry   AH  10h=DWORD, 00h=WORD, F0h=BYTE, 20h=QWORD
1601
;   Uses    AX
1602

1603
;   SHOWPTR - Print " PTR"
1604
;   Uses    AX
1605

1606
;   SHOWDWD - Print "DWORD PTR"
1607
;   Uses    AX
1608

1609
showsize proc
1610
	mov [rmsize],ah	;save r/m size
1611
	mov [sizeloc],di;save where we're putting this
1612
	mov al,'Q'
1613
	cmp ah,20h
1614
	jz showqwd
1615
	cmp ah,0
1616
	jg showdwd	;if dword
1617
	je showwd	;if word
1618
	mov ax,'YB'
1619
	stosw
1620
	mov ax,'ET'
1621
	jmp ssz3
1622
showdwd::		;<---
1623
	mov al,'D'
1624
showqwd:
1625
	stosb
1626
showwd:
1627
	mov ax,'OW'
1628
	stosw
1629
	mov ax,'DR'
1630
ssz3:
1631
	stosw
1632
showptr::		;<---
1633
	mov ax,'P '
1634
	stosw
1635
	mov ax,'RT'
1636
	stosw
1637
	mov al,' '
1638
	stosb
1639
	ret
1640
showsize endp
1641

1642
;   DISGETBYTE - Get byte for disassembler.
1643
;   Entry   None
1644
;   Exit    AL  Next byte in instruction stream
1645
;   Uses    None
1646

1647
disgetbyte proc
1648
	push ds
1649
if ?PM
1650
	test [bCSAttr], CS32
1651
	jnz @F
1652
endif
1653
	push si
1654
	mov si,[u_addr]
1655
	add si,[dis_n]		;index to the right byte
1656
	mov ds,[u_addr+4]
1657
	lodsb 				;get the byte
1658
	pop si
1659
	pop ds
1660
	inc [dis_n]			;indicate that we've gotten this byte
1661
	ret
1662
if ?PM
1663
	.386
1664
@@:
1665
	push esi
1666
	lds esi,fword ptr [u_addr]
1667
	add esi,dword ptr cs:[dis_n]	;index to the right byte
1668
	lodsb ds:[esi]
1669
	pop esi
1670
	pop ds
1671
	inc [dis_n]
1672
	ret
1673
	.8086
1674
endif
1675
disgetbyte endp
1676

1677
;   DISGETWORD - Get word for disassembler.
1678
;   Entry   None
1679
;   Exit    AX  Next word
1680
;   Uses    None
1681

1682
disgetword proc
1683
	push ds
1684
if ?PM
1685
	test [bCSAttr], CS32
1686
	jnz @F
1687
endif
1688
	push si
1689
	mov si,[u_addr]
1690
	add si,[dis_n]		;index to the right byte
1691
	mov ds,[u_addr+4]
1692
	lodsw
1693
	pop si
1694
	pop ds
1695
	add [dis_n],2
1696
	ret
1697
if ?PM
1698
	.386
1699
@@:
1700
	push esi
1701
	lds esi,fword ptr [u_addr]
1702
	add esi,dword ptr cs:[dis_n]	;index to the right byte
1703
	lodsw ds:[esi]
1704
	pop esi
1705
	pop ds
1706
	add [dis_n],2
1707
	ret
1708
	.8086
1709
endif
1710
disgetword endp
1711

1712
;   DISSHOWBYTES - Show bytes for the disassembler.
1713
;   Entry   BX  Number of bytes (must be > 0)
1714
;   Exit        u_addr updated
1715
;   Uses    BX, SI.
1716

1717
disshowbytes proc
1718
if ?PM
1719
	test [bCSAttr], CS32
1720
	jnz dissb_1
1721
endif
1722
	mov si,[u_addr]
1723
	mov ds,[u_addr+4]
1724
@@:
1725
	lodsb
1726
	call hexbyte
1727
	dec bx
1728
	jnz @B
1729
	@RestoreSeg ds
1730
	mov [u_addr],si
1731
	ret
1732
if ?PM
1733
	.386
1734
dissb_1:
1735
	lds esi,fword ptr [u_addr]
1736
@@:
1737
	lodsb ds:[esi]
1738
	call hexbyte
1739
	dec bx
1740
	jnz @B
1741
	@RestoreSeg ds
1742
	mov dword ptr [u_addr],esi
1743
	ret
1744
    .8086
1745
endif
1746
disshowbytes endp
1747

1748
;   MOVEOVER - Move the line to the right - disassembler subfunction.
1749
;   used to insert prefixes - called by code in the "prefix loop" only.
1750
;   Entry   DI  Last address + 1 of line so far
1751
;   Exit    CX  Number of bytes to move
1752
;   DI  Updated
1753
;   Uses    SI
1754

1755
moveover proc
1756
	cmp [sizeloc],0
1757
	je @F		;if sizeloc not saved
1758
	add [sizeloc],cx
1759
@@:
1760
	mov si,di
1761
	add di,cx
1762
	mov cx,di
1763
	sub cx,offset line_out+MNEMONOFS
1764
	push di
1765
	std
1766
	dec si
1767
	dec di
1768
	rep movsb
1769
	pop di
1770
	cld
1771
	ret
1772
moveover endp
1773

1774
;   TAB_TO - Space fill until reaching the column indicated by AX.
1775
;   (Print a new line if necessary.)
1776

1777
tab_to proc
1778
	push ax
1779
	sub ax,di
1780
	ja @F			;if there's room on this line
1781
	call trimputs
1782
	mov di,offset line_out
1783
@@:
1784
	pop cx
1785
	sub cx,di
1786
	mov al,' '
1787
	rep stosb		;space fill to the right end
1788
	ret
1789
tab_to endp
1790

1791

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.