Subject: v15i007: Symbolic disassembler for PC/IX, Part02/02 Newsgroups: comp.sources.unix Approved: rsalz@uunet.UU.NET Submitted-by: "G. M. Harding" Posting-number: Volume 15, Issue 7 Archive-name: dis88/part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'dishand.c' <<'END_OF_FILE' static char *sccsid = X "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01"; X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * Copyright (C) 1987 G. M. Harding, all rights reserved * X * * X * Permission to copy and redistribute is hereby granted, * X * provided full source code, with all copyright notices, * X * accompanies any redistribution. * X * * X * This file contains the source code for most of the spe- * X * cialized handler routines of the disassembler program. * X * (The file disfp.c contains handler routines specific to * X * the 8087 numeric co-processor.) Each handler routine * X * interprets the opcode byte (and subsequent data bytes, * X * if any) of a particular family of opcodes, and is re- * X * sponsible for generating appropriate output. All of the * X * code in this file is highly MACHINE-SPECIFIC, and would * X * have to be rewritten for a different CPU. The handler * X * routines are accessed only via pointers in the optab[] * X * array, however, so machine dependencies are confined to * X * this file, its sister file "disfp.c", and the data file * X * "distabs.c". * X * * X * All of the code in this file is based on the assumption * X * of sixteen-bit integers. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X X#include "dis.h" /* Disassembler declarations */ X int segflg; /* Segment-override flag */ X unsigned char objbuf[OBJMAX]; /* Buffer for object code */ X int objptr; /* Index into objbuf[] */ X unsigned long PC; /* Current program counter */ X X /* * * * * * MISCELLANEOUS SUPPORTING ROUTINES * * * * * */ X X void objini(j) /* Object code init routine */ X X register int j; X X{ X if ((segflg == 1) || (segflg == 2)) X segflg *= 3; X else X segflg = 0; X objptr = 0; X objbuf[objptr++] = (unsigned char)(j); X} X X void objout() /* Object-code output routine */ X X{ X register int k; X X if ( ! objflg ) X return; X else X { X printf("\t|"); X if (symptr >= 0) X printf(" %05.5lx:",(PC + 1L - (long)(objptr))); X for (k = 0; k < objptr; ++k) X printf(" %02.2x",objbuf[k]); X putchar('\n'); X } X} X X void badseq(j,k) /* Invalid-sequence routine */ X X register int j, k; X X{ X printf("\t.byte\t0x%02.2x\t\t| invalid code sequence\n",j); X printf("\t.byte\t0x%02.2x\n",k); X} X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This routine is the first of several opcode-specific * X * handlers, each of which is dedicated to a particular * X * opcode family. A pointer to a handler routine is con- * X * tained in the second field of each optab[] entry. The * X * dfhand() routine is the default handler, invoked when * X * no other handler is appropriate (generally, when an in- * X * valid opcode is encountered). * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void dfhand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF dfhand() * * * * * * * * * */ X X segflg = 0; X X printf("\t.byte\t0x%02.2x",j); X X if (optab[j].min || optab[j].max) X putchar('\n'); X else X printf("\t\t| unimplemented opcode\n"); X X}/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the single-byte handler, invoked whenever a * X * one-byte opcode is encountered. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void sbhand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF sbhand() * * * * * * * * * */ X X objini(j); X X if (j == 0x2e) /* seg cs */ X segflg = 1; X X if ((j == 0x26) /* seg es */ X || (j == 0x36) /* seg ss */ X || (j == 0x3e)) /* seg ds */ X segflg = 2; X X printf("%s\n",optab[j].text); X X objout(); X X}/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for most of the processor's regular * X * arithmetic operations. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void aohand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF aohand() * * * * * * * * * */ X X register int k; X int m, n; X char b[64]; X X objini(j); X X switch (j & 7) X { X case 0 : X case 1 : X case 2 : X case 3 : X printf("%s\t",optab[j].text); X FETCH(k); X printf("%s\n",mtrans(j,k,TR_STD)); X break; X case 4 : X FETCH(k); X printf("%s\tal,*0x%02.2x\n",optab[j].text,k); X break; X case 5 : X FETCH(m); X FETCH(n); X k = (n << 8) | m; X if (lookext((long)(k),(PC - 1),b)) X printf("%s\tax,#%s\n",optab[j].text,b); X else X printf("%s\tax,#0x%04.4x\n",optab[j].text,k); X break; X default : X dfhand(j); X break; X } X X objout(); X X}/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for opcodes which perform short * X * (eight-bit) relative jumps. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void sjhand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF sjhand() * * * * * * * * * */ X X register int k; X int m; X X objini(j); X X FETCH(m); X X if (m & 0x80) X k = 0xff00; X else X k = 0; X X k |= m; X X printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, X lookup((PC + k + 1L),N_TEXT,LOOK_REL,-1L), X (PC + k + 1L)); X X objout(); X X}/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for a loosely-knit family of op- * X * codes which perform arithmetic and logical operations, * X * and which take immediate data. The routine's logic is * X * rather complex, so, in an effort to avoid additional * X * complexity, the search for external references in the * X * relocation table has been dispensed with. Eager hackers * X * can try their hand at coding such a search. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void imhand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF imhand() * * * * * * * * * */ X X unsigned long pc; X register int k; X int offset, oflag, immed, iflag, mod, opi, w, rm; X int m, n; X static char a[100], b[30]; X X objini(j); X X FETCH(k); X X pc = PC + 1; X X offset = 0; X mod = (k & 0xc0) >> 6; X opi = (k & 0x38) >> 3; X w = j & 1; X rm = k & 7; X X if ((j & 2) X && ((opi == 1) X || (opi == 4) X || (opi == 6))) X { X badseq(j,k); X return; X } X X strcpy(a,OPFAM[opi]); X X if ( ! w ) X strcat(a,"b"); X X if ((oflag = mod) > 2) X oflag = 0; X X if ((mod == 0) && (rm == 6)) X { X FETCH(m); X FETCH(n); X offset = (n << 8) | m; X } X else if (oflag) X if (oflag == 2) X { X FETCH(m); X FETCH(n); X offset = (n << 8) | m; X } X else X { X FETCH(m); X if (m & 0x80) X n = 0xff00; X else X n = 0; X offset = n | m; X } X X switch (j & 3) X { X case 0 : X case 2 : X FETCH(immed); X iflag = 0; X break; X case 1 : X FETCH(m); X FETCH(n); X immed = (n << 8) | m; X iflag = 1; X break; X case 3 : X FETCH(immed); X if (immed & 0x80) X immed &= 0xff00; X iflag = 0; X break; X } X X strcat(a,"\t"); X X switch (mod) X { X case 0 : X if (rm == 6) X strcat(a, X lookup((long)(offset),N_DATA,LOOK_ABS,pc)); X else X { X sprintf(b,"(%s)",REGS0[rm]); X strcat(a,b); X } X break; X case 1 : X case 2 : X if (mod == 1) X strcat(a,"*"); X else X strcat(a,"#"); X sprintf(b,"%d(",offset); X strcat(a,b); X strcat(a,REGS1[rm]); X strcat(a,")"); X break; X case 3 : X strcat(a,REGS[(w << 3) | rm]); X break; X } X X strcat(a,","); X if (iflag) X strcat(a,"#"); X else X strcat(a,"*"); X sprintf(b,"%d",immed); X strcat(a,b); X X printf("%s\n",a); X X objout(); X X}/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for various "mov"-type opcodes * X * which use the mod, reg, and r/m fields of the second * X * code byte in a standard, straightforward way. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void mvhand(j) X X int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF mvhand() * * * * * * * * * */ X X register int k, m = j; X X objini(j); X X FETCH(k); X X if ((m == 0x84) || (m == 0x85) /* Kind of kludgey */ X || (m == 0xc4) || (m == 0xc5) X || (m == 0x8d)) X if (m & 0x40) X m |= 0x03; X else X m |= 0x02; X X printf("%s\t%s\n",optab[j].text,mtrans(m,k,TR_STD)); X X objout(); X X}/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for segment-register "mov" opcodes. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void mshand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF mshand() * * * * * * * * * */ X X register int k; X X objini(j); X X FETCH(k); X X if (k & 0x20) X { X badseq(j,k); X return; X } X X printf("%s\t%s\n",optab[j].text,mtrans(j,k,TR_SEG)); X X objout(); X X}/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for pops, other than single-byte * X * pops. (The 8088 allows popping into any register, or * X * directly into memory, accessed either immediately or * X * through a register and an index.) * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void pohand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF pohand() * * * * * * * * * */ X X char *a; X register int k; X X objini(j); X X FETCH(k); X X if (k & 0x38) X { X badseq(j,k); X return; X } X X printf("%s\t",optab[j].text); X X a = mtrans((j & 0xfd),k,TR_STD); X X mtrunc(a); X X printf("%s\n",a); X X objout(); X X}/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler routine for intersegment calls and * X * jumps. Its output is never symbolic, because the host * X * linker does not allow symbolic intersegment address * X * references except by means of symbolic constants, and * X * any such constants in the symbol table, even if they * X * are of the appropriate value, may be misleading. In * X * compiled code, intersegment references should not be * X * encountered, and even in assembled code, they should * X * occur infrequently. If and when they do occur, however, * X * they will be disassembled in absolute form. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void cihand(j) X X int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF cihand() * * * * * * * * * */ X X register int m, n; X X objini(j); X X printf("%s\t",optab[j].text); X X FETCH(m); X FETCH(n); X X printf("#0x%04.4x,",((n << 8) | m)); X X FETCH(m); X FETCH(n); X X printf("#0x%04.4x\n",((n << 8) | m)); X X objout(); X X}/* * * * * * * * * * * END OF cihand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for "mov" opcodes with immediate * X * data. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void mihand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF mihand() * * * * * * * * * */ X X register int k; X int m, n; X char b[64]; X X objini(j); X X printf("%s",optab[j].text); X X if (j & 8) X { X FETCH(m); X FETCH(n); X k = ((n << 8) | m); X if (lookext((long)(k),(PC - 1),b)) X printf("#%s\n",b); X else X printf("#%d\n",k); X } X else X { X FETCH(m); X printf("*%d\n",m); X } X X objout(); X X}/* * * * * * * * * * * END OF mihand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for a family of quick-move opcodes. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void mqhand(j) X X int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF mqhand() * * * * * * * * * */ X X unsigned long pc; X register int m, n; X X objini(j); X X pc = PC + 1; X X FETCH(m); X FETCH(n); X X m = (n << 8) | m; X X printf("%s\t",optab[j].text); X X if (j & 2) X printf("%s,%s\n", X lookup((long)(m),N_DATA,LOOK_ABS,pc), X REGS[(j & 1) << 3]); X else X printf("%s,%s\n", X REGS[(j & 1) << 3], X lookup((long)(m),N_DATA,LOOK_ABS,pc)); X X objout(); X X}/* * * * * * * * * * * END OF mqhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for a family of quick-test opcodes. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void tqhand(j) X X int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF tqhand() * * * * * * * * * */ X X register int m, n; X int k; X char b[64]; X X objini(j); X X printf("%s\t%s,",optab[j].text,REGS[(j & 1) << 3]); X X FETCH(m); X X if (j & 1) X { X FETCH(n); X k = ((n << 8) | m); X if (lookext((long)(k),(PC - 1),b)) X printf("#%s\n",b); X else X printf("#%d\n",k); X } X else X { X if (m & 80) X m |= 0xff00; X printf("*%d\n",m); X } X X objout(); X X}/* * * * * * * * * * * END OF tqhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for multiple-byte "return" opcodes. * X * The 8088 allows returns to take an optional 16-bit ar- * X * gument, which reflects the amount to be added to SP * X * after the pop of the return address. The idea is to * X * facilitate the use of local parameters on the stack. * X * After some rumination, it was decided to disassemble * X * any such arguments as absolute quantities, rather than * X * rummaging through the symbol table for possible corre- * X * sponding constants. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void rehand(j) X X int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF rehand() * * * * * * * * * */ X X register int m, n; X X objini(j); X X FETCH(m); X FETCH(n); X X m = (n << 8) | m; X X printf("%s\t#0x%04.4x\n",optab[j].text,m); X X objout(); X X}/* * * * * * * * * * * END OF rehand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for "mov" opcodes involving memory * X * and immediate data. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void mmhand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF mmhand() * * * * * * * * * */ X X char *a; X register int k; X char b[64]; X X objini(j); X X FETCH(k); X X if (k & 0x38) X { X badseq(j,k); X return; X } X X printf("%s",optab[j].text); X X if ( ! (j & 1) ) X putchar('b'); X X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); X X mtrunc(a); X X printf("\t%s,",a); X X if (j & 1) X { X FETCH(j); X FETCH(k); X k = (k << 8) | j; X if (lookext((long)(k),(PC - 1),b)) X printf("#%s\n",b); X else X printf("#%d\n",k); X } X else X { X FETCH(k); X printf("*%d\n",k); X } X X objout(); X X}/* * * * * * * * * * * END OF mmhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for the 8088 family of shift and * X * rotate instructions. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void srhand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF srhand() * * * * * * * * * */ X X char *a; X register int k; X X objini(j); X X FETCH(k); X X if ((k & 0x38) == 0x30) X { X badseq(j,k); X return; X } X X printf("%s",OPFAM[((k & 0x38) >> 3) + 16]); X X if ( ! (j & 1) ) X putchar('b'); X X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); X X mtrunc(a); X X printf("\t%s",a); X X if (j & 2) X printf(",cl\n"); X else X printf(",*1\n"); X X objout(); X X}/* * * * * * * * * * * END OF srhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for the ASCII-adjust opcodes. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void aahand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF aahand() * * * * * * * * * */ X X register int k; X X objini(j); X X FETCH(k); X X if (k != 0x0a) X { X badseq(j,k); X return; X } X X printf("%s\n",optab[j].text); X X objout(); X X}/* * * * * * * * * * * END OF aahand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for port I/O opcodes which specify * X * the port address as an immediate operand. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void iohand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF iohand() * * * * * * * * * */ X X register int k; X X objini(j); X X FETCH(k); X X printf("%s\t0x%02.2x\n",optab[j].text,k); X X objout(); X X}/* * * * * * * * * * * END OF iohand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for opcodes which perform long * X * (sixteen-bit) relative jumps and calls. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void ljhand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF ljhand() * * * * * * * * * */ X X register int k; X int m, n; X X objini(j); X X FETCH(m); X FETCH(n); X X k = (n << 8) | m; X X printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text, X lookup((PC + k + 1L),N_TEXT,LOOK_LNG,(PC - 1L)), X (PC + k + 1L)); X X objout(); X X}/* * * * * * * * * * * END OF ljhand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for a pair of oddball opcodes (0xf6 * X * and 0xf7) which perform miscellaneous arithmetic opera- * X * tions not dealt with elsewhere. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void mahand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF mahand() * * * * * * * * * */ X X char *a; X register int k; X char b[64]; X X objini(j); X X FETCH(k); X X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); X X mtrunc(a); X X switch (((k = objbuf[1]) & 0x38) >> 3) X { X case 0 : X printf("\ttest"); X break; X case 1 : X badseq(j,k); X return; X case 2 : X printf("\tnot"); X break; X case 3 : X printf("\tneg"); X break; X case 4 : X printf("\tmul"); X break; X case 5 : X printf("\timul"); X break; X case 6 : X printf("\tdiv"); X break; X case 7 : X printf("\tidiv"); X break; X } X X if ( ! (j & 1) ) X putchar('b'); X X printf("\t%s",a); X X if (k & 0x38) X putchar('\n'); X else X if (j & 1) X { X FETCH(j); X FETCH(k); X k = (k << 8) | j; X if (lookext((long)(k),(PC - 1),b)) X printf(",#%s\n",b); X else X printf(",#%d\n",k); X } X else X { X FETCH(k); X printf(",*%d\n",k); X } X X objout(); X X}/* * * * * * * * * * * END OF mahand() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This is the handler for miscellaneous jump, call, push, * X * and increment/decrement opcodes (0xfe and 0xff) which * X * are not dealt with elsewhere. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void mjhand(j) X X register int j; /* Pointer to optab[] entry */ X X{/* * * * * * * * * * START OF mjhand() * * * * * * * * * */ X X char *a; X register int k; X X objini(j); X X FETCH(k); X X a = mtrans((j & 0xfd),(k & 0xc7),TR_STD); X X mtrunc(a); X X switch (((k = objbuf[1]) & 0x38) >> 3) X { X case 0 : X printf("\tinc"); X if ( ! (j & 1) ) X putchar('b'); X putchar('\t'); X break; X case 1 : X printf("\tdec"); X if ( ! (j & 1) ) X putchar('b'); X putchar('\t'); X break; X case 2 : X if (j & 1) X printf("\tcall\t@"); X else X goto BAD; X break; X case 3 : X if (j & 1) X printf("\tcalli\t@"); X else X goto BAD; X break; X case 4 : X if (j & 1) X printf("\tjmp\t@"); X else X goto BAD; X break; X case 5 : X if (j & 1) X printf("\tjmpi\t@"); X else X goto BAD; X break; X case 6 : X if (j & 1) X printf("\tpush\t"); X else X goto BAD; X break; X case 7 : X BAD : X badseq(j,k); X return; X } X X printf("%s\n",a); X X objout(); X X}/* * * * * * * * * * * END OF mjhand() * * * * * * * * * * */ X X END_OF_FILE if test 25688 -ne `wc -c <'dishand.c'`; then echo shar: \"'dishand.c'\" unpacked with wrong size! fi # end of 'dishand.c' fi if test -f 'distabs.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'distabs.c'\" else echo shar: Extracting \"'distabs.c'\" \(30238 characters\) sed "s/^X//" >'distabs.c' <<'END_OF_FILE' static char *sccsid = X "@(#) distabs.c, Ver. 2.1 created 00:00:00 87/09/01"; X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * Copyright (C) 1987 G. M. Harding, all rights reserved * X * * X * Permission to copy and redistribute is hereby granted, * X * provided full source code, with all copyright notices, * X * accompanies any redistribution. * X * * X * This file contains the lookup tables and other data * X * structures for the Intel 8088 symbolic disassembler. It * X * also contains a few global routines which facilitate * X * access to the tables, for use primarily by the handler * X * functions. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X X#include "dis.h" /* Disassembler declarations */ X struct exec HDR; /* Used to hold header info */ X struct nlist symtab[MAXSYM]; /* Array of symbol table info */ X struct reloc relo[MAXSYM]; /* Array of relocation info */ X int symptr = -1, /* Index into symtab[] */ X relptr = -1; /* Index into relo[] */ X char *REGS[] = /* Table of register names */ X { X "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", X "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", X "es", "cs", "ss", "ds" X }; X char *REGS0[] = /* Mode 0 register name table */ X { X "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "", "bx" X }; X char *REGS1[] = /* Mode 1 register name table */ X { X "bx_si", "bx_di", "bp_si", "bp_di", "si", "di", "bp", "bx" X }; X int symrank[6][6] = /* Symbol type/rank matrix */ X { X /* UND ABS TXT DAT BSS COM */ X /* UND */ 5, 4, 1, 2, 3, 0, X /* ABS */ 1, 5, 4, 3, 2, 0, X /* TXT */ 4, 1, 5, 3, 2, 0, X /* DAT */ 3, 1, 2, 5, 4, 0, X /* BSS */ 3, 1, 2, 4, 5, 0, X /* COM */ 2, 0, 1, 3, 4, 5 X }; X X /* * * * * * * * * * * * OPCODE DATA * * * * * * * * * * * */ X char ADD[] = "\tadd", /* Mnemonics by family */ X OR[] = "\tor", X ADC[] = "\tadc", X SBB[] = "\tsbb", X AND[] = "\tand", X SUB[] = "\tsub", X XOR[] = "\txor", X CMP[] = "\tcmp", X NOT[] = "\tnot", X NEG[] = "\tneg", X MUL[] = "\tmul", X DIV[] = "\tdiv", X MOV[] = "\tmov", X ESC[] = "\tesc", X TEST[] = "\ttest", X AMBIG[] = "", X ROL[] = "\trol", X ROR[] = "\tror", X RCL[] = "\trcl", X RCR[] = "\trcr", X SAL[] = "\tsal", X SHR[] = "\tshr", X SHL[] = "\tshl", X SAR[] = "\tsar"; X char *OPFAM[] = /* Family lookup table */ X { X ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, X NOT, NEG, MUL, DIV, MOV, ESC, TEST, AMBIG, X ROL, ROR, RCL, RCR, SAL, SHR, SHL, SAR X }; X struct opcode optab[] = /* Table of opcode data */ X { X ADD, aohand, 2, 4, /* 0x00 */ X ADD, aohand, 2, 4, /* 0x01 */ X ADD, aohand, 2, 4, /* 0x02 */ X ADD, aohand, 2, 4, /* 0x03 */ X ADD, aohand, 2, 2, /* 0x04 */ X ADD, aohand, 3, 3, /* 0x05 */ X "\tpush\tes", sbhand, 1, 1, /* 0x06 */ X "\tpop\tes", sbhand, 1, 1, /* 0x07 */ X OR, aohand, 2, 4, /* 0x08 */ X OR, aohand, 2, 4, /* 0x09 */ X OR, aohand, 2, 4, /* 0x0a */ X OR, aohand, 2, 4, /* 0x0b */ X OR, aohand, 2, 2, /* 0x0c */ X OR, aohand, 3, 3, /* 0x0d */ X "\tpush\tcs", sbhand, 1, 1, /* 0x0e */ X NULL, dfhand, 0, 0, /* 0x0f */ X ADC, aohand, 2, 4, /* 0x10 */ X ADC, aohand, 2, 4, /* 0x11 */ X ADC, aohand, 2, 4, /* 0x12 */ X ADC, aohand, 2, 4, /* 0x13 */ X ADC, aohand, 2, 2, /* 0x14 */ X ADC, aohand, 3, 3, /* 0x15 */ X "\tpush\tss", sbhand, 1, 1, /* 0x16 */ X "\tpop\tss", sbhand, 1, 1, /* 0x17 */ X SBB, aohand, 2, 4, /* 0x18 */ X SBB, aohand, 2, 4, /* 0x19 */ X SBB, aohand, 2, 4, /* 0x1a */ X SBB, aohand, 2, 4, /* 0x1b */ X SBB, aohand, 2, 2, /* 0x1c */ X SBB, aohand, 3, 3, /* 0x1d */ X "\tpush\tds", sbhand, 1, 1, /* 0x1e */ X "\tpop\tds", sbhand, 1, 1, /* 0x1f */ X AND, aohand, 2, 4, /* 0x20 */ X AND, aohand, 2, 4, /* 0x21 */ X AND, aohand, 2, 4, /* 0x22 */ X AND, aohand, 2, 4, /* 0x23 */ X AND, aohand, 2, 2, /* 0x24 */ X AND, aohand, 3, 3, /* 0x25 */ X "\tseg\tes", sbhand, 1, 1, /* 0x26 */ X "\tdaa", sbhand, 1, 1, /* 0x27 */ X SUB, aohand, 2, 4, /* 0x28 */ X SUB, aohand, 2, 4, /* 0x29 */ X SUB, aohand, 2, 4, /* 0x2a */ X SUB, aohand, 2, 4, /* 0x2b */ X SUB, aohand, 2, 2, /* 0x2c */ X SUB, aohand, 3, 3, /* 0x2d */ X "\tseg\tcs", sbhand, 1, 1, /* 0x2e */ X "\tdas", sbhand, 1, 1, /* 0x2f */ X XOR, aohand, 2, 4, /* 0x30 */ X XOR, aohand, 2, 4, /* 0x31 */ X XOR, aohand, 2, 4, /* 0x32 */ X XOR, aohand, 2, 4, /* 0x33 */ X XOR, aohand, 2, 2, /* 0x34 */ X XOR, aohand, 3, 3, /* 0x35 */ X "\tseg\tss", sbhand, 1, 1, /* 0x36 */ X "\taaa", sbhand, 1, 1, /* 0x37 */ X CMP, aohand, 2, 4, /* 0x38 */ X CMP, aohand, 2, 4, /* 0x39 */ X CMP, aohand, 2, 4, /* 0x3a */ X CMP, aohand, 2, 4, /* 0x3b */ X CMP, aohand, 2, 2, /* 0x3c */ X CMP, aohand, 3, 3, /* 0x3d */ X "\tseg\tds", sbhand, 1, 1, /* 0x3e */ X "\taas", sbhand, 1, 1, /* 0x3f */ X "\tinc\tax", sbhand, 1, 1, /* 0x40 */ X "\tinc\tcx", sbhand, 1, 1, /* 0x41 */ X "\tinc\tdx", sbhand, 1, 1, /* 0x42 */ X "\tinc\tbx", sbhand, 1, 1, /* 0x43 */ X "\tinc\tsp", sbhand, 1, 1, /* 0x44 */ X "\tinc\tbp", sbhand, 1, 1, /* 0x45 */ X "\tinc\tsi", sbhand, 1, 1, /* 0x46 */ X "\tinc\tdi", sbhand, 1, 1, /* 0x47 */ X "\tdec\tax", sbhand, 1, 1, /* 0x48 */ X "\tdec\tcx", sbhand, 1, 1, /* 0x49 */ X "\tdec\tdx", sbhand, 1, 1, /* 0x4a */ X "\tdec\tbx", sbhand, 1, 1, /* 0x4b */ X "\tdec\tsp", sbhand, 1, 1, /* 0x4c */ X "\tdec\tbp", sbhand, 1, 1, /* 0x4d */ X "\tdec\tsi", sbhand, 1, 1, /* 0x4e */ X "\tdec\tdi", sbhand, 1, 1, /* 0x4f */ X "\tpush\tax", sbhand, 1, 1, /* 0x50 */ X "\tpush\tcx", sbhand, 1, 1, /* 0x51 */ X "\tpush\tdx", sbhand, 1, 1, /* 0x52 */ X "\tpush\tbx", sbhand, 1, 1, /* 0x53 */ X "\tpush\tsp", sbhand, 1, 1, /* 0x54 */ X "\tpush\tbp", sbhand, 1, 1, /* 0x55 */ X "\tpush\tsi", sbhand, 1, 1, /* 0x56 */ X "\tpush\tdi", sbhand, 1, 1, /* 0x57 */ X "\tpop\tax", sbhand, 1, 1, /* 0x58 */ X "\tpop\tcx", sbhand, 1, 1, /* 0x59 */ X "\tpop\tdx", sbhand, 1, 1, /* 0x5a */ X "\tpop\tbx", sbhand, 1, 1, /* 0x5b */ X "\tpop\tsp", sbhand, 1, 1, /* 0x5c */ X "\tpop\tbp", sbhand, 1, 1, /* 0x5d */ X "\tpop\tsi", sbhand, 1, 1, /* 0x5e */ X "\tpop\tdi", sbhand, 1, 1, /* 0x5f */ X NULL, dfhand, 0, 0, /* 0x60 */ X NULL, dfhand, 0, 0, /* 0x61 */ X NULL, dfhand, 0, 0, /* 0x62 */ X NULL, dfhand, 0, 0, /* 0x63 */ X NULL, dfhand, 0, 0, /* 0x64 */ X NULL, dfhand, 0, 0, /* 0x65 */ X NULL, dfhand, 0, 0, /* 0x66 */ X NULL, dfhand, 0, 0, /* 0x67 */ X NULL, dfhand, 0, 0, /* 0x68 */ X NULL, dfhand, 0, 0, /* 0x69 */ X NULL, dfhand, 0, 0, /* 0x6a */ X NULL, dfhand, 0, 0, /* 0x6b */ X NULL, dfhand, 0, 0, /* 0x6c */ X NULL, dfhand, 0, 0, /* 0x6d */ X NULL, dfhand, 0, 0, /* 0x6e */ X NULL, dfhand, 0, 0, /* 0x6f */ X "\tjo", sjhand, 2, 2, /* 0x70 */ X "\tjno", sjhand, 2, 2, /* 0x71 */ X "\tjc", sjhand, 2, 2, /* 0x72 */ X "\tjnc", sjhand, 2, 2, /* 0x73 */ X "\tjz", sjhand, 2, 2, /* 0x74 */ X "\tjnz", sjhand, 2, 2, /* 0x75 */ X "\tjna", sjhand, 2, 2, /* 0x76 */ X "\tja", sjhand, 2, 2, /* 0x77 */ X "\tjs", sjhand, 2, 2, /* 0x78 */ X "\tjns", sjhand, 2, 2, /* 0x79 */ X "\tjp", sjhand, 2, 2, /* 0x7a */ X "\tjnp", sjhand, 2, 2, /* 0x7b */ X "\tjl", sjhand, 2, 2, /* 0x7c */ X "\tjnl", sjhand, 2, 2, /* 0x7d */ X "\tjng", sjhand, 2, 2, /* 0x7e */ X "\tjg", sjhand, 2, 2, /* 0x7f */ X AMBIG, imhand, 3, 5, /* 0x80 */ X AMBIG, imhand, 4, 6, /* 0x81 */ X AMBIG, imhand, 3, 5, /* 0x82 */ X AMBIG, imhand, 3, 5, /* 0x83 */ X TEST, mvhand, 2, 4, /* 0x84 */ X TEST, mvhand, 2, 4, /* 0x85 */ X "\txchg", mvhand, 2, 4, /* 0x86 */ X "\txchg", mvhand, 2, 4, /* 0x87 */ X MOV, mvhand, 2, 4, /* 0x88 */ X MOV, mvhand, 2, 4, /* 0x89 */ X MOV, mvhand, 2, 4, /* 0x8a */ X MOV, mvhand, 2, 4, /* 0x8b */ X MOV, mshand, 2, 4, /* 0x8c */ X "\tlea", mvhand, 2, 4, /* 0x8d */ X MOV, mshand, 2, 4, /* 0x8e */ X "\tpop", pohand, 2, 4, /* 0x8f */ X "\tnop", sbhand, 1, 1, /* 0x90 */ X "\txchg\tax,cx", sbhand, 1, 1, /* 0x91 */ X "\txchg\tax,dx", sbhand, 1, 1, /* 0x92 */ X "\txchg\tax,bx", sbhand, 1, 1, /* 0x93 */ X "\txchg\tax,sp", sbhand, 1, 1, /* 0x94 */ X "\txchg\tax,bp", sbhand, 1, 1, /* 0x95 */ X "\txchg\tax,si", sbhand, 1, 1, /* 0x96 */ X "\txchg\tax,di", sbhand, 1, 1, /* 0x97 */ X "\tcbw", sbhand, 1, 1, /* 0x98 */ X "\tcwd", sbhand, 1, 1, /* 0x99 */ X "\tcalli", cihand, 5, 5, /* 0x9a */ X "\twait", sbhand, 1, 1, /* 0x9b */ X "\tpushf", sbhand, 1, 1, /* 0x9c */ X "\tpopf", sbhand, 1, 1, /* 0x9d */ X "\tsahf", sbhand, 1, 1, /* 0x9e */ X "\tlahf", sbhand, 1, 1, /* 0x9f */ X MOV, mqhand, 3, 3, /* 0xa0 */ X MOV, mqhand, 3, 3, /* 0xa1 */ X MOV, mqhand, 3, 3, /* 0xa2 */ X MOV, mqhand, 3, 3, /* 0xa3 */ X "\tmovb", sbhand, 1, 1, /* 0xa4 */ X "\tmovw", sbhand, 1, 1, /* 0xa5 */ X "\tcmpb", sbhand, 1, 1, /* 0xa6 */ X "\tcmpw", sbhand, 1, 1, /* 0xa7 */ X TEST, tqhand, 2, 2, /* 0xa8 */ X TEST, tqhand, 3, 3, /* 0xa9 */ X "\tstob", sbhand, 1, 1, /* 0xaa */ X "\tstow", sbhand, 1, 1, /* 0xab */ X "\tlodb", sbhand, 1, 1, /* 0xac */ X "\tlodw", sbhand, 1, 1, /* 0xad */ X "\tscab", sbhand, 1, 1, /* 0xae */ X "\tscaw", sbhand, 1, 1, /* 0xaf */ X "\tmov\tal,", mihand, 2, 2, /* 0xb0 */ X "\tmov\tcl,", mihand, 2, 2, /* 0xb1 */ X "\tmov\tdl,", mihand, 2, 2, /* 0xb2 */ X "\tmov\tbl,", mihand, 2, 2, /* 0xb3 */ X "\tmov\tah,", mihand, 2, 2, /* 0xb4 */ X "\tmov\tch,", mihand, 2, 2, /* 0xb5 */ X "\tmov\tdh,", mihand, 2, 2, /* 0xb6 */ X "\tmov\tbh,", mihand, 2, 2, /* 0xb7 */ X "\tmov\tax,", mihand, 3, 3, /* 0xb8 */ X "\tmov\tcx,", mihand, 3, 3, /* 0xb9 */ X "\tmov\tdx,", mihand, 3, 3, /* 0xba */ X "\tmov\tbx,", mihand, 3, 3, /* 0xbb */ X "\tmov\tsp,", mihand, 3, 3, /* 0xbc */ X "\tmov\tbp,", mihand, 3, 3, /* 0xbd */ X "\tmov\tsi,", mihand, 3, 3, /* 0xbe */ X "\tmov\tdi,", mihand, 3, 3, /* 0xbf */ X NULL, dfhand, 0, 0, /* 0xc0 */ X NULL, dfhand, 0, 0, /* 0xc1 */ X "\tret", rehand, 3, 3, /* 0xc2 */ X "\tret", sbhand, 1, 1, /* 0xc3 */ X "\tles", mvhand, 2, 4, /* 0xc4 */ X "\tlds", mvhand, 2, 4, /* 0xc5 */ X MOV, mmhand, 3, 5, /* 0xc6 */ X MOV, mmhand, 4, 6, /* 0xc7 */ X NULL, dfhand, 0, 0, /* 0xc8 */ X NULL, dfhand, 0, 0, /* 0xc9 */ X "\treti", rehand, 3, 3, /* 0xca */ X "\treti", sbhand, 1, 1, /* 0xcb */ X "\tint", sbhand, 1, 1, /* 0xcc */ X "\tint", inhand, 2, 2, /* 0xcd */ X "\tinto", sbhand, 1, 1, /* 0xce */ X "\tiret", sbhand, 1, 1, /* 0xcf */ X AMBIG, srhand, 2, 4, /* 0xd0 */ X AMBIG, srhand, 2, 4, /* 0xd1 */ X AMBIG, srhand, 2, 4, /* 0xd2 */ X AMBIG, srhand, 2, 4, /* 0xd3 */ X "\taam", aahand, 2, 2, /* 0xd4 */ X "\taad", aahand, 2, 2, /* 0xd5 */ X NULL, dfhand, 0, 0, /* 0xd6 */ X "\txlat", sbhand, 1, 1, /* 0xd7 */ X ESC, eshand, 2, 2, /* 0xd8 */ X ESC, eshand, 2, 2, /* 0xd9 */ X ESC, eshand, 2, 2, /* 0xda */ X ESC, eshand, 2, 2, /* 0xdb */ X ESC, eshand, 2, 2, /* 0xdc */ X ESC, eshand, 2, 2, /* 0xdd */ X ESC, eshand, 2, 2, /* 0xde */ X ESC, eshand, 2, 2, /* 0xdf */ X "\tloopne", sjhand, 2, 2, /* 0xe0 */ X "\tloope", sjhand, 2, 2, /* 0xe1 */ X "\tloop", sjhand, 2, 2, /* 0xe2 */ X "\tjcxz", sjhand, 2, 2, /* 0xe3 */ X "\tin", iohand, 2, 2, /* 0xe4 */ X "\tinw", iohand, 2, 2, /* 0xe5 */ X "\tout", iohand, 2, 2, /* 0xe6 */ X "\toutw", iohand, 2, 2, /* 0xe7 */ X "\tcall", ljhand, 3, 3, /* 0xe8 */ X "\tjmp", ljhand, 3, 3, /* 0xe9 */ X "\tjmpi", cihand, 5, 5, /* 0xea */ X "\tj", sjhand, 2, 2, /* 0xeb */ X "\tin", sbhand, 1, 1, /* 0xec */ X "\tinw", sbhand, 1, 1, /* 0xed */ X "\tout", sbhand, 1, 1, /* 0xee */ X "\toutw", sbhand, 1, 1, /* 0xef */ X "\tlock", sbhand, 1, 1, /* 0xf0 */ X NULL, dfhand, 0, 0, /* 0xf1 */ X "\trepnz", sbhand, 1, 1, /* 0xf2 */ X "\trepz", sbhand, 1, 1, /* 0xf3 */ X "\thlt", sbhand, 1, 1, /* 0xf4 */ X "\tcmc", sbhand, 1, 1, /* 0xf5 */ X AMBIG, mahand, 2, 5, /* 0xf6 */ X AMBIG, mahand, 2, 6, /* 0xf7 */ X "\tclc", sbhand, 1, 1, /* 0xf8 */ X "\tstc", sbhand, 1, 1, /* 0xf9 */ X "\tcli", sbhand, 1, 1, /* 0xfa */ X "\tsti", sbhand, 1, 1, /* 0xfb */ X "\tcld", sbhand, 1, 1, /* 0xfc */ X "\tstd", sbhand, 1, 1, /* 0xfd */ X AMBIG, mjhand, 2, 4, /* 0xfe */ X AMBIG, mjhand, 2, 4 /* 0xff */ X }; X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This simple routine returns the name field of a symbol * X * table entry as a printable string. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X char * getnam(k) X X register int k; X X{/* * * * * * * * * * START OF getnam() * * * * * * * * * */ X X register int j; X static char a[9]; X X for (j = 0; j < 8; ++j) X if ( ! symtab[k].n_name[j] ) X break; X else X a[j] = symtab[k].n_name[j]; X X a[j] = '\0'; X X return (a); X X}/* * * * * * * * * * * END OF getnam() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This function is responsible for mucking through the * X * relocation table in search of externally referenced * X * symbols to be output as operands. It accepts two long * X * arguments: the code-segment location at which an extern * X * reference is expected, and the offset value which is * X * embedded in the object code and used at link time to * X * bias the external value. In the most typical case, the * X * function will be called by lookup(), which always makes * X * a check for external names before searching the symbol * X * table proper. However, it may also be called directly * X * by any function (such as the move-immediate handler) * X * which wants to make an independent check for externals. * X * The caller is expected to supply, as the third argument * X * to the function, a pointer to a character buffer large * X * enough to hold any possible output string. Lookext() * X * will fill this buffer and return a logical TRUE if it * X * finds an extern reference; otherwise, it will return a * X * logical FALSE, leaving the buffer undisturbed. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X int lookext(off,loc,buf) X X long off, loc; X char *buf; X X{/* * * * * * * * * * START OF lookext() * * * * * * * * * */ X X register int k; X char c[16]; X X if ((loc != -1L) && (relptr >= 0)) X for (k = 0; k <= relptr; ++k) X if ((relo[k].r_vaddr == loc) X && (relo[k].r_symndx < S_BSS)) X { X strcpy(buf,getnam(relo[k].r_symndx)); X if (off) X { X if (off < 0) X sprintf(c,"%ld",off); X else X sprintf(c,"+%ld",off); X strcat(buf,c); X } X return (1); X } X X return (0); X X}/* * * * * * * * * * END OF lookext() * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This function finds an entry in the symbol table by * X * value. Its input is a (long) machine address, and its * X * output is a pointer to a string containing the corre- * X * sponding symbolic name. The function first searches the * X * relocation table for a possible external reference; if * X * none is found, a linear search of the symbol table is * X * undertaken. If no matching symbol has been found at the * X * end of these searches, the function returns a pointer * X * to a string containing the ASCII equivalent of the ad- * X * dress which was to be located, so that, regardless of * X * the success of the search, the function's return value * X * is suitable for use as a memory-reference operand. The * X * caller specifies the type of symbol to be found (text, * X * data, bss, undefined, absolute, or common) by means of * X * the function's second parameter. The third parameter * X * specifies the format to be used in the event of a nu- * X * meric output: zero for absolute format, one for short * X * relative format, two for long relative format. The * X * fourth parameter is the address which would appear in * X * the relocation table for the reference in question, or * X * -1 if the relocation table is not to be searched. The * X * function attempts to apply a certain amount of intelli- * X * gence in its selection of symbols, so it is possible * X * that, in the absence of a type match, a symbol of the * X * correct value but different type will be returned. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X char * lookup(addr,type,kind,ext) X X long addr; /* Machine address to be located */ X X int type, /* Type of symbol to be matched */ X kind; /* Addressing output mode to use */ X X long ext; /* Value for extern ref, if any */ X X{/* * * * * * * * * * START OF lookup() * * * * * * * * * */ X X register int j, k; X static char b[64]; X X struct X { X int i; X int t; X } X best; X X if (lookext(addr,ext,b)) X return (b); X X if (segflg) X if (segflg & 1) X type = N_TEXT; X else X type = N_DATA; X X for (k = 0, best.i = -1; k <= symptr; ++k) X if (symtab[k].n_value == addr) X if ((j = symtab[k].n_sclass & N_SECT) == type) X { X best.t = j; X best.i = k; X break; X } X else if (segflg || (HDR.a_flags & A_SEP)) X continue; X else if (best.i < 0) X best.t = j, best.i = k; X else if (symrank[type][j] > symrank[type][best.t]) X best.t = j, best.i = k; X X if (best.i >= 0) X return (getnam(best.i)); X X if (kind == LOOK_ABS) X sprintf(b,"0x%05.5x",addr); X else X { X long x = addr - (PC - kind); X if (x < 0) X sprintf(b,".%ld",x); X else X sprintf(b,".+%ld",x); X } X X return (b); X X}/* * * * * * * * * * * END OF lookup() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This function translates an 8088 addressing mode byte * X * to an equivalent assembler string, returning a pointer * X * thereto. If necessary, it performs successive inputs * X * of bytes from the object file in order to obtain offset * X * data, adjusting PC accordingly. (The addressing mode * X * byte appears in several 8088 opcodes; it is used to * X * specify source and destination operand locations.) The * X * third argument to the function is zero if the standard * X * registers are to be used, or eight if the segment reg- * X * isters are to be used; these constants are defined sym- * X * bolically in dis.h. NOTE: The mtrans() function must * X * NEVER be called except immediately after fetching the * X * mode byte. If any additional object bytes are fetched * X * after the fetch of the mode byte, mtrans() will not * X * produce correct output! * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X char * mtrans(c,m,type) X X register int c; /* Primary instruction byte */ X register int m; /* Addressing mode byte */ X X int type; /* Type code: standard or seg */ X X{/* * * * * * * * * * START OF mtrans() * * * * * * * * * */ X X unsigned long pc; X int offset, oflag, dir, w, mod, reg, rm; X static char a[100]; X static char b[30]; X X offset = 0; X dir = c & 2; X w = c & 1; X mod = (m & 0xc0) >> 6; X reg = (m & 0x38) >> 3; X rm = m & 7; X pc = PC + 1; X X if (type) X w = 1; X X if ((oflag = mod) > 2) X oflag = 0; X X if (oflag) X { X int j, k; X if (oflag == 2) X { X FETCH(j); X FETCH(k); X offset = (k << 8) | j; X } X else X { X FETCH(j); X if (j & 0x80) X k = 0xff00; X else X k = 0; X offset = k | j; X } X } X X if (dir) X { X strcpy(a,REGS[type + ((w << 3) | reg)]); X strcat(a,","); X switch (mod) X { X case 0 : X if (rm == 6) X { X int j, k; X FETCH(j); X FETCH(k); X offset = (k << 8) | j; X strcat(a, X lookup((long)(offset),N_DATA,LOOK_ABS,pc)); X } X else X { X sprintf(b,"(%s)",REGS0[rm]); X strcat(a,b); X } X break; X case 1 : X case 2 : X if (mod == 1) X strcat(a,"*"); X else X strcat(a,"#"); X sprintf(b,"%d(",offset); X strcat(a,b); X strcat(a,REGS1[rm]); X strcat(a,")"); X break; X case 3 : X strcat(a,REGS[(w << 3) | rm]); X break; X } X } X else X { X switch (mod) X { X case 0 : X if (rm == 6) X { X int j, k; X FETCH(j); X FETCH(k); X offset = (k << 8) | j; X strcpy(a, X lookup((long)(offset),N_DATA,LOOK_ABS,pc)); X } X else X { X sprintf(b,"(%s)",REGS0[rm]); X strcpy(a,b); X } X break; X case 1 : X case 2 : X if (mod == 1) X strcpy(a,"*"); X else X strcpy(a,"#"); X sprintf(b,"%d(",offset); X strcat(a,b); X strcat(a,REGS1[rm]); X strcat(a,")"); X break; X case 3 : X strcpy(a,REGS[(w << 3) | rm]); X break; X } X strcat(a,","); X strcat(a,REGS[type + ((w << 3) | reg)]); X } X X return (a); X X}/* * * * * * * * * * * END OF mtrans() * * * * * * * * * * */ X X /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X * * X * This simple routine truncates a string returned by the * X * mtrans() function, removing its source operand. This is * X * useful in handlers which ignore the "reg" field of the * X * mode byte. * X * * X * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X void mtrunc(a) X X register char *a; /* Ptr. to string to truncate */ X X{/* * * * * * * * * * START OF mtrunc() * * * * * * * * * */ X X register int k; X X for (k = strlen(a) - 1; k >= 0; --k) X if (a[k] == ',') X { X a[k] = '\0'; X break; X } X X}/* * * * * * * * * * * END OF mtrunc() * * * * * * * * * * */ X X END_OF_FILE if test 30238 -ne `wc -c <'distabs.c'`; then echo shar: \"'distabs.c'\" unpacked with wrong size! fi # end of 'distabs.c' fi echo shar: End of archive 2 \(of 2\). cp /dev/null ark2isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0