📄 outco386.c
字号:
,
{
0, 0, 0
}
,
};
OPCODE popn_stc[] =
{
{
OP_CODEONLY, 0x00f9, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_std[] =
{
{
OP_CODEONLY, 0x00fd, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_sti[] =
{
{
OP_CODEONLY, 0x00fb, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_stos[] =
{
{
OP_STOS, 0x00ab, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_stosb[] =
{
{
OP_CODEONLY, 0x00aa, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_stosd[] =
{
{
OP_INSDWORDSIZE, 0x00ab, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_stosw[] =
{
{
OP_INSWORDSIZE, 0x00ab, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_str[] =
{
{
OP_NOSTRICTRM, 0x0800, 0x0a03
}
,
{
0, 0, 0
}
,
};
OPCODE popn_sub[] =
{
{
OP_RMIMMSIGNED, 0x2880, 0x0200
}
,
{
OP_ACCIMM, 0x002c, 0x0000
}
,
{
OP_REGRMREG, 0x0028, 0x0200
}
,
{
0, 0, 0
}
,
};
OPCODE popn_test[] =
{
{
OP_ACCIMM, 0x00a8, 0x0000
}
,
{
OP_REGMOD, 0x0084, 0x0200
}
,
{
OP_RMIMM, 0x00f6, 0x0200
}
,
{
0, 0, 0
}
,
};
OPCODE popn_ud2[] =
{
{
OP_CODEONLY, 0x000b, 0x0806
}
,
{
0, 0, 0
}
,
};
OPCODE popn_verr[] =
{
{
OP_NOSTRICTRM, 0x2000, 0x0a02
}
,
{
0, 0, 0
}
,
};
OPCODE popn_verw[] =
{
{
OP_NOSTRICTRM, 0x2800, 0x0a02
}
,
{
0, 0, 0
}
,
};
OPCODE popn_wait[] =
{
{
OP_CODEONLY, 0x009b, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_wbinvd[] =
{
{
OP_CODEONLY, 0x0009, 0x0904
}
,
{
0, 0, 0
}
,
};
OPCODE popn_wrmsr[] =
{
{
OP_CODEONLY, 0x0030, 0x0905
}
,
{
0, 0, 0
}
,
};
OPCODE popn_xadd[] =
{
{
OP_BYTERMREG, 0x00c0, 0x0a04
}
,
{
0, 0, 0
}
,
};
OPCODE popn_xbts[] =
{
{
OP_CODEONLY, 0x00a6, 0x0803
}
,
{
0, 0, 0
}
,
};
OPCODE popn_xchg[] =
{
{
OP_ACCREG02, 0x0090, 0x0000
}
,
{
OP_REGRM, 0x0086, 0x0200
}
,
{
0, 0, 0
}
,
};
OPCODE popn_xlat[] =
{
{
OP_CODEONLY, 0x00d7, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_xlatb[] =
{
{
OP_CODEONLY, 0x00d7, 0x0000
}
,
{
0, 0, 0
}
,
};
OPCODE popn_xor[] =
{
{
OP_RMIMMSIGNED, 0x3080, 0x0200
}
,
{
OP_ACCIMM, 0x0034, 0x0000
}
,
{
OP_REGRMREG, 0x0030, 0x0200
}
,
{
0, 0, 0
}
,
};
void outcode_file_init(void)
{
int i;
labelbuf = xalloc(400 *sizeof(LABEL*));
for (i = 0; i < MAX_SEGS; i++)
memset(&segs[i], 0, sizeof(segs[i]));
linelist = 0;
virtualFirst = virtualLast = 0;
}
//-------------------------------------------------------------------------
void outcode_func_init(void)
{
int i;
// memset(labelbuf,0,400 * sizeof(LABEL *)) ;
for (i = 0; i < MAX_SEGS; i++)
segs[i].curbase = segs[i].curlast;
if (currentfunc)
if (curseg == virtseg)
currentfunc->mainsym->offset = outcode_base_address = 0;
else
currentfunc->mainsym->offset = outcode_base_address =
segs[codeseg].curbase;
}
//-------------------------------------------------------------------------
void InsertLabel(int lbl, int address, int seg)
{
int x = lbl / 512;
if (!labelbuf[x])
{
global_flag++;
labelbuf[x] = xalloc(512 *sizeof(LABEL));
global_flag--;
}
labelbuf[x][lbl % 512].address = address;
labelbuf[x][lbl % 512].seg = seg;
}
//-------------------------------------------------------------------------
int LabelAddress(int lbl)
{
if (labelbuf)
{
LABEL *p = labelbuf[lbl / 512];
if (p)
{
// printf("addr %x\n",p[lbl%412].address) ;
return p[lbl % 512].address;
}
}
DIAG("LabelAddress - missing label");
return 0;
// return labelbuf[lbl/512][lbl%512].address ;
}
//-------------------------------------------------------------------------
int LabelSeg(int lbl)
{
return labelbuf[lbl / 512][lbl % 512].seg;
}
//-------------------------------------------------------------------------
void InsertLine(int address, int line, int file)
{
LINEBUF *l;
global_flag++;
l = xalloc(sizeof(LINEBUF));
global_flag--;
l->address = address;
l->lineno = line;
l->file = file;
if (linelist)
linetail = linetail->next = l;
else
linelist = linetail = l;
}
//-------------------------------------------------------------------------
EMIT_TAB *gettab(int seg)
{
if (seg == virtseg)
return virtualLast->seg;
else
{
EMIT_TAB *rv = &segs[seg];
if (!rv->first)
{
global_flag++;
rv->first = rv->last = xalloc(sizeof(EMIT_LIST));
global_flag--;
}
return rv;
}
}
//-------------------------------------------------------------------------
void emit(int seg, BYTE *data, int len)
{
EMIT_TAB *tab = gettab(seg);
int ofs = 0;
if (!tab->first)
{
global_flag++;
tab->first = tab->last = xalloc(sizeof(EMIT_LIST));
global_flag--;
}
tab->last->lastfilled = tab->last->filled;
tab->curlast += len;
while (len)
{
int size = len >= 1024 ? 1024 : len;
if (tab->last->filled + len > 1024)
{
int address = tab->last->address + tab->last->filled;
global_flag++;
tab->last = tab->last->next = xalloc(sizeof(EMIT_LIST));
tab->last->address = address;
global_flag++;
}
memcpy(tab->last->data + tab->last->filled, data + ofs, size);
tab->last->filled += size;
len -= size;
ofs += size;
}
}
//-------------------------------------------------------------------------
void write_to_seg(int seg, int offset, char *value, int len)
{
EMIT_TAB *tab = gettab(seg);
EMIT_LIST *lst = tab->first;
while (lst->address + lst->filled < offset)
lst = lst->next;
memcpy(lst->data + offset - lst->address, value, len);
}
//-------------------------------------------------------------------------
void gen_symbol_fixup(enum mode xmode, int seg, int address, SYM *pub)
{
FIXUP *fixup;
EMIT_TAB *tab = gettab(seg);
global_flag++;
fixup = xalloc(sizeof(FIXUP));
global_flag--;
fixup->fmode = xmode;
fixup->address = address;
fixup->sym = pub;
if (tab->last->fixups)
tab->last->lastfixup = tab->last->lastfixup->next = fixup;
else
tab->last->fixups = tab->last->lastfixup = fixup;
} void gen_label_fixup(enum mode xmode, int seg, int address, int lab)
{
FIXUP *fixup;
EMIT_TAB *tab = gettab(seg);
global_flag++;
fixup = xalloc(sizeof(FIXUP));
global_flag--;
fixup->fmode = xmode;
fixup->address = address;
fixup->label = lab;
if (tab->last->fixups)
tab->last->lastfixup = tab->last->lastfixup->next = fixup;
else
tab->last->fixups = tab->last->lastfixup = fixup;
} void outcode_dump_muldivval(void)
{
MULDIV *v = muldivlink;
unsigned char buf[10];
while (v)
{
InsertLabel(v->label, segs[curseg].curlast, curseg);
if (v->size == 0)
{
*(int*)buf = v->value;
emit(curseg, buf, 4);
}
else if (v->size == 7 || v->size == 15)
{
*(float*)buf = v->floatvalue;
emit(curseg, buf, 4);
}
else if (v->size == 8 || v->size == 16)
{
*(double*)buf = v->floatvalue;
emit(curseg, buf, 8);
}
else
{
*(long double*)buf = v->floatvalue;
emit(curseg, buf, 10);
}
v = v->link;
}
}
//-------------------------------------------------------------------------
void outcode_dump_browsedata(unsigned char *buf, int len)
{
emit(browseseg, buf, len);
}
//-------------------------------------------------------------------------
void outcode_dumplits(void)
{
struct slit *v = strtab;
int val = 0;
xstringseg();
while (v != 0)
{
InsertLabel(v->label, segs[stringseg].curlast, stringseg);
emit(curseg, v->str, v->len - 1);
if (v->type)
emit(curseg, (unsigned char*) &val, 2);
else
emit(curseg, (unsigned char*) &val, 1);
v = v->next;
} nl();
}
//-------------------------------------------------------------------------
void outcode_genref(SYM *sp, int offset)
{
EMIT_TAB *seg = gettab(curseg);
emit(curseg, &offset, 4);
gen_symbol_fixup(fm_symbol, curseg, seg->last->address + seg->last
->lastfilled, sp);
}
//-------------------------------------------------------------------------
void outcode_gen_labref(int n)
{
int i = 0;
EMIT_TAB *seg = gettab(curseg);
emit(curseg, &i, 4);
gen_label_fixup(fm_label, curseg, seg->last->address + seg->last
->lastfilled, n);
}
/* the labels will already be resolved well enough by this point */
void outcode_gen_labdifref(int n1, int n2)
{
int i = LabelAddress(n1) - LabelAddress(n2);
EMIT_TAB *seg = gettab(curseg);
emit(curseg, &i, 4);
}
//-------------------------------------------------------------------------
void outcode_gensrref(SYM *sp, int val)
{
char buf[8];
EMIT_TAB *seg = gettab(curseg);
memset(buf, 0, 8);
*(int*)(buf + 4) = val;
emit(curseg, buf, 8);
gen_symbol_fixup(fm_symbol, curseg, seg->last->address + seg->last
->lastfilled, sp);
}
//-------------------------------------------------------------------------
void outcode_genstorage(int len)
{
char buf[256];
memset(buf, 0, 256);
while (len >= 256)
{
emit(curseg, buf, 256);
len -= 256;
}
if (len)
emit(curseg, buf, len);
}
//-------------------------------------------------------------------------
void outcode_genfloat(long double val)
{
float f = val;
emit(curseg, &f, 4);
}
//-------------------------------------------------------------------------
void outcode_gendouble(long double val)
{
double d = val;
emit(curseg, &d, 8);
}
//-------------------------------------------------------------------------
void outcode_genlongdouble(long double val)
{
emit(curseg, &val, 10);
}
//-------------------------------------------------------------------------
void outcode_genstring(char *string, int len)
{
emit(curseg, string, len);
}
//-------------------------------------------------------------------------
void outcode_genbyte(int val)
{
emit(curseg, &val, 1);
}
//-------------------------------------------------------------------------
void outcode_genword(int val)
{
emit(curseg, &val, 2);
}
//-------------------------------------------------------------------------
void outcode_genlong(int val)
{
emit(curseg, &val, 4);
}
//-------------------------------------------------------------------------
void outcode_genlonglong(LLONG_TYPE val)
{
emit(curseg, &val, 4);
#ifdef BCC32
val = val < 0 ? - 1: 0;
#else
val = val >> 32;
#endif
emit(curseg, &val, 4);
}
//-------------------------------------------------------------------------
void outcode_align(int size)
{
EMIT_TAB *seg = gettab(curseg);
int adr = seg->last->address + seg->last->filled;
adr = size - adr % size;
if (size != adr)
outcode_genstorage(adr);
}
//-------------------------------------------------------------------------
void outcode_put_label(int lab)
{
EMIT_TAB *seg = gettab(curseg);
InsertLabel(lab, seg->last->address + seg->last->filled, curseg);
}
//-------------------------------------------------------------------------
void outcode_start_virtual_seg(SYM *sp, int data)
{
VIRTUAL_LIST *x;
global_flag++;
x = xalloc(sizeof(VIRTUAL_LIST));
x->sp = sp;
x->seg = xalloc(sizeof(EMIT_TAB));
x->data = data;
global_flag--;
if (virtualFirst)
virtualLast = virtualLast->next = x;
else
virtualFirst = virtualLast = x;
}
//-------------------------------------------------------------------------
void outcode_end_virtual_seg(SYM *sp){}
ENODE *GetSymRef(ENODE *n)
{
ENODE *rv;
switch (n->nodetype)
{
case en_add:
case en_addstruc:
if (rv = GetSymRef(n->v.p[0]))
break;
rv = GetSymRef(n->v.p[1]);
break;
case en_icon:
case en_boolcon:
case en_ccon:
case en_cucon:
case en_lcon:
case en_lucon:
case en_iucon:
return 0;
case en_labcon:
case en_nacon:
case en_autocon:
case en_absacon:
case en_nalabcon:
case en_napccon:
return n;
default:
DIAG("Unexpected node type in GetSymRef");
break;
}
return rv;
}
//-------------------------------------------------------------------------
int resolveoffset(OCODE *ins, ENODE *n, int *resolved)
{
int rv = 0;
if (n)
{
switch (n->nodetype)
{
case en_add:
case en_addstruc:
rv += resolveoffset(ins, n->v.p[0], resolved);
rv += resolveoffset(ins, n->v.p[1], resolved);
break;
case en_llcon:
case en_llucon:
case en_icon:
case en_ccon:
case en_cucon:
case en_lcon:
case en_lucon:
case en_iucon:
case en_absacon:
case en_boolcon:
rv += n->v.i;
break;
case en_autocon:
case en_autoreg:
break;
case en_labcon:
case en_nacon:
case en_nalabcon:
case en_napccon:
*resolved = 0;
break;
default:
DIAG("Unexpected node type in resolveoffset");
break;
}
}
return rv;
}
//-------------------------------------------------------------------------
int asmrm(int reg, OCODE *ins, AMODE *data, BYTE **p)
{
int resolved = 1, val;
BYTE *rm;
if (data->mode == am_dreg)
{
reg |= 0xc0 + data->preg;
*(*p)++ = reg;
return 1;
}
rm = *p;
if (data == ins->oper2)
{
ins->resobyte = 1;
}
switch (data->mode)
{
case am_indisp:
indisp: if (data->preg == EBP)
{
*(*p)++ = 5 | reg;
ins->addroffset = *p - ins->outbuf;
val = resolveoffset(ins, data->offset, &resolved);
ins->resolved = resolved;
}
else if (data->preg == ESP)
{
*(*p)++ = 4+reg;
*(*p)++ = 0x24;
ins->addroffset = *p - ins->outbuf;
val = resolveoffset(ins, data->offset, &resolved);
ins->resolved = resolved;
#ifdef FULLVERSION
if (resolved &!val)
return 1;
#endif
}
else
{
*(*p)++ = reg + data->preg;
ins->addroffset = *p - ins->outbuf;
val = resolveoffset(ins, data->offset, &resolved);
ins->resolved = resolved;
#ifdef FULLVERSION
if (resolved && !val)
return 1;
#endif
}
break;
case am_indispscale:
if (data->sreg == - 1)
goto indisp;
if (data->preg == - 1)
{
*(*p)++ = 0x04 + reg;
*(*p)++ = 5+(data->sreg << 3) + (data->scale << 6);
ins->addroffset = *p - ins->outbuf;
*((int*)(*p))++ = resolveoffset(ins, data->offset, &resolved);
ins->resolved = resolved;
return 1;
}
else
{
if (data->sreg == ESP || data->sreg == data->preg && data->sreg
== EBP)
return 0;
if (data->preg != EBP)
{
*(*p)++ = 4+reg;
*(*p)++ = data->preg + (data->sreg << 3) + (data->scale <<
6);
ins->addroffset = *p - ins->outbuf;
val = resolveoffset(ins, data->offset, &resolved);
#ifdef FULLVERSION
if (!val && resolved)
return 1;
#endif
}
else
{
*(*p)++ = 4+reg;
*(*p)++ = 5+(data->sreg << 3) + (data->scale << 6);
ins->addroffset = *p - ins->outbuf;
val = resolveoffset(ins, data->offset, &resolved);
ins->resolved = resolved;
}
}
break;
case am_direct:
*(*p)++ = 5 | reg;
ins->addroffset = *p - ins->outbuf;
*((int*)(*p))++ = resolveoffset(ins, data->offset, &resolved);
ins->resolved = resolved;
return 1;
default:
return 0;
}
if (resolved)
{
#ifdef FULLVERSION
if (val >= - 128 && val < 128)
{
*rm |= 0x40;
*(*p)++ = val;
}
else
#endif
{
*rm |= 0x80;
*((int*)(*p))++ = val;
}
}
else
{
*rm |= 0x80;
*((int*)(*p))++ = val;
}
ins->resolved = resolved;
return 1;
}
//-------------------------------------------------------------------------
int asmfrm(int reg, OCODE *ins, AMODE *data, BYTE **p)
{
reg &= 0x38;
if (data->mode == am_freg)
{
*(*p)++ = 0xc0 + reg + data->preg;
return 1;
}
return asmrm(reg, ins, data, p);
}
/*
* no operands. In this case, the opcode length is 1, so we go through this
* weird locution to rep mov a single byte out of the structure and
* into [di], wherever that points. Apparently it points into an opcode
* buffer somewhere. If the opcode length is greater than one, what
* happens?
*/
int AOP0(OPCODE *descript, OCODE *data, BYTE **p)
{
if (data->oper1)
return 0;
if (descript->ocflags &OCtwobyte)
*((short*)(*p))++ = descript->ocvalue;
else
*(*p)++ = descript->ocvalue;
return 1;
}
/*
* word reg, bits 0-2 of opcode = reg num
*/
int AOP1(OPCODE *descript, OCODE *data, BYTE **p)
{
if (data->oper2)
return 0;
if (data->oper1->length > 5)
return 0;
if (data->oper1->length == 1 || data->oper1->l
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -