Annotation of ADD_ver_10/Source Code/Source Files/Desensambladorx86IA16.c, revision 1.1
1.1 ! rico 1: /******************************************************************************/
! 2: /* MÓDULO: DesensambladorX86IA16.c */
! 3: /* */
! 4: /* Este módulo determina el nemónico, los operandos y la longitud del */
! 5: /* formato a partir de una cadena de bytes del código binario del ejecutable. */
! 6: /* - El nemónico depende del código de operación y en casos excepcionales */
! 7: /* del 2º byte. */
! 8: /* - Los operandos dependen del modo de direccionamiento (a través del código */
! 9: /* de operación) y de los bytes del formato. */
! 10: /******************************************************************************/
! 11: /* Fecha: 29 de junio de 2005 */
! 12: /******************************************************************************/
! 13:
! 14:
! 15: #include <stdio.h>
! 16: #include <string.h>
! 17:
! 18: #include "defines.h"
! 19: #include "tipos.h"
! 20:
! 21: /* tipos de formatos y modos de direccionamiento */
! 22: #define SINOPERANDOS 0 /* formato de 1 byte sin operandos */
! 23: #define PREFIJOS 1 /* formato de 1 byte sin operandos que es un prefijo */
! 24: #define REGPALABRA 2 /* formato de 1 byte: 1 operando registro palabra */
! 25: #define REGSEGMENTO 3 /* formato de 1 byte: 1 operando reg. segmento */
! 26: #define REGMEM 4 /* hasta 4 bytes; 1 operando reg/mem */
! 27: #define INMED8 5 /* formato de 2 bytes: 1 operando inm8 */
! 28: #define INMED16 6 /* formato de 3 bytes: 1 operando inm16 */
! 29: #define SALTO8 7 /* formato de 2 bytes: 1 operando: relativo IP 8bits */
! 30: #define SALTO16 8 /* formato de 3 bytes: 1 operando: relativo IP 16bits */
! 31: #define BASEOFFSET 9 /* formato de 5 bytes: 1 op: BASE:OFFSET (CALL y JMP) */
! 32: #define REGULAR 10 /* hasta 4 bytes; 2 operandos reg/mem -> reg/mem */
! 33: #define INMEDTOAX 11 /* hasta 3 bytes; 2 operandos inm -> acc */
! 34: #define INMEDTOREGMEM 12 /* hasta 6 bytes; 2 operandos inm -> reg/mem */
! 35: #define MOVMEMAX 13 /* formato de 3 bytes; 2 op LOAD/STORE mem-AX */
! 36: #define MOVSEGMTO 14 /* hasta 4 bytes; 2 op MOV entre reg/mem y reg. seg. */
! 37: #define MOVINMEDTOREG 15 /* hasta 3 bytes; 2 operandos MOV inm -> registro */
! 38: #define DESPLAZAMIENTO 16 /* hasta 4 bytes; 2 op reg/mem y contador (1 o CL) */
! 39: #define ENTRADA_SALIDA 17 /* hasta 2 bytes: 2 operandos: acc y DX o inm8 */
! 40:
! 41:
! 42: void OperandoRegistro(char w, char codigo, char *registro)
! 43: {
! 44: char *registrosL[] = {"AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"};
! 45: char *registrosX[] = {"AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"};
! 46:
! 47: switch(w)
! 48: {
! 49: case 0:
! 50: sprintf(registro, registrosL[codigo]);
! 51: break;
! 52:
! 53: case 1:
! 54: sprintf(registro, registrosX[codigo]);
! 55: break;
! 56: }
! 57: }
! 58:
! 59: void OperandoRegSeg(char codigo, char *registro)
! 60: {
! 61: char *regSEG[] = {"ES", "CS", "SS", "DS"};
! 62:
! 63: sprintf(registro, regSEG[codigo]);
! 64: }
! 65:
! 66: void OperandoMemoria(char codigo, char *memoria)
! 67: {
! 68: /* char *direfectiva[] = {"[BX][SI]", "[BX][DI]", "[BP][SI]", "[BP][DI]",
! 69: "[SI]", "[DI]", "[BP]", "[BX]"}; */
! 70: /* cambio los identificadores de las ubicaciones de memoria para simplificar el análisis */
! 71: char *direfectiva[] = {"[BXSI]", "[BXDI]", "[BPSI]", "[BPDI]",
! 72: "[SI]", "[DI]", "[BP]", "[BX]"};
! 73:
! 74: sprintf(memoria, direfectiva[codigo]);
! 75: }
! 76:
! 77: void OperandoRM(char w, char mod, char r_m, unsigned char byteL, unsigned char byteH, char *registro_memoria, char *l)
! 78: {
! 79: char desplazamiento[5];
! 80:
! 81: switch(mod)
! 82: {
! 83: case 3: /* el operando es un registro */
! 84: OperandoRegistro(w, r_m, registro_memoria); *l=0;
! 85: break;
! 86:
! 87: case 0:
! 88: /* el operando es memoria sin desplazamiento */
! 89: if(r_m!=6) {OperandoMemoria(r_m, registro_memoria); *l=0;}
! 90: /* el operando es una dirección absoluta de memoria */
! 91: else {sprintf(registro_memoria, "[%02X%02X]", byteH, byteL); *l=2;}
! 92: break;
! 93:
! 94: case 1: /* el operando es memoria con desplazamiento 8 */
! 95: OperandoMemoria(r_m, registro_memoria);
! 96: sprintf(desplazamiento, "%02X", byteL); *l=1;
! 97: strcat(registro_memoria, desplazamiento);
! 98: break;
! 99:
! 100: case 2: /* el operando es memoria con desplazamiento 16 */
! 101: OperandoMemoria(r_m, registro_memoria);
! 102: sprintf(desplazamiento, "%02X%02X", byteH, byteL); *l=2;
! 103: strcat(registro_memoria, desplazamiento);
! 104: break;
! 105: }
! 106: }
! 107:
! 108:
! 109: void DecodificarInstruccion086(unsigned char formato[6], struct desensamblado *instruccion)
! 110: {
! 111: char *saltos_cc[] = {"JO", "JNO", "JB/JNAE", "JNB/JAE", "JE/JZ",
! 112: "JNE/JNZ", "JBE/JNA", "JNBE/JA", "JS", "JNS",
! 113: "JP/JPE", "JNP/JPO", "JL/JNGE", "JNL/JGE",
! 114: "JLE/JNG", "JNLE/JG"};
! 115: char *tablainmediatos[] = {"ADD", "OR", "ADC", "SBB", "AND",
! 116: "SUB", "XOR", "CMP"};
! 117: char *tabladesplazamientos[] = {"ROL", "ROR", "RCL", "RCR",
! 118: "SHL/SAL", "SHR", "(086)?", "SAR"};
! 119: char *tablagrupo1[] = {"TEST", "(086)?", "NOT", "NEG", "MUL",
! 120: "IMUL", "DIV", "IDIV"};
! 121: char *tablagrupo2[] = {"INC", "DEC", "CALL", "CALL", "JMP",
! 122: "JMP", "PUSH", "(086)?"};
! 123:
! 124: char nemonico[20] = {""};
! 125: char op1[20] = {""};
! 126: char op2[20] = {""};
! 127: char modo = SINOPERANDOS;
! 128: char longitud = 0;
! 129: char bytesadicionales = 0;
! 130:
! 131:
! 132: union{
! 133: struct{
! 134: unsigned short int valor;
! 135: }byte;
! 136: struct{
! 137: unsigned int L:4;
! 138: unsigned int H:4;
! 139: }nibble;
! 140: struct{
! 141: unsigned int w:1;
! 142: unsigned int d:1;
! 143: unsigned int opcode:6;
! 144: }campo;
! 145: }byte1;
! 146:
! 147: union{
! 148: struct{
! 149: unsigned short int valor;
! 150: }byte;
! 151: struct{
! 152: unsigned int r_m:3;
! 153: unsigned int reg:3;
! 154: unsigned int mod:2;
! 155: }campo;
! 156: }byte2;
! 157:
! 158: byte1.byte.valor = formato[0]; /* primer byte del formato */
! 159: byte2.byte.valor = formato[1]; /* segundo byte del formato */
! 160:
! 161: longitud = 1; /* al menos leo el primer byte del formato */
! 162:
! 163: switch(byte1.nibble.H)
! 164: {
! 165: case 0x0:
! 166: switch(byte1.nibble.L)
! 167: {
! 168: case 0x0:
! 169: case 0x1:
! 170: case 0x2:
! 171: case 0x3:
! 172: sprintf(nemonico, "ADD"); modo = REGULAR; break;
! 173:
! 174: case 0x4:
! 175: case 0x5:
! 176: sprintf(nemonico, "ADD"); modo = INMEDTOAX; break;
! 177:
! 178: case 0x6:
! 179: sprintf(nemonico, "PUSH"); modo = REGSEGMENTO; break;
! 180:
! 181: case 0x7:
! 182: sprintf(nemonico, "POP"); modo = REGSEGMENTO; break;
! 183:
! 184: case 0x8:
! 185: case 0x9:
! 186: case 0xA:
! 187: case 0xB:
! 188: sprintf(nemonico, "OR"); modo = REGULAR; break;
! 189:
! 190: case 0xC:
! 191: case 0xD:
! 192: sprintf(nemonico, "OR"); modo = INMEDTOAX; break;
! 193:
! 194: case 0xE:
! 195: sprintf(nemonico, "PUSH"); modo = REGSEGMENTO; break;
! 196:
! 197: case 0xF: /* esta instrucción no existe realmente */
! 198: sprintf(nemonico, "POP"); modo = REGSEGMENTO; break;
! 199: }
! 200: break;
! 201:
! 202: case 0x1:
! 203: switch(byte1.nibble.L)
! 204: {
! 205: case 0x0:
! 206: case 0x1:
! 207: case 0x2:
! 208: case 0x3:
! 209: sprintf(nemonico, "ADC"); modo = REGULAR; break;
! 210:
! 211: case 0x4:
! 212: case 0x5:
! 213: sprintf(nemonico, "ADC"); modo = INMEDTOAX; break;
! 214:
! 215: case 0x6:
! 216: sprintf(nemonico, "PUSH"); modo = REGPALABRA; break;
! 217:
! 218: case 0x7:
! 219: sprintf(nemonico, "POP"); modo = REGPALABRA; break;
! 220:
! 221: case 0x8:
! 222: case 0x9:
! 223: case 0xA:
! 224: case 0xB:
! 225: sprintf(nemonico, "SBB"); modo = REGULAR; break;
! 226:
! 227: case 0xC:
! 228: case 0xD:
! 229: sprintf(nemonico, "SBB"); modo = INMEDTOAX; break;
! 230:
! 231: case 0xE:
! 232: sprintf(nemonico, "PUSH"); modo = REGPALABRA; break;
! 233:
! 234: case 0xF:
! 235: sprintf(nemonico, "POP"); modo = REGPALABRA; break;
! 236: }
! 237: break;
! 238:
! 239: case 0x2:
! 240: switch(byte1.nibble.L)
! 241: {
! 242: case 0x0:
! 243: case 0x1:
! 244: case 0x2:
! 245: case 0x3:
! 246: sprintf(nemonico, "AND"); modo = REGULAR; break;
! 247:
! 248: case 0x4:
! 249: case 0x5:
! 250: sprintf(nemonico, "AND"); modo = INMEDTOAX; break;
! 251:
! 252: case 0x6:
! 253: sprintf(nemonico, "ES"); modo = PREFIJOS; break;
! 254:
! 255: case 0x7:
! 256: sprintf(nemonico, "DAA"); modo = SINOPERANDOS; break;
! 257:
! 258: case 0x8:
! 259: case 0x9:
! 260: case 0xA:
! 261: case 0xB:
! 262: sprintf(nemonico, "SUB"); modo = REGULAR; break;
! 263:
! 264: case 0xC:
! 265: case 0xD:
! 266: sprintf(nemonico, "SUB"); modo = INMEDTOAX; break;
! 267:
! 268: case 0xE:
! 269: sprintf(nemonico, "CS"); modo = PREFIJOS; break;
! 270:
! 271: case 0xF:
! 272: sprintf(nemonico, "DAS"); modo = SINOPERANDOS; break;
! 273: }
! 274: break;
! 275:
! 276: case 0x3:
! 277: switch(byte1.nibble.L)
! 278: {
! 279: case 0x0:
! 280: case 0x1:
! 281: case 0x2:
! 282: case 0x3:
! 283: sprintf(nemonico, "XOR"); modo = REGULAR; break;
! 284:
! 285: case 0x4:
! 286: case 0x5:
! 287: sprintf(nemonico, "XOR"); modo = INMEDTOAX; break;
! 288:
! 289: case 0x6:
! 290: sprintf(nemonico, "SS"); modo = PREFIJOS; break;
! 291:
! 292: case 0x7:
! 293: sprintf(nemonico, "AAA"); modo = SINOPERANDOS; break;
! 294:
! 295: case 0x8:
! 296: case 0x9:
! 297: case 0xA:
! 298: case 0xB:
! 299: sprintf(nemonico, "CMP"); modo = REGULAR; break;
! 300:
! 301: case 0xC:
! 302: case 0xD:
! 303: sprintf(nemonico, "CMP"); modo = INMEDTOAX; break;
! 304:
! 305: case 0xE:
! 306: sprintf(nemonico, "DS"); modo = PREFIJOS; break;
! 307:
! 308: case 0xF:
! 309: sprintf(nemonico, "AAS"); modo = SINOPERANDOS; break;
! 310: }
! 311: break;
! 312:
! 313: case 0x4:
! 314: if(byte1.nibble.L < 8)
! 315: sprintf(nemonico, "INC");
! 316: else
! 317: sprintf(nemonico, "DEC");
! 318: modo = REGPALABRA;
! 319: break;
! 320:
! 321:
! 322: case 0x5:
! 323: if(byte1.nibble.L < 8) sprintf(nemonico, "PUSH");
! 324: else sprintf(nemonico, "POP");
! 325: modo = REGPALABRA;
! 326: break;
! 327:
! 328: case 0x6:
! 329: sprintf(nemonico, "(086)?");
! 330: modo = SINOPERANDOS;
! 331: break;
! 332:
! 333: case 0x7:
! 334: sprintf(nemonico, saltos_cc[byte1.nibble.L]);
! 335: modo = SALTO8;
! 336: break;
! 337:
! 338: case 0x8:
! 339: switch(byte1.nibble.L)
! 340: {
! 341: case 0x0: /* requiere 2º byte */
! 342: case 0x1:
! 343: case 0x2:
! 344: case 0x3: /* binario 1000 00 XX; grupo inmediatos */
! 345: /* aunque necesito el 2º byte del formato no lo cuanto ahora */
! 346: /* lo contaré después cuando obtenga el operando del 2º byte */
! 347: sprintf(nemonico, tablainmediatos[byte2.campo.reg]);
! 348: modo = INMEDTOREGMEM;
! 349: break;
! 350:
! 351: case 0x4:
! 352: case 0x5:
! 353: sprintf(nemonico, "TEST"); modo = REGULAR; break;
! 354:
! 355: case 0x6:
! 356: case 0x7:
! 357: sprintf(nemonico, "XCHG"); modo = REGULAR; break;
! 358:
! 359: case 0x8:
! 360: case 0x9:
! 361: case 0xA:
! 362: case 0xB:
! 363: sprintf(nemonico, "MOV"); modo = REGULAR; break;
! 364:
! 365: case 0xC:
! 366: case 0xE:
! 367: sprintf(nemonico, "MOV"); modo = MOVSEGMTO; break;
! 368:
! 369: case 0xD:
! 370: sprintf(nemonico, "LEA");
! 371: modo = REGULAR; /* CON */ byte1.campo.d = 1; byte1.campo.w = 1;
! 372: break;
! 373:
! 374: case 0xF:
! 375: sprintf(nemonico, "POP"); modo = REGMEM; break;
! 376: }
! 377: break;
! 378:
! 379: case 0x9:
! 380: switch(byte1.nibble.L)
! 381: {
! 382: case 0x0:
! 383: sprintf(nemonico, "NOP"); modo = SINOPERANDOS; break;
! 384:
! 385: case 0x8:
! 386: sprintf(nemonico, "CBW"); modo = SINOPERANDOS; break;
! 387:
! 388: case 0x9:
! 389: sprintf(nemonico, "CWD"); modo = SINOPERANDOS; break;
! 390:
! 391: case 0xA:
! 392: sprintf(nemonico, "CALL"); modo = BASEOFFSET; break;
! 393:
! 394: case 0xB:
! 395: sprintf(nemonico, "WAIT"); modo = SINOPERANDOS; break;
! 396:
! 397: case 0xC:
! 398: sprintf(nemonico, "PUSHF"); modo = SINOPERANDOS; break;
! 399:
! 400: case 0xD:
! 401: sprintf(nemonico, "POPF"); modo = SINOPERANDOS; break;
! 402:
! 403: case 0xE:
! 404: sprintf(nemonico, "SAHF"); modo = SINOPERANDOS; break;
! 405:
! 406: case 0xF:
! 407: sprintf(nemonico, "LAHF"); modo = SINOPERANDOS; break;
! 408:
! 409: default:
! 410: sprintf(nemonico, "XCHG"); modo = REGPALABRA;
! 411: }
! 412: break;
! 413:
! 414: case 0xA:
! 415: switch(byte1.nibble.L)
! 416: {
! 417: case 0x0:
! 418: case 0x1:
! 419: case 0x2:
! 420: case 0x3:
! 421: sprintf(nemonico, "MOV"); modo = MOVMEMAX; break;
! 422:
! 423: case 0x4:
! 424: case 0x5:
! 425: sprintf(nemonico, "MOVS"); modo = SINOPERANDOS; break;
! 426:
! 427: case 0x6:
! 428: case 0x7:
! 429: sprintf(nemonico, "CMPS"); modo = SINOPERANDOS; break;
! 430:
! 431: case 0x8:
! 432: case 0x9:
! 433: sprintf(nemonico, "TEST"); modo = INMEDTOAX; break;
! 434:
! 435: case 0xA:
! 436: case 0xB:
! 437: sprintf(nemonico, "STOS"); modo = SINOPERANDOS; break;
! 438:
! 439: case 0xC:
! 440: case 0xD:
! 441: sprintf(nemonico, "LODS"); modo = SINOPERANDOS; break;
! 442:
! 443: case 0xE:
! 444: case 0xF:
! 445: sprintf(nemonico, "SCAS"); modo = SINOPERANDOS; break;
! 446: }
! 447: break;
! 448:
! 449: case 0xB:
! 450: sprintf(nemonico, "MOV"); modo = MOVINMEDTOREG; break;
! 451:
! 452: case 0xC:
! 453: switch(byte1.nibble.L)
! 454: {
! 455: case 0x0:
! 456: case 0x1:
! 457: case 0x8:
! 458: case 0x9:
! 459: sprintf(nemonico, "(086)?"); modo = SINOPERANDOS; break;
! 460:
! 461: case 0x2:
! 462: sprintf(nemonico, "RET"); modo = INMED16; break;
! 463:
! 464: case 0x3:
! 465: sprintf(nemonico, "RET"); modo = SINOPERANDOS; break;
! 466:
! 467: case 0xA:
! 468: sprintf(nemonico, "RETF"); modo = INMED16; break;
! 469:
! 470: case 0xB:
! 471: sprintf(nemonico, "RETF"); modo = SINOPERANDOS; break;
! 472: break;
! 473:
! 474: case 0x4:
! 475: sprintf(nemonico, "LES");
! 476: modo = REGULAR; /* CON */ byte1.campo.d = 1; byte1.campo.w = 1;
! 477: break;
! 478:
! 479: case 0x5:
! 480: sprintf(nemonico, "LDS");
! 481: modo = REGULAR; /* CON */ byte1.campo.d = 1; byte1.campo.w = 1;
! 482: break;
! 483:
! 484: case 0x6:
! 485: case 0x7:
! 486: sprintf(nemonico, "MOV"); modo = INMEDTOREGMEM; break;
! 487:
! 488: case 0xC:
! 489: sprintf(nemonico, "INT 3"); modo = SINOPERANDOS; break;
! 490:
! 491: case 0xD:
! 492: sprintf(nemonico, "INT"); modo = INMED8; break;
! 493:
! 494: case 0xE:
! 495: sprintf(nemonico, "INTO"); modo = SINOPERANDOS; break;
! 496:
! 497: case 0xF:
! 498: sprintf(nemonico, "IRET"); modo = SINOPERANDOS; break;
! 499: }
! 500: break;
! 501:
! 502: case 0xD:
! 503: switch(byte1.nibble.L)
! 504: {
! 505: case 0x00: /* requiere 2º byte */
! 506: case 0x01:
! 507: case 0x02:
! 508: case 0x03: /* binario 1101 00 XX; grupo desplazamientos */
! 509: /* aunque necesito el 2º byte del formato lo contaré cuando lea el operando */
! 510: sprintf(nemonico, tabladesplazamientos[byte2.campo.reg]);
! 511: modo = DESPLAZAMIENTO;
! 512: break;
! 513:
! 514: case 0x04:
! 515: sprintf(nemonico, "AAM"); modo = INMED8; break;
! 516:
! 517: case 0x05:
! 518: sprintf(nemonico, "AAD"); modo = INMED8; break;
! 519:
! 520: case 0x06:
! 521: sprintf(nemonico, "(086)?"); modo = SINOPERANDOS; break;
! 522:
! 523: case 0x07:
! 524: sprintf(nemonico, "XLAT"); modo = SINOPERANDOS; break;
! 525:
! 526: default:
! 527: sprintf(nemonico, "ESC"); modo = REGMEM;
! 528: }
! 529: break;
! 530:
! 531: case 0xE:
! 532: switch(byte1.nibble.L)
! 533: {
! 534: case 0x0:
! 535: sprintf(nemonico, "LOOPNZ/LOOPNE"); modo = SALTO8; break;
! 536:
! 537: case 0x1:
! 538: sprintf(nemonico, "LOOPZ/LOOPE"); modo = SALTO8; break;
! 539:
! 540: case 0x2:
! 541: sprintf(nemonico, "LOOP"); modo = SALTO8; break;
! 542:
! 543: case 0x3:
! 544: sprintf(nemonico, "JCXZ"); modo = SALTO8; break;
! 545:
! 546: case 0x4:
! 547: case 0x5:
! 548: case 0xC:
! 549: case 0xD:
! 550: sprintf(nemonico, "IN"); modo = ENTRADA_SALIDA; break;
! 551:
! 552: case 0x6:
! 553: case 0x7:
! 554: case 0xE:
! 555: case 0xF:
! 556: sprintf(nemonico, "OUT"); modo = ENTRADA_SALIDA; break;
! 557:
! 558: case 0x8:
! 559: sprintf(nemonico, "CALL"); modo = SALTO16; break;
! 560:
! 561: case 0x9:
! 562: sprintf(nemonico, "JMP"); modo = SALTO16; break;
! 563:
! 564:
! 565: case 0xA:
! 566: sprintf(nemonico, "JMP"); modo = BASEOFFSET; break;
! 567:
! 568: case 0xB:
! 569: sprintf(nemonico, "JMP"); modo = SALTO8; break;
! 570: }
! 571: break;
! 572:
! 573: case 0xF:
! 574: switch(byte1.nibble.L)
! 575: {
! 576: case 0x0:
! 577: sprintf(nemonico, "LOCK"); modo = SINOPERANDOS; break;
! 578:
! 579: case 0x1:
! 580: sprintf(nemonico, "(086)?"); modo = SINOPERANDOS; break;
! 581:
! 582: case 0x2: /* este nemónico es equivalente a "REPZ/REPE" */
! 583: sprintf(nemonico, "REP"); modo = PREFIJOS; break;
! 584:
! 585: case 0x3:
! 586: sprintf(nemonico, "REPNZ/REPNE"); modo = PREFIJOS; break;
! 587:
! 588: case 0x4:
! 589: sprintf(nemonico, "HLT"); modo = SINOPERANDOS; break;
! 590:
! 591: case 0x5:
! 592: sprintf(nemonico, "CMC"); modo = SINOPERANDOS; break;
! 593:
! 594: case 0x6: /* requiere 2º byte */
! 595: case 0x7: /* binario 1111 01 1X; grupo 1 */
! 596: /* aunque necesito el 2º byte del formato no lo cuento ahora */
! 597: /* lo contaré cuando leo el operando del 2º byte */
! 598: sprintf(nemonico, tablagrupo1[byte2.campo.reg]);
! 599: switch(byte2.campo.reg)
! 600: {
! 601: case 0: /* instrucción TEST */
! 602: modo = INMEDTOREGMEM;
! 603: break;
! 604:
! 605: case 1: /* no definida (086)? */
! 606: modo = SINOPERANDOS;
! 607: break;
! 608:
! 609: case 2: /* instrucción NOT */
! 610: case 3: /* instrucción NEG */
! 611: case 4: /* instrucción MUL */
! 612: case 5: /* instrucción IMUL */
! 613: case 6: /* instrucción DIV */
! 614: case 7: /* instrucción IDIV */
! 615: modo = REGMEM;
! 616: break;
! 617: }
! 618: break;
! 619:
! 620: case 0x8:
! 621: sprintf(nemonico, "CLC"); modo = SINOPERANDOS; break;
! 622:
! 623: case 0x9:
! 624: sprintf(nemonico, "STC"); modo = SINOPERANDOS; break;
! 625:
! 626: case 0xA:
! 627: sprintf(nemonico, "CLI"); modo = SINOPERANDOS; break;
! 628:
! 629: case 0xB:
! 630: sprintf(nemonico, "STI"); modo = SINOPERANDOS; break;
! 631:
! 632: case 0xC:
! 633: sprintf(nemonico, "CLD"); modo = SINOPERANDOS; break;
! 634:
! 635: case 0xD:
! 636: sprintf(nemonico, "STD"); modo = SINOPERANDOS; break;
! 637:
! 638: case 0xE: /* requiere 2º byte */
! 639: case 0xF: /* binario 1111 11 1X; grupo 2 */
! 640: /* aunque necesito el 2º byte del formato lo contaré cuando saque el operando */
! 641: sprintf(nemonico, tablagrupo2[byte2.campo.reg]);
! 642: switch(byte2.campo.reg)
! 643: {
! 644: case 0: /* instrucción INC */
! 645: case 1: /* instrucción DEC */
! 646: case 2:
! 647: case 3: /* instrucciones CALL */
! 648: case 4:
! 649: case 5: /* instrucciones JMP */
! 650: case 6: /* instrucción PUSH */
! 651: modo = REGMEM;
! 652: break;
! 653:
! 654: case 7:
! 655: modo = SINOPERANDOS; /* no definida (086)? */
! 656: break;
! 657: }
! 658: break;
! 659: }
! 660: break;
! 661: }
! 662:
! 663: /* ahora añado los operandos (si los hay) al nemónico */
! 664: /* quizá sea interesante dar un formato que permita distinguir con más facilidad */
! 665: /* el tipo de operando (registro, memoria, inmediato, etc.) con el fin de */
! 666: /* facilitar el análisis posterior por funciones de los operandos */
! 667: /* cuando hay un único operando siempre se considera op1 (destino en la notación INTEL) */
! 668:
! 669: switch (modo)
! 670: {
! 671: case SINOPERANDOS: /* sin operandos */
! 672: case PREFIJOS:
! 673: break;
! 674:
! 675: case REGPALABRA: /* 1 operando: registro tamaño palabra */
! 676: OperandoRegistro(1, byte1.nibble.L & 0x7, op1);
! 677: break;
! 678:
! 679: case REGSEGMENTO: /* 1 operando registro segmento */
! 680: OperandoRegSeg((byte1.campo.opcode >> 1) & 0x03, op1);
! 681: break;
! 682:
! 683: case REGMEM: /* 1 operando registro o memoria */
! 684: longitud += 1; /* necesito el 2º byte */
! 685: OperandoRM(byte1.campo.w, byte2.campo.mod, byte2.campo.r_m, formato[longitud], formato[longitud+1], op1, &bytesadicionales);
! 686: longitud += bytesadicionales; /* sumo los posibles bytes del formato utilizados */
! 687: break;
! 688:
! 689: case INMED8: /* 1 operando inmediato de 8 bits */
! 690: longitud += 1; /* necesito otro byte más */
! 691: if(!strcmp(nemonico, "INT")) sprintf(op1, "%02X", formato[longitud-1]);
! 692: /* en los casos de AAM y AAD el 2º byte es 0x0A y sólo hay que contarlo */
! 693: break;
! 694:
! 695: case INMED16: /* 1 operando inmediato de 16 bits */
! 696: longitud += 2; /* necesito otros 2 bytes más */
! 697: sprintf(op1, "%02X%02X", formato[longitud-1], formato[longitud-2]);
! 698: break;
! 699:
! 700: case SALTO8: /* 1 operando: byte */
! 701: longitud += 1; /* necesito otro byte más */
! 702: /* sprintf(destino, "IP+%02X", formato[longitud-1]); */
! 703: /* no hace falta dar IP ya que es un implícito indicado en la base de datos */
! 704: sprintf(op1, "%02X", formato[longitud-1]);
! 705: break;
! 706:
! 707: case SALTO16: /* 1 operando: 2 bytes */
! 708: longitud += 2; /* necesito otros 2 bytes más */
! 709: /* sprintf(destino, "IP+%02X%02X", formato[longitud-1], formato[longitud-2]); */
! 710: /* no hace falta dar IP ya que es un implícito indicado en la base de datos */
! 711: sprintf(op1, "%02X%02X", formato[longitud-1], formato[longitud-2]);
! 712: break;
! 713:
! 714: case BASEOFFSET: /* 1 operando: base:offset */
! 715: longitud += 4; /* necesito otros 4 bytes más */
! 716: sprintf(op1, "%02X%02X:%02X%02X", formato[longitud-1], formato[longitud-2], formato[longitud-3], formato[longitud-4]);
! 717: break;
! 718:
! 719: case REGULAR: /* 2 operandos: 1 registro y 1 reg/mem */
! 720: longitud += 1; /* necesito el 2º byte */
! 721: switch(byte1.campo.d)
! 722: {
! 723: case 0: /* reg es el operando 2 (fuente) */
! 724: OperandoRegistro(byte1.campo.w, byte2.campo.reg, op2);
! 725: OperandoRM(byte1.campo.w, byte2.campo.mod, byte2.campo.r_m, formato[longitud], formato[longitud+1], op1, &bytesadicionales);
! 726: break;
! 727:
! 728: case 1: /* reg es el operando 1 (destino) */
! 729: OperandoRegistro(byte1.campo.w, byte2.campo.reg, op1);
! 730: OperandoRM(byte1.campo.w, byte2.campo.mod, byte2.campo.r_m, formato[longitud], formato[longitud+1], op2, &bytesadicionales);
! 731: break;
! 732: }
! 733: longitud += bytesadicionales; /* sumo los posibles bytes del formato utilizados */
! 734: break;
! 735:
! 736: case INMEDTOAX: /* 2 operandos: inmediato -> acumulador */
! 737: switch(byte1.campo.w)
! 738: {
! 739: case 0:
! 740: longitud += 1; /* necesito otro byte más */
! 741: sprintf(op2, "%02X", formato[longitud-1]);
! 742: sprintf(op1, "AL"); /* este op1 está asociado a la operación (es implícito) */
! 743: /* sin embargo no lo considero tal ya que el programador */
! 744: /* lo explicita voluntariamente cuando escribe la instrucción */
! 745: /* el formato lo hace implícito para ahorrar espacio */
! 746: break;
! 747:
! 748: case 1:
! 749: longitud += 2; /* necesito otros 2 bytes más */
! 750: sprintf(op2, "%02X%02X", formato[longitud-1], formato[longitud-2]);
! 751: sprintf(op1, "AX");
! 752: break;
! 753: }
! 754: break;
! 755:
! 756: case INMEDTOREGMEM: /* 2 operandos: inmediato -> registro o memoria */
! 757: longitud += 1; /* necesito el 2º byte */
! 758: OperandoRM(byte1.campo.w, byte2.campo.mod, byte2.campo.r_m, formato[longitud], formato[longitud+1], op1, &bytesadicionales);
! 759: longitud += bytesadicionales; /* sumo los posibles bytes del formato utilizados */
! 760: switch(byte1.campo.w)
! 761: {
! 762: case 0:
! 763: longitud += 1; /* necesito otro byte más */
! 764: sprintf(op2, "%02X", formato[longitud-1]);
! 765: break;
! 766:
! 767: case 1:
! 768: longitud += 2; /* necesito otros 2 bytes más */
! 769: sprintf(op2, "%02X%02X", formato[longitud-1], formato[longitud-2]);
! 770: break;
! 771: }
! 772: break;
! 773:
! 774: case MOVMEMAX: /* 2 operandos: load/store entre memoria y acc */
! 775: longitud += 2; /* necesito otros 2 bytes más */
! 776: switch(byte1.campo.d)
! 777: {
! 778: case 0: /* memoria es el operando 2 */
! 779: sprintf(op2, "[%02X%02X]", formato[longitud-1], formato[longitud-2]);
! 780: OperandoRegistro(byte1.campo.w, 0, op1); /* es el acumulador */
! 781: break;
! 782:
! 783: case 1: /* memoria es el operando 1 */
! 784: sprintf(op1, "[%02X%02X]", formato[longitud-1], formato[longitud-2]);
! 785: OperandoRegistro(byte1.campo.w, 0, op2); /* es el acumulador */
! 786: /* este op1 está asociado a la operación (es implícito) */
! 787: /* sin embargo no lo considero tal ya que el programador */
! 788: /* lo explicita voluntariamente cuando escribe la instrucción */
! 789: /* el formato lo hace implícito para ahorrar espacio */
! 790: break;
! 791: }
! 792: break;
! 793:
! 794: case MOVSEGMTO: /* 2 operandos: 1 reg. de segmento y 1 reg/mem */
! 795: longitud += 1; /* necesito el 2º byte */
! 796: switch(byte1.campo.d)
! 797: {
! 798: case 0: /* reg. de segmento es el operando 2 */
! 799: OperandoRegSeg(byte2.campo.reg & 0x3, op2);
! 800: OperandoRM(1, byte2.campo.mod, byte2.campo.r_m, formato[longitud], formato[longitud+1], op1, &bytesadicionales);
! 801: /* hay que forzar w = 1 ya que del formato viene a 0 */
! 802: break;
! 803:
! 804: case 1: /* reg. de segmento es el operando 1 */
! 805: OperandoRegSeg(byte2.campo.reg & 0x3, op1);
! 806: OperandoRM(1, byte2.campo.mod, byte2.campo.r_m, formato[longitud], formato[longitud+1], op2, &bytesadicionales);
! 807: /* hay que forzar w = 1 ya que del formato viene a 0 */
! 808: break;
! 809: }
! 810: longitud += bytesadicionales; /* sumo los posibles bytes del formato utilizados */
! 811: break;
! 812:
! 813: case MOVINMEDTOREG: /* 2 operandos: inm -> registro */
! 814: switch((byte1.nibble.L & 0x8) >> 3)
! 815: {
! 816: case 0:
! 817: longitud += 1; /* necesito otro byte más */
! 818: sprintf(op2, "%02X", formato[longitud-1]);
! 819: OperandoRegistro(0, byte1.nibble.L & 0x7, op1);
! 820: break;
! 821:
! 822: case 1:
! 823: longitud += 2; /* necesito otros 2 bytes más */
! 824: sprintf(op2, "%02X%02X", formato[longitud-1], formato[longitud-2]);
! 825: OperandoRegistro(1, byte1.nibble.L & 0x7, op1);
! 826: break;
! 827: }
! 828: break;
! 829:
! 830: case DESPLAZAMIENTO: /* 2 operandos: reg/mem y contador */
! 831: longitud += 1; /* necesito el 2º byte */
! 832: OperandoRM(byte1.campo.w, byte2.campo.mod, byte2.campo.r_m, formato[longitud], formato[longitud+1], op1, &bytesadicionales);
! 833: longitud += bytesadicionales; /* sumo los posibles bytes del formato utilizados */
! 834: switch(byte1.campo.d) /* ahora se llama 'v' en lugar de 'd' pero es el mismo */
! 835: {
! 836: case 0:
! 837: sprintf(op2, "01"); /* todos los inmediatos deben tener 2 dígitos hex por byte */
! 838: break;
! 839:
! 840: case 1:
! 841: sprintf(op2, "CL");
! 842: break;
! 843: }
! 844: break;
! 845:
! 846: case ENTRADA_SALIDA: /* 2 operandos: acc y DX o inm8 */
! 847: switch(byte1.campo.d)
! 848: {
! 849: case 0: /* reg es el operando 2 */
! 850: if(byte1.campo.opcode == 57) /* 111 001 */
! 851: {
! 852: longitud += 1; /* necesito otro byte más */
! 853: sprintf(op2, "%02X", formato[longitud-1]);
! 854: }
! 855: else sprintf(op2, "DX");
! 856: OperandoRegistro(byte1.campo.w, 0, op1); /* es el acumulador */
! 857: break;
! 858:
! 859: case 1: /* reg es el operando 1 */
! 860: OperandoRegistro(byte1.campo.w, 0, op2); /* es el acumulador */
! 861: if(byte1.campo.opcode == 57) /* 111 011 */
! 862: {
! 863: longitud += 1; /* necesito otro byte más */
! 864: sprintf(op1, "%02X", formato[longitud-1]);
! 865: }
! 866: else sprintf(op1, "DX");
! 867: break;
! 868: }
! 869: break;
! 870: }
! 871:
! 872: /* (*p).miembro es equivalente a p->miembro */
! 873:
! 874: strcpy((*instruccion).nemonico, nemonico);
! 875: strcpy(instruccion->op2, op2);
! 876: strcpy(instruccion->op1, op1);
! 877: instruccion->longitud = longitud;
! 878: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>