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};