📄 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 */
}
size_prob = FALSE;
temp = nasm_instructions[instruction->opcode];
while (temp->opcode != -1) {
int m = matches(temp, instruction);
if (m == 99)
m += jmp_match(segment, offset, bits, instruction, temp->code);
if (m == 100) { /* matches! */
const char *codes = temp->code;
long 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++) {
unsigned char 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:
c = 0x2E;
break;
case R_DS:
c = 0x3E;
break;
case R_ES:
c = 0x26;
break;
case R_FS:
c = 0x64;
break;
case R_GS:
c = 0x65;
break;
case R_SS:
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 != 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 != 32)
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 */
if (size_prob == 1) /* would have matched, but for size */
error(ERR_NONFATAL, "operation size not specified");
else if (size_prob == 2)
error(ERR_NONFATAL, "mismatch in operand sizes");
else if (size_prob == 3)
error(ERR_NONFATAL, "no instruction for this cpu level");
else
error(ERR_NONFATAL,
"invalid combination of opcode and operands");
}
return 0;
}
long insn_size(long segment, long offset, int bits, unsigned long cp,
insn * instruction, efunc error)
{
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) {
extop *e;
long 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;
}
for (e = instruction->eops; e; e = e->next) {
long 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;
long 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 */
}
temp = nasm_instructions[instruction->opcode];
while (temp->opcode != -1) {
int m = matches(temp, instruction);
if (m == 99)
m += jmp_match(segment, offset, bits, instruction, temp->code);
if (m == 100) {
/* we've matched an instruction. */
long 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++) {
if ((instruction->prefixes[j] != P_A16 &&
instruction->prefixes[j] != P_O16 && bits == 16) ||
(instruction->prefixes[j] != P_A32 &&
instruction->prefixes[j] != P_O32 && bits == 32)) {
isize++;
}
}
return isize * instruction->times;
}
temp++;
}
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)
{
signed long 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 = (signed short)v; /* sign extend if 16 bits */
return ret && v >= -128L && v <= 127L;
}
static long calcsize(long segment, long offset, int bits,
insn * ins, const char *codes)
{
long length = 0;
unsigned char c;
(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:
codes++, length++;
break;
case 017:
length++;
break;
case 014:
case 015:
case 016:
length++;
break;
case 020:
case 021:
case 022:
length++;
break;
case 024:
case 025:
case 026:
length++;
break;
case 030:
case 031:
case 032:
length += 2;
break;
case 034:
case 035:
case 036:
if (ins->oprs[c - 034].type & (BITS16 | BITS32))
length += (ins->oprs[c - 034].type & BITS16) ? 2 : 4;
else
length += (bits == 16) ? 2 : 4;
break;
case 037:
length += 2;
break;
case 040:
case 041:
case 042:
length += 4;
break;
case 044:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -