📄 assembl.c
字号:
if (j==0) arg=pd->arg1;
else if (j==1) arg=pd->arg2;
else arg=pd->arg3;
if (arg==NNN) break; // All operands processed
switch (arg) {
case REG: // Integer register in Reg field
case RG4: // Integer 4-byte register in Reg field
case RMX: // MMX register MMx
case R3D: // 3DNow! register MMx
case CRX: // Control register CRx
case DRX: // Debug register DRx
hasrm=1;
if (op->index<8) {
tcode[i+1]|=(char)(op->index<<3); tmask[i+1]|=0x38; };
break;
case RCM: // Integer register in command byte
case RST: // FPU register (ST(i)) in command byte
if (op->index<8) {
tcode[i]|=(char)op->index; tmask[i]|=0x07; };
break;
case RAC: // Accumulator (AL/AX/EAX, implicit)
case RAX: // AX (2-byte, implicit)
case RDX: // DX (16-bit implicit port address)
case RCL: // Implicit CL register (for shifts)
case RS0: // Top of FPU stack (ST(0))
case MDE: // Destination in string op's ([EDI])
case C01: // Implicit constant 1 (for shifts)
break; // Simply skip implicit operands
case MSO: // Source in string op's ([ESI])
case MXL: // XLAT operand ([EBX+AL])
if (op->segment!=SEG_UNDEF && op->segment!=SEG_DS)
segment=op->segment;
break;
case MRG: // Memory/register in ModRM byte
case MRJ: // Memory/reg in ModRM as JUMP target
case MR1: // 1-byte memory/register in ModRM byte
case MR2: // 2-byte memory/register in ModRM byte
case MR4: // 4-byte memory/register in ModRM byte
case RR4: // 4-byte memory/register (register only)
case MR8: // 8-byte memory/MMX register in ModRM
case RR8: // 8-byte MMX register only in ModRM
case MRD: // 8-byte memory/3DNow! register in ModRM
case RRD: // 8-byte memory/3DNow! (register only)
hasrm=1;
if (op->type!=MRG) { // Register in ModRM byte
tcode[i+1]|=0xC0; tmask[i+1]|=0xC0;
if (op->index<8) {
tcode[i+1]|=(char)op->index; tmask[i+1]|=0x07; };
break;
}; // Note: NO BREAK, continue with address
case MMA: // Memory address in ModRM byte for LEA
case MML: // Memory in ModRM byte (for LES)
case MMS: // Memory in ModRM byte (as SEG:OFFS)
case MM6: // Memory in ModRm (6-byte descriptor)
case MMB: // Two adjacent memory locations (BOUND)
case MD2: // Memory in ModRM byte (16-bit integer)
case MB2: // Memory in ModRM byte (16-bit binary)
case MD4: // Memory in ModRM byte (32-bit integer)
case MD8: // Memory in ModRM byte (64-bit integer)
case MDA: // Memory in ModRM byte (80-bit BCD)
case MF4: // Memory in ModRM byte (32-bit float)
case MF8: // Memory in ModRM byte (64-bit float)
case MFA: // Memory in ModRM byte (80-bit float)
case MFE: // Memory in ModRM byte (FPU environment)
case MFS: // Memory in ModRM byte (FPU state)
case MFX: // Memory in ModRM byte (ext. FPU state)
hasrm=1; displacement=op->offset; anydisp=op->anyoffset;
if (op->base<0 && op->index<0) {
dispsize=4; // Special case of immediate address
if (op->segment!=SEG_UNDEF && op->segment!=SEG_DS)
segment=op->segment;
tcode[i+1]|=0x05;
tmask[i+1]|=0xC7; }
else if (op->index<0 && op->base!=REG_ESP) {
tmask[i+1]|=0xC0; // SIB byte unnecessary
if (op->offset==0 && op->anyoffset==0 && op->base!=REG_EBP)
; // [EBP] always requires offset
else if ((constsize & 1)!=0 &&
((op->offset>=-128 && op->offset<128) || op->anyoffset!=0)
) {
tcode[i+1]|=0x40; // Disp8
dispsize=1; }
else {
tcode[i+1]|=0x80; // Disp32
dispsize=4; };
if (op->base<8) {
if (op->segment!=SEG_UNDEF && op->segment!=addr32[op->base].defseg)
segment=op->segment;
tcode[i+1]|=
(char)op->base; // Note that case [ESP] has base<0.
tmask[i+1]|=0x07; }
else segment=op->segment; }
else { // SIB byte necessary
hassib=1;
if (op->base==REG_EBP && // EBP as base requires offset, optimize
op->index>=0 && op->scale==1 && op->offset==0 && op->anyoffset==0) {
op->base=op->index; op->index=REG_EBP; };
if (op->index==REG_ESP && // ESP cannot be an index, reorder
op->scale<=1) {
op->index=op->base; op->base=REG_ESP; op->scale=1; };
if (op->base<0 && // No base means 4-byte offset, optimize
op->index>=0 && op->scale==2 &&
op->offset>=-128 && op->offset<128 && op->anyoffset==0) {
op->base=op->index; op->scale=1; };
if (op->index==REG_ESP) { // Reordering was unsuccessfull
strcpy(errtext,"Invalid indexing mode");
goto error; };
if (op->base<0) {
tcode[i+1]|=0x04;
dispsize=4; }
else if (op->offset==0 && op->anyoffset==0 && op->base!=REG_EBP)
tcode[i+1]|=0x04; // No displacement
else if ((constsize & 1)!=0 &&
((op->offset>=-128 && op->offset<128) || op->anyoffset!=0)
) {
tcode[i+1]|=0x44; // Disp8
dispsize=1; }
else {
tcode[i+1]|=0x84; // Disp32
dispsize=4; };
tmask[i+1]|=0xC7; // ModRM completed, proceed with SIB
if (op->scale==2) tcode[i+2]|=0x40;
else if (op->scale==4) tcode[i+2]|=0x80;
else if (op->scale==8) tcode[i+2]|=0xC0;
tmask[i+2]|=0xC0;
if (op->index<8) {
if (op->index<0) op->index=0x04;
tcode[i+2]|=(char)(op->index<<3);
tmask[i+2]|=0x38; };
if (op->base<8) {
if (op->base<0) op->base=0x05;
if (op->segment!=SEG_UNDEF && op->segment!=addr32[op->base].defseg)
segment=op->segment;
tcode[i+2]|=(char)op->base;
tmask[i+2]|=0x07; }
else segment=op->segment; };
break;
case IMM: // Immediate data (8 or 16/32)
case IMU: // Immediate unsigned data (8 or 16/32)
case VXD: // VxD service (32-bit only)
if (datasize==0 && pd->arg2==NNN && (pd->bits==SS || pd->bits==WS))
datasize=4;
if (datasize==0) {
strcpy(errtext,"Please specify operand size");
goto error; };
immediate=op->offset; anyimm=op->anyoffset;
if (pd->bits==SS || pd->bits==WS) {
if (datasize>1 && (constsize & 2)!=0 &&
((immediate>=-128 && immediate<128) || op->anyoffset!=0)) {
immsize=1; tcode[i]|=0x02; }
else immsize=datasize;
tmask[i]|=0x02; }
else immsize=datasize;
break;
case IMX: // Immediate sign-extendable byte
case IMS: // Immediate byte (for shifts)
case IM1: // Immediate byte
if (immsize==2) // To accomodate ENTER instruction
immediate=(immediate & 0xFFFF) | (op->offset<<16);
else immediate=op->offset;
anyimm|=op->anyoffset;
immsize++; break;
case IM2: // Immediate word (ENTER/RET)
immediate=op->offset; anyimm=op->anyoffset;
immsize=2; break;
case IMA: // Immediate absolute near data address
if (op->segment!=SEG_UNDEF && op->segment!=SEG_DS)
segment=op->segment;
displacement=op->offset; anydisp=op->anyoffset;
dispsize=4; break;
case JOB: // Immediate byte offset (for jumps)
jmpoffset=op->offset; anyjmp=op->anyoffset;
jmpsize=1; break;
case JOW: // Immediate full offset (for jumps)
jmpoffset=op->offset; anyjmp=op->anyoffset;
jmpsize=4; break;
case JMF: // Immediate absolute far jump/call addr
displacement=op->offset; anydisp=op->anyoffset; dispsize=4;
immediate=op->segment; anyimm=op->anyoffset; immsize=2;
break;
case SGM: // Segment register in ModRM byte
hasrm=1;
if (op->index<6) {
tcode[i+1]|=(char)(op->index<<3); tmask[i+1]|=0x38; };
break;
case SCM: // Segment register in command byte
if (op->index==SEG_FS || op->index==SEG_GS) {
tcode[0]=0x0F; tmask[0]=0xFF;
i=1;
if (strcmp(name,"PUSH")==0)
tcode[i]=(char)((op->index<<3) | 0x80);
else
tcode[i]=(char)((op->index<<3) | 0x81);
tmask[i]=0xFF; }
else if (op->index<6) {
if (op->index==SEG_CS && strcmp(name,"POP")==0) {
strcpy(errtext,"Unable to POP CS");
goto error; };
tcode[i]=(char)((tcode[i] & 0xC7) | (op->index<<3)); }
else {
tcode[i]&=0xC7;
tmask[i]&=0xC7; };
break;
case PRN: // Near return address (pseudooperand)
case PRF: // Far return address (pseudooperand)
case PAC: // Accumulator (AL/AX/EAX, pseudooperand)
case PAH: // AH (in LAHF/SAHF, pseudooperand)
case PFL: // Lower byte of flags (pseudooperand)
case PS0: // Top of FPU stack (pseudooperand)
case PS1: // ST(1) (pseudooperand)
case PCX: // CX/ECX (pseudooperand)
case PDI: // EDI (pseudooperand in MMX extentions)
break; // Simply skip preudooperands
default: // Undefined type of operand
strcpy(errtext,"Internal Assembler error");
goto error;
};
};
// Gather parts of command together in the complete command.
j=0;
if (lock!=0) { // Lock prefix specified
model->code[j]=0xF0;
model->mask[j]=0xFF; j++; };
if (datasize==2 && pd->bits!=FF) { // Data size prefix necessary
model->code[j]=0x66;
model->mask[j]=0xFF; j++; };
if (addrsize==2) { // Address size prefix necessary
model->code[j]=0x67;
model->mask[j]=0xFF; j++; };
if (segment!=SEG_UNDEF) { // Segment prefix necessary
if (segment==SEG_ES) model->code[j]=0x26;
else if (segment==SEG_CS) model->code[j]=0x2E;
else if (segment==SEG_SS) model->code[j]=0x36;
else if (segment==SEG_DS) model->code[j]=0x3E;
else if (segment==SEG_FS) model->code[j]=0x64;
else if (segment==SEG_GS) model->code[j]=0x65;
else { strcpy(errtext,"Internal Assembler error"); goto error; };
model->mask[j]=0xFF; j++; };
if (dispsize>0) {
memcpy(tcode+i+1+hasrm+hassib,&displacement,dispsize);
if (anydisp==0) memset(tmask+i+1+hasrm+hassib,0xFF,dispsize); };
if (immsize>0) {
if (immsize==1) l=0xFFFFFF00L;
else if (immsize==2) l=0xFFFF0000L;
else l=0L;
if ((immediate & l)!=0 && (immediate & l)!=l) {
strcpy(errtext,"Constant does not fit into operand");
goto error; };
memcpy(tcode+i+1+hasrm+hassib+dispsize,&immediate,immsize);
if (anyimm==0) memset(tmask+i+1+hasrm+hassib+dispsize,0xFF,immsize); };
i=i+1+hasrm+hassib+dispsize+immsize;
jmpoffset=jmpoffset-(i+j+jmpsize);
model->jmpsize=jmpsize;
model->jmpoffset=jmpoffset;
model->jmppos=i+j;
if (jmpsize!=0) {
if (ip!=0) {
jmpoffset=jmpoffset-ip;
if (jmpsize==1 && anyjmp==0 && (jmpoffset<-128 || jmpoffset>=128)) {
if (longjump==0 && (jmpmode & 0x03)==0) {
longjump=1;
goto retrylongjump; };
sprintf(errtext,
"Relative jump out of range, use %s LONG form",name);
goto error; };
memcpy(tcode+i,&jmpoffset,jmpsize);
};
if (anyjmp==0) memset(tmask+i,0xFF,jmpsize);
i+=jmpsize; };
memcpy(model->code+j,tcode,i);
memcpy(model->mask+j,tmask,i);
i+=j;
model->length=i;
return i; // Positive value: length of code
error:
model->l
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -