
/***************************************************************************
**
**    $Header:   D:/EPSLDV1/SRC/LOG/ASM.CPP   1.8   20 Jun 1996 09:23:46   ZJRD  $
**
**    $Log:   D:/EPSLDV1/SRC/LOG/ASM.CPP  $
** 
**    Rev 1.8   20 Jun 1996 09:23:46   ZJRD
** EasyPack/SLD Version 1.20a
** 
**    Rev 1.6   10 Jun 1996 10:18:30   ZJRD
** EasyPack/SLD Version 1.20
** 
**    Rev 1.4   29 May 1996 09:27:00   ZJRD
** No change.
** 
**    Rev 1.3   16 May 1996 08:58:50   ZJRD
** No change.
** 
**    Rev 1.2   10 May 1996 09:07:22   ZJRD
** No change.
** 
**    Rev 1.1   02 May 1996 10:21:54   ZJRD
** EasyPack/SLD Version 1.92
** 
**    Rev 1.31   18 Apr 1996 12:52:10   Shirley
** No change.
** 
**    Rev 1.30   12 Apr 1996 10:33:00   Shirley
** EasyPack/SLD Version 1.90
** 
**    Rev 1.28   15 Feb 1996 08:46:06   Shirley
** No change.
** 
**    Rev 1.27   12 Feb 1996 14:01:12   Shirley
** No change.
** 
**    Rev 1.26   06 Feb 1996 15:26:36   Shirley
** No change.
** 
**    Rev 1.25   06 Feb 1996 13:42:00   Shirley
** No change.
** 
**    Rev 1.24   01 Feb 1996 10:10:34   Shirley
** No change.
** 
**    Rev 1.23   26 Jan 1996 09:11:22   Shirley
** No change.
** 
**    Rev 1.22   25 Jan 1996 13:11:42   Shirley
** No change.
** 
**    Rev 1.21   24 Jan 1996 10:31:08   Shirley
** No change.
** 
**    Rev 1.20   23 Jan 1996 11:21:14   Shirley
** EasypPack/SLD Version 0.34c
** 
**    Rev 1.18   15 Jan 1996 16:09:28   Shirley
** EasyPack/SLD Version 0.34a
** 
**    Rev 1.16   30 Nov 1995 09:07:30   Shirley
** No change.
** 
**    Rev 1.15   28 Nov 1995 15:28:34   Shirley
** No change.
** 
**    Rev 1.14   21 Nov 1995 11:17:28   Shirley
** No change.
** 
**    Rev 1.13   13 Nov 1995 09:21:04   Shirley
** No change.
** 
**    Rev 1.12   12 Nov 1995 11:27:40   Shirley
** No change.
** 
**    Rev 1.11   08 Nov 1995 16:27:14   Shirley
** No change.
** 
**    Rev 1.10   08 Nov 1995 12:38:58   Shirley
** No change.
** 
**    Rev 1.9   02 Nov 1995 10:01:52   Shirley
** EasyPack/SLD Version 0.21
** 
**    Rev 1.8   27 Oct 1995 16:44:32   Shirley
** No change.
** 
**    Rev 1.7   27 Oct 1995 13:42:40   Shirley
** No change.
** 
**    Rev 1.6   25 Oct 1995 14:25:20   Shirley
** No change.
** 
**    Rev 1.5   18 Oct 1995 14:46:24   Shirley
** EasyPack/SLD Version 0.1e
** 
**    Rev 1.3   29 Sep 1995 09:47:42   Shirley
** No change.
** 
**    Rev 1.2   20 Sep 1995 10:52:26   Shirley
** No change.
** 
**    Rev 1.1   15 Sep 1995 09:43:32   Shirley
** No change.
** 
**    Rev 1.0   07 Sep 1995 09:53:18   Shirley
** Initial revision.
**
****************************************************************************/

/***************************************************************************
**
** File name : asm.cpp
** Author:John Zhou
** Description:
**    Having functions used in assembly. 
**
**
**    Finished date: 1995.4.21
**
**
**    Copyright (C) 1995 Microtek International, Inc.
**    All Rights Reserved
**
****************************************************************************/
#include "stdafx.h"

#include "dad.h"
#include "dadtbl.h"//define external data that are defined in dadtbl.cpp
#include <string.h>
        
/******************************************************************
the Asm function analyses the input string and convert it to hex by
51 command rule.
INPUT:(1)unsigned char * PAsmInput
         "PAsmInput" point to the string which obtains only one instruction,
         It is devided by ' ' or ',',and ended by 0.
         The max length is defined by MAXASCII.
      (2)unsigned short AsmAddr
         The current address in 51's code memory.From 0000h to ffffh
OUTPUT:(1)unsigned char * PAsmResult
         This point points to the buffer which contains the HEX code
         assembled from input string.
       (2)unsigned int *AsmBytes
         This value has the number of HEX codes that have been assembled
         from input string.
RETURN:int =0 refers to ok.
           <0 refers to wrong.
********************************************************************/

SFRNAME SFRbit={(unsigned char*) "            ",0x80,1,0,0};
SFRNAME SFRbyte={(unsigned char*) "            ",0x0,1,0,0};

extern unsigned char gEPModule; //cpu type ,globle
extern unsigned long CpuModule_H,CpuModule_L;  //only used in DAD ,eg:CM31--8031

int GetASymbol(unsigned char *,unsigned char *);
int GetConstSymbolIndex(unsigned char *);
int StrtoHex(unsigned char *,unsigned short *);
int StrCmp(unsigned char *,unsigned char *);
int GetOpcodeClassSet(unsigned char *,unsigned char *,unsigned short,FLAG);


//this function get a symbol string devided by ' ' or ',' from imput string
//the result is in the output string.
int GetASymbol(unsigned char *Input,unsigned char *Output)
{
  int i,j;

  i=0;  j=0;
  while(Input[i]==' ' || Input[i]==',')i++;
  while(Input[i+j]!=' ' && Input[i+j]!=',' && Input[i+j]!=0)
   {
    //if(Input[i+j]>=(unsigned char)'a' && Input[i+j]<=(unsigned char)'z') Input[i+j]=(unsigned char)(Input[i+j]-'a'+'A');
    Output[j]=Input[i+j];
    j++;
    }
  Output[j]=0;
  while(Input[i+j]==' ' || Input[i+j]==',')j++;
  return i+j;
  }
//return value refers to how many bytes have benn analysed

//this function get the index in table DAsmSpecialSymbolTbl using input string
//input need not to be UPCAS
int GetConstSymbolIndex(unsigned char *InputBuf)
{
 int i,GetOk;
 unsigned char Input[255];
 i=0;    GetOk=0;  
 
 //convert Low characters to UPCASE
 while (*InputBuf!=0)                    
  {
   Input[i]=(*InputBuf>=(unsigned char)'a' && *InputBuf<=(unsigned char)'z') 
   ? (unsigned char)(*InputBuf-'a'+'A')
   : (unsigned char)(*InputBuf);
   i++; InputBuf++;
   if(i>250) return -2;//refer to too long string;
   }
  Input[i]=0;
  i=0; 
 
 //ADDED BY JOHN 95.11.1
 if(StrCmp((unsigned char __far *)"ACC",Input)==0) return 1;
 if(StrCmp((unsigned char __far *)"CY",Input)==0) return 2; 
 if(StrCmp((unsigned char __far *)"@ACC+DPTR",Input)==0) return 4;
 if(StrCmp((unsigned char __far *)"@ACC+PC",Input)==0) return 5;
 
 while (!GetOk && *(DAsmSpecialSymTbl[i])!=0)
    {
      if(StrCmp(DAsmSpecialSymTbl[i],Input)==0)
         GetOk=1;
      i++;
      }

   if(GetOk) return i-1; else return -1;
  }
//return: >=0 refer to getting ok; return value refer to index based on 0
//        <0  refer to failure

//this function convert string to hex and check whether the string is correct
//the input string need not to be UPCAS.
int StrtoHex(unsigned char *InputStr,unsigned short *Output)
{
 int i,j;
 unsigned long kk,k;                
 unsigned char Input[256];
 unsigned char *P;
 
 //copy the inputstr                                
 for(i=0;InputStr[i]!=0;i++) Input[i]=InputStr[i];
 Input[i]=0;
                                 
 for(P=Input;*P=='0' && P[1]=='0';P++);
 for(;*P!=0;P++)
     *P=(*P>='a' && *P<='z')?(unsigned char)(*P-'a'+'A'):*P;
 
 i=strlen((char *)Input);  kk=0;k=1;  *Output=0;
 if(i==0) return -101;
 if(Input[i-1]=='H') i--;
 if(i==0 || i>5) return -101;
 for(j=i;j>0;j--)
  {
   if(!(Input[j-1]>='0' && Input[j-1]<='9') && !(Input[j-1]>='A' && Input[j-1]<='F')) return -101;
   if(Input[j-1]>='A' && Input[j-1]<='F') Input[j-1]=(unsigned char)(Input[j-1]-'A'+'9'+1);
   kk+=k*(Input[j-1]-'0');
   k*=16;
   }

 if(kk>0x0ffff) return -102;
 *Output=(unsigned short)(kk);
 return 0;//ok
}
//return 0 refers to ok
//return -101 refers to the wrong string
//return -102 refers to too large number

//this function return 0 if string x== string y
//it be sensitive to UP OR low characters
int StrCmp(unsigned char *x,unsigned char *y)
{
 int i;
 i=0;
 do{
   if(x[i]!=y[i]) return -1;
   i++;
   }while(x[i-1]!=0);
 return 0;
 }

//this funtion analyses the input string,and convert to the opcode class set in output
//and it also change the symbol to absolute address
//the input string is also converted if necessary
//it does not deal with the '/' and '.'
int GetOpcodeClassSet(unsigned char *Input,unsigned char *Output,unsigned short Addr,FLAG ABIAddrType)
                      //MAX 100            //MAX 26
                      //Input points to real used buffer,not a copy
{  int i;
   union AddrTemp n;  //used for text go hex
               
  Output[0]=0;               
               
//for 0--16 and 20,23 ****************************************************                       
  //for 0-16 constant
  if((i=GetConstSymbolIndex(Input))>=0) 
    {
      Output[0]=(unsigned char)i; Output[1]=0;
      }//ok
  //for 20 byteaddress
  if((i=GetByteSFRAddrIndex(Input,&(SFRbyte),CpuModule_H,CpuModule_L))>=0) //for byteaddress
    {//convert input string to hex value because it can be converted
     unsigned char *tempP;
     n.addrShort=(unsigned short)(SFRbyte.DirAddr);
     Input[0]=n.addrStruct.addrl; Input[1]=n.addrStruct.addrh;
     Input[2]=0;
     tempP=&(Output[strlen((char *)Output)]);
     *tempP=20;tempP++;*tempP=0;
     return SFRbyte.SfrAttr;//0 for being unbitable and 1 for bitable
     }
  //for 23 bitaddress
  if((i=GetBitSFRAddrIndex(Input,&(SFRbit),CpuModule_H,CpuModule_L))>=0) 
    {//convert input string to hex value because it can be converted 
     unsigned char *tempP;
     n.addrShort=(unsigned short)(SFRbit.DirAddr);
     Input[0]=n.addrStruct.addrl; Input[1]=n.addrStruct.addrh;
     Input[2]=0;          
     tempP=&(Output[strlen((char *)Output)]); 
     *tempP=23;tempP++;*tempP=0;
     return 0; //ok
     }      
//*************************************************************************

   if(*Input=='$') //for $ ************************************************
    {             
     unsigned short usTmpShort;
     switch (Input[1])
      {
       case  0  : n.addrShort=Addr;//convert input string to hex value because it can be converted
                  break;
       case '+' : i=StrtoHex((unsigned char *)(&Input[2]),
                             &usTmpShort);
                  if(i<0) return i;
                  n.addrShort=Addr+usTmpShort;
                  break;
       case '-' : i=StrtoHex((unsigned char *)(&Input[2]),
                             &usTmpShort);
                  if(i<0) return i;
                  n.addrShort=Addr-usTmpShort;
                  break; 
       case '*' : i=StrtoHex((unsigned char *)(&Input[2]),
                             &usTmpShort);
                  if(i<0) return i;
                  n.addrShort=Addr*usTmpShort;
                  break;                              
       case '/' : i=StrtoHex((unsigned char *)(&Input[2]),
                             &usTmpShort);
                  if(i<0) return i;
                  n.addrShort=Addr/usTmpShort;
                  break;                       
       case '%' : i=StrtoHex((unsigned char *)(&Input[2]),
                             &usTmpShort);
                  if(i<0) return i;
                  n.addrShort=Addr%usTmpShort;
                  break;                                 
       default  : return -99;
       }           
     Input[0]=n.addrStruct.addrl; Input[1]=n.addrStruct.addrh;
     Input[2]=0;
     Output[0]=17; Output[1]=18; Output[2]=19;
     Output[3]=25; Output[5]=0;
     return 0; //ok
     }

   if(*Input=='#') //for # ***********************************************
    {//convert input string to hex value because it can be converted
     i=(StrtoHex(&Input[1],&n.addrShort));
     //modified by john 96.6 to support asm symbol
     if(i>=0) {
        Input[0]=n.addrStruct.addrl; Input[1]=n.addrStruct.addrh;
        Input[2]=0;
        Output[0]=21; Output[1]=22; Output[2]=0;
        return 0;//ok                           
     } else {                             
            U8 bType; U32 nAddr;
            if (0 == SymToAddr((char *)(&Input[0])  , &bType , &nAddr )) {
                if(ABIAddrType == bType) {
                    n.addrShort = (unsigned short)nAddr;
                    Input[0]=n.addrStruct.addrl; Input[1]=n.addrStruct.addrh;
                    Input[2]=0;
                    Output[0]=17; Output[1]=18; Output[2]=19;
                    Output[3]=25; Output[5]=0;  
                    return 0;
                } else if (bType == 3 || bType == 4){//for i , r
                		   n.addrShort = (unsigned short)nAddr;
                           Input[0]=n.addrStruct.addrl; 
                           Input[1]=0;
                           Input[2]=0;
                           Output[0]=20; Output[1]=0; 
                           return 0;
                       } else  if (bType == 5){                
                       				n.addrShort = (unsigned short)nAddr;
                                    Input[0]=n.addrStruct.addrl; 
                                    Input[1]=0;
                                    Input[2]=0;
                                    Output[0]=23; Output[1]=0; 
                                    return 0;
                               }
            }
                
       }
     return i;  
        
   }

   if(*Input>='0' && *Input<='9') //for number *****************************
    {//convert input string to hex value because it can be converted
     i=(StrtoHex(&Input[0],&n.addrShort));
     if(i<0) return i;
     Input[0]=n.addrStruct.addrl; Input[1]=n.addrStruct.addrh;
     Input[2]=0;
     Output[0]=17; Output[1]=20; Output[2]=19;
     Output[3]=25; Output[4]=23; Output[5]=18;
     Output[6]=0;
     if(Input[1]==0)// if <256
      {
       if(n.addrShort>=BITABLELOW && n.addrShort<=BITABLEHIGH) return BITABLE;
       if(GetByteSFRSymbolIndex(Input[0],&(SFRbyte),CpuModule_H,CpuModule_L)>=0)
        return SFRbyte.SfrAttr;//0 for being unbitable 1 for bitable
       }//if
     return 0;//ok
     }

   //otherwise
   if(Output[0]==0) return -99; else return 0;

 }
//return =-99 refer to no means,the opcode can't be recognized
//return =0 ok
//return =SfrAttr indicates that this opcode can be considered
//        as a IDATA address which is bitable
//return <-100 StrtoHex error

int Asm (unsigned char * PAsmInput,    // line assembly input a stream.hope it ended with 0 and no more than 100
         unsigned short AsmAddr, // the address to be assembly
         unsigned char * PAsmResult,            // pointer to ASM result hex code
         unsigned int *AsmBytes        //  Bytes have been assembly
         #ifdef ABI
         ,FLAG ABIAddrType   //refer to ABI address type
         #endif
         )
{
  union AddrTemp n;  //used for short to string
  unsigned long i,k,ii;
  int j;
  unsigned int k1; //only used in ABI convert
  unsigned long kk;//refer to index in Cmd_51
  unsigned char *opcode;
  unsigned char OpSet[5][27];
  unsigned char Str[5][MAXASCII+2];
                //5 is more than it needs,so does MAXASCII+2
  #ifdef ABI
  unsigned char Copy[5];//reserved to backup result before call ABI
  ADDR AddrforABI;
  unsigned short AddrMax,AddrMin ;
  #endif

  #ifdef ABI
  switch(ABIAddrType)
    {
     case ABI_CODE_ADDR_JOHN  : AddrMax=ABI_CODE_ADDR_JOHN_MAX;AddrMin=ABI_CODE_ADDR_JOHN_MIN;break;
     case ABI_XDATA_ADDR : AddrMax=ABI_XDATA_ADDR_MAX;AddrMin=ABI_XDATA_ADDR_MIN;break;
     //case ABI_IDATA_ADDR : AddrMax=ABI_IDATA_ADDR_MAX;AddrMin=ABI_IDATA_ADDR_MIN;break;
     //case ABI_SFR_ADDR   : AddrMax=ABI_SFR_ADDR_MAX;AddrMin=ABI_SFR_ADDR_MIN;break;
     //case ABI_BIT_ADDR   : AddrMax=ABI_BIT_ADDR_MAX;AddrMin=ABI_BIT_ADDR_MIN;break;
     default           : AddrMax=ABI_CODE_ADDR_JOHN_MAX;AddrMin=ABI_CODE_ADDR_JOHN_MIN;ABIAddrType=ABI_CODE_ADDR_JOHN;break;
     }
   if((WORD)AsmAddr>AddrMax || (WORD)AsmAddr<AddrMin) return -20;//refer to having wrong address comparing to address type
  #endif


  if(gEPModule>63) return -6;//invalid cpu mode
//convert the cpu module to own definition 
  if(gEPModule<32)
   {
    CpuModule_L=1;  CpuModule_H=0;
    CpuModule_L<<=gEPModule;
    }                            
    else
     { 
      CpuModule_L=0;  CpuModule_H=1;
      CpuModule_H<<=(gEPModule-32);
      }

  for(i=0;i<5;i++) OpSet[i][0]=0;
  for(i=0;i<5;i++) Str[i][0]=0;
  i=k=0; j=0;

  do{
     j=GetASymbol(&(PAsmInput[i]),Str[k]);
     k++;i+=j;
     if(i>=MAXASCII) return -7;//too many text
     } while(k<4 && strlen((char *)(Str[k-1]))>0);
     
  //added in 95.7 for call instruction,it will first get a chance in acall,then in lcall  
    if( StrCmp((unsigned char *)(strupr((char *)(Str[0]))),(unsigned char *)"CALL") == 0 )
     {      
      unsigned char strtmp[105];
      strtmp[0]=0;
      strcat((char *)strtmp,"A");   strcat((char *)strtmp,(char *)PAsmInput);
      int returntmp;
      returntmp=Asm (strtmp,AsmAddr,PAsmResult,AsmBytes
              #ifdef ABI
              ,ABIAddrType   //refer to ABI address type
              #endif
              );
      if ( returntmp==0) return 0;        
      strtmp[0]='L';
      returntmp=Asm (strtmp,AsmAddr,PAsmResult,AsmBytes
                  #ifdef ABI
                  ,ABIAddrType   //refer to ABI address type
                  #endif
                  );
      return returntmp;            
      }
  ///////////////////////////////////////////////////////////////////////////   
  
  if(Str[0][0]==0) return -14;//have no string
  if(k==4 && strlen((char *)(&(PAsmInput[i])))!=0)return -18;//too many opcodes
  Str[k][0]=0; //point out the end

  //convert intruction (jmp,mov,add ...) to UPCAS                   
  for(unsigned char *P=&(Str[0][0]);*P!=0;P++)
     *P=(*P>='a' && *P<='z')?(unsigned char)(*P-'a'+'A'):*P;                   
                     
  //analyses the opcode
  i=1;
  while(Str[i][0]!=0)
   {
    unsigned char *dot;//point to dotbak
    unsigned char dotbak[MAXASCII+2];//backup for the string after '.'
    int i_dot;

    k=0; 
    if(Str[i][0]=='/') k++;
    dot=(unsigned char *)strchr((char *)(&Str[i][k]),'.');
    
    if(dot!=NULL) 
     { 
       *dot=0;
       i_dot=0;
       dot++;
       do
        {
          dotbak[i_dot]=*dot; dot++; i_dot++;
          } while(*dot!=0 && i_dot!=MAXASCII) ;
       dotbak[i_dot]=0;   
       dot=&(dotbak[0]);   
       }
       
    j=GetOpcodeClassSet(&(Str[i][k]),OpSet[i],AsmAddr,ABIAddrType);
    if(j==-99) return (0-(int)i);
    if(j<0) return j;

    if(dot!=NULL)
    {
     if(j==1/*BITABLE*/)
     {

      if(StrtoHex(dot,&(n.addrShort))==0)
       {
        if(n.addrShort<BITLENGTH)
         {
          if(Str[i][k]>=BITABLELOW && Str[i][k]<=BITABLEHIGH)
           {
            Str[i][k]=(unsigned char)((Str[i][k]-BITABLELOW)*BITLENGTH+n.addrStruct.addrl);
            Str[i][k+1]=0;
            OpSet[i][0]=23; OpSet[i][1]=0;
            }
           else //SFR address
            {
             Str[i][k]=(unsigned char)(Str[i][k]+n.addrShort);
             Str[i][k+1]=0;
             if(n.addrShort>=256) return -8;//invalid converting address from byte to bit
             OpSet[i][0]=23; OpSet[i][1]=0;
             }//else
          }//if
          else return -9;//offset in bit converting too large
        }//if
        else return -10;//unkown offset
      }//if
      else return -11;//'.' used in byte which can't be addressed in bit
      }//if

    if(k!=0)  //FOR '/' USING
     {
      if(strchr((char *)(OpSet[i]),23)!=NULL && Str[i][k+1]==0)
       {
        k--;
        Str[i][k]=Str[i][k+1];Str[i][k+1]=0;
        OpSet[i][0]=24; OpSet[i][1]=0;
        }
        else return -12;//wrong use of '/'
      }//if

    i++;
    }//while
   OpSet[i][0]=0;

//now locates the instruction in Cmd_51,if more than one maybe campatible,the first is selected(eg:acall,ajmp)
  unsigned long kkk,kk_num;
  j=0;kkk=kk=0;
  kk_num=4; //max instruction numbers+1
  for(ii=0;ii<260;ii++)
   if(StrCmp(CMd_51[ii].Intruction,Str[0])==0)
    if((CMd_51[ii].opcode1!=0 && strchr((char *)(OpSet[1]),CMd_51[ii].opcode1)!=NULL) || (CMd_51[ii].opcode1==0 && OpSet[1][0]==0))
     if((CMd_51[ii].opcode2!=0 && strchr((char *)(OpSet[2]),CMd_51[ii].opcode2)!=NULL) || (CMd_51[ii].opcode2==0 && OpSet[2][0]==0))
      if((CMd_51[ii].opcode3!=0 && strchr((char *)(OpSet[3]),CMd_51[ii].opcode3)!=NULL) || (CMd_51[ii].opcode3==0 && OpSet[3][0]==0))
       { 
        j++; kkk=ii; 
        if(CMd_51[kkk].ByteNum<kk_num)
         { kk=kkk;  
           kk_num=CMd_51[kk].ByteNum;  }
        }   

  if(j<=0) return -13;//no corresponding in Cmd_51

// now produce the hex code
   opcode=&(CMd_51[kk].opcode1);
   i=0;
   
   if(kk<=0xff)//fill the result if the instruction is the real 51's instruction
   {
    PAsmResult[i]=(unsigned char) kk ; //kk point to the index in CMd_51
    i++;
    }

   while((&(CMd_51[kk].opcode3)-opcode)>=0)
   {
   j=3-(&(CMd_51[kk].opcode3)-opcode);//the index in Str
   switch(*opcode)
    {
          //for NONE
     case 0: break;
          //for CONSTANT SYMBOL
     case 1:
     case 2:
     case 3:
     case 4:
     case 5:
     case 6:
     case 7:
     case 8:
     case 9:
     case 10:
     case 11:
     case 12:
     case 13:
     case 14:
     case 15:
     case 16: break;
             //codeAddrH  no use
             //suppose codeAddrH always followed by codeAddrL
     case 17: PAsmResult[i]=Str[j][1];PAsmResult[i+1]=Str[j][0];
              i++;i++;
              break;
             //for codeAddrL
     case 18: break;
             //for codeAddrPg(orient code address),must change absolute addr to relative addr
     case 19: n.addrStruct.addrl=Str[j][0];n.addrStruct.addrh=Str[j][1];
              {unsigned short temp;
                if(AsmAddr+CMd_51[kk].ByteNum<=n.addrShort)
                 {
                 temp=n.addrShort-(CMd_51[kk].ByteNum+AsmAddr);
                 if(temp<=127)PAsmResult[i]=(unsigned char)temp;
                  else
                   {
                    if(0xffff-temp+1<=0x80)
                     (PAsmResult[i])=(unsigned char)(-(signed short)(0xffff-temp+1));
                     else return -15;
                     }
                 }
                 else
                  {
                   temp=(CMd_51[kk].ByteNum+AsmAddr)-n.addrShort;
                   if(temp<=128)(PAsmResult[i])=(unsigned char)(-(signed short)(temp));
                    else
                     {if(0xffff-temp+1<=127)
                       PAsmResult[i]=(unsigned char)(0xffff-temp+1);
                       else return -15;}
                   }//else
                }
              i++;
              break;
             //for dataAddr (0-oxff data address)
     case 20: //for instruction:"MOV data,data " change the code order
              if((j<3) && *(opcode+1)==20/*the same as *opcode*/)
               {
                 unsigned char  m;
                 m=Str[j][0];  Str[j][0]=Str[j+1][0]; Str[j+1][0]=m;
                 }                       
              if(Str[j][1]!=0) return -99;
              PAsmResult[i]=Str[j][0]; i++;
              break;
             //for dataByte
     case 21: if(Str[j][1]!=0) return -99;
              PAsmResult[i]=Str[j][0]; i++;
              break;
             //for dataWord
     case 22: PAsmResult[i]=Str[j][1];PAsmResult[i+1]=Str[j][0];
              i++;i++;
              break;
             //for NbitAddr
     case 24:
             //for bitAddr
     case 23: if(Str[j][1]!=0) return -99;
              PAsmResult[i]=Str[j][0]; i++;
              break;
             //for dataAddr11
             //becasue more one instruction like it in table have the same opcode,it is a little different.
     case 25: n.addrStruct.addrl=Str[j][0];n.addrStruct.addrh=Str[j][1];
              n.addrShort<<=5;n.addrShort>>=5;
              n.addrStruct.addrh<<=5;
              PAsmResult[0]=(unsigned char)(n.addrStruct.addrh+((kk<<3)>>3));
              PAsmResult[i]=n.addrStruct.addrl;i++;

              n.addrStruct.addrl=Str[j][0];n.addrStruct.addrh=Str[j][1];
              n.addrShort>>=11;
              if(n.addrShort!=((AsmAddr+CMd_51[kk].ByteNum)>>11)) return -17;//wrong addr11;
              break;
     }//switch
    opcode++;
    }//while

  if(i!=CMd_51[kk].ByteNum) return -16;//the number of return codes is wrong,the Cmd_51 table may be wrong
  *AsmBytes=(unsigned int)i;

  #ifdef ABI
  for(k1=0;k1<*AsmBytes;k1++) Copy[k1]=PAsmResult[k1];
  AddrforABI.addrType=ABIAddrType;
  AddrforABI.addr=(WORD)AsmAddr;
  { ADDR addrtemp;
    addrtemp.addrType=ABIAddrType;
    addrtemp.addr=AddrforABI.addr+*AsmBytes-1;
    if(AddrforABI.addr<=addrtemp.addr)
     {if(AbiSetMemN(AddrforABI,(char *)Copy,(UINT)(*AsmBytes))!=0) return -19;}//refer to failure in calling ABI
    else
    {
     if(AbiSetMemN(AddrforABI,(char *)Copy,(UINT)((0xffff-AddrforABI.addr)+1))!=0) return -19;//refer to failure in calling ABI
     addrtemp.addr=AddrMin;
     if(AbiSetMemN(addrtemp,(char *)(&(Copy[(0xffff-AddrforABI.addr)+1])),(UINT)(*AsmBytes-(0xffff-AddrforABI.addr)-1))!=0) return -19;//refer to failure in calling ABI
     }
    }
  #endif

  return 0;//ok
//return 0 ok
//return -1 to -3 refer to opcode1 to opcode2 error,the opcodes haven't any meaning
//return -6 refer to invalid cpu mode
//return -7 refer to too many text
//return -8 invalid converting address from byte to bit
//return -9 offset in bit converting too large
//return -10 unkown offset
//return -11 '.' used in byte which can't be addressed in bit
//return -12 refer to wrong use of '/'
//return -13 no corresponding in Cmd_51
//return -14 have no string
//return -15 rel address not in -128--127
//return -16 the number of return codes is wrong,the Cmd_51 table may be wrong
//return -17 wrong addr11;
//return -18 too many opcodes
//return -19 refer to failure in calling ABI
//return -20 refer to having wrong address comparing to address type
//return -99 refer to opcode is too large
//return <-100 refer to StrtoHex error
  }
/*******************  THE END OF FILE **************************************/
