📄 assemble.c
字号:
break;
case 2:
case 4:
data = ins->oprs[(c>>3)&7].offset;
out (offset, segment, &data,
OUT_ADDRESS+ea_data.bytes,
ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
s += ea_data.bytes;
break;
}
offset += s;
} else
errfunc (ERR_PANIC, "internal instruction table corrupt"
": instruction code 0x%02X given", c);
}
}
#include "regvals.c"
static int regval (operand *o)
{
if ( o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT ) {
errfunc (ERR_PANIC, "invalid operand passed to regval()");
}
return regvals[o->basereg];
}
static int matches (struct itemplate *itemp, insn *instruction)
{
int i, size[3], asize, oprs, ret;
ret = 100;
/*
* Check the opcode
*/
if (itemp->opcode != instruction->opcode) return 0;
/*
* Count the operands
*/
if (itemp->operands != instruction->operands) return 0;
/*
* Check that no spurious colons or TOs are present
*/
for (i=0; i<itemp->operands; i++)
if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
return 0;
/*
* Check that the operand flags all match up
*/
for (i=0; i<itemp->operands; i++)
if (itemp->opd[i] & ~instruction->oprs[i].type ||
((itemp->opd[i] & SIZE_MASK) &&
((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
{
if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
(instruction->oprs[i].type & SIZE_MASK))
return 0;
else
/* ret = 1; */
return 1;
}
/*
* Check operand sizes
*/
if (itemp->flags & IF_ARMASK) {
size[0] = size[1] = size[2] = 0;
switch (itemp->flags & IF_ARMASK) {
case IF_AR0: i = 0; break;
case IF_AR1: i = 1; break;
case IF_AR2: i = 2; break;
default: break; /* Shouldn't happen */
}
if (itemp->flags & IF_SB) {
size[i] = BITS8;
} else if (itemp->flags & IF_SW) {
size[i] = BITS16;
} else if (itemp->flags & IF_SD) {
size[i] = BITS32;
}
} else {
asize = 0;
if (itemp->flags & IF_SB) {
asize = BITS8;
oprs = itemp->operands;
} else if (itemp->flags & IF_SW) {
asize = BITS16;
oprs = itemp->operands;
} else if (itemp->flags & IF_SD) {
asize = BITS32;
oprs = itemp->operands;
}
size[0] = size[1] = size[2] = asize;
}
if (itemp->flags & (IF_SM | IF_SM2)) {
oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
asize = 0;
for (i=0; i<oprs; i++) {
if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
int j;
for (j=0; j<oprs; j++)
size[j] = asize;
break;
}
}
} else {
oprs = itemp->operands;
}
for (i=0; i<itemp->operands; i++)
if (!(itemp->opd[i] & SIZE_MASK) &&
(instruction->oprs[i].type & SIZE_MASK & ~size[i]))
/* ret = 2; */
return 2;
/*
* Check template is okay at the set cpu level
*/
if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
/*
* Check if special handling needed for Jumps
*/
if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
return ret;
}
static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
int forw_ref)
{
if (!(REGISTER & ~input->type)) { /* it's a single register */
static int regs[] = {
R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH,
R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI,
R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI,
R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
};
int i;
for (i=0; i<elements(regs); i++)
if (input->basereg == regs[i]) break;
if (i<elements(regs)) {
output->sib_present = FALSE;/* no SIB necessary */
output->bytes = 0; /* no offset necessary either */
output->modrm = 0xC0 | (rfield << 3) | (i & 7);
}
else
return NULL;
} else { /* it's a memory reference */
if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
/* it's a pure offset */
if (input->addr_size)
addrbits = input->addr_size;
output->sib_present = FALSE;
output->bytes = (addrbits==32 ? 4 : 2);
output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
}
else { /* it's an indirection */
int i=input->indexreg, b=input->basereg, s=input->scale;
long o=input->offset, seg=input->segment;
int hb=input->hintbase, ht=input->hinttype;
int t;
if (s==0) i = -1; /* make this easy, at least */
if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
|| i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
|| b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
|| b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
/* it must be a 32-bit memory reference. Firstly we have
* to check that all registers involved are type Exx. */
if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
&& i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
return NULL;
if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
&& b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
return NULL;
/* While we're here, ensure the user didn't specify WORD. */
if (input->addr_size == 16)
return NULL;
/* now reorganise base/index */
if (s == 1 && b != i && b != -1 && i != -1 &&
((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
t = b, b = i, i = t; /* swap if hints say so */
if (b==i) /* convert EAX+2*EAX to 3*EAX */
b = -1, s++;
if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
b = i, i = -1; /* make single reg base, unless hint */
if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
s==3 || s==5 || s==9) && b==-1)
b = i, s--; /* convert 3*EAX to EAX+2*EAX */
if (i==-1 && b!=R_ESP && (input->eaflags & EAF_TIMESTWO))
i = b, b = -1, s = 1;
/* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
if (s==1 && i==R_ESP) /* swap ESP into base if scale is 1 */
i = b, b = R_ESP;
if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
return NULL; /* wrong, for various reasons */
if (i==-1 && b!=R_ESP) {/* no SIB needed */
int mod, rm;
switch(b) {
case R_EAX: rm = 0; break;
case R_ECX: rm = 1; break;
case R_EDX: rm = 2; break;
case R_EBX: rm = 3; break;
case R_EBP: rm = 5; break;
case R_ESI: rm = 6; break;
case R_EDI: rm = 7; break;
case -1: rm = 5; break;
default: /* should never happen */
return NULL;
}
if (b==-1 || (b!=R_EBP && o==0 &&
seg==NO_SEG && !forw_ref &&
!(input->eaflags &
(EAF_BYTEOFFS|EAF_WORDOFFS))))
mod = 0;
else if (input->eaflags & EAF_BYTEOFFS ||
(o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
!(input->eaflags & EAF_WORDOFFS))) {
mod = 1;
}
else
mod = 2;
output->sib_present = FALSE;
output->bytes = (b==-1 || mod==2 ? 4 : mod);
output->modrm = (mod<<6) | (rfield<<3) | rm;
}
else { /* we need a SIB */
int mod, scale, index, base;
switch (b) {
case R_EAX: base = 0; break;
case R_ECX: base = 1; break;
case R_EDX: base = 2; break;
case R_EBX: base = 3; break;
case R_ESP: base = 4; break;
case R_EBP: case -1: base = 5; break;
case R_ESI: base = 6; break;
case R_EDI: base = 7; break;
default: /* then what the smeg is it? */
return NULL; /* panic */
}
switch (i) {
case R_EAX: index = 0; break;
case R_ECX: index = 1; break;
case R_EDX: index = 2; break;
case R_EBX: index = 3; break;
case -1: index = 4; break;
case R_EBP: index = 5; break;
case R_ESI: index = 6; break;
case R_EDI: index = 7; break;
default: /* then what the smeg is it? */
return NULL; /* panic */
}
if (i==-1) s = 1;
switch (s) {
case 1: scale = 0; break;
case 2: scale = 1; break;
case 4: scale = 2; break;
case 8: scale = 3; break;
default: /* then what the smeg is it? */
return NULL; /* panic */
}
if (b==-1 || (b!=R_EBP && o==0 &&
seg==NO_SEG && !forw_ref &&
!(input->eaflags &
(EAF_BYTEOFFS|EAF_WORDOFFS))))
mod = 0;
else if (input->eaflags & EAF_BYTEOFFS ||
(o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
!(input->eaflags & EAF_WORDOFFS)))
mod = 1;
else
mod = 2;
output->sib_present = TRUE;
output->bytes = (b==-1 || mod==2 ? 4 : mod);
output->modrm = (mod<<6) | (rfield<<3) | 4;
output->sib = (scale<<6) | (index<<3) | base;
}
}
else { /* it's 16-bit */
int mod, rm;
/* check all registers are BX, BP, SI or DI */
if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
(i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
return NULL;
/* ensure the user didn't specify DWORD */
if (input->addr_size == 32)
return NULL;
if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
if ((b==R_SI || b==R_DI) && i!=-1)
{ int tmp = b; b = i; i = tmp; }
/* have BX/BP as base, SI/DI index */
if (b==i) return NULL;/* shouldn't ever happen, in theory */
if (i!=-1 && b!=-1 &&
(i==R_BP || i==R_BX || b==R_SI || b==R_DI))
return NULL; /* invalid combinations */
if (b==-1) /* pure offset: handled above */
return NULL; /* so if it gets to here, panic! */
rm = -1;
if (i!=-1)
switch (i*256 + b) {
case R_SI*256+R_BX: rm=0; break;
case R_DI*256+R_BX: rm=1; break;
case R_SI*256+R_BP: rm=2; break;
case R_DI*256+R_BP: rm=3; break;
}
else
switch (b) {
case R_SI: rm=4; break;
case R_DI: rm=5; break;
case R_BP: rm=6; break;
case R_BX: rm=7; break;
}
if (rm==-1) /* can't happen, in theory */
return NULL; /* so panic if it does */
if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
!(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
mod = 0;
else if (input->eaflags & EAF_BYTEOFFS ||
(o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
!(input->eaflags & EAF_WORDOFFS)))
mod = 1;
else
mod = 2;
output->sib_present = FALSE; /* no SIB - it's 16-bit */
output->bytes = mod; /* bytes of offset needed */
output->modrm = (mod<<6) | (rfield<<3) | rm;
}
}
}
output->size = 1 + output->sib_present + output->bytes;
return output;
}
static int chsize (operand *input, int addrbits)
{
if (!(MEMORY & ~input->type)) {
int i=input->indexreg, b=input->basereg;
if (input->scale==0) i = -1;
if (i == -1 && b == -1) /* pure offset */
return (input->addr_size != 0 && input->addr_size != addrbits);
if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
|| i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
|| b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
|| b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
return (addrbits==16);
else
return (addrbits==32);
}
else
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -