Annotation of ADD_ver_10/Source Code/Source Files/Desensambladorx86IA16.c, revision 1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>