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