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