📄 assemble.c
字号:
/*
* 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 + -