|
|
1.1 ! root 1: /* ! 2: * db/i386/i386db2.c ! 3: * A debugger. ! 4: * i386 disassembler. ! 5: * Table-driven, using tables in i386db4.c. ! 6: * A hearty thank-you to the architectural geniuses at Intel Corporation ! 7: * who produced this simple and elegant design -- NOT. ! 8: */ ! 9: ! 10: #include "i386db.h" ! 11: ! 12: #define MAX_INST_LEN 50 /* Max expanded opcode string length */ ! 13: #define MAX_DISP_SIZE 6 /* Max displacement size in bytes */ ! 14: ! 15: /* Instruction prefix codes. */ ! 16: #define ESC2 0x0F /* Escape to 2-byte opcode */ ! 17: #define REP 0xF3 ! 18: #define REPNE 0xF2 ! 19: #define LOCK 0xF0 ! 20: #define AD_PRE 0x67 /* Address size prefix */ ! 21: #define OP_PRE 0x66 /* Operand size prefix */ ! 22: #define CS_PRE 0x2E /* CS: segment override prefix */ ! 23: #define DS_PRE 0x3E ! 24: #define ES_PRE 0x26 ! 25: #define FS_PRE 0x64 ! 26: #define GS_PRE 0x65 ! 27: #define SS_PRE 0x36 ! 28: ! 29: #define EBP_SIB 5 ! 30: ! 31: /* Is_signed arg for get_value() et al.: unsigned or signed displacement. */ ! 32: #define UNSIGNED 0 ! 33: #define SIGNED 1 ! 34: ! 35: /* Flag arg for get_value(): absolute or PC-relative address. */ ! 36: #define ABSOLUTE 0 ! 37: #define PCREL 1 ! 38: ! 39: #define ADDRINDEX(x) (x==32 ? 1 : 0) /* first index for modRMtab[] */ ! 40: #define TOLSYM 0x100 /* print symbol if greater */ ! 41: #define TOLHEX 0x10 /* print hexidecimal if greater */ ! 42: /* print decimal if less */ ! 43: ! 44: /* Disassembler static data. */ ! 45: static int ad_pre_flag; /* address size prefix flag */ ! 46: static long delta; /* displacement */ ! 47: static unsigned char ibp[MAX_DISP_SIZE]; /* input buffer */ ! 48: static unsigned char m; /* "Mod" field of ModR/M byte */ ! 49: static unsigned char mRM; /* "R/M" field of ModR/M byte */ ! 50: static unsigned char mReg; /* "REG" field of ModR/M byte */ ! 51: static int modRM_flag; /* ModR/M byte has been loaded */ ! 52: static char *obp; /* output buffer pointer */ ! 53: static int op_pre_flag; /* operand size prefix flag */ ! 54: static char outbuf[MAX_INST_LEN]; /* output buffer */ ! 55: static int segn; /* segment number */ ! 56: static unsigned char seg_prefix; /* segment prefix, e.g. "cs:" */ ! 57: static int sib_flag; /* SIB byte has been loaded */ ! 58: static unsigned char sb; /* "base" field of SIB byte */ ! 59: static unsigned char sss; /* "ss" field of SIB byte */ ! 60: static unsigned char sx; /* "index" field of SIB byte */ ! 61: ! 62: /* ! 63: * Return the current address size. ! 64: * With no address prefix flag, the address size is aop_size (16 or 32); ! 65: * with address prefix flag, it is the other (32 or 16). ! 66: */ ! 67: int ! 68: ad_size() ! 69: { ! 70: return (ad_pre_flag) ? 48 - aop_size : aop_size; ! 71: } ! 72: ! 73: /* ! 74: * Adjust argument according to specified operand size (possibly escaped). ! 75: */ ! 76: int ! 77: adj_op_size(c2) int c2; ! 78: { ! 79: if (op_size()==16) { ! 80: switch(c2) { /* set to addr16 lengths */ ! 81: case 'a': c2 = 'w'; break; ! 82: case 'p': c2 = 'f'; break; ! 83: case 'v': c2 = 'w'; break; ! 84: } ! 85: } else { ! 86: switch(c2) { /* set to addr32 lengths */ ! 87: case 'a': c2 = 'd'; break; ! 88: case 'p': c2 = 'l'; break; ! 89: case 'v': c2 = 'd'; break; ! 90: } ! 91: } ! 92: return c2; ! 93: } ! 94: ! 95: /* ! 96: * Disassemble from segment 's' to string 'dest'. ! 97: * Return a pointer to its terminator. ! 98: */ ! 99: char * ! 100: disassemble(dest, s) char *dest; int s; ! 101: { ! 102: char is[MAX_INST_LEN]; /* formatted instruction buffer */ ! 103: char *isp, *cp; ! 104: int loop, useMap2; ! 105: ! 106: /* ! 107: * Initialize. ! 108: */ ! 109: segn = s; ! 110: modRM_flag = sib_flag = ad_pre_flag = op_pre_flag = seg_prefix = 0; ! 111: isp = is; ! 112: ! 113: /* ! 114: * Check whether any prefixes are present. ! 115: * Treat each prefix like a separate instruction. ! 116: */ ! 117: for (loop = 1, useMap2 = 0; loop; ) { ! 118: if (get_code(1) == 0) ! 119: return NULL; ! 120: switch (ibp[0]) { ! 121: case REP: ! 122: case REPNE: ! 123: case LOCK: ! 124: loop = 0; ! 125: break; ! 126: case AD_PRE: ! 127: ++ad_pre_flag; ! 128: continue; ! 129: case OP_PRE: ! 130: ++op_pre_flag; ! 131: continue; ! 132: case CS_PRE: ! 133: case DS_PRE: ! 134: case ES_PRE: ! 135: case FS_PRE: ! 136: case GS_PRE: ! 137: case SS_PRE: ! 138: seg_prefix = ibp[0]; ! 139: break; ! 140: case ESC2: /* opcode info is in the next byte */ ! 141: useMap2 = 1; ! 142: if (get_code(1) == 0) ! 143: return NULL; ! 144: loop = 0; ! 145: break; ! 146: default: ! 147: loop = 0; ! 148: } ! 149: } ! 150: ! 151: /* Get formatted opcode string from op_map[12] and store in is[]. */ ! 152: if ((cp = (useMap2) ? op_map_2[ibp[0]] : op_map_1[ibp[0]]) == NULL) { ! 153: sprintf(dest, "Invalid instruction byte = %02x (op_map_%d)\n", ! 154: ibp[0], useMap2 ? 2 : 1); ! 155: return strchr(dest, '\0') ; ! 156: } ! 157: strcpy(isp, cp); ! 158: ! 159: /* ! 160: * Expand the formatted opcode string pointed at by isp to produce an ! 161: * assembler mnemonic string. ! 162: * Make sure dest is pointing to the current ! 163: * end-of-string after each loop. ! 164: */ ! 165: for ( ; isp[0]; isp++) { ! 166: switch (isp[0]) { ! 167: case '%': ! 168: if ((isp = format(isp, dest)) == NULL) { ! 169: printr("Invalid opcode string"); ! 170: return NULL; ! 171: } ! 172: dest = strchr(dest, '\0'); /* point to end of string */ ! 173: break; ! 174: case ' ': ! 175: *dest++ = '\t'; ! 176: *dest = '\0'; ! 177: break; ! 178: case ',': ! 179: *dest++ = isp[0]; ! 180: *dest++ = ' '; ! 181: *dest = '\0'; ! 182: break; ! 183: default: ! 184: *dest++ = isp[0]; ! 185: *dest = '\0'; ! 186: break; ! 187: } ! 188: } ! 189: return dest; ! 190: } ! 191: ! 192: /* ! 193: * Evalute "%c1c2" and store the expanded results in outbuf[]. ! 194: * Then copy outbuf[] into dest[] and return isp pointing ! 195: * to the next character of the formatted instruction string. ! 196: * When doing string manipulations, make sure that obp ! 197: * is pointing at '\0' before breaking from switch statement! ! 198: */ ! 199: char * ! 200: format(isp, dest) char *isp, *dest; ! 201: { ! 202: unsigned char c1, c2; /* 1st & 2nd char after '%' */ ! 203: ADDR_T val; ! 204: char **cpp; ! 205: char *s1; /* temporary string pointer */ ! 206: ! 207: c1 = *++isp; ! 208: c2 = *++isp; ! 209: obp = outbuf; ! 210: *obp = '\0'; ! 211: ! 212: switch (c1) { ! 213: ! 214: case 'A': ! 215: c2 = adj_op_size(c2); ! 216: val = get_value(c2, UNSIGNED, ABSOLUTE); ! 217: out_disp('a', UNSIGNED, val); ! 218: break; ! 219: ! 220: case 'C': ! 221: cpp = ctrlReg; ! 222: outreg: ! 223: get_modRM(); ! 224: output(cpp[mReg]); ! 225: break; ! 226: ! 227: case 'D': ! 228: cpp = dbgReg; ! 229: goto outreg; ! 230: break; ! 231: ! 232: case 'E': ! 233: case 'M': ! 234: case 'R': ! 235: if (ad_size() == 16) ! 236: out_modRM16(c2); ! 237: else ! 238: out_modRM32(c2); ! 239: break; ! 240: ! 241: case 'G': ! 242: cpp = &genReg[genRegIndex(c2)][0]; ! 243: goto outreg; ! 244: break; ! 245: ! 246: case 'H': ! 247: case 'I': ! 248: *obp++ = '$'; ! 249: c2 = adj_op_size(c2); ! 250: val = get_value(c2, SIGNED, ABSOLUTE); ! 251: if (c1 == 'I') { ! 252: switch (get_nbytes(c2)) { ! 253: case 1: val &= 0xFF; break; ! 254: case 2: val &= 0xFFFF; break; ! 255: } ! 256: } ! 257: out_disp('x', SIGNED, val); ! 258: break; ! 259: ! 260: case 'J': ! 261: case 'K': ! 262: out_segpre(); ! 263: c2 = adj_op_size(c2); ! 264: val = get_value(c2, SIGNED, PCREL); ! 265: seg_prefix = CS_PRE; /* CS-relative disp */ ! 266: out_disp((c1=='J') ? 'a': 's', SIGNED, val); ! 267: break; ! 268: ! 269: /* case 'M': see case 'E' */ ! 270: ! 271: case 'O': ! 272: out_segpre(); ! 273: c2 = ad_size() == 16 ? 'w' : 'd'; ! 274: val = get_value(c2, SIGNED, ABSOLUTE); ! 275: out_disp('s', SIGNED, val); ! 276: break; ! 277: /* case 'R': see case 'E' */ ! 278: ! 279: case 'S': ! 280: cpp = segReg; ! 281: goto outreg; ! 282: ! 283: case 'T': ! 284: cpp = tstReg; ! 285: goto outreg; ! 286: break; ! 287: ! 288: case 'X': ! 289: #if 0 ! 290: sprintf(obp, (ad_size()==16) ? "ds:(%%si)" : "ds:(%%esi)"); ! 291: obp = strchr(obp, '\0'); ! 292: #endif ! 293: break; ! 294: ! 295: case 'Y': ! 296: #if 0 ! 297: sprintf(obp, (ad_size()==16) ? "es:(%%di)" : "es:(%%edi)"); ! 298: obp = strchr(obp, '\0'); ! 299: #endif ! 300: break; ! 301: ! 302: case 'Z': ! 303: c2 = adj_op_size(c2); ! 304: switch(c2) { ! 305: case 'b': *obp++ = 'b'; break; ! 306: case 'd': *obp++ = 'l'; break; ! 307: case 'w': *obp++ = 'w'; break; ! 308: case 'z': *obp++ = (op_size()==16 ? 'w': 'l'); break; ! 309: } ! 310: *obp = '\0'; ! 311: break; ! 312: ! 313: case 'e': ! 314: *obp++ = '%'; ! 315: if (op_size()!=16) ! 316: *obp++ = 'e'; ! 317: *obp++ = c2; ! 318: *obp = '\0'; ! 319: break; ! 320: ! 321: case 'f': ! 322: /* Handle NDP opcodes. */ ! 323: get_modRM(); ! 324: *obp++ = 'f'; /* leading 'f' implicit in opcode tables */ ! 325: if (m==3) { ! 326: register NDPMTAB *mtp; ! 327: register int val; ! 328: ! 329: /* NDP_op_3 gives opcodes with NDP register args. */ ! 330: if ((s1 = NDP_op_3[c2-'0'][mReg]) != NULL) { ! 331: /* Leading 1, 2 or 3 indicates operand type. */ ! 332: if ((c1 = *s1)=='1' || c1=='2' || c1=='3') ! 333: s1++; ! 334: else ! 335: c1 = 0; ! 336: output(s1); ! 337: if (!c1) ! 338: break; ! 339: *obp++ = '\t'; ! 340: /* Output the NDP operand[s]. */ ! 341: switch(c1) { ! 342: case '1': ! 343: output(NDPReg[mRM]); ! 344: break; ! 345: case '2': ! 346: output(NDPReg[0]); ! 347: *obp++ = ','; ! 348: *obp++ = ' '; ! 349: output(NDPReg[mRM]); ! 350: break; ! 351: case '3': ! 352: output(NDPReg[mRM]); ! 353: *obp++ = ','; ! 354: *obp++ = ' '; ! 355: output(NDPReg[0]); ! 356: break; ! 357: } ! 358: break; ! 359: } ! 360: /* Look for opcode in NDP_misc_op[]. */ ! 361: val = (c2-'0'+0xD8)*0x100 + ibp[0]; ! 362: for (mtp = NDP_misc_op; mtp->ndpm_val != 0; ++mtp) { ! 363: if (mtp->ndpm_val >= val) ! 364: break; ! 365: } ! 366: if (mtp->ndpm_val == val) { ! 367: output(mtp->ndpm_op); ! 368: break; ! 369: } ! 370: } else if ((s1 = NDP_op[c2-'0'][mReg]) != NULL) { ! 371: /* NDP opcode with memory operand from mod r/m byte. */ ! 372: output(s1); ! 373: *obp++ = '\t'; ! 374: if (ad_size() == 16) ! 375: out_modRM16(c2); ! 376: else ! 377: out_modRM32(c2); ! 378: break; ! 379: } ! 380: printr("Invalid NDP instruction %02x %02x", ! 381: c2-'0'+0xD8, ibp[0]); ! 382: break; ! 383: ! 384: case 'g': /* just inserting the group string into isp */ ! 385: get_modRM(); ! 386: if (grp_map[c2-'0'][mReg] == NULL) { ! 387: sprintf(obp, "\nInvalid instruction byte = %02x (grp_map[%d][%d])\n", ! 388: ibp[0], c2-'0', mReg); ! 389: return strchr(obp, '\0'); ! 390: } ! 391: { ! 392: char buf[MAX_INST_LEN]; ! 393: ! 394: s1 = isp+1; /* save current pointer */ ! 395: strcpy(buf, s1); /* save rest of fmt */ ! 396: strcpy(s1, grp_map[c2-'0'][mReg]); ! 397: s1 = strchr(s1, '\0'); /* copy group string */ ! 398: strcpy(s1, buf); /* add remainder */ ! 399: *obp = '\0'; ! 400: } ! 401: break; ! 402: ! 403: case 'r': ! 404: if (get_code(1) == 0) ! 405: return NULL; ! 406: break; ! 407: ! 408: default: ! 409: *obp++ = c1; ! 410: *obp++ = c2; ! 411: *obp = '\0'; ! 412: } ! 413: strcpy(dest, outbuf); ! 414: return isp; ! 415: } ! 416: ! 417: /* ! 418: * Return the appropriate first index into genreg[][]: ! 419: * 0 byte ! 420: * 1 word ! 421: * 2 dword ! 422: */ ! 423: int ! 424: genRegIndex(c2) int c2; ! 425: { ! 426: switch(c2) { ! 427: case 'a': return (op_size() == 16) ? 1 : 2; ! 428: case 'b': return 0; ! 429: case 'd': return 2; ! 430: case 'v': return (op_size() == 16) ? 1 : 2; ! 431: case 'w': return 1; ! 432: } ! 433: return printr("Invalid c2 = %c; a 1 byte reg is shown by default", c2); ! 434: } ! 435: ! 436: #if 0 /* covered by macro in i386db.h */ ! 437: /* ! 438: * Read nbytes of code to ibp. ! 439: */ ! 440: int ! 441: get_code(nbytes) int nbytes; ! 442: { ! 443: return getb(segn, ibp, nbytes); ! 444: } ! 445: #endif ! 446: ! 447: /* ! 448: * Read and decode a mod r/m byte. ! 449: */ ! 450: #define mod(x) (((x)>>6)&3) ! 451: #define modR(x) (((x)>>3)&7) ! 452: #define modRM(x) ((x)&7) ! 453: int ! 454: get_modRM() ! 455: { ! 456: if (!modRM_flag) { ! 457: if (get_code(1) == 0) ! 458: return 0; ! 459: m = mod(ibp[0]); ! 460: mRM = modRM(ibp[0]); ! 461: mReg = modR(ibp[0]); ! 462: modRM_flag = 1; ! 463: } ! 464: return 1; ! 465: } ! 466: ! 467: /* ! 468: * Convert a size character to an actual size in bytes. ! 469: */ ! 470: int ! 471: get_nbytes(mysize) int mysize; ! 472: { ! 473: switch(mysize) { ! 474: case 'b': return 1; ! 475: case 'd': return 4; ! 476: case 'f': return 4; ! 477: case 'l': return 6; ! 478: case 'w': return 2; ! 479: case '\0': return 0; ! 480: } ! 481: printr("Invalid nbytes=%c; 1 byte size is chosen by default", mysize); ! 482: return 1; ! 483: } ! 484: ! 485: /* ! 486: * Read and decode a SIB byte. ! 487: */ ! 488: #define sibss(x) (((x)>>6)&3) ! 489: #define sibx(x) (((x)>>3)&7) ! 490: #define sibb(x) ((x)&7) ! 491: int ! 492: get_sib() ! 493: { ! 494: if (!sib_flag) { ! 495: if ((get_code(1)) == 0) ! 496: return 0; ! 497: sss = sibss(ibp[0]); ! 498: sx = sibx(ibp[0]); ! 499: sb = sibb(ibp[0]); ! 500: sib_flag = 1; ! 501: } ! 502: return 1; ! 503: } ! 504: ! 505: /* ! 506: * Get displacement or immediate data and sign- or zero-extend it. ! 507: * Return the number of bytes read, or 0 on failure. ! 508: */ ! 509: int ! 510: getValData(is_signed, mysize) int is_signed, mysize; ! 511: { ! 512: register int nbytes, i; ! 513: ! 514: if ((nbytes = get_nbytes(mysize)) == 0) ! 515: return 0; ! 516: else if ((get_code(nbytes)) == 0) ! 517: return printr("Cannot read displacement or immediate data"); ! 518: ! 519: for (i = nbytes; i < MAX_DISP_SIZE; i++) ! 520: ibp[i] = (is_signed && (ibp[i-1] & 0x80)) ? 0xFF : 0; ! 521: return nbytes; ! 522: } ! 523: ! 524: /* ! 525: * Get immediate or displacement value. ! 526: */ ! 527: ADDR_T ! 528: get_value(mysize, is_signed, flag) int mysize, is_signed, flag; ! 529: { ! 530: register ADDR_T base; ! 531: int nbytes; ! 532: ! 533: if ((nbytes = getValData(is_signed, mysize)) == 0) ! 534: return (ADDR_T)0; ! 535: base = (flag) ? add : (ADDR_T)0; ! 536: if (mysize == 'f' || mysize == 'l') { ! 537: /* Output 32-bit or 48-bit pointer segment. */ ! 538: sprintf(obp, "0x%02x%02x:", ibp[nbytes-1], ibp[nbytes-2]); ! 539: obp = strchr(obp, '\0'); ! 540: nbytes -= 2; ! 541: } ! 542: switch (nbytes) { ! 543: case 1: ! 544: delta = (is_signed) ? *(char *)ibp : *(unsigned char *)ibp; ! 545: break; ! 546: case 2: ! 547: delta = (is_signed) ? *(short *)ibp : *(unsigned short *)ibp; ! 548: break; ! 549: case 4: ! 550: delta = *(long *)ibp; ! 551: break; ! 552: } ! 553: return base + (ADDR_T)delta; ! 554: } ! 555: ! 556: /* ! 557: * Return the current operand size. ! 558: * With no operand prefix flag, the address size is aop_size (16 or 32); ! 559: * with address prefix flag, it is the other (32 or 16). ! 560: */ ! 561: int ! 562: op_size() ! 563: { ! 564: return (op_pre_flag) ? 48 - aop_size : aop_size; ! 565: } ! 566: ! 567: /* ! 568: * Output an address. ! 569: */ ! 570: void ! 571: out_addr(v) ADDR_T v; ! 572: { ! 573: sprintf(obp, "0x%lX", v); ! 574: obp = strchr(obp, '\0'); ! 575: } ! 576: ! 577: /* ! 578: * Output a displacement. ! 579: */ ! 580: void ! 581: out_disp(fmt, is_signed, val) int fmt; int is_signed; ADDR_T val; ! 582: { ! 583: dbprintf(("out_disp(%c, %d, %lX):\n", fmt, is_signed, val)); ! 584: if (is_signed && delta < 0) ! 585: delta = -delta; ! 586: switch(fmt) { ! 587: ! 588: case 'd': /* print decimal */ ! 589: if (val == (ADDR_T)0) ! 590: break; /* huh? */ ! 591: sprintf(obp, "%ld", val); ! 592: break; ! 593: ! 594: case 'x': /* print hex */ ! 595: sprintf(obp, (delta > TOLHEX) ? "0x%lX" : "%ld", val); ! 596: break; ! 597: ! 598: case 'a': /* print address */ ! 599: if (delta <= TOLSYM) { ! 600: out_addr(val); /* print address in hex */ ! 601: break; ! 602: } ! 603: /* else fall through to print symbolic address... */ ! 604: ! 605: case 's': /* print symbol if possible; otherwise print address */ ! 606: cvt_addr(obp, (seg_prefix == CS_PRE) ? ISEG : DSEG, val); ! 607: break; ! 608: ! 609: default: ! 610: printr("Invalid fmt=%c in out_disp", fmt); ! 611: } ! 612: obp = strchr(obp, '\0'); ! 613: } ! 614: ! 615: /* ! 616: * Output mod r/m info. ! 617: */ ! 618: void ! 619: out_modRM(dispsize, fmt, addrsize, is_signed) int dispsize, fmt, addrsize, is_signed; ! 620: { ! 621: unsigned long val; ! 622: ! 623: out_segpre(); ! 624: val = get_value(dispsize, is_signed, ABSOLUTE); ! 625: out_disp(fmt, is_signed, val); ! 626: output(modRMtab[ADDRINDEX(addrsize)][mRM]); ! 627: } ! 628: ! 629: /* ! 630: * Output 1b-bit mod r/m info. ! 631: */ ! 632: void ! 633: out_modRM16(c2) int c2; ! 634: { ! 635: unsigned long val; ! 636: ! 637: get_modRM(); ! 638: c2 = adj_op_size(c2); ! 639: ! 640: switch(m) { ! 641: case 0: ! 642: out_segpre(); ! 643: if (mRM==6) { ! 644: val = get_value('w', SIGNED, ABSOLUTE); ! 645: out_disp('s', SIGNED, val); ! 646: break; ! 647: } ! 648: output(modRMtab[ADDRINDEX(16)][mRM]); ! 649: break; ! 650: case 1: ! 651: case 2: ! 652: out_modRM((m==1) ? 'b' : 'w', 'd', 16, SIGNED); ! 653: break; ! 654: case 3: ! 655: output(genReg[genRegIndex(c2)][mRM]); ! 656: break; ! 657: } ! 658: } ! 659: ! 660: /* ! 661: * Output 32-bit mod r/m info. ! 662: */ ! 663: void ! 664: out_modRM32(c2) int c2; ! 665: { ! 666: unsigned long val; ! 667: char c; ! 668: ! 669: get_modRM(); ! 670: c2 = adj_op_size(c2); ! 671: ! 672: switch(m) { ! 673: case 0: ! 674: if (mRM==4) { ! 675: out_sib('\0', m); ! 676: break; ! 677: } ! 678: out_segpre(); ! 679: if (mRM==5) { ! 680: val = get_value('d', SIGNED, ABSOLUTE); ! 681: out_disp('s', SIGNED, val); ! 682: break; ! 683: } ! 684: output(modRMtab[ADDRINDEX(32)][mRM]); ! 685: break; ! 686: case 1: ! 687: case 2: ! 688: c = (m==1) ? 'b' : 'd'; ! 689: if (mRM==4) ! 690: out_sib(c, m); ! 691: else ! 692: out_modRM(c, 'd', 32, 1); ! 693: break; ! 694: case 3: ! 695: output(genReg[genRegIndex(c2)][mRM]); ! 696: break; ! 697: } ! 698: } ! 699: ! 700: /* ! 701: * Copy src to output buffer outbuf, ! 702: * updating the output buffer pointer accordingly. ! 703: */ ! 704: void ! 705: output(src) char *src; ! 706: { ! 707: strcpy(obp, src); ! 708: obp = strchr(obp, '\0'); ! 709: } ! 710: ! 711: /* ! 712: * Write a segment escape prefix. ! 713: */ ! 714: void ! 715: out_segpre() ! 716: { ! 717: if (seg_prefix != 0) ! 718: output(op_map_1[seg_prefix]); ! 719: } ! 720: ! 721: /* ! 722: * Output a SIB indirect address. ! 723: */ ! 724: void ! 725: out_sib(dispsize, m) int dispsize, m; ! 726: { ! 727: unsigned long val; ! 728: ! 729: get_sib(); ! 730: switch(m) { ! 731: case 0: ! 732: out_segpre(); ! 733: if (sb == EBP_SIB) { ! 734: val = get_value('d', SIGNED, ABSOLUTE); ! 735: out_disp('d', SIGNED, val); ! 736: } else ! 737: output(modRMtab[ADDRINDEX(32)][sb]); ! 738: break; ! 739: case 1: ! 740: case 2: ! 741: out_segpre(); ! 742: val = get_value(dispsize, SIGNED, ABSOLUTE); ! 743: out_disp('d', SIGNED, val); ! 744: output(modRMtab[ADDRINDEX(32)][sb]); ! 745: break; ! 746: } ! 747: if (sibtab[sss][sx] != NULL) ! 748: output(sibtab[sss][sx]); ! 749: } ! 750: ! 751: /* end of db/i386/i386db2.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.