home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 October
/
VPR9710A.ISO
/
BENCH
/
DJ1SRC_K
/
105
/
DEBUG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-02
|
42KB
|
1,780 lines
/* This is file DEBUG.C */
/*
** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
**
** This file is distributed under the terms listed in the document
** "copying.dj", available from DJ Delorie at the address above.
** A copy of "copying.dj" should accompany this file; if not, a copy
** should be available from where this file was obtained. This file
** may not be distributed without a verbatim copy of "copying.dj".
**
** This file is distributed WITHOUT ANY WARRANTY; without even the implied
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* 1997/05/01 modified by Kimio Itoh(kitoh@nn.iij4u.or.jp)
for reduce binary size and for dead code elimination.
and merged debug.c, unassmbl.c and unassmbl.h
*/
/* History:175,26 */
#include <stdarg.h>
#include "build.h"
extern int was_exception, have_80387;
jmp_buf back_to_debugger;
int can_longjmp = 0;
void go_til_stop(void);
extern int exception_handler(void);
extern void go32(void);
#if DEBUGGER
static
#endif
void go_til_stop(void)
{
tss_ptr = &a_tss;
while (1) {
go32();
if (!was_exception)
return;
if (exception_handler())
return;
}
}
#if DEBUGGER
extern void __fastcall syms_listwild(char *pattern);
extern void __pascal tssprint(TSS * t);
extern void save_npx(void);
extern word32 dr[8];
extern word32 dr0, dr1, dr2, dr3, dr6, dr7;
static void print_reason(void);
/* merged from unassmbl.h */
static word32 __pascal unassemble(word32 v, int showregs);
static void __pascal ua_str(char *s);
static int last_unassemble_unconditional;
static int last_unassemble_jump;
static int last_unassemble_extra_lines;
typedef struct {
char *cp;
int t;
} item;
static void __pascal my_getline(char *buf, char *lasttoken)
{
int idx, i, ch;
if (use_ansi)
printf("\033[0;32m");
mono_attr = MONO_NORMAL;
printf(">> %s", lasttoken);
for (i = 0; lasttoken[i]; i++)
mputchar(8);
while (!bioskey(1));
for (i = 0; lasttoken[i]; i++)
mputchar(' ');
for (i = 0; lasttoken[i]; i++)
mputchar(8);
idx = 0;
if (use_ansi)
printf("\033[1;33m");
mono_attr = MONO_BOLD;
while (1) {
ch = bioskey(0) & 0xff;
switch (ch) {
case 10:
case 13:
buf[idx] = 0;
if (!idx && lasttoken[0])
printf("\r \r");
else
mputchar('\n');
if (use_ansi)
printf("\033[0m");
mono_attr = MONO_NORMAL;
return;
case 27:
while (idx) {
printf("\b \b");
idx--;
}
break;
case 8:
if (idx) {
printf("\b \b");
idx--;
}
break;
default:
mputchar(ch);
buf[idx++] = ch;
break;
}
}
}
typedef enum {
Zero, Unknown, CONT, STEP, NEXT, REGS, SET, HELP, LIST,
DUMP, QUIT, BREAK, STATUS, WHERE, DUMP_A, DUMP_B, DUMP_W, WHEREIS, XNPX,
CLS
};
extern struct {
char *name;
int size;
int ofs;
} regs[];
static item cmds[] =
{
{"g", CONT},
{"go", CONT},
{"cont", CONT},
{"c", CONT},
{"step", STEP},
{"s", STEP},
{"next", NEXT},
{"n", NEXT},
{"regs", REGS},
{"r", REGS},
{"set", SET},
{"help", HELP},
{"h", HELP},
{"?", HELP},
{"list", LIST},
{"l", LIST},
{"u", LIST},
{"dump", DUMP},
{"d", DUMP},
{"da", DUMP_A},
{"db", DUMP_B},
{"dw", DUMP_W},
{"dd", DUMP},
{"quit", QUIT},
{"q", QUIT},
{"break", BREAK},
{"b", BREAK},
{"status", STATUS},
{"where", WHERE},
{"whereis", WHEREIS},
{"npx", XNPX},
{"cls", CLS},
{0, 0}};
extern int debug_mode;
void debugger(void)
{
static char buf[140], token[10], buf2[140], lasttoken[140];
char *name;
int i, n, s, len, rem_cmd, cmd, found;
word32 vaddr, v, rem_v, olddr7;
int32 delta;
dr0 = dr1 = dr2 = ARENA;
dr3 = syms_name2val("_main") + ARENA;
if (undefined_symbol)
dr3 = tss_ptr->tss_eip + ARENA;
rem_cmd = Zero;
lasttoken[0] = 0;
setjmp(back_to_debugger);
can_longjmp = 1;
while (1) {
if (debug_mode) {
int found;
my_getline(buf, lasttoken);
token[0] = 0;
if (sscanf(buf, "%s %[^\n]", token, buf) < 2)
buf[0] = 0;
if (token[0])
strcpy(lasttoken, token);
cmd = rem_cmd;
found = 0;
for (i = 0; cmds[i].cp; i++)
if (!strcmp(cmds[i].cp, token)) {
cmd = cmds[i].t;
found = 1;
}
if (!found && token[0])
cmd = Unknown;
if (rem_cmd != cmd)
vaddr = tss_ptr->tss_eip;
} else {
cmd = CONT;
debug_mode = 1;
}
switch (cmd) {
case HELP:
printf("Commands:\n"
"go <v>\tg\tgo, stop at <v>\n"
"cont\tc\tcontinue execution\n"
"step\ts\tstep through current instruction\n"
"next\tn\tstep to next instruction\n"
"list\tl u\tlist instructions (takes addr, count)\n"
"dump\td\tdump memory (takes addr, count)\n"
"break\tb\tset breakpoint (takes which, addr)\n"
"status\t\tbreakpoint status\n"
"regs\tr\tprint registers\n"
"set\t\tset register/memory\n"
"npx\t\tdisplay 80387 contents\n"
"where\t\tdisplay list of active functions\n"
"whereis\t\tfind a symbol/location (takes wildcard or value)\n"
"cls\t\tclear screen\n"
"help\th,?\tprint help\n"
"quit\tq\tquit\n");
break;
case CONT:
sscanf(buf, "%s", buf);
if (buf[0]) {
v = syms_name2val(buf);
if (undefined_symbol)
break;
dr3 = v + ARENA;
dr7 |= 0xc0;
} else
dr7 &= ~0xc0;
olddr7 = dr7;
dr7 = 0;
tss_ptr->tss_eflags |= 0x0100;
go_til_stop();
dr7 = olddr7;
if (tss_ptr->tss_irqn == 1) {
tss_ptr->tss_eflags &= ~0x0100;
tss_ptr->tss_eflags |= 0x10000L;
go_til_stop();
if (tss_ptr->tss_irqn == 1)
tssprint(tss_ptr);
}
print_reason();
dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
break;
case STEP:
if (rem_cmd != cmd)
n = 1;
sscanf(buf, "%d", &n);
tss_ptr->tss_eflags |= 0x0100;
for (i = 0; i < n; i++) {
olddr7 = dr7;
dr7 = 0;
go_til_stop();
dr7 = olddr7;
print_reason();
dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
if (tss_ptr->tss_irqn != 1)
break;
}
tss_ptr->tss_eflags &= ~0x0100;
break;
case NEXT:
if (rem_cmd != cmd)
n = 1;
sscanf(buf, "%d", &n);
for (i = 0; i < n; i++) {
olddr7 = dr7;
dr7 &= ~0xc0;
dr7 |= 0xc0;
if (last_unassemble_unconditional ||
last_unassemble_jump)
tss_ptr->tss_eflags |= 0x0100; /* step */
else
tss_ptr->tss_eflags &= ~0x0100;
go_til_stop();
dr7 = olddr7;
print_reason();
dr3 = unassemble(tss_ptr->tss_eip, 1) + ARENA;
if (tss_ptr->tss_irqn != 1)
break;
}
tss_ptr->tss_eflags &= ~0x0100;
break;
case WHERE:
v = tss_ptr->tss_ebp;
vaddr = tss_ptr->tss_eip;
printf("%#08lx %s", vaddr, syms_val2name(vaddr, (word32 *) & delta));
name = syms_val2line(vaddr, &i, 0);
if (name)
printf(", line %d in file %s", i, name);
else if (delta)
printf("%+ld", delta);
mputchar('\n');
do {
if (!v)
break;
rem_v = peek32(v + ARENA);
if (!rem_v)
break;
vaddr = peek32(v + ARENA + 4);
printf("%#08lx %s", vaddr, syms_val2name(vaddr, (word32 *) & delta));
name = syms_val2line(vaddr, &i, 0);
if (name)
printf(", line %d in file %s", i, name);
else if (delta)
printf("%+ld", delta);
mputchar('\n');
v = rem_v;
} while ((v >= tss_ptr->tss_esp) && (v < 0x90000000L));
break;
case WHEREIS:
sscanf(buf, "%s", buf2);
if (strpbrk(buf2, "*?")) {
syms_listwild(buf2);
break;
}
if (buf2[0])
vaddr = syms_name2val(buf2);
if (undefined_symbol)
break;
name = syms_val2name(vaddr, (word32 *) & delta);
printf("%#08lx %s", vaddr, name);
if (delta)
printf("+%lx", delta);
name = syms_val2line(vaddr, &i, 0);
if (name)
printf(", line %d in file %s", i, name);
mputchar('\n');
break;
case LIST:
if (rem_cmd != cmd)
n = 10;
buf2[0] = 0;
sscanf(buf, "%s %d", buf2, &n);
if (buf2[0] && strcmp(buf2, "."))
vaddr = syms_name2val(buf2);
if (undefined_symbol)
break;
for (i = 0; i < n; i++) {
vaddr = unassemble(vaddr, 0);
i += last_unassemble_extra_lines;
/* if (last_unassemble_unconditional)
break; */
}
break;
case DUMP_A:
buf2[0] = 0;
sscanf(buf, "%s %d", buf2, &n);
if (buf2[0])
vaddr = syms_name2val(buf2);
if (undefined_symbol)
break;
while (1) {
word8 ch;
if (!page_is_valid(vaddr + ARENA)) {
printf("<bad address>\n");
break;
}
ch = peek8(vaddr + ARENA);
if (!ch) {
mputchar('\n');
break;
}
if (ch < ' ')
printf("^%c", ch + '@');
else if ((ch >= ' ') && (ch < 0x7f))
mputchar(ch);
else if (ch == 0x7f)
printf("^?");
else if ((ch >= 0x80) && (ch < 0xa0))
printf("M-^%c", ch - 0x80 + '@');
else if (ch >= 0xa0)
printf("M-%c", ch - 0x80);
vaddr++;
}
break;
case DUMP:
case DUMP_B:
case DUMP_W:
if (rem_cmd != cmd)
n = 4;
buf2[0] = 0;
sscanf(buf, "%s %d", buf2, &n);
if (buf2[0])
vaddr = syms_name2val(buf2);
if (undefined_symbol)
break;
s = 0;
len = n + (int)(~((vaddr & 15) / 4 - 1) & 3);
for (i = -(int)(vaddr & 15) / 4; i < len; i++) {
if (!(s & 3))
printf("%#08lx:", vaddr + i * 4);
if ((i >= 0) && (i < n))
printf(" %#08lx", peek32(vaddr + i * 4 + ARENA));
else
printf(" ");
if ((s & 3) == 3) {
int j, c;
printf(" ");
for (j = 0; j < 16; j++)
if ((j + i * 4 - 12 >= 0) && (j + i * 4 - 12 < n * 4)) {
c = peek8(vaddr + j + i * 4 - 12 + ARENA);
if (c < ' ')
mputchar('.');
else
mputchar(c);
} else
mputchar(' ');
printf("\n");
}
s++;
}
if (s & 3)
printf("\n");
vaddr += n * 4;
break;
case BREAK:
vaddr = n = 0;
buf2[0] = 0;
sscanf(buf, "%d %s", &n, buf2);
if (buf2[0])
vaddr = syms_name2val(buf2);
if (undefined_symbol)
break;
dr[n] = vaddr + ARENA;
if (!vaddr)
dr7 &= ~(2 << (n * 2));
else
dr7 |= 2 << (n * 2);
case STATUS:
s = 0;
for (n = 0; n < 4; n++) {
s = 1;
name = syms_val2name(dr[n] - ARENA, (word32 *) & delta);
printf(" dr%d %s", n, name);
if (delta)
printf("+%#lx", delta);
if (name[0] != '0')
printf(" (%#lx)", dr[n] - ARENA);
if (!(dr7 & (3 << (n * 2))))
printf(" (disabled)");
mputchar('\n');
}
if (!s)
printf(" No breakpoints set\n");
break;
case REGS:
tssprint(tss_ptr);
unassemble(tss_ptr->tss_eip, 0);
break;
case SET:
cmd = Zero;
lasttoken[0] = 0;
buf2[0] = 0;
len = sscanf(buf, "%s %s", buf2, buf);
if (!buf2[0])
break;
if (len > 1) {
v = syms_name2val(buf);
if (undefined_symbol)
break;
}
found = 0;
for (i = 0; regs[i].name; i++)
if (!strcmp(regs[i].name, buf2)) {
found = 1;
if (len > 1) {
switch (regs[i].size) {
case 1:
*(word8 *) ((word8 *) tss_ptr + regs[i].ofs) = (word8) v;
break;
case 2:
*(word16 *) ((word8 *) tss_ptr + regs[i].ofs) = (word16) v;
break;
case 4:
*(word32 *) ((word8 *) tss_ptr + regs[i].ofs) = v;
break;
}
} else {
switch (regs[i].size) {
case 1:
printf("%02x ", *(word8 *) ((word8 *) tss_ptr + regs[i].ofs));
my_getline(buf, "");
if (buf[0]) {
v = syms_name2val(buf);
if (undefined_symbol)
break;
*(word8 *) ((word8 *) tss_ptr + regs[i].ofs) = (word8) v;
}
break;
case 2:
printf("%04x ", *(word16 *) ((word16 *) tss_ptr + regs[i].ofs));
my_getline(buf, "");
if (buf[0]) {
v = syms_name2val(buf);
if (undefined_symbol)
break;
*(word16 *) ((word16 *) tss_ptr + regs[i].ofs) = (word16) v;
}
break;
case 4:
printf("%08lx ", *(word32 *) ((word32 *) tss_ptr + regs[i].ofs));
my_getline(buf, "");
if (buf[0]) {
v = syms_name2val(buf);
if (undefined_symbol)
break;
*(word32 *) ((word32 *) tss_ptr + regs[i].ofs) = v;
}
break;
}
}
break;
}
if (found)
break;
vaddr = syms_name2val(buf2);
if (undefined_symbol)
break;
if (len < 2) {
v = syms_name2val(buf);
if (undefined_symbol)
break;
poke32(vaddr, v);
}
while (1) {
printf("%#08lx %#08lx", vaddr, peek32(vaddr + ARENA));
my_getline(buf, "");
if (buf[0]) {
if (!strcmp(buf, "."))
break;
poke32(vaddr + ARENA, syms_name2val(buf));
}
vaddr += 4;
}
break;
case XNPX:
if (!have_80387) {
printf("No 80387 present\n");
break;
}
save_npx();
printf("Control: %#04lx Status: %#04lx Tag: %#04lx\n",
npx.control, npx.status, npx.tag);
for (i = 0; i < 8; i++) {
double d;
int tag, ex;
int tos = (npx.status >> 11) & 7;
printf("st(%d) ", i);
if (npx.reg[i].sign)
mputchar('-');
else
mputchar('+');
printf(" %04x %04x %04x %04x e %04x ",
npx.reg[i].sig3,
npx.reg[i].sig2,
npx.reg[i].sig1,
npx.reg[i].sig0,
npx.reg[i].exponent);
tag = (npx.tag >> (((i + tos) % 8) * 2)) & 3;
switch (tag) {
case 0:
printf("Valid");
ex = (int)npx.reg[i].exponent - 16382;
if ((ex < 1000) && (ex > -1000)) {
#define D1 65536.0L
d = npx.reg[i].sig3 / D1 + npx.reg[i].sig2 / D1 / D1 + npx.reg[i].sig1 / D1 / D1 / D1;
d = ldexp(d, ex);
if (npx.reg[i].sign)
d = -d;
printf(" %.16lg\n", d);
} else
printf(" (too big to display)\n");
break;
case 1:
printf("Zero\n");
break;
case 2:
printf("Special\n");
break;
case 3:
printf("Empty\n");
break;
}
}
break;
case CLS:
if (use_mono)
mputchar(12);
else {
_AH = 15;
geninterrupt(0x10);
_AH = 0;
geninterrupt(0x10);
mputchar('\n');
}
break;
case QUIT:
return;
case Zero:
break;
default:
printf("Unknown command\n");
lasttoken[0] = 0;
cmd = Zero;
break;
}
if (undefined_symbol) {
lasttoken[0] = 0;
cmd = Zero;
undefined_symbol = 0;
}
rem_cmd = cmd;
debug_mode = 1;
}
}
static void print_reason(void)
{
int n, i;
i = tss_ptr->tss_irqn;
if ((i == 0x21) && ((tss_ptr->tss_eax & 0xff00) == 0x4c00)) {
tss_ptr->tss_eip -= 2; /* point to int 21h */
return;
}
if (use_ansi)
printf("\033[1;34m");
mono_attr = MONO_BOLD;
if (i != 1) {
tssprint(tss_ptr);
if (tss_ptr != &a_tss) {
printf("internal error: tss_ptr NOT a_tss\n");
}
if (i == 0x79)
printf("Keyboard interrupt\n");
else if (i == 0x75) {
save_npx();
printf("Numeric Exception (");
if ((npx.status & 0x0241) == 0x0241)
printf("stack overflow");
else if ((npx.status & 0x0241) == 0x0041)
printf("stack underflow");
else if (npx.status & 1)
printf("invalid operation");
else if (npx.status & 2)
printf("denormal operand");
else if (npx.status & 4)
printf("divide by zero");
else if (npx.status & 8)
printf("overflow");
else if (npx.status & 16)
printf("underflow");
else if (npx.status & 32)
printf("loss of precision");
printf(") at eip=%#08lx\n", npx.eip);
unassemble(npx.eip, 0);
} else {
printf("exception %d (%#02x) occurred", i, i);
if ((i == 8) || ((i >= 10) && (i <= 14)))
printf(", error code=%#lx", tss_ptr->tss_error);
mputchar('\n');
}
}
for (n = 0; n < 3; n++)
if ((dr6 & (1 << n)) && (dr7 & (3 << (n * 2))))
printf("breakpoint %d hit\n", n);
if (use_ansi)
printf("\033[0m");
mono_attr = MONO_NORMAL;
}
/* This is file UNASSMBL.C */
static int seg_size = 32;
static word8 buf[20];
static word32 vaddr;
static int bufp, bufe;
static char ubuf[100], *ubufp;
static int col;
/* Percent tokens in strings:
First char after '%':
A - direct address
C - reg of r/m picks control register
D - reg of r/m picks debug register
E - r/m picks operand
F - flags register
G - reg of r/m picks general register
I - immediate data
J - relative IP offset
M - r/m picks memory
O - no r/m, offset only
R - mod of r/m picks register only
S - reg of r/m picks segment register
T - reg of r/m picks test register
X - DS:ESI
Y - ES:EDI
2 - prefix of two-byte opcode
e - put in 'e' if use32 (second char is part of reg name)
put in 'w' for use16 or 'd' for use32 (second char is 'w')
f - floating point (second char is esc value)
g - do r/m group 'n'
p - prefix
s - size override (second char is a,o)
Second char after '%':
a - two words in memory (BOUND)
b - byte
c - byte or word
d - dword
p - 32 or 48 bit pointer
s - six byte pseudo-descriptor
v - word or dword
w - word
F - use floating regs in mod/rm
1-8 - group number, esc value, etc
*/
static char *opmap1[] =
{
/* 0 */
"add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev",
"add al,%Ib", "add %eax,%Iv", "push es", "pop es",
"or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev",
"or al,%Ib", "or %eax,%Iv", "push cs", "%2 ",
/* 1 */
"adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev",
"adc al,%Ib", "adc %eax,%Iv", "push ss", "pop ss",
"sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev",
"sbb al,%Ib", "sbb %eax,%Iv", "push ds", "pop ds",
/* 2 */
"and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev",
"and al,%Ib", "and %eax,%Iv", "%pe", "daa",
"sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev",
"sub al,%Ib", "sub %eax,%Iv", "%pc", "das",
/* 3 */
"xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev",
"xor al,%Ib", "xor %eax,%Iv", "%ps", "aaa",
"cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev",
"cmp al,%Ib", "cmp %eax,%Iv", "%pd", "aas",
/* 4 */
"inc %eax", "inc %ecx", "inc %edx", "inc %ebx",
"inc %esp", "inc %ebp", "inc %esi", "inc %edi",
"dec %eax", "dec %ecx", "dec %edx", "dec %ebx",
"dec %esp", "dec %ebp", "dec %esi", "dec %edi",
/* 5 */
"push %eax", "push %ecx", "push %edx", "push %ebx",
"push %esp", "push %ebp", "push %esi", "push %edi",
"pop %eax", "pop %ecx", "pop %edx", "pop %ebx",
"pop %esp", "pop %ebp", "pop %esi", "pop %edi",
/* 6 */
"pusha", "popa", "bound %Gv,%Ma", "arpl %Ew,%Rw",
"%pf", "%pg", "%so", "%sa",
"push %Iv", "imul %Gv=%Ev*%Iv", "push %Ib", "imul %Gv=%Ev*%Ib",
"insb %Yb,dx", "ins%ew %Yv,dx", "outsb dx,%Xb", "outs%ew dx,%Xv",
/* 7 */
"jo %Jb", "jno %Jb", "jnc %Jb", "jc %Jb",
"jz %Jb", "jnz %Jb", "jbe %Jb", "jnbe %Jb",
"js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb",
"jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb",
/* 8 */
"%g1 %Eb,%Ib", "%g1 %Ev,%Iv", "mov al,%Ib", "%g1 %Ev,%Ib",
"test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv",
"mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev",
"mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev",
/* 9 */
"nop", "xchg %eax,%ecx", "xchg %eax,%edx", "xchg %eax,%ebx",
"xchg %eax,%esp", "xchg %eax,%ebp", "xchg %eax,%esi", "xchg %eax,%edi",
"cbw", "cwd", "call %Ap", "fwait",
"push %eflags", "pop %eflags", "sahf", "lahf",
/* a */
"mov al,%Ob", "mov %eax,%Ov", "mov %Ob,al", "mov %Ov,%eax",
"movsb %Xb,%Yb", "movs%ew %Xv,%Yv", "cmpsb %Xb,%Yb", "cmps%ew %Xv,%Yv",
"test al,%Ib", "test %eax,%Iv", "stosb %Yb,al", "stos%ew %Yv,%eax",
"lodsb al,%Xb", "lods%ew %eax,%Xv", "scasb al,%Xb", "scas%ew %eax,%Xv",
/* b */
"mov al,%Ib", "mov cl,%Ib", "mov dl,%Ib", "mov bl,%Ib",
"mov ah,%Ib", "mov ch,%Ib", "mov dh,%Ib", "mov bh,%Ib",
"mov %eax,%Iv", "mov %ecx,%Iv", "mov %edx,%Iv", "mov %ebx,%Iv",
"mov %esp,%Iv", "mov %ebp,%Iv", "mov %esi,%Iv", "mov %edi,%Iv",
/* c */
"%g2 %Eb,%Ib", "%g2 %Ev,%Ib", "ret %Iw", "ret",
"les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ib", "mov %Ev,%Iv",
"enter %Iw,%Ib", "leave", "retf %Iw", "retf",
"int 3", "int %Ib", "into", "iret",
/* d */
"%g2 %Eb,1", "%g2 %Ev,1", "%g2 %Eb,cl", "%g2 %Ev,cl",
"aam", "aad", 0, "xlat",
"%f0", "%f1", "%f2", "%f3",
"%f4", "%f5", "%f6", "%f7",
/* e */
"loopne %Jb", "loope %Jb", "loop %Jb", "jcxz %Jb",
"in al,%Ib", "in %eax,%Ib", "out %Ib,al", "out %Ib,%eax",
"call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Jb",
"in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax",
/* f */
"lock %p ", 0, "repne %p ", "rep(e) %p ",
"hlt", "cmc", "%g3", "%g0",
"clc", "stc", "cli", "sti",
"cld", "std", "%g4", "%g5"
};
static char *second[] =
{
/* 0 */
"%g6", "%g7", "lar %Gv,%Ew", "lsl %Gv,%Ew", 0, 0, "clts", 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* 1 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 2 */
"mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd",
"mov %Rd,%Td", 0, "mov %Td,%Rd", 0,
0, 0, 0, 0, 0, 0, 0, 0,
/* 3 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 8 */
"jo %Jv", "jno %Jv", "jnc %Jv", "jc %Jv",
"jz %Jv", "jnz %Jv", "jbe %Jv", "jnbe %Jv",
"js %Jv", "jns %Jv", "jpe %Jv", "jpo %Jv",
"jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv",
/* 9 */
"seto %Eb", "setno %Eb", "setnc %Eb", "setc %Eb",
"setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb",
"sets %Eb", "setns %Eb", "setp %Eb", "setnp %Eb",
"setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb",
/* a */
"push fs", "pop fs", 0, "bt %Ev,%Gv",
"shld %Ev,%Gv,%Ib", "shld %Ev,%Gv,cl", 0, 0,
"push gs", "pop gs", 0, "bts %Ev,%Gv",
"shrd %Ev,%Gv,%Ib", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev",
/* b */
0, 0, "lss %Mp", "btr %Ev,%Gv",
"lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew",
0, 0, "%g8 %Ev,%Ib", "btc %Ev,%Gv",
"bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew",
/* c */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static char *groups[][8] =
{ /* group 0 is group 3 for %Ev set */
{"test %Ev,%Iv", "test %Ev,%Iv,", "not %Ev", "neg %Ev",
"mul %eax,%Ev", "imul %eax,%Ev", "div %eax,%Ev", "idiv %eax,%Ev"},
{"add", "or", "adc", "sbb", "and", "sub", "xor", "cmp"},
{"rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar"},
{"test %Eb,%Ib", "test %Eb,%Ib,", "not %Eb", "neg %Eb",
"mul al,%Eb", "imul al,%Eb", "div al,%Eb", "idiv al,%Eb"},
{"inc %Eb", "dec %Eb", 0, 0, 0, 0, 0, 0},
{"inc %Ev", "dec %Ev", "call %Ev", "call %Ep",
"jmp %Ev", "jmp %Ep", "push %Ev", 0},
{"sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew",
"verr %Ew", "verw %Ew", 0, 0},
{"sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms",
"smsw %Ew", 0, "lmsw %Ew", 0},
{0, 0, 0, 0, "bt", "bts", "btr", "btc"}
};
/* zero here means invalid. If first entry starts with '*', use st(i) */
/* no assumed %EFs here. Indexed by rm(modrm()) */
static char *f0[] =
{0, 0, 0, 0, 0, 0, 0, 0};
static char *fop_9[] =
{"*fxch st,%GF"};
static char *fop_10[] =
{"fnop", 0, 0, 0, 0, 0, 0, 0};
static char *fop_12[] =
{"fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0};
static char *fop_13[] =
{"fld1", "fldl2t", "fldl2e", "fldpi", "fldlg2", "fldln2", "fldz", 0};
static char *fop_14[] =
{"f2xm1", "fyl2x", "fptan", "fpatan", "fxtract", "fprem1", "fdecstp", "fincstp"};
static char *fop_15[] =
{"fprem", "fyl2xp1", "fsqrt", "fsincos", "frndint", "fscale", "fsin", "fcos"};
static char *fop_21[] =
{0, "fucompp", 0, 0, 0, 0, 0, 0};
static char *fop_28[] =
{0, 0, "fclex", "finit", 0, 0, 0, 0};
static char *fop_32[] =
{"*fadd %GF,st"};
static char *fop_33[] =
{"*fmul %GF,st"};
static char *fop_36[] =
{"*fsubr %GF,st"};
static char *fop_37[] =
{"*fsub %GF,st"};
static char *fop_38[] =
{"*fdivr %GF,st"};
static char *fop_39[] =
{"*fdiv %GF,st"};
static char *fop_40[] =
{"*ffree %GF"};
static char *fop_42[] =
{"*fst %GF"};
static char *fop_43[] =
{"*fstp %GF"};
static char *fop_44[] =
{"*fucom %GF"};
static char *fop_45[] =
{"*fucomp %GF"};
static char *fop_48[] =
{"*faddp %GF,st"};
static char *fop_49[] =
{"*fmulp %GF,st"};
static char *fop_51[] =
{0, "fcompp", 0, 0, 0, 0, 0, 0};
static char *fop_52[] =
{"*fsubrp %GF,st"};
static char *fop_53[] =
{"*fsubp %GF,st"};
static char *fop_54[] =
{"*fdivrp %GF,st"};
static char *fop_55[] =
{"*fdivp %GF,st"};
static char *fop_60[] =
{"fstsw ax", 0, 0, 0, 0, 0, 0, 0};
static char **fspecial[] =
{ /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
0, 0, 0, 0, 0, 0, 0, 0,
0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
f0, f0, f0, f0, f0, fop_21, f0, f0,
f0, f0, f0, f0, fop_28, f0, f0, f0,
fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
f0, f0, f0, f0, fop_60, f0, f0, f0,
};
static char *floatops[] =
{ /* assumed " %EF" at end of each. mod != 3 only */
/*00 */ "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr",
/*08 */ "fld", 0, "fst", "fstp", "fldenv", "fldcw", "fstenv", "fstcw",
/*16 */ "fiadd", "fimul", "ficomw", "ficompw", "fisub", "fisubr", "fidiv", "fidivr",
/*24 */ "fild", 0, "fist", "fistp", "frstor", "fldt", 0, "fstpt",
/*32 */ "faddq", "fmulq", "fcomq", "fcompq", "fsubq", "fsubrq", "fdivq", "fdivrq",
/*40 */ "fldq", 0, "fstq", "fstpq", 0, 0, "fsave", "fstsww",
/*48 */ "fiaddw", "fimulw", "ficomw", "ficompw", "fisubw", "fisubrw", "fidivw", "fidivr",
/*56 */ "fildw", 0, "fistw", "fistpw", "fbldt", "fildq", "fbstpt", "fistpq"
};
static word8 getbyte(void)
{
int s;
if (bufp >= bufe) {
s = 20;
if ((vaddr & 0xfff) + s > 0x1000)
s = 0x1000 - (int)(vaddr & 0xfff);
memget(vaddr + ARENA, buf, s);
bufe = s;
bufp = 0;
}
vaddr++;
printf("%02x", buf[bufp]);
col += 2;
return buf[bufp++];
}
static int prefix;
static int modrmv;
static int sibv;
static int opsize;
static int addrsize;
static int modrm(void)
{
if (modrmv == -1)
modrmv = getbyte();
return modrmv;
}
static int sib(void)
{
if (sibv == -1)
sibv = getbyte();
return sibv;
}
#define mod(a) (((a)>>6)&7)
#define reg(a) (((a)>>3)&7)
#define rm(a) ((a)&7)
#define ss(a) (((a)>>6)&7)
#define indx(a) (((a)>>3)&7)
#define base(a) ((a)&7)
/*------------------------------------------------------------------------*/
static void __cdecl uprintf(char *s,...)
{
va_list ap;
va_start(ap, s);
vsprintf(ubufp, s, ap);
va_end(ap);
while (*ubufp)
ubufp++;
}
static void __pascal uputchar(char c)
{
if (c == '\t') {
do {
*ubufp++ = ' ';
} while ((ubufp - ubuf) % 8);
} else
*ubufp++ = c;
*ubufp = 0;
}
/*------------------------------------------------------------------------*/
static int bytes(char c)
{
switch (c) {
case 'b':
return 1;
case 'w':
return 2;
case 'd':
return 4;
case 'v':
if (opsize == 32)
return 4;
else
return 2;
}
return 0;
}
/*------------------------------------------------------------------------*/
static void __pascal ohex(char c, int extend, int optional, int defsize, int sign)
{
int n, s, i;
int32 delta;
unsigned char buf[6];
char *name;
n = s = 0;
switch (c) {
case 'a':
break;
case 'b':
n = 1;
break;
case 'w':
n = 2;
break;
case 'd':
n = 4;
break;
case 's':
n = 6;
break;
case 'c':
case 'v':
n = (defsize == 32) ? 4 : 2;
break;
case 'p':
n = (defsize == 32) ? 6 : 4;
s = 1;
break;
}
for (i = 0; i < n; i++)
buf[i] = getbyte();
for (; i < extend; i++)
buf[i] = (buf[i - 1] & 0x80) ? 0xff : 0;
if (s) {
uprintf("%#02x%02x:", buf[n - 1], buf[n - 2]);
n -= 2;
}
switch (n) {
case 1:
delta = *(signed char *)buf;
break;
case 2:
delta = *(signed int *)buf;
break;
case 4:
delta = *(signed long *)buf;
break;
}
if (extend > n) {
if (delta || !optional)
uprintf("%+ld", delta);
return;
}
if ((n == 4) && !sign) {
name = syms_val2name((word32) delta, (word32 *) & delta);
if (name) {
uprintf("%s", name);
if (delta)
uprintf("+%lu", delta);
return;
}
}
switch (n) {
case 1:
if (sign)
uprintf("%+d", (unsigned char)delta);
else
uprintf("%#x", (unsigned char)delta);
break;
case 2:
if (sign)
uprintf("%+d", (unsigned int)delta);
else
uprintf("%#x", (unsigned int)delta);
break;
case 4:
if (sign)
uprintf("%+ld", (unsigned long)delta);
else
uprintf("%#lx", (unsigned long)delta);
break;
}
}
/*------------------------------------------------------------------------*/
static char *reg_names[3][8] =
{
{"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"},
{"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"},
{"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}};
static void __pascal reg_name(int which, char size)
{
if (size == 'F') {
uprintf("st(%d)", which);
return;
}
if (((size == 'v') && (opsize == 32)) || (size == 'd')) {
uputchar('e');
}
if (size == 'b') {
uputchar("acdbacdb"[which]);
uputchar("llllhhhh"[which]);
} else {
uputchar("acdbsbsd"[which]);
uputchar("xxxxppii"[which]);
}
}
/*------------------------------------------------------------------------*/
static void do_sib(int m)
{
int s, i, b;
s = ss(sib());
i = indx(sib());
b = base(sib());
switch (b) {
case 0:
ua_str("%p:[eax");
break;
case 1:
ua_str("%p:[ecx");
break;
case 2:
ua_str("%p:[edx");
break;
case 3:
ua_str("%p:[ebx");
break;
case 4:
ua_str("%p:[esp");
break;
case 5:
if (!m) {
ua_str("%p:[");
ohex('d', 4, 0, addrsize, 0);
} else
ua_str("%p:[ebp");
break;
case 6:
ua_str("%p:[esi");
break;
case 7:
ua_str("%p:[edi");
break;
}
switch (i) {
case 0:
uprintf("+eax");
break;
case 1:
uprintf("+ecx");
break;
case 2:
uprintf("+edx");
break;
case 3:
uprintf("+ebx");
break;
case 4:
break;
case 5:
uprintf("+ebp");
break;
case 6:
uprintf("+esi");
break;
case 7:
uprintf("+edi");
break;
}
if (i != 4)
switch (s) {
case 0:
uprintf("");
break;
case 1:
uprintf("*2");
break;
case 2:
uprintf("*4");
break;
case 3:
uprintf("*8");
break;
}
}
/*------------------------------------------------------------------------*/
static void __pascal do_modrm(char t)
{
int m = mod(modrm());
int r = rm(modrm());
int extend = (addrsize == 32) ? 4 : 2;
if (m == 3) {
reg_name(r, t);
return;
}
if (!m && (r == 5) && (addrsize == 32)) {
ua_str("%p:[");
ohex('d', extend, 0, addrsize, 0);
uputchar(']');
return;
}
if (!m && (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) {
switch (r) {
case 0:
uprintf("bx+si");
break;
case 1:
uprintf("bx+di");
break;
case 2:
uprintf("bp+si");
break;
case 3:
uprintf("bp+di");
break;
case 4:
uprintf("si");
break;
case 5:
uprintf("di");
break;
case 6:
uprintf("bp");
break;
case 7:
uprintf("bx");
break;
}
} else {
switch (r) {
case 0:
uprintf("eax");
break;
case 1:
uprintf("ecx");
break;
case 2:
uprintf("edx");
break;
case 3:
uprintf("ebx");
break;
case 4:
do_sib(m);
break;
case 5:
uprintf("ebp");
break;
case 6:
uprintf("esi");
break;
case 7:
uprintf("edi");
break;
}
}
switch (m) {
case 1:
ohex('b', extend, 1, addrsize, 0);
break;
case 2:
ohex('v', extend, 1, addrsize, 1);
break;
}
uputchar(']');
}
/*------------------------------------------------------------------------*/
static void floating_point(int e1)
{
int esc = e1 * 8 + reg(modrm());
if (mod(modrm()) == 3) {
if (fspecial[esc]) {
if (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 void percent(char c, char t)
{
word32 vofs, delta;
char *name;
int extend = (addrsize == 32) ? 4 : 2;
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':
ohex(t, 0, 0, opsize, 0);
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 (%#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;
}
}
static void __pascal ua_str(char *s)
{
int c;
if (!s) {
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.
** keep the source line offsets in virtual memory, so you can
** debug big programs
** 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;
word32 offsets;
} line_info;
static line_info files[32];
static last_file = 0;
/*
** these don't seem to be defined anywhere else ...
*/
static void *__pascal xmalloc(unsigned size)
{
void *rval = malloc(size);
if (!rval) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
return rval;
}
static void *xrealloc(void *rval, unsigned size)
{
rval = realloc(rval, size);
if (!rval) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
return rval;
}
static char *xstrdup(char *s)
{
char *rval = xmalloc(strlen(s) + 1);
strcpy(rval, s);
return rval;
}
/*
** add_file -- add a file to the source line database
*/
static int add_file(char *name)
{
FILE *f = fopen(name, "r");
char c;
long *lines, curpos;
unsigned curline = 0;
if (!f)
return -1;
files[last_file].filename = xstrdup(name);
/*
** build an array of line offsets in real memory.
*/
lines = xmalloc(sizeof(long));
lines[curline++] = curpos = 0L;
while ((c = fgetc(f)) != EOF) {
curpos++;
if (c == '\n') {
lines = xrealloc(lines, sizeof(long) * (curline + 1));
lines[curline++] = curpos;
}
}
/*
** now move the whole array into virtual memory
*/
files[last_file].offsets = salloc(curline * sizeof(long));
symsput(files[last_file].offsets, lines, (curline * sizeof(long)));
/*
** don't need the real memory version any more
*/
free(lines);
fclose(f);
last_file++;
return 0;
}
static line_info *__pascal find_file(char *name)
{
int i;
for (i = 0; i < last_file; i++)
if (!strcmp(name, files[i].filename))
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))
return current;
if (current != NULL)
fclose(current);
strcpy(fname, name);
return (current = fopen(name, "r"));
}
/*
** put_source_line -- print the current source line, along with
** the line # and file name, if necessary.
*/
static void __pascal put_source_line(int fmt, char *name, int line)
{
line_info *current = find_file(name);
FILE *cur;
if (current == NULL) {
regular:
if (!fmt)
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
*/
symsget(current->offsets + ((line - 1) * sizeof(long)),
&offset, sizeof(long));
fseek(cur, offset, SEEK_SET);
/*
** truncate line so it fits on screen.
*/
fgets(buf, sizeof(buf) - 2, cur);
if (strchr(buf, '\n') == NULL)
strcat(buf, "\n");
if (!fmt)
printf(" (%s#%d): %s", name, line, buf);
else
printf("#%d: %s", line, buf);
}
}
#endif
static word32 __pascal unassemble(word32 v, int showregs)
{
int a, b, n, wi, linenum;
char *cmp, *brp;
word8 *wp;
word32 delta;
char *name, *lname;
last_unassemble_unconditional = last_unassemble_jump = last_unassemble_extra_lines = 0;
name = syms_val2name(v, &delta);
if (use_ansi)
printf("\033[1;36m");
mono_attr = MONO_BOLD;
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++;
}
}
if (use_ansi)
printf("\033[0m");
mono_attr = MONO_NORMAL;
printf("%08lx: ", v);
if (!page_is_valid(v + ARENA) || !page_is_valid(v + 5 + ARENA)) {
printf("<bad address>\n");
return v;
}
prefix = bufp = bufe = col = 0;
modrmv = sibv = -1;
opsize = addrsize = seg_size;
vaddr = v;
ubufp = ubuf;
ua_str(opmap1[getbyte()]);
do {
mputchar(' ');
col++;
} while (col < 15);
col += strlen(ubuf);
do {
uputchar(' ');
col++;
} while (col < 43);
if (use_ansi)
printf("\033[1m");
mono_attr = MONO_BOLD;
printf("%s", ubuf);
if (use_ansi)
printf("\033[0m");
mono_attr = MONO_NORMAL;
if (!strncmp(ubuf, "jmp ", 4) || !strncmp(ubuf, "ret", 3))
last_unassemble_unconditional = 1;
if (ubuf[0] == 'j')
last_unassemble_jump = 1;
if (!showregs) {
mputchar('\n');
return vaddr;
}
col -= 43; /* total 25 columns left */
wp = (word8 *) & (tss_ptr->tss_eax);
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) ? 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]);
wi = (!a) ? ((b & 3) * 4 + (b >> 2)) : (b * 4);
while (n) {
n--;
printf("%02x", wp[wi + n]);
}
mputchar(' ');
break;
}
}
}
mputchar('\n');
return vaddr;
}
#endif /* DEBUGGER */