📄 assemble.c
字号:
}
list->downlevel(LIST_INCBIN);
if (instruction->times > 1) {
/*
* Dummy call to list->output to give the offset to the
* listing module.
*/
list->output(offset, NULL, OUT_RAWDATA);
list->uplevel(LIST_TIMES);
list->downlevel(LIST_TIMES);
}
fclose(fp);
return instruction->times * len;
}
return 0; /* if we're here, there's an error */
}
/* Check to see if we need an address-size prefix */
add_asp(instruction, bits);
size_prob = false;
for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++){
int m = matches(temp, instruction, bits);
if (m == 99)
m += jmp_match(segment, offset, bits, instruction, temp->code);
if (m == 100) { /* matches! */
const char *codes = temp->code;
int32_t insn_size = calcsize(segment, offset, bits,
instruction, codes);
itimes = instruction->times;
if (insn_size < 0) /* shouldn't be, on pass two */
error(ERR_PANIC, "errors made it through from pass one");
else
while (itimes--) {
for (j = 0; j < instruction->nprefix; j++) {
uint8_t c = 0;
switch (instruction->prefixes[j]) {
case P_LOCK:
c = 0xF0;
break;
case P_REPNE:
case P_REPNZ:
c = 0xF2;
break;
case P_REPE:
case P_REPZ:
case P_REP:
c = 0xF3;
break;
case R_CS:
if (bits == 64) {
error(ERR_WARNING,
"cs segment base ignored in 64-bit mode");
}
c = 0x2E;
break;
case R_DS:
if (bits == 64) {
error(ERR_WARNING,
"ds segment base ignored in 64-bit mode");
}
c = 0x3E;
break;
case R_ES:
if (bits == 64) {
error(ERR_WARNING,
"es segment base ignored in 64-bit mode");
}
c = 0x26;
break;
case R_FS:
c = 0x64;
break;
case R_GS:
c = 0x65;
break;
case R_SS:
if (bits == 64) {
error(ERR_WARNING,
"ss segment base ignored in 64-bit mode");
}
c = 0x36;
break;
case R_SEGR6:
case R_SEGR7:
error(ERR_NONFATAL,
"segr6 and segr7 cannot be used as prefixes");
break;
case P_A16:
if (bits == 64) {
error(ERR_NONFATAL,
"16-bit addressing is not supported "
"in 64-bit mode");
break;
}
if (bits != 16)
c = 0x67;
break;
case P_A32:
if (bits != 32)
c = 0x67;
break;
case P_O16:
if (bits != 16)
c = 0x66;
break;
case P_O32:
if (bits == 16)
c = 0x66;
break;
default:
error(ERR_PANIC, "invalid instruction prefix");
}
if (c != 0) {
out(offset, segment, &c, OUT_RAWDATA + 1,
NO_SEG, NO_SEG);
offset++;
}
}
insn_end = offset + insn_size;
gencode(segment, offset, bits, instruction, codes,
insn_end);
offset += insn_size;
if (itimes > 0 && itimes == instruction->times - 1) {
/*
* Dummy call to list->output to give the offset to the
* listing module.
*/
list->output(offset, NULL, OUT_RAWDATA);
list->uplevel(LIST_TIMES);
}
}
if (instruction->times > 1)
list->downlevel(LIST_TIMES);
return offset - start;
} else if (m > 0 && m > size_prob) {
size_prob = m;
}
// temp++;
}
if (temp->opcode == -1) { /* didn't match any instruction */
switch (size_prob) {
case 1:
error(ERR_NONFATAL, "operation size not specified");
break;
case 2:
error(ERR_NONFATAL, "mismatch in operand sizes");
break;
case 3:
error(ERR_NONFATAL, "no instruction for this cpu level");
break;
case 4:
error(ERR_NONFATAL, "instruction not supported in 64-bit mode");
break;
default:
error(ERR_NONFATAL,
"invalid combination of opcode and operands");
break;
}
}
return 0;
}
int32_t insn_size(int32_t segment, int32_t offset, int bits, uint32_t cp,
insn * instruction, efunc error)
{
const struct itemplate *temp;
errfunc = error; /* to pass to other functions */
cpu = cp;
if (instruction->opcode == -1)
return 0;
if (instruction->opcode == I_DB || instruction->opcode == I_DW ||
instruction->opcode == I_DD || instruction->opcode == I_DQ ||
instruction->opcode == I_DT || instruction->opcode == I_DO) {
extop *e;
int32_t isize, osize, wsize = 0; /* placate gcc */
isize = 0;
switch (instruction->opcode) {
case I_DB:
wsize = 1;
break;
case I_DW:
wsize = 2;
break;
case I_DD:
wsize = 4;
break;
case I_DQ:
wsize = 8;
break;
case I_DT:
wsize = 10;
break;
case I_DO:
wsize = 16;
break;
default:
break;
}
for (e = instruction->eops; e; e = e->next) {
int32_t align;
osize = 0;
if (e->type == EOT_DB_NUMBER)
osize = 1;
else if (e->type == EOT_DB_STRING)
osize = e->stringlen;
align = (-osize) % wsize;
if (align < 0)
align += wsize;
isize += osize + align;
}
return isize * instruction->times;
}
if (instruction->opcode == I_INCBIN) {
char fname[FILENAME_MAX];
FILE *fp;
int32_t len;
char *prefix = "", *combine;
char **pPrevPath = NULL;
len = FILENAME_MAX - 1;
if (len > instruction->eops->stringlen)
len = instruction->eops->stringlen;
strncpy(fname, instruction->eops->stringval, len);
fname[len] = '\0';
while (1) { /* added by alexfru: 'incbin' uses include paths */
combine = nasm_malloc(strlen(prefix) + len + 1);
strcpy(combine, prefix);
strcat(combine, fname);
if ((fp = fopen(combine, "rb")) != NULL) {
nasm_free(combine);
break;
}
nasm_free(combine);
pPrevPath = pp_get_include_path_ptr(pPrevPath);
if (pPrevPath == NULL)
break;
prefix = *pPrevPath;
}
if (fp == NULL)
error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
fname);
else if (fseek(fp, 0L, SEEK_END) < 0)
error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
fname);
else {
len = ftell(fp);
fclose(fp);
if (instruction->eops->next) {
len -= instruction->eops->next->offset;
if (instruction->eops->next->next &&
len > instruction->eops->next->next->offset) {
len = instruction->eops->next->next->offset;
}
}
return instruction->times * len;
}
return 0; /* if we're here, there's an error */
}
/* Check to see if we need an address-size prefix */
add_asp(instruction, bits);
for (temp = nasm_instructions[instruction->opcode]; temp->opcode != -1; temp++) {
int m = matches(temp, instruction, bits);
if (m == 99)
m += jmp_match(segment, offset, bits, instruction, temp->code);
if (m == 100) {
/* we've matched an instruction. */
int32_t isize;
const char *codes = temp->code;
int j;
isize = calcsize(segment, offset, bits, instruction, codes);
if (isize < 0)
return -1;
for (j = 0; j < instruction->nprefix; j++) {
switch (instruction->prefixes[j]) {
case P_A16:
if (bits != 16)
isize++;
break;
case P_A32:
if (bits != 32)
isize++;
break;
case P_O16:
if (bits != 16)
isize++;
break;
case P_O32:
if (bits == 16)
isize++;
break;
default:
isize++;
break;
}
}
return isize * instruction->times;
}
}
return -1; /* didn't match any instruction */
}
/* check that opn[op] is a signed byte of size 16 or 32,
and return the signed value*/
static int is_sbyte(insn * ins, int op, int size)
{
int32_t v;
int ret;
ret = !(ins->forw_ref && ins->oprs[op].opflags) && /* dead in the water on forward reference or External */
optimizing >= 0 &&
!(ins->oprs[op].type & STRICT) &&
ins->oprs[op].wrt == NO_SEG && ins->oprs[op].segment == NO_SEG;
v = ins->oprs[op].offset;
if (size == 16)
v = (int16_t)v; /* sign extend if 16 bits */
return ret && v >= -128L && v <= 127L;
}
static int32_t calcsize(int32_t segment, int32_t offset, int bits,
insn * ins, const char *codes)
{
int32_t length = 0;
uint8_t c;
int rex_mask = ~0;
ins->rex = 0; /* Ensure REX is reset */
(void)segment; /* Don't warn that this parameter is unused */
(void)offset; /* Don't warn that this parameter is unused */
while (*codes)
switch (c = *codes++) {
case 01:
case 02:
case 03:
codes += c, length += c;
break;
case 04:
case 05:
case 06:
case 07:
length++;
break;
case 010:
case 011:
case 012:
case 013:
ins->rex |=
op_rexflags(&ins->oprs[c - 010], REX_B|REX_H|REX_P|REX_W);
codes++, length++;
break;
case 014:
case 015:
case 016:
case 017:
length++;
break;
case 020:
case 021:
case 022:
case 023:
length++;
break;
case 024:
case 025:
case 026:
case 027:
length++;
break;
case 030:
case 031:
case 032:
case 033:
length += 2;
break;
case 034:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -