Annotation of ADD_ver_10/Desensambladorx86IA16.c, revision 1.1

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

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