📄 unassmbl.c
字号:
static int modrm_extend;
do_modrm(char t)
{
int m = mod(modrm());
int r = rm(modrm());
int extend = (addrsize == 32) ? 4 : 2;
int pick_signed = default_pick_sign;
if (m == 3)
{
reg_name(r, t);
return;
}
if ((m == 0) && (r == 5) && (addrsize == 32))
{
ua_str("%p:[");
ohex('d', extend, 0, addrsize, 0);
uputchar(']');
return;
}
if ((m == 0) && (r == 6) && (addrsize == 16))
{
ua_str("%p:[");
ohex('w', extend, 0, addrsize, 0);
uputchar(']');
return;
}
if ((addrsize != 32) || (r != 4))
ua_str("%p:[");
if (addrsize == 16)
{
static char *r_str[] = {
"bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" };
uprintf(r_str[r]);
pick_signed |= 2;
}
else
{
if (r == 4)
pick_signed |= do_sib(m);
else
{
uprintf(reg_names[2][r]);
pick_signed |= 2;
}
}
modrm_extend = extend;
ohex("xbv"[m], extend, 1, addrsize, pick_signed);
uputchar(']');
}
/*------------------------------------------------------------------------*/
static floating_point(int e1)
{
int esc = e1*8 + reg(modrm());
if (mod(modrm()) == 3)
{
if (fspecial[esc])
{
if (fspecial[esc][0] && (fspecial[esc][0][0] == '*'))
{
ua_str(fspecial[esc][0]+1);
}
else
{
ua_str(fspecial[esc][rm(modrm())]);
}
}
else
{
ua_str(floatops[esc]);
ua_str(" %EF");
}
}
else
{
ua_str(floatops[esc]);
ua_str(" %EF");
}
}
/*------------------------------------------------------------------------*/
static percent(char c, char **tptr)
{
word32 vofs, v, delta;
char *name;
int default_signed = default_pick_sign;
char t = *(*tptr)++, it;
int extend = (addrsize == 32) ? 4 : 2;
int iextend;
if (c != '+')
{
if (t == '-')
{
default_signed = 1;
t = *(*tptr)++;
}
else if (t == '+')
{
default_signed = 2;
t = *(*tptr)++;
}
}
switch (c)
{
case 'A':
ohex(t, extend, 0, addrsize, 0);
break;
case 'C':
uprintf("cr%d", reg(modrm()));
break;
case 'D':
uprintf("dr%d", reg(modrm()));
break;
case 'E':
do_modrm(t);
break;
case 'G':
if (t == 'F')
reg_name(rm(modrm()), t);
else
reg_name(reg(modrm()), t);
break;
case 'I':
it = *(*tptr)++;
switch (t)
{
case 'b':
iextend = 1;
break;
case 'v':
iextend = extend;
break;
default:
iextend = 0;
break;
}
ohex(it, iextend, 0, opsize, default_signed);
break;
case 'J':
switch (bytes(t))
{
case 1:
vofs = (int8)getbyte();
break;
case 2:
vofs = getbyte();
vofs += getbyte()<<8;
vofs = (int16)vofs;
break;
case 4:
vofs = (word32)getbyte();
vofs |= (word32)getbyte() << 8;
vofs |= (word32)getbyte() << 16;
vofs |= (word32)getbyte() << 24;
break;
}
name = syms_val2name(vofs+vaddr, &delta);
uprintf("%s", name);
if (delta)
uprintf("+%lu (0x%lx %c)", delta, vofs+vaddr,
(vofs & 0x80000000L) ? 0x1e : 0x1f);
break;
case 'M':
do_modrm(t);
break;
case 'O':
ua_str("%p:[");
ohex(t, extend, 0, addrsize, 0);
uputchar(']');
break;
case 'R':
do_modrm(t);
break;
case 'S':
uputchar("ecsdfg"[reg(modrm())]);
uputchar('s');
break;
case 'T':
uprintf("tr%d", reg(modrm()));
break;
case 'X':
uprintf("ds:[");
if (addrsize == 32)
uputchar('e');
uprintf("si]");
break;
case 'Y':
uprintf("es:[");
if (addrsize == 32)
uputchar('e');
uprintf("di]");
break;
case '2':
ua_str(second[getbyte()]);
break;
case 'e':
if (opsize == 32)
{
if (t == 'w')
uputchar('d');
else
{
uputchar('e');
uputchar(t);
}
}
else
uputchar(t);
break;
case 'f':
floating_point(t-'0');
break;
case 'g':
ua_str(groups[t-'0'][reg(modrm())]);
break;
case 'p':
switch (t)
{
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 's':
prefix = t;
ua_str(opmap1[getbyte()]);
break;
case ':':
if (prefix)
uprintf("%cs:", prefix);
break;
case ' ':
ua_str(opmap1[getbyte()]);
break;
}
break;
case 's':
switch (t)
{
case 'a':
addrsize = 48 - addrsize;
ua_str(opmap1[getbyte()]);
break;
case 'o':
opsize = 48 - opsize;
ua_str(opmap1[getbyte()]);
break;
}
break;
case '+':
switch (t)
{
case '-':
default_pick_sign = 1;
break;
case '+':
default_pick_sign = 2;
break;
default:
default_pick_sign = 0;
break;
}
}
}
static ua_str(char *s)
{
int c;
if (s == 0)
{
uprintf("<invalid>");
return;
}
while ((c = *s++) != 0)
{
if (c == '%')
{
c = *s++;
percent(c, &s);
}
else
if (c == ' ')
uputchar('\t');
else
uputchar(c);
}
}
#ifdef SOURCE_LIST
/*
** A little brute force hacking and hey presto! A source debugger!
** Courtesy of Kent Williams williams@herky.cs.uiowa.edu
**
** KNOWN BUGS:
** The program will summarily terminate if you run out
** of memory while you're looking for all the line offsets. Since
** a two thousand line source file only creats an 8K array, and the
** symbol table goes into virtual memory, this shouldn't happen too
** often.
**
** One file is left open for reading indefinitely.
*/
#include <stdlib.h>
#include <string.h>
/*
** keep the source line offsets in virtual memory, so you can
** debug big programs
*/
extern word32 salloc(word32 size);
#define symsput(where,ptr,size) memput(where,ptr,size)
#define symsget(where,ptr,size) memget(where,ptr,size)
/*
** for each file encountered, keep an array of line start offsets
** so you can seek into the file to display the current line.
*/
typedef struct {
char *filename;
long *offsets;
} line_info;
static line_info *files;
static last_file = 0;
/*
** add_file -- add a file to the source line database
*/
static int
add_file(char *name) {
FILE *f = fopen(name,"rb");
char c;
long *lines,curpos;
unsigned curline = 0;
if(!f)
return -1;
if (files == 0)
files = (line_info *)malloc(sizeof(line_info));
else
files = realloc(files, (last_file+1) * sizeof(line_info));
files[last_file].filename = strdup(name);
/*
** build an array of line offsets in real memory.
*/
lines = malloc(sizeof(long));
lines[curline++] = curpos = 0L;
while((c = getc(f)) != EOF) {
curpos++;
if(c == '\n') {
lines = realloc(lines,sizeof(long)*(curline+1));
lines[curline++] = curpos;
}
}
/*
** now move the whole array into virtual memory
*/
files[last_file].offsets = lines;
fclose(f);
last_file++;
return 0;
}
static line_info *
find_file(char *name) {
int i;
for(i = 0; i < last_file; i++)
if(strcmp(name,files[i].filename) == 0)
return &files[i];
if(add_file(name) == -1)
return NULL;
return find_file(name);
}
/*
** myfopen -- cache the most recently accessed source file
** so you aren't constantly reopening a new file
*/
static FILE *
myfopen(char *name) {
static char fname[80] = "";
static FILE *current = NULL;
if(current != NULL && strcmp(fname,name) == 0)
return current;
if(current != NULL) fclose(current);
strcpy(fname,name);
return (current = fopen(name,"rb"));
}
/*
** put_source_line -- print the current source line, along with
** the line # and file name, if necessary.
*/
void
put_source_line(int fmt,char *name,int line) {
line_info *current = find_file(name);
FILE *cur;
if(current == NULL) {
regular:
if(fmt == 0)
printf(" (%s#%d):\n", name, line);
else
printf("#%d:\n", line);
} else {
char buf[70];
long offset;
if((cur = myfopen(name)) == NULL)
goto regular;
/*
** get the symbol out of virtual memory
*/
offset = current->offsets[line-1];
fseek(cur,offset,0);
/*
** truncate line so it fits on screen.
*/
fgets(buf,sizeof(buf)-2,cur);
if(strchr(buf,'\n') == NULL)
strcat(buf,"\n");
if(fmt == 0)
printf(" (%s#%d): %s", name, line,buf);
else
printf("#%d: %s",line,buf);
}
}
#endif
int last_unassemble_unconditional;
int last_unassemble_jump;
int last_unassemble_extra_lines;
word32 unassemble(word32 v, int showregs)
{
int a,b,n,wi, linenum;
char *cmp, *brp;
word8 *wp;
word32 delta;
char *name, *lname;
long ptracev;
default_pick_sign = 0;
ansi(A_yellow);
last_unassemble_unconditional = 0;
last_unassemble_jump = 0;
last_unassemble_extra_lines = 0;
name = syms_val2name(v, &delta);
if (!delta && (name[0] != '0'))
{
printf("%s()", name);
lname = syms_val2line(v, &linenum, 1);
if (lname)
#ifndef SOURCE_LIST
printf(" (%s#%d):\n", lname, linenum);
#else
put_source_line(0,lname,linenum);
#endif
else
printf(":\n");
last_unassemble_extra_lines++;
}
else
{
lname = syms_val2line(v, &linenum, 1);
if (lname)
{
#ifndef SOURCE_LIST
printf("#%d:\n", linenum);
#else
put_source_line(1,lname,linenum);
#endif
last_unassemble_extra_lines++;
}
}
ansi(A_cyan);
printf("%08lx: ", v);
#if 0
if (!page_is_valid(v+ARENA) || !page_is_valid(v+5+ARENA))
{
printf("<bad address>\n");
ansi(A_white);
return v;
}
#endif
ansi(A_blue);
prefix = 0;
modrmv = sibv = -1;
opsize = addrsize = seg_size;
vaddr = v;
bufp = bufe = 0;
col = 0;
ubufp = ubuf;
ua_str(opmap1[getbyte()]);
do {
putchar(' ');
col++;
} while (col < 15);
col += strlen(ubuf);
do {
uputchar(' ');
col++;
} while (col < 43);
ansi(A_red);
printf("%s", ubuf);
if ((strncmp(ubuf, "jmp ", 4) == 0)
|| (strncmp(ubuf, "ret", 3) == 0))
last_unassemble_unconditional = 1;
if (ubuf[0] == 'j')
last_unassemble_jump = 1;
if (!showregs)
{
ansi(A_white);
putchar('\n');
return vaddr;
}
ansi(A_purple);
col -= 43; /* total 25 columns left */
cmp = strchr(ubuf+8, ',');
brp = strchr(ubuf+8, '[');
if (!cmp) cmp = ubuf+8;
if (!brp) brp = ubufp;
if (brp < cmp) cmp = brp;
if (strncmp(ubuf, "mov ", 4))
cmp = ubuf+8;
for (b=0; b<8; b++)
{
for (a=2; a>=0; a--)
{
n = (a==0) ? 1 : ((a==1) ? 2 : 4);
if (strstr(cmp, reg_names[a][b]))
{
col += strlen(reg_names[a][b])+n*2+2;
if (col > 29)
{
printf("\n%53s", "");
col = 0;
}
printf("%s=", reg_names[a][b]);
ptracev = ptrace_get_register(reg_index[b] * 4);
wp = (char *) &ptracev;
while (n)
{
n--;
printf("%02x", wp[n]);
}
putchar(' ');
break;
}
}
}
ansi(A_white);
putchar('\n');
return vaddr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -