/** Simple arm disassembler via a library Argv[0] - disasm Argv[1] - Address to start disassembling from ARgv[2] - Number of instructions to disassembly (optional) @param Argc Number of command arguments in Argv @param Argv Array of strings that represent the parsed command line. Argv[0] is the comamnd name @return EFI_SUCCESS **/ EFI_STATUS EblDisassembler ( IN UINTN Argc, IN CHAR8 **Argv ) { UINT8 *Ptr, *CurrentAddress; UINT32 Address; UINT32 Count; CHAR8 Buffer[80]; UINT32 ItBlock; if (Argc < 2) { return EFI_INVALID_PARAMETER; } Address = AsciiStrHexToUintn (Argv[1]); Count = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 20; Ptr = (UINT8 *)(UINTN)Address; ItBlock = 0; do { CurrentAddress = Ptr; DisassembleInstruction (&Ptr, TRUE, TRUE, &ItBlock, Buffer, sizeof (Buffer)); AsciiPrint ("0x%08x: %a\n", CurrentAddress, Buffer); } while (Count-- > 0); return EFI_SUCCESS; }
// Print disassembled instructions // Return value: number of words in the last instruction int PrintDisassemble(CProcessor* pProc, WORD address, BOOL okOneInstr, BOOL okShort) { BOOL okHaltMode = pProc->IsHaltMode(); const int nWindowSize = 30; WORD memory[nWindowSize + 2]; int addrtype; for (int i = 0; i < nWindowSize + 2; i++) memory[i] = g_pBoard->GetWordView(address + i * 2, okHaltMode, TRUE, &addrtype); TCHAR bufaddr[7]; TCHAR bufvalue[7]; TCHAR buffer[64]; int lastLength = 0; int length = 0; for (int index = 0; index < nWindowSize; index++) // –исуем строки { PrintOctalValue(bufaddr, address); WORD value = memory[index]; PrintOctalValue(bufvalue, value); if (length > 0) { if (!okShort) { wsprintf(buffer, _T(" %s %s\r\n"), bufaddr, bufvalue); ConsoleView_Print(buffer); } } else { if (okOneInstr && index > 0) break; TCHAR instr[8]; TCHAR args[32]; length = DisassembleInstruction(memory + index, address, instr, args); lastLength = length; if (index + length > nWindowSize) break; if (okShort) wsprintf(buffer, _T(" %s %-7s %s\r\n"), bufaddr, instr, args); else wsprintf(buffer, _T(" %s %s %-7s %s\r\n"), bufaddr, bufvalue, instr, args); ConsoleView_Print(buffer); } length--; address += 2; } return lastLength; }
void UnassembleCommand(void) { int count = 8; // Default instruction count to display Sb(); if (IsDwDebugNumeric(NextCh())) {Uaddr = ReadInstructionAddress("U"); Wl();} Sb(); if (IsDwDebugNumeric(NextCh())) {count = ReadNumber(0);} Sb(); if (!DwEoln()) {Wsl("Unrecognised parameters on unassemble command.");} int firstByte = Uaddr; int limitByte = min(firstByte + count*4, FlashSize()); // Allow for up to 2 words per instruction int length = limitByte - firstByte; if (length <= 0) {Fail("Nothing to disassemble.");} u8 buf[length+2]; DwReadFlash(firstByte, length, buf); buf[length] = 0; buf[length+1] = 0; while (1) { Uaddr += DisassembleInstruction(Uaddr, &buf[Uaddr-firstByte]); count--; if (count <= 0 || Uaddr >= FlashSize()) {return;} Wl(); } }
int DisasmView_DrawDisassemble(HDC hdc, CProcessor* pProc, WORD base, WORD previous, int x, int y) { int result = -1; int cxChar, cyLine; GetFontWidthAndHeight(hdc, &cxChar, &cyLine); COLORREF colorText = GetSysColor(COLOR_WINDOWTEXT); const CMemoryController* pMemCtl = pProc->GetMemoryController(); WORD proccurrent = pProc->GetPC(); WORD current = base; // Draw current line background if (!m_okDisasmSubtitles) //NOTE: Subtitles can move lines down { HGDIOBJ oldBrush = SelectObject(hdc, CreateSolidBrush(COLOR_CURRENT)); int yCurrent = (proccurrent - (current - 5)) * cyLine; PatBlt(hdc, 0, yCurrent, 1000, cyLine, PATCOPY); SelectObject(hdc, oldBrush); } // Читаем из памяти процессора в буфер const int nWindowSize = 30; WORD memory[nWindowSize + 2]; for (int idx = 0; idx < nWindowSize; idx++) { BOOL okValidAddress; memory[idx] = pMemCtl->GetWordView( (WORD)(current + idx * 2 - 10), pProc->IsHaltMode(), TRUE, &okValidAddress); } WORD address = current - 10; WORD disasmfrom = current; if (previous >= address && previous < current) disasmfrom = previous; int length = 0; WORD wNextBaseAddr = 0; for (int index = 0; index < nWindowSize; index++) // Рисуем строки { if (m_okDisasmSubtitles) // Subtitles - комментарий к блоку { DisasmSubtitleItem* pSubItem = DisasmView_FindSubtitle(address, SUBTYPE_BLOCKCOMMENT); if (pSubItem != NULL && pSubItem->comment != NULL) { LPCTSTR strBlockSubtitle = pSubItem->comment; ::SetTextColor(hdc, COLOR_SUBTITLE); TextOut(hdc, x + 21 * cxChar, y, strBlockSubtitle, (int) _tcslen(strBlockSubtitle)); ::SetTextColor(hdc, colorText); y += cyLine; } } DrawOctalValue(hdc, x + 5 * cxChar, y, address); // Address // Value at the address WORD value = memory[index]; ::SetTextColor(hdc, COLOR_VALUE); DrawOctalValue(hdc, x + 13 * cxChar, y, value); ::SetTextColor(hdc, colorText); // Current position if (address == current) { TextOut(hdc, x + 1 * cxChar, y, _T(" >"), 3); result = y; // Remember line for the focus rect } if (address == proccurrent) TextOut(hdc, x + 1 * cxChar, y, _T("PC>>"), 4); else if (address == previous) { ::SetTextColor(hdc, COLOR_BLUE); TextOut(hdc, x + 1 * cxChar, y, _T(" > "), 4); } BOOL okData = FALSE; if (m_okDisasmSubtitles) // Show subtitle { DisasmSubtitleItem* pSubItem = DisasmView_FindSubtitle(address, SUBTYPE_COMMENT | SUBTYPE_DATA); if (pSubItem != NULL && (pSubItem->type & SUBTYPE_DATA) != 0) okData = TRUE; if (pSubItem != NULL && (pSubItem->type & SUBTYPE_COMMENT) != 0 && pSubItem->comment != NULL) { LPCTSTR strSubtitle = pSubItem->comment; ::SetTextColor(hdc, COLOR_SUBTITLE); TextOut(hdc, x + 52 * cxChar, y, strSubtitle, (int) _tcslen(strSubtitle)); ::SetTextColor(hdc, colorText); // Строку с субтитром мы можем использовать как опорную для дизассемблера if (disasmfrom > address) disasmfrom = address; } } if (address >= disasmfrom && length == 0) { TCHAR strInstr[8]; TCHAR strArg[32]; if (okData) // По этому адресу лежат данные -- нет смысла дизассемблировать { lstrcpy(strInstr, _T("data")); PrintOctalValue(strArg, *(memory + index)); length = 1; } else { length = DisassembleInstruction(memory + index, address, strInstr, strArg); int delta; if (!m_okDisasmSubtitles && //NOTE: Subtitles can move lines down DisasmView_CheckForJump(memory + index, address, &delta) && abs(delta) < 32) { DisasmView_DrawJump(hdc, y, delta, x + (30 + _tcslen(strArg)) * cxChar, cyLine); } } if (index + length <= nWindowSize) { TextOut(hdc, x + 21 * cxChar, y, strInstr, (int) _tcslen(strInstr)); TextOut(hdc, x + 29 * cxChar, y, strArg, (int) _tcslen(strArg)); } ::SetTextColor(hdc, colorText); if (wNextBaseAddr == 0) wNextBaseAddr = (WORD)(address + length * 2); } if (length > 0) length--; address += 2; y += cyLine; } m_wDisasmNextBaseAddr = wNextBaseAddr; return result; }