📄 assemble.c
字号:
char fname[FILENAME_MAX];
FILE * fp;
long len;
len = FILENAME_MAX-1;
if (len > instruction->eops->stringlen)
len = instruction->eops->stringlen;
strncpy (fname, instruction->eops->stringval, len);
fname[len] = '\0';
if ( (fp = fopen(fname, "rb")) == 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) {
if (matches(temp, instruction) == 100) {
/* we've matched an instruction. */
long isize;
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 */
}
static long calcsize (long segment, long offset, int bits,
insn *ins, 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:
length += ((ins->oprs[c-034].addr_size ?
ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
case 037:
length += 2; break;
case 040: case 041: case 042:
length += 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:
length += ((ins->oprs[c-064].addr_size ?
ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
case 070: case 071: case 072:
length += 4; 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;
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, 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:
bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break;
case R_SS:
bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break;
default:
errfunc (ERR_PANIC, "bizarre 8086 segment register received");
}
out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset++;
break;
case 05: case 07:
switch (ins->oprs[0].basereg) {
case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break;
case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break;
default:
errfunc (ERR_PANIC, "bizarre 386 segment register received");
}
out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset++;
break;
case 010: case 011: case 012:
bytes[0] = *codes++ + regval(&ins->oprs[c-010]);
out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
break;
case 017:
bytes[0] = 0;
out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
break;
case 014: case 015: case 016:
if (ins->oprs[c-014].offset < -128
|| ins->oprs[c-014].offset > 127)
{
errfunc (ERR_WARNING, "signed byte value exceeds bounds");
}
if (ins->oprs[c-014].segment != NO_SEG)
{
data = ins->oprs[c-014].offset;
out (offset, segment, &data, OUT_ADDRESS+1,
ins->oprs[c-014].segment, ins->oprs[c-014].wrt);
}
else {
bytes[0] = ins->oprs[c-014].offset;
out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
}
offset += 1;
break;
case 020: case 021: case 022:
if (ins->oprs[c-020].offset < -256
|| ins->oprs[c-020].offset > 255)
{
errfunc (ERR_WARNING, "byte value exceeds bounds");
}
if (ins->oprs[c-020].segment != NO_SEG) {
data = ins->oprs[c-020].offset;
out (offset, segment, &data, OUT_ADDRESS+1,
ins->oprs[c-020].segment, ins->oprs[c-020].wrt);
}
else {
bytes[0] = ins->oprs[c-020].offset;
out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
}
offset += 1;
break;
case 024: case 025: case 026:
if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255)
errfunc (ERR_WARNING, "unsigned byte value exceeds bounds");
if (ins->oprs[c-024].segment != NO_SEG) {
data = ins->oprs[c-024].offset;
out (offset, segment, &data, OUT_ADDRESS+1,
ins->oprs[c-024].segment, ins->oprs[c-024].wrt);
}
else {
bytes[0] = ins->oprs[c-024].offset;
out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
}
offset += 1;
break;
case 030: case 031: case 032:
if (ins->oprs[c-030].segment == NO_SEG &&
ins->oprs[c-030].wrt == NO_SEG &&
(ins->oprs[c-030].offset < -65536L ||
ins->oprs[c-030].offset > 65535L))
{
errfunc (ERR_WARNING, "word value exceeds bounds");
}
data = ins->oprs[c-030].offset;
out (offset, segment, &data, OUT_ADDRESS+2,
ins->oprs[c-030].segment, ins->oprs[c-030].wrt);
offset += 2;
break;
case 034: case 035: case 036:
data = ins->oprs[c-034].offset;
size = ((ins->oprs[c-034].addr_size ?
ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
if (size==16 && (data < -65536L || data > 65535L))
errfunc (ERR_WARNING, "word value exceeds bounds");
out (offset, segment, &data, OUT_ADDRESS+size,
ins->oprs[c-034].segment, ins->oprs[c-034].wrt);
offset += size;
break;
case 037:
if (ins->oprs[0].segment == NO_SEG)
errfunc (ERR_NONFATAL, "value referenced by FAR is not"
" relocatable");
data = 0L;
out (offset, segment, &data, OUT_ADDRESS+2,
outfmt->segbase(1+ins->oprs[0].segment),
ins->oprs[0].wrt);
offset += 2;
break;
case 040: case 041: case 042:
data = ins->oprs[c-040].offset;
out (offset, segment, &data, OUT_ADDRESS+4,
ins->oprs[c-040].segment, ins->oprs[c-040].wrt);
offset += 4;
break;
case 050: case 051: case 052:
if (ins->oprs[c-050].segment != segment)
errfunc (ERR_NONFATAL, "short relative jump outside segment");
data = ins->oprs[c-050].offset - insn_end;
if (data > 127 || data < -128)
errfunc (ERR_NONFATAL, "short jump is out of range");
bytes[0] = data;
out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
break;
case 060: case 061: case 062:
if (ins->oprs[c-060].segment != segment) {
data = ins->oprs[c-060].offset;
out (offset, segment, &data, OUT_REL2ADR+insn_end-offset,
ins->oprs[c-060].segment, ins->oprs[c-060].wrt);
} else {
data = ins->oprs[c-060].offset - insn_end;
out (offset, segment, &data,
OUT_ADDRESS+2, NO_SEG, NO_SEG);
}
offset += 2;
break;
case 064: case 065: case 066:
size = ((ins->oprs[c-064].addr_size ?
ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
if (ins->oprs[c-064].segment != segment) {
data = ins->oprs[c-064].offset;
size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
out (offset, segment, &data, size+insn_end-offset,
ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
size = (bits == 16 ? 2 : 4);
} else {
data = ins->oprs[c-064].offset - insn_end;
out (offset, segment, &data,
OUT_ADDRESS+size, NO_SEG, NO_SEG);
}
offset += size;
break;
case 070: case 071: case 072:
if (ins->oprs[c-070].segment != segment) {
data = ins->oprs[c-070].offset;
out (offset, segment, &data, OUT_REL4ADR+insn_end-offset,
ins->oprs[c-070].segment, ins->oprs[c-070].wrt);
} else {
data = ins->oprs[c-070].offset - insn_end;
out (offset, segment, &data,
OUT_ADDRESS+4, NO_SEG, NO_SEG);
}
offset += 4;
break;
case 0300: case 0301: case 0302:
if (chsize (&ins->oprs[c-0300], bits)) {
*bytes = 0x67;
out (offset, segment, bytes,
OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
} else
offset += 0;
break;
case 0310:
if (bits==32) {
*bytes = 0x67;
out (offset, segment, bytes,
OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
} else
offset += 0;
break;
case 0311:
if (bits==16) {
*bytes = 0x67;
out (offset, segment, bytes,
OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
} else
offset += 0;
break;
case 0312:
break;
case 0320:
if (bits==32) {
*bytes = 0x66;
out (offset, segment, bytes,
OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
} else
offset += 0;
break;
case 0321:
if (bits==16) {
*bytes = 0x66;
out (offset, segment, bytes,
OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
} else
offset += 0;
break;
case 0322:
break;
case 0330:
*bytes = *codes++ + condval[ins->condition];
out (offset, segment, bytes,
OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
break;
case 0331:
case 0332:
break;
case 0333:
*bytes = 0xF3;
out (offset, segment, bytes,
OUT_RAWDATA+1, NO_SEG, NO_SEG);
offset += 1;
break;
case 0340: case 0341: case 0342:
if (ins->oprs[0].segment != NO_SEG)
errfunc (ERR_PANIC, "non-constant BSS size in pass two");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -