⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 assembl.c

📁 一款压缩壳PE123的DELPHI源码 学习写壳的很好的参考
💻 C
📖 第 1 页 / 共 5 页
字号:
            scan=SCAN_ERR; return; };
          if (scan!=SCAN_REG32) {
            asmerror="Syntax error"; scan=SCAN_ERR; return; };
          if (offset==6 || offset==7 || offset>9) {
            asmerror="Invalid scale"; scan=SCAN_ERR; return; };
          r[idata]+=offset;
          Scanasm(0); }
        else {
          if (sign=='-') op->offset-=offset;
          else op->offset+=offset;
        }; }
      else if (scan==SCAN_OFS) {
        Scanasm(0);
        if (scan==SCAN_SYMB && idata=='*') {
          asmerror="Undefined scale is not allowed"; scan=SCAN_ERR; return; }
        else {
          op->anyoffset=1;
        }; }
      else break;                      // None of expected address elements
      if (scan==SCAN_SYMB && idata==']') break;
      sign='?';
    };
    if (scan==SCAN_ERR) return;
    if (scan!=SCAN_SYMB || idata!=']') {
      asmerror="Syntax error";
      scan=SCAN_ERR; return; };
    // Process XLAT address separately.
    if (xlataddr!=0) {                 // XLAT address in form [EBX+AX]
      for (i=0; i<=8; i++) {           // Check which registers used
        if (i==REG_EBX) continue;
        if (r[i]!=0) break; };
      if (i<=8 || r[REG_EBX]!=1 || op->offset!=0 || op->anyoffset!=0) {
        asmerror="Invalid address"; scan=SCAN_ERR; return; };
      op->type=MXL; }
    // Determine scale, index and base.
    else {
      j=0;                             // Number of used registers
      for (i=0; i<=8; i++) {
        if (r[i]==0)
          continue;                    // Unused register
        if (r[i]==3 || r[i]==5 || r[i]==9) {
          if (op->index>=0 || op->base>=0) {
            if (j==0) asmerror="Invalid scale";
            else asmerror="Too many registers";
            scan=SCAN_ERR; return; };
          op->index=op->base=i;
          op->scale=r[i]-1; }
        else if (r[i]==2 || r[i]==4 || r[i]==8) {
          if (op->index>=0) {
            if (j<=1) asmerror="Only one register may be scaled";
            else asmerror="Too many registers";
            scan=SCAN_ERR; return; };
          op->index=i; op->scale=r[i]; }
        else if (r[i]==1) {
          if (op->base<0)
            op->base=i;
          else if (op->index<0) {
            op->index=i; op->scale=1; }
          else {
            asmerror="Too many registers";
            scan=SCAN_ERR; return;
          }; }
        else {
          asmerror="Invalid scale"; scan=SCAN_ERR; return; };
        j++;
      };
      op->type=MRG;
    }; }
  else {
    asmerror="Unrecognized operand"; scan=SCAN_ERR; return; };
  // In general, address modifier is allowed only with address expression which
  // is a constant, a far address or a memory expression. More precise check
  // will be done later in Assemble().
  if (op->jmpmode!=0 && op->type!=IMM && op->type!=JMF && op->type!=MRG) {
    asmerror="Jump address modifier is not allowed";
    scan=SCAN_ERR; return; };
  Scanasm(0);                          // Fetch next token from input line
};

// Function assembles text into 32-bit 80x86 machine code. It supports imprecise
// operands (for example, R32 stays for any general-purpose 32-bit register).
// This allows to search for incomplete commands. Command is precise when all
// significant bytes in model.mask are 0xFF. Some commands have more than one
// decoding. By calling Assemble() with attempt=0,1... and constsize=0,1,2,3 one
// gets also alternative variants (bit 0x1 of constsize is responsible for size
// of address constant and bit 0x2 - for immediate data). However, only one
// address form is generated ([EAX*2], but not [EAX+EAX]; [EBX+EAX] but not
// [EAX+EBX]; [EAX] will not use SIB byte; no DS: prefix and so on). Returns
// number of bytes in assembled code or non-positive number in case of detected
// error. This number is the negation of the offset in the input text where the
// error encountered. Unfortunately, BC 4.52 is unable to compile the switch
// (arg) in this code when any common subexpression optimization is on. The
// next #pragma statement disables all optimizations.

//#pragma option -Od                     // No optimizations, or BC 4.52 crashes

int Assemble(char *cmd,ulong ip,t_asmmodel *model,int attempt,
  int constsize,char *errtext) {
  int i,j,k,namelen,nameok,arg,match,datasize,addrsize,bytesize,minop,maxop;
  int rep,lock,segment,jmpsize,jmpmode,longjump;
  int hasrm,hassib,dispsize,immsize;
  int anydisp,anyimm,anyjmp;
  long l,displacement,immediate,jmpoffset;
  char name[32],*nameend;
  char tcode[MAXCMDSIZE],tmask[MAXCMDSIZE];
  t_asmoperand aop[3],*op;             // Up to 3 operands allowed
  const t_cmddata *pd;
  if (model!=NULL) model->length=0;
  if (cmd==NULL || model==NULL || errtext==NULL) {
    if (errtext!=NULL) strcpy(errtext,"Internal error");
    return 0; };                       // Error in parameters
  asmcmd=cmd;
  rep=lock=0; errtext[0]='\0';
  Scanasm(SA_NAME);
  if (scan==SCAN_EOL)                  // End of line, nothing to assemble
    return 0;
  while (1) {                          // Fetch all REPxx and LOCK prefixes
    if (scan==SCAN_REP || scan==SCAN_REPE || scan==SCAN_REPNE) {
      if (rep!=0) {
        strcpy(errtext,"Duplicated REP prefix"); goto error; };
      rep=scan; }
    else if (scan==SCAN_LOCK) {
      if (lock!=0) {
        strcpy(errtext,"Duplicated LOCK prefix"); goto error; };
      lock=scan; }
    else break;                        // No more prefixes
    Scanasm(SA_NAME); };
  if (scan!=SCAN_NAME || idata>16) {
    strcpy(errtext,"Command mnemonic expected"); goto error; };
  nameend=asmcmd;
  strupr(sdata);
  // Prepare full mnemonic (including repeat prefix, if any).
  if (rep==SCAN_REP) sprintf(name,"REP %s",sdata);
  else if (rep==SCAN_REPE) sprintf(name,"REPE %s",sdata);
  else if (rep==SCAN_REPNE) sprintf(name,"REPNE %s",sdata);
  else strcpy(name,sdata);
  Scanasm(0);
  // Parse command operands (up to 3). Note: jump address is always the first
  // (and only) operand in actual command set.
  for (i=0; i<3; i++) {
    aop[i].type=NNN;                   // No operand
    aop[i].size=0;                     // Undefined size
    aop[i].index=-1;                   // No index
    aop[i].scale=0;                    // No scale
    aop[i].base=-1;                    // No base
    aop[i].offset=0;                   // No offset
    aop[i].anyoffset=0;                // No offset
    aop[i].segment=SEG_UNDEF;          // No segment
    aop[i].jmpmode=0; };               // No jump size modifier
  Parseasmoperand(aop+0);
  jmpmode=aop[0].jmpmode;
  if (jmpmode!=0) jmpmode|=0x80;
  if (scan==SCAN_SYMB && idata==',') {
    Scanasm(0);
    Parseasmoperand(aop+1);
    if (scan==SCAN_SYMB && idata==',') {
      Scanasm(0);
      Parseasmoperand(aop+2);
    };
  };
  if (scan==SCAN_ERR) {
    strcpy(errtext,asmerror); goto error; };
  if (scan!=SCAN_EOL) {
    strcpy(errtext,"Extra input after operand"); goto error; };
  // If jump size is not specified, function tries to use short jump. If
  // attempt fails, it retries with long form.
  longjump=0;                          // Try short jump on the first pass
retrylongjump:
  nameok=0;
  // Some commands allow different number of operands. Variables minop and
  // maxop accumulate their minimal and maximal counts. The numbers are not
  // used in assembly process but allow for better error diagnostics.
  minop=3; maxop=0;
  // Main assembly loop: try to find the command which matches all operands,
  // but do not process operands yet.
  namelen=strlen(name);
  for (pd=cmddata; pd->mask!=0; pd++) {
    if (pd->name[0]=='&') {            // Mnemonic depends on operand size
      j=1;
      datasize=2;
      addrsize=4;
      while (1) {                      // Try all mnemonics (separated by ':')
        for (i=0; pd->name[j]!='\0' && pd->name[j]!=':'; j++) {
          if (pd->name[j]=='*') {
            if (name[i]=='W') { datasize=2; i++; }
            else if (name[i]=='D') { datasize=4; i++; }
            else if (sizesens==0) datasize=2;
            else datasize=4; }
          else if (pd->name[j]==name[i]) i++;
          else break;
        };
        if (name[i]=='\0' && (pd->name[j]=='\0' || pd->name[j]==':'))
          break;                       // Bingo!
        while (pd->name[j]!='\0' && pd->name[j]!=':')
          j++;
        if (pd->name[j]==':') {
          j++; datasize=4; }           // Retry with 32-bit mnenonic
        else {
          i=0; break;                  // Comparison failed
        };
      };
      if (i==0) continue; }
    else if (pd->name[0]=='$') {       // Mnemonic depends on address size
      j=1;
      datasize=0;
      addrsize=2;
      while (1) {                      // Try all mnemonics (separated by ':')
        for (i=0; pd->name[j]!='\0' && pd->name[j]!=':'; j++) {
          if (pd->name[j]=='*') {
            if (name[i]=='W') { addrsize=2; i++; }
            else if (name[i]=='D') { addrsize=4; i++; }
            else if (sizesens==0) addrsize=2;
            else addrsize=4; }
          else if (pd->name[j]==name[i]) i++;
          else break;
        };
        if (name[i]=='\0' && (pd->name[j]=='\0' || pd->name[j]==':'))
          break;                       // Bingo!
        while (pd->name[j]!='\0' && pd->name[j]!=':')
          j++;
        if (pd->name[j]==':') {
          j++; addrsize=4; }           // Retry with 32-bit mnenonic
        else {
          i=0; break;                  // Comparison failed
        };
      };
      if (i==0) continue; }
    else {                             // Compare with all synonimes
      j=k=0;
      datasize=0;                      // Default settings
      addrsize=4;
      while (1) {
        while (pd->name[j]!=',' && pd->name[j]!='\0') j++;
        if (j-k==namelen && strnicmp(name,pd->name+k,namelen)==0) break;
        k=j+1; if (pd->name[j]=='\0') break;
        j=k; };
      if (k>j) continue;
    };
    // For error diagnostics it is important to know whether mnemonic exists.
    nameok++;
    if (pd->arg1==NNN || pd->arg1>=PSEUDOOP)
       minop=0;
    else if (pd->arg2==NNN || pd->arg2>=PSEUDOOP) {
       if (minop>1) minop=1;
       if (maxop<1) maxop=1; }
    else if (pd->arg3==NNN || pd->arg3>=PSEUDOOP) {
       if (minop>2) minop=2;
       if (maxop<2) maxop=2; }
    else
      maxop=3;
    // Determine default and allowed operand size(s).
    if (pd->bits==FF) datasize=2;      // Forced 16-bit size
    if (pd->bits==WW || pd->bits==WS || pd->bits==W3 || pd->bits==WP)
      bytesize=1;                      // 1-byte size allowed
    else
      bytesize=0;                      // Word/dword size only
    // Check whether command operands match specified. If so, variable match
    // remains zero, otherwise it contains kind of mismatch. This allows for
    // better error diagnostics.
    match=0;
    for (j=0; j<3; j++) {              // Up to 3 operands
      op=aop+j;
      if (j==0) arg=pd->arg1;
      else if (j==1) arg=pd->arg2;
      else arg=pd->arg3;
      if (arg==NNN || arg>=PSEUDOOP) {
        if (op->type!=NNN)             // No more arguments
          match|=MA_NOP;
        break; };
      if (op->type==NNN) {
        match|=MA_NOP; break; };       // No corresponding operand
      switch (arg) {
        case REG:                      // Integer register in Reg field
        case RCM:                      // Integer register in command byte
        case RAC:                      // Accumulator (AL/AX/EAX, implicit)
          if (op->type!=REG) match|=MA_TYP;
          if (arg==RAC && op->index!=REG_EAX && op->index!=8) match|=MA_TYP;
          if (bytesize==0 && op->size==1) match|=MA_SIZ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -