Annotation of ADD_ver_10/Desensambladorx86IA16.c, revision 1.2

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:
1.2     ! rico      837:             sprintf(op2, "01");        /* todos los inmediatos deben tener 2 dígitos hex por byte */
1.1       rico      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>