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>