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>