📄 assemble.c
字号:
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: case 045: case 046:
length += ((ins->oprs[c-044].addr_size ?
ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); break;
case 050: case 051: case 052:
length++; break;
case 060: case 061: case 062:
length += 2; break;
case 064: case 065: case 066:
if ( ins->oprs[c-064].type & (BITS16|BITS32) )
length += (ins->oprs[c-064].type & BITS16) ? 2 : 4;
else
length += (bits == 16) ? 2 : 4;
break;
case 070: case 071: case 072:
length += 4; break;
case 0130: case 0131: case 0132:
length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break;
case 0133: case 0134: case 0135:
codes+=2; length++; break;
case 0140: case 0141: case 0142:
length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break;
case 0143: case 0144: case 0145:
codes+=2; length++; break;
case 0300: case 0301: case 0302:
length += chsize (&ins->oprs[c-0300], bits);
break;
case 0310:
length += (bits==32);
break;
case 0311:
length += (bits==16);
break;
case 0312:
break;
case 0320:
length += (bits==32);
break;
case 0321:
length += (bits==16);
break;
case 0322:
break;
case 0330:
codes++, length++; break;
case 0331:
case 0332:
break;
case 0333:
length++; break;
case 0340: case 0341: case 0342:
if (ins->oprs[0].segment != NO_SEG)
errfunc (ERR_NONFATAL, "attempt to reserve non-constant"
" quantity of BSS space");
else
length += ins->oprs[0].offset << (c-0340);
break;
case 0370: case 0371: case 0372:
break;
case 0373:
length++; break;
default: /* can't do it by 'case' statements */
if (c>=0100 && c<=0277) { /* it's an EA */
ea ea_data;
if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0,
ins->forw_ref)) {
errfunc (ERR_NONFATAL, "invalid effective address");
return -1;
} else
length += ea_data.size;
} else
errfunc (ERR_PANIC, "internal instruction table corrupt"
": instruction code 0x%02X given", c);
}
return length;
}
static void gencode (long segment, long offset, int bits,
insn *ins, const char *codes, long insn_end)
{
static char condval[] = { /* conditional opcodes */
0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2,
0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5,
0x0, 0xA, 0xA, 0xB, 0x8, 0x4
};
unsigned char c;
unsigned char bytes[4];
long data, size;
while (*codes)
switch (c = *codes++)
{
case 01: case 02: case 03:
out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG);
codes += c;
offset += c;
break;
case 04: case 06:
switch (ins->oprs[0].basereg)
{
case R_CS:
bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break;
case R_DS:
bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break;
case R_ES:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -