28 | #include "disasm.h"
29 |
30 |
31 | /** Resource IDs ************************************************************/
32 |
33 |
34 | #define IDI_ICON1 100 // Main program icon.
35 | #define IDI_ICON2 101 // "Browse" icon.
36 | #define IDI_ICON3 102 // "Assemble" icon.
37 | #define IDI_ICON4 103 // "Search" icon.
38 |
39 | #define IDD_MAIN 1000 // Main dialog box.
40 |
41 | #define IDC_LABEL1 1001 // "Library" (label).
42 | #define IDC_EDIT1 1002 // Library filename (edit box).
43 | #define IDC_BUTTON1 1003 // "Browse" (button).
44 | #define IDC_LABEL2 1004 // "Code" (label).
45 | #define IDC_EDIT2 1005 // Assembly single-line command (edit box).
46 | #define IDC_BUTTON2 1006 // "Assemble" (button).
47 | #define IDC_LABEL3 1007 // "Binary" (label).
48 | #define IDC_EDIT3 1008 // Bytecode display (edit box).
49 | #define IDC_BUTTON3 1009 // "Search" (button).
50 | #define IDC_RICHEDIT1 1010 // Results report (rich edit).
51 | #define IDC_LABEL4 1011 // Status messages (label).
52 |
53 |
54 | /** Prototypes **************************************************************/
55 |
56 |
57 | static LRESULT CALLBACK MainDlgProc(HWND, UINT, WPARAM, LPARAM);
58 | static LONG CalcFontHeight(int pt);
59 | static BOOL BytecodeToText(TCHAR *output);
60 | static BOOL FindBytecodeInFile(HWND hDlg);
61 | static void FindBytecodeInSection(HWND hDlg, PIMAGE_SECTION_HEADER pSecHdr, PLOADED_IMAGE Image);
62 | static void AppendToReport(HWND hDlg, PIMAGE_SECTION_HEADER pSecHdr, PLOADED_IMAGE Image, int count);
63 | static void AppendText(HWND hRichEdt, TCHAR *pszText);
64 |
65 |
66 | /** Global variables ********************************************************/
67 |
68 |
69 | // Module instance handle. We use this to load resources.
70 | static HINSTANCE ghInstance;
71 |
72 | // Monospaced font to use in the list box.
73 | static LOGFONT g_lf = {
74 | 0,0,
75 | 0,0,FW_DONTCARE,FALSE,FALSE,FALSE,
76 | DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
77 | FIXED_PITCH | FF_DONTCARE,
78 | _T("Courier New")
79 | };
80 |
81 | // This globals are used to assemble mnemonics.
82 | // (I know it's ugly, but it was the easiest way, honest...)
83 | static int attempt = 0;
84 | static int constsize = 0;
85 | static t_asmmodel asmmodel;
86 |
87 | // Paths and filenames buffers. Used for GetOpenFileName().
88 | static TCHAR gsCustomFilter[MAX_PATH]; // Empty on startup, changed later by the user.
89 | static TCHAR gsInitialDir[MAX_PATH]; // %SYSTEM% on app startup, chaged later by user.
90 | static TCHAR gsFilename[MAX_PATH]; // Contains the DLL library filename.
91 | //static TCHAR gsPathname[MAX_PATH * 2]; // Full pathname, generated from gsFilename.
92 |
93 | // Valid file type filters. Used for GetOpenFileName().
94 | static const TCHAR gsFilter[] =
95 | "Dynamic link libraries\0*.dll\0"
96 | "All PE files\0*.cpl;*.dll;*.exe;*.ocx;*.scr\0"
97 | "All files\0*.*\0"
98 | "\0";
99 |
100 | // Setup for the GetOpenFileName() dialog box.
101 | static OPENFILENAME gOfn =
102 | {
103 | sizeof(OPENFILENAME), 0, 0,
104 | (TCHAR *)gsFilter, (TCHAR *)gsCustomFilter, sizeof(gsCustomFilter), 0,
105 | (TCHAR *)&gsFilename, sizeof(gsFilename),
106 | 0, 0, (TCHAR *)&gsInitialDir, _T("Browse for DLL..."),
107 | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
108 | 0, 0, _T(".dll"), 0, 0, 0
109 | }; // Unsupported flags: OFN_DONTADDTORECENT, OFN_FORCESHOWHIDDEN
110 |
111 |
112 | /** Procedures **************************************************************/
113 |
114 |
115 | static BOOL TryToAssemble(char *psCommand, char *psError)
116 | {
117 | // Globals:
118 | // in/out:
119 | // attempt
120 | // constsize
121 | // asmmodel
122 |
123 | // Try to assemble at the four different const sizes.
124 | // If we had at least one successful assembly at some const size,
125 | // we are allowed to move on to the next attempt.
126 | // If we fail at attempt 0, const size 0, we just quit.
127 | // If we get repeated bytecodes, skip them and keep trying.
128 | // The variables "constsize" and "attempt" are globals, because I wanted
129 | // to access them from MainProc.
130 | t_asmmodel local_asmmodel;
131 | psError[0] = 0;
132 | memcpy(&local_asmmodel, &asmmodel, sizeof(local_asmmodel));
133 | while( TRUE )
134 | {
135 | BOOL we_had_a_good_one = ( constsize > 0 );
136 | while( constsize < 4 )
137 | {
138 | int status = Assemble(psCommand, 0, &local_asmmodel, attempt, constsize, psError);
139 | constsize++;
140 | if( status > 0 )
141 | {
142 | if( memcmp(&(local_asmmodel.code), &(asmmodel.code), sizeof(TEXTLEN)) != 0 )
143 | {
144 | memcpy(&asmmodel, &local_asmmodel, sizeof(asmmodel));
145 | return TRUE;
146 | };
147 | }
148 | else if( attempt == 0 && constsize == 1 )
149 | {
150 | constsize = 0;
151 | return FALSE;
152 | };
153 | };
154 | constsize = 0;
155 | attempt++;
156 | if( !we_had_a_good_one ) break;
157 | };
158 | // attempt = 0;
159 | return FALSE;
160 | };
161 |
162 |
163 | static BOOL BytecodeToText(char *output)
164 | {
165 | // Globals:
166 | // in:
167 | // asmmodel
168 |
169 | // Converts the opcodes to hexa values for display.
170 | // Uses ASCIIZ strings only.
171 | char sTemp[8]; // BOF warning
172 | int i;
173 | BOOL iComplete = TRUE;
174 | output[0] = 0;
175 | for( i = 0; i < asmmodel.length; i++ )
176 | {
177 | char msk = asmmodel.mask[i];
178 | char ch = asmmodel.code[i] & msk;
179 | if( msk != 0xFF )
180 | {
181 | iComplete = FALSE;
182 | };
183 | sTemp[0] = 0;
184 | wsprintfA((char *)sTemp, "%.2X ", (int)ch);
185 | lstrcatA(output, (char *)sTemp);
186 | };
187 | return iComplete;
188 | };
189 |
190 |
191 | static BOOL FindBytecodeInFile(HWND hDlg)
192 | {
193 | BOOL iSuccess = FALSE;
194 | LOADED_IMAGE Image;
195 |
196 | // Clear the report.
197 | SetDlgItemText(hDlg, IDC_RICHEDIT1, NULL);
198 |
199 | // Load the PE file into memory.
200 | if( MapAndLoad((char *)&gsFilename, NULL, &Image, TRUE, TRUE) )
201 | {
202 | // For each section...
203 | __try
204 | {
205 | ULONG iSectionCount = Image.NumberOfSections;
206 | PIMAGE_SECTION_HEADER pSecHdr = Image.Sections;
207 | while( iSectionCount > 0 )
208 | {
209 | // Search for the bytecode in this section.
210 | if( (*pSecHdr).PointerToRawData != 0 )
211 | {
212 | FindBytecodeInSection(hDlg, pSecHdr, &Image);
213 | };
214 |
215 | // Next section.
216 | pSecHdr++;
217 | iSectionCount--;
218 | };
219 | }
220 | __except( EXCEPTION_EXECUTE_HANDLER )
221 | {
222 | char *pStr;
223 | pStr = LocalAlloc(LPTR, 512);
224 | if( pStr == NULL ) pStr = _T("Exception!");
225 | wsprintf(pStr, _T("Exception %X was thrown!"), exception_code());
226 | MessageBox(hDlg, pStr, _T("Debug"), MB_OK);
227 | LocalFree(pStr);
228 | };
229 |
230 | // Success!
231 | iSuccess = TRUE;
232 |
233 | // Unload the PE file from memory.
234 | UnMapAndLoad(&Image);
235 | };
236 | return iSuccess;
237 | };
238 |
239 |
240 | static void FindBytecodeInSection(HWND hDlg, PIMAGE_SECTION_HEADER pSecHdr, PLOADED_IMAGE Image)
241 | {
242 | char *rawptr;
243 | int max;
244 | int count;
245 | DWORD bcpos;
246 |
247 | rawptr = (char *)((*Image).MappedAddress + (*pSecHdr).PointerToRawData);
248 | max = (*pSecHdr).SizeOfRawData;
249 | if( !IsBadReadPtr(rawptr, max) )
250 | {
251 | count = 0;
252 | while( count < (int)(max - asmmodel.length) )
253 | {
254 | bcpos = 0;
255 | while( bcpos < asmmodel.length && asmmodel.code[bcpos] == rawptr[bcpos] )
256 | {
257 | bcpos++;
258 | };
259 | if( bcpos == asmmodel.length )
260 | {
261 | AppendToReport(hDlg, pSecHdr, Image, count);
262 | };
263 | rawptr++;
264 | count++;
265 | };
266 | }
267 | else
268 | {
269 | MessageBox(hDlg, _T("Bad read pointer!"), _T("Debug"), MB_OK);
270 | };
271 | };
272 |
273 |
274 | static void AppendToReport(HWND hDlg, PIMAGE_SECTION_HEADER pSecHdr, PLOADED_IMAGE Image, int count)
275 | {
276 | PIMAGE_NT_HEADERS pNtHdr;
277 | DWORD RVA;
278 | DWORD RA;
279 | TCHAR buffer[256];
280 |
281 | pNtHdr = ImageNtHeader((*Image).MappedAddress);
282 | if( pNtHdr == NULL )
283 | {
284 | MessageBox(hDlg, _T("No NT header!"), _T("Debug"), MB_OK);
285 | return;
286 | };
287 | RVA = (*pSecHdr).VirtualAddress + count;
288 | RA = RVA + (*pNtHdr).OptionalHeader.ImageBase;
289 | buffer[0] = 0;
290 | wsprintf(
291 | (TCHAR *)&buffer,
292 | _T("Found at 0x%08X (RVA 0x%08X).\n"),
293 | RA,
294 | RVA);
295 | AppendText(GetDlgItem(hDlg, IDC_RICHEDIT1), (TCHAR *)&buffer);
296 | };
297 |
298 |
299 | static void AppendText(HWND hRichEdt, TCHAR *pszText)
300 | {
301 | CHARRANGE cr_old;
302 | CHARRANGE cr_new;
303 |
304 | // Initialize the local variables.
305 | cr_old.cpMin = cr_old.cpMax = 0;
306 | cr_new.cpMin = cr_new.cpMax = -1;
307 |
308 | // Lock the window redrawing.
309 | LockWindowUpdate(hRichEdt);
310 |
311 | // Get the current selection range.
312 | SendMessage(hRichEdt, EM_EXGETSEL, 0, (LPARAM)&cr_old);
313 |
314 | // Set the selection to the end of the current text.
315 | SendMessage(hRichEdt, EM_EXSETSEL, 0, (LPARAM)&cr_new);
316 |
317 | // Append the text.
318 | SendMessage(hRichEdt, EM_REPLACESEL, FALSE, (LPARAM)pszText);
319 |
320 | // Set the previous selection range.
321 | SendMessage(hRichEdt, EM_EXSETSEL, 0, (LPARAM)&cr_old);
322 |
323 | // Unlock window redrawing.
324 | LockWindowUpdate(NULL);
325 | };
326 |
327 |
328 | static LONG CalcFontHeight(int pt)
329 | {
330 | HWND hWnd = GetDesktopWindow();
331 | HDC hDC = GetDC(hWnd);
332 | int height = -((GetDeviceCaps(hDC, LOGPIXELSY) * pt) / 72);
333 | ReleaseDC(hWnd, hDC);
334 | return height;
335 | };
336 |
337 |
338 | int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
339 | {
340 | // Globals:
341 | // out:
342 | // ghInstance
343 |
344 | int retval;
345 | HINSTANCE hLib;
346 | INITCOMMONCONTROLSEX icce;
347 |
348 | // Keep the instance handle. We'll need it later ot load resources.
349 | ghInstance = hInstance;
350 |
351 | // Initialize common controls. Also needed for MANIFEST's.
352 | icce.dwSize = sizeof(icce);
353 | icce.dwICC = ICC_USEREX_CLASSES;
354 | InitCommonControlsEx(&icce);
355 |
356 | // Initialize the OLE library.
357 | OleInitialize(NULL);
358 |
359 | // Load the Rich Edit library.
360 | hLib = LoadLibrary(_T("Riched32.dll"));
361 |
362 | // The user interface is a modal dialog box.
363 | retval = DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC)MainDlgProc);
364 |
365 | // Unload the Rich Edit library.
366 | FreeLibrary(hLib);
367 |
368 | // Uninitialize the OLE library.
369 | OleUninitialize();
370 |
371 | // Return.
372 | return retval;
373 | }
374 |
375 |
376 | static LRESULT CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
377 | {
378 | // Globals:
379 | // in:
380 | // gsFilter
381 | // in/out:
382 | // ghInstance
383 | // attempt
384 | // constsize
385 | // asmmodel
386 | // gsCustomFilter
387 | // gsInitialDir
388 | // gsFilename
389 | // gsPathname
390 |
391 | switch ( uMsg )
392 | {
393 | case WM_COMMAND:
394 | {
395 | // Decide based on the control ID.
396 | switch ( wParam & 0x0000FFFF )
397 | {
398 | case IDC_EDIT2: // Edit box notify message.
399 | {
400 | // Is is a text change?
401 | if( ((wParam & 0xFFFF0000) >> 16) == EN_UPDATE )
402 | {
403 | // Clear the bytecode display.
404 | SetDlgItemText(hDlg, IDC_EDIT3, NULL);
405 |
406 | // Reset the assembly-related global variables.
407 | attempt = constsize = 0;
408 | memset(&asmmodel, 0, sizeof(asmmodel));
409 | };
410 | };
411 | break;
412 |
413 | case IDC_BUTTON1: // Browse for a DLL library...
414 | {
415 | gOfn.hInstance = ghInstance;
416 | gOfn.hwndOwner = hDlg;
417 | GetDlgItemText(hDlg, IDC_EDIT1, (TCHAR *)&gsFilename, sizeof(gsFilename));
418 | if( GetOpenFileName(&gOfn) ) {
419 | SetDlgItemText(hDlg, IDC_EDIT1, (TCHAR *)&gsFilename);
420 | };
421 | };
422 | break;
423 |
424 | case IDC_BUTTON2: // Assemble the current command.
425 | {
426 | // Get the assembly command.
427 | char sError[TEXTLEN];
428 | char sHexa[TEXTLEN]; // BOF warning
429 | char sCommand[TEXTLEN];
430 | if( GetDlgItemTextA(hDlg, IDC_EDIT2, (char *)&sCommand, sizeof(sCommand)) )
431 | {
432 | // Assemble the command.
433 | if( TryToAssemble((char *)&sCommand, (char *)&sError) )
434 | {
435 | // Parse a display string for the bytecode.
436 | if( ! BytecodeToText((char *)&sHexa) )
437 | {
438 | // If the command is not complete, warn so.
439 | SetDlgItemText(hDlg, IDC_LABEL4,
440 | _T("Warning: command is not precise!"));
441 | }
442 | else
443 | {
444 | // If not, show a status message.
445 | TCHAR sNum[256]; // BOF warning
446 | sNum[0] = 0;
447 | wsprintf((TCHAR *)sNum, _T("Attempt %i, const size %i, assembled %i byte(s)."),
448 | attempt, constsize - 1, asmmodel.length);
449 | SetDlgItemText(hDlg, IDC_LABEL4, (TCHAR *)&sNum);
450 | };
451 |
452 | // Show the bytecode to the user.
453 | SetDlgItemTextA(hDlg, IDC_EDIT3, (char *)&sHexa);
454 | }
455 | else
456 | {
457 | // Clear the bytecode display.
458 | SetDlgItemText(hDlg, IDC_EDIT3, NULL);
459 |
460 | // Set the keyboard focus on the second edit box.
461 | SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
462 |
463 | // Was it a real error, or just no more attempts?
464 | if( attempt == 0 )
465 | {
466 | // Show the error text.
467 | SetDlgItemTextA(hDlg, IDC_LABEL4, (char *)&sError);
468 | }
469 | else
470 | {
471 | // No more attempts allowed.
472 | SetDlgItemText(hDlg, IDC_LABEL4, _T("No more attempts allowed for this command."));
473 |
474 | // Reset the assembly-related global variables.
475 | attempt = constsize = 0;
476 | memset(&asmmodel, 0, sizeof(asmmodel));
477 | };
478 | };
479 | }
480 | else
481 | {
482 | // Error: no command was entered.
483 | SetDlgItemText(hDlg, IDC_LABEL4, _T("Please enter an assembly command..."));
484 | // Set the keyboard focus on the second edit box.
485 | SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
486 | };
487 | };
488 | break;
489 |
490 | case IDC_BUTTON3: // Search for the bytecode.
491 | {
492 | // Make sure we have a valid bytecode.
493 | if( asmmodel.length > 0 )
494 | {
495 | // Try to get the file name.
496 | gsFilename[0] = 0;
497 | if( ! GetDlgItemText(hDlg, IDC_EDIT1, (TCHAR *)gsFilename, sizeof(gsFilename)) )
498 | {
499 | // No filename was entered, browse for one.
500 | // (Updates the gFilename global string).
501 | SendMessage(hDlg, WM_COMMAND, IDC_BUTTON1, 0);
502 | };
503 |
504 | // Do we have the filename?
505 | if( gsFilename[0] != 0 )
506 | {
507 | BOOL bOk;
508 | HLOCAL hMem = NULL;
509 |
510 | // Search for the bytecode.
511 | SetDlgItemText(hDlg, IDC_LABEL4, _T("Searching..."));
512 | bOk = FindBytecodeInFile(hDlg);
513 |
514 | // Parse a status message from the last error value.
515 | if( FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
516 | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM |
517 | FORMAT_MESSAGE_MAX_WIDTH_MASK, 0, GetLastError(),
518 | 0, (void *)&hMem, 1, NULL) )
519 | {
520 | // Show the status message.
521 | SetDlgItemText(hDlg, IDC_LABEL4, (TCHAR *)hMem);
522 | LocalFree(hMem);
523 | };
524 |
525 | // Set the keyboard focus on the first edit control, or the list box.
526 | SetFocus(GetDlgItem(hDlg, bOk ? IDC_RICHEDIT1 : IDC_EDIT1));
527 | }
528 | else
529 | {
530 | // Error: no filename was entered.
531 | SetDlgItemText(hDlg, IDC_LABEL4, _T("Please enter a filename..."));
532 | SetFocus(GetDlgItem(hDlg, IDC_EDIT1));
533 | };
534 | }
535 | else
536 | {
537 | // Error: no valid bytecode to search.
538 | SetDlgItemText(hDlg, IDC_LABEL4, _T("Please enter an assembly command..."));
539 | SetFocus(GetDlgItem(hDlg, IDC_EDIT2));
540 | };
541 | };
542 | break;
543 |
544 | case IDOK:
545 | {
546 | // Depends on the currently focused control...
547 | HWND hCtrl = GetFocus();
548 | if( hCtrl == GetDlgItem(hDlg, IDC_EDIT1) )
549 | {
550 | // Browse for a DLL library.
551 | SendMessage(hDlg, WM_COMMAND, IDC_BUTTON1, 0);
552 | }
553 | else if( hCtrl == GetDlgItem(hDlg, IDC_EDIT2) )
554 | {
555 | // Assemble the command.
556 | SendMessage(hDlg, WM_COMMAND, IDC_BUTTON2, 0);
557 | }
558 | else
559 | {
560 | // Search for the bytecode.
561 | SendMessage(hDlg, WM_COMMAND, IDC_BUTTON3, 0);
562 | };
563 | };
564 | break;
565 |
566 | case IDCANCEL:
567 | {
568 | // Close the dialog box.
569 | EndDialog(hDlg, TRUE);
570 | };
571 | };
572 | };
573 | break;
574 |
575 | case WM_INITDIALOG:
576 | {
577 | // Initialize the disassembler.
578 | ideal = FALSE; // Force IDEAL decoding mode
579 | lowercase = FALSE; // Force lowercase display
580 | tabarguments = FALSE; // Tab between mnemonic and arguments
581 | extraspace = TRUE; // Extra space between arguments
582 | putdefseg = FALSE; // Display default segments in listing
583 | showmemsize = TRUE; // Always show memory size
584 | shownear = TRUE; // Show NEAR modifiers
585 | shortstringcmds = TRUE; // Use short form of string commands
586 | sizesens = TRUE; // How to decode size-sensitive mnemonics
587 | symbolic = FALSE; // Show symbolic addresses in disasm
588 | farcalls = TRUE; // Accept far calls, returns & addresses
589 | decodevxd = TRUE; // Decode VxD calls (Win95/98)
590 | privileged = TRUE; // Accept privileged commands
591 | iocommand = TRUE; // Accept I/O commands
592 | badshift = TRUE; // Accept shift out of range 1..31
593 | extraprefix = TRUE; // Accept superfluous prefixes
594 | lockedbus = TRUE; // Accept LOCK prefixes
595 | stackalign = TRUE; // Accept unaligned stack operations
596 | iswindowsnt = TRUE; // When checking for dangers, assume NT
597 |
598 | // Initialize the gsInitialDir variable.
599 | GetSystemDirectory((TCHAR *)&gsInitialDir, sizeof(gsInitialDir));
600 |
601 | // Set the main dialog's icon.
602 | SendMessage(hDlg, WM_SETICON, ICON_SMALL,
603 | (LPARAM)LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_ICON1)));
604 |
605 | // Set the button icons.
606 | SendDlgItemMessage(hDlg, IDC_BUTTON1, BM_SETIMAGE, IMAGE_ICON,
607 | (LPARAM)LoadImage(ghInstance, MAKEINTRESOURCE(IDI_ICON2),
608 | IMAGE_ICON, 0, 0, LR_CREATEDIBSECTION));
609 | SendDlgItemMessage(hDlg, IDC_BUTTON2, BM_SETIMAGE, IMAGE_ICON,
610 | (LPARAM)LoadImage(ghInstance, MAKEINTRESOURCE(IDI_ICON3),
611 | IMAGE_ICON, 0, 0, LR_CREATEDIBSECTION));
612 | SendDlgItemMessage(hDlg, IDC_BUTTON3, BM_SETIMAGE, IMAGE_ICON,
613 | (LPARAM)LoadImage(ghInstance, MAKEINTRESOURCE(IDI_ICON4),
614 | IMAGE_ICON, 0, 0, LR_CREATEDIBSECTION));
615 |
616 | // Set the rich edit font.
617 | g_lf.lfHeight = CalcFontHeight(9);
618 | SendDlgItemMessage(hDlg, IDC_RICHEDIT1, WM_SETFONT,
619 | (WPARAM)CreateFontIndirect(&g_lf), (LPARAM)TRUE);
620 |
621 | // Enable autocomplete for the filename edit box.
622 | SHAutoComplete(GetDlgItem(hDlg, IDC_EDIT1), SHACF_FILESYSTEM);
623 |
624 | // Set keyboard focus on the first control in tab order.
625 | return TRUE;
626 | };
627 |
628 | case WM_DESTROY:
629 | {
630 | // Destroy the main window icon.
631 | DestroyIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)NULL));
632 |
633 | // Destroy the button icons.
634 | DestroyIcon((HICON)SendDlgItemMessage(hDlg, IDC_BUTTON1, BM_SETIMAGE, IMAGE_ICON, (LPARAM)NULL));
635 | DestroyIcon((HICON)SendDlgItemMessage(hDlg, IDC_BUTTON2, BM_SETIMAGE, IMAGE_ICON, (LPARAM)NULL));
636 | DestroyIcon((HICON)SendDlgItemMessage(hDlg, IDC_BUTTON3, BM_SETIMAGE, IMAGE_ICON, (LPARAM)NULL));
637 |
638 | // Destroy the rich edit font.
639 | DeleteObject((HGDIOBJ)SendDlgItemMessage(hDlg, IDC_RICHEDIT1, WM_SETFONT, 0, TRUE));
640 | };
641 | }
642 | return FALSE;
643 | }
644 |
645 |
646 | /** End of file *************************************************************/
647 |
--------------------------------------------------------------------------------
/FindOC/disasm/readme.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 80x86 Assembler and Disasssembler
10 |
11 |
12 | 80x86
13 | 32-bit Disassembler and Assembler
14 | Legal part
15 |
Introduction
16 |
Brief description of functions
17 |
Assemble
18 |
Checkcondition
19 |
Decodeaddress
20 |
Disasm
21 |
Disassembleback
22 |
Disassembleforward
23 |
Isfilling
24 |
Printfloat* functions
25 |
26 |
27 |
Legal
28 | part
29 | This package includes source code of 32-bit Disassembler and 32-bit
30 | single line Assembler for 80x86-compatible processors. The source is a
31 | slightly stripped version of code used in OllyDbg v1.04 and is well proven
32 | by its numerous users. (If you haven't heard before, OllyDbg
33 | is a 32-bit Assembler level debugger with powerful analyzing capabilities
34 | that makes binary machine code understandable).
35 |
This program is free software; you can redistribute it and/or modify
36 | it under the terms of the GNU General Public License as published by the
37 | Free Software Foundation; either version 2 of the License, or (at your
38 | option) any later version. This program is distributed in the hope that
39 | it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
40 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41 | General Public License (http://www.fsf.org/copyleft/gpl.html)
42 | for more details.
43 |
You should have received a copy of the GNU General Public License (gpl.txt)
44 | along with this program; if not, write to the Free Software Foundation,
45 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
46 |
All brand names and product names used in 80x86 Assembler and Disassembler,
47 | accompanying files or in this help file are trademarks, registered trademarks,
48 | or trade names of their respective holders.
49 |
50 |
51 |
52 |
Introduction
53 | Disassembler understands all standard 80x86 commands, FPU, MMX, AMD's
54 | MMX extensions, Athlon/PIII MMX extensions and 3DNow! instructions. It
55 | does not decode SSI or SSI2 commands. Disassembler assumes 32 bit code
56 | and data segments but correctly decodes prefixed 16-bit commands. Several
57 | decoding modes allow you to select the amount of returned information (which
58 | is inversely proportional to execution speed): command length only, basic
59 | information useful for code analysis, or full decoding with dump and assembler
60 | form. Multiple options select desired format. Disassembler and Assembler
61 | support both MASM and Borland's IDEAL modes.
62 |
Assembler converts single command from the ASCII form to the binary
63 | code. It allows to find several possible encodings, or even to create search
64 | patterns with undefined operands.
65 |
This package includes following files:
66 |
67 | -
68 | disasm.h - common definitions
69 |
70 | -
71 | disasm.c - Disassembler
72 |
73 | -
74 | assembl.c - Assembler
75 |
76 | -
77 | asmserv.c - table of commands and service functions
78 |
79 | -
80 | main.c - demo program
81 |
82 | Total source size exceeds 3800 lines of dense text (more than 190
83 | K!). I have used Borland C and do not guarantee that it will work with
84 | any other compiler. Please set the default character type to unsigned!
85 | Please also place the following statements into the main file of your program,
86 | and do not #define MAINPROG in any other file:
87 |
88 | #define MAINPROG // Place all unique variables here
89 |
90 | #include "disasm.h"
91 |
(I use this trick to define shared global variables). Below is a small
92 | piece of code disassembled with OllyDbg 1.04 using different text settings:
93 |
94 |
95 |
96 | 004505B3 A1 DC464B00
97 | MOV EAX,DS:[4B46DC]
98 | 004505B8 8B0498
99 | MOV EAX,DS:[EAX+EBX*4]
100 | 004505BB 50
101 | PUSH EAX
102 | 004505BC 8D85 E0FBFFFF
103 | LEA EAX,SS:[EBP-420]
104 | 004505C2 50
105 | PUSH EAX
106 | 004505C3 E8 141BFCFF
107 | CALL 004120DC
108 | 004505C8 83C4 08
109 | ADD ESP,8
110 | 004505CB 43
111 | INC EBX
112 | 004505CC 3B1D D8464B00
113 | CMP EBX,DS:[4B46D8]
114 | 004505D2 0F8C AFFEFFFF
115 | JL 00450487
116 | 004505D8 80BD E0FDFFFF 00 CMP BYTE PTR
117 | SS:[EBP-220],0
118 | 004505DF 75 14
119 | JNZ SHORT 004505F5
120 | 004505E1 68 B39E4600
121 | PUSH 469EB3
122 | 004505E6 8D85 E0FDFFFF
123 | LEA EAX,SS:[EBP-220]
124 | 004505EC 50
125 | PUSH EAX
126 | 004505ED E8 521BFCFF
127 | CALL 00412144 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | 004505B3 A1 DC464B00
135 | mov eax,[dword ds:4B46DC]
136 | 004505B8 8B0498
137 | mov eax,[dword ds:eax+ebx*4]
138 | 004505BB 50
139 | push eax
140 | 004505BC 8D85 E0FBFFFF
141 | lea eax,[dword ss:ebp-420]
142 | 004505C2 50
143 | push eax
144 | 004505C3 E8 141BFCFF
145 | call 004120DC
146 | 004505C8 83C4 08
147 | add esp,8
148 | 004505CB 43
149 | inc ebx
150 | 004505CC 3B1D D8464B00
151 | cmp ebx,[dword ds:4B46D8]
152 | 004505D2 0F8C AFFEFFFF
153 | jl 00450487
154 | 004505D8 80BD E0FDFFFF 00 cmp
155 | [byte ss:ebp-220],0
156 | 004505DF 75 14
157 | jnz short 004505F5
158 | 004505E1 68 B39E4600
159 | push 469EB3
160 | 004505E6 8D85 E0FDFFFF
161 | lea eax,[dword ss:ebp-220]
162 | 004505EC 50
163 | push eax
164 | 004505ED E8 521BFCFF
165 | call 00412144 |
166 |
167 |
168 |
169 |
170 |
171 |
Brief
172 | description of functions
173 |
174 | -
175 | int Assemble(char
176 | *cmd,ulong ip,t_asmmodel *model,int attempt,int constsize,char *errtext)
177 | - assembles text command to binary code;
178 |
179 | -
180 | int Checkcondition(int
181 | code,ulong flags) - checks whether flags met condition in the command;
182 |
183 | -
184 | int Decodeaddress(ulong
185 | addr,ulong base,int addrmode,char *symb,int nsymb,char *comment)
186 | - user-supplied function that decodes addresses into symbolic names;
187 |
188 | -
189 | ulong Disasm(char
190 | *src,ulong srcsize,ulong srcip,t_disasm *disasm,int disasmmode)
191 | - determines length of the binary command or disassembles it to the text;
192 |
193 | -
194 | ulong Disassembleback(char
195 | *block,ulong base,ulong size,ulong ip,int n) - walks binary code
196 | backward;
197 |
198 | -
199 | ulong Disassembleforward(char
200 | *block,ulong base,ulong size,ulong ip,int n) - walks binary code
201 | forward;
202 |
203 | -
204 | int Isfilling(ulong
205 | addr,char *data,ulong size,ulong align) - determines whether command
206 | is equivalent to NOP;
207 |
208 | -
209 | int Print3dnow(char
210 | *s,char *f) - converts 3DNow! constant to text without triggering
211 | FPU exception for invalid operands;
212 |
213 | -
214 | int Printfloat10(char
215 | *s,long double ext) - converts 10-byte floating constant to text
216 | without causing exception;
217 |
218 | -
219 | int Printfloat4(char
220 | *s,float f) - converts 4-byte floating constant to text without
221 | causing exception;
222 |
223 | -
224 | int Printfloat8(char
225 | *s,double d) - converts 8-byte floating constant to text without
226 | causing exception.
227 |
228 |
229 |
230 |
Assemble
231 | Function Assemble(), as expected, converts command from ASCII form to
232 | binary 32 bit code. It shares command table with Disasm(), so if some command
233 | can be disassembled, it can be assembled back too, with one exception:
234 | Assemble doesn't support 16 bit addresses. With some unimportant exceptions,
235 | 16 bit addresses cannot be used in Win32 programs.
236 |
Some commands have more than one encoding. Assemble() allows you to
237 | find them all. This is important, for example, if you want to find the
238 | shortest possible code or to find all possible occurrences of this command
239 | in the code. There are two parameters, constsize and attempt. First parameter
240 | selects size of immediate constant and address constant (8 or 32 bits),
241 | second is the occurrence of the command in the command table. To find all
242 | variants, call Assemble() with attempt=0,1,2... and for each attempt with
243 | constsize=0,1,2,3 as long as function reports success for at least one
244 | constsize. Generated codes may repeat. Please note that if command uses
245 | memory addresses, only one form will be generated in each case: [EAX*2]
246 | but not [EAX+EAX]; [EBX+EAX] but not [EAX+EBX]; [EAX] will not use SIB
247 | byte; no DS: prefix and so on.
248 |
Assemble compiles also imprecise commands that include following generalized
249 | operands:
250 |
251 | -
252 | R8 - any 8-bit register (stays for AL, BL, CL, DL, AH, BH, CH, DH)
253 |
254 | -
255 | R16 - any 16 bit register (AX, BX, CX, DX, SP, BP, SI, DI)
256 |
257 | -
258 | R32 - any 32 bit register (EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI)
259 |
260 | -
261 | FPU - any FPU register (ST0..ST7)
262 |
263 | -
264 | MMX - any MMX register (MM0..MM7)
265 |
266 | -
267 | CRX - any control register (CR0..CR7)
268 |
269 | -
270 | DRX - any debug register (DR0..DR7)
271 |
272 | -
273 | CONST - any constant
274 |
275 | This allows to generate imprecise search patterns, where mask contains
276 | zero bits at the positions occupied by imprecise operands in binary code.
277 | For example, patterns generated for command MOV R32,CONST will match both
278 | MOV EAX,1 and MOV ECX,12345678h.
279 | Function returns number of bytes in assembled code or non-positive (zero
280 | or negative) number in case of error or when variant selected by combination
281 | of attempt and constsize doesn't exist. This number is the negative position
282 | of error in the input command. If you generate executable code, imprecise
283 | commands are usually not allowed. To assure that command is precise, check
284 | that all significant bytes in mask contain 0xFF.
285 |
int Assemble(char *cmd,ulong ip,t_asmmodel
286 | *model,int attempt,int constsize,char *errtext);
287 |
Parameters:
288 |
289 | -
290 | cmd - pointer to zero terminated ASCII command;
291 |
292 | -
293 | pi - address of the first byte of generated
294 | binary command in memory;
295 |
296 | -
297 | model - pointer to the structure that receives
298 | machine code and mask, see detailed description below;
299 |
300 | -
301 | attempt - index of alternative encoding of
302 | the command. Call Assemble with attempt=0,1,2... to obtain all possible
303 | versions of the command. Stop this sequence when Assemble reports error;
304 |
305 | -
306 | constsize - requested size of address constant
307 | and immediate data. Call Assemble with constsize=0,1,2,3 to obtain all
308 | possible encodings of the version selected by attempt;
309 |
310 | -
311 | errtext - pointer to text buffer of length
312 | at least TEXTLEN bytes that receives description of detected error.
313 |
314 | t_asmmodel: structure that receives assembled code.
315 | typedef struct t_asmmodel {
316 | // Model to search for assembler command
317 |
char code[MAXCMDSIZE];
318 | // Binary code
319 |
char mask[MAXCMDSIZE];
320 | // Mask for binary code (0: bit ignored)
321 |
int length;
322 | // Length of code, bytes (0: empty)
323 |
int jmpsize;
324 | // Offset size if relative jump
325 |
int jmpoffset;
326 | // Offset relative to IP
327 |
int jmppos;
328 | // Position of jump offset in command
329 |
} t_asmmodel;
330 |
Members:
331 |
332 | -
333 | code - binary code of the command. Only bits
334 | that have 1's in corresponding mask bits are significant;
335 |
336 | -
337 | mask - comparison mask. Search routine ignores
338 | all code bits where mask is set to 0;
339 |
340 | -
341 | length - length of code and mask, bytes. If
342 | length is 0, search model is empty or invalid;
343 |
344 | -
345 | jmpsize - if nonzero, command is a relative
346 | jump and jmpsize is a size of offset in bytes;
347 |
348 | -
349 | jmpoffset - if jmpsize is nonzero, jump offset
350 | relative to address of the following command, otherwise undefined;
351 |
352 | -
353 | jmppos - if jmpsize is nonzero, position of
354 | the first byte of the offset in code, otherwise undefined.
355 |
356 |
357 |
358 |
Checkcondition
359 | Checks whether 80x86 flags meet condition code in the command. Returns
360 | 1 if condition is met and 0 if not.
361 |
int Checkcondition(int code,ulong flags);
362 |
Parameters:
363 |
364 | -
365 | code - byte of command that contains condition
366 | code;
367 |
368 | -
369 | flags - contents of register EFL.
370 |
371 |
372 |
373 |
Decodeaddress
374 | Custom user-supplied function that converts constant (address) into
375 | symbolic name. Initially, source code includes dummy function that returns
376 | 0.
377 |
Decodeaddress() decodes memory address or constant to the ASCII string
378 | and optionally comments this address. Returns length of decoded string
379 | (not including terminal 0), or 0 on error or if symbolic name is not available.
380 |
int Decodeaddress(ulong addr,char *symb,int
381 | nsymb,char *comment);
382 |
Parameters:
383 |
384 | -
385 | addr - address to decode in address space
386 | of debugged program;
387 |
388 | -
389 | symb - pointer to buffer of length at least
390 | nsymb bytes where Decodeaddress() places decoded string;
391 |
392 | -
393 | nsymb - length, in characters, of buffer symb;
394 |
395 | -
396 | comment - pointer to string of length at least
397 | TEXTLEN bytes or NULL, receives comment associated with addr.
398 |
399 |
400 |
401 |
Disasm
402 | The most important (and complex) function in this package. Depending
403 | on the specified disasmmode, Disasm() performs one of the four functions:
404 |
405 | -
406 | DISASM_SIZE - quickly determines size of the command. Use this mode
407 | if you want to walk through the code. In this mode, treat all members of
408 | disasm as undefined;
409 |
410 | -
411 | DISASM_DATA - determines size and analyses operands. Use this mode
412 | for quick analysis, for example, if you need to calculate jump destination.
413 | Members of disasm marked with asterisk (*) are undefined;
414 |
415 | -
416 | DISASM_FILE - determines size, analyses operand and disassembles
417 | command, but doesn't attempt to convert addresses to symbols. Use this
418 | mode if there is no correspondence between addresses and symbols, for example,
419 | if you dump the contents of binary file;
420 |
421 | -
422 | DISASM_CODE - full disassembly.
423 |
424 | Function returns size of disassembled command. There are several global
425 | constants that influence the behavior of this function. They are described
426 | later in this section. All symbolic constants are described in file disasm.h.
427 | ulong Disasm(char *src,ulong srcsize,ulong
428 | srcip,t_disasm *disasm,int disasmmode);
429 |
Parameters:
430 |
431 | -
432 | src - pointer to binary code that must be
433 | disassembled;
434 |
435 | -
436 | srcsize - size of src. Length of 80x86 command
437 | is limited to MAXCMDSIZE bytes;
438 |
439 | -
440 | srcip - address of the command;
441 |
442 | -
443 | disasm - pointer to structure that receives
444 | results of disassembling, see detailed description below;
445 |
446 | -
447 | disasmmode - disassembly mode, one of DISASM_xxx
448 | (see above).
449 |
450 | t_disasm:
451 | typedef struct t_disasm {
452 | // Results of disassembling
453 |
ulong pi;
454 | // Instruction pointer
455 |
char dump[TEXTLEN];
456 | // (*) Hexadecimal dump of the command
457 |
char result[TEXTLEN];
458 | // (*) Disassembled command
459 |
char comment[TEXTLEN];
460 | // (*) Brief comment
461 |
int cmdtype;
462 | // One of C_xxx
463 |
int memtype;
464 | // Type of addressed variable in memory
465 |
int nprefix;
466 | // Number of prefixes
467 |
int indexed;
468 | // Address contains register(s)
469 |
ulong jmpconst;
470 | // Constant jump address
471 |
ulong jmptable;
472 | // Possible address of switch table
473 |
ulong adrconst;
474 | // Constant part of address
475 |
ulong immconst;
476 | // Immediate constant
477 |
int zeroconst;
478 | // Whether contains zero constant
479 |
int fixupoffset;
480 | // Possible offset of 32 bit fixups
481 |
int fixupsize;
482 | // Possible total size of fixups or 0
483 |
int error;
484 | // Error while disassembling command
485 |
int warnings;
486 | // Combination of DAW_xxx
487 |
} t_disasm;
488 |
Members:
489 |
490 | -
491 | pi - address of the disassembled command;
492 |
493 | -
494 | dump - ASCII string, formatted hexadecimal
495 | dump of the command;
496 |
497 | -
498 | result - ASCII string, disassembled command
499 | itself;
500 |
501 | -
502 | comment - ASCII string, brief comment that
503 | applies to the whole command;
504 |
505 | -
506 | cmdtype - type of the disassembled command,
507 | one of C_xxx possibly ORed with C_RARE to indicate that command is seldom
508 | in ordinary Win32 applications. Commands of type C_MMX additionally contain
509 | size of MMX data in the 3 least significant bits (0 means 8-byte operands).
510 | Non-MMX commands may have C_EXPL bit set which means that some memory operand
511 | has size which is not conform with standard 80x86 rules;
512 |
513 | -
514 | memtype - type of memory operand, one of DEC_xxx,
515 | or DEC_UNKNOWN if operand is non-standard or command does not access memory;
516 |
517 | -
518 | nprefix - number of prefixes that this command
519 | contains;
520 |
521 | -
522 | indexed - if memory address contains index
523 | register, set to scale, otherwise 0;
524 |
525 | -
526 | jmpconst - address of jump destination if
527 | this address is a constant, and 0 otherwise;
528 |
529 | -
530 | jmptable - if indirect jump can be interpreted
531 | as switch, base address of switch table and 0 otherwise;
532 |
533 | -
534 | adrconst - constant part of memory address;
535 |
536 | -
537 | immconst - immediate constant or 0 if command
538 | contains no immediate constant. The only command that contains two immediate
539 | constants is ENTER. Disasm() ignores second constant which is anyway 0
540 | in most cases;
541 |
542 | -
543 | zeroconst - nonzero if command contains immediate
544 | zero constant;
545 |
546 | -
547 | fixupoffset - possible start of 32 bit fixup
548 | within the command, or 0 if command can't contain fixups;
549 |
550 | -
551 | fixupsize - possible total size of fixups
552 | (0, 4 or 8). If command contains both immediate constant and immediate
553 | address, they are always adjacent on 80x86 processors;
554 |
555 | -
556 | error - Disasm() was unable to disassemble
557 | command (for example, command does not exist or crosses end of memory block),
558 | one of DAE_xxx;
559 |
560 | -
561 | warnings - command is suspicious or meaningless
562 | (for example, far jump or MOV EAX,EAX preceded with segment prefix), combination
563 | of DAW_xxx bits;
564 |
565 | Global flags that influence text of disassembled command:
566 |
567 | -
568 | ideal - force IDEAL decoding mode
569 |
570 | -
571 | lowercase - force lowercase
572 |
573 | -
574 | tabarguments - insert tab between mnemonic
575 | and arguments
576 |
577 | -
578 | extraspace - insert extra space between arguments
579 |
580 | -
581 | putdefseg - show default segments
582 |
583 | -
584 | showmemsize - always show memory size
585 |
586 | -
587 | shownear - show NEAR modifiers
588 |
589 | -
590 | shortstringcmds - use short form of string
591 | commands
592 |
593 | -
594 | sizesens - mode of decoding of size-sensitive
595 | mnemonics (16/32 bits) like:
596 |
597 |
598 | 0 - PUSHA/PUSHAD
599 |
600 | 1 - PUSHAW/PUSHAD
601 |
602 | 2 - PUSHAW/PUSHA
603 |
604 | -
605 | symbolic - show symbolic addresses, requires
606 | Decodeaddress()
607 |
608 | Global flags that warn of potentially invalid commands:
609 |
610 | -
611 | farcalls - accept far calls, returns &
612 | addresses
613 |
614 | -
615 | decodevxd - decode VxD calls (Win95/98)
616 |
617 | -
618 | privileged - accept privileged commands
619 |
620 | -
621 | iocommand - accept I/O commands
622 |
623 | -
624 | badshift - accept shift out of range 1..31
625 |
626 | -
627 | extraprefix - accept superfluous prefixes
628 |
629 | -
630 | lockedbus - accept LOCK prefixes
631 |
632 | -
633 | stackalign - accept unaligned stack operations
634 |
635 | -
636 | iswindowsnt - when checking for dangerous
637 | commands, assume NT-based OS
638 |
639 | If Disasm() encounters potentially invalid command and corresponding flag
640 | is 0, it sets bit in disasm->warning and places warning message in disasm->comment.
641 |
642 |
643 |
Disassembleback
644 | Calculates address of assembler instruction that is n instructions (maximally
645 | 127) back from the instruction at specified pi. Returns address of found
646 | instruction. In case of error, it may be less than n instructions apart.
647 |
80x86 commands have variable length. Disassembleback uses heuristical
648 | methods to separate commands and in some (astoundingly rare!) cases may
649 | return invalid answer.
650 |
ulong Disassembleback(char *block,ulong base,ulong
651 | size,ulong ip,int n);
652 |
Parameters:
653 |
654 | -
655 | block - pointer to the copy of code;
656 |
657 | -
658 | base - address of first byte in the code block;
659 |
660 | -
661 | size - size of code block;
662 |
663 | -
664 | pi - address of current instruction;
665 |
666 | -
667 | n - number of instructions to walk back.
668 |
669 |
670 |
671 |
Disassembleforward
672 | Calculates address of assembler instruction that is n instructions forward
673 | from instruction at specified address. Returns address of found instruction.
674 | In case of error, it may be less than n instructions apart.
675 |
ulong Disassembleforward(char *block,ulong
676 | base,ulong size,ulong ip,int n,int usedec);
677 |
Parameters:
678 |
679 | -
680 | block - pointer to the copy of code;
681 |
682 | -
683 | base - address of first byte in the code block;
684 |
685 | -
686 | size - size of code block;
687 |
688 | -
689 | pi - address of current instruction;
690 |
691 | -
692 | n - number of instructions to walk forward.
693 |
694 |
695 |
696 |
Isfilling
697 | Function determines whether pointed instruction is a no-action command
698 | (equivalent to NOP) used by different compilers to fill the gap between
699 | procedures or data blocks to a specified aligned border. Returns length
700 | of filling command in bytes or 0 if command is not a recognized filling.
701 |
int Isfilling(ulong addr,char *data,ulong size,ulong
702 | align);
703 |
Parameters:
704 |
705 | -
706 | addr - address of the first byte of analyzed
707 | command;
708 |
709 | -
710 | data - pointer to the binary command;
711 |
712 | -
713 | size - size of data;
714 |
715 | -
716 | align - assumed alignment of the next non-filling
717 | command (power of 2), or 0 if alignment is not required.
718 |
719 |
720 |
721 |
Printfloat*
722 | functions
723 | These functions decode 4-, 8-, 10-byte floating point number or 8-byte
724 | 3DNow! operand into the text form to string s. They correctly decode all
725 | cases of NANs or INFs without triggering floating point exceptions. If
726 | operand is not a valid floating point number, functions print hexadecimal
727 | dump of the number. Return length of decoded string in bytes, not including
728 | terminal 0.
729 |
int Print3dnow(char *s,char *f);
730 |
int Printfloat10(char *s,long double ext);
731 |
int Printfloat4(char *s,float f);
732 |
int Printfloat8(char *s,double d);
733 |
734 |
735 |
Copyleft (C) 2001 Oleh Yuschuk
736 |
737 |
738 |
739 |
--------------------------------------------------------------------------------
/FindOC/disasm/asmserv.c:
--------------------------------------------------------------------------------
1 | // Free Disassembler and Assembler -- Command data and service routines
2 | //
3 | // Copyright (C) 2001 Oleh Yuschuk
4 | //
5 | // This program is free software; you can redistribute it and/or modify
6 | // it under the terms of the GNU General Public License as published by
7 | // the Free Software Foundation; either version 2 of the License, or
8 | // (at your option) any later version.
9 | //
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License
16 | // along with this program; if not, write to the Free Software
17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | //
19 | // 05.03.2002: Corrected error, FSTSW AX assembled with data size prefix
20 |
21 | #define STRICT
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | //#include
28 | #include
29 | #include
30 | #pragma hdrstop
31 |
32 | #include "disasm.h"
33 |
34 | const char *regname[3][9] = {
35 | { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8" },
36 | { "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R16" },
37 | { "EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI","R32" } };
38 |
39 | const char *segname[8] = {
40 | "ES","CS","SS","DS","FS","GS","SEG?","SEG?" };
41 |
42 | const char *sizename[11] = {
43 | "(0-BYTE)", "BYTE", "WORD", "(3-BYTE)",
44 | "DWORD", "(5-BYTE)", "FWORD", "(7-BYTE)",
45 | "QWORD", "(9-BYTE)", "TBYTE" };
46 |
47 | const t_addrdec addr16[8] = {
48 | { SEG_DS,"BX+SI" }, { SEG_DS,"BX+DI" },
49 | { SEG_SS,"BP+SI" }, { SEG_SS,"BP+DI" },
50 | { SEG_DS,"SI" }, { SEG_DS,"DI" },
51 | { SEG_SS,"BP" }, { SEG_DS,"BX" } };
52 |
53 | const t_addrdec addr32[8] = {
54 | { SEG_DS,"EAX" }, { SEG_DS,"ECX" },
55 | { SEG_DS,"EDX" }, { SEG_DS,"EBX" },
56 | { SEG_SS,"" }, { SEG_SS,"EBP" },
57 | { SEG_DS,"ESI" }, { SEG_DS,"EDI" } };
58 |
59 | const char *fpuname[9] = {
60 | "ST0","ST1","ST2","ST3","ST4","ST5","ST6","ST7","FPU" };
61 |
62 | const char *mmxname[9] = {
63 | "MM0","MM1","MM2","MM3","MM4","MM5","MM6","MM7","MMX" };
64 |
65 | const char *crname[9] = {
66 | "CR0","CR1","CR2","CR3","CR4","CR5","CR6","CR7","CRX" };
67 |
68 | const char *drname[9] = {
69 | "DR0","DR1","DR2","DR3","DR4","DR5","DR6","DR7","DRX" };
70 |
71 | // List of available processor commands with decoding, types of parameters and
72 | // other useful information. Last element has field mask=0. If mnemonic begins
73 | // with ampersand ('&'), its mnemonic decodes differently depending on operand
74 | // size (16 or 32 bits). If mnemonic begins with dollar ('$'), this mnemonic
75 | // depends on address size. Semicolon (':') separates 16-bit form from 32-bit,
76 | // asterisk ('*') will be substituted by either W (16), D (32) or none (16/32)
77 | // character. If command is of type C_MMX or C_NOW, or if type contains C_EXPL
78 | // (=0x01), Disassembler must specify explicit size of memory operand.
79 | const t_cmddata cmddata[] = {
80 | { 0x0000FF, 0x000090, 1,00, NNN,NNN,NNN, C_CMD+0, "NOP" },
81 | { 0x0000FE, 0x00008A, 1,WW, REG,MRG,NNN, C_CMD+0, "MOV" },
82 | { 0x0000F8, 0x000050, 1,00, RCM,NNN,NNN, C_PSH+0, "PUSH" },
83 | { 0x0000FE, 0x000088, 1,WW, MRG,REG,NNN, C_CMD+0, "MOV" },
84 | { 0x0000FF, 0x0000E8, 1,00, JOW,NNN,NNN, C_CAL+0, "CALL" },
85 | { 0x0000FD, 0x000068, 1,SS, IMM,NNN,NNN, C_PSH+0, "PUSH" },
86 | { 0x0000FF, 0x00008D, 1,00, REG,MMA,NNN, C_CMD+0, "LEA" },
87 | { 0x0000FF, 0x000074, 1,CC, JOB,NNN,NNN, C_JMC+0, "JE,JZ" },
88 | { 0x0000F8, 0x000058, 1,00, RCM,NNN,NNN, C_POP+0, "POP" },
89 | { 0x0038FC, 0x000080, 1,WS, MRG,IMM,NNN, C_CMD+1, "ADD" },
90 | { 0x0000FF, 0x000075, 1,CC, JOB,NNN,NNN, C_JMC+0, "JNZ,JNE" },
91 | { 0x0000FF, 0x0000EB, 1,00, JOB,NNN,NNN, C_JMP+0, "JMP" },
92 | { 0x0000FF, 0x0000E9, 1,00, JOW,NNN,NNN, C_JMP+0, "JMP" },
93 | { 0x0000FE, 0x000084, 1,WW, MRG,REG,NNN, C_CMD+0, "TEST" },
94 | { 0x0038FE, 0x0000C6, 1,WW, MRG,IMM,NNN, C_CMD+1, "MOV" },
95 | { 0x0000FE, 0x000032, 1,WW, REG,MRG,NNN, C_CMD+0, "XOR" },
96 | { 0x0000FE, 0x00003A, 1,WW, REG,MRG,NNN, C_CMD+0, "CMP" },
97 | { 0x0038FC, 0x003880, 1,WS, MRG,IMM,NNN, C_CMD+1, "CMP" },
98 | { 0x0038FF, 0x0010FF, 1,00, MRJ,NNN,NNN, C_CAL+0, "CALL" },
99 | { 0x0000FF, 0x0000C3, 1,00, PRN,NNN,NNN, C_RET+0, "RETN,RET" },
100 | { 0x0000F0, 0x0000B0, 1,W3, RCM,IMM,NNN, C_CMD+0, "MOV" },
101 | { 0x0000FE, 0x0000A0, 1,WW, RAC,IMA,NNN, C_CMD+0, "MOV" },
102 | { 0x00FFFF, 0x00840F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JE,JZ" },
103 | { 0x0000F8, 0x000040, 1,00, RCM,NNN,NNN, C_CMD+0, "INC" },
104 | { 0x0038FE, 0x0000F6, 1,WW, MRG,IMU,NNN, C_CMD+1, "TEST" },
105 | { 0x0000FE, 0x0000A2, 1,WW, IMA,RAC,NNN, C_CMD+0, "MOV" },
106 | { 0x0000FE, 0x00002A, 1,WW, REG,MRG,NNN, C_CMD+0, "SUB" },
107 | { 0x0000FF, 0x00007E, 1,CC, JOB,NNN,NNN, C_JMC+0, "JLE,JNG" },
108 | { 0x00FFFF, 0x00850F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JNZ,JNE" },
109 | { 0x0000FF, 0x0000C2, 1,00, IM2,PRN,NNN, C_RET+0, "RETN" },
110 | { 0x0038FF, 0x0030FF, 1,00, MRG,NNN,NNN, C_PSH+1, "PUSH" },
111 | { 0x0038FC, 0x000880, 1,WS, MRG,IMU,NNN, C_CMD+1, "OR" },
112 | { 0x0038FC, 0x002880, 1,WS, MRG,IMM,NNN, C_CMD+1, "SUB" },
113 | { 0x0000F8, 0x000048, 1,00, RCM,NNN,NNN, C_CMD+0, "DEC" },
114 | { 0x00FFFF, 0x00BF0F, 2,00, REG,MR2,NNN, C_CMD+1, "MOVSX" },
115 | { 0x0000FF, 0x00007C, 1,CC, JOB,NNN,NNN, C_JMC+0, "JL,JNGE" },
116 | { 0x0000FE, 0x000002, 1,WW, REG,MRG,NNN, C_CMD+0, "ADD" },
117 | { 0x0038FC, 0x002080, 1,WS, MRG,IMU,NNN, C_CMD+1, "AND" },
118 | { 0x0000FE, 0x00003C, 1,WW, RAC,IMM,NNN, C_CMD+0, "CMP" },
119 | { 0x0038FF, 0x0020FF, 1,00, MRJ,NNN,NNN, C_JMP+0, "JMP" },
120 | { 0x0038FE, 0x0010F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "NOT" },
121 | { 0x0038FE, 0x0028C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "SHR" },
122 | { 0x0000FE, 0x000038, 1,WW, MRG,REG,NNN, C_CMD+0, "CMP" },
123 | { 0x0000FF, 0x00007D, 1,CC, JOB,NNN,NNN, C_JMC+0, "JGE,JNL" },
124 | { 0x0000FF, 0x00007F, 1,CC, JOB,NNN,NNN, C_JMC+0, "JG,JNLE" },
125 | { 0x0038FE, 0x0020C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "SHL" },
126 | { 0x0000FE, 0x00001A, 1,WW, REG,MRG,NNN, C_CMD+0, "SBB" },
127 | { 0x0038FE, 0x0018F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "NEG" },
128 | { 0x0000FF, 0x0000C9, 1,00, NNN,NNN,NNN, C_CMD+0, "LEAVE" },
129 | { 0x0000FF, 0x000060, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "&PUSHA*" },
130 | { 0x0038FF, 0x00008F, 1,00, MRG,NNN,NNN, C_POP+1, "POP" },
131 | { 0x0000FF, 0x000061, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "&POPA*" },
132 | { 0x0000F8, 0x000090, 1,00, RAC,RCM,NNN, C_CMD+0, "XCHG" },
133 | { 0x0000FE, 0x000086, 1,WW, MRG,REG,NNN, C_CMD+0, "XCHG" },
134 | { 0x0000FE, 0x000000, 1,WW, MRG,REG,NNN, C_CMD+0, "ADD" },
135 | { 0x0000FE, 0x000010, 1,WW, MRG,REG,NNN, C_CMD+C_RARE+0, "ADC" },
136 | { 0x0000FE, 0x000012, 1,WW, REG,MRG,NNN, C_CMD+C_RARE+0, "ADC" },
137 | { 0x0000FE, 0x000020, 1,WW, MRG,REG,NNN, C_CMD+0, "AND" },
138 | { 0x0000FE, 0x000022, 1,WW, REG,MRG,NNN, C_CMD+0, "AND" },
139 | { 0x0000FE, 0x000008, 1,WW, MRG,REG,NNN, C_CMD+0, "OR" },
140 | { 0x0000FE, 0x00000A, 1,WW, REG,MRG,NNN, C_CMD+0, "OR" },
141 | { 0x0000FE, 0x000028, 1,WW, MRG,REG,NNN, C_CMD+0, "SUB" },
142 | { 0x0000FE, 0x000018, 1,WW, MRG,REG,NNN, C_CMD+C_RARE+0, "SBB" },
143 | { 0x0000FE, 0x000030, 1,WW, MRG,REG,NNN, C_CMD+0, "XOR" },
144 | { 0x0038FC, 0x001080, 1,WS, MRG,IMM,NNN, C_CMD+C_RARE+1, "ADC" },
145 | { 0x0038FC, 0x001880, 1,WS, MRG,IMM,NNN, C_CMD+C_RARE+1, "SBB" },
146 | { 0x0038FC, 0x003080, 1,WS, MRG,IMU,NNN, C_CMD+1, "XOR" },
147 | { 0x0000FE, 0x000004, 1,WW, RAC,IMM,NNN, C_CMD+0, "ADD" },
148 | { 0x0000FE, 0x000014, 1,WW, RAC,IMM,NNN, C_CMD+C_RARE+0, "ADC" },
149 | { 0x0000FE, 0x000024, 1,WW, RAC,IMU,NNN, C_CMD+0, "AND" },
150 | { 0x0000FE, 0x00000C, 1,WW, RAC,IMU,NNN, C_CMD+0, "OR" },
151 | { 0x0000FE, 0x00002C, 1,WW, RAC,IMM,NNN, C_CMD+0, "SUB" },
152 | { 0x0000FE, 0x00001C, 1,WW, RAC,IMM,NNN, C_CMD+C_RARE+0, "SBB" },
153 | { 0x0000FE, 0x000034, 1,WW, RAC,IMU,NNN, C_CMD+0, "XOR" },
154 | { 0x0038FE, 0x0000FE, 1,WW, MRG,NNN,NNN, C_CMD+1, "INC" },
155 | { 0x0038FE, 0x0008FE, 1,WW, MRG,NNN,NNN, C_CMD+1, "DEC" },
156 | { 0x0000FE, 0x0000A8, 1,WW, RAC,IMU,NNN, C_CMD+0, "TEST" },
157 | { 0x0038FE, 0x0020F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "MUL" },
158 | { 0x0038FE, 0x0028F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "IMUL" },
159 | { 0x00FFFF, 0x00AF0F, 2,00, REG,MRG,NNN, C_CMD+0, "IMUL" },
160 | { 0x0000FF, 0x00006B, 1,00, REG,MRG,IMX, C_CMD+C_RARE+0, "IMUL" },
161 | { 0x0000FF, 0x000069, 1,00, REG,MRG,IMM, C_CMD+C_RARE+0, "IMUL" },
162 | { 0x0038FE, 0x0030F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "DIV" },
163 | { 0x0038FE, 0x0038F6, 1,WW, MRG,NNN,NNN, C_CMD+1, "IDIV" },
164 | { 0x0000FF, 0x000098, 1,00, NNN,NNN,NNN, C_CMD+0, "&CBW:CWDE" },
165 | { 0x0000FF, 0x000099, 1,00, NNN,NNN,NNN, C_CMD+0, "&CWD:CDQ" },
166 | { 0x0038FE, 0x0000D0, 1,WW, MRG,C01,NNN, C_CMD+1, "ROL" },
167 | { 0x0038FE, 0x0008D0, 1,WW, MRG,C01,NNN, C_CMD+1, "ROR" },
168 | { 0x0038FE, 0x0010D0, 1,WW, MRG,C01,NNN, C_CMD+1, "RCL" },
169 | { 0x0038FE, 0x0018D0, 1,WW, MRG,C01,NNN, C_CMD+1, "RCR" },
170 | { 0x0038FE, 0x0020D0, 1,WW, MRG,C01,NNN, C_CMD+1, "SHL" },
171 | { 0x0038FE, 0x0028D0, 1,WW, MRG,C01,NNN, C_CMD+1, "SHR" },
172 | { 0x0038FE, 0x0038D0, 1,WW, MRG,C01,NNN, C_CMD+1, "SAR" },
173 | { 0x0038FE, 0x0000D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "ROL" },
174 | { 0x0038FE, 0x0008D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "ROR" },
175 | { 0x0038FE, 0x0010D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "RCL" },
176 | { 0x0038FE, 0x0018D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "RCR" },
177 | { 0x0038FE, 0x0020D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "SHL" },
178 | { 0x0038FE, 0x0028D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "SHR" },
179 | { 0x0038FE, 0x0038D2, 1,WW, MRG,RCL,NNN, C_CMD+1, "SAR" },
180 | { 0x0038FE, 0x0000C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "ROL" },
181 | { 0x0038FE, 0x0008C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "ROR" },
182 | { 0x0038FE, 0x0010C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "RCL" },
183 | { 0x0038FE, 0x0018C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "RCR" },
184 | { 0x0038FE, 0x0038C0, 1,WW, MRG,IMS,NNN, C_CMD+1, "SAR" },
185 | { 0x0000FF, 0x000070, 1,CC, JOB,NNN,NNN, C_JMC+0, "JO" },
186 | { 0x0000FF, 0x000071, 1,CC, JOB,NNN,NNN, C_JMC+0, "JNO" },
187 | { 0x0000FF, 0x000072, 1,CC, JOB,NNN,NNN, C_JMC+0, "JB,JC" },
188 | { 0x0000FF, 0x000073, 1,CC, JOB,NNN,NNN, C_JMC+0, "JNB,JNC" },
189 | { 0x0000FF, 0x000076, 1,CC, JOB,NNN,NNN, C_JMC+0, "JBE,JNA" },
190 | { 0x0000FF, 0x000077, 1,CC, JOB,NNN,NNN, C_JMC+0, "JA,JNBE" },
191 | { 0x0000FF, 0x000078, 1,CC, JOB,NNN,NNN, C_JMC+0, "JS" },
192 | { 0x0000FF, 0x000079, 1,CC, JOB,NNN,NNN, C_JMC+0, "JNS" },
193 | { 0x0000FF, 0x00007A, 1,CC, JOB,NNN,NNN, C_JMC+C_RARE+0, "JPE,JP" },
194 | { 0x0000FF, 0x00007B, 1,CC, JOB,NNN,NNN, C_JMC+C_RARE+0, "JPO,JNP" },
195 | { 0x0000FF, 0x0000E3, 1,00, JOB,NNN,NNN, C_JMC+C_RARE+0, "$JCXZ:JECXZ" },
196 | { 0x00FFFF, 0x00800F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JO" },
197 | { 0x00FFFF, 0x00810F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JNO" },
198 | { 0x00FFFF, 0x00820F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JB,JC" },
199 | { 0x00FFFF, 0x00830F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JNB,JNC" },
200 | { 0x00FFFF, 0x00860F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JBE,JNA" },
201 | { 0x00FFFF, 0x00870F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JA,JNBE" },
202 | { 0x00FFFF, 0x00880F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JS" },
203 | { 0x00FFFF, 0x00890F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JNS" },
204 | { 0x00FFFF, 0x008A0F, 2,CC, JOW,NNN,NNN, C_JMC+C_RARE+0, "JPE,JP" },
205 | { 0x00FFFF, 0x008B0F, 2,CC, JOW,NNN,NNN, C_JMC+C_RARE+0, "JPO,JNP" },
206 | { 0x00FFFF, 0x008C0F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JL,JNGE" },
207 | { 0x00FFFF, 0x008D0F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JGE,JNL" },
208 | { 0x00FFFF, 0x008E0F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JLE,JNG" },
209 | { 0x00FFFF, 0x008F0F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JG,JNLE" },
210 | { 0x0000FF, 0x0000F8, 1,00, NNN,NNN,NNN, C_CMD+0, "CLC" },
211 | { 0x0000FF, 0x0000F9, 1,00, NNN,NNN,NNN, C_CMD+0, "STC" },
212 | { 0x0000FF, 0x0000F5, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "CMC" },
213 | { 0x0000FF, 0x0000FC, 1,00, NNN,NNN,NNN, C_CMD+0, "CLD" },
214 | { 0x0000FF, 0x0000FD, 1,00, NNN,NNN,NNN, C_CMD+0, "STD" },
215 | { 0x0000FF, 0x0000FA, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "CLI" },
216 | { 0x0000FF, 0x0000FB, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "STI" },
217 | { 0x0000FF, 0x00008C, 1,FF, MRG,SGM,NNN, C_CMD+C_RARE+0, "MOV" },
218 | { 0x0000FF, 0x00008E, 1,FF, SGM,MRG,NNN, C_CMD+C_RARE+0, "MOV" },
219 | { 0x0000FE, 0x0000A6, 1,WW, MSO,MDE,NNN, C_CMD+1, "CMPS" },
220 | { 0x0000FE, 0x0000AC, 1,WW, MSO,NNN,NNN, C_CMD+1, "LODS" },
221 | { 0x0000FE, 0x0000A4, 1,WW, MDE,MSO,NNN, C_CMD+1, "MOVS" },
222 | { 0x0000FE, 0x0000AE, 1,WW, MDE,PAC,NNN, C_CMD+1, "SCAS" },
223 | { 0x0000FE, 0x0000AA, 1,WW, MDE,PAC,NNN, C_CMD+1, "STOS" },
224 | { 0x00FEFF, 0x00A4F3, 1,WW, MDE,MSO,PCX, C_REP+1, "REP MOVS" },
225 | { 0x00FEFF, 0x00ACF3, 1,WW, MSO,PAC,PCX, C_REP+C_RARE+1, "REP LODS" },
226 | { 0x00FEFF, 0x00AAF3, 1,WW, MDE,PAC,PCX, C_REP+1, "REP STOS" },
227 | { 0x00FEFF, 0x00A6F3, 1,WW, MDE,MSO,PCX, C_REP+1, "REPE CMPS" },
228 | { 0x00FEFF, 0x00AEF3, 1,WW, MDE,PAC,PCX, C_REP+1, "REPE SCAS" },
229 | { 0x00FEFF, 0x00A6F2, 1,WW, MDE,MSO,PCX, C_REP+1, "REPNE CMPS" },
230 | { 0x00FEFF, 0x00AEF2, 1,WW, MDE,PAC,PCX, C_REP+1, "REPNE SCAS" },
231 | { 0x0000FF, 0x0000EA, 1,00, JMF,NNN,NNN, C_JMP+C_RARE+0, "JMP" },
232 | { 0x0038FF, 0x0028FF, 1,00, MMS,NNN,NNN, C_JMP+C_RARE+1, "JMP" },
233 | { 0x0000FF, 0x00009A, 1,00, JMF,NNN,NNN, C_CAL+C_RARE+0, "CALL" },
234 | { 0x0038FF, 0x0018FF, 1,00, MMS,NNN,NNN, C_CAL+C_RARE+1, "CALL" },
235 | { 0x0000FF, 0x0000CB, 1,00, PRF,NNN,NNN, C_RET+C_RARE+0, "RETF" },
236 | { 0x0000FF, 0x0000CA, 1,00, IM2,PRF,NNN, C_RET+C_RARE+0, "RETF" },
237 | { 0x00FFFF, 0x00A40F, 2,00, MRG,REG,IMS, C_CMD+0, "SHLD" },
238 | { 0x00FFFF, 0x00AC0F, 2,00, MRG,REG,IMS, C_CMD+0, "SHRD" },
239 | { 0x00FFFF, 0x00A50F, 2,00, MRG,REG,RCL, C_CMD+0, "SHLD" },
240 | { 0x00FFFF, 0x00AD0F, 2,00, MRG,REG,RCL, C_CMD+0, "SHRD" },
241 | { 0x00F8FF, 0x00C80F, 2,00, RCM,NNN,NNN, C_CMD+C_RARE+0, "BSWAP" },
242 | { 0x00FEFF, 0x00C00F, 2,WW, MRG,REG,NNN, C_CMD+C_RARE+0, "XADD" },
243 | { 0x0000FF, 0x0000E2, 1,LL, JOB,PCX,NNN, C_JMC+0, "$LOOP*" },
244 | { 0x0000FF, 0x0000E1, 1,LL, JOB,PCX,NNN, C_JMC+0, "$LOOP*E" },
245 | { 0x0000FF, 0x0000E0, 1,LL, JOB,PCX,NNN, C_JMC+0, "$LOOP*NE" },
246 | { 0x0000FF, 0x0000C8, 1,00, IM2,IM1,NNN, C_CMD+0, "ENTER" },
247 | { 0x0000FE, 0x0000E4, 1,WP, RAC,IM1,NNN, C_CMD+C_RARE+0, "IN" },
248 | { 0x0000FE, 0x0000EC, 1,WP, RAC,RDX,NNN, C_CMD+C_RARE+0, "IN" },
249 | { 0x0000FE, 0x0000E6, 1,WP, IM1,RAC,NNN, C_CMD+C_RARE+0, "OUT" },
250 | { 0x0000FE, 0x0000EE, 1,WP, RDX,RAC,NNN, C_CMD+C_RARE+0, "OUT" },
251 | { 0x0000FE, 0x00006C, 1,WP, MDE,RDX,NNN, C_CMD+C_RARE+1, "INS" },
252 | { 0x0000FE, 0x00006E, 1,WP, RDX,MDE,NNN, C_CMD+C_RARE+1, "OUTS" },
253 | { 0x00FEFF, 0x006CF3, 1,WP, MDE,RDX,PCX, C_REP+C_RARE+1, "REP INS" },
254 | { 0x00FEFF, 0x006EF3, 1,WP, RDX,MDE,PCX, C_REP+C_RARE+1, "REP OUTS" },
255 | { 0x0000FF, 0x000037, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "AAA" },
256 | { 0x0000FF, 0x00003F, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "AAS" },
257 | { 0x00FFFF, 0x000AD4, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "AAM" },
258 | { 0x0000FF, 0x0000D4, 1,00, IM1,NNN,NNN, C_CMD+C_RARE+0, "AAM" },
259 | { 0x00FFFF, 0x000AD5, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "AAD" },
260 | { 0x0000FF, 0x0000D5, 1,00, IM1,NNN,NNN, C_CMD+C_RARE+0, "AAD" },
261 | { 0x0000FF, 0x000027, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "DAA" },
262 | { 0x0000FF, 0x00002F, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "DAS" },
263 | { 0x0000FF, 0x0000F4, 1,PR, NNN,NNN,NNN, C_PRI+C_RARE+0, "HLT" },
264 | { 0x0000FF, 0x00000E, 1,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH" },
265 | { 0x0000FF, 0x000016, 1,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH" },
266 | { 0x0000FF, 0x00001E, 1,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH" },
267 | { 0x0000FF, 0x000006, 1,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH" },
268 | { 0x00FFFF, 0x00A00F, 2,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH" },
269 | { 0x00FFFF, 0x00A80F, 2,00, SCM,NNN,NNN, C_PSH+C_RARE+0, "PUSH" },
270 | { 0x0000FF, 0x00001F, 1,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP" },
271 | { 0x0000FF, 0x000007, 1,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP" },
272 | { 0x0000FF, 0x000017, 1,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP" },
273 | { 0x00FFFF, 0x00A10F, 2,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP" },
274 | { 0x00FFFF, 0x00A90F, 2,00, SCM,NNN,NNN, C_POP+C_RARE+0, "POP" },
275 | { 0x0000FF, 0x0000D7, 1,00, MXL,NNN,NNN, C_CMD+C_RARE+1, "XLAT" },
276 | { 0x00FFFF, 0x00BE0F, 2,00, REG,MR1,NNN, C_CMD+1, "MOVSX" },
277 | { 0x00FFFF, 0x00B60F, 2,00, REG,MR1,NNN, C_CMD+1, "MOVZX" },
278 | { 0x00FFFF, 0x00B70F, 2,00, REG,MR2,NNN, C_CMD+1, "MOVZX" },
279 | { 0x0000FF, 0x00009B, 1,00, NNN,NNN,NNN, C_CMD+0, "WAIT" },
280 | { 0x0000FF, 0x00009F, 1,00, PAH,PFL,NNN, C_CMD+C_RARE+0, "LAHF" },
281 | { 0x0000FF, 0x00009E, 1,00, PFL,PAH,NNN, C_CMD+C_RARE+0, "SAHF" },
282 | { 0x0000FF, 0x00009C, 1,00, NNN,NNN,NNN, C_PSH+0, "&PUSHF*" },
283 | { 0x0000FF, 0x00009D, 1,00, NNN,NNN,NNN, C_FLG+0, "&POPF*" },
284 | { 0x0000FF, 0x0000CD, 1,00, IM1,NNN,NNN, C_CAL+C_RARE+0, "INT" },
285 | { 0x0000FF, 0x0000CC, 1,00, NNN,NNN,NNN, C_CAL+C_RARE+0, "INT3" },
286 | { 0x0000FF, 0x0000CE, 1,00, NNN,NNN,NNN, C_CAL+C_RARE+0, "INTO" },
287 | { 0x0000FF, 0x0000CF, 1,00, NNN,NNN,NNN, C_RTF+C_RARE+0, "&IRET*" },
288 | { 0x00FFFF, 0x00900F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETO" },
289 | { 0x00FFFF, 0x00910F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETNO" },
290 | { 0x00FFFF, 0x00920F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETB,SETC" },
291 | { 0x00FFFF, 0x00930F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETNB,SETNC" },
292 | { 0x00FFFF, 0x00940F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETE,SETZ" },
293 | { 0x00FFFF, 0x00950F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETNE,SETNZ" },
294 | { 0x00FFFF, 0x00960F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETBE,SETNA" },
295 | { 0x00FFFF, 0x00970F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETA,SETNBE" },
296 | { 0x00FFFF, 0x00980F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETS" },
297 | { 0x00FFFF, 0x00990F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETNS" },
298 | { 0x00FFFF, 0x009A0F, 2,CC, MR1,NNN,NNN, C_CMD+C_RARE+0, "SETPE,SETP" },
299 | { 0x00FFFF, 0x009B0F, 2,CC, MR1,NNN,NNN, C_CMD+C_RARE+0, "SETPO,SETNP" },
300 | { 0x00FFFF, 0x009C0F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETL,SETNGE" },
301 | { 0x00FFFF, 0x009D0F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETGE,SETNL" },
302 | { 0x00FFFF, 0x009E0F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETLE,SETNG" },
303 | { 0x00FFFF, 0x009F0F, 2,CC, MR1,NNN,NNN, C_CMD+0, "SETG,SETNLE" },
304 | { 0x38FFFF, 0x20BA0F, 2,00, MRG,IM1,NNN, C_CMD+C_RARE+1, "BT" },
305 | { 0x38FFFF, 0x28BA0F, 2,00, MRG,IM1,NNN, C_CMD+C_RARE+1, "BTS" },
306 | { 0x38FFFF, 0x30BA0F, 2,00, MRG,IM1,NNN, C_CMD+C_RARE+1, "BTR" },
307 | { 0x38FFFF, 0x38BA0F, 2,00, MRG,IM1,NNN, C_CMD+C_RARE+1, "BTC" },
308 | { 0x00FFFF, 0x00A30F, 2,00, MRG,REG,NNN, C_CMD+C_RARE+1, "BT" },
309 | { 0x00FFFF, 0x00AB0F, 2,00, MRG,REG,NNN, C_CMD+C_RARE+1, "BTS" },
310 | { 0x00FFFF, 0x00B30F, 2,00, MRG,REG,NNN, C_CMD+C_RARE+1, "BTR" },
311 | { 0x00FFFF, 0x00BB0F, 2,00, MRG,REG,NNN, C_CMD+C_RARE+1, "BTC" },
312 | { 0x0000FF, 0x0000C5, 1,00, REG,MML,NNN, C_CMD+C_RARE+0, "LDS" },
313 | { 0x0000FF, 0x0000C4, 1,00, REG,MML,NNN, C_CMD+C_RARE+0, "LES" },
314 | { 0x00FFFF, 0x00B40F, 2,00, REG,MML,NNN, C_CMD+C_RARE+0, "LFS" },
315 | { 0x00FFFF, 0x00B50F, 2,00, REG,MML,NNN, C_CMD+C_RARE+0, "LGS" },
316 | { 0x00FFFF, 0x00B20F, 2,00, REG,MML,NNN, C_CMD+C_RARE+0, "LSS" },
317 | { 0x0000FF, 0x000063, 1,00, MRG,REG,NNN, C_CMD+C_RARE+0, "ARPL" },
318 | { 0x0000FF, 0x000062, 1,00, REG,MMB,NNN, C_CMD+C_RARE+0, "BOUND" },
319 | { 0x00FFFF, 0x00BC0F, 2,00, REG,MRG,NNN, C_CMD+C_RARE+0, "BSF" },
320 | { 0x00FFFF, 0x00BD0F, 2,00, REG,MRG,NNN, C_CMD+C_RARE+0, "BSR" },
321 | { 0x00FFFF, 0x00060F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "CLTS" },
322 | { 0x00FFFF, 0x00400F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVO" },
323 | { 0x00FFFF, 0x00410F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVNO" },
324 | { 0x00FFFF, 0x00420F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVB,CMOVC" },
325 | { 0x00FFFF, 0x00430F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVNB,CMOVNC" },
326 | { 0x00FFFF, 0x00440F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVE,CMOVZ" },
327 | { 0x00FFFF, 0x00450F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVNE,CMOVNZ" },
328 | { 0x00FFFF, 0x00460F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVBE,CMOVNA" },
329 | { 0x00FFFF, 0x00470F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVA,CMOVNBE" },
330 | { 0x00FFFF, 0x00480F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVS" },
331 | { 0x00FFFF, 0x00490F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVNS" },
332 | { 0x00FFFF, 0x004A0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVPE,CMOVP" },
333 | { 0x00FFFF, 0x004B0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVPO,CMOVNP" },
334 | { 0x00FFFF, 0x004C0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVL,CMOVNGE" },
335 | { 0x00FFFF, 0x004D0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVGE,CMOVNL" },
336 | { 0x00FFFF, 0x004E0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVLE,CMOVNG" },
337 | { 0x00FFFF, 0x004F0F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVG,CMOVNLE" },
338 | { 0x00FEFF, 0x00B00F, 2,WW, MRG,REG,NNN, C_CMD+C_RARE+0, "CMPXCHG" },
339 | { 0x38FFFF, 0x08C70F, 2,00, MD8,NNN,NNN, C_CMD+C_RARE+1, "CMPXCHG8B" },
340 | { 0x00FFFF, 0x00A20F, 2,00, NNN,NNN,NNN, C_CMD+0, "CPUID" },
341 | { 0x00FFFF, 0x00080F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "INVD" },
342 | { 0x00FFFF, 0x00020F, 2,00, REG,MRG,NNN, C_CMD+C_RARE+0, "LAR" },
343 | { 0x00FFFF, 0x00030F, 2,00, REG,MRG,NNN, C_CMD+C_RARE+0, "LSL" },
344 | { 0x38FFFF, 0x38010F, 2,PR, MR1,NNN,NNN, C_CMD+C_RARE+0, "INVLPG" },
345 | { 0x00FFFF, 0x00090F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "WBINVD" },
346 | { 0x38FFFF, 0x10010F, 2,PR, MM6,NNN,NNN, C_CMD+C_RARE+0, "LGDT" },
347 | { 0x38FFFF, 0x00010F, 2,00, MM6,NNN,NNN, C_CMD+C_RARE+0, "SGDT" },
348 | { 0x38FFFF, 0x18010F, 2,PR, MM6,NNN,NNN, C_CMD+C_RARE+0, "LIDT" },
349 | { 0x38FFFF, 0x08010F, 2,00, MM6,NNN,NNN, C_CMD+C_RARE+0, "SIDT" },
350 | { 0x38FFFF, 0x10000F, 2,PR, MR2,NNN,NNN, C_CMD+C_RARE+0, "LLDT" },
351 | { 0x38FFFF, 0x00000F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "SLDT" },
352 | { 0x38FFFF, 0x18000F, 2,PR, MR2,NNN,NNN, C_CMD+C_RARE+0, "LTR" },
353 | { 0x38FFFF, 0x08000F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "STR" },
354 | { 0x38FFFF, 0x30010F, 2,PR, MR2,NNN,NNN, C_CMD+C_RARE+0, "LMSW" },
355 | { 0x38FFFF, 0x20010F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "SMSW" },
356 | { 0x38FFFF, 0x20000F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "VERR" },
357 | { 0x38FFFF, 0x28000F, 2,00, MR2,NNN,NNN, C_CMD+C_RARE+0, "VERW" },
358 | { 0xC0FFFF, 0xC0220F, 2,PR, CRX,RR4,NNN, C_CMD+C_RARE+0, "MOV" },
359 | { 0xC0FFFF, 0xC0200F, 2,00, RR4,CRX,NNN, C_CMD+C_RARE+0, "MOV" },
360 | { 0xC0FFFF, 0xC0230F, 2,PR, DRX,RR4,NNN, C_CMD+C_RARE+0, "MOV" },
361 | { 0xC0FFFF, 0xC0210F, 2,PR, RR4,DRX,NNN, C_CMD+C_RARE+0, "MOV" },
362 | { 0x00FFFF, 0x00310F, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "RDTSC" },
363 | { 0x00FFFF, 0x00320F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "RDMSR" },
364 | { 0x00FFFF, 0x00300F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "WRMSR" },
365 | { 0x00FFFF, 0x00330F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "RDPMC" },
366 | { 0x00FFFF, 0x00AA0F, 2,PR, NNN,NNN,NNN, C_RTF+C_RARE+0, "RSM" },
367 | { 0x00FFFF, 0x000B0F, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "UD2" },
368 | { 0x00FFFF, 0x00340F, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "SYSENTER" },
369 | { 0x00FFFF, 0x00350F, 2,PR, NNN,NNN,NNN, C_CMD+C_RARE+0, "SYSEXIT" },
370 | { 0x0000FF, 0x0000D6, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "SALC" },
371 | // FPU instructions. Never change the order of instructions!
372 | { 0x00FFFF, 0x00F0D9, 2,00, PS0,NNN,NNN, C_FLT+0, "F2XM1" },
373 | { 0x00FFFF, 0x00E0D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FCHS" },
374 | { 0x00FFFF, 0x00E1D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FABS" },
375 | { 0x00FFFF, 0x00E2DB, 2,00, NNN,NNN,NNN, C_FLT+0, "FCLEX" },
376 | { 0x00FFFF, 0x00E3DB, 2,00, NNN,NNN,NNN, C_FLT+0, "FINIT" },
377 | { 0x00FFFF, 0x00F6D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FDECSTP" },
378 | { 0x00FFFF, 0x00F7D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FINCSTP" },
379 | { 0x00FFFF, 0x00E4D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FTST" },
380 | { 0x00FFFF, 0x00FAD9, 2,00, PS0,NNN,NNN, C_FLT+0, "FSQRT" },
381 | { 0x00FFFF, 0x00FED9, 2,00, PS0,NNN,NNN, C_FLT+0, "FSIN" },
382 | { 0x00FFFF, 0x00FFD9, 2,00, PS0,NNN,NNN, C_FLT+0, "FCOS" },
383 | { 0x00FFFF, 0x00FBD9, 2,00, PS0,NNN,NNN, C_FLT+0, "FSINCOS" },
384 | { 0x00FFFF, 0x00F2D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FPTAN" },
385 | { 0x00FFFF, 0x00F3D9, 2,00, PS0,PS1,NNN, C_FLT+0, "FPATAN" },
386 | { 0x00FFFF, 0x00F8D9, 2,00, PS1,PS0,NNN, C_FLT+0, "FPREM" },
387 | { 0x00FFFF, 0x00F5D9, 2,00, PS1,PS0,NNN, C_FLT+0, "FPREM1" },
388 | { 0x00FFFF, 0x00F1D9, 2,00, PS0,PS1,NNN, C_FLT+0, "FYL2X" },
389 | { 0x00FFFF, 0x00F9D9, 2,00, PS0,PS1,NNN, C_FLT+0, "FYL2XP1" },
390 | { 0x00FFFF, 0x00FCD9, 2,00, PS0,NNN,NNN, C_FLT+0, "FRNDINT" },
391 | { 0x00FFFF, 0x00E8D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLD1" },
392 | { 0x00FFFF, 0x00E9D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDL2T" },
393 | { 0x00FFFF, 0x00EAD9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDL2E" },
394 | { 0x00FFFF, 0x00EBD9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDPI" },
395 | { 0x00FFFF, 0x00ECD9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDLG2" },
396 | { 0x00FFFF, 0x00EDD9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDLN2" },
397 | { 0x00FFFF, 0x00EED9, 2,00, NNN,NNN,NNN, C_FLT+0, "FLDZ" },
398 | { 0x00FFFF, 0x00FDD9, 2,00, PS0,PS1,NNN, C_FLT+0, "FSCALE" },
399 | { 0x00FFFF, 0x00D0D9, 2,00, NNN,NNN,NNN, C_FLT+0, "FNOP" },
400 | { 0x00FFFF, 0x00E0DF, 2,FF, RAX,NNN,NNN, C_FLT+0, "FSTSW" },
401 | { 0x00FFFF, 0x00E5D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FXAM" },
402 | { 0x00FFFF, 0x00F4D9, 2,00, PS0,NNN,NNN, C_FLT+0, "FXTRACT" },
403 | { 0x00FFFF, 0x00D9DE, 2,00, PS0,PS1,NNN, C_FLT+0, "FCOMPP" },
404 | { 0x00FFFF, 0x00E9DA, 2,00, PS0,PS1,NNN, C_FLT+0, "FUCOMPP" },
405 | { 0x00F8FF, 0x00C0DD, 2,00, RST,NNN,NNN, C_FLT+0, "FFREE" },
406 | { 0x00F8FF, 0x00C0DA, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVB" },
407 | { 0x00F8FF, 0x00C8DA, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVE" },
408 | { 0x00F8FF, 0x00D0DA, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVBE" },
409 | { 0x00F8FF, 0x00D8DA, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVU" },
410 | { 0x00F8FF, 0x00C0DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVNB" },
411 | { 0x00F8FF, 0x00C8DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVNE" },
412 | { 0x00F8FF, 0x00D0DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVNBE" },
413 | { 0x00F8FF, 0x00D8DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCMOVNU" },
414 | { 0x00F8FF, 0x00F0DB, 2,00, RS0,RST,NNN, C_FLT+0, "FCOMI" },
415 | { 0x00F8FF, 0x00F0DF, 2,00, RS0,RST,NNN, C_FLT+0, "FCOMIP" },
416 | { 0x00F8FF, 0x00E8DB, 2,00, RS0,RST,NNN, C_FLT+0, "FUCOMI" },
417 | { 0x00F8FF, 0x00E8DF, 2,00, RS0,RST,NNN, C_FLT+0, "FUCOMIP" },
418 | { 0x00F8FF, 0x00C0D8, 2,00, RS0,RST,NNN, C_FLT+0, "FADD" },
419 | { 0x00F8FF, 0x00C0DC, 2,00, RST,RS0,NNN, C_FLT+0, "FADD" },
420 | { 0x00F8FF, 0x00C0DE, 2,00, RST,RS0,NNN, C_FLT+0, "FADDP" },
421 | { 0x00F8FF, 0x00E0D8, 2,00, RS0,RST,NNN, C_FLT+0, "FSUB" },
422 | { 0x00F8FF, 0x00E8DC, 2,00, RST,RS0,NNN, C_FLT+0, "FSUB" },
423 | { 0x00F8FF, 0x00E8DE, 2,00, RST,RS0,NNN, C_FLT+0, "FSUBP" },
424 | { 0x00F8FF, 0x00E8D8, 2,00, RS0,RST,NNN, C_FLT+0, "FSUBR" },
425 | { 0x00F8FF, 0x00E0DC, 2,00, RST,RS0,NNN, C_FLT+0, "FSUBR" },
426 | { 0x00F8FF, 0x00E0DE, 2,00, RST,RS0,NNN, C_FLT+0, "FSUBRP" },
427 | { 0x00F8FF, 0x00C8D8, 2,00, RS0,RST,NNN, C_FLT+0, "FMUL" },
428 | { 0x00F8FF, 0x00C8DC, 2,00, RST,RS0,NNN, C_FLT+0, "FMUL" },
429 | { 0x00F8FF, 0x00C8DE, 2,00, RST,RS0,NNN, C_FLT+0, "FMULP" },
430 | { 0x00F8FF, 0x00D0D8, 2,00, RST,PS0,NNN, C_FLT+0, "FCOM" },
431 | { 0x00F8FF, 0x00D8D8, 2,00, RST,PS0,NNN, C_FLT+0, "FCOMP" },
432 | { 0x00F8FF, 0x00E0DD, 2,00, RST,PS0,NNN, C_FLT+0, "FUCOM" },
433 | { 0x00F8FF, 0x00E8DD, 2,00, RST,PS0,NNN, C_FLT+0, "FUCOMP" },
434 | { 0x00F8FF, 0x00F0D8, 2,00, RS0,RST,NNN, C_FLT+0, "FDIV" },
435 | { 0x00F8FF, 0x00F8DC, 2,00, RST,RS0,NNN, C_FLT+0, "FDIV" },
436 | { 0x00F8FF, 0x00F8DE, 2,00, RST,RS0,NNN, C_FLT+0, "FDIVP" },
437 | { 0x00F8FF, 0x00F8D8, 2,00, RS0,RST,NNN, C_FLT+0, "FDIVR" },
438 | { 0x00F8FF, 0x00F0DC, 2,00, RST,RS0,NNN, C_FLT+0, "FDIVR" },
439 | { 0x00F8FF, 0x00F0DE, 2,00, RST,RS0,NNN, C_FLT+0, "FDIVRP" },
440 | { 0x00F8FF, 0x00C0D9, 2,00, RST,NNN,NNN, C_FLT+0, "FLD" },
441 | { 0x00F8FF, 0x00D0DD, 2,00, RST,PS0,NNN, C_FLT+0, "FST" },
442 | { 0x00F8FF, 0x00D8DD, 2,00, RST,PS0,NNN, C_FLT+0, "FSTP" },
443 | { 0x00F8FF, 0x00C8D9, 2,00, RST,PS0,NNN, C_FLT+0, "FXCH" },
444 | { 0x0038FF, 0x0000D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FADD" },
445 | { 0x0038FF, 0x0000DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FADD" },
446 | { 0x0038FF, 0x0000DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FIADD" },
447 | { 0x0038FF, 0x0000DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FIADD" },
448 | { 0x0038FF, 0x0020D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FSUB" },
449 | { 0x0038FF, 0x0020DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FSUB" },
450 | { 0x0038FF, 0x0020DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FISUB" },
451 | { 0x0038FF, 0x0020DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FISUB" },
452 | { 0x0038FF, 0x0028D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FSUBR" },
453 | { 0x0038FF, 0x0028DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FSUBR" },
454 | { 0x0038FF, 0x0028DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FISUBR" },
455 | { 0x0038FF, 0x0028DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FISUBR" },
456 | { 0x0038FF, 0x0008D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FMUL" },
457 | { 0x0038FF, 0x0008DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FMUL" },
458 | { 0x0038FF, 0x0008DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FIMUL" },
459 | { 0x0038FF, 0x0008DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FIMUL" },
460 | { 0x0038FF, 0x0010D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FCOM" },
461 | { 0x0038FF, 0x0010DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FCOM" },
462 | { 0x0038FF, 0x0018D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FCOMP" },
463 | { 0x0038FF, 0x0018DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FCOMP" },
464 | { 0x0038FF, 0x0030D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FDIV" },
465 | { 0x0038FF, 0x0030DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FDIV" },
466 | { 0x0038FF, 0x0030DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FIDIV" },
467 | { 0x0038FF, 0x0030DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FIDIV" },
468 | { 0x0038FF, 0x0038D8, 1,00, MF4,PS0,NNN, C_FLT+1, "FDIVR" },
469 | { 0x0038FF, 0x0038DC, 1,00, MF8,PS0,NNN, C_FLT+1, "FDIVR" },
470 | { 0x0038FF, 0x0038DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FIDIVR" },
471 | { 0x0038FF, 0x0038DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FIDIVR" },
472 | { 0x0038FF, 0x0020DF, 1,00, MDA,NNN,NNN, C_FLT+C_RARE+1, "FBLD" },
473 | { 0x0038FF, 0x0030DF, 1,00, MDA,PS0,NNN, C_FLT+C_RARE+1, "FBSTP" },
474 | { 0x0038FF, 0x0010DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FICOM" },
475 | { 0x0038FF, 0x0010DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FICOM" },
476 | { 0x0038FF, 0x0018DE, 1,00, MD2,PS0,NNN, C_FLT+1, "FICOMP" },
477 | { 0x0038FF, 0x0018DA, 1,00, MD4,PS0,NNN, C_FLT+1, "FICOMP" },
478 | { 0x0038FF, 0x0000DF, 1,00, MD2,NNN,NNN, C_FLT+1, "FILD" },
479 | { 0x0038FF, 0x0000DB, 1,00, MD4,NNN,NNN, C_FLT+1, "FILD" },
480 | { 0x0038FF, 0x0028DF, 1,00, MD8,NNN,NNN, C_FLT+1, "FILD" },
481 | { 0x0038FF, 0x0010DF, 1,00, MD2,PS0,NNN, C_FLT+1, "FIST" },
482 | { 0x0038FF, 0x0010DB, 1,00, MD4,PS0,NNN, C_FLT+1, "FIST" },
483 | { 0x0038FF, 0x0018DF, 1,00, MD2,PS0,NNN, C_FLT+1, "FISTP" },
484 | { 0x0038FF, 0x0018DB, 1,00, MD4,PS0,NNN, C_FLT+1, "FISTP" },
485 | { 0x0038FF, 0x0038DF, 1,00, MD8,PS0,NNN, C_FLT+1, "FISTP" },
486 | { 0x0038FF, 0x0000D9, 1,00, MF4,NNN,NNN, C_FLT+1, "FLD" },
487 | { 0x0038FF, 0x0000DD, 1,00, MF8,NNN,NNN, C_FLT+1, "FLD" },
488 | { 0x0038FF, 0x0028DB, 1,00, MFA,NNN,NNN, C_FLT+1, "FLD" },
489 | { 0x0038FF, 0x0010D9, 1,00, MF4,PS0,NNN, C_FLT+1, "FST" },
490 | { 0x0038FF, 0x0010DD, 1,00, MF8,PS0,NNN, C_FLT+1, "FST" },
491 | { 0x0038FF, 0x0018D9, 1,00, MF4,PS0,NNN, C_FLT+1, "FSTP" },
492 | { 0x0038FF, 0x0018DD, 1,00, MF8,PS0,NNN, C_FLT+1, "FSTP" },
493 | { 0x0038FF, 0x0038DB, 1,00, MFA,PS0,NNN, C_FLT+1, "FSTP" },
494 | { 0x0038FF, 0x0028D9, 1,00, MB2,NNN,NNN, C_FLT+0, "FLDCW" },
495 | { 0x0038FF, 0x0038D9, 1,00, MB2,NNN,NNN, C_FLT+0, "FSTCW" },
496 | { 0x0038FF, 0x0020D9, 1,00, MFE,NNN,NNN, C_FLT+0, "FLDENV" },
497 | { 0x0038FF, 0x0030D9, 1,00, MFE,NNN,NNN, C_FLT+0, "FSTENV" },
498 | { 0x0038FF, 0x0020DD, 1,00, MFS,NNN,NNN, C_FLT+0, "FRSTOR" },
499 | { 0x0038FF, 0x0030DD, 1,00, MFS,NNN,NNN, C_FLT+0, "FSAVE" },
500 | { 0x0038FF, 0x0038DD, 1,00, MB2,NNN,NNN, C_FLT+0, "FSTSW" },
501 | { 0x38FFFF, 0x08AE0F, 2,00, MFX,NNN,NNN, C_FLT+0, "FXRSTOR" },
502 | { 0x38FFFF, 0x00AE0F, 2,00, MFX,NNN,NNN, C_FLT+0, "FXSAVE" },
503 | { 0x00FFFF, 0x00E0DB, 2,00, NNN,NNN,NNN, C_FLT+0, "FENI" },
504 | { 0x00FFFF, 0x00E1DB, 2,00, NNN,NNN,NNN, C_FLT+0, "FDISI" },
505 | // MMX instructions. Length of MMX operand fields (in bytes) is added to the
506 | // type, length of 0 means 8-byte MMX operand.
507 | { 0x00FFFF, 0x00770F, 2,00, NNN,NNN,NNN, C_MMX+0, "EMMS" },
508 | { 0x00FFFF, 0x006E0F, 2,00, RMX,MR4,NNN, C_MMX+0, "MOVD" },
509 | { 0x00FFFF, 0x007E0F, 2,00, MR4,RMX,NNN, C_MMX+0, "MOVD" },
510 | { 0x00FFFF, 0x006F0F, 2,00, RMX,MR8,NNN, C_MMX+0, "MOVQ" },
511 | { 0x00FFFF, 0x007F0F, 2,00, MR8,RMX,NNN, C_MMX+0, "MOVQ" },
512 | { 0x00FFFF, 0x00630F, 2,00, RMX,MR8,NNN, C_MMX+2, "PACKSSWB" },
513 | { 0x00FFFF, 0x006B0F, 2,00, RMX,MR8,NNN, C_MMX+4, "PACKSSDW" },
514 | { 0x00FFFF, 0x00670F, 2,00, RMX,MR8,NNN, C_MMX+2, "PACKUSWB" },
515 | { 0x00FFFF, 0x00FC0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PADDB" },
516 | { 0x00FFFF, 0x00FD0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PADDW" },
517 | { 0x00FFFF, 0x00FE0F, 2,00, RMX,MR8,NNN, C_MMX+4, "PADDD" },
518 | { 0x00FFFF, 0x00F80F, 2,00, RMX,MR8,NNN, C_MMX+1, "PSUBB" },
519 | { 0x00FFFF, 0x00F90F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSUBW" },
520 | { 0x00FFFF, 0x00FA0F, 2,00, RMX,MR8,NNN, C_MMX+4, "PSUBD" },
521 | { 0x00FFFF, 0x00EC0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PADDSB" },
522 | { 0x00FFFF, 0x00ED0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PADDSW" },
523 | { 0x00FFFF, 0x00E80F, 2,00, RMX,MR8,NNN, C_MMX+1, "PSUBSB" },
524 | { 0x00FFFF, 0x00E90F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSUBSW" },
525 | { 0x00FFFF, 0x00DC0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PADDUSB" },
526 | { 0x00FFFF, 0x00DD0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PADDUSW" },
527 | { 0x00FFFF, 0x00D80F, 2,00, RMX,MR8,NNN, C_MMX+1, "PSUBUSB" },
528 | { 0x00FFFF, 0x00D90F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSUBUSW" },
529 | { 0x00FFFF, 0x00DB0F, 2,00, RMX,MR8,NNN, C_MMX+0, "PAND" },
530 | { 0x00FFFF, 0x00DF0F, 2,00, RMX,MR8,NNN, C_MMX+0, "PANDN" },
531 | { 0x00FFFF, 0x00740F, 2,00, RMX,MR8,NNN, C_MMX+1, "PCMPEQB" },
532 | { 0x00FFFF, 0x00750F, 2,00, RMX,MR8,NNN, C_MMX+2, "PCMPEQW" },
533 | { 0x00FFFF, 0x00760F, 2,00, RMX,MR8,NNN, C_MMX+4, "PCMPEQD" },
534 | { 0x00FFFF, 0x00640F, 2,00, RMX,MR8,NNN, C_MMX+1, "PCMPGTB" },
535 | { 0x00FFFF, 0x00650F, 2,00, RMX,MR8,NNN, C_MMX+2, "PCMPGTW" },
536 | { 0x00FFFF, 0x00660F, 2,00, RMX,MR8,NNN, C_MMX+4, "PCMPGTD" },
537 | { 0x00FFFF, 0x00F50F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMADDWD" },
538 | { 0x00FFFF, 0x00E50F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMULHW" },
539 | { 0x00FFFF, 0x00D50F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMULLW" },
540 | { 0x00FFFF, 0x00EB0F, 2,00, RMX,MR8,NNN, C_MMX+0, "POR" },
541 | { 0x00FFFF, 0x00F10F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSLLW" },
542 | { 0x38FFFF, 0x30710F, 2,00, MR8,IM1,NNN, C_MMX+2, "PSLLW" },
543 | { 0x00FFFF, 0x00F20F, 2,00, RMX,MR8,NNN, C_MMX+4, "PSLLD" },
544 | { 0x38FFFF, 0x30720F, 2,00, MR8,IM1,NNN, C_MMX+4, "PSLLD" },
545 | { 0x00FFFF, 0x00F30F, 2,00, RMX,MR8,NNN, C_MMX+0, "PSLLQ" },
546 | { 0x38FFFF, 0x30730F, 2,00, MR8,IM1,NNN, C_MMX+0, "PSLLQ" },
547 | { 0x00FFFF, 0x00E10F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSRAW" },
548 | { 0x38FFFF, 0x20710F, 2,00, MR8,IM1,NNN, C_MMX+2, "PSRAW" },
549 | { 0x00FFFF, 0x00E20F, 2,00, RMX,MR8,NNN, C_MMX+4, "PSRAD" },
550 | { 0x38FFFF, 0x20720F, 2,00, MR8,IM1,NNN, C_MMX+4, "PSRAD" },
551 | { 0x00FFFF, 0x00D10F, 2,00, RMX,MR8,NNN, C_MMX+2, "PSRLW" },
552 | { 0x38FFFF, 0x10710F, 2,00, MR8,IM1,NNN, C_MMX+2, "PSRLW" },
553 | { 0x00FFFF, 0x00D20F, 2,00, RMX,MR8,NNN, C_MMX+4, "PSRLD" },
554 | { 0x38FFFF, 0x10720F, 2,00, MR8,IM1,NNN, C_MMX+4, "PSRLD" },
555 | { 0x00FFFF, 0x00D30F, 2,00, RMX,MR8,NNN, C_MMX+0, "PSRLQ" },
556 | { 0x38FFFF, 0x10730F, 2,00, MR8,IM1,NNN, C_MMX+0, "PSRLQ" },
557 | { 0x00FFFF, 0x00680F, 2,00, RMX,MR8,NNN, C_MMX+1, "PUNPCKHBW" },
558 | { 0x00FFFF, 0x00690F, 2,00, RMX,MR8,NNN, C_MMX+2, "PUNPCKHWD" },
559 | { 0x00FFFF, 0x006A0F, 2,00, RMX,MR8,NNN, C_MMX+4, "PUNPCKHDQ" },
560 | { 0x00FFFF, 0x00600F, 2,00, RMX,MR8,NNN, C_MMX+1, "PUNPCKLBW" },
561 | { 0x00FFFF, 0x00610F, 2,00, RMX,MR8,NNN, C_MMX+2, "PUNPCKLWD" },
562 | { 0x00FFFF, 0x00620F, 2,00, RMX,MR8,NNN, C_MMX+4, "PUNPCKLDQ" },
563 | { 0x00FFFF, 0x00EF0F, 2,00, RMX,MR8,NNN, C_MMX+0, "PXOR" },
564 | // AMD extentions to MMX command set (including Athlon/PIII extentions).
565 | { 0x00FFFF, 0x000E0F, 2,00, NNN,NNN,NNN, C_MMX+0, "FEMMS" },
566 | { 0x38FFFF, 0x000D0F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCH" },
567 | { 0x38FFFF, 0x080D0F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHW" },
568 | { 0x00FFFF, 0x00F70F, 2,00, RMX,RR8,PDI, C_MMX+1, "MASKMOVQ" },
569 | { 0x00FFFF, 0x00E70F, 2,00, MD8,RMX,NNN, C_MMX+0, "MOVNTQ" },
570 | { 0x00FFFF, 0x00E00F, 2,00, RMX,MR8,NNN, C_MMX+1, "PAVGB" },
571 | { 0x00FFFF, 0x00E30F, 2,00, RMX,MR8,NNN, C_MMX+2, "PAVGW" },
572 | { 0x00FFFF, 0x00C50F, 2,00, RR4,RMX,IM1, C_MMX+2, "PEXTRW" },
573 | { 0x00FFFF, 0x00C40F, 2,00, RMX,MR2,IM1, C_MMX+2, "PINSRW" },
574 | { 0x00FFFF, 0x00EE0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMAXSW" },
575 | { 0x00FFFF, 0x00DE0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PMAXUB" },
576 | { 0x00FFFF, 0x00EA0F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMINSW" },
577 | { 0x00FFFF, 0x00DA0F, 2,00, RMX,MR8,NNN, C_MMX+1, "PMINUB" },
578 | { 0x00FFFF, 0x00D70F, 2,00, RG4,RR8,NNN, C_MMX+1, "PMOVMSKB" },
579 | { 0x00FFFF, 0x00E40F, 2,00, RMX,MR8,NNN, C_MMX+2, "PMULHUW" },
580 | { 0x38FFFF, 0x00180F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHNTA" },
581 | { 0x38FFFF, 0x08180F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHT0" },
582 | { 0x38FFFF, 0x10180F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHT1" },
583 | { 0x38FFFF, 0x18180F, 2,00, MD8,NNN,NNN, C_MMX+0, "PREFETCHT2" },
584 | { 0x00FFFF, 0x00F60F, 2,00, RMX,MR8,NNN, C_MMX+1, "PSADBW" },
585 | { 0x00FFFF, 0x00700F, 2,00, RMX,MR8,IM1, C_MMX+2, "PSHUFW" },
586 | { 0xFFFFFF, 0xF8AE0F, 2,00, NNN,NNN,NNN, C_MMX+0, "SFENCE" },
587 | // AMD 3DNow! instructions (including Athlon extentions).
588 | { 0x00FFFF, 0xBF0F0F, 2,00, RMX,MR8,NNN, C_NOW+1, "PAVGUSB" },
589 | { 0x00FFFF, 0x9E0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFADD" },
590 | { 0x00FFFF, 0x9A0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFSUB" },
591 | { 0x00FFFF, 0xAA0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFSUBR" },
592 | { 0x00FFFF, 0xAE0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFACC" },
593 | { 0x00FFFF, 0x900F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PFCMPGE" },
594 | { 0x00FFFF, 0xA00F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PFCMPGT" },
595 | { 0x00FFFF, 0xB00F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PFCMPEQ" },
596 | { 0x00FFFF, 0x940F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFMIN" },
597 | { 0x00FFFF, 0xA40F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFMAX" },
598 | { 0x00FFFF, 0x0D0F0F, 2,00, R3D,MR8,NNN, C_NOW+4, "PI2FD" },
599 | { 0x00FFFF, 0x1D0F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PF2ID" },
600 | { 0x00FFFF, 0x960F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRCP" },
601 | { 0x00FFFF, 0x970F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRSQRT" },
602 | { 0x00FFFF, 0xB40F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFMUL" },
603 | { 0x00FFFF, 0xA60F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRCPIT1" },
604 | { 0x00FFFF, 0xA70F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRSQIT1" },
605 | { 0x00FFFF, 0xB60F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFRCPIT2" },
606 | { 0x00FFFF, 0xB70F0F, 2,00, RMX,MR8,NNN, C_NOW+2, "PMULHRW" },
607 | { 0x00FFFF, 0x1C0F0F, 2,00, RMX,MRD,NNN, C_NOW+4, "PF2IW" },
608 | { 0x00FFFF, 0x8A0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFNACC" },
609 | { 0x00FFFF, 0x8E0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PFPNACC" },
610 | { 0x00FFFF, 0x0C0F0F, 2,00, R3D,MR8,NNN, C_NOW+4, "PI2FW" },
611 | { 0x00FFFF, 0xBB0F0F, 2,00, R3D,MRD,NNN, C_NOW+4, "PSWAPD" },
612 | // Some alternative mnemonics for Assembler, not used by Disassembler (so
613 | // implicit pseudooperands are not marked).
614 | { 0x0000FF, 0x0000A6, 1,00, NNN,NNN,NNN, C_CMD+0, "CMPSB" },
615 | { 0x00FFFF, 0x00A766, 2,00, NNN,NNN,NNN, C_CMD+0, "CMPSW" },
616 | { 0x0000FF, 0x0000A7, 1,00, NNN,NNN,NNN, C_CMD+0, "CMPSD" },
617 | { 0x0000FF, 0x0000AC, 1,00, NNN,NNN,NNN, C_CMD+0, "LODSB" },
618 | { 0x00FFFF, 0x00AD66, 2,00, NNN,NNN,NNN, C_CMD+0, "LODSW" },
619 | { 0x0000FF, 0x0000AD, 1,00, NNN,NNN,NNN, C_CMD+0, "LODSD" },
620 | { 0x0000FF, 0x0000A4, 1,00, NNN,NNN,NNN, C_CMD+0, "MOVSB" },
621 | { 0x00FFFF, 0x00A566, 2,00, NNN,NNN,NNN, C_CMD+0, "MOVSW" },
622 | { 0x0000FF, 0x0000A5, 1,00, NNN,NNN,NNN, C_CMD+0, "MOVSD" },
623 | { 0x0000FF, 0x0000AE, 1,00, NNN,NNN,NNN, C_CMD+0, "SCASB" },
624 | { 0x00FFFF, 0x00AF66, 1,00, NNN,NNN,NNN, C_CMD+0, "SCASW" },
625 | { 0x0000FF, 0x0000AF, 1,00, NNN,NNN,NNN, C_CMD+0, "SCASD" },
626 | { 0x0000FF, 0x0000AA, 1,00, NNN,NNN,NNN, C_CMD+0, "STOSB" },
627 | { 0x00FFFF, 0x00AB66, 2,00, NNN,NNN,NNN, C_CMD+0, "STOSW" },
628 | { 0x0000FF, 0x0000AB, 1,00, NNN,NNN,NNN, C_CMD+0, "STOSD" },
629 | { 0x00FFFF, 0x00A4F3, 1,00, NNN,NNN,NNN, C_REP+0, "REP MOVSB" },
630 | { 0xFFFFFF, 0xA5F366, 2,00, NNN,NNN,NNN, C_REP+0, "REP MOVSW" },
631 | { 0x00FFFF, 0x00A5F3, 1,00, NNN,NNN,NNN, C_REP+0, "REP MOVSD" },
632 | { 0x00FFFF, 0x00ACF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP LODSB" },
633 | { 0xFFFFFF, 0xADF366, 2,00, NNN,NNN,NNN, C_REP+0, "REP LODSW" },
634 | { 0x00FFFF, 0x00ADF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP LODSD" },
635 | { 0x00FFFF, 0x00AAF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP STOSB" },
636 | { 0xFFFFFF, 0xABF366, 2,00, NNN,NNN,NNN, C_REP+0, "REP STOSW" },
637 | { 0x00FFFF, 0x00ABF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP STOSD" },
638 | { 0x00FFFF, 0x00A6F3, 1,00, NNN,NNN,NNN, C_REP+0, "REPE CMPSB" },
639 | { 0xFFFFFF, 0xA7F366, 2,00, NNN,NNN,NNN, C_REP+0, "REPE CMPSW" },
640 | { 0x00FFFF, 0x00A7F3, 1,00, NNN,NNN,NNN, C_REP+0, "REPE CMPSD" },
641 | { 0x00FFFF, 0x00AEF3, 1,00, NNN,NNN,NNN, C_REP+0, "REPE SCASB" },
642 | { 0xFFFFFF, 0xAFF366, 2,00, NNN,NNN,NNN, C_REP+0, "REPE SCASW" },
643 | { 0x00FFFF, 0x00AFF3, 1,00, NNN,NNN,NNN, C_REP+0, "REPE SCASD" },
644 | { 0x00FFFF, 0x00A6F2, 1,00, NNN,NNN,NNN, C_REP+0, "REPNE CMPSB" },
645 | { 0xFFFFFF, 0xA7F266, 2,00, NNN,NNN,NNN, C_REP+0, "REPNE CMPSW" },
646 | { 0x00FFFF, 0x00A7F2, 1,00, NNN,NNN,NNN, C_REP+0, "REPNE CMPSD" },
647 | { 0x00FFFF, 0x00AEF2, 1,00, NNN,NNN,NNN, C_REP+0, "REPNE SCASB" },
648 | { 0xFFFFFF, 0xAFF266, 2,00, NNN,NNN,NNN, C_REP+0, "REPNE SCASW" },
649 | { 0x00FFFF, 0x00AFF2, 1,00, NNN,NNN,NNN, C_REP+0, "REPNE SCASD" },
650 | { 0x0000FF, 0x00006C, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "INSB" },
651 | { 0x00FFFF, 0x006D66, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "INSW" },
652 | { 0x0000FF, 0x00006D, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "INSD" },
653 | { 0x0000FF, 0x00006E, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "OUTSB" },
654 | { 0x00FFFF, 0x006F66, 2,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "OUTSW" },
655 | { 0x0000FF, 0x00006F, 1,00, NNN,NNN,NNN, C_CMD+C_RARE+0, "OUTSD" },
656 | { 0x00FFFF, 0x006CF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP INSB" },
657 | { 0xFFFFFF, 0x6DF366, 2,00, NNN,NNN,NNN, C_REP+0, "REP INSW" },
658 | { 0x00FFFF, 0x006DF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP INSD" },
659 | { 0x00FFFF, 0x006EF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP OUTSB" },
660 | { 0xFFFFFF, 0x6FF366, 2,00, NNN,NNN,NNN, C_REP+0, "REP OUTSW" },
661 | { 0x00FFFF, 0x006FF3, 1,00, NNN,NNN,NNN, C_REP+0, "REP OUTSD" },
662 | { 0x0000FF, 0x0000E1, 1,00, JOB,NNN,NNN, C_JMC+0, "$LOOP*Z" },
663 | { 0x0000FF, 0x0000E0, 1,00, JOB,NNN,NNN, C_JMC+0, "$LOOP*NZ" },
664 | { 0x0000FF, 0x00009B, 1,00, NNN,NNN,NNN, C_CMD+0, "FWAIT" },
665 | { 0x0000FF, 0x0000D7, 1,00, NNN,NNN,NNN, C_CMD+0, "XLATB" },
666 | { 0x00FFFF, 0x00C40F, 2,00, RMX,RR4,IM1, C_MMX+2, "PINSRW" },
667 | { 0x00FFFF, 0x0020CD, 2,00, VXD,NNN,NNN, C_CAL+C_RARE+0, "VxDCall" },
668 | // Pseudocommands used by Assembler for masked search only.
669 | { 0x0000F0, 0x000070, 1,CC, JOB,NNN,NNN, C_JMC+0, "JCC" },
670 | { 0x00F0FF, 0x00800F, 2,CC, JOW,NNN,NNN, C_JMC+0, "JCC" },
671 | { 0x00F0FF, 0x00900F, 2,CC, MR1,NNN,NNN, C_CMD+1, "SETCC" },
672 | { 0x00F0FF, 0x00400F, 2,CC, REG,MRG,NNN, C_CMD+0, "CMOVCC" },
673 | // End of command table.
674 | { 0x000000, 0x000000, 0,00, NNN,NNN,NNN, C_CMD+0, "" }
675 | };
676 |
677 | const t_cmddata vxdcmd = // Decoding of VxD calls (Win95/98)
678 | { 0x00FFFF, 0x0020CD, 2,00, VXD,NNN,NNN, C_CAL+C_RARE+0, "VxDCall" };
679 |
680 | // Bit combinations that can be potentially dangerous when executed:
681 | const t_cmddata dangerous[] = {
682 | { 0x00FFFF, 0x00DCF7, 0,0,0,0,0,C_DANGER95,
683 | "Win95/98 may crash when NEG ESP is executed" },
684 | { 0x00FFFF, 0x00D4F7, 0,0,0,0,0,C_DANGER95,
685 | "Win95/98 may crash when NOT ESP is executed" },
686 | { 0x00FFFF, 0x0020CD, 0,0,0,0,0,C_DANGER95,
687 | "Win95/98 may crash when VxD call is executed in user mode" },
688 | { 0xF8FFFF, 0xC8C70F, 0,0,0,0,1,C_DANGERLOCK,
689 | "LOCK CMPXCHG8B may crash some processors when executed" },
690 | { 0x000000, 0x000000, 0,0,0,0,0,0, "" }
691 | };
692 |
693 | // Decodes address into symb (nsymb bytes long, including the terminating zero
694 | // character) and comments its possible meaning. Returns number of bytes in
695 | // symb not including terminating zero.
696 | int Decodeaddress(ulong addr,char *symb,int nsymb,char *comment) {
697 |
698 |
699 | // Environment-specific routine! Do it yourself!
700 |
701 |
702 | return 0;
703 | };
704 |
705 | // Decodes and prints 32-bit float f into string s (which must be at least 16
706 | // bytes long). Returns resulting length of the string.
707 | int Printfloat4(char *s,float f) {
708 | int k;
709 | if (*(ulong *)&f==0x7F800000L)
710 | k=sprintf(s,"+INF 7F800000");
711 | else if (*(ulong *)&f==0xFF800000L)
712 | k=sprintf(s,"-INF FF800000");
713 | else if ((*(ulong *)&f & 0xFF800000L)==0x7F800000L)
714 | k=sprintf(s,"+NAN %08lX",*(ulong *)&f);
715 | else if ((*(ulong *)&f & 0xFF800000L)==0xFF800000L)
716 | k=sprintf(s,"-NAN %08lX",*(ulong *)&f);
717 | else if (f==0.0) // By default, 0 is printed without
718 | k=sprintf(s,"0.0"); // decimal point, which I don't want.
719 | else
720 | k=sprintf(s,"%#.7g",f);
721 | return k;
722 | };
723 |
724 | // Decodes and prints 64-bit double d into string s (at least 25 bytes long).
725 | // Returns resulting length of the string.
726 | int Printfloat8(char *s,double d) {
727 | int k;
728 | ulong lod,hid;
729 | lod=((ulong *)&d)[0];
730 | hid=((ulong *)&d)[1];
731 | if (lod==0 && hid==0x7F800000L)
732 | k=sprintf(s,"+INF 7F800000 00000000");
733 | else if (lod==0 && hid==0xFF800000L)
734 | k=sprintf(s,"-INF FF800000 00000000");
735 | else if ((hid & 0xFFF00000L)==0x7FF00000)
736 | k=sprintf(s,"+NAN %08lX %08lX",hid,lod);
737 | else if ((hid & 0xFFF00000L)==0xFFF00000)
738 | k=sprintf(s,"-NAN %08lX %08lX",hid,lod);
739 | else if (d==0.0) // Print 0 with decimal point
740 | k=sprintf(s,"0.0");
741 | else
742 | k=sprintf(s,"%#.16lg",d);
743 | return k;
744 | };
745 |
746 | // Decodes and prints 80-bit long double ext into string s (at least 32 bytes
747 | // long). Procedure correctly displays all, even invalid, numbers without
748 | // arithmetical exceptions. Returns resulting length of the string.
749 | int Printfloat10(char *s,long double ext) {
750 | int k;
751 | char *e=(char *)&ext;
752 | if (*(ulong *)e==0 && *(ushort *)(e+4)==0 && *(ulong *)(e+6)==0x7FFF8000L)
753 | k=sprintf(s,"+INF 7FFF 80000000 00000000");
754 | else if (*(ulong *)e==0 && *(ushort *)(e+4)==0 &&
755 | *(ulong *)(e+6)==0xFFFF8000L)
756 | k=sprintf(s,"-INF FFFF 80000000 00000000");
757 | else if ((*(ulong *)(e+6) & 0x7FFF8000L)==0x7FFF8000L)
758 | k=sprintf(s,"%cNAN %04X %08lX %08lX",(e[9] & 0x80)==0?'+':'-',
759 | (int)(*(ushort *)(e+8)),*(ulong *)(e+4),*(ulong *)e);
760 | else if ((*(ulong *)(e+6) & 0x7FFF0000L)==0x7FFF0000L)
761 | k=sprintf(s,"%c??? %04X %08lX %08lX",(e[9] & 0x80)==0?'+':'-',
762 | (int)(*(ushort *)(e+8)),*(ulong *)(e+4),*(ulong *)e);
763 | else if ((*(ulong *)(e+6) & 0x7FFF0000L)!=0 &&
764 | (*(ulong *)(e+6) & 0x00008000)==0)
765 | k=sprintf(s,"%cUNORM %04X %08lX %08lX",(e[9] & 0x80)==0?'+':'-',
766 | (int)(*(ushort *)(e+8)),*(ulong *)(e+4),*(ulong *)e);
767 | else if (*(ulong *)e==0 && *(ushort *)(e+4)==0 &&
768 | *(ulong *)(e+6)==0x80000000L)
769 | k=sprintf(s,"-0.0"); // Negative floating 0.0
770 | else if (ext==0.0)
771 | k=sprintf(s,"0.0"); // Print 0 with decimal point
772 | else if ((ext>=-1.e10 && ext<-1.0) || (ext>1.0 && ext<=1.e10))
773 | k=sprintf(s,"%#.20Lg",ext);
774 | else if ((ext>=-1.0 && ext<=-1.e-5) || (ext>=1.e-5 && ext<=1.0))
775 | k=sprintf(s,"%#.19Lf",ext);
776 | else
777 | k=sprintf(s,"%#.19Le",ext);
778 | return k;
779 | };
780 |
781 | // Decodes and prints 64-bit 3DNow! element f into string s (which must be at
782 | // least 30 bytes long). Returns resulting length of the string.
783 | int Print3dnow(char *s,char *f) {
784 | int n;
785 | n=Printfloat4(s,*(float *)(f+4));
786 | n+=sprintf(s+n,", ");
787 | n+=Printfloat4(s+n,*(float *)f);
788 | return n;
789 | };
790 |
791 | // Function attempts to calculate address of assembler instruction which is n
792 | // lines back in the listing. Maximal stepback is limited to 127. In general,
793 | // this is rather non-trivial task. Proposed solution may cause problems which
794 | // however are not critical here.
795 | ulong Disassembleback(char *block,ulong base,ulong size,ulong ip,int n) {
796 | int i;
797 | ulong abuf[131],addr,back,cmdsize;
798 | char *pdata;
799 | t_disasm da;
800 | if (block==NULL) return 0; // Error, no code!
801 | if (n<0) n=0; else if (n>127) n=127; // Try to correct obvious errors
802 | if (ip>base+size) ip=base+size;
803 | if (n==0) return ip; // Obvious answers
804 | if (ip<=base+n) return base;
805 | back=MAXCMDSIZE*(n+3); // Command length limited to MAXCMDSIZE
806 | if (ipbase+size) ip=base+size;
829 | if (n<=0) return ip;
830 | pdata=block+(ip-base);
831 | size-=(ip-base);
832 | for (i=0; i0; i++) {
833 | cmdsize=Disasm(pdata,size,ip,&da,DISASM_SIZE);
834 | pdata+=cmdsize;
835 | ip+=cmdsize;
836 | size-=cmdsize; };
837 | return ip;
838 | };
839 |
840 | // Service function, checks whether command at offset addr in data is a valid
841 | // filling command (usually some kind of NOP) used to align code to a specified
842 | // (align=power of 2, 0 means no alignment) border. Returns length of filling
843 | // command in bytes or 0 if command is not a recognized filling.
844 | int Isfilling(ulong addr,char *data,ulong size,ulong align) {
845 | if (data==NULL) return 0; // Invalid parameters
846 | // Convert power of 2 to bitmask.
847 | align--;
848 | // Many compilers and assemblers use NOP or INT3 as filling:
849 | if (addr>3)^data[addr+1]) & 0x07)==0 &&
858 | (addr & align)!=0x0F && (addr & align)!=0x00)
859 | return 2;
860 | // Some other programs use LEA EAX,[EAX] (8D,40,00). For completeness, allow
861 | // any register except ESP (here address is constructed differently):
862 | if (addr+2>3)^data[addr+1]) & 0x07)==0)
866 | return 3;
867 | // WATCOM compilers use LEA EAX,[EAX] with SIB and 8-bit zero (8D,44,20,00)
868 | // and without SIB but with 32-bit immediate zero (8D,80,00,00,00,00) and
869 | // alike:
870 | if (addr+3>3)^data[addr+2]) & 0x07)==0)
873 | return 4;
874 | if (addr+5>3)^data[addr+1]) & 0x07)==0)
878 | return 6;
879 | // Unable to recognize this code as a valid filling.
880 | return 0;
881 | };
882 |
883 |
--------------------------------------------------------------------------------