-
-
ARM反汇编
-
发表于: 2010-8-29 21:27 10139
-
#include <stdio.h>
#include <string.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange (CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog (CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange (pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP (CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CUnasmARMDlg dialog
CUnasmARMDlg::CUnasmARMDlg (CWnd* pParent /*=NULL*/)
: CDialog (CUnasmARMDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CUnasmARMDlg)
m_filename1 = _T ("");
m_filename2 = _T ("");
m_filename3 = _T ("");
m_Hex = TRUE;
m_Radio1 = -1;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon (IDR_MAINFRAME);
}
void CUnasmARMDlg::DoDataExchange (CDataExchange* pDX)
{
CDialog::DoDataExchange (pDX);
//{{AFX_DATA_MAP(CUnasmARMDlg)
DDX_Text (pDX, IDC_EDIT1, m_filename1);
DDX_Text (pDX, IDC_EDIT2, m_filename2);
DDX_Text (pDX, IDC_EDIT3, m_filename3);
DDX_Check (pDX, IDC_CHECK1, m_Hex);
DDX_Radio (pDX, IDC_RADIO1, m_Radio1);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP (CUnasmARMDlg, CDialog)
//{{AFX_MSG_MAP(CUnasmARMDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED (IDC_BUTTON1, OnButton1)
ON_BN_CLICKED (IDC_BUTTON2, OnButton2)
ON_BN_CLICKED (IDC_BUTTON3, OnButton3)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CUnasmARMDlg message handlers
BOOL CUnasmARMDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT ( (IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT (IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu (FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString (IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty() )
{
pSysMenu->AppendMenu (MF_SEPARATOR);
pSysMenu->AppendMenu (MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon (m_hIcon, TRUE); // Set big icon
SetIcon (m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
// m_filename1 = _T("D:\\下载资料\\5110v530\\5110v530.fls");
// m_filename2 = _T("D:\\下载资料\\5110v530\\5110v530.ref");
// m_filename3 = _T("D:\\下载资料\\5110v530\\5110v530.asm");
m_Radio1 = 0;
UpdateData (FALSE);
strcpy (RegisterName[0], "R0");
strcpy (RegisterName[1], "R1");
strcpy (RegisterName[2], "R2");
strcpy (RegisterName[3], "R3");
strcpy (RegisterName[4], "R4");
strcpy (RegisterName[5], "R5");
strcpy (RegisterName[6], "R6");
strcpy (RegisterName[7], "R7");
strcpy (RegisterName[8], "R8");
strcpy (RegisterName[9], "R9");
strcpy (RegisterName[10], "R10");
strcpy (RegisterName[11], "R11");
strcpy (RegisterName[12], "R12");
strcpy (RegisterName[13], "SP");
strcpy (RegisterName[14], "LR");
strcpy (RegisterName[15], "PC");
regNo = -1;
return TRUE; // return TRUE unless you set the focus to a control
}
void CUnasmARMDlg::OnSysCommand (UINT nID, LPARAM lParam)
{
if ( (nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand (nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CUnasmARMDlg::OnPaint()
{
if (IsIconic() )
{
CPaintDC dc (this); // device context for painting
SendMessage (WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics (SM_CXICON);
int cyIcon = GetSystemMetrics (SM_CYICON);
CRect rect;
GetClientRect (&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon (x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CUnasmARMDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CUnasmARMDlg::OnOK()
{
// TODO: Add extra validation here
// CDialog::OnOK();
UpdateData (TRUE);
if (m_filename1.IsEmpty() )
{
AfxMessageBox ("You must specify source filename");
return;
}
if (m_filename2.IsEmpty() )
{
AfxMessageBox ("You must specify Reference filename");
return;
}
if (m_filename3.IsEmpty() )
{
AfxMessageBox ("You must specify Target filename");
return;
}
FILE *fd_src, *fd_ref, *fd_tar;
fd_src = fopen (m_filename1, "rb");
if (fd_src == NULL)
{
AfxMessageBox ("Source file not found.");
return;
}
fd_ref = fopen (m_filename2, "r");
if (fd_ref == NULL)
{
fclose (fd_src);
AfxMessageBox ("Reference file not found.");
return;
}
fd_tar = fopen (m_filename3, "w");
if (fd_tar == NULL)
{
fclose (fd_src);
fclose (fd_ref);
AfxMessageBox ("Error creating target file.");
return;
}
#define ARM_MODE 0x1
#define THUMB_MODE 0x2
char ref_buffer[1024];
int theMode = ARM_MODE;
long addr = 0;
long addr1, addr2; //Unasm
int i;
/*
$ADDRESS=0x200000
$ARM
$UN0x0,0x0fff
$REM This is a subroutine
$DB0x1000,0x10ff // Define Byte
$DC0x1000,0x10ff // Define Code
$DH0x1100,0x11ff // Define Halfword
$DW0x1200,0x12ff // Define Word
$DF0x1300,0x13FF // Define Float
$DD0x1400,0x14FF // Define Double
$THUMB
$UN0x2000,0x20FF
$END
*/
for (;;)
{
i = fscanf (fd_ref, "%s", ref_buffer);
if (i < 0) break;
if (_memicmp ( ref_buffer, "$REM", 4) == 0)
{ // Remark
while (1)
{
i = fscanf (fd_ref, "%s", ref_buffer);
if (i < 0) break;
if (ref_buffer[0] == '$')
{
fwrite ("\n", 1, 1, fd_tar);
if (_memicmp ( ref_buffer, "$REM", 4) == 0)
{ // Remark
continue;
}
break;
}
fwrite (ref_buffer, 1, strlen (ref_buffer), fd_tar);
fwrite (" ", 1, 1, fd_tar);
}
if (i < 0) break;
}
if (_memicmp ( ref_buffer, "$END", 4) == 0)
{ // $END
break;
}
if (_memicmp ( ref_buffer, "$ARM", 4) == 0)
{ // $ARM
regNo = -1;
theMode = ARM_MODE;
continue;
}
if (_memicmp ( ref_buffer, "$THUMB", 6) == 0)
{ // $THUMB
regNo = -1;
theMode = THUMB_MODE;
continue;
}
if (_memicmp ( ref_buffer, "$ADDRESS=0x", 11) == 0)
{ // $ADDRESS
addr = GetHex (&ref_buffer[11]);
continue;
}
if (_memicmp ( ref_buffer, "$UN0X", 5) == 0)
{ // $UN
addr1 = GetHex (&ref_buffer[5]);
addr2 = addr1 + 0x7f; // 0x80 bytes
i = 0;
for (;;)
{
if ( (ref_buffer[i] == '\0') || (ref_buffer[i] == ',') )
break;
i++;
}
if (ref_buffer[i] == ',')
{
i++;
if (_memicmp ( &ref_buffer[i], "0x", 2) == 0)
{
addr2 = GetHex (&ref_buffer[i+2]);
if (addr2 <= addr1) continue;
}
}
// Now we can disassembly from addr1 to addr2
if (theMode == ARM_MODE)
dis_arm (fd_src, fd_tar, addr, addr1, addr2);
else
dis_thumb (fd_src, fd_tar, addr, addr1, addr2);
continue;
}
if ( (ref_buffer[0] == '$' ) &&
(toupper (ref_buffer[1]) == 'D') )
{ // $DB/DH/DW/DC/DD/DF
char ch;
int d_mode = 0;
ch = toupper (ref_buffer[2]);
switch (ch)
{
case 'B':
d_mode = 1; // $DB
break;
case 'C':
d_mode = 3; // $DC
break;
case 'D':
d_mode = 5; // $DD
break;
case 'F':
d_mode = 6; // $DF
break;
case 'H':
d_mode = 2; // $DH
break;
case 'W':
d_mode = 4; // $DW
break;
}
if (!d_mode) continue;
if (_memicmp ( &ref_buffer[3], "0x", 2) == 0)
{
addr1 = GetHex (&ref_buffer[5]);
addr2 = addr1 + 0x7f; // 0x80 bytes
i = 0;
for (;;)
{
if ( (ref_buffer[i] == '\0') || (ref_buffer[i] == ',') )
break;
i++;
}
if (ref_buffer[i] == ',')
{
i++;
if (_memicmp ( &ref_buffer[i], "0x", 2) == 0)
{
addr2 = GetHex (&ref_buffer[i+2]);
if (addr2 <= addr1) continue;
}
}
// Now we can dump data from addr1 to addr2
switch (d_mode)
{
case 1:
dump_byte (fd_src, fd_tar, addr, addr1, addr2);
break;
case 2:
dump_halfword (fd_src, fd_tar, addr, addr1, addr2);
break;
case 3:
dump_byte_nochar (fd_src, fd_tar, addr, addr1, addr2);
break;
case 4:
dump_word (fd_src, fd_tar, addr, addr1, addr2);
break;
case 5:
dump_double (fd_src, fd_tar, addr, addr1, addr2);
break;
case 6:
dump_float (fd_src, fd_tar, addr, addr1, addr2);
break;
}
}
continue;
}
}
fclose (fd_src);
fclose (fd_ref);
fclose (fd_tar);
AfxMessageBox ("Successful");
}
long CUnasmARMDlg::GetHex (char * str)
{
int i;
long v;
char ch;
for (i = 0, v = 0; str[i]; i++)
{
ch = toupper (str[i]);
if ( (ch >= '0') && (ch <= '9') )
{
v = v * 16 + ch - '0';
continue;
}
if ( (ch >= 'A') && (ch <= 'F') )
{
v = v * 16 + ch - 'A' + 10;
continue;
}
break;
}
return v;
}
int CUnasmARMDlg::dump_byte (FILE *fd_src, FILE *fd_tar, long addr, long addr1, long addr2)
{
int i, loc_str;
long bytes;
char src_buffer[16384];
char string[32];
string[0] = ' ';
i = fseek (fd_src, addr1, SEEK_SET);
bytes = addr2 - addr1 + 1;
while (bytes)
{
int loc, times_16, remains_16;
int bytes1 = (bytes <= 16384) ? bytes : 16384;
char str[128];
int k, l;
if (addr1 & 15)
{
if ( (16 - (addr1 & 15) ) < bytes1)
bytes1 = 16 - (addr1 & 15);
}
bytes -= bytes1;
i = fread ( src_buffer, 1, bytes1, fd_src);
if (i > 0)
{
bytes1 = i; // Bytes actually
times_16 = bytes1 >> 4;
remains_16 = bytes1 & 0x0f;
l = 0;
while (times_16)
{
loc_str = 1;
sprintf (str, "%08x ", addr + addr1);
for (k = 0; k < 16; k++, l++)
{
loc = strlen (str);
sprintf (&str[loc], "%02X ", 0xff & src_buffer[l]);
string[loc_str++] = (src_buffer[l] >= ' ') ? src_buffer[l] : '.';
}
string[loc_str] = '\0';
strcat (str, string);
str[33] = '-';
loc = strlen (str);
str[loc++] = '\n';
str[loc] = '\0';
fwrite (str, 1, loc, fd_tar);
times_16--;
addr1 += 16;
}
if (remains_16)
{
memset (str, ' ', 128);
loc_str = 1;
sprintf (str, "%08x ", addr + addr1);
for (k = 0; k < remains_16; k++, l++)
{
loc = strlen (str);
sprintf (&str[loc], "%02X ", 0xff & src_buffer[l]);
string[loc_str++] = (src_buffer[l] >= ' ') ? src_buffer[l] : '.';
}
string[loc_str] = '\0';
loc = strlen (str);
str[loc] = ' ';
str[58] = '\0';
strcat (str, string);
if (remains_16 > 8)
str[33] = '-';
loc = strlen (str);
str[loc++] = '\n';
str[loc] = '\0';
fwrite (str, 1, loc, fd_tar);
addr1 += remains_16;
}
}
}
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
int CUnasmARMDlg::dump_halfword (FILE * fd_src, FILE * fd_tar, long addr, long addr1, long addr2)
{
int i, loc_str;
long bytes;
char src_buffer[16384];
i = fseek (fd_src, addr1, SEEK_SET);
bytes = addr2 - addr1 + 1;
while (bytes)
{
int loc, times_16, remains_16;
int bytes1 = (bytes <= 16384) ? bytes : 16384;
char str[128];
int k, l;
if (addr1 & 15)
{
if ( (16 - (addr1 & 15) ) < bytes1)
bytes1 = 16 - (addr1 & 15);
}
bytes -= bytes1;
i = fread ( src_buffer, 1, bytes1, fd_src);
if (i > 0)
{
bytes1 = i; // Bytes actually
times_16 = bytes1 >> 4;
remains_16 = (bytes1 & 0x0f) >> 1;
l = 0;
while (times_16)
{
loc_str = 1;
sprintf (str, "%08x ", addr + addr1);
for (k = 0; k < 8; k++, l += 2)
{
loc = strlen (str);
if (m_Radio1)
{
sprintf (&str[loc], "%02X%02X ",
0xff & src_buffer[l],
0xff & src_buffer[l+1]);
}
else
{
sprintf (&str[loc], "%02X%02X ",
0xff & src_buffer[l+1],
0xff & src_buffer[l]);
}
}
loc = strlen (str);
str[loc-1] = '\n';
fwrite (str, 1, loc, fd_tar);
times_16--;
addr1 += 16;
}
if (remains_16)
{
loc_str = 1;
sprintf (str, "%08x ", addr + addr1);
for (k = 0; k < remains_16; k++, l += 2)
{
loc = strlen (str);
if (m_Radio1)
{
sprintf (&str[loc], "%02X%02X ",
0xff & src_buffer[l],
0xff & src_buffer[l+1]);
}
else
{
sprintf (&str[loc], "%02X%02X ",
0xff & src_buffer[l+1],
0xff & src_buffer[l]);
}
}
loc = strlen (str);
str[loc-1] = '\n';
fwrite (str, 1, loc, fd_tar);
addr1 += (remains_16 << 1);
}
}
}
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
int CUnasmARMDlg::dump_word (FILE * fd_src, FILE * fd_tar, long addr, long addr1, long addr2)
{
int i, loc_str;
long bytes;
char src_buffer[16384];
i = fseek (fd_src, addr1, SEEK_SET);
bytes = addr2 - addr1 + 1;
while (bytes)
{
int loc, times_16, remains_16;
int bytes1 = (bytes <= 16384) ? bytes : 16384;
char str[128];
int k, l;
if (addr1 & 15)
{
if ( (16 - (addr1 & 15) ) < bytes1)
bytes1 = 16 - (addr1 & 15);
}
bytes -= bytes1;
i = fread ( src_buffer, 1, bytes1, fd_src);
if (i > 0)
{
bytes1 = i; // Bytes actually
times_16 = bytes1 >> 4;
remains_16 = (bytes1 & 0x0f) >> 2;
l = 0;
while (times_16)
{
loc_str = 1;
sprintf (str, "%08x ", addr + addr1);
for (k = 0; k < 4; k++, l += 4)
{
loc = strlen (str);
if (m_Radio1)
{
sprintf (&str[loc], "%02X%02X%02X%02X ",
0xff & src_buffer[l],
0xff & src_buffer[l+1],
0xff & src_buffer[l+2],
0xff & src_buffer[l+3]);
}
else
{
sprintf (&str[loc], "%02X%02X%02X%02X ",
0xff & src_buffer[l+3],
0xff & src_buffer[l+2],
0xff & src_buffer[l+1],
0xff & src_buffer[l]);
}
}
loc = strlen (str);
str[loc-1] = '\n';
fwrite (str, 1, loc, fd_tar);
times_16--;
addr1 += 16;
}
if (remains_16)
{
loc_str = 1;
sprintf (str, "%08x ", addr + addr1);
for (k = 0; k < remains_16; k++, l += 4)
{
loc = strlen (str);
if (m_Radio1)
{
sprintf (&str[loc], "%02X%02X%02X%02X ",
0xff & src_buffer[l],
0xff & src_buffer[l+1],
0xff & src_buffer[l+2],
0xff & src_buffer[l+3]);
}
else
{
sprintf (&str[loc], "%02X%02X%02X%02X ",
0xff & src_buffer[l+3],
0xff & src_buffer[l+2],
0xff & src_buffer[l+1],
0xff & src_buffer[l]);
}
}
loc = strlen (str);
str[loc-1] = '\n';
fwrite (str, 1, loc, fd_tar);
addr1 += (remains_16 << 2);
}
}
}
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
int CUnasmARMDlg::dis_arm (FILE * fd_src, FILE * fd_tar, long addr, long addr1, long addr2)
{
long bytes;
int i, bytes1;
char src_buffer[16384];
int op_type;
long cur_addr = addr + addr1;
CrLf = 0;
i = fseek (fd_src, addr1, SEEK_SET);
bytes = (addr2 - addr1 + 1) & (~3);
while (bytes > 0)
{
bytes1 = (bytes <= 16384) ? bytes : 16384;
bytes -= bytes1;
i = fread ( src_buffer, 1, bytes1, fd_src);
if (i > 0)
{
//Dis-asm from src_buffer[0] , bytes1 bytes
for (i = 0; i < bytes1; i += 4)
{
if (m_Radio1)
{
op_type = dis_arm_one ( (unsigned char ) src_buffer[i],
(unsigned char ) src_buffer[i+1],
(unsigned char ) src_buffer[i+2],
(unsigned char ) src_buffer[i+3]);
do_dis_arm (fd_src, fd_tar, cur_addr, addr, op_type,
(unsigned char) src_buffer[i],
(unsigned char) src_buffer[i+1],
(unsigned char) src_buffer[i+2],
(unsigned char) src_buffer[i+3]);
}
else
{
op_type = dis_arm_one ( (unsigned char ) src_buffer[i+3],
(unsigned char ) src_buffer[i+2],
(unsigned char ) src_buffer[i+1],
(unsigned char ) src_buffer[i]);
do_dis_arm (fd_src, fd_tar, cur_addr, addr, op_type,
(unsigned char) src_buffer[i+3],
(unsigned char) src_buffer[i+2],
(unsigned char) src_buffer[i+1],
(unsigned char) src_buffer[i]);
}
cur_addr += 4;
}
}
}
if (CrLf)
CrLf = 0;
else
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
int CUnasmARMDlg::dis_thumb (FILE * fd_src, FILE * fd_tar, long addr, long addr1, long addr2)
{
int i, j, i_delta;
long bytes;
int bytes1;
int remains;
char temp, src_buffer[16384];
int op_type;
long cur_addr = addr + addr1;
CrLf = 0;
i = fseek (fd_src, addr1, SEEK_SET);
bytes = (addr2 - addr1 + 1) & (~1);
remains = 0;
while (bytes > 0)
{
bytes1 = (bytes <= 16384) ? bytes : 16384;
if (remains && (bytes1 > 16382) )
bytes1 -= remains;
bytes -= bytes1;
i = fread ( &src_buffer[remains], 1, bytes1, fd_src);
if (i > 0)
{
if (!m_Radio1)
{
for (j = 0; j < bytes1; j += 2)
{
temp = src_buffer[j];
src_buffer[j] = src_buffer[j+1];
src_buffer[j+1] = temp;
}
}
//Dis-asm from src_buffer[0] , (bytes1+remains) bytes
for (i = 0; i < bytes1 + remains; i += i_delta)
{
op_type = dis_thumb_one ( (unsigned char *) & src_buffer[i]);
if (op_type != 19)
{
i_delta = 2;
do_dis_thumb (fd_src, fd_tar, cur_addr,
addr, op_type,
(unsigned char) src_buffer[i],
(unsigned char) src_buffer[i+1]);
cur_addr += 2;
}
else
{
i_delta = 4;
if ( (bytes1 + remains - i) < 4)
{
remains = 2;
src_buffer[0] = src_buffer[i];
src_buffer[1] = src_buffer[i+1];
break;
}
else
{
int offset;
char str[128], temp[128];
int TooBad = 0;
if ( (src_buffer[i] & 8) == 0)
{
if ( (src_buffer[i+2] & 0xf8) != 0xf8)
TooBad = 1;
}
else
TooBad = 1;
if (TooBad)
{
i_delta = 2;
do_dis_thumb (fd_src, fd_tar, cur_addr,
addr, 19,
(unsigned char) src_buffer[i],
(unsigned char) src_buffer[i+1]);
cur_addr += 2;
continue;
}
offset = (src_buffer[i+3] & 0xff) |
( (src_buffer[i+2] & 7) << 8) |
( (src_buffer[i+1] & 0xff) << 11) |
( (src_buffer[i] & 7) << 19);
if (offset & 0x200000)
{
( (unsigned char *) &offset) [3] = 0xff;
( (unsigned char *) &offset) [2] |= 0xc0;
}
offset = cur_addr + (offset << 1) + 4;
if (m_Hex)
{
sprintf (str, "%08x %02X%02X%02X%02X ",
cur_addr, 0xff & src_buffer[i],
0xff & src_buffer[i+1],
0xff & src_buffer[i+2],
0xff & src_buffer[i+3]);
}
else
{
sprintf (str, "%08x ", cur_addr);
}
sprintf (temp, "BL 0x%08x\n", offset);
regNo = -1;
strcat (str, temp);
fwrite (str, 1, strlen (str), fd_tar);
cur_addr += 4;
}
}
}
if (i_delta == 2)
remains = 0;
}
}
if (CrLf)
CrLf = 0;
else
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
int CUnasmARMDlg::dis_thumb_one (unsigned char * bin_code)
{
unsigned uch;
int op_type; //1-19
uch = bin_code[0] & 0xf0; // 1111 0000
switch (uch)
{
case 0x00:
op_type = 1; // Move shifted register
break;
case 0x10:
if ( (bin_code[0] & 0xf8) == 0x18)
op_type = 2; // Add/substract
else
op_type = 1; // Move shifted register
break;
case 0x20:
case 0x30:
op_type = 3; // Move/compare/add/substract imm
break;
case 0x40:
if ( (bin_code[0] & 0xfc) == 0x40)
{
op_type = 4; // ALU operations
break;
}
if ( (bin_code[0] & 0xfc) == 0x44)
{
op_type = 5; // Hi register operation/Branch exchange
break;
}
op_type = 6; // PC-relative load
break;
case 0x50:
if ( (bin_code[0] & 0xf2) == 0x52)
op_type = 8; // Load/store sign-exted byte/hw
else
op_type = 7; // Load/store with register offset
break;
case 0x60:
case 0x70:
op_type = 9; // Load/store with imm offset
break;
case 0x80:
op_type = 10; // Load/store halfword
break;
case 0x90:
op_type = 11; // SP-relative load/store
break;
case 0xa0:
op_type = 12; // Load address
break;
case 0xb0:
if (bin_code[0] == 0xb0)
op_type = 13; // Add offset to stack pointer
else
op_type = 14; // Push/pop registers
break;
case 0xc0:
op_type = 15; // Multiple load/store
break;
case 0xd0:
if (bin_code[0] == 0xdf)
op_type = 17; // Software interrupt
else
op_type = 16; // Conditional branch
break;
case 0xe0:
op_type = 18; // Unconditional branch
break;
case 0xf0:
op_type = 19; // Long branch with link
break;
}
return op_type;
}
int CUnasmARMDlg::do_dis_thumb (FILE * fd_src, FILE * fd_tar,
long addr, long start, int op_type,
unsigned char byte1, unsigned char byte2)
{
char fourbytes[4], str[128];
unsigned long tar_addr;
char temp[128];
int op, Rd, Rs, Rn, Ro, Rb, offset5, Cond, LB, HS;
char *op_name = {"MOV CMP ADD SUB "};
char *op_name1 = {"AND EOR LSL LSR ASR ADC SBC ROR TST NEG CMP CMN ORR MUL BIC MVN "};
char *op_name2 = {"LSL LSR ASR "};
char *cond_name = {"BEQ BNE BCS BCC BMI BPL BVS BVC BHI BLS BGE BLT BGT BLE "};
char *op_name3 = {"STR STRBLDR LDRB"};
char *op_name4 = {"STRHLDSBLDRHLDSH"};
char *op_name5 = {"STR LDR STRBLDRB"};
char *op_name6 = {"ADD CMP MOV BX "};
long cur_loc;
int len;
CrLf = 0;
if (m_Hex)
{
sprintf (str, "%08x %02X%02X ", addr, byte1, byte2);
}
else
{
sprintf (str, "%08x ", addr);
}
switch (op_type)
{
case 1:
op = (byte1 & 0x18) >> 3;
memcpy (temp, &op_name2[op << 2], 4);
temp[4] = '\0';
strcat (temp, " ");
offset5 = ( (byte1 & 7) << 2) | ( (byte2 & 0xc0) >> 6);
if (op)
{
if (offset5 == 0)
offset5 = 32;
}
Rd = byte2 & 7;
Rs = (byte2 & 0x38) >> 3;
if (Rd != Rs)
{
sprintf (&temp[8], "R%d, R%d, #%d", Rd, Rs, offset5);
if ( (Rs == regNo) && (!op) )
{
len = strlen (temp);
if (offset5 < 10)
sprintf (&temp[len], " ;%08x", regValue << offset5);
else
sprintf (&temp[len], " ;%08x", regValue << offset5);
}
}
else
{
sprintf (&temp[8], "R%d, #%d", Rd, offset5);
if ( (Rs == regNo) && (!op) )
{
len = strlen (temp);
if (offset5 < 10)
sprintf (&temp[len], " ;%08x", regValue << offset5);
else
sprintf (&temp[len], " ;%08x", regValue << offset5);
}
}
regNo = -1;
strcat (str, temp);
break;
case 2:
Rn = ( (byte1 & 1) << 2) | ( (byte2 & 0xc0) >> 6);
Rd = byte2 & 7;
Rs = (byte2 & 0x38) >> 3;
if (byte1 & 2)
strcpy (temp, "SUB ");
else
strcpy (temp, "ADD ");
if (byte1 & 4)
{ // Immediate operation
if (Rn == 0)
{
temp[0] = 'M'; // ADD rd, rs, #0 -> MOV rd, rs
temp[1] = 'O';
temp[2] = 'V';
sprintf (&temp[8], "R%d, R%d", Rd, Rs);
}
else
{
sprintf (&temp[8], "R%d, R%d, #%d", Rd, Rs, Rn);
}
}
else
{ // Register operation
sprintf (&temp[8], "R%d, R%d, R%d",
Rd, Rs, Rn);
}
regNo = -1;
strcat (str, temp);
break;
case 3:
op = (byte1 & 0x18) >> 3;
memcpy (temp, &op_name[op << 3], 8);
Rd = byte1 & 7;
if ( (Rd == 15) && (op == 0) )
CrLf = 1;
if (byte2 > 9)
sprintf (&temp[8], "%s, #0x%02x", RegisterName[Rd], byte2);
else
sprintf (&temp[8], "%s, #%d", RegisterName[Rd], byte2);
if (!op)
{
regNo = Rd;
regValue = byte2;
}
if (op == 2)
{
if (Rd == regNo)
{
len = strlen (temp);
if (byte2 > 9)
sprintf (&temp[len], " ;%08x", regValue + byte2);
else
sprintf (&temp[len], " ;%08x", regValue + byte2);
regNo = -1;
}
}
strcat (str, temp);
break;
case 4:
op = ( (byte1 & 3) << 2) | ( (byte2 & 0xc0) ) >> 6;
memcpy (temp, &op_name1[op << 2], 4);
temp[4] = '\0';
strcat (temp, " ");
Rd = byte2 & 7;
Rs = (byte2 & 0x38) >> 3;
sprintf (&temp[8], "R%d, R%d", Rd, Rs);
regNo = -1;
strcat (str, temp);
break;
case 5:
op = byte1 & 3;
memcpy (temp, &op_name6[op << 2], 4);
temp[4] = '\0';
strcat (temp, " ");
if (op == 3)
{ // BX
Rs = (byte2 & 0x38) >> 3;
HS = ( (byte2 & 0xc0) >> 6) & 3;
if (HS == 1)
Rs += 8;
sprintf (temp, "BX %s", RegisterName[Rs]);
CrLf = 1;
}
else
{
Rs = (byte2 & 0x38) >> 3;
Rd = byte2 & 7;
HS = ( (byte2 & 0xc0) >> 6) & 3;
if (HS == 0)
{
strcat (temp, "??????");
}
else
{
if (HS == 1)
Rs += 8;
if (HS == 2)
Rd += 8;
if (HS == 3)
{
Rs += 8;
Rd += 8;
}
if ( (Rd == 15) && (op == 2) ) // MOV PC, ...
CrLf = 1;
sprintf (&temp[8], "%s, %s", RegisterName[Rd], RegisterName[Rs]);
}
}
strcat (str, temp);
regNo = -1;
break;
case 6:
float f;
Rd = byte1 & 7;
tar_addr = ( (byte2 << 2) + addr + 4) & 0xfffffffc;
cur_loc = ftell (fd_src);
fseek (fd_src, tar_addr - start, SEEK_SET);
fread ( fourbytes, 1, 4, fd_src);
fseek (fd_src, cur_loc, SEEK_SET);
if (Rd < 10)
{
if ( (unsigned) fourbytes[0] >= '0')
{
if (m_Radio1)
{
( (char *) (&f) ) [0] = fourbytes[3];
( (char *) (&f) ) [1] = fourbytes[2];
( (char *) (&f) ) [2] = fourbytes[1];
( (char *) (&f) ) [3] = fourbytes[0];
sprintf (temp, "LDR R%d, 0x%08x ;%02x%02x%02x%02x(%g)",
Rd, tar_addr, 0xff & fourbytes[0],
0xff & fourbytes[1], 0xff & fourbytes[2],
0xff & fourbytes[3], f);
}
else
{
( (char *) (&f) ) [0] = fourbytes[0];
( (char *) (&f) ) [1] = fourbytes[1];
( (char *) (&f) ) [2] = fourbytes[2];
( (char *) (&f) ) [3] = fourbytes[3];
sprintf (temp, "LDR R%d, 0x%08x ;%02x%02x%02x%02x(%g)",
Rd, tar_addr, 0xff & fourbytes[3],
0xff & fourbytes[2], 0xff & fourbytes[1],
0xff & fourbytes[0], f);
}
}
else
{
if (m_Radio1)
{
sprintf (temp, "LDR R%d, 0x%08x ;%02x%02x%02x%02x",
Rd, tar_addr, 0xff & fourbytes[0],
0xff & fourbytes[1], 0xff & fourbytes[2],
0xff & fourbytes[3]);
}
else
{
sprintf (temp, "LDR R%d, 0x%08x ;%02x%02x%02x%02x",
Rd, tar_addr, 0xff & fourbytes[3],
0xff & fourbytes[2], 0xff & fourbytes[1],
0xff & fourbytes[0]);
}
}
}
else
{
if ( (unsigned) fourbytes[0] >= '0')
{
if (m_Radio1)
{
( (char *) (&f) ) [0] = fourbytes[3];
( (char *) (&f) ) [1] = fourbytes[2];
( (char *) (&f) ) [2] = fourbytes[1];
( (char *) (&f) ) [3] = fourbytes[0];
sprintf (temp, "LDR R%d, 0x%08x ;%02x%02x%02x%02x(%g)",
Rd, tar_addr, 0xff & fourbytes[0],
0xff & fourbytes[1], 0xff & fourbytes[2],
0xff & fourbytes[3], f);
}
else
{
( (char *) (&f) ) [0] = fourbytes[0];
( (char *) (&f) ) [1] = fourbytes[1];
( (char *) (&f) ) [2] = fourbytes[2];
( (char *) (&f) ) [3] = fourbytes[3];
sprintf (temp, "LDR R%d, 0x%08x ;%02x%02x%02x%02x(%g)",
Rd, tar_addr, 0xff & fourbytes[3],
0xff & fourbytes[2], 0xff & fourbytes[1],
0xff & fourbytes[0], f);
}
}
else
{
if (m_Radio1)
{
sprintf (temp, "LDR R%d, 0x%08x ;%02x%02x%02x%02x",
Rd, tar_addr, 0xff & fourbytes[0],
0xff & fourbytes[1], 0xff & fourbytes[2],
0xff & fourbytes[3]);
}
else
{
sprintf (temp, "LDR R%d, 0x%08x ;%02x%02x%02x%02x",
Rd, tar_addr, 0xff & fourbytes[3],
0xff & fourbytes[2], 0xff & fourbytes[1],
0xff & fourbytes[0]);
}
}
}
strcat (str, temp);
regNo = -1;
break;
case 7:
LB = (byte1 & 0x0c) >> 2;
Ro = ( (byte1 & 1) << 2) | ( (byte2 & 0xc0) >> 6);
Rd = byte2 & 7;
Rb = (byte2 & 0x38) >> 3;
memcpy (temp, &op_name3[LB << 2], 4);
temp[4] = '\0';
strcat (temp, " ");
sprintf (&temp[8], "R%d, [R%d, R%d]", Rd, Rb, Ro);
strcat (str, temp);
regNo = -1;
break;
case 8:
HS = (byte1 & 0x0c) >> 2;
Ro = ( (byte1 & 1) << 2) | ( (byte2 & 0xc0) >> 6);
Rd = byte2 & 7;
Rb = (byte2 & 0x38) >> 3;
memcpy (temp, &op_name4[HS << 2], 4);
temp[4] = '\0';
strcat (temp, " ");
sprintf (&temp[8], "R%d, [R%d, R%d]", Rd, Rb, Ro);
strcat (str, temp);
regNo = -1;
break;
case 9:
LB = (byte1 & 0x18) >> 3;
offset5 = ( (byte1 & 7) << 2) | ( (byte2 & 0xc0) >> 6);
Rd = byte2 & 7;
Rb = (byte2 & 0x38) >> 3;
memcpy (temp, &op_name5[LB << 2], 4);
temp[4] = '\0';
strcat (temp, " ");
if (LB < 2)
{ // WORD
sprintf (&temp[8], "R%d, [R%d, #0x%02x]", Rd, Rb, offset5 << 2);
}
else
{
sprintf (&temp[8], "R%d, [R%d, #0x%02x]", Rd, Rb, offset5);
}
strcat (str, temp);
regNo = -1;
break;
case 10:
offset5 = ( (byte1 & 7) << 2) | ( (byte2 & 0xc0) >> 6);
Rd = byte2 & 7;
Rb = (byte2 & 0x38) >> 3;
if (byte1 & 8)
strcpy (temp, "LDRH ");
else
strcpy (temp, "STRH ");
sprintf (&temp[8], "R%d, [R%d, #0x%02x]", Rd, Rb, offset5 << 1);
strcat (str, temp);
regNo = -1;
break;
case 11:
if (byte1 & 8) // LOAD
strcpy (temp, "LDR ");
else
strcpy (temp, "STR ");
Rd = byte1 & 7;
sprintf (&temp[8], "R%d, [R13, #0x%02x]", Rd, byte2 << 2);
strcat (str, temp);
regNo = -1;
break;
case 12:
Rd = byte1 & 7;
if (byte1 & 8)
sprintf (temp, "ADD R%d, SP, #0x%02x", Rd, byte2 << 2);
else
{
sprintf (temp, "ADR R%d, 0x%08x", Rd, ( (byte2 << 2) + addr + 4) & ~3);
}
strcat (str, temp);
regNo = -1;
break;
case 13:
if (byte2 & 0x80)
{
sprintf (temp, "SUB SP, #0x%02x", (byte2 & 0x7f) << 2);
}
else
{
sprintf (temp, "ADD SP, #0x%02x", (byte2 & 0x7f) << 2);
}
strcat (str, temp);
regNo = -1;
break;
case 14:
if (byte1 & 8)
strcpy (temp, "POP {");
else
strcpy (temp, "PUSH {");
LB = strlen (temp);
if (byte2)
{
offset5 = byte2;
for (op = 0; op < 8; op++)
{
if (offset5 & 1)
{
temp[LB++] = 'R';
temp[LB++] = op + '0';
temp[LB++] = ',';
}
offset5 >>= 1;
}
LB--; // Discard ','
}
if (byte1 & 1)
{
if (byte2)
temp[LB++] = ',';
if (byte1 & 8)
{ // POP {Rlist, PC}
temp[LB++] = 'P';
temp[LB++] = 'C';
CrLf = 1;
}
else
{ // PUSH {Rlist, LR}
temp[LB++] = 'L';
temp[LB++] = 'R';
}
}
temp[LB++] = '}';
temp[LB] = '\0';
strcat (str, temp);
regNo = -1;
break;
case 15:
if (byte1 & 8)
strcpy (temp, "LDMIA ");
else
strcpy (temp, "STMIA ");
Rb = byte1 & 7;
sprintf (&temp[8], "R%d!, {", Rb);
LB = strlen (temp);
if (byte2)
{
offset5 = byte2;
for (op = 0; op < 8; op++)
{
if (offset5 & 1)
{
temp[LB++] = 'R';
temp[LB++] = op + '0';
temp[LB++] = ',';
}
offset5 >>= 1;
}
LB--; // Discard ','
}
temp[LB++] = '}';
temp[LB] = '\0';
strcat (str, temp);
regNo = -1;
break;
case 16:
Cond = (byte1 & 0x0f);
if (byte2 & 0x80)
{
offset5 = byte2;
( (unsigned char *) &offset5) [1] = 0xff;
( (unsigned char *) &offset5) [2] = 0xff;
( (unsigned char *) &offset5) [3] = 0xff;
tar_addr = addr + 4 + (offset5 << 1);
}
else
tar_addr = (byte2 << 1) + addr + 4;
memcpy (temp, &cond_name[Cond << 2], 4);
sprintf (&temp[4], " 0x%08x", tar_addr);
strcat (str, temp);
regNo = -1;
break;
case 17:
sprintf (temp, "SWI 0x%02x", byte2);
strcat (str, temp);
regNo = -1;
break;
case 18:
offset5 = ( (byte1 & 0x7) << 8) | byte2;
if (offset5 & 0x400)
{
( (unsigned char *) &offset5) [1] |= 0xf8;
( (unsigned char *) &offset5) [2] = 0xff;
( (unsigned char *) &offset5) [3] = 0xff;
}
tar_addr = (offset5 << 1) + addr + 4;
sprintf (temp, "B 0x%08x", tar_addr);
strcat (str, temp);
regNo = -1;
break;
case 19:
strcpy (temp, "?????? ; Bad statement");
strcat (str, temp);
regNo = -1;
break;
}
strcat (str, "\n");
fwrite (str, 1, strlen (str), fd_tar);
if (CrLf)
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
int CUnasmARMDlg::dis_arm_one (unsigned char bin_code1,
unsigned char bin_code2,
unsigned char bin_code3,
unsigned char bin_code4)
{
unsigned uch1, uch4;
int op_type; // 1-15
uch1 = bin_code1 & 0x0f; // 0000 1111
uch4 = bin_code4 & 0xf0; // 1111 0000
if (uch1 == 1)
{
if ( (bin_code2 == 0x2f) && (bin_code3 == 0xff) && (uch4 == 0x10) )
return 5;
else
{
if ( (uch4 == 0x90) && ( (bin_code3 & 15) == 0) )
return 4;
}
}
if ( (uch1 == 0) && (uch4 == 0x90) )
{
if (bin_code2 & 0x80)
return 3;
else
return 2;
}
if ( (uch1 == 0) || (uch1 == 1) )
{
if ( (uch4 & 0x90) == 0x90)
{
if ( (bin_code2 & 0x40) == 0x40)
return 7;
else
{
if ( (bin_code3 & 15) == 0)
return 6;
}
}
}
if (uch1 < 4)
{
if ( (uch1 == 1) && ( (bin_code2 & 0xbf) == 0x0f)
&& (bin_code4 == 0) && ( (bin_code3 & 0x0f) == 0) )
return 16;
if ( (uch1 == 1) && ( (bin_code2 & 0xb0) == 0x20)
&& (bin_code3 == 0xf0) && (uch4 == 0) )
return 17;
if ( ( (uch1 & 0x0d) == 1) && ( (bin_code2 & 0xb0) == 0x20)
&& ( (bin_code3 & 0xf0) == 0xf0) )
return 18;
else
return 1;
}
if (uch1 < 8)
{
if ( ( (uch4 & 0x10) == 0x10) && ( (uch1 & 6) == 6) )
return 9;
else
return 8;
}
if (uch1 == 15)
return 15;
if (uch1 == 14)
{
if ( (uch4 & 0x10) == 0x10)
return 14;
else
return 13;
}
op_type = (uch1 >> 1) + 6;
return op_type;
}
int CUnasmARMDlg::do_dis_arm (FILE * fd_src, FILE * fd_tar, long addr, long start,
int op_type, unsigned char byte1, unsigned char byte2, unsigned char byte3, unsigned char byte4)
{
char fourbytes[4], str[128];
char temp[128];
int loc, sft_type;
int Opcode, Rn, Rd, Rm, Rs, RdLo, RdHi, CP;
unsigned int ImmValue;
int offset;
long cur_loc;
int cond;
char *cond_name = {"EQNECSCCMIPLVSVCHILSGELTGTLE"};
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
char *op_name1 = {"AND EOR SUB RSB ADD ADC SBC RSC TST TEQ CMP CMN ORR MOV BIC MVN "};
// For LDM/STM
int LPU;
char *op_name;
char *op_name2 = {"EDEAFDFAFAFDEAED"}; // Stack
char *op_name3 = {"DAIADBIBDAIADBIB"}; // Other
// For LDRH/...
int SH;
char *op_name4 = {"LDRH LDRSB LDRSH "};
char *Sft_name = {"lsl lsr asr ror "};
if (m_Hex)
{
sprintf (str, "%08x %02X%02X%02X%02X ", addr, byte1, byte2, byte3, byte4);
}
else
{
sprintf (str, "%08x ", addr);
}
cond = byte1 >> 4;
CrLf = 0;
switch (op_type)
{
case 1:
Opcode = ( (byte1 & 1) << 3) | (byte2 >> 5);
memcpy (temp, &op_name1[Opcode << 2], 4);
temp[4] = '\0';
strcat (temp, " ");
Rn = byte2 & 15;
Rd = byte3 >> 4;
if (byte1 & 2)
{ // Operand 2 is an imm value
ImmValue = ROR (byte4, byte3 & 15);
if ( (Opcode == 13) || (Opcode == 15) )
{
sprintf (&temp[8], "%s, #0x%-x",
RegisterName[Rd], ImmValue);
}
else
{
if ( (Opcode >= 8) && (Opcode <= 11) )
{
sprintf (&temp[8], "%s, #0x%-x",
RegisterName[Rn], ImmValue);
}
else
{
sprintf (&temp[8], "%s, %s, #0x%-x",
RegisterName[Rd], RegisterName[Rn], ImmValue);
}
}
}
else
{ // Operand 2 is a register
Rm = byte4 & 15;
if ( (Opcode >= 8) && (Opcode <= 11) )
{
sprintf (&temp[8], "%s, ", RegisterName[Rn]);
}
else
{
if ( (Opcode == 13) || (Opcode == 15) )
{
sprintf (&temp[8], "%s, ", RegisterName[Rd]);
}
else
{
sprintf (&temp[8], "%s, %s, ", RegisterName[Rd], RegisterName[Rn]);
}
}
loc = strlen (temp);
sprintf (&temp[loc], "%s, ", RegisterName[Rm]);
sft_type = (byte4 >> 5) & 3;
loc = strlen (temp);
memcpy (&temp[loc], &Sft_name[sft_type << 2], 4);
loc += 4;
if (byte4 & 0x10)
{
Rs = byte3 & 15;
sprintf (&temp[loc], "%s", RegisterName[Rs]);
}
else
{
Rs = ( (byte3 & 15) << 1) | ( (byte4 & 0x80) >> 7);
if (Rs == 0)
{
if (/*(Opcode != 13) && */sft_type)
{ // not MOV
if (sft_type == 3)
{ // ror
loc -= 4; // ror #0 -> rrx
strcpy (&temp[loc], "RRX");
}
else
strcpy (&temp[loc], "#32");
}
else
{
loc -= 6; // MOV
temp[loc] = '\0';
}
}
else
sprintf (&temp[loc], "#%d", Rs);
}
}
if (byte2 & 0x10)
{ // Set Condition codes
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
temp[5] = ( (Opcode >= 8) && (Opcode <= 11) ) ? ' ' : 'S';
}
else
{
temp[3] = ( (Opcode >= 8) && (Opcode <= 11) ) ? ' ' : 'S';
}
}
else
{
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
}
strcat (str, temp);
break;
case 2:
Rd = byte2 & 15;
Rn = byte3 >> 4;
Rs = byte3 & 15;
Rm = byte4 & 15;
if (byte2 & 0x20)
sprintf (temp, "MLA R%d, R%d, R%d, R%d",
Rd, Rm, Rs, Rn);
else
sprintf (temp, "MUL R%d, R%d, R%d",
Rd, Rm, Rs);
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
loc = 5;
}
else
loc = 3;
if (byte2 & 0x10)
temp[loc] = 'S';
strcat (str, temp);
break;
case 3:
RdHi = byte2 & 15;
RdLo = byte3 >> 4;
Rs = byte3 & 15;
Rm = byte4 & 15;
if (byte2 & 0x20)
{
sprintf (temp, "%cMLAL R%d, R%d, R%d, R%d",
(byte2 & 0x40) ? 'S' : 'U',
RdLo, RdHi, Rm, Rs);
}
else
{
sprintf (temp, "%cMULL R%d, R%d, R%d, R%d",
(byte2 & 0x40) ? 'S' : 'U',
RdLo, RdHi, Rm, Rs);
}
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[5] = cond_name[cond];
temp[6] = cond_name[cond+1];
loc = 7;
}
else
loc = 5;
if (byte2 & 0x10)
temp[loc] = 'S';
strcat (str, temp);
break;
case 4:
Rn = byte2 & 15;
Rd = byte3 >> 4;
Rm = byte4 & 15;
sprintf (temp, "SWP R%d, R%d, [R%d]",
Rd, Rm, Rn);
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
loc = 5;
}
else
loc = 3;
if (byte2 & 0x40)
temp[loc] = 'B';
strcat (str, temp);
break;
case 5:
Rn = byte4 & 15;
sprintf (temp, "BX %s", RegisterName[Rn]);
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[2] = cond_name[cond];
temp[3] = cond_name[cond+1];
}
strcat (str, temp);
CrLf = 1;
break;
case 6:
Rn = byte2 & 15;
Rd = byte3 >> 4;
Rm = byte4 & 15;
SH = (byte4 >> 5) & 3;
if (SH == 0)
{
strcat (str, "Bad SH!");
break;
}
SH = (SH - 1) << 3;
if (byte2 & 0x10)
{ // Load
memcpy (temp, &op_name4[SH], 8);
}
else
{ // Store
strcpy (temp, "STRH ");
}
if (byte1 & 1)
{ // Pre
sprintf (&temp[8], "R%d, [R%d, %cR%d]%c",
Rd, Rn,
(byte2 & 0x80) ? ' ' : '-', Rm,
(byte2 & 0x20) ? '!' : ' ');
}
else
{
sprintf (&temp[8], "R%d, [R%d], %cR%d",
Rd, Rn, (byte2 & 0x80) ? ' ' : '-', Rm);
}
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[6] = temp[4];
temp[5] = temp[3];
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 7:
Rn = byte2 & 15;
Rd = byte3 >> 4;
offset = (byte4 & 15) | ( (byte3 << 4) & 0xf0);
SH = (byte4 >> 5) & 3;
if (SH == 0)
{
strcat (str, "Bad SH!");
break;
}
SH = (SH - 1) << 3;
if (byte2 & 0x10)
{ // Load
memcpy (temp, &op_name4[SH], 8);
}
else
{ // Store
strcpy (temp, "STRH ");
}
if (byte1 & 1)
{ // Pre
if (byte2 & 0x80)
{
sprintf (&temp[8], "R%d, [R%d, #0x%-x]%c",
Rd, Rn, offset, (byte2 & 0x20) ? '!' : ' ');
}
else
{
sprintf (&temp[8], "R%d, [R%d, #-0x%-x]%c",
Rd, Rn, offset, (byte2 & 0x20) ? '!' : ' ');
}
}
else
{
if (byte2 & 0x80)
{
sprintf (&temp[8], "R%d, [R%d], #0x%0x", Rd, Rn, offset);
}
else
{
sprintf (&temp[8], "R%d, [R%d], #-0x%0x", Rd, Rn, offset);
}
}
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[6] = temp[4];
temp[5] = temp[3];
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 8:
if (byte2 & 0x10)
strcpy (temp, "LDR ");
else
strcpy (temp, "STR ");
if (byte2 & 0x40)
temp[3] = 'B';
Rn = byte2 & 15;
Rd = byte3 >> 4;
sprintf (&temp[8], "R%d, [R%d", Rd, Rn);
loc = strlen (temp);
if (byte1 & 1)
{ // Pre
if (byte1 & 2)
{ // offset is a register
temp[loc++] = ',';
temp[loc++] = ' ';
Rm = byte4 & 15;
if ( (byte2 & 0x80) == 0)
{
temp[loc++] = '-';
}
sprintf (&temp[loc], "R%d, ", Rm);
sft_type = (byte4 >> 5) & 3;
loc = strlen (temp);
memcpy (&temp[loc], &Sft_name[sft_type << 2], 4);
loc += 4;
Rs = ( (byte3 & 15) << 1) | ( (byte4 & 0x80) >> 7);
if (Rs == 0)
{
loc -= 6;
temp[loc++] = ']';
temp[loc] = '\0';
}
else
sprintf (&temp[loc], "#%d]", Rs);
}
else
{ // offset is imm value
offset = byte4 | ( (byte3 & 15) << 8);
if (Rn == 15)
{ // PC
loc -= 4;
cur_loc = ftell (fd_src);
if (byte2 & 0x80)
{
sprintf (&temp[loc], "0x%08x", addr + offset + 8);
fseek (fd_src, addr + offset + 8 - start, SEEK_SET);
}
else
{
sprintf (&temp[loc], "0x%08x", addr - offset + 8);
fseek (fd_src, addr - offset + 8 - start, SEEK_SET);
}
fread ( fourbytes, 1, 4, fd_src);
fseek (fd_src, cur_loc, SEEK_SET);
loc = strlen (temp);
if (Rd < 10)
{
if (m_Radio1)
{
sprintf (&temp[loc], " ;%02x%02x%02x%02x",
0xff & fourbytes[0],
0xff & fourbytes[1],
0xff & fourbytes[2],
0xff & fourbytes[3]);
}
else
{
sprintf (&temp[loc], " ;%02x%02x%02x%02x",
0xff & fourbytes[3],
0xff & fourbytes[2],
0xff & fourbytes[1],
0xff & fourbytes[0]);
}
}
else
{
if (m_Radio1)
{
sprintf (&temp[loc], " ;%02x%02x%02x%02x",
0xff & fourbytes[0],
0xff & fourbytes[1],
0xff & fourbytes[2],
0xff & fourbytes[3]);
}
else
{
sprintf (&temp[loc], " ;%02x%02x%02x%02x",
0xff & fourbytes[3],
0xff & fourbytes[2],
0xff & fourbytes[1],
0xff & fourbytes[0]);
}
}
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[6] = temp[4];
temp[5] = temp[3];
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
}
if (offset == 0)
{
temp[loc++] = ']';
temp[loc] = '\0';
}
else
{
if ( (byte2 & 0x80) == 0)
sprintf (&temp[loc], ", #-0x%-x]", offset);
else
sprintf (&temp[loc], ", #0x%-x]", offset);
}
}
if (byte2 & 0x20)
{ // write-back
loc = strlen (temp);
temp[loc++] = '!';
temp[loc] = '\0';
}
}
else
{ // Post
temp[loc++] = ']';
if (byte1 & 2)
{ // offset is a register
Rm = byte4 & 15;
temp[loc++] = ',';
temp[loc++] = ' ';
if ( (byte2 & 0x80) == 0)
temp[loc++] = '-';
sprintf (&temp[loc], "R%d, ", Rm);
sft_type = (byte4 >> 5) & 3;
loc = strlen (temp);
memcpy (&temp[loc], &Sft_name[sft_type << 2], 4);
loc += 4;
Rs = ( (byte3 & 15) << 1) | ( (byte4 & 0x80) >> 7);
if (Rs == 0)
{
loc -= 6;
temp[loc] = '\0';
}
else
sprintf (&temp[loc], "#%d", Rs);
}
else
{ // offset is imm value
offset = byte4 | ( (byte3 & 15) << 8);
if (offset == 0)
{
temp[loc] = '\0';
}
else
{
if ( (byte2 & 0x80) == 0)
sprintf (&temp[loc], ", #-0x%-x", offset);
else
sprintf (&temp[loc], ", #0x%-x", offset);
}
}
if (byte2 & 0x20)
{ // write-back
if (temp[3] == 'B')
temp[4] = 'T';
else
temp[3] = 'T';
}
}
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[6] = temp[4];
temp[5] = temp[3];
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 9:
strcat (str, "Undefined instruction");
break;
case 10:
Rn = byte2 & 15;
if (Rn == 13)
op_name = op_name2;
else
op_name = op_name3;
LPU = ( (byte1 & 1) << 1) | ( (byte2 >> 2) & 4) | ( (byte2 >> 7) & 1);
if (LPU & 4)
strcpy (temp, "LDM ");
else
strcpy (temp, "STM ");
LPU <<= 1;
temp[3] = op_name[LPU];
temp[4] = op_name[LPU+1];
sprintf (&temp[8], "R%d%c, {", Rn, (byte2 & 0x20) ? '!' : ' ');
offset = ( (byte3 << 8) | byte4) & 0xffff;
loc = strlen (temp);
for (Opcode = 0; Opcode < 10; Opcode++)
{
if (offset & 1)
{
temp[loc++] = 'R';
temp[loc++] = Opcode + '0';
temp[loc++] = ',';
}
offset >>= 1;
}
for (Opcode = 10; Opcode < 16; Opcode++)
{
if (offset & 1)
{
if (Opcode == 15)
{
temp[loc++] = 'P';
temp[loc++] = 'C';
temp[loc++] = ',';
if (temp[0] == 'L') // LDM
CrLf = 1;
}
else
{
if (Opcode == 14)
{
temp[loc++] = 'L';
temp[loc++] = 'R';
temp[loc++] = ',';
}
else
{
temp[loc++] = 'R';
temp[loc++] = '1';
temp[loc++] = Opcode - 10 + '0';
temp[loc++] = ',';
}
}
}
offset >>= 1;
}
if (temp[loc-1] == ',')
loc--;
temp[loc++] = '}';
if (byte2 & 0x40)
temp[loc++] = '^';
temp[loc] = '\0';
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[6] = temp[4];
temp[5] = temp[3];
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 11:
if (byte1 & 1)
{ // Branch with link
strcpy (temp, "BL ");
loc = 2;
}
else
{
strcpy (temp, "B ");
loc = 1;
}
offset = byte4 | (byte3 << 8) | (byte2 << 16);
if (byte2 & 0x80) // Sign extended
( (unsigned char *) &offset) [3] |= 0xff;
offset = addr + 8 + (offset << 2);
sprintf (&temp[8], "0x%08x", offset);
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[loc++] = cond_name[cond];
temp[loc] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 12:
Rn = byte2 & 15;
Rd = byte3 >> 4;
CP = byte3 & 15;
if (byte2 & 0x10) // Load
strcpy (temp, "LDC ");
else
strcpy (temp, "STC ");
if (byte2 & 0x40)
temp[3] = 'N';
offset = byte4 << 2;
if (byte1 & 1)
{ // Pre
if (byte2 & 0x80)
{
sprintf (&temp[8], "P%d, C%d, [R%d, #0x%-x]%c",
CP, Rd, Rn, offset, (byte2 & 0x20) ? '!' : ' ');
}
else
{
sprintf (&temp[8], "P%d, C%d, [R%d, #-0x%-x]%c",
CP, Rd, Rn, offset, (byte2 & 0x20) ? '!' : ' ');
}
}
else
{
if (byte2 & 0x80)
{
sprintf (&temp[8], "P%d, C%d, [R%d], #0x%-x",
CP, Rd, Rn, offset);
}
else
{
sprintf (&temp[8], "P%d, C%d, [R%d], #-0x%-x",
CP, Rd, Rn, offset);
}
}
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[5] = temp[3];
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 13:
sprintf (temp, "CDP P%d, %d, C%d, C%d, C%d, %d",
(byte3 & 15), (byte2 >> 4), (byte3 >> 4),
(byte2 & 15), (byte4 & 15), (byte4 >> 5) );
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 14:
if (byte2 & 0x10)
strcpy (temp, "MRC ");
else
strcpy (temp, "MCR ");
sprintf (&temp[8], "P%d, %d, R%d, C%d, C%d, %d",
(byte3 & 15), (byte2 >> 5), (byte3 >> 4),
(byte2 & 15), (byte4 & 15), (byte4 >> 5) );
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 15:
sprintf (temp, "SWI 0x%02x%02x%02x",
byte2, byte3, byte4);
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 16:
Rd = byte3 >> 4;
if (byte2 & 0x40)
sprintf (temp, "MRS R%d, SPSR", Rd);
else
sprintf (temp, "MRS R%d, CPSR", Rd);
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 17:
Rm = byte4 & 15;
strcpy (temp, "MSR CPSR_");
if (byte2 & 0x40) temp[8] = 'S';
loc = strlen (temp);
if (byte2 & 1) temp[loc++] = 'C';
if (byte2 & 2) temp[loc++] = 'X';
if (byte2 & 4) temp[loc++] = 'S';
if (byte2 & 8) temp[loc++] = 'F';
sprintf (&temp[loc], ", R%d", Rm);
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
case 18:
strcpy (temp, "MSR CPSR_");
if (byte2 & 0x40) temp[8] = 'S';
loc = strlen (temp);
if (byte2 & 1) temp[loc++] = 'C';
if (byte2 & 2) temp[loc++] = 'X';
if (byte2 & 4) temp[loc++] = 'S';
if (byte2 & 8) temp[loc++] = 'F';
if (byte1 & 2)
{ // Operand 2 is an imm value
ImmValue = ROR (byte4, byte3 & 15);
sprintf (&temp[loc], ", #0x%-8x", ImmValue);
}
else
{ // Operand 2 is a register
Rm = byte4 & 15;
sprintf (&temp[loc], ", R%d", Rm);
}
if (cond < 14)
{ // Conditional
cond <<= 1;
temp[3] = cond_name[cond];
temp[4] = cond_name[cond+1];
}
strcat (str, temp);
break;
default:
sprintf (temp, "No=%d", op_type);
strcat (str, temp);
break;
}
strcat (str, "\n");
fwrite (str, 1, strlen (str), fd_tar);
if (CrLf)
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
unsigned long CUnasmARMDlg::ROR (unsigned char value, unsigned char rotate)
{
int i;
unsigned int result = value;
for ( i = 0; i < rotate << 1; i++)
{
if (result & 1)
{
result >>= 1;
( (unsigned char *) &result) [3] |= 0x80;
}
else
result >>= 1;
}
return result;
}
void CUnasmARMDlg::OnButton1()
{
// TODO: Add your control notification handler code here
int i;
/*
char sss[120];
unsigned short sss1[120];
memset(sss, 0, 120);
sss1[0] = 0x542F;
sss1[1] = 0x52A8;
sss1[2] = 0x547C;
sss1[3] = 0x53EB;
sss1[4] = 0x8F6C;
sss1[5] = 0x63A5;
sss1[6] = 0x04ff;
int iii = WideCharToMultiByte( CP_ACP, 0, sss1, 7, sss, 120, NULL, NULL);
AfxMessageBox(sss);
return;
*/
CFileDialog myFD (TRUE, NULL, NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"BIN files (*.bin)|*.bin|All files (*.*)|*.*||");
i = myFD.DoModal();
if (i == IDOK)
{
m_filename1 = myFD.GetPathName();
UpdateData (FALSE);
}
}
void CUnasmARMDlg::OnButton2()
{
// TODO: Add your control notification handler code here
int i;
CFileDialog myFD (TRUE, NULL, NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"Ref files (*.ref)|*.ref||");
i = myFD.DoModal();
if (i == IDOK)
{
m_filename2 = myFD.GetPathName();
UpdateData (FALSE);
}
}
void CUnasmARMDlg::OnButton3()
{
// TODO: Add your control notification handler code here
int i;
CFileDialog myFD (FALSE, NULL, NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"ASM files (*.asm)|*.asm||");
i = myFD.DoModal();
if (i == IDOK)
{
m_filename3 = myFD.GetPathName();
UpdateData (FALSE);
}
}
int CUnasmARMDlg::dump_byte_nochar (FILE * fd_src, FILE * fd_tar, long addr, long addr1, long addr2)
{
int i;
long bytes;
char src_buffer[16384];
i = fseek (fd_src, addr1, SEEK_SET);
bytes = addr2 - addr1 + 1;
while (bytes)
{
int loc, times_16, remains_16;
int bytes1 = (bytes <= 16384) ? bytes : 16384;
char str[128];
int k, l;
if (addr1 & 15)
{
if ( (16 - (addr1 & 15) ) < bytes1)
bytes1 = 16 - (addr1 & 15);
}
bytes -= bytes1;
i = fread ( src_buffer, 1, bytes1, fd_src);
if (i > 0)
{
bytes1 = i; // Bytes actually
times_16 = bytes1 >> 4;
remains_16 = bytes1 & 0x0f;
l = 0;
while (times_16)
{
sprintf (str, "%08x ", addr + addr1);
for (k = 0; k < 16; k++, l++)
{
loc = strlen (str);
sprintf (&str[loc], "%02X ", 0xff & src_buffer[l]);
}
str[33] = '-';
loc = strlen (str);
str[loc-1] = '\n';
fwrite (str, 1, loc, fd_tar);
times_16--;
addr1 += 16;
}
if (remains_16)
{
memset (str, ' ', 128);
sprintf (str, "%08x ", addr + addr1);
for (k = 0; k < remains_16; k++, l++)
{
loc = strlen (str);
sprintf (&str[loc], "%02X ", 0xff & src_buffer[l]);
}
loc = strlen (str);
str[loc-1] = '\n';
if (remains_16 > 8)
str[33] = '-';
fwrite (str, 1, loc, fd_tar);
addr1 += remains_16;
}
}
}
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
int CUnasmARMDlg::dump_double (FILE * fd_src, FILE * fd_tar, long addr, long addr1, long addr2)
{
int i, l, bytes1;
long bytes;
char src_buffer[16384];
int loc, times_8;
char str[128];
double theValue;
i = fseek (fd_src, addr1, SEEK_SET);
bytes = (addr2 - addr1 + 1) & ~7;
while (bytes)
{
bytes1 = (bytes <= 16384) ? bytes : 16384;
bytes -= bytes1;
i = fread ( src_buffer, 1, bytes1, fd_src);
if (i > 0)
{
times_8 = (i >> 3);
for (i = 0, l = 0; i < times_8; i++, l += 8)
{
sprintf (str, "%08x ", addr + addr1);
loc = strlen (str);
if (m_Radio1)
{
( (char *) &theValue) [0] = src_buffer[l+7];
( (char *) &theValue) [1] = src_buffer[l+6];
( (char *) &theValue) [2] = src_buffer[l+5];
( (char *) &theValue) [3] = src_buffer[l+4];
( (char *) &theValue) [4] = src_buffer[l+3];
( (char *) &theValue) [5] = src_buffer[l+2];
( (char *) &theValue) [6] = src_buffer[l+1];
( (char *) &theValue) [7] = src_buffer[l];
sprintf (&str[loc], "%02X%02X%02X%02X%02X%02X%02X%02X ;%g\n",
0xff & src_buffer[l],
0xff & src_buffer[l+1],
0xff & src_buffer[l+2],
0xff & src_buffer[l+3],
0xff & src_buffer[l+4],
0xff & src_buffer[l+5],
0xff & src_buffer[l+6],
0xff & src_buffer[l+7],
theValue);
}
else
{
( (char *) &theValue) [0] = src_buffer[l];
( (char *) &theValue) [1] = src_buffer[l+1];
( (char *) &theValue) [2] = src_buffer[l+2];
( (char *) &theValue) [3] = src_buffer[l+3];
( (char *) &theValue) [4] = src_buffer[l+4];
( (char *) &theValue) [5] = src_buffer[l+5];
( (char *) &theValue) [6] = src_buffer[l+6];
( (char *) &theValue) [7] = src_buffer[l+7];
sprintf (&str[loc], "%02X%02X%02X%02X%02X%02X%02X%02X ;%g\n",
0xff & src_buffer[l+7],
0xff & src_buffer[l+6],
0xff & src_buffer[l+5],
0xff & src_buffer[l+4],
0xff & src_buffer[l+3],
0xff & src_buffer[l+2],
0xff & src_buffer[l+1],
0xff & src_buffer[l],
theValue);
}
fwrite (str, 1, strlen (str), fd_tar);
addr1 += 8;
}
}
}
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
int CUnasmARMDlg::dump_float (FILE * fd_src, FILE * fd_tar, long addr, long addr1, long addr2)
{
int i, l, bytes1;
long bytes;
char src_buffer[16384];
int loc, times_4;
char str[128];
float theValue;
i = fseek (fd_src, addr1, SEEK_SET);
bytes = (addr2 - addr1 + 1) & ~3;
while (bytes)
{
bytes1 = (bytes <= 16384) ? bytes : 16384;
bytes -= bytes1;
i = fread ( src_buffer, 1, bytes1, fd_src);
if (i > 0)
{
times_4 = (i >> 2);
for (i = 0, l = 0; i < times_4; i++, l += 4)
{
sprintf (str, "%08x ", addr + addr1);
loc = strlen (str);
if (m_Radio1)
{
( (char *) &theValue) [0] = src_buffer[l+3];
( (char *) &theValue) [1] = src_buffer[l+2];
( (char *) &theValue) [2] = src_buffer[l+1];
( (char *) &theValue) [3] = src_buffer[l];
sprintf (&str[loc], "%02X%02X%02X%02X ;%g\n",
0xff & src_buffer[l],
0xff & src_buffer[l+1],
0xff & src_buffer[l+2],
0xff & src_buffer[l+3],
theValue);
}
else
{
( (char *) &theValue) [0] = src_buffer[l];
( (char *) &theValue) [1] = src_buffer[l+1];
( (char *) &theValue) [2] = src_buffer[l+2];
( (char *) &theValue) [3] = src_buffer[l+3];
sprintf (&str[loc], "%02X%02X%02X%02X ;%g\n",
0xff & src_buffer[l+3],
0xff & src_buffer[l+2],
0xff & src_buffer[l+1],
0xff & src_buffer[l],
theValue);
}
fwrite (str, 1, strlen (str), fd_tar);
addr1 += 4;
}
}
}
fwrite ("\n", 1, 1, fd_tar);
return 0;
}
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏记录
参与人
雪币
留言
时间
Youlor
为你点赞~
2024-5-31 03:23
伟叔叔
为你点赞~
2024-2-14 00:09
QinBeast
为你点赞~
2024-1-16 04:16
shinratensei
为你点赞~
2024-1-10 00:11
心游尘世外
为你点赞~
2023-12-28 00:04
飘零丶
为你点赞~
2023-12-16 00:46
PLEBFE
为你点赞~
2023-3-18 02:50
赞赏
他的文章
- 一种简单的Android全局注入方案 28923
- [分享]源码百度云加速 5355
- 定位Method的dalvik字节码 6403
- 测试 4202
- [讨论]上个看雪都被劫持了, 7797
赞赏
雪币:
留言: