2 "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01";
4 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
6 * Copyright (C) 1987 G. M. Harding, all rights reserved *
8 * Permission to copy and redistribute is hereby granted, *
9 * provided full source code, with all copyright notices, *
10 * accompanies any redistribution. *
12 * This file contains the source code for most of the spe- *
13 * cialized handler routines of the disassembler program. *
14 * (The file disfp.c contains handler routines specific to *
15 * the 8087 numeric co-processor.) Each handler routine *
16 * interprets the opcode byte (and subsequent data bytes, *
17 * if any) of a particular family of opcodes, and is re- *
18 * sponsible for generating appropriate output. All of the *
19 * code in this file is highly MACHINE-SPECIFIC, and would *
20 * have to be rewritten for a different CPU. The handler *
21 * routines are accessed only via pointers in the optab[] *
22 * array, however, so machine dependencies are confined to *
23 * this file, its sister file "disfp.c", and the data file *
26 * All of the code in this file is based on the assumption *
27 * of sixteen-bit integers. *
29 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
31 #include "dis.h" /* Disassembler declarations */
33 int segflg
; /* Segment-override flag */
35 unsigned char objbuf
[OBJMAX
]; /* Buffer for object code */
37 int objptr
; /* Index into objbuf[] */
39 unsigned long PC
; /* Current program counter */
41 /* * * * * * MISCELLANEOUS SUPPORTING ROUTINES * * * * * */
45 objini(j
) /* Object code init routine */
50 if ((segflg
== 1) || (segflg
== 2))
55 objbuf
[objptr
++] = (unsigned char)(j
);
60 objout() /* Object-code output routine */
71 printf(" %05.5lx:",(PC
+ 1L - (long)(objptr
)));
72 for (k
= 0; k
< objptr
; ++k
)
73 printf(" %02.2x",objbuf
[k
]);
80 badseq(j
,k
) /* Invalid-sequence routine */
85 printf("\t.byte\t0x%02.2x\t\t| invalid code sequence\n",j
);
86 printf("\t.byte\t0x%02.2x\n",k
);
89 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
91 * This routine is the first of several opcode-specific *
92 * handlers, each of which is dedicated to a particular *
93 * opcode family. A pointer to a handler routine is con- *
94 * tained in the second field of each optab[] entry. The *
95 * dfhand() routine is the default handler, invoked when *
96 * no other handler is appropriate (generally, when an in- *
97 * valid opcode is encountered). *
99 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
104 register int j
; /* Pointer to optab[] entry */
106 {/* * * * * * * * * * START OF dfhand() * * * * * * * * * */
110 printf("\t.byte\t0x%02.2x",j
);
112 if (optab
[j
].min
|| optab
[j
].max
)
115 printf("\t\t| unimplemented opcode\n");
117 }/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */
119 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
121 * This is the single-byte handler, invoked whenever a *
122 * one-byte opcode is encountered. *
124 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
129 register int j
; /* Pointer to optab[] entry */
131 {/* * * * * * * * * * START OF sbhand() * * * * * * * * * */
135 if (j
== 0x2e) /* seg cs */
138 if ((j
== 0x26) /* seg es */
139 || (j
== 0x36) /* seg ss */
140 || (j
== 0x3e)) /* seg ds */
143 printf("%s\n",optab
[j
].text
);
147 }/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */
149 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
151 * This is the handler for most of the processor's regular *
152 * arithmetic operations. *
154 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
159 register int j
; /* Pointer to optab[] entry */
161 {/* * * * * * * * * * START OF aohand() * * * * * * * * * */
175 printf("%s\t",optab
[j
].text
);
177 printf("%s\n",mtrans(j
,k
,TR_STD
));
181 printf("%s\tal,*0x%02.2x\n",optab
[j
].text
,k
);
187 if (lookext((long)(k
),(PC
- 1),b
))
188 printf("%s\tax,#%s\n",optab
[j
].text
,b
);
190 printf("%s\tax,#0x%04.4x\n",optab
[j
].text
,k
);
199 }/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */
201 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
203 * This is the handler for opcodes which perform short *
204 * (eight-bit) relative jumps. *
206 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
211 register int j
; /* Pointer to optab[] entry */
213 {/* * * * * * * * * * START OF sjhand() * * * * * * * * * */
229 printf("%s\t%s\t\t| loc %05.5lx\n",optab
[j
].text
,
230 lookup((PC
+ k
+ 1L),N_TEXT
,LOOK_REL
,-1L),
235 }/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */
237 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
239 * This is the handler for a loosely-knit family of op- *
240 * codes which perform arithmetic and logical operations, *
241 * and which take immediate data. The routine's logic is *
242 * rather complex, so, in an effort to avoid additional *
243 * complexity, the search for external references in the *
244 * relocation table has been dispensed with. Eager hackers *
245 * can try their hand at coding such a search. *
247 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
252 register int j
; /* Pointer to optab[] entry */
254 {/* * * * * * * * * * START OF imhand() * * * * * * * * * */
258 int offset
, oflag
, immed
, iflag
, mod
, opi
, w
, rm
;
260 static char a
[100], b
[30];
269 mod
= (k
& 0xc0) >> 6;
270 opi
= (k
& 0x38) >> 3;
283 strcpy(a
,OPFAM
[opi
]);
288 if ((oflag
= mod
) > 2)
291 if ((mod
== 0) && (rm
== 6))
295 offset
= (n
<< 8) | m
;
302 offset
= (n
<< 8) | m
;
324 immed
= (n
<< 8) | m
;
342 lookup((long)(offset
),N_DATA
,LOOK_ABS
,pc
));
345 sprintf(b
,"(%s)",REGS0
[rm
]);
355 sprintf(b
,"%d(",offset
);
361 strcat(a
,REGS
[(w
<< 3) | rm
]);
370 sprintf(b
,"%d",immed
);
377 }/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */
379 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
381 * This is the handler for various "mov"-type opcodes *
382 * which use the mod, reg, and r/m fields of the second *
383 * code byte in a standard, straightforward way. *
385 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
390 int j
; /* Pointer to optab[] entry */
392 {/* * * * * * * * * * START OF mvhand() * * * * * * * * * */
394 register int k
, m
= j
;
400 if ((m
== 0x84) || (m
== 0x85) /* Kind of kludgey */
401 || (m
== 0xc4) || (m
== 0xc5)
408 printf("%s\t%s\n",optab
[j
].text
,mtrans(m
,k
,TR_STD
));
412 }/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */
414 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
416 * This is the handler for segment-register "mov" opcodes. *
418 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
423 register int j
; /* Pointer to optab[] entry */
425 {/* * * * * * * * * * START OF mshand() * * * * * * * * * */
439 printf("%s\t%s\n",optab
[j
].text
,mtrans(j
,k
,TR_SEG
));
443 }/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */
445 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
447 * This is the handler for pops, other than single-byte *
448 * pops. (The 8088 allows popping into any register, or *
449 * directly into memory, accessed either immediately or *
450 * through a register and an index.) *
452 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
457 register int j
; /* Pointer to optab[] entry */
459 {/* * * * * * * * * * START OF pohand() * * * * * * * * * */
474 printf("%s\t",optab
[j
].text
);
476 a
= mtrans((j
& 0xfd),k
,TR_STD
);
484 }/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */
486 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
488 * This is the handler routine for intersegment calls and *
489 * jumps. Its output is never symbolic, because the host *
490 * linker does not allow symbolic intersegment address *
491 * references except by means of symbolic constants, and *
492 * any such constants in the symbol table, even if they *
493 * are of the appropriate value, may be misleading. In *
494 * compiled code, intersegment references should not be *
495 * encountered, and even in assembled code, they should *
496 * occur infrequently. If and when they do occur, however, *
497 * they will be disassembled in absolute form. *
499 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
504 int j
; /* Pointer to optab[] entry */
506 {/* * * * * * * * * * START OF cihand() * * * * * * * * * */
512 printf("%s\t",optab
[j
].text
);
517 printf("#0x%04.4x,",((n
<< 8) | m
));
522 printf("#0x%04.4x\n",((n
<< 8) | m
));
526 }/* * * * * * * * * * * END OF cihand() * * * * * * * * * * */
528 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
530 * This is the handler for "mov" opcodes with immediate *
533 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
538 register int j
; /* Pointer to optab[] entry */
540 {/* * * * * * * * * * START OF mihand() * * * * * * * * * */
548 printf("%s",optab
[j
].text
);
555 if (lookext((long)(k
),(PC
- 1),b
))
568 }/* * * * * * * * * * * END OF mihand() * * * * * * * * * * */
570 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
572 * This is the handler for a family of quick-move opcodes. *
574 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
579 int j
; /* Pointer to optab[] entry */
581 {/* * * * * * * * * * START OF mqhand() * * * * * * * * * */
595 printf("%s\t",optab
[j
].text
);
599 lookup((long)(m
),N_DATA
,LOOK_ABS
,pc
),
604 lookup((long)(m
),N_DATA
,LOOK_ABS
,pc
));
608 }/* * * * * * * * * * * END OF mqhand() * * * * * * * * * * */
610 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
612 * This is the handler for a family of quick-test opcodes. *
614 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
619 int j
; /* Pointer to optab[] entry */
621 {/* * * * * * * * * * START OF tqhand() * * * * * * * * * */
629 printf("%s\t%s,",optab
[j
].text
,REGS
[(j
& 1) << 3]);
637 if (lookext((long)(k
),(PC
- 1),b
))
651 }/* * * * * * * * * * * END OF tqhand() * * * * * * * * * * */
653 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
655 * This is the handler for multiple-byte "return" opcodes. *
656 * The 8088 allows returns to take an optional 16-bit ar- *
657 * gument, which reflects the amount to be added to SP *
658 * after the pop of the return address. The idea is to *
659 * facilitate the use of local parameters on the stack. *
660 * After some rumination, it was decided to disassemble *
661 * any such arguments as absolute quantities, rather than *
662 * rummaging through the symbol table for possible corre- *
663 * sponding constants. *
665 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
670 int j
; /* Pointer to optab[] entry */
672 {/* * * * * * * * * * START OF rehand() * * * * * * * * * */
683 printf("%s\t#0x%04.4x\n",optab
[j
].text
,m
);
687 }/* * * * * * * * * * * END OF rehand() * * * * * * * * * * */
689 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
691 * This is the handler for "mov" opcodes involving memory *
692 * and immediate data. *
694 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
699 register int j
; /* Pointer to optab[] entry */
701 {/* * * * * * * * * * START OF mmhand() * * * * * * * * * */
717 printf("%s",optab
[j
].text
);
722 a
= mtrans((j
& 0xfd),(k
& 0xc7),TR_STD
);
733 if (lookext((long)(k
),(PC
- 1),b
))
746 }/* * * * * * * * * * * END OF mmhand() * * * * * * * * * * */
748 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
750 * This is the handler for the 8088 family of shift and *
751 * rotate instructions. *
753 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
758 register int j
; /* Pointer to optab[] entry */
760 {/* * * * * * * * * * START OF srhand() * * * * * * * * * */
769 if ((k
& 0x38) == 0x30)
775 printf("%s",OPFAM
[((k
& 0x38) >> 3) + 16]);
780 a
= mtrans((j
& 0xfd),(k
& 0xc7),TR_STD
);
793 }/* * * * * * * * * * * END OF srhand() * * * * * * * * * * */
795 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
797 * This is the handler for the ASCII-adjust opcodes. *
799 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
804 register int j
; /* Pointer to optab[] entry */
806 {/* * * * * * * * * * START OF aahand() * * * * * * * * * */
820 printf("%s\n",optab
[j
].text
);
824 }/* * * * * * * * * * * END OF aahand() * * * * * * * * * * */
826 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
828 * This is the handler for port I/O opcodes which specify *
829 * the port address as an immediate operand. *
831 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
836 register int j
; /* Pointer to optab[] entry */
838 {/* * * * * * * * * * START OF iohand() * * * * * * * * * */
846 printf("%s\t0x%02.2x\n",optab
[j
].text
,k
);
850 }/* * * * * * * * * * * END OF iohand() * * * * * * * * * * */
852 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
854 * This is the handler for opcodes which perform long *
855 * (sixteen-bit) relative jumps and calls. *
857 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
862 register int j
; /* Pointer to optab[] entry */
864 {/* * * * * * * * * * START OF ljhand() * * * * * * * * * */
876 printf("%s\t%s\t\t| loc %05.5lx\n",optab
[j
].text
,
877 lookup((PC
+ k
+ 1L),N_TEXT
,LOOK_LNG
,(PC
- 1L)),
882 }/* * * * * * * * * * * END OF ljhand() * * * * * * * * * * */
884 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
886 * This is the handler for a pair of oddball opcodes (0xf6 *
887 * and 0xf7) which perform miscellaneous arithmetic opera- *
888 * tions not dealt with elsewhere. *
890 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
895 register int j
; /* Pointer to optab[] entry */
897 {/* * * * * * * * * * START OF mahand() * * * * * * * * * */
907 a
= mtrans((j
& 0xfd),(k
& 0xc7),TR_STD
);
911 switch (((k
= objbuf
[1]) & 0x38) >> 3)
952 if (lookext((long)(k
),(PC
- 1),b
))
965 }/* * * * * * * * * * * END OF mahand() * * * * * * * * * * */
967 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
969 * This is the handler for miscellaneous jump, call, push, *
970 * and increment/decrement opcodes (0xfe and 0xff) which *
971 * are not dealt with elsewhere. *
973 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
978 register int j
; /* Pointer to optab[] entry */
980 {/* * * * * * * * * * START OF mjhand() * * * * * * * * * */
989 a
= mtrans((j
& 0xfd),(k
& 0xc7),TR_STD
);
993 switch (((k
= objbuf
[1]) & 0x38) >> 3)
1009 printf("\tcall\t@");
1015 printf("\tcalli\t@");
1027 printf("\tjmpi\t@");
1047 }/* * * * * * * * * * * END OF mjhand() * * * * * * * * * * */