📄 dishand.c
字号:
static char *sccsid = "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01"; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 1987 G. M. Harding, all rights reserved * * * * Permission to copy and redistribute is hereby granted, * * provided full source code, with all copyright notices, * * accompanies any redistribution. * * * * This file contains the source code for most of the spe- * * cialized handler routines of the disassembler program. * * (The file disfp.c contains handler routines specific to * * the 8087 numeric co-processor.) Each handler routine * * interprets the opcode byte (and subsequent data bytes, * * if any) of a particular family of opcodes, and is re- * * sponsible for generating appropriate output. All of the * * code in this file is highly MACHINE-SPECIFIC, and would * * have to be rewritten for a different CPU. The handler * * routines are accessed only via pointers in the optab[] * * array, however, so machine dependencies are confined to * * this file, its sister file "disfp.c", and the data file * * "distabs.c". * * * * All of the code in this file is based on the assumption * * of sixteen-bit integers. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */#include "dis.h" /* Disassembler declarations */int segflg; /* Segment-override flag */unsigned char objbuf[OBJMAX]; /* Buffer for object code */int objptr; /* Index into objbuf[] */unsigned long PC; /* Current program counter */ /* * * * * * MISCELLANEOUS SUPPORTING ROUTINES * * * * * */voidobjini(j) /* Object code init routine */ register int j;{ if ((segflg == 1) || (segflg == 2)) segflg *= 3; else segflg = 0; objptr = 0; objbuf[objptr++] = (unsigned char)(j);}voidobjout() /* Object-code output routine */{ register int k; if ( ! objflg ) return; else { printf("\t|"); if (symptr >= 0) printf(" %05.5lx:",(PC + 1L - (long)(objptr))); for (k = 0; k < objptr; ++k) printf(" %02.2x",objbuf[k]); putchar('\n'); }}voidbadseq(j,k) /* Invalid-sequence routine */ register int j, k;{ printf("\t.byte\t0x%02.2x\t\t| invalid code sequence\n",j); printf("\t.byte\t0x%02.2x\n",k);} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This routine is the first of several opcode-specific * * handlers, each of which is dedicated to a particular * * opcode family. A pointer to a handler routine is con- * * tained in the second field of each optab[] entry. The * * dfhand() routine is the default handler, invoked when * * no other handler is appropriate (generally, when an in- * * valid opcode is encountered). * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */voiddfhand(j) register int j; /* Pointer to optab[] entry */{/* * * * * * * * * * START OF dfhand() * * * * * * * * * */ segflg = 0; printf("\t.byte\t0x%02.2x",j); if (optab[j].min || optab[j].max) putchar('\n'); else printf("\t\t| unimplemented opcode\n");}/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the single-byte handler, invoked whenever a * * one-byte opcode is encountered. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */voidsbhand(j) register int j; /* Pointer to optab[] entry */{/* * * * * * * * * * START OF sbhand() * * * * * * * * * */ objini(j); if (j == 0x2e) /* seg cs */ segflg = 1; if ((j == 0x26) /* seg es */ || (j == 0x36) /* seg ss */ || (j == 0x3e)) /* seg ds */ segflg = 2; printf("%s\n",optab[j].text); objout();}/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for most of the processor's regular * * arithmetic operations. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */voidaohand(j) register int j; /* Pointer to optab[] entry */{/* * * * * * * * * * START OF aohand() * * * * * * * * * */ register int k; int m, n; char b[64]; objini(j); switch (j & 7) { case 0 : case 1 : case 2 : case 3 : printf("%s\t",optab[j].text); FETCH(k); printf("%s\n",mtrans(j,k,TR_STD)); break; case 4 : FETCH(k); printf("%s\tal,*0x%02.2x\n",optab[j].text,k); break; case 5 : FETCH(m); FETCH(n); k = (n << 8) | m; if (lookext((long)(k),(PC - 1),b)) printf("%s\tax,#%s\n",optab[j].text,b); else printf("%s\tax,#0x%04.4x\n",optab[j].text,k); break; default : dfhand(j); break; } objout();}/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for opcodes which perform short * * (eight-bit) relative jumps. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */voidsjhand(j) register int j; /* Pointer to optab[] entry */{/* * * * * * * * * * START OF sjhand() * * * * * * * * * */ register int k; int m; objini(j); FETCH(m); if (m & 0x80) k = 0xff00; else k = 0; k |= m; printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, lookup((PC + k + 1L),N_TEXT,LOOK_REL,-1L), (PC + k + 1L)); objout();}/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for a loosely-knit family of op- * * codes which perform arithmetic and logical operations, * * and which take immediate data. The routine's logic is * * rather complex, so, in an effort to avoid additional * * complexity, the search for external references in the * * relocation table has been dispensed with. Eager hackers * * can try their hand at coding such a search. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */voidimhand(j) register int j; /* Pointer to optab[] entry */{/* * * * * * * * * * START OF imhand() * * * * * * * * * */ unsigned long pc; register int k; int offset, oflag, immed, iflag, mod, opi, w, rm; int m, n; static char a[100], b[30]; objini(j); FETCH(k); pc = PC + 1; offset = 0; mod = (k & 0xc0) >> 6; opi = (k & 0x38) >> 3; w = j & 1; rm = k & 7; if ((j & 2) && ((opi == 1) || (opi == 4) || (opi == 6))) { badseq(j,k); return; } strcpy(a,OPFAM[opi]); if ( ! w ) strcat(a,"b"); if ((oflag = mod) > 2) oflag = 0; if ((mod == 0) && (rm == 6)) { FETCH(m); FETCH(n); offset = (n << 8) | m; } else if (oflag) if (oflag == 2) { FETCH(m); FETCH(n); offset = (n << 8) | m; } else { FETCH(m); if (m & 0x80) n = 0xff00; else n = 0; offset = n | m; } switch (j & 3) { case 0 : case 2 : FETCH(immed); iflag = 0; break; case 1 : FETCH(m); FETCH(n); immed = (n << 8) | m; iflag = 1; break; case 3 : FETCH(immed); if (immed & 0x80) immed &= 0xff00; iflag = 0; break; } strcat(a,"\t"); switch (mod) { case 0 : if (rm == 6) strcat(a, lookup((long)(offset),N_DATA,LOOK_ABS,pc)); else { sprintf(b,"(%s)",REGS0[rm]); strcat(a,b); } break; case 1 : case 2 : if (mod == 1) strcat(a,"*"); else strcat(a,"#"); sprintf(b,"%d(",offset); strcat(a,b); strcat(a,REGS1[rm]); strcat(a,")"); break; case 3 : strcat(a,REGS[(w << 3) | rm]); break; } strcat(a,","); if (iflag) strcat(a,"#"); else strcat(a,"*"); sprintf(b,"%d",immed); strcat(a,b); printf("%s\n",a); objout();}/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for various "mov"-type opcodes * * which use the mod, reg, and r/m fields of the second * * code byte in a standard, straightforward way. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */voidmvhand(j) int j; /* Pointer to optab[] entry */{/* * * * * * * * * * START OF mvhand() * * * * * * * * * */ register int k, m = j; objini(j); FETCH(k); if ((m == 0x84) || (m == 0x85) /* Kind of kludgey */ || (m == 0xc4) || (m == 0xc5) || (m == 0x8d)) if (m & 0x40) m |= 0x03; else m |= 0x02; printf("%s\t%s\n",optab[j].text,mtrans(m,k,TR_STD)); objout();}/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for segment-register "mov" opcodes. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */voidmshand(j) register int j; /* Pointer to optab[] entry */{/* * * * * * * * * * START OF mshand() * * * * * * * * * */ register int k; objini(j); FETCH(k); if (k & 0x20) { badseq(j,k); return; } printf("%s\t%s\n",optab[j].text,mtrans(j,k,TR_SEG)); objout();}/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler for pops, other than single-byte * * pops. (The 8088 allows popping into any register, or * * directly into memory, accessed either immediately or * * through a register and an index.) * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */voidpohand(j) register int j; /* Pointer to optab[] entry */{/* * * * * * * * * * START OF pohand() * * * * * * * * * */ char *a; register int k; objini(j); FETCH(k); if (k & 0x38) { badseq(j,k); return; } printf("%s\t",optab[j].text); a = mtrans((j & 0xfd),k,TR_STD); mtrunc(a); printf("%s\n",a); objout();}/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This is the handler routine for intersegment calls and * * jumps. Its output is never symbolic, because the host * * linker does not allow symbolic intersegment address * * references except by means of symbolic constants, and * * any such constants in the symbol table, even if they * * are of the appropriate value, may be misleading. In * * compiled code, intersegment references should not be * * encountered, and even in assembled code, they should * * occur infrequently. If and when they do occur, however, * * they will be disassembled in absolute form. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */voidcihand(j) int j; /* Pointer to optab[] entry */{/* * * * * * * * * * START OF cihand() * * * * * * * * * */ register int m, n; objini(j); printf("%s\t",optab[j].text); FETCH(m); FETCH(n); printf("#0x%04.4x,",((n << 8) | m)); FETCH(m); FETCH(n); printf("#0x%04.4x\n",((n << 8) | m)); objout();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -