📄 assemble.c
字号:
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"); else { long size = ins->oprs[0].offset << (c-0340); if (size > 0) out (offset, segment, NULL, OUT_RESERVE+size, NO_SEG, NO_SEG); offset += size; } break; case 0370: case 0371: case 0372: break; case 0373: *bytes = bits==16 ? 3 : 5; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset += 1; break; default: /* can't do it by 'case' statements */ if (c>=0100 && c<=0277) { /* it's an EA */ ea ea_data; int rfield; unsigned char *p; long s; if (c<=0177) /* pick rfield from operand b */ rfield = regval (&ins->oprs[c&7]); else /* rfield is constant */ rfield = c & 7; if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield, ins->forw_ref)) { errfunc (ERR_NONFATAL, "invalid effective address"); } p = bytes; *p++ = ea_data.modrm; if (ea_data.sib_present) *p++ = ea_data.sib; s = p-bytes; out (offset, segment, bytes, OUT_RAWDATA + s, NO_SEG, NO_SEG); switch (ea_data.bytes) { case 0: break; case 1: if (ins->oprs[(c>>3)&7].segment != NO_SEG) { data = ins->oprs[(c>>3)&7].offset; out (offset, segment, &data, OUT_ADDRESS+1, ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt); } else { *bytes = ins->oprs[(c>>3)&7].offset; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); } s++; break; case 2: case 4: data = ins->oprs[(c>>3)&7].offset; out (offset, segment, &data, OUT_ADDRESS+ea_data.bytes, ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt); s += ea_data.bytes; break; } offset += s; } else errfunc (ERR_PANIC, "internal instruction table corrupt" ": instruction code 0x%02X given", c); }}#include "regvals.c"static int regval (operand *o) { if ( o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT ) { errfunc (ERR_PANIC, "invalid operand passed to regval()"); } return regvals[o->basereg];}static int matches (struct itemplate *itemp, insn *instruction) { int i, size[3], asize, oprs, ret; ret = 100; /* * Check the opcode */ if (itemp->opcode != instruction->opcode) return 0; /* * Count the operands */ if (itemp->operands != instruction->operands) return 0; /* * Check that no spurious colons or TOs are present */ for (i=0; i<itemp->operands; i++) if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO)) return 0; /* * Check that the operand flags all match up */ for (i=0; i<itemp->operands; i++) if (itemp->opd[i] & ~instruction->oprs[i].type || ((itemp->opd[i] & SIZE_MASK) && ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK))) { if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) || (instruction->oprs[i].type & SIZE_MASK)) return 0; else/* ret = 1; */ return 1; } /* * Check operand sizes */ if (itemp->flags & IF_ARMASK) { size[0] = size[1] = size[2] = 0; switch (itemp->flags & IF_ARMASK) { case IF_AR0: i = 0; break; case IF_AR1: i = 1; break; case IF_AR2: i = 2; break; default: break; /* Shouldn't happen */ } if (itemp->flags & IF_SB) { size[i] = BITS8; } else if (itemp->flags & IF_SW) { size[i] = BITS16; } else if (itemp->flags & IF_SD) { size[i] = BITS32; } } else { asize = 0; if (itemp->flags & IF_SB) { asize = BITS8; oprs = itemp->operands; } else if (itemp->flags & IF_SW) { asize = BITS16; oprs = itemp->operands; } else if (itemp->flags & IF_SD) { asize = BITS32; oprs = itemp->operands; } size[0] = size[1] = size[2] = asize; } if (itemp->flags & (IF_SM | IF_SM2)) { oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands); asize = 0; for (i=0; i<oprs; i++) { if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) { int j; for (j=0; j<oprs; j++) size[j] = asize; break; } } } else { oprs = itemp->operands; } for (i=0; i<itemp->operands; i++) if (!(itemp->opd[i] & SIZE_MASK) && (instruction->oprs[i].type & SIZE_MASK & ~size[i]))/* ret = 2; */ return 2; /* * 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 + -