Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1845 → Rev 1846

/programs/develop/c--/trunk/generate.h--
0,0 → 1,1718
dword ACTUALMNEMDESC; // “ª § â¥«ì ­  ®¯¨á ­¨¥ ⥪ã饩 ¬­¥¬®­¨ª¨
byte ACTUALMNEMONIC; // Š®¤ ⥪ã饩 ¬­¥¬®­¨ª¨
byte OPERANDSIZE; //  §¬¥à ®¯¥à ­¤ (B,W,D,BW,WB,DW)
byte OPDESC[3]; // ’¨¯ë ®¯¥à ­¤®¢ (R,E,D,CC,SR,TR,DR,CR)
byte OPDATA[3]; // ˆ­ä®à¬ æ¨ï ¯® ®¯¥à ­¤ã (RG,CO,EA)
dword OPCONST[3]; // ‡­ ç¥­¨¥ ª®­áâ ­âë ¢ ®¯¥à ­¤¥
byte OPCONSTFLAG[3]; //  «¨ç¨¥ ª®­áâ ­âë ¢ ®¯¥à ­¤¥
byte OPCONSTSIZE[3]; //  §¬¥à­®áâì ª®­áâ ­âë ¢ ®¯¥à ­¤¥
byte OPPOST[3];
dword OPPOSTREF[3];
byte PFLAG; // ‡­ ç¥­¨¥ P-ä« £  (­®¬¥à ª« áá ).
byte RANDFLAG; // TRUE: RAND: âॡã¥âáï ¯à¥ä¨ªá 0x66
byte ADDRFLAG; // TRUE: ADDR: âॡã¥âáï ¯à¥ä¨ªá 0x67
byte WBIT; // ¨â WORD ¢ OPCODE
byte DBIT; // ¨â DIRECTION ¢ OPCODE
byte OPLENGTH; // Š®«¨ç¥á⢮ ®¯¥à ­¤®¢ ¢ ⥪ã饩 ¨­áâàãªæ¨¨
byte EA_M; //  ©â XRM
byte EA_X;
byte EA_R; // R NIBBLE IN XRM BYTE.
byte EA_S; //SEGMENT REGISTER
byte EA_R2; //BASE REGISTER
byte EA_I; //INDEX REGISTER
byte EADESC[2]; //CONTAINS INFORMATION ABOUT AN PARSED EFFECTIVE ADRESS.
byte EALENGTH; // Š®«¨ç¥á⢮ ॣ¨áâ஢ ¢ EA
byte EA_SIBFLAG; // ”« £ ­ «¨ç¨ï Sib ¢ 32-¡¨â­®¬ EA
byte EA_SCALING; // ˆ­¤¥ªá ¢ Sib
dword EA_SCALE; // ‡­ ç¥­¨¥ ¤«ï Scale ¢ Sib
dword EADescInd; // ˆ­¤¥ªá ¢ EADESC
byte SEGREGISTER; // SEGMENT OVERRIDE PREFIX NEEDED OR 0.
byte SYSRNUM; // CONTROL/DEBUG/TASKREG INDEX
byte SYSRTYPE; // SYSTEM REGISTER TYPE (CR,CR4,DR,TR)
byte SYSRCODE; // ENCODED REGISTER TYPE
byte OVERRIDE; //SEGMENT OVERRIDE PREFIX NEEDED OR 0.
dword opDescInd;
dword prevTok;
// ----- €áᥬ¡«¨à®¢ ­¨¥ áâப¨
 
Asm(dword str)
byte holdcha;
byte source[256],s[STRLEN],s2[STRLEN];
{
lstrcpyA(#source,str);
IF(list){
fprint(mapfile,"\t//\t");
fprint(mapfile,str);
fprint(mapfile,"\n");
}
holdcha=cha2; //§ ¯®¬­¨âì ¯®§¨æ¨î à §¡®à 
$PUSH linenum2,inptr2,number,tok2,tok,input,inptr,currmod,linenumber,
endoffile,displaytokerrors,type;
lstrcpyA(#s,#string);
lstrcpyA(#s2,#string2);
input=#source; //à §¡¨à ¥¬ ­®¢ãî áâபã
inptr = input;
inptr2=input;
endoffile=0; //   ­ ç «¥ ä ©« 
NextChar();
cha2 = cha;
inptr2=inptr;
linenum2 = 1;
for(;;){
NextTok();
IF(tok==tk_mnemonics)DoMnemonics();
ELSE IF(tok==tk_eof)BREAK;
ELSE IF(tok==tk_locallabel)DoLocalPost();
ELSE IF(tok!=tk_semicolon)preerror("ASM: Bad input format\n");
}
lstrcpyA(#string,#s); //¢®áâ ­®¢¨âì
lstrcpyA(#string2,#s2);
$POP type,displaytokerrors,endoffile,linenumber,currmod,inptr,input,
tok,tok2,number,inptr2,linenum2;
cha2=holdcha;
}
 
DoLocalPost()
dword i;
{
tok = tk_number;
number = outptr-output+OptImageBase+OptBaseOfCode;
ESI=localptr;
DSDWORD[ESI+localtok] = tok;
DSDWORD[ESI+localnumber] = number;
i=0;
WHILE(i<posts){
ECX=i<<2+postnum;
EAX=DSDWORD[ECX];
IF(EAX==localptr){
DSDWORD[ECX]=number;
EBX=i<<2+posttype;
DSDWORD[EBX]=POST_LOC;
}
i++;
}
NextTok();
NextTok();
}
 
// ---- “áâ ­®¢ª  áá뫪¨ ­  ¯®ª  ­¥®¡ê¥­­ë© ¨¤¥­â¨ä¨ª â®à
SetPost(dword ref,ptype)
{
IF(posts >= MAXPOSTS)maxwordpostserror();
EBX=posts<<2+postloc;
DSDWORD[EBX] = outptr;
EBX=posts<<2+postnum;
DSDWORD[EBX] = ref;
EBX=posts<<2+posttype;
DSDWORD[EBX] = ptype;
posts++;
}
 
// ---- à®¯ã᪠¤® á«¥¤ãî饩 § ¯¨á¨ ¢ è ¡«®­¥ ¨­áâàãªæ¨¨
SCDEND()
{
$LODSB
IF(AL!=0){
$CMP AL,_END
$JNE SCDEND
illegaloperand();
$POP EAX; // ‚ë室 ¨§ MapOperands
}
}
 
GETSCALING()
{
NextTok(); // ®«ã稬 §­ ç¥­¨¥ ¬ áèâ ¡­®£® ª®íää¨æ¨¥­â 
IF(tok==tk_number){
DoScale:
EA_SCALE=number; // Scale
EA_SIBFLAG=1; // Žâ¬¥â¨¬ ­ «¨ç¨¥ Sib ¢ 32-¡¨â­®¬ EA
}
ELSE preerror("ASM: Illegal scaling value\n");
}
 
// ---- ®¨áª ¢ è ¡«®­¥ ¯®¤å®¤ï饩 ª ®¯¥à ­¤ã § ¯¨á¨ (¤«ï ®¤­®®¯¥à ­¤­®© ¨­áâàãªæ¨¨)
GETOL1()
{
if(DSBYTE[ESI]!=0){ // ˆ­áâàãªæ¨ï JMP - ­¥ ¯à®¢¥à塞 ᮢ¯ ¤¥­¨¥ à §¬¥à®¢
G4:
$LODSB
AH=AL&NOLBITS; // ˆáª«î稬 ç¨á«® ®¯¥à ­¤®¢
if(NOTZEROFLAG){// â® ¢á¥-â ª¨ JMP...
DL=AL&OPBITS; // Œ áª  ¤«ï ⨯  ®¯¥à ­¤ 
IF(DL!=SOO){ // ‚ ¯®«¥ à §¬¥à  ®¯¥à ­¤  ᮤ¥à¦¨âáï ¨­ä®à¬ æ¨ï ® ⨯¥ ®¯¥à ­¤ ?
AL&=OLBITS; // ‚뤥«¨¬ ª®«¨ç¥á⢮ ®¯¥à ­¤®¢
IF(AL!=OL1){ // ˜ ¡«®­ ¤«ï ¨­áâàãªæ¨¨ á ®¤­¨¬ ®¯¥à ­¤®¬?
G3:
do{
$LODSB // à®á¬®âਬ á«¥¤ãîéãî § ¯¨áì è ¡«®­ 
IF(AL==0)GOTO G4; // Š®­¥æ § ¯¨á¨?
}while(AL!=_END); // â® ª®­¥æ è ¡«®­ ?
illegaloperand(); // ¥â ¯®¤å®¤ï饩 § ¯¨á¨ ¤«ï â ª®© ¬­¥¬®­¨ª¨
$POP EAX;
$RET // ‚ë室 ¨§ MapOperands
}
// Ž¡à ¡®âª  § ¯¨á¨ è ¡«®­ 
G2:
AL=AH&TRANSBITS; // ‚뤥«¨¬ à §¬¥à ®¯¥à ­¤ 
$CMP AL,_D
$JBE G5 // Ž¯¥à ­¤ ¬.¡. à §¬¥à : byte, word, dword
$CMP AL,_OW
$JNE J0
OPERANDSIZE=_W;
GOTO G40;
J0:
$CMP AL,_OD;
$JNE J1
OPERANDSIZE=_D;
GOTO G40;
J1:
$CMP AL,NB
$JB G90 // Ž¯¥à ­¤ ¬.¡. à §¬¥à  WB,DW OR BW.
AL-=NB; // ¥à¥áç¨â ¥¬ ¤«ï 䨪á¨à®¢ ­­ëå à §¬¥à®¢: NB->B,OW->W, AF->D
G90:
$CMP AL,OPERANDSIZE //  §¬¥à ®¯¥à ­¤  ¨ à §¬¥à ¨§ è ¡«®­  ᮢ¯ «¨?
$JNE G3 // ¥â - ᬮâਬ á«¥¤ãîéãî § ¯¨áì ¢ è ¡«®­¥
GOTO G40; //  §¬¥àë ᮢ¯ «¨ - ¯à®¤®«¦¨¬
G5:
$CMP AL,OPERANDSIZE //  §¬¥à ®¯¥à ­¤  ¨ à §¬¥à ¨§ è ¡«®­  ᮢ¯ «¨?
$JA G3 // ¥â - ᬮâਬ á«¥¤ãîéãî § ¯¨áì ¢ è ¡«®­¥
EBX=0; // WBIT/RANDFLAG=0
DL=AL;
AL=OPERANDSIZE;
IF(DL==_B)&&(AL!=_B)BL++;
// $CMP DL,_B // ‚ è ¡«®­¥ byte?
// $JNE G20
// $CMP AL,_B // Ž¯¥à ­¤ byte?
// $JE G20
// BL++; // W-¡¨â=TRUE
//G20:
$CMP AL,_W // ‚ è ¡«®­¥ word?
$JNE G30
$JA G30
BH++; // Ž¯¥à ­¤ ®¡ï§ â¥«ì­® ¤.¡. word - âॡã¥âáï ¯à¥ä¨ªá RAND
G30:
WBIT=BL;
RANDFLAG=BH; // ‡ ¯®¬­¨¬ ¨­ä®à¬ æ¨î ® ¯à¥ä¨ªá¥ ¨ W-¡¨â¥
G40:
AH&=NTRANSBITS; // Žáâ ¢¨¬ SOO ¡¨âë
}
}
}
AL=AH; // ‚®§¢à â¨¬ SOO ¯®«¥
}
 
// ----  §¡®àª  è ¡«®­  ¤«ï ¤¢ã宯¥à ­¤­®© ¨­áâàãªæ¨¨
GETOL2()
{
G7:
$LODSB // ®«ã稬 ¡ ©â ¨§ è ¡«®­ 
AH=AL;
AL&=OLBITS; // ‚뤥«¨¬ ç¨á«® ®¯¥à ­¤®¢
$CMP AL,OL2 // —¨á«® ®¯¥à ­¤®¢ = 2?
$JE G8 // „  - ­ ç­¥¬ ¯à®¢¥àªã
G9:
$LODSB // ®¨áª á«¥¤ãî饩 § ¯¨á¨ ¢ è ¡«®­¥
$OR AL,AL // Š®­¥æ § ¯¨á¨?
$JZ G7 // „  - ¯à®¢¥à¨¬ ­®¢ãî § ¯¨áì
$CMP AL,_END // Š®­¥æ è ¡«®­ ?
$JNE G9 // ‘¬®âਠ¤ «ìè¥ ¨­ ç¥ - ®è¨¡ª 
toomuchoperands();
$POP EAX;
$RET // ‚ë室 ¨§ MapOperands
G8:
AH&=NOLBITS; // ˆáª«î稬 ç¨á«® ®¯¥à ­¤®¢
AL=AH;
AL&=TRANSBITS; // ‚뤥«¨¬ à §¬¥à ®¯¥à ­¤ 
$CMP AL,_D
$JBE G100 // Ž¯¥à ­¤ ¬.¡. à §¬¥à : byte, word, dword
G94:
$CMP AL,NB
$JB J0 //G95 // Ž¯¥à ­¤ ¬.¡. à §¬¥à  WB,DW OR BW.
AL-=NB; // ¥à¥áç¨â ¥¬ ¤«ï 䨪á¨à®¢ ­­ëå à §¬¥à®¢: NB->B,OW->W, AF->D
G95:
$CMP AL,OPERANDSIZE //  §¬¥à ®¯¥à ­¤  ¨ à §¬¥à ¨§ è ¡«®­  ᮢ¯ «¨?
$JNE G9 //  §¬¥àë ­¥ ᮢ¯ «¨ - ¨é¥¬ á«¥¤ãîéãî § ¯¨áì
$JMP G11 //  §¬¥àë ᮢ¯ «¨ - ¯à®¤®«¦¨¬
J0:
$CMP OPDESC[0],CO
$JNE J1
$CMP AL,WB;
$JNE J1
OPCONSTSIZE[0]=_W;
OPCONSTSIZE[1]=_B;
GOTO G11;
J1:
$CMP AL,_DW;
$JNE J2;
RANDFLAG=0;
OPCONSTSIZE[0]=_D;// OPCONSTSIZE[1]=_W;
GOTO G11;
J2:
$CMP AL,BW;
$JNE G95
OPCONSTSIZE[0]=_B;
OPCONSTSIZE[1]=_W;
GOTO G11;
G100:
$CMP OPERANDSIZE,_D
$JA NEAR G9 //  §¬¥à ®¯¥à ­¤  > dword - ­  á«¥¤ãîéãî § ¯¨áì
$CMP OPERANDSIZE,AL
$JB NEAR G9 //  §¬¥àë ­¥ ᮢ¯ «¨ - ¨é¥¬ á«¥¤ãîéãî § ¯¨áì
EBX=0;
DL=AL;
AL=OPERANDSIZE;
$CMP DL,_B //  §¬¥à ¢ è ¡«®­¥ = byte?
$JNE G50
$CMP AL,_B //  §¬¥à ®¯¥à ­¤  = byte?
$JE G50
BL++; // W-¡¨â=TRUE
G50:
$CMP AL,_W // ‚ è ¡«®­¥ word?
$JNE G60
$JA G60
BH++; // Ž¯¥à ­¤ ®¡ï§ â¥«ì­® ¤.¡. word - âॡã¥âáï ¯à¥ä¨ªá RAND
G60:
WBIT=BL;
RANDFLAG=BH;
G11:
AH&=NTRANSBITS;
AL=AH; // ‚®§¢à â¨¬ SOO ¯®«¥
}
 
// ----  §¡®àª  è ¡«®­  ¤«ï âà¥å®¯¥à ­¤­®© ¨­áâàãªæ¨¨
GETOL3()
{
G12:
$LODSB
AH=AL;
AL&=OLBITS;
$CMP AL,OL3
$JE G13
G14:
$LODSB //TRY NEXT ENTRY.
$OR AL,AL
$JZ G12
$CMP AL,_END
$JNE G14
toomuchoperands();
$POP EAX;
$RET // ‚ë室 ¨§ MapOperands
G13:
AH&=NOLBITS;
$CMP OPERANDSIZE,_D //DWORD ?
$JE G15
$CMP OPERANDSIZE,_W //WORD ?
$JE G16
preerror("ASM: This instruction required a WORD/DWORD operand\n");
$RET
G16:
RANDFLAG=1;
G15:
AL=AH&0xE0;
}
 
// ----
CREATE_EA()
{
EA_M=AL&7;
EA_X=3;
}
 
// ----
CREATE_R()
{
EA_R=AL&7;
}
 
// ---- ƒ¥­¥àà æ¨ï ModRM ¨ Sib
GETMODRMBYTE()
{
DL=EALENGTH; // Š®«¨ç¥á⢮ ॣ¨áâ஢ ¢ EA
$OR DL,DL // ¥â ॣ¨áâ஢ ¢ EA?
$JE NEAR C11 // „ 
$TEST EADESC,_W+_D*8
$JE NEAR E1 // 8-¡¨â­ë¥ ॣ¨áâàë ­¥«ì§ï ¯à¨¬¥­ âì ¢  ¤à¥á¥
$TEST EADESC,_W*8 // 16-¡¨â­ë© ॣ¨áâà?
$JNE NEAR E4 // 16-¡¨â­ ï  ¤à¥á æ¨ï ­¥ à §à¥è¥­ 
GETEADISPX();
$CMP DH,2
$JNZ X00
EAX=opDescInd;
OPCONSTSIZE[EAX]=_D; // Ž¡ï§ â¥«ì­® 32-¡¨â­ë© disp
X00:
DL--; // 1 ॣ¨áâà?
$JNE N1 // ­¥â...
AL=EADESC&7;
$CMP EA_SIBFLAG,1 // ”« £ ­ «¨ç¨ï Sib ¢ 32-¡¨â­®¬ EA
$JNE L2 // ¥â Sib
EA_R2=5; // ”¨ªá¨à㥬 ¡ §®¢ë© ॣ¨áâà
EA_M=4;
EA_I=AL;
EDX=opDescInd;
$CMP OPCONSTFLAG[EDX],1 // ˆá¯®«ì§ã¥¬ disp?
$JE L1
EAX=0;
OPCONSTFLAG[EDX]=1;
EDX<<=2;
OPCONST[EDX]=EAX; // disp=0 ¢ EA
L1:
EDX=opDescInd;
OPCONSTSIZE[EDX]=_D;
EA_X=0; //EA_X=AL;
$RET
L2:
EA_M=AL;
$RET
N1:
EA_M=4; //2 REGISTERS USED.
EA_SIBFLAG=1;
AL=EADESC[1]>>3;
$CMP AL,_W
$JE E5 //ERROR: INDEX REGISTER ISN'T OF SIZE DWORD
AL=EADESC;
AH=EADESC[1];
EAX&=0x707;
$CMP AH,5 //CAN'T USE BP AS INDEX.
$JE E6
EA_R2=AL;
EA_I=AH;
$RET
E1:
preerror("ASM: You can't use byte registers in addresses\n");
$RET
E4:
preerror("ASM: 16-bit addressing mode not allowed\n");
$RET
E5:
preerror("ASM: You must use a 32-bit registers for scaling\n");
$RET
E6:
preerror("ASM: You can't use EBP as an index\n");
$RET
C11:
EA_X=0;
EA_M=5;
ECX=opDescInd;
AL=OPCONSTSIZE[ECX];
IF(AL==_B)OPCONSTSIZE[ECX]=_D;
ELSE IF(AL==_W)ADDRFLAG=1;
}
 
// ----
GETEADISPX()
{ //CREATE X NIBBLE OF DISPLACEMENT SIZE.
DH=0;
$PUSH ECX
ECX=opDescInd;
IF(OPCONSTFLAG[ECX]==1){
AL=OPCONSTSIZE[ECX];
DH=2; //(D)WORD DISPLACEMENT
IF(AL==_B)DH--; //SBYTE DISPLACEMENT
}
EA_X=DH;
$POP ECX
}
 
// ---- ˆ­¨æ¨ «¨§ æ¨ï ¡ãä¥à   áᥬ¡«¥à 
INIT_LINE()
{
ECX=#opDescInd-#OPERANDSIZE;
AL=0;
EDI=#OPERANDSIZE;
$REP $STOSB;
AL=255;
OPERANDSIZE=AL;
SEGREGISTER=AL;
}
 
// ---- ‡ ¯¨áì ¯¥à¥®¯à¥¤¥«¥­¨ï ᥣ¬¥­â 
WRITEOVERRIDE()
{
EBX=OVERRIDE;
IF(BL!=0){
AL=OVERRIDETAB[EBX]-rES;
OP();
}
}
 
// ---- ‡ ¯¨áì ¯à¥ä¨ªá  à §¬¥à­®á⨠®¯¥à ­¤ 
WRITERAND()
{
$PUSH EAX
IF(RANDFLAG==1){
AL=0x66;
OP();
}
$POP EAX
}
 
// ---- ‡ ¯¨áì ª®­áâ ­âë: CL=TYPE; EDI 㪠§ â¥«ì ­  §­ ç¥­¨¥
WRITECONST()
{
IF(CL==_B)CL=1;
ELSE IF(CL==_W)CL=2;
ELSE IF(CL==_D)CL=4;
ELSE CL++;
loop(ECX){
AL=DSBYTE[EDI];
EDI++;
OP();
}
}
 
// ---- Ž¡à ¡®âª  Override
GETOVERRIDE()
{
IF(tok==tk_seg)&&(tok2==tk_colon){
IF(OVERRIDE==0){
OVERRIDE=number;
$STC // ù ᥣ¬¥­â­®£® ॣ¨áâà 
}
ELSE preerror("ASM: Double segment override");
NextTok();
NextTok(); // à®¯ã᪠¥¬ :
}
}
 
// ---- ‚ëç¨á«¥­¨¥ à §¬¥à  ®¯¥à ­¤ : _B,_W,_D,WB,_DW & RAND-FLAG. AL=SIZE
DEF_OPSIZE()
{
AH=OPERANDSIZE;
IF(AH==255){
OPERANDSIZE=AL; // Ž¤¨­ ®¯¥à ­¤
return;
}
IF(AH==AL)return; //  §¬¥àë ᮢ¯ ¤ îâ
IF(AX==0X100){ // RW,RB ?
RANDFLAG=1;// OPERANDSIZE=WB;
return;
}
IF(AX==0X200){ // RD,RB ?
IF(ACTUALMNEMDESC==#PCOMMANDS3_){
// OPERANDSIZE=_D;
return;
}
OPERANDSIZE=WB;
return;
}
IF(AX==0X201){ //RD,RW
RANDFLAG=1;
OPERANDSIZE=_DW;
}
}
 
// ---- ‡ ¯¨áì ¯à¥ä¨ªá   ¤à¥á æ¨¨
WRITEADDR()
{
$PUSH EAX
IF(ADDRFLAG==1){
AL=0x67;
OP();
}
$POP EAX
}
 
// ---- Ž¯à¥¤¥«¥­¨¥ à §¬¥à­®á⨠ª®­áâ ­âë
DefConstSize()
{ // Ž¯à¥¤¥«¨¬ à §¬¥à­®áâì ª®­áâ ­âë
EBX=opDescInd;
DL=_D;
IF(OPPOST[EBX]==0){
EBX=opDescInd<<2;
EAX=OPCONST[EBX];
DL=_B; // byte
IF(long EAX>=-128){ // -128
$CMP EAX,0XFF // 255
$JNG W2
}
DL++; // _W - word
IF(long EAX>=-32768){
$CMP EAX,0XFFFF // 65535
$JNG W2
}
DL++; // _D - dword
}
W2:
EBX=opDescInd;
OPCONSTSIZE[EBX]=DL;
OPCONSTFLAG[EBX]=1;
}
 
// ---- Ž¡à ¡®âª  ¬­¥¬®­¨ª¨  áᥬ¡«¥à 
DoMnemonics()
{
opDescInd=0;
EADescInd=0;
INIT_LINE(); // Žç¨á⪠ ¡ãä¥à®¢
IF(number<24){
IF(number<8)EBX=#PCOMMANDS1;
ELSE IF(number<12){
number-=8;
EBX=#PCOMMANDS2;
}
ELSE IF(number<20){
number-=12;
EBX=#PCOMMANDS3;
}
ELSE{
number-=20;
EBX=#PCOMMANDS4;
}
number+=DSBYTE[EBX];
PFLAG=number;
EBX++;
}
ELSE{
number-=24;
EBX=number<<2;
EBX=TAB_MNEMONICS[EBX];
IF(EBX>=#T_DAA)&&(EBX<#T_NOT){ // à®¢¥à¨¬ ­  ­ «¨ç¨¥ ¨­áâàãªæ¨¨ ¡¥§ ®¯¥à ­¤®¢
ACTUALMNEMDESC=EBX;
IF(tok2==tk_semicolon)NextTok();
ESI=ACTUALMNEMDESC;
$JMP CreateCode;// ƒ¥­¥à æ¨ï ª®¤  ¤«ï ¨­áâàãªæ¨¨ ¡¥§ ®¯¥à ­¤®¢
}
}
ACTUALMNEMDESC=EBX; // ‡ ¯®¬­¨¬ 㪠§ â¥«ì ­  ⥪ã騩 è ¡«®­ ¬­¥¬®­¨ª¨
for(;;){ // –¨ª«  ­ «¨§  ®¯¥à ­¤®¢
prevTok=tok;
NextTok(); // ‘«¥¤ãî騩 ®¯¥à ­¤
FastSearch(#string,#St_Sizes);// â® à §¬¥à ®¯¥à ­¤ ?
IF(CARRYFLAG){ // „ : byte,word ¨«¨ dword
OPERANDSIZE=AL; // ‡ ¯®¬­¨¬ _B,_W,_D
continue;
}
GETOVERRIDE(); // Ž¡à ¡®âª  ª®­áâàãªæ¨¨ SEG:
ContLine: // ’®çª  ¤«ï ¯à®¤®«¦¥­¨ï ®¡à ¡®âª¨ ⥪ã饣®
IF(tok==tk_eof)||(tok==tk_semicolon){
EBX=opDescInd;
IF(OPDESC[EBX]==E){ // Ž¡à ¡®âª  ¢ EA?
DefConstSize();
GETMODRMBYTE(); // EOL - GENERATE MODRM OPCODE BYTE.
}
IF(prevTok!=tk_mnemonics){ // ë«¨ ®¯¥à ­¤ë
OPLENGTH++;
IF(OPERANDSIZE==255){
OPERANDSIZE=_D; // à¨­ã¤¨â¥«ì­® ãáâ ­®¢¨¬ dword
}
}
$JMP MapOperands
}
else IF(tok==tk_comma){
IF(opDescInd==3){
toomuchoperands();
break;
}
EBX=opDescInd;
IF(OPDESC[EBX]==E){ // Ž¡à ¡®âª  ¢ EA?
DefConstSize();
GETMODRMBYTE(); // EOL - GENERATE MODRM OPCODE BYTE.
}
opDescInd++;
OPLENGTH++;
}
else IF(tok==tk_openblock){
EBX=opDescInd;
OPDESC[EBX]=E; // Žâ¬¥â¨¬, çâ® à ¡®â ¥¬ á EA ®¯¥à ­¤®¬
}
else IF(tok==tk_closeblock){ // ]
DefConstSize();
GETMODRMBYTE(); // EOL - GENERATE MODRM OPCODE BYTE.
}
else IF(tok==tk_minus){
IF(tok2 == tk_number){
NextTok();
number = -number;
$JMP ContLine; // à®¤®«¦¨¬ docase ¡¥§ ¢ë¡®àª¨ á«¥¤.token
}
}
else IF(tok==tk_plus) continue;
else IF(tok==tk_mult){ // *
GETSCALING(); // “ª § ­ ¬ áè ¡ ¢ Sib
}
else if(tok==tk_reg){ // Ž¡à ¡®âª  ॣ¨áâà 
G0:
EBX=opDescInd;
IF(OPDESC[EBX]==E){ // Ž¡à ¡®âª  ¢ EA?
IF(type==tk_byte){
preerror("ASM: No byte register in address\n");
return;
}
IF(EALENGTH<2){ // Š®«¨ç¥á⢮ ॣ¨áâ஢ ¢ EA < 2 ?
EALENGTH++; // Žâ¬¥â¨¬, çâ® ¥áâì ¥é¥ ®¤¨­ ॣ¨áâà ¢ EA
EBX=EADescInd;
EADESC[EBX]=number; // ‡ ¯®¬­¨¬ ù ॣ¨áâà 
EADescInd++;
}
ELSE{ // ‘«¨èª®¬ ¬­®£® ॣ¨áâ஢ ¢ EA
preerror("ASM: too much registers in combination\n");
return;
}
}
ELSE{
OPDATA[EBX]=number; // ù ॣ¨áâà 
OPDESC[EBX]=R;
AH=number&7;
EA_R=AH;
IF(opDescInd!=2){
AL>>=3;
DEF_OPSIZE();
}
}
}
else IF(tok==tk_number) { // Ž¡à ¡®âª  ª®­áâ ­âë
IF(tok2==tk_mult){
DoScale();
NextTok();
continue;
}
NUM:
EBX=opDescInd<<2;
OPCONST[EBX]+=number; // ‡ ¯®¬­¨¬ ª®­áâ ­âã
DefConstSize(); // Ž¯à¥¤¥«¨¬ à §¬¥à­®áâì ª®­áâ ­âë
IF(OPDESC[EBX]!=E) // Š®­áâ ­â  ¢ EA?
OPDESC[EBX]=CO;
}
else IF(tok==tk_postnumber){
EBX=opDescInd;
OPPOST[EBX]=POST_DATA;
EBX<<=2;
OPPOSTREF[EBX]=treeptr;
ESI=treeptr;
DSDWORD[ESI+recpost]++;
GOTO NUM;
}
else IF(tok==tk_proc){
IF(post){
EBX=opDescInd;
OPPOST[EBX]=POST_CALL;
EBX<<=2;
OPPOSTREF[EBX]=treeptr;
ESI=treeptr;
DSDWORD[ESI+recpost]++;
}
$JMP NUM
}
else IF(tok==tk_locallabel){
EBX=opDescInd<<2;
OPPOSTREF[EBX]=localptr;
I2:
EBX=opDescInd;
$CMP ACTUALMNEMDESC,#T_JCXZ;
$JB I1
$CMP ACTUALMNEMDESC,#T_CALLFAR;
$JA I1
OPPOST[EBX]=POST_CALL;
$JMP NUM
I1:
OPPOST[EBX]=POST_DATA;
AL=_D;
DEF_OPSIZE();
$JMP PARSE_EA1
}
else IF(tok==tk_undefproc){
I0:
EBX=opDescInd<<2;
OPPOSTREF[EBX]=treeptr;
GOTO I2;
}
else IF(tok==tk_id){
tok = tk_undefproc;
post = 1;
number=0;
AddToTree(#string);
GOTO I0;
}
else IF(tok==tk_var){ // ˆ­¨æ¨ «¨§ æ¨ï EA á ª®­á⠭⮩: EA+disp
AL=type-tk_byte>>1; // AL=à §¬¥à  ¤à¥á㥬®£® ®¯¥à ­¤  (_B,_W,_D)
DEF_OPSIZE();
EBX=opDescInd;
IF(post){
EBX<<=2;
OPPOSTREF[EBX]=treeptr;
EBX=opDescInd;
OPPOST[EBX]=POST_DATA;
ESI=treeptr;
DSDWORD[ESI+recpost]++;
}
PARSE_EA1:
OPDESC[EBX]=E;
OPCONSTFLAG[EBX]=1; // Žâ¬¥â¨¬, çâ® à ¡®â ¥¬ á EA ®¯¥à ­¤®¬
EBX<<=2;
OPCONST[EBX]+=number; // ‡ ¯®¬­¨¬  ¤à¥á
}
else IF(tok==tk_seg){
EBX=opDescInd;
OPDATA[EBX]=number-rES; // ù ᥣ¬¥­â­®£® ॣ¨áâà 
SEGREGISTER=AL;
AL<<=3; // ‘®§¤ âì ª®¤ ¤«ï XSM ¯®«ï
EA_S=AL;
OPDESC[EBX]=_SR;
AL=_W;
DEF_OPSIZE();
}
else IF(tok==tk_param)||(tok==tk_local){
PARSE_PAR:
AL=type-tk_byte>>1;
DEF_OPSIZE();
EBX=opDescInd;
OPDESC[EBX]=E;
EBX<<=2; // Žâ¬¥â¨¬, çâ® à ¡®â ¥¬ á EA ®¯¥à ­¤®¬
OPCONST[EBX]+=number; // ‡ ¯®¬­¨¬  ¤à¥á
OPCONSTFLAG[EBX]=1;
number=rEBP;
$JMP G0;
}
else IF(tok==tk_controlreg){
EBX=opDescInd;
OPDESC[EBX]=SYSR;
SYSRNUM=number;
IF(AL==4)SYSRTYPE=_CR4;
ELSE{
SYSRTYPE=_CR;
SYSRCODE=0;
}
}
ELSE IF(tok==tk_debugreg){
EBX=opDescInd;
OPDESC[EBX]=SYSR;
SYSRNUM=number;
SYSRTYPE=_DR;
SYSRCODE=1;
}
ELSE IF(tok==tk_testreg){
EBX=opDescInd;
OPDESC[EBX]=SYSR;
SYSRNUM=number;
SYSRTYPE=_TR;
SYSRCODE=4;
}
ELSE preerror("ASM: Syntax error\n");
}
}
 
CreateScale()
{
IF(ADDRFLAG)return;
if(EA_SIBFLAG){ // ”« £ ­ «¨ç¨ï Sib ¢ 32-¡¨â­®¬ EA
IF(EA_SCALE==0){ // Žâáãâáâ¢ã¥â
EA_SCALING=0;
}
else IF(EA_SCALE==1)EA_SCALING=0;
else IF(EA_SCALE==2)EA_SCALING=0x40;
ELSE IF(EA_SCALE==4)EA_SCALING=0x80;
ELSE IF(EA_SCALE==8)EA_SCALING=0xC0;
ELSE{
EA_SCALING=0;
IF(EA_SCALE>255)OP(byte 0x69);
ELSE OP(byte 0x6B);
AL=EA_I<<3|EA_I|0xC0;
OP(byte AL);
IF(EA_SCALE>255)OUTDWORD(EA_SCALE);
ELSE OP(byte EA_SCALE);
}
}
}
 
// ---- ƒ¥­¥à æ¨ï ª®¤ . ESI=ptr ­  § ¯¨áì ® ®¯¨á ­¨¥ ¬­¥¬®­¨ª¨ (§ ¯¨áì ⨯  T_...)
CreateCode()
{
WRITEOVERRIDE();
CreateScale();
IF(ADDRFLAG==1){ //ADDR: PREFIX ?
OP(byte 0x67);
}
IF(RANDFLAG==1){ //RAND: PREFIX ?
OP(byte 0x66);
}
EDI=ESI;
IF(ACTUALMNEMDESC==#T_TEST)DBIT=0; //DON'T ADD ANYTHING IF TESTING
$SHL DBIT,1 //SHIFT D-BIT TO THE RIGHT POSITION.
NEXT_DESC_BYTE: // Ž¡à ¡®âª  ¡ ©â  ¨§ ¤¥áªà¨¯â®à  ¬­¥¬®­¨ª¨
EBX=0;
BL=DSBYTE[EDI];
EDI++;
NB3:
$CMP BL,X7M
$JA NC3
$CMP BL,X0M
$JB N24
AH=BL-X0M;
AL=EA_X<<3|AH<<3|EA_M;
OP();
GOTO NEXT_DESC_BYTE;
N24:
EBX<<=2;
EBX+=#Dsc_Jump;
$JMP NEAR DSDWORD[EBX]
NC3:
$CMP BL,_END
$JNE E42
$JMP CreateConstants // Š®­¥æ è ¡«®­  ¤«ï ¬­¥¬®­¨ª¨
E42:
preerror("Descriptor damaged\n");
return;
// OpCode - 1 ¡ ©â
Dsc_O:
AL=DSBYTE[EDI]+WBIT+DBIT;
EDI++;
OP();
GOTO NEXT_DESC_BYTE;
// OpCode - 1 á«®¢®
Dsc_OW:
AL=DSBYTE[EDI];
EDI++;
OP();
AL=DSBYTE[EDI]+WBIT+DBIT;
EDI++;
OP();
$JMP NEXT_DESC_BYTE
// OpCode - 1 ¡ ©â ¨ á«¥¤ãî騩 ¡ ©â, § ¤ ­­ë© 8-à¨ç­®© áâப®©
Dsc_OS:
AL=DSBYTE[EDI];
EDI++;
OP();
// OpCode - 8-à¨ç­ ï áâப  á ª®¤®¬
Dsc_S:
S01:
CL=3;
EAX=0;
loop(CL){
AL=DSBYTE[EDI];
EDI++;
IF(AL=='X'){ //X CHAR
AL=EA_X;
}
ELSE IF(AL=='R')AL=EA_R;
ELSE IF(AL=='M')AL=EA_M;
ELSE IF(AL=='S')AL=SEGREGISTER;
ELSE IF(AL=='N')AL=SYSRNUM;
ELSE IF(AL=='P')AL=PFLAG;
ELSE AL-='0';
AH=AH<<3|AL;
}
AL=AH+DBIT+WBIT;
N15:
OP();
$JMP NEXT_DESC_BYTE
// OpCode - ModRM ¡ ©â
Dsc_XRM:
AL=EA_X<<3|EA_R<<3|EA_M; // ®«ãç¨âì ॣ¨áâà ¨§ ®¯¨á ­¨ï ¬­¥¬®­¨ª¨
GOTO N15;
// OpCode - ModRM á P-ä« £®¬ ( à¨ä¬¥â¨ç¥áª¨¥ ¨­áâàãªæ¨¨)
Dsc_XPM:
AL=EA_X<<3|PFLAG<<3|EA_M;
GOTO N15;
// OpCode - ModRM á ᥣ¬¥­â­ë¬ ॣ¨áâ஬
Dsc_XSM:
AL=EA_X<<3|SEGREGISTER<<3|EA_M;
GOTO N15;
// JMP NEXT_DESC_BYTE
}
 
// ----  §¡®à § ª®­ç¥­ -> ­  £¥­¥à æ¨î ª®¤  ¯® è ¡«®­ã
MapOperands()
{
// AL=0; WBIT=AL; DBIT=AL;
opDescInd=0;
ESI=ACTUALMNEMDESC; // “ª § â¥«ì ­  ¨­ä®à¬ æ¨î ¯® £¥­¥à æ¨¨
AL=OPLENGTH; // Š®«¨ç¥á⢮ ®¯¥à ­¤®¢
ECX=#OPDESC; // “ª § â¥«ì ­  ¨­ä®à¬ æ¨î ®¡ ®¯¥à ­¤ å
ECX=DSDWORD[ECX];
IF(ESI!=#T_MOV){ // ˆ­áâàãªæ¨ï MOV?
IF(AL!=0){
$CMP AL,1
$JE NEAR ONEOP // ˆ­áâàãªæ¨ï á ®¤­¨¬ ®¯¥à ­¤®¬
$CMP AL,2
$JE NEAR TWOOPS // ˆ­áâàãªæ¨ï á ¤¢ã¬ï ®¯¥à ­¤ ¬¨
$CMP AL,3
$JE NEAR THREEOPS // ˆ­áâàãªæ¨ï á âà¥¬ï ®¯¥à ­¤ ¬¨
toomuchoperands();
return;
}
// ---- ˆ­áâàãªæ¨ï ¡¥§ ®¯¥à ­¤®¢
do{
$LODSB
IF(AL==0)goto CreateCode; // ƒ¥­¥à æ¨ï ª®¤ 
}while(AL!=_END);
preerror("ASM: Operand required\n");
return;
// ---- ƒ¥­¥à æ¨ï MOV ¨­áâàãªæ¨¨
}
$PUSH EAX,ECX
WRITEOVERRIDE();
CreateScale();
$POP ECX,EAX
IF(AL!=2){ // 2 OPERANDS IN INSTRUCTION?
preerror("ASM: Two operands required\n");
return;
L2:
preerror("ASM: Not same size\n");
return;
}
L1:
BL=0;
AL=OPERANDSIZE;
IF(AL!=_D){
$CMP AL,_W
$JA L2
$JNE N4
RANDFLAG=1;
}
BL=1;
N4:
WBIT=BL; //STORE W-BIT
DL=0; //CLEAR D-BIT
WRITEADDR();
EBX=0;
BL=CL;
EBX=EBX<<2+#Jmp_Mov;
$JMP NEAR DSDWORD[EBX]
Mov_ERR:
preerror("ASM: a constant can't be used as a destination\n");
return;
Mov_R:
EBX=0;
BL=CH;
EBX=EBX<<2+#Jmp_Mov_R;
$JMP NEAR DSDWORD[EBX]
Mov_E:
EBX=0;
BL=CH;
EBX=EBX<<2+#Jmp_Mov_E;
$JMP NEAR DSDWORD[EBX]
Mov_R2R:
WRITERAND();
AL=OPDATA[1];
AH=OPDATA[0];
DL=DBIT;
$PUSH EAX
AL=0o210+WBIT;
$SHL DL,1
AL+=DL; //D-BIT
OP();
$POP EAX
AL=AL&7<<3;
AH&=7;
AL=AL|AH|0o300;
OP();
$JMP CreateConstants
Mov_R2E:
AL=OPDATA&7; //AL/AX/EAX ?
$OR AL,AL
$JNE N1
$CMP EA_M,6 //AR,[DW] POSSIBLE?
$JNE N1 //NO, ONLY AR,[EA]
$CMP ADDRFLAG,0 //32BIT-EA ?
$JE N1 //NO, TRY ANOTHER...
WRITERAND();
AL=0o240+WBIT; //INSTRUCTION FOUND.
OP();
$JMP CreateConstants
Mov_E2R:
D1:
AL=OPDATA[1]&7; //[DW],AR POSSIBLE?
$OR AL,AL
$JNE Y1
$CMP ADDRFLAG,0 //32BIT EA ?
$JNE Y1 //YES, RAVE ON...
$CMP EA_M,6
$JNE Y1
WRITERAND();
AL=0o242+WBIT; //INSTRUCTION FOUND.
OP();
$JMP CreateConstants
N1:
DL=2; //SET D-BIT
Y1:
DL+=0o210;
WRITERAND();
AL=DL;
DL=0;
AL+=WBIT;
OP();
AL=EA_X<<3|EA_R<<3|EA_M;
OP();
$JMP CreateConstants
E1:
preerror("ASM: Not same size\n");
return;
//EA,CONSTANT ?
Mov_E2C:
OPCONSTSIZE[1]=OPERANDSIZE;
$CMP AL,_D
$JA E1
$JE X1
$CMP AL,_W
$JNE X1
AL=0x66;
OP();
X1:
AL=0o306+WBIT;
OP();
AL=EA_X<<6|EA_M;
OP();
$JMP CreateConstants
Mov_R2C:
OPCONSTSIZE[1]=OPERANDSIZE;
$CMP OPERANDSIZE,_B
$JNE N2
AL=OPDATA&7|0o260;
OP();
$JMP CreateConstants
N2:
$CMP OPERANDSIZE,_D //BYTE, WORD OR DWORD?
$JA NEAR E1 // Not same size
IF(OPERANDSIZE==_W){
AL=0x66;
OP();
}
AL=OPDATA&7|0o270;
OP();
$JMP CreateConstants
E21:
preerror("ASM: Word required\n");
return; //SEGMENT REGISTER IS ALWAYS WORD.
Mov_S:
AL=0;
$CMP CX,_SR*256+E // mov EA,segreg
$JE O1
$CMP CX,_SR*256+R // mov segreg,reg
$JE O2
$CMP CX,R*256+_SR // mov reg,segreg
$JE O3
$CMP CX,E*256+_SR // mov segreg,EA
$JNE NEAR N12
AL=2; //SET D-BIT
O1:
$CMP OPERANDSIZE,_W
$JNE E21
AL+=0o214;
OP();
AL=EA_X<<6|EA_S|EA_M;
OP();
$JMP CreateConstants
O2:
$CMP OPERANDSIZE,_W
$JNE E21
AL=0o214;
OP();
AL=EA_S|0o300|EA_R; //CREATE XSM BYTE
OP();
$STC
$RET
O3:
$CMP OPERANDSIZE,_W
$JNE NEAR E21
AL=0o216;
OP();
AL=EA_S|0o300|EA_R;
OP();
$STC
$RET
E31:
preerror("ASM: CR1 only readable\n");
$RET
E32:
preerror("ASM: SysR must be dword\n");
$RET
Mov_SYSR:
N12:
AH=0o40;
$CMP CX,SYSR*256+R
$JE O11
$CMP CX,R*256+SYSR
$JNE N22 //ERROR: ILLEGAL OPERANDS
AH=0o42;
$CMP SYSRTYPE,_CR //CR1 REGISTER USED?
$JNE O11
$CMP SYSRNUM,1
$JE E31 //YES, ONLY READ FROM IT.
O11:
AH+=SYSRCODE;
$CMP OPERANDSIZE,_D //SYSTEM REGISTERS ARE ALWAYS DWORD.
$JNE E32
AL=0o17;
OP();
$CMP SYSRTYPE,_CR4 //EXCEPTION: CR4
$JE N22
AL=AH;
OP();
AL=SYSRNUM<<3|0o300|EA_R; //CREATE 3NR OPCODE
OP();
$STC
$RET
N22:
$CMP CX,SYSR*256+R
$JNE N32
AL=0x22;
OP();
GOTO L11;
N32:
AL=0x20;
OP();
L11:
AL=0o340|EA_R;
OP();
$STC
$RET
// ---- ˆ­áâàãªæ¨ï á ®¤­¨¬ ®¯¥à ­¤®¬
ONEOP:
EBX=CL<<2+#Jmp_Op1;
$JMP NEAR DSDWORD[EBX]
Op1ERR:
preerror("ASM: only use system registers within MOV instruction\n");
$RET
// RX
L31:
SCDEND();
Op1R:
GETOL1(); //GET FIRST GENERATION INFO.
$CMP AL,SOR //SINGLE OPERAND/REGISTER ?
$JNE X23
$JMP CreateCode
X23:
$CMP AL,SOE //CONVERT REGISTER INTO EFFECTIVE ADDRESS?
$JNE L31
C2:
EA_X=3;
AL=EA_R;
EA_M=AL;
$JMP CreateCode
// EA
L41:
SCDEND();
Op1E:
GETOL1();
$CMP AL,SOE //SINGLE OPERAND/EFFECTIVE ADDRESS ?
$JNE X24;
$JMP CreateCode
X24:
$CMP AL,SOM //SINGLE OPERAND/MEMORY POINTER ?
$JNE L41
$CMP EA_X,0
$JNE L41
$CMP EA_M,6 //[WORD CONSTANT]?
$JNE L41
C11:
$JMP CreateCode
// CO
L51:
SCDEND();
Op1C:
GETOL1();
$OR AL,AL //JUMP INSTRUCTION?
$JNE NEAR N13
// ‡¤¥áì ®¡à ¡®âª  call&jmp
ECX=OPCONST[0]-OptImageBase-OptBaseOfCode-outptr+output; //  áç¥â ®â­®á¨â¥«ì­®£® ᬥ饭¨ï
$LODSB // ®«ã稬 short ¨«¨ near
$CMP AL,_JB // short?
$JNE N14
ECX-=2;
$CMP ECX,0xFFFFFF80
$JL L10
$CMP ECX,0x7F
$JG L10
OPCONSTSIZE[0]=_B;
H1:
OPCONST[0]=ECX;
$JMP CreateCode
N14:
EAX=0;
$LODSB // ®¯à ¢ª  ­  à §¬¥à call ¨«¨ jmp
ECX-=EAX;
OPCONSTSIZE[0]=_D;
GOTO H1;
L10:
$CMP ACTUALMNEMDESC,#T_JCXZ
$JB L51
$CMP ACTUALMNEMDESC,#T_LOOP
$JA NEAR L51
preerror("ASM: Jump range too long\n");
$RET
N13:
$CMP AL,SO3 //CONSTANT VALUE 3 ?
$JNE N23
$CMP OPCONST[0],3
$JNE NEAR L51
OPCONSTFLAG[0]=0; //YES, AVOID CONSTANT GENERATION.
$JMP CreateCode
N23:
$CMP AL,SOC //SINGLE OPERAND/CONSTANT?
$JNE X25
OPCONSTSIZE[0]=OPERANDSIZE;
$JMP CreateCode
X25:
$CMP AL,SOO_CC //SINGLE OPERAND/SIGNED BYTE ?
$JNE NEAR L51
IF(OPPOST[0])$JMP L51
$CMP OPCONST[0],0x7F
$JG NEAR L51
$CMP OPCONST[0],0xFFFFFF80
$JL NEAR L51
OPCONSTSIZE[0]=_B;
$JMP CreateCode
// SR
L61:
SCDEND();
Op1S:
GETOL1();
$CMP AL,SOS //SINGLE OPERAND/SEGMENT REGISTER?
$JNE L61
$JMP CreateCode
// AF
L71:
SCDEND();
Op1AF:
GETOL1();
$CMP AL,SOO_AF
$JNE L71
$JMP CreateCode
// ---- ˆ­áâàãªæ¨ï á ¤¢ã¬ï ®¯¥à ­¤ ¬¨
TWOOPS:
EBX=CL<<2+#Jmp_Op2;
$JMP NEAR DSDWORD[EBX] // ¥à¥å®¤ ¯® ⨯㠯¥à¢®£® ®¯¥à ­¤ 
//Op2ERRC:
// preerror("ASM: A constant can't be used as a destination\n");
// return;
Op2ERRS:
preerror("ASM: segment register can only be used within a MOV or PUSH\n");
return;
Op2ERRSYS:
preerror("ASM: only use system registers within MOV instruction\n");
return;
Op2ERRAF:
preerror("Absolute FAR addresses can only be used for jumps\n");
return;
// ¥à¢ë© ®¯¥à ­¤ ¢ 2-®¯¥à ­¤­®© ¨­áâàãªæ¨¨ - ॣ¨áâà
Op2R:
EBX=0;
BL=CH;
EBX=EBX<<2+#Jmp_Op2R;
$JMP NEAR DSDWORD[EBX] // ¥à¥å®¤ ¯® ⨯㠢â®à®£® ®¯¥à ­¤ 
// ¥à¢ë© ®¯¥à ­¤ ¢ 2-®¯¥à ­¤­®© ¨­áâàãªæ¨¨ - EA
Op2E:
EBX=0;
BL=CH;
EBX=EBX<<2+#Jmp_Op2E;
$JMP NEAR DSDWORD[EBX] // ¥à¥å®¤ ¯® ⨯㠢â®à®£® ®¯¥à ­¤ 
// mnem EA,RX
L81:
SCDEND();
OpE2R:
GETOL2(); // Ž¡à ¡®âª  § ¯¨á¨ ¨§ è ¡«®­ 
$CMP AL,DER //EA & R + D-BIT ?
$JE C21
X26:
$CMP AL,ERO //'ERO' ORDER ?
$JE C21
$CMP AL,EAO //EA, ?
$JNE L81 //   ¯à®¯ã᪠§ ¯¨á¨ ¢ è ¡«®­¥
$CMP OPDATA[1],rCL //CL REGISTER USED??
$JNE L81 //   ¯à®¯ã᪠§ ¯¨á¨ ¢ è ¡«®­¥
$CMP DSBYTE[ESI+1],rCL //CL IN GENERATION INFO?
$JNE L81 //   ¯à®¯ã᪠§ ¯¨á¨ ¢ è ¡«®­¥
// CMP OPERANDSIZE,_B //YES, CHECK SIZE.
// JNE L81 //   ¯à®¯ã᪠§ ¯¨á¨ ¢ è ¡«®­¥
ESI++;
ESI++;
C21:
$JMP CreateCode
L91:
SCDEND();
OpR2E:
GETOL2();
$CMP AL,DER //DER ?
$JNE N43
DBIT=1; //(DIRECTION BIT)
$JMP CreateCode
N43:
$CMP AL,REO //REO ?
$JNE L91;
$JMP CreateCode
//RX,RX ?
W2:
ESI++;
GOTO W1;
LA1:
SCDEND();
OpR2R:
$CMP DSBYTE[ESI],_B+OL2+EAO // ¡ ©â+2®¯+EAold?
$JE W2 //EAO FOUND, R+R COMBINATION NOT PERMITTED.
GETOL2(); // Ž¡à ¡®âª  § ¯¨á¨ è ¡«®­ 
$CMP AL,DER // EA,reg ¨«¨ reg,EA á D/W-¡¨â®¬?
$JNE N53
LB2:
AL=OPDATA[0]; // à¥®¡à §ã¥¬ ॣ¨áâà ¢ EA
CREATE_EA();
AL=OPDATA[1]; // ‚â®à®© ®¯¥à ­¤
CREATE_R();
$JMP CreateCode
N53:
$CMP AL,ERO
$JE LB2
$CMP AL,REO
$JNE N63
AL=OPDATA[1]; //RX,EP
CREATE_EA();
AL=OPDATA[0];
CREATE_R();
$JMP CreateCode
N63:
$CMP AL,EAO
$JNE LA1 //   ¯à®¯ã᪠§ ¯¨á¨ ¢ è ¡«®­¥
W1:
ECX=2; //COMPARE 2 OPERANDS.
opDescInd=0;
LX2:
$LODSB // ¯®«¥ ¨§ § ¯¨á¨ è ¡«®­ 
$CMP AL,255 //1ST OPERAND OK.
$JE L022
$CMP AL,AR //AL/AX/EAX?
$JE OL2X_AR
$CMP AL,rDX //DX?
$JE OL2X_DX
$CMP AL,rCL
$JE OL2X_CL
GOTO LA1; //   ¯à®¯ã᪠§ ¯¨á¨ ¢ è ¡«®­¥
OL2X_AR:
EBX=opDescInd;
AH=OPDATA[EBX]&7; // Ž¯¥à ­¤ ¨§ ¬­¥¬®­¨ª¨
$JNZ NEAR LA1 //   ¯à®¯ã᪠§ ¯¨á¨ ¢ è ¡«®­¥
L022:
opDescInd++;
$LOOP LX2
GOTO L23;
OL2X_DX:
EBX=opDescInd;
$CMP OPDATA[EBX],0o12
$JNE NEAR LA1 //   ¯à®¯ã᪠§ ¯¨á¨ ¢ è ¡«®­¥
opDescInd++;
$LOOP LX2
GOTO L23;
OL2X_CL:
EBX=opDescInd;
$CMP OPDATA[EBX],rCL //CL
$JNE NEAR LC1
opDescInd++;
$LOOP LX2
$TEST OPDATA[0],8+16 //1ST REGISTER WORD/DWORD?
$JZ L23
WBIT=1; //YES, SET W-BIT.
L23:
AL=OPDATA[0];
CREATE_EA();
$JMP CreateCode
//EA,CONSTANT ? //EA,CONST?
LB1:
SCDEND();
OpE2C:
GETOL2();
opDescInd=1;
$CMP AL,ECO
$JNE N73
OPCONSTSIZE[1]=OPERANDSIZE;
$JMP CreateCode
N73:
$CMP AL,EAO
$JNE N83
$CMP OPERANDSIZE,_B
$JNE N83
$CMP DSBYTE[ESI],_1
$JNE N83
$CMP OPCONST[4],1
$JNE N83
OPCONSTFLAG[1]=0;
ESI++;
$JMP CreateCode
N83:
$CMP AL,ECCO //EA/SIGNED BYTE ?
$JNE LB1
$CMP OPCONST[4],0xFFFFFF80
$JL LB1
$CMP OPCONST[4],0x7F
$JG NEAR LB1
OPERANDSIZE=_B; //OMIT A SINGLE BYTE ON GENERATION.
$JMP CreateCode
// mnem reg,const
LC1:
SCDEND();
OpR2C:
GETOL2();
opDescInd=1;
$CMP AL,RCO;
$JNE Q1
A0:
OPCONSTSIZE[1]=OPERANDSIZE;
$JMP CreateCode // reg,const
Q1:
$CMP AL,ECO;
$JNE L110
A1:
AL=EA_R;
CREATE_EA();
GOTO A0;
L110:
$CMP AL,EAO;
$JE N93
$CMP AL,ECCO;
$JNE LC1 //SIGNED BYTE CONST ?
$CMP OPCONST[4],0xFFFFFF80;
$JL LC1
$CMP OPCONST[4],0x7F;
$JG LC1
OPERANDSIZE=_B;
OPCONSTSIZE[1]=_B;
GOTO A1; //CONVERT REGISTER TO EFFECTIVE ADDRESS AND GENERATE OPCODE.
N93:
ECX=2; //COMPARE 2 OPERAND.
B2:
$LODSB;
$CMP AL,255;
$JE L122
$CMP AL,AR;
$JE OL2_AR //AL/AX/EAX?
$CMP AL,CO;
$JE OL2_CO //CONSTANT?
$CMP AL,rDX;
$JE OL2_DX //DX?
$CMP AL,_1;
$JE OL2_1 //CONSTANT VALUE 1?
$JMP LC1
OL2_AR:
AH=OPDATA[0]&7;
$JNZ NEAR LC1
L122:
$LOOP B2;
$JMP CreateCode
OL2_CO:
$CMP OPDESC[1],CO;
$JNE NEAR LC1
OPCONSTSIZE[1]=OPERANDSIZE;
GOTO L122;
OL2_DX:
$CMP OPDATA[0],0o12;
$JE L122;
$JMP LC1
OL2_1:
$CMP OPCONSTSIZE[1],_B;
$JNE NEAR LC1
$CMP OPCONST[4],1;
$JNE NEAR LC1
OPCONSTFLAG[1]=0;
$JMP A1
LD1:
SCDEND();
// ¥à¢ë© ®¯¥à ­¤ ¢ 2-®¯¥à ­¤­®© ¨­áâàãªæ¨¨ - ª®­áâ ­â 
Op2C:
GETOL2();
$CMP AL,EAO
$JNE LD1
ECX=2; //COMPARE 2 OPERANDS.
opDescInd=0;
B12:
$LODSB
$CMP AL,255
$JE L222
$CMP AL,AR //AL/AX/EAX
$JE XOL2_AR
$CMP AL,CO
$JE XOL2_CO
$CMP AL,rDX //DX
$JE XOL2_DX
$CMP AL,_1
$JE XOL2_1
GOTO LD1;
XOL2_AR:
EBX=opDescInd;
AH=OPDATA[EBX]&7;
$JNZ N21
L222:
opDescInd++;
$LOOP B12
$JMP CreateCode
N21:
GOTO LD1;
XOL2_CO:
EBX=opDescInd;
$CMP OPDESC[EBX],CO
$JNE LD1
opDescInd++;
$LOOP B12
$JMP CreateCode
XOL2_DX:
EBX=opDescInd;
$CMP OPDATA[EBX],0o12
$JNE NEAR LD1
opDescInd++;
$LOOP B12
$JMP CreateCode
XOL2_1:
EDX=opDescInd;
$CMP OPCONSTSIZE[EDX],_B
$JNE NEAR LD1
EDX<<=2;
$CMP OPCONST[EDX],1
$JNE NEAR LD1
EDX=opDescInd;
OPCONSTFLAG[EDX]=0;
AL=EA_R;
CREATE_EA();
$JMP CreateCode
// ’à¥å®¯¥à ­¤­ ï ¨­áâàãªæ¨ï
LE1:
SCDEND();
THREEOPS:
D11:
GETOL3();
$CMP AL,ERO
$JNE N42
$CMP CX,R*256+E
$JE O21
$CMP CX,R*256+R
$JNE LE1
AL=OPDATA[0];
CREATE_EA();
AL=OPDATA[1];
CREATE_R();
GOTO O21;
N42:
$CMP AL,REO
$JNE N52 //ERROR: INVALID OPERANDS.
$CMP CX,E*256+R
$JE O21
$CMP CX,R*256+R
$JNE LE1
AL=OPDATA[1];
CREATE_EA();
AL=OPDATA[0];
CREATE_R();
O21:
BL=AH&TRANSBITS;
$CMP OPCONSTFLAG[2],1
$JNE NEAR NA3
$CMP BL,CC3
$JNE N52
$CMP OPCONST[8],0xFFFFFF80
$JL NEAR LE1
$CMP OPCONST[8],0x7F
$JG NEAR LE1
OPCONSTSIZE[2]=_B;
$JMP CreateCode
N52:
$CMP BL,CB3
$JNE N62
$CMP OPCONST[8],0xFF
$JA NEAR LE1
OPCONSTSIZE[2]=_B;
$JMP CreateCode
N62:
$CMP BL,CW3
$JNE NA3
$CMP OPCONST[8],0xFFFFFFFF
$JA NEAR LE1
$CMP RANDFLAG,1
$JNE NA2
OPCONSTSIZE[2]=_W;
$JMP CreateCode
NA2:
OPCONSTSIZE[2]=_D;
NA_2:
$JMP CreateCode
NA3:
$CMP BL,CL3
$JNE NEAR LE1
$CMP OPDESC[2],R
$JNE NEAR LE1
$CMP OPDATA[2],rCL
$JE NA_2
illegaloperand();
}
 
CreateConstants()
{
$CMP EA_SIBFLAG,1 // ”« £ ­ «¨ç¨ï Sib ¢ 32-¡¨â­®¬ EA
$JNE L3 // Sib ®âáãâáâ¢ã¥â
$CMP ADDRFLAG,1
$JE L3 //NO, NORMAL XRM
// ‡ ¯¨áì SIB - ¡ ©â 
AL=EA_I<<3|EA_R2|EA_SCALING;
OP();
L3:
$CMP OPCONSTFLAG[0],1
$JNE NEAR N1
IF(OPPOST[0])SetPost(OPPOSTREF[0],OPPOST[0]);
ECX=OPCONSTSIZE[0];
EDI=#OPCONST; // ‡­ ç¥­¨¥ disp ¢ EA
WRITECONST();
N1:
$CMP OPCONSTFLAG[1],1
$JNE NEAR N41
ECX=OPCONSTSIZE[1];
$CMP CL,AF //ABSOLUTE FAR ?
$JNE D21
EDI=#OPCONST+4; //YES, CREATE ADDRESS.
CL=_W; //(32 BIT)
$CMP ADDRFLAG,1
$JNE D2
ECX=_D; //(48 BIT)
D2:
WRITECONST();
EDX+=output;
EBX=EDX>>4;
$AND EDX,15
$PUSH EBX,EDX
$POP EDX //???
EAX=opDescInd;
DSDWORD[EAX]=EDX;
ECX=_W;
/* AFSEG ­¨£¤¥ ­¥ ®¯à¥¤¥«¥­, ­ ¤® ¡ã¤¥â à §¡¨à âìáï
EDI=#AFSEG; //(SEGMENT/SELECTOR) */
 
WRITECONST();
$STC
$RET
D21:
IF(OPPOST[1])SetPost(OPPOSTREF[4],OPPOST[1]);
EDI=#OPCONST+4;
WRITECONST();
N41:
IF(OPCONSTFLAG[2]==1){
ECX=OPCONSTSIZE[2];
EDI=#OPCONST+8;
WRITECONST();
}
}
 
// ----
illegaloperand()
{
preerror("ASM: Illegal operand\n");
}
// ----
toomuchoperands()
{
preerror("ASM: Illegal number of operands\n");
}
 
// JUMP TABLES
dword Jmp_Mov={#Mov_R,#Mov_E,#Mov_ERR,#Mov_S,
#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR};
dword Jmp_Mov_R={#Mov_R2R,#Mov_R2E,#Mov_R2C,#Mov_S,
#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR};
dword Jmp_Mov_E={#Mov_E2R,#Mov_ERR,#Mov_E2C,#Mov_S,
#Mov_ERR,#Mov_ERR,#Mov_ERR,#Mov_ERR,#Mov_ERR,#Mov_ERR};
 
dword Jmp_Op1={#Op1R,#Op1E,#Op1C,#Op1S,
#Op1ERR,#Op1ERR,#Op1ERR,#Op1ERR,#Op1ERR,#Op1AF};
dword Jmp_Op2={#Op2R,#Op2E,#Op2C,#Op2ERRS,
#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRAF};
dword Jmp_Op2R={#OpR2R,#OpR2E,#OpR2C,#Op2ERRS,
#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRAF};
dword Jmp_Op2E={#OpE2R,0,#OpE2C,#Op2ERRS,
#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRAF};
//dword TC_JMP={#T_JMPSHORT,#T_JMPNEAR,#T_JMPFAR};
//dword TC_CALL={0,#T_CALL,#T_CALLFAR};
//dword TC_J={#T_J,#T_JN,1};
dword Dsc_Jump={#CreateConstants,#Dsc_O,#Dsc_OW,#Dsc_OS,#Dsc_S,#Dsc_XRM,#Dsc_XPM,#Dsc_XSM};