📄 assemble.c
字号:
else {
long size = ins->oprs[0].offset << (c-0340);
if (size > 0)
out (offset, segment, NULL,
OUT_RESERVE+size, NO_SEG, NO_SEG);
offset += size;
}
break;
default: /* can't do it by 'case' statements */
if (c>=0100 && c<=0277) { /* it's an EA */
ea ea_data;
int rfield;
unsigned char *p;
long s;
if (c<=0177) /* pick rfield from operand b */
rfield = regval (&ins->oprs[c&7]);
else /* rfield is constant */
rfield = c & 7;
if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,
ins->forw_ref))
{
errfunc (ERR_NONFATAL, "invalid effective address");
}
p = bytes;
*p++ = ea_data.modrm;
if (ea_data.sib_present)
*p++ = ea_data.sib;
s = p-bytes;
out (offset, segment, bytes, OUT_RAWDATA + s,
NO_SEG, NO_SEG);
switch (ea_data.bytes) {
case 0:
break;
case 1:
if (ins->oprs[(c>>3)&7].segment != NO_SEG) {
data = ins->oprs[(c>>3)&7].offset;
out (offset, segment, &data, OUT_ADDRESS+1,
ins->oprs[(c>>3)&7].segment,
ins->oprs[(c>>3)&7].wrt);
} else {
*bytes = ins->oprs[(c>>3)&7].offset;
out (offset, segment, bytes, OUT_RAWDATA+1,
NO_SEG, NO_SEG);
}
s++;
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);
}
}
static int regval (operand *o)
{
switch (o->basereg) {
case R_EAX: case R_AX: case R_AL: case R_ES: case R_CR0: case R_DR0:
case R_ST0: case R_MM0: case R_XMM0:
return 0;
case R_ECX: case R_CX: case R_CL: case R_CS: case R_DR1: case R_ST1:
case R_MM1: case R_XMM1:
return 1;
case R_EDX: case R_DX: case R_DL: case R_SS: case R_CR2: case R_DR2:
case R_ST2: case R_MM2: case R_XMM2:
return 2;
case R_EBX: case R_BX: case R_BL: case R_DS: case R_CR3: case R_DR3:
case R_TR3: case R_ST3: case R_MM3: case R_XMM3:
return 3;
case R_ESP: case R_SP: case R_AH: case R_FS: case R_CR4: case R_TR4:
case R_ST4: case R_MM4: case R_XMM4:
return 4;
case R_EBP: case R_BP: case R_CH: case R_GS: case R_TR5: case R_ST5:
case R_MM5: case R_XMM5:
return 5;
case R_ESI: case R_SI: case R_DH: case R_DR6: case R_TR6: case R_ST6:
case R_MM6: case R_XMM6:
return 6;
case R_EDI: case R_DI: case R_BH: case R_DR7: case R_TR7: case R_ST7:
case R_MM7: case R_XMM7:
return 7;
default: /* panic */
errfunc (ERR_PANIC, "invalid register operand given to regval()");
return 0;
}
}
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;
}
/*
* 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 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 (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) b ^= i ^= b ^= i; /* swap them round */
if ((b==R_SI || b==R_DI) && i!=-1)
b ^= i ^= b ^= i; /* 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 + -