Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. dword ACTUALMNEMDESC; // Указатель на описание текущей мнемоники
  2. byte ACTUALMNEMONIC;    // Код текущей мнемоники
  3. byte OPERANDSIZE; // Размер операнда(B,W,D,BW,WB,DW)
  4. byte OPDESC[3];         // Типы операндов (R,E,D,CC,SR,TR,DR,CR)
  5. byte OPDATA[3];         // Информация по операнду (RG,CO,EA)
  6. dword OPCONST[3]; // Значение константы в операнде
  7. byte OPCONSTFLAG[3];    // Наличие константы в операнде
  8. byte OPCONSTSIZE[3];    // Размерность константы в операнде
  9. byte OPPOST[3];
  10. dword OPPOSTREF[3];
  11. byte PFLAG;     // Значение P-флага (номер класса).
  12. byte RANDFLAG;          // TRUE: RAND: требуется префикс 0x66
  13. byte ADDRFLAG;          // TRUE: ADDR: требуется префикс 0x67
  14. byte WBIT;              // Бит WORD в OPCODE
  15. byte DBIT;              // Бит DIRECTION в OPCODE
  16. byte OPLENGTH;          // Количество операндов в текущей инструкции
  17. byte EA_M;              // Байт XRM
  18. byte EA_X;
  19. byte EA_R;              // R NIBBLE IN XRM BYTE.
  20. byte EA_S;              //SEGMENT REGISTER
  21. byte EA_R2;     //BASE REGISTER
  22. byte EA_I;              //INDEX REGISTER
  23. byte EADESC[2];         //CONTAINS INFORMATION ABOUT AN PARSED EFFECTIVE ADRESS.
  24. byte EALENGTH;          // Количество регистров в EA
  25. byte EA_SIBFLAG;        // Флаг наличия Sib в 32-битном EA
  26. byte EA_SCALING;        // Индекс в Sib
  27. dword EA_SCALE;         // Значение для Scale в Sib
  28. dword EADescInd;        // Индекс в EADESC
  29. byte SEGREGISTER; // SEGMENT OVERRIDE PREFIX NEEDED OR 0.
  30. byte SYSRNUM;   // CONTROL/DEBUG/TASKREG INDEX
  31. byte SYSRTYPE;          // SYSTEM REGISTER TYPE (CR,CR4,DR,TR)
  32. byte SYSRCODE;          // ENCODED REGISTER TYPE
  33. byte OVERRIDE;          //SEGMENT OVERRIDE PREFIX NEEDED OR 0.
  34. dword opDescInd;
  35. dword prevTok;
  36. // ----- Ассемблирование строки
  37.  
  38. Asm(dword str)
  39. byte holdcha;
  40. byte source[256],s[STRLEN],s2[STRLEN];
  41. {
  42.         lstrcpyA(#source,str);
  43.         IF(list){
  44.                 fprint(mapfile,"\t//\t");
  45.                 fprint(mapfile,str);
  46.                 fprint(mapfile,"\n");
  47.         }
  48.         holdcha=cha2; //запомнить позицию разбора
  49.         $PUSH linenum2,inptr2,number,tok2,tok,input,inptr,currmod,linenumber,
  50.                 endoffile,displaytokerrors,type;
  51.         lstrcpyA(#s,#string);
  52.         lstrcpyA(#s2,#string2);
  53.         input=#source;  //разбираем новую строку
  54.         inptr = input;
  55.         inptr2=input;
  56.         endoffile=0;    // На начале файла
  57.         NextChar();
  58.         cha2 = cha;
  59.         inptr2=inptr;
  60.         linenum2 = 1;
  61.         for(;;){
  62.                 NextTok();
  63.                 IF(tok==tk_mnemonics)DoMnemonics();
  64.                 ELSE IF(tok==tk_eof)BREAK;
  65.                 ELSE IF(tok==tk_locallabel)DoLocalPost();
  66.                 ELSE IF(tok!=tk_semicolon)preerror("ASM: Bad input format\n");
  67.         }
  68.         lstrcpyA(#string,#s); //востановить
  69.         lstrcpyA(#string2,#s2);
  70.         $POP type,displaytokerrors,endoffile,linenumber,currmod,inptr,input,
  71.                         tok,tok2,number,inptr2,linenum2;
  72.         cha2=holdcha;
  73. }
  74.  
  75. DoLocalPost()
  76. dword i;
  77. {
  78.         tok = tk_number;
  79.         number = outptr-output+OptImageBase+OptBaseOfCode;
  80.         ESI=localptr;
  81.         DSDWORD[ESI+localtok] = tok;
  82.         DSDWORD[ESI+localnumber] = number;
  83.         i=0;
  84.         WHILE(i<posts){
  85.                 ECX=i<<2+postnum;
  86.                 EAX=DSDWORD[ECX];
  87.                 IF(EAX==localptr){
  88.                         DSDWORD[ECX]=number;
  89.                         EBX=i<<2+posttype;
  90.                         DSDWORD[EBX]=POST_LOC;
  91.                 }
  92.                 i++;
  93.         }
  94.         NextTok();
  95.         NextTok();
  96. }
  97.  
  98. // ---- Установка ссылки на пока необъявленный идентификатор
  99. SetPost(dword ref,ptype)
  100. {
  101.         IF(posts >= MAXPOSTS)maxwordpostserror();
  102.         EBX=posts<<2+postloc;
  103.         DSDWORD[EBX] = outptr;
  104.         EBX=posts<<2+postnum;
  105.         DSDWORD[EBX] = ref;
  106.         EBX=posts<<2+posttype;
  107.         DSDWORD[EBX] = ptype;
  108.         posts++;
  109. }
  110.  
  111. // ---- Пропуск до следующей записи в шаблоне инструкции
  112. SCDEND()
  113. {
  114.         $LODSB
  115.         IF(AL!=0){
  116.                 $CMP AL,_END
  117.                 $JNE SCDEND
  118.                 illegaloperand();
  119.                 $POP EAX;       // Выход из MapOperands
  120.         }
  121. }
  122.  
  123. GETSCALING()
  124. {
  125.         NextTok();              // Получим значение масштабного коэффициента
  126.         IF(tok==tk_number){
  127. DoScale:
  128.                 EA_SCALE=number;        // Scale
  129.                 EA_SIBFLAG=1; // Отметим наличие Sib в 32-битном EA
  130.         }
  131.         ELSE preerror("ASM: Illegal scaling value\n");
  132. }
  133.  
  134. // ---- Поиск в шаблоне подходящей к операнду записи (для однооперандной инструкции)
  135. GETOL1()
  136. {
  137.         if(DSBYTE[ESI]!=0){     // Инструкция JMP - не проверяем совпадение размеров
  138. G4:
  139.                 $LODSB
  140.                 AH=AL&NOLBITS;          // Исключим число операндов
  141.                 if(NOTZEROFLAG){// Это все-таки JMP...
  142.                         DL=AL&OPBITS;   // Маска для типа операнда
  143.                         IF(DL!=SOO){    // В поле размера операнда содержится информация о типе операнда?
  144.                                 AL&=OLBITS;     // Выделим количество операндов
  145.                                 IF(AL!=OL1){    // Шаблон для инструкции с одним операндом?
  146. G3:
  147.                                         do{
  148.                                                 $LODSB                  // Просмотрим следующую запись шаблона
  149.                                                 IF(AL==0)GOTO G4;       // Конец записи?
  150.                                         }while(AL!=_END);               // Это конец шаблона?
  151.                                         illegaloperand(); // Нет подходящей записи для такой мнемоники
  152.                                         $POP EAX;
  153.                                         $RET            // Выход из MapOperands
  154.                                 }
  155.         // Обработка записи шаблона
  156. G2:
  157.                                 AL=AH&TRANSBITS;                // Выделим размер операнда
  158.                                 $CMP AL,_D
  159.                                 $JBE G5                 // Операнд м.б. размера: byte, word, dword
  160.                                 $CMP AL,_OW
  161.                                 $JNE J0
  162.                                 OPERANDSIZE=_W;
  163.                                 GOTO G40;
  164. J0:
  165.                                 $CMP AL,_OD;
  166.                                 $JNE J1
  167.                                 OPERANDSIZE=_D;
  168.                                 GOTO G40;
  169. J1:
  170.                                 $CMP AL,NB
  171.                                 $JB G90                 // Операнд м.б. размера WB,DW OR BW.
  172.                                 AL-=NB;                 // Пересчитаем для фиксированных размеров: NB->B,OW->W, AF->D
  173. G90:
  174.                                 $CMP AL,OPERANDSIZE // Размер операнда и размер из шаблона совпали?
  175.                                 $JNE G3                 // Нет - смотрим следующую запись в шаблоне
  176.                                 GOTO G40;               // Размеры совпали - продолжим
  177. G5:
  178.                                 $CMP AL,OPERANDSIZE // Размер операнда и размер из шаблона совпали?
  179.                                 $JA G3                  // Нет - смотрим следующую запись в шаблоне
  180.                                 EBX=0;                  // WBIT/RANDFLAG=0
  181.                                 DL=AL;
  182.                                 AL=OPERANDSIZE;
  183.                                 IF(DL==_B)&&(AL!=_B)BL++;
  184. //                              $CMP DL,_B              // В шаблоне byte?
  185. //                              $JNE G20
  186. //                              $CMP AL,_B              // Операнд byte?
  187. //                              $JE G20
  188. //                              BL++;           // W-бит=TRUE
  189. //G20:
  190.                                 $CMP AL,_W              // В шаблоне word?
  191.                                 $JNE G30
  192.                                 $JA G30
  193.                                 BH++;           // Операнд обязательно д.б. word - требуется префикс RAND
  194. G30:
  195.                                 WBIT=BL;
  196.                                 RANDFLAG=BH;    // Запомним информацию о префиксе и W-бите
  197. G40:
  198.                                 AH&=NTRANSBITS;         // Оставим SOO биты
  199.                         }
  200.                 }
  201.         }
  202.         AL=AH;                  // Возвратим SOO поле
  203. }
  204.  
  205. // ---- Разборка шаблона для двухоперандной инструкции
  206. GETOL2()
  207. {
  208. G7:
  209.         $LODSB                  // Получим байт из шаблона
  210.         AH=AL;
  211.         AL&=OLBITS;     // Выделим число операндов
  212.         $CMP AL,OL2     // Число операндов = 2?
  213.         $JE G8                  // Да - начнем проверку
  214. G9:
  215.         $LODSB                  // Поиск следующей записи в шаблоне
  216.         $OR AL,AL       // Конец записи?
  217.         $JZ G7                  // Да - проверим новую запись
  218.         $CMP AL,_END            // Конец шаблона?
  219.         $JNE G9                 // Смотри дальше иначе - ошибка
  220.         toomuchoperands();
  221.         $POP EAX;
  222.         $RET            // Выход из MapOperands
  223. G8:
  224.         AH&=NOLBITS;            // Исключим число операндов
  225.         AL=AH;
  226.         AL&=TRANSBITS;          // Выделим размер операнда
  227.         $CMP AL,_D
  228.         $JBE G100       // Операнд м.б. размера: byte, word, dword
  229. G94:
  230.         $CMP AL,NB
  231.         $JB J0  //G95           // Операнд м.б. размера WB,DW OR BW.
  232.         AL-=NB; // Пересчитаем для фиксированных размеров: NB->B,OW->W, AF->D
  233. G95:
  234.         $CMP AL,OPERANDSIZE // Размер операнда и размер из шаблона совпали?
  235.         $JNE G9                 // Размеры не совпали - ищем следующую запись
  236.         $JMP G11                        // Размеры совпали - продолжим
  237. J0:
  238.         $CMP OPDESC[0],CO
  239.         $JNE J1
  240.         $CMP AL,WB;
  241.         $JNE J1
  242.         OPCONSTSIZE[0]=_W;
  243.         OPCONSTSIZE[1]=_B;
  244.         GOTO G11;
  245. J1:
  246.         $CMP AL,_DW;
  247.         $JNE J2;
  248.         RANDFLAG=0;
  249.         OPCONSTSIZE[0]=_D;// OPCONSTSIZE[1]=_W;
  250.         GOTO G11;
  251. J2:
  252.         $CMP AL,BW;
  253.         $JNE G95
  254.         OPCONSTSIZE[0]=_B;
  255.         OPCONSTSIZE[1]=_W;
  256.         GOTO G11;
  257. G100:
  258.         $CMP OPERANDSIZE,_D
  259.         $JA NEAR G9             // Размер операнда > dword - на следующую запись
  260.         $CMP OPERANDSIZE,AL
  261.         $JB NEAR G9             // Размеры не совпали - ищем следующую запись
  262.         EBX=0;
  263.         DL=AL;
  264.         AL=OPERANDSIZE;
  265.         $CMP DL,_B              // Размер в шаблоне = byte?
  266.         $JNE G50
  267.         $CMP AL,_B              // Размер операнда = byte?
  268.         $JE G50
  269.         BL++;           // W-бит=TRUE
  270. G50:
  271.         $CMP AL,_W              // В шаблоне word?
  272.         $JNE G60
  273.         $JA G60
  274.         BH++;           // Операнд обязательно д.б. word - требуется префикс RAND
  275. G60:
  276.         WBIT=BL;
  277.         RANDFLAG=BH;
  278. G11:
  279.         AH&=NTRANSBITS;
  280.         AL=AH;  // Возвратим SOO поле
  281. }
  282.  
  283. // ---- Разборка шаблона для трехоперандной инструкции
  284. GETOL3()
  285. {
  286. G12:
  287.         $LODSB
  288.         AH=AL;
  289.         AL&=OLBITS;
  290.         $CMP AL,OL3
  291.         $JE G13
  292. G14:
  293.         $LODSB                  //TRY NEXT ENTRY.
  294.         $OR AL,AL
  295.         $JZ G12
  296.         $CMP AL,_END
  297.         $JNE G14
  298.         toomuchoperands();
  299.         $POP EAX;
  300.         $RET            // Выход из MapOperands
  301. G13:
  302.         AH&=NOLBITS;
  303.         $CMP OPERANDSIZE,_D //DWORD ?
  304.         $JE G15
  305.         $CMP OPERANDSIZE,_W //WORD ?
  306.         $JE G16
  307.         preerror("ASM: This instruction required a WORD/DWORD operand\n");
  308.         $RET
  309. G16:
  310.         RANDFLAG=1;
  311. G15:
  312.         AL=AH&0xE0;
  313. }
  314.  
  315. // ----
  316. CREATE_EA()
  317. {
  318.         EA_M=AL&7;
  319.         EA_X=3;
  320. }
  321.  
  322. // ----
  323. CREATE_R()
  324. {
  325.         EA_R=AL&7;
  326. }
  327.  
  328. // ---- Генеррация ModRM и Sib
  329. GETMODRMBYTE()
  330. {
  331.         DL=EALENGTH;            // Количество регистров в EA
  332.         $OR DL,DL       // Нет регистров в EA?
  333.         $JE NEAR C11            // Да
  334.         $TEST EADESC,_W+_D*8
  335.         $JE NEAR E1                                              // 8-битные регистры нельзя применать в адресе
  336.         $TEST EADESC,_W*8                       // 16-битный регистр?
  337.         $JNE NEAR E4            // 16-битная адресация не разрешена
  338.         GETEADISPX();
  339.         $CMP DH,2
  340.         $JNZ X00
  341.         EAX=opDescInd;
  342.         OPCONSTSIZE[EAX]=_D; // Обязательно 32-битный disp
  343. X00:
  344.         DL--;   // 1 регистр?
  345.         $JNE N1         // нет...
  346.         AL=EADESC&7;
  347.         $CMP EA_SIBFLAG,1 // Флаг наличия Sib в 32-битном EA
  348.         $JNE L2                 // Нет Sib
  349.         EA_R2=5;                // Фиксируем базовый регистр
  350.         EA_M=4;
  351.         EA_I=AL;
  352.         EDX=opDescInd;
  353.         $CMP OPCONSTFLAG[EDX],1 // Используем disp?
  354.         $JE L1
  355.         EAX=0;
  356.         OPCONSTFLAG[EDX]=1;
  357.         EDX<<=2;
  358.         OPCONST[EDX]=EAX; // disp=0 в EA
  359. L1:
  360.         EDX=opDescInd;
  361.         OPCONSTSIZE[EDX]=_D;
  362.         EA_X=0; //EA_X=AL;
  363.         $RET
  364. L2:
  365.         EA_M=AL;
  366.         $RET
  367. N1:
  368.         EA_M=4;                                         //2 REGISTERS USED.
  369.         EA_SIBFLAG=1;
  370.         AL=EADESC[1]>>3;
  371.         $CMP AL,_W
  372.         $JE E5                                                                  //ERROR: INDEX REGISTER ISN'T OF SIZE DWORD
  373.         AL=EADESC;
  374.         AH=EADESC[1];
  375.         EAX&=0x707;
  376.         $CMP AH,5                                                        //CAN'T USE BP AS INDEX.
  377.         $JE E6
  378.         EA_R2=AL;
  379.         EA_I=AH;
  380.         $RET
  381. E1:
  382.         preerror("ASM: You can't use byte registers in addresses\n");
  383.         $RET
  384. E4:
  385.         preerror("ASM: 16-bit addressing mode not allowed\n");
  386.         $RET
  387. E5:
  388.         preerror("ASM: You must use a 32-bit registers for scaling\n");
  389.         $RET
  390. E6:
  391.         preerror("ASM: You can't use EBP as an index\n");
  392.         $RET
  393. C11:
  394.         EA_X=0;
  395.         EA_M=5;
  396.         ECX=opDescInd;
  397.         AL=OPCONSTSIZE[ECX];
  398.         IF(AL==_B)OPCONSTSIZE[ECX]=_D;
  399.         ELSE IF(AL==_W)ADDRFLAG=1;
  400. }
  401.  
  402. // ----
  403. GETEADISPX()
  404. {                                                                        //CREATE X NIBBLE OF DISPLACEMENT SIZE.
  405.         DH=0;
  406.         $PUSH ECX
  407.         ECX=opDescInd;
  408.         IF(OPCONSTFLAG[ECX]==1){
  409.                 AL=OPCONSTSIZE[ECX];
  410.                 DH=2;   //(D)WORD DISPLACEMENT
  411.                 IF(AL==_B)DH--;                                                                  //SBYTE DISPLACEMENT
  412.         }
  413.         EA_X=DH;
  414.         $POP ECX
  415. }
  416.  
  417. // ---- Инициализация буфера ассемблера
  418. INIT_LINE()
  419. {
  420.         ECX=#opDescInd-#OPERANDSIZE;
  421.         AL=0;
  422.         EDI=#OPERANDSIZE;
  423.         $REP $STOSB;
  424.         AL=255;
  425.         OPERANDSIZE=AL;
  426.         SEGREGISTER=AL;
  427. }
  428.  
  429. // ---- Запись переопределения сегмента
  430. WRITEOVERRIDE()
  431. {
  432.         EBX=OVERRIDE;
  433.         IF(BL!=0){
  434.                 AL=OVERRIDETAB[EBX]-rES;
  435.                 OP();
  436.         }
  437. }
  438.  
  439. // ---- Запись префикса размерности операнда
  440. WRITERAND()
  441. {
  442.         $PUSH EAX
  443.         IF(RANDFLAG==1){
  444.                 AL=0x66;
  445.                 OP();
  446.         }
  447.         $POP EAX
  448. }
  449.  
  450. // ---- Запись константы: CL=TYPE; EDI указатель на значение
  451. WRITECONST()
  452. {
  453.         IF(CL==_B)CL=1;
  454.         ELSE IF(CL==_W)CL=2;
  455.         ELSE IF(CL==_D)CL=4;
  456.         ELSE CL++;
  457.         loop(ECX){
  458.                 AL=DSBYTE[EDI];
  459.                 EDI++;
  460.                 OP();
  461.         }
  462. }
  463.  
  464. // ---- Обработка Override
  465. GETOVERRIDE()
  466. {
  467.         IF(tok==tk_seg)&&(tok2==tk_colon){
  468.                 IF(OVERRIDE==0){
  469.                         OVERRIDE=number;
  470.                         $STC    // ∙ сегментного регистра
  471.                 }
  472.                 ELSE preerror("ASM: Double segment override");
  473.                 NextTok();
  474.                 NextTok();      // Пропускаем :
  475.         }
  476. }
  477.  
  478. // ---- Вычисление размера операнда: _B,_W,_D,WB,_DW & RAND-FLAG. AL=SIZE
  479. DEF_OPSIZE()
  480. {
  481.         AH=OPERANDSIZE;
  482.         IF(AH==255){
  483.                 OPERANDSIZE=AL; // Один операнд
  484.                 return;
  485.         }
  486.         IF(AH==AL)return;       // Размеры совпадают
  487.         IF(AX==0X100){  // RW,RB ?
  488.                 RANDFLAG=1;// OPERANDSIZE=WB;
  489.                 return;
  490.         }
  491.         IF(AX==0X200){  // RD,RB ?
  492.                 IF(ACTUALMNEMDESC==#PCOMMANDS3_){
  493. //      OPERANDSIZE=_D;
  494.                         return;
  495.                 }
  496.                 OPERANDSIZE=WB;
  497.                 return;
  498.         }
  499.         IF(AX==0X201){  //RD,RW
  500.                 RANDFLAG=1;
  501.                 OPERANDSIZE=_DW;
  502.         }
  503. }
  504.  
  505. // ---- Запись префикса адресации
  506. WRITEADDR()
  507. {
  508.         $PUSH EAX
  509.         IF(ADDRFLAG==1){
  510.                 AL=0x67;
  511.                 OP();
  512.         }
  513.         $POP EAX
  514. }
  515.  
  516. // ---- Определение размерности константы
  517. DefConstSize()
  518. {               // Определим размерность константы
  519.         EBX=opDescInd;
  520.         DL=_D;
  521.         IF(OPPOST[EBX]==0){
  522.                 EBX=opDescInd<<2;
  523.                 EAX=OPCONST[EBX];
  524.                 DL=_B;                  // byte
  525.                 IF(long EAX>=-128){ // -128
  526.                         $CMP EAX,0XFF   // 255
  527.                         $JNG W2
  528.                 }
  529.                 DL++;           // _W - word
  530.                 IF(long EAX>=-32768){
  531.                         $CMP EAX,0XFFFF         // 65535
  532.                         $JNG W2
  533.                 }
  534.                 DL++;           // _D - dword
  535.         }
  536. W2:
  537.         EBX=opDescInd;
  538.         OPCONSTSIZE[EBX]=DL;
  539.         OPCONSTFLAG[EBX]=1;
  540. }
  541.  
  542. // ---- Обработка мнемоники ассемблера
  543. DoMnemonics()
  544. {
  545.         opDescInd=0;
  546.         EADescInd=0;
  547.         INIT_LINE();    // Очистка буферов
  548.         IF(number<24){
  549.                 IF(number<8)EBX=#PCOMMANDS1;
  550.                 ELSE IF(number<12){
  551.                         number-=8;
  552.                         EBX=#PCOMMANDS2;
  553.                 }
  554.                 ELSE IF(number<20){
  555.                         number-=12;
  556.                         EBX=#PCOMMANDS3;
  557.                 }
  558.                 ELSE{
  559.                         number-=20;
  560.                         EBX=#PCOMMANDS4;
  561.                 }
  562.                 number+=DSBYTE[EBX];
  563.                 PFLAG=number;
  564.                 EBX++;
  565.         }
  566.         ELSE{
  567.                 number-=24;
  568.                 EBX=number<<2;
  569.                 EBX=TAB_MNEMONICS[EBX];
  570.                 IF(EBX>=#T_DAA)&&(EBX<#T_NOT){  // Проверим на наличие инструкции без операндов
  571.                         ACTUALMNEMDESC=EBX;
  572.                         IF(tok2==tk_semicolon)NextTok();
  573.                         ESI=ACTUALMNEMDESC;
  574.                         $JMP CreateCode;// Генерация кода для инструкции без операндов
  575.                 }
  576.         }
  577.         ACTUALMNEMDESC=EBX;     // Запомним указатель на текущий шаблон мнемоники
  578.         for(;;){                // Цикл анализа операндов
  579.                 prevTok=tok;
  580.                 NextTok();              // Следующий операнд
  581.                 FastSearch(#string,#St_Sizes);// Это размер операнда?
  582.                 IF(CARRYFLAG){  // Да: byte,word или dword
  583.                         OPERANDSIZE=AL; // Запомним _B,_W,_D
  584.                         continue;
  585.                 }
  586.                 GETOVERRIDE();  // Обработка конструкции SEG:
  587. ContLine:       // Точка для продолжения обработки текущего
  588.                 IF(tok==tk_eof)||(tok==tk_semicolon){
  589.                         EBX=opDescInd;
  590.                         IF(OPDESC[EBX]==E){ // Обработка в EA?
  591.                                 DefConstSize();
  592.                                 GETMODRMBYTE(); // EOL - GENERATE MODRM OPCODE BYTE.
  593.                         }
  594.                         IF(prevTok!=tk_mnemonics){              // Были операнды
  595.                                 OPLENGTH++;
  596.                                 IF(OPERANDSIZE==255){
  597.                                         OPERANDSIZE=_D;         // Принудительно установим dword
  598.                                 }
  599.                         }
  600.                         $JMP MapOperands
  601.                 }
  602.                 else IF(tok==tk_comma){
  603.                         IF(opDescInd==3){
  604.                                 toomuchoperands();
  605.                                 break;
  606.                         }
  607.                         EBX=opDescInd;
  608.                         IF(OPDESC[EBX]==E){ // Обработка в EA?
  609.                                 DefConstSize();
  610.                                 GETMODRMBYTE(); // EOL - GENERATE MODRM OPCODE BYTE.
  611.                         }
  612.                         opDescInd++;
  613.                         OPLENGTH++;
  614.                 }
  615.                 else IF(tok==tk_openblock){
  616.                         EBX=opDescInd;
  617.                         OPDESC[EBX]=E;  // Отметим, что работаем с EA операндом
  618.                 }
  619.                 else IF(tok==tk_closeblock){    // ]
  620.                         DefConstSize();
  621.                         GETMODRMBYTE(); // EOL - GENERATE MODRM OPCODE BYTE.
  622.                 }
  623.                 else IF(tok==tk_minus){
  624.                         IF(tok2 == tk_number){
  625.                                 NextTok();
  626.                                 number = -number;
  627.                                 $JMP ContLine;  // Продолжим docase без выборки след.token
  628.                         }
  629.                 }
  630.                 else IF(tok==tk_plus) continue;
  631.                 else IF(tok==tk_mult){          // *
  632.                         GETSCALING(); // Указан масшаб в Sib
  633.                 }
  634.                 else if(tok==tk_reg){ // Обработка регистра
  635. G0:
  636.                         EBX=opDescInd;
  637.                         IF(OPDESC[EBX]==E){ // Обработка в EA?
  638.                                 IF(type==tk_byte){
  639.                                         preerror("ASM: No byte register in address\n");
  640.                                         return;
  641.                                 }
  642.                                 IF(EALENGTH<2){ // Количество регистров в EA < 2 ?
  643.                                         EALENGTH++; // Отметим, что есть еще один регистр в EA
  644.                                         EBX=EADescInd;
  645.                                         EADESC[EBX]=number; // Запомним ∙ регистра
  646.                                         EADescInd++;
  647.                                 }
  648.                                 ELSE{   // Слишком много регистров в EA
  649.                                         preerror("ASM: too much registers in combination\n");
  650.                                         return;
  651.                                 }
  652.                         }
  653.                         ELSE{
  654.                                 OPDATA[EBX]=number; // ∙ регистра
  655.                                 OPDESC[EBX]=R;
  656.                                 AH=number&7;
  657.                                 EA_R=AH;
  658.                                 IF(opDescInd!=2){
  659.                                         AL>>=3;
  660.                                         DEF_OPSIZE();
  661.                                 }
  662.                         }
  663.                 }
  664.                 else IF(tok==tk_number) { // Обработка константы
  665.                         IF(tok2==tk_mult){
  666.                                 DoScale();
  667.                                 NextTok();
  668.                                 continue;
  669.                         }
  670. NUM:
  671.                         EBX=opDescInd<<2;
  672.                         OPCONST[EBX]+=number; // Запомним константу
  673.                         DefConstSize();         // Определим размерность константы
  674.                         IF(OPDESC[EBX]!=E)              // Константа в EA?
  675.                                 OPDESC[EBX]=CO;
  676.                 }
  677.                 else IF(tok==tk_postnumber){
  678.                         EBX=opDescInd;
  679.                         OPPOST[EBX]=POST_DATA;
  680.                         EBX<<=2;
  681.                         OPPOSTREF[EBX]=treeptr;
  682.                         ESI=treeptr;
  683.                         DSDWORD[ESI+recpost]++;
  684.                         GOTO NUM;
  685.                 }
  686.                 else IF(tok==tk_proc){
  687.                         IF(post){
  688.                                 EBX=opDescInd;
  689.                                 OPPOST[EBX]=POST_CALL;
  690.                                 EBX<<=2;
  691.                                 OPPOSTREF[EBX]=treeptr;
  692.                                 ESI=treeptr;
  693.                                 DSDWORD[ESI+recpost]++;
  694.                         }
  695.                         $JMP NUM
  696.                 }
  697.                 else IF(tok==tk_locallabel){
  698.                         EBX=opDescInd<<2;
  699.                         OPPOSTREF[EBX]=localptr;
  700. I2:
  701.                         EBX=opDescInd;
  702.                         $CMP ACTUALMNEMDESC,#T_JCXZ;
  703.                         $JB I1
  704.                         $CMP ACTUALMNEMDESC,#T_CALLFAR;
  705.                         $JA I1
  706.                         OPPOST[EBX]=POST_CALL;
  707.                         $JMP NUM
  708. I1:
  709.                         OPPOST[EBX]=POST_DATA;
  710.                         AL=_D;
  711.                         DEF_OPSIZE();
  712.                         $JMP PARSE_EA1
  713.                 }
  714.                 else IF(tok==tk_undefproc){
  715. I0:
  716.                         EBX=opDescInd<<2;
  717.                         OPPOSTREF[EBX]=treeptr;
  718.                         GOTO I2;
  719.                 }
  720.                 else IF(tok==tk_id){
  721.                         tok = tk_undefproc;
  722.                         post = 1;
  723.                         number=0;
  724.                         AddToTree(#string);
  725.                         GOTO I0;
  726.                 }
  727.                 else IF(tok==tk_var){ // Инициализация EA с константой: EA+disp
  728.                         AL=type-tk_byte>>1; // AL=размер адресуемого операнда (_B,_W,_D)
  729.                         DEF_OPSIZE();
  730.                         EBX=opDescInd;
  731.                         IF(post){
  732.                                 EBX<<=2;
  733.                                 OPPOSTREF[EBX]=treeptr;
  734.                                 EBX=opDescInd;
  735.                                 OPPOST[EBX]=POST_DATA;
  736.                                 ESI=treeptr;
  737.                                 DSDWORD[ESI+recpost]++;
  738.                         }
  739. PARSE_EA1:
  740.                         OPDESC[EBX]=E;
  741.                         OPCONSTFLAG[EBX]=1; // Отметим, что работаем с EA операндом
  742.                         EBX<<=2;
  743.                         OPCONST[EBX]+=number; // Запомним адрес
  744.                 }
  745.                 else IF(tok==tk_seg){
  746.                         EBX=opDescInd;
  747.                         OPDATA[EBX]=number-rES; // ∙ сегментного регистра
  748.                         SEGREGISTER=AL;
  749.                         AL<<=3; // Создать код для XSM поля
  750.                         EA_S=AL;
  751.                         OPDESC[EBX]=_SR;
  752.                         AL=_W;
  753.                         DEF_OPSIZE();
  754.                 }
  755.                 else IF(tok==tk_param)||(tok==tk_local){
  756. PARSE_PAR:
  757.                         AL=type-tk_byte>>1;
  758.                         DEF_OPSIZE();
  759.                         EBX=opDescInd;
  760.                         OPDESC[EBX]=E;
  761.                         EBX<<=2;        // Отметим, что работаем с EA операндом
  762.                         OPCONST[EBX]+=number; // Запомним адрес
  763.                         OPCONSTFLAG[EBX]=1;
  764.                         number=rEBP;
  765.                         $JMP G0;
  766.                 }
  767.                 else IF(tok==tk_controlreg){
  768.                         EBX=opDescInd;
  769.                         OPDESC[EBX]=SYSR;
  770.                         SYSRNUM=number;
  771.                         IF(AL==4)SYSRTYPE=_CR4;
  772.                         ELSE{
  773.                                 SYSRTYPE=_CR;
  774.                                 SYSRCODE=0;
  775.                         }
  776.                 }
  777.                 ELSE IF(tok==tk_debugreg){
  778.                         EBX=opDescInd;
  779.                         OPDESC[EBX]=SYSR;
  780.                         SYSRNUM=number;
  781.                         SYSRTYPE=_DR;
  782.                         SYSRCODE=1;
  783.                 }
  784.                 ELSE IF(tok==tk_testreg){
  785.                         EBX=opDescInd;
  786.                         OPDESC[EBX]=SYSR;
  787.                         SYSRNUM=number;
  788.                         SYSRTYPE=_TR;
  789.                         SYSRCODE=4;
  790.                 }
  791.                 ELSE preerror("ASM: Syntax error\n");
  792.         }
  793. }
  794.  
  795. CreateScale()
  796. {
  797.         IF(ADDRFLAG)return;
  798.         if(EA_SIBFLAG){         // Флаг наличия Sib в 32-битном EA
  799.                 IF(EA_SCALE==0){        // Отсутствует
  800.                         EA_SCALING=0;
  801.                  }
  802.                 else IF(EA_SCALE==1)EA_SCALING=0;
  803.                 else IF(EA_SCALE==2)EA_SCALING=0x40;
  804.                 ELSE IF(EA_SCALE==4)EA_SCALING=0x80;
  805.                 ELSE IF(EA_SCALE==8)EA_SCALING=0xC0;
  806.                 ELSE{
  807.                         EA_SCALING=0;
  808.                         IF(EA_SCALE>255)OP(byte 0x69);
  809.                         ELSE OP(byte 0x6B);
  810.                         AL=EA_I<<3|EA_I|0xC0;
  811.                         OP(byte AL);
  812.                         IF(EA_SCALE>255)OUTDWORD(EA_SCALE);
  813.                         ELSE OP(byte EA_SCALE);
  814.                 }
  815.         }
  816. }
  817.  
  818. // ---- Генерация кода. ESI=ptr на запись о описание мнемоники (запись типа T_...)
  819. CreateCode()
  820. {
  821.         WRITEOVERRIDE();
  822.         CreateScale();
  823.         IF(ADDRFLAG==1){        //ADDR: PREFIX ?
  824.                 OP(byte 0x67);
  825.         }
  826.         IF(RANDFLAG==1){        //RAND: PREFIX ?
  827.                 OP(byte 0x66);
  828.         }
  829.         EDI=ESI;
  830.         IF(ACTUALMNEMDESC==#T_TEST)DBIT=0;      //DON'T ADD ANYTHING IF TESTING
  831.         $SHL DBIT,1                      //SHIFT D-BIT TO THE RIGHT POSITION.
  832. NEXT_DESC_BYTE:         // Обработка байта из дескриптора мнемоники
  833.         EBX=0;
  834.         BL=DSBYTE[EDI];
  835.         EDI++;
  836. NB3:
  837.         $CMP BL,X7M
  838.         $JA NC3
  839.         $CMP BL,X0M
  840.         $JB N24
  841.         AH=BL-X0M;
  842.         AL=EA_X<<3|AH<<3|EA_M;
  843.         OP();
  844.         GOTO NEXT_DESC_BYTE;
  845. N24:
  846.         EBX<<=2;
  847.         EBX+=#Dsc_Jump;
  848.         $JMP NEAR DSDWORD[EBX]
  849. NC3:
  850.         $CMP BL,_END
  851.         $JNE E42
  852.         $JMP CreateConstants    // Конец шаблона для мнемоники
  853. E42:
  854.         preerror("Descriptor damaged\n");
  855.         return;
  856. // OpCode - 1 байт
  857. Dsc_O:
  858.         AL=DSBYTE[EDI]+WBIT+DBIT;
  859.         EDI++;
  860.         OP();
  861.         GOTO NEXT_DESC_BYTE;
  862. // OpCode - 1 слово
  863. Dsc_OW:
  864.         AL=DSBYTE[EDI];
  865.         EDI++;
  866.         OP();
  867.         AL=DSBYTE[EDI]+WBIT+DBIT;
  868.         EDI++;
  869.         OP();
  870.         $JMP NEXT_DESC_BYTE
  871. // OpCode - 1 байт и следующий байт, заданный 8-ричной строкой
  872. Dsc_OS:
  873.         AL=DSBYTE[EDI];
  874.         EDI++;
  875.         OP();
  876. // OpCode - 8-ричная строка с кодом
  877. Dsc_S:
  878. S01:
  879.         CL=3;
  880.         EAX=0;
  881.         loop(CL){
  882.                 AL=DSBYTE[EDI];
  883.                 EDI++;
  884.                 IF(AL=='X'){            //X CHAR
  885.                         AL=EA_X;
  886.                 }
  887.                 ELSE IF(AL=='R')AL=EA_R;
  888.                 ELSE IF(AL=='M')AL=EA_M;
  889.                 ELSE IF(AL=='S')AL=SEGREGISTER;
  890.                 ELSE IF(AL=='N')AL=SYSRNUM;
  891.                 ELSE IF(AL=='P')AL=PFLAG;
  892.                 ELSE AL-='0';
  893.                 AH=AH<<3|AL;
  894.         }
  895.         AL=AH+DBIT+WBIT;
  896. N15:
  897.         OP();
  898.         $JMP NEXT_DESC_BYTE
  899. // OpCode - ModRM байт
  900. Dsc_XRM:
  901.         AL=EA_X<<3|EA_R<<3|EA_M;                // Получить регистр из описания мнемоники
  902.         GOTO N15;
  903. // OpCode - ModRM с P-флагом (арифметические инструкции)
  904. Dsc_XPM:
  905.         AL=EA_X<<3|PFLAG<<3|EA_M;
  906.         GOTO N15;
  907. // OpCode - ModRM с сегментным регистром
  908. Dsc_XSM:
  909.         AL=EA_X<<3|SEGREGISTER<<3|EA_M;
  910.         GOTO N15;
  911. //      JMP NEXT_DESC_BYTE
  912. }
  913.  
  914. // ---- Разбор закончен -> на генерацию кода по шаблону
  915. MapOperands()
  916. {
  917. //      AL=0; WBIT=AL; DBIT=AL;
  918.         opDescInd=0;
  919.         ESI=ACTUALMNEMDESC; // Указатель на информацию по генерации
  920.         AL=OPLENGTH;            // Количество операндов
  921.         ECX=#OPDESC;            // Указатель на информацию об операндах
  922.         ECX=DSDWORD[ECX];
  923.         IF(ESI!=#T_MOV){                // Инструкция MOV?
  924.                 IF(AL!=0){
  925.                         $CMP AL,1
  926.                         $JE NEAR ONEOP          // Инструкция с одним операндом
  927.                         $CMP AL,2
  928.                         $JE NEAR TWOOPS         // Инструкция с двумя операндами
  929.                         $CMP AL,3
  930.                         $JE NEAR THREEOPS // Инструкция с тремя операндами
  931.                         toomuchoperands();
  932.                         return;
  933.                 }
  934. // ---- Инструкция без операндов
  935.                 do{
  936.                         $LODSB
  937.                         IF(AL==0)goto CreateCode;       // Генерация кода
  938.                 }while(AL!=_END);
  939.                 preerror("ASM: Operand required\n");
  940.                 return;
  941. // ---- Генерация MOV инструкции
  942.         }
  943.         $PUSH EAX,ECX
  944.         WRITEOVERRIDE();
  945.         CreateScale();
  946.         $POP ECX,EAX
  947.         IF(AL!=2){              // 2 OPERANDS IN INSTRUCTION?
  948.                 preerror("ASM: Two operands required\n");
  949.                 return;
  950. L2:
  951.                 preerror("ASM: Not same size\n");
  952.                 return;
  953.         }
  954. L1:
  955.         BL=0;
  956.         AL=OPERANDSIZE;
  957.         IF(AL!=_D){
  958.                 $CMP AL,_W
  959.                 $JA L2
  960.                 $JNE N4
  961.                 RANDFLAG=1;
  962.         }
  963.         BL=1;
  964. N4:
  965.         WBIT=BL;                //STORE W-BIT
  966.         DL=0;   //CLEAR D-BIT
  967.         WRITEADDR();
  968.         EBX=0;
  969.         BL=CL;
  970.         EBX=EBX<<2+#Jmp_Mov;
  971.         $JMP NEAR DSDWORD[EBX]
  972. Mov_ERR:
  973.         preerror("ASM: a constant can't be used as a destination\n");
  974.         return;
  975. Mov_R:
  976.         EBX=0;
  977.         BL=CH;
  978.         EBX=EBX<<2+#Jmp_Mov_R;
  979.         $JMP NEAR DSDWORD[EBX]
  980. Mov_E:
  981.         EBX=0;
  982.         BL=CH;
  983.         EBX=EBX<<2+#Jmp_Mov_E;
  984.         $JMP NEAR DSDWORD[EBX]
  985. Mov_R2R:
  986.         WRITERAND();
  987.         AL=OPDATA[1];
  988.         AH=OPDATA[0];
  989.         DL=DBIT;
  990.         $PUSH EAX
  991.         AL=0o210+WBIT;
  992.         $SHL DL,1
  993.         AL+=DL;         //D-BIT
  994.         OP();
  995.         $POP EAX
  996.         AL=AL&7<<3;
  997.         AH&=7;
  998.         AL=AL|AH|0o300;
  999.         OP();
  1000.         $JMP CreateConstants
  1001. Mov_R2E:
  1002.         AL=OPDATA&7;    //AL/AX/EAX ?
  1003.         $OR AL,AL
  1004.         $JNE N1
  1005.         $CMP EA_M,6 //AR,[DW] POSSIBLE?
  1006.         $JNE N1                 //NO, ONLY AR,[EA]
  1007.         $CMP ADDRFLAG,0 //32BIT-EA ?
  1008.         $JE N1          //NO, TRY ANOTHER...
  1009.         WRITERAND();
  1010.         AL=0o240+WBIT;  //INSTRUCTION FOUND.
  1011.         OP();
  1012.         $JMP CreateConstants
  1013. Mov_E2R:
  1014. D1:
  1015.         AL=OPDATA[1]&7; //[DW],AR POSSIBLE?
  1016.         $OR AL,AL
  1017.         $JNE Y1
  1018.         $CMP ADDRFLAG,0 //32BIT EA ?
  1019.         $JNE Y1                 //YES, RAVE ON...
  1020.         $CMP EA_M,6
  1021.         $JNE Y1
  1022.         WRITERAND();
  1023.         AL=0o242+WBIT;          //INSTRUCTION FOUND.
  1024.         OP();
  1025.         $JMP CreateConstants
  1026. N1:
  1027.         DL=2;   //SET D-BIT
  1028. Y1:
  1029.         DL+=0o210;
  1030.         WRITERAND();
  1031.         AL=DL;
  1032.         DL=0;
  1033.         AL+=WBIT;
  1034.         OP();
  1035.         AL=EA_X<<3|EA_R<<3|EA_M;
  1036.         OP();
  1037.         $JMP CreateConstants
  1038. E1:
  1039.         preerror("ASM: Not same size\n");
  1040.         return;
  1041. //EA,CONSTANT ?
  1042. Mov_E2C:
  1043.         OPCONSTSIZE[1]=OPERANDSIZE;
  1044.         $CMP AL,_D
  1045.         $JA E1
  1046.         $JE X1
  1047.         $CMP AL,_W
  1048.         $JNE X1
  1049.         AL=0x66;
  1050.         OP();
  1051. X1:
  1052.         AL=0o306+WBIT;
  1053.         OP();
  1054.         AL=EA_X<<6|EA_M;
  1055.         OP();
  1056.         $JMP CreateConstants
  1057. Mov_R2C:
  1058.         OPCONSTSIZE[1]=OPERANDSIZE;
  1059.         $CMP OPERANDSIZE,_B
  1060.         $JNE N2
  1061.         AL=OPDATA&7|0o260;
  1062.         OP();
  1063.         $JMP CreateConstants
  1064. N2:
  1065.         $CMP OPERANDSIZE,_D              //BYTE, WORD OR DWORD?
  1066.         $JA NEAR E1     // Not same size
  1067.         IF(OPERANDSIZE==_W){
  1068.                 AL=0x66;
  1069.                 OP();
  1070.         }
  1071.         AL=OPDATA&7|0o270;
  1072.         OP();
  1073.         $JMP CreateConstants
  1074. E21:
  1075.         preerror("ASM: Word required\n");
  1076.         return; //SEGMENT REGISTER IS ALWAYS WORD.
  1077. Mov_S:
  1078.         AL=0;
  1079.         $CMP CX,_SR*256+E // mov EA,segreg
  1080.         $JE O1
  1081.         $CMP CX,_SR*256+R // mov segreg,reg
  1082.         $JE O2
  1083.         $CMP CX,R*256+_SR // mov reg,segreg
  1084.         $JE O3
  1085.         $CMP CX,E*256+_SR // mov segreg,EA
  1086.         $JNE NEAR N12
  1087.         AL=2;           //SET D-BIT
  1088. O1:
  1089.         $CMP OPERANDSIZE,_W
  1090.         $JNE E21
  1091.         AL+=0o214;
  1092.         OP();
  1093.         AL=EA_X<<6|EA_S|EA_M;
  1094.         OP();
  1095.         $JMP CreateConstants
  1096. O2:
  1097.         $CMP OPERANDSIZE,_W
  1098.         $JNE E21
  1099.         AL=0o214;
  1100.         OP();
  1101.         AL=EA_S|0o300|EA_R;      //CREATE XSM BYTE
  1102.         OP();
  1103.         $STC
  1104.         $RET
  1105. O3:
  1106.         $CMP OPERANDSIZE,_W
  1107.         $JNE NEAR E21
  1108.         AL=0o216;
  1109.         OP();
  1110.         AL=EA_S|0o300|EA_R;
  1111.         OP();
  1112.         $STC
  1113.         $RET
  1114. E31:
  1115.         preerror("ASM: CR1 only readable\n");
  1116.         $RET
  1117. E32:
  1118.         preerror("ASM: SysR must be dword\n");
  1119.         $RET
  1120. Mov_SYSR:
  1121. N12:
  1122.         AH=0o40;
  1123.         $CMP CX,SYSR*256+R
  1124.         $JE O11
  1125.         $CMP CX,R*256+SYSR
  1126.         $JNE N22                //ERROR: ILLEGAL OPERANDS
  1127.         AH=0o42;
  1128.         $CMP SYSRTYPE,_CR //CR1 REGISTER USED?
  1129.         $JNE O11
  1130.         $CMP SYSRNUM,1
  1131.         $JE E31                 //YES, ONLY READ FROM IT.
  1132. O11:
  1133.         AH+=SYSRCODE;
  1134.         $CMP OPERANDSIZE,_D //SYSTEM REGISTERS ARE ALWAYS DWORD.
  1135.         $JNE E32
  1136.         AL=0o17;
  1137.         OP();
  1138.         $CMP SYSRTYPE,_CR4      //EXCEPTION: CR4
  1139.         $JE N22
  1140.         AL=AH;
  1141.         OP();
  1142.         AL=SYSRNUM<<3|0o300|EA_R; //CREATE 3NR OPCODE
  1143.         OP();
  1144.         $STC
  1145.         $RET
  1146. N22:
  1147.         $CMP CX,SYSR*256+R
  1148.         $JNE N32
  1149.         AL=0x22;
  1150.         OP();
  1151.         GOTO L11;
  1152. N32:
  1153.         AL=0x20;
  1154.         OP();
  1155. L11:
  1156.         AL=0o340|EA_R;
  1157.         OP();
  1158.         $STC
  1159.         $RET
  1160. // ---- Инструкция с одним операндом
  1161. ONEOP:
  1162.         EBX=CL<<2+#Jmp_Op1;
  1163.         $JMP NEAR DSDWORD[EBX]
  1164. Op1ERR:
  1165.         preerror("ASM: only use system registers within MOV instruction\n");
  1166.         $RET
  1167. // RX
  1168. L31:
  1169.         SCDEND();
  1170. Op1R:
  1171.         GETOL1();       //GET FIRST GENERATION INFO.
  1172.         $CMP AL,SOR     //SINGLE OPERAND/REGISTER ?
  1173.         $JNE X23
  1174.         $JMP CreateCode
  1175. X23:
  1176.         $CMP AL,SOE     //CONVERT REGISTER INTO EFFECTIVE ADDRESS?
  1177.         $JNE L31
  1178. C2:
  1179.         EA_X=3;
  1180.         AL=EA_R;
  1181.         EA_M=AL;
  1182.         $JMP CreateCode
  1183. // EA
  1184. L41:
  1185.         SCDEND();
  1186. Op1E:
  1187.         GETOL1();
  1188.         $CMP AL,SOE     //SINGLE OPERAND/EFFECTIVE ADDRESS ?
  1189.         $JNE X24;
  1190.         $JMP CreateCode
  1191. X24:
  1192.         $CMP AL,SOM     //SINGLE OPERAND/MEMORY POINTER ?
  1193.         $JNE L41
  1194.         $CMP EA_X,0
  1195.         $JNE L41
  1196.         $CMP EA_M,6     //[WORD CONSTANT]?
  1197.         $JNE L41
  1198. C11:
  1199.         $JMP CreateCode
  1200. // CO
  1201. L51:
  1202.         SCDEND();
  1203. Op1C:
  1204.         GETOL1();
  1205.         $OR AL,AL       //JUMP INSTRUCTION?
  1206.         $JNE NEAR N13
  1207. // Здесь обработка call&jmp
  1208.         ECX=OPCONST[0]-OptImageBase-OptBaseOfCode-outptr+output;        // Расчет относительного смещения
  1209.         $LODSB          // Получим short или near
  1210.         $CMP AL,_JB // short?
  1211.         $JNE N14
  1212.         ECX-=2;
  1213.         $CMP ECX,0xFFFFFF80
  1214.         $JL L10
  1215.         $CMP ECX,0x7F
  1216.         $JG L10
  1217.         OPCONSTSIZE[0]=_B;
  1218. H1:
  1219.         OPCONST[0]=ECX;
  1220.         $JMP CreateCode
  1221. N14:
  1222.         EAX=0;
  1223.         $LODSB          // Поправка на размер call или jmp
  1224.         ECX-=EAX;
  1225.         OPCONSTSIZE[0]=_D;
  1226.         GOTO H1;
  1227. L10:
  1228.         $CMP ACTUALMNEMDESC,#T_JCXZ
  1229.         $JB L51
  1230.         $CMP ACTUALMNEMDESC,#T_LOOP
  1231.         $JA NEAR L51
  1232.         preerror("ASM: Jump range too long\n");
  1233.         $RET
  1234. N13:
  1235.         $CMP AL,SO3     //CONSTANT VALUE 3 ?
  1236.         $JNE N23
  1237.         $CMP OPCONST[0],3
  1238.         $JNE NEAR L51
  1239.         OPCONSTFLAG[0]=0; //YES, AVOID CONSTANT GENERATION.
  1240.         $JMP CreateCode
  1241. N23:
  1242.         $CMP AL,SOC     //SINGLE OPERAND/CONSTANT?
  1243.         $JNE X25
  1244.         OPCONSTSIZE[0]=OPERANDSIZE;
  1245.         $JMP CreateCode
  1246. X25:
  1247.         $CMP AL,SOO_CC          //SINGLE OPERAND/SIGNED BYTE ?
  1248.         $JNE NEAR L51
  1249.         IF(OPPOST[0])$JMP L51
  1250.         $CMP OPCONST[0],0x7F
  1251.         $JG NEAR L51
  1252.         $CMP OPCONST[0],0xFFFFFF80
  1253.         $JL NEAR L51
  1254.         OPCONSTSIZE[0]=_B;
  1255.         $JMP CreateCode
  1256. // SR
  1257. L61:
  1258.         SCDEND();
  1259. Op1S:
  1260.         GETOL1();
  1261.         $CMP AL,SOS     //SINGLE OPERAND/SEGMENT REGISTER?
  1262.         $JNE L61
  1263.         $JMP CreateCode
  1264. // AF
  1265. L71:
  1266.         SCDEND();
  1267. Op1AF:
  1268.         GETOL1();
  1269.         $CMP AL,SOO_AF
  1270.         $JNE L71
  1271.         $JMP CreateCode
  1272. // ---- Инструкция с двумя операндами
  1273. TWOOPS:
  1274.         EBX=CL<<2+#Jmp_Op2;
  1275.         $JMP NEAR DSDWORD[EBX]          // Переход по типу первого операнда
  1276. //Op2ERRC:
  1277. //      preerror("ASM: A constant can't be used as a destination\n");
  1278. //      return;
  1279. Op2ERRS:
  1280.         preerror("ASM: segment register can only be used within a MOV or PUSH\n");
  1281.         return;
  1282. Op2ERRSYS:
  1283.         preerror("ASM: only use system registers within MOV instruction\n");
  1284.         return;
  1285. Op2ERRAF:
  1286.         preerror("Absolute FAR addresses can only be used for jumps\n");
  1287.         return;
  1288. // Первый операнд в 2-операндной инструкции - регистр
  1289. Op2R:
  1290.         EBX=0;
  1291.         BL=CH;
  1292.         EBX=EBX<<2+#Jmp_Op2R;
  1293.         $JMP NEAR DSDWORD[EBX]          // Переход по типу второго операнда
  1294. // Первый операнд в 2-операндной инструкции - EA
  1295. Op2E:
  1296.         EBX=0;
  1297.         BL=CH;
  1298.         EBX=EBX<<2+#Jmp_Op2E;
  1299.         $JMP NEAR DSDWORD[EBX]          // Переход по типу второго операнда
  1300. // mnem EA,RX
  1301. L81:
  1302.         SCDEND();
  1303. OpE2R:
  1304.         GETOL2();       // Обработка записи из шаблона
  1305.         $CMP AL,DER     //EA & R + D-BIT ?
  1306.         $JE  C21
  1307. X26:
  1308.         $CMP AL,ERO     //'ERO' ORDER ?
  1309.         $JE  C21
  1310.         $CMP AL,EAO     //EA, ?
  1311.         $JNE L81                        // На пропуск записи в шаблоне
  1312.         $CMP OPDATA[1],rCL      //CL REGISTER USED??
  1313.         $JNE L81                        // На пропуск записи в шаблоне
  1314.         $CMP DSBYTE[ESI+1],rCL  //CL IN GENERATION INFO?
  1315.         $JNE L81                        // На пропуск записи в шаблоне
  1316. //      CMP OPERANDSIZE,_B      //YES, CHECK SIZE.
  1317. //      JNE L81                 // На пропуск записи в шаблоне
  1318.         ESI++;
  1319.         ESI++;
  1320. C21:
  1321.         $JMP CreateCode
  1322. L91:
  1323.         SCDEND();
  1324. OpR2E:
  1325.         GETOL2();
  1326.         $CMP AL,DER     //DER ?
  1327.         $JNE N43
  1328.         DBIT=1;         //(DIRECTION BIT)
  1329.         $JMP CreateCode
  1330. N43:
  1331.         $CMP AL,REO     //REO ?
  1332.         $JNE L91;
  1333.         $JMP CreateCode
  1334. //RX,RX ?
  1335. W2:
  1336.         ESI++;
  1337.         GOTO W1;
  1338. LA1:
  1339.         SCDEND();
  1340. OpR2R:
  1341.         $CMP DSBYTE[ESI],_B+OL2+EAO // байт+2оп+EAold?
  1342.         $JE W2                  //EAO FOUND, R+R COMBINATION NOT PERMITTED.
  1343.         GETOL2();       // Обработка записи шаблона
  1344.         $CMP AL,DER     // EA,reg или reg,EA с D/W-битом?
  1345.         $JNE N53
  1346. LB2:
  1347.         AL=OPDATA[0];   // Преобразуем регистр в EA
  1348.         CREATE_EA();
  1349.         AL=OPDATA[1];   // Второй операнд
  1350.         CREATE_R();
  1351.         $JMP CreateCode
  1352. N53:
  1353.         $CMP AL,ERO
  1354.         $JE LB2
  1355.         $CMP AL,REO
  1356.         $JNE N63
  1357.         AL=OPDATA[1]; //RX,EP
  1358.         CREATE_EA();
  1359.         AL=OPDATA[0];
  1360.         CREATE_R();
  1361.         $JMP CreateCode
  1362. N63:
  1363.         $CMP AL,EAO
  1364.         $JNE LA1                        // На пропуск записи в шаблоне
  1365. W1:
  1366.         ECX=2;          //COMPARE 2 OPERANDS.
  1367.         opDescInd=0;
  1368. LX2:
  1369.         $LODSB          // поле из записи шаблона
  1370.         $CMP AL,255     //1ST OPERAND OK.
  1371.         $JE L022
  1372.         $CMP AL,AR              //AL/AX/EAX?
  1373.         $JE OL2X_AR
  1374.         $CMP AL,rDX     //DX?
  1375.         $JE OL2X_DX
  1376.         $CMP AL,rCL
  1377.         $JE OL2X_CL
  1378.         GOTO LA1;                       // На пропуск записи в шаблоне
  1379. OL2X_AR:
  1380.         EBX=opDescInd;
  1381.         AH=OPDATA[EBX]&7; // Операнд из мнемоники
  1382.         $JNZ NEAR LA1           // На пропуск записи в шаблоне
  1383. L022:
  1384.         opDescInd++;
  1385.         $LOOP LX2
  1386.         GOTO L23;
  1387. OL2X_DX:
  1388.         EBX=opDescInd;
  1389.         $CMP OPDATA[EBX],0o12
  1390.         $JNE NEAR LA1           // На пропуск записи в шаблоне
  1391.         opDescInd++;
  1392.         $LOOP LX2
  1393.         GOTO L23;
  1394. OL2X_CL:
  1395.         EBX=opDescInd;
  1396.         $CMP OPDATA[EBX],rCL    //CL
  1397.         $JNE NEAR LC1
  1398.         opDescInd++;
  1399.         $LOOP LX2
  1400.         $TEST OPDATA[0],8+16    //1ST REGISTER WORD/DWORD?
  1401.         $JZ L23
  1402.         WBIT=1;         //YES, SET W-BIT.
  1403. L23:
  1404.         AL=OPDATA[0];
  1405.         CREATE_EA();
  1406.         $JMP CreateCode
  1407. //EA,CONSTANT ?         //EA,CONST?
  1408. LB1:
  1409.         SCDEND();
  1410. OpE2C:
  1411.         GETOL2();
  1412.         opDescInd=1;
  1413.         $CMP AL,ECO
  1414.         $JNE N73
  1415.         OPCONSTSIZE[1]=OPERANDSIZE;
  1416.         $JMP CreateCode
  1417. N73:
  1418.         $CMP AL,EAO
  1419.         $JNE N83
  1420.         $CMP OPERANDSIZE,_B
  1421.         $JNE N83
  1422.         $CMP DSBYTE[ESI],_1
  1423.         $JNE N83
  1424.         $CMP OPCONST[4],1
  1425.         $JNE N83
  1426.         OPCONSTFLAG[1]=0;
  1427.         ESI++;
  1428.         $JMP CreateCode
  1429. N83:
  1430.         $CMP AL,ECCO            //EA/SIGNED BYTE ?
  1431.         $JNE LB1
  1432.         $CMP OPCONST[4],0xFFFFFF80
  1433.         $JL LB1
  1434.         $CMP OPCONST[4],0x7F
  1435.         $JG NEAR LB1
  1436.         OPERANDSIZE=_B; //OMIT A SINGLE BYTE ON GENERATION.
  1437.         $JMP CreateCode
  1438. // mnem reg,const
  1439. LC1:
  1440.         SCDEND();
  1441. OpR2C:
  1442.         GETOL2();
  1443.         opDescInd=1;
  1444.         $CMP AL,RCO;
  1445.         $JNE Q1
  1446. A0:
  1447.         OPCONSTSIZE[1]=OPERANDSIZE;
  1448.         $JMP CreateCode // reg,const
  1449. Q1:
  1450.         $CMP AL,ECO;
  1451.         $JNE L110
  1452. A1:
  1453.         AL=EA_R;
  1454.         CREATE_EA();
  1455.         GOTO A0;
  1456. L110:
  1457.         $CMP AL,EAO;
  1458.         $JE N93
  1459.         $CMP AL,ECCO;
  1460.         $JNE LC1                //SIGNED BYTE CONST ?
  1461.         $CMP OPCONST[4],0xFFFFFF80;
  1462.         $JL LC1
  1463.         $CMP OPCONST[4],0x7F;
  1464.         $JG LC1
  1465.         OPERANDSIZE=_B;
  1466.         OPCONSTSIZE[1]=_B;
  1467.         GOTO A1; //CONVERT REGISTER TO EFFECTIVE ADDRESS AND GENERATE OPCODE.
  1468. N93:
  1469.         ECX=2;          //COMPARE 2 OPERAND.
  1470. B2:
  1471.         $LODSB;
  1472.         $CMP AL,255;
  1473.         $JE L122
  1474.         $CMP AL,AR;
  1475.         $JE OL2_AR      //AL/AX/EAX?
  1476.         $CMP AL,CO;
  1477.         $JE OL2_CO      //CONSTANT?
  1478.         $CMP AL,rDX;
  1479.         $JE OL2_DX      //DX?
  1480.         $CMP AL,_1;
  1481.         $JE OL2_1 //CONSTANT VALUE 1?
  1482.         $JMP LC1
  1483. OL2_AR:
  1484.         AH=OPDATA[0]&7;
  1485.         $JNZ NEAR LC1
  1486. L122:
  1487.         $LOOP B2;
  1488.         $JMP CreateCode
  1489. OL2_CO:
  1490.         $CMP OPDESC[1],CO;
  1491.         $JNE NEAR LC1
  1492.         OPCONSTSIZE[1]=OPERANDSIZE;
  1493.         GOTO L122;
  1494. OL2_DX:
  1495.         $CMP OPDATA[0],0o12;
  1496.         $JE  L122;
  1497.         $JMP LC1
  1498. OL2_1:
  1499.         $CMP OPCONSTSIZE[1],_B;
  1500.         $JNE NEAR LC1
  1501.         $CMP OPCONST[4],1;
  1502.         $JNE NEAR LC1
  1503.         OPCONSTFLAG[1]=0;
  1504.         $JMP A1
  1505. LD1:
  1506.         SCDEND();
  1507. // Первый операнд в 2-операндной инструкции - константа
  1508. Op2C:
  1509.         GETOL2();
  1510.         $CMP AL,EAO
  1511.         $JNE LD1
  1512.         ECX=2;          //COMPARE 2 OPERANDS.
  1513.         opDescInd=0;
  1514. B12:
  1515.         $LODSB
  1516.         $CMP AL,255
  1517.         $JE L222
  1518.         $CMP AL,AR              //AL/AX/EAX
  1519.         $JE XOL2_AR
  1520.         $CMP AL,CO
  1521.         $JE XOL2_CO
  1522.         $CMP AL,rDX     //DX
  1523.         $JE XOL2_DX
  1524.         $CMP AL,_1
  1525.         $JE XOL2_1
  1526.         GOTO LD1;
  1527. XOL2_AR:
  1528.         EBX=opDescInd;
  1529.         AH=OPDATA[EBX]&7;
  1530.         $JNZ N21
  1531. L222:
  1532.         opDescInd++;
  1533.         $LOOP B12
  1534.         $JMP CreateCode
  1535. N21:
  1536.         GOTO LD1;
  1537. XOL2_CO:
  1538.         EBX=opDescInd;
  1539.         $CMP OPDESC[EBX],CO
  1540.         $JNE LD1
  1541.         opDescInd++;
  1542.         $LOOP B12
  1543.         $JMP CreateCode
  1544. XOL2_DX:
  1545.         EBX=opDescInd;
  1546.         $CMP OPDATA[EBX],0o12
  1547.         $JNE NEAR LD1
  1548.         opDescInd++;
  1549.         $LOOP B12
  1550.         $JMP CreateCode
  1551. XOL2_1:
  1552.         EDX=opDescInd;
  1553.         $CMP OPCONSTSIZE[EDX],_B
  1554.         $JNE NEAR LD1
  1555.         EDX<<=2;
  1556.         $CMP OPCONST[EDX],1
  1557.         $JNE NEAR LD1
  1558.         EDX=opDescInd;
  1559.         OPCONSTFLAG[EDX]=0;
  1560.         AL=EA_R;
  1561.         CREATE_EA();
  1562.         $JMP CreateCode
  1563. // Трехоперандная инструкция
  1564. LE1:
  1565.         SCDEND();
  1566. THREEOPS:
  1567. D11:
  1568.         GETOL3();
  1569.         $CMP AL,ERO
  1570.         $JNE N42
  1571.         $CMP CX,R*256+E
  1572.         $JE O21
  1573.         $CMP CX,R*256+R
  1574.         $JNE LE1
  1575.         AL=OPDATA[0];
  1576.         CREATE_EA();
  1577.         AL=OPDATA[1];
  1578.         CREATE_R();
  1579.         GOTO O21;
  1580. N42:
  1581.         $CMP AL,REO
  1582.         $JNE N52                //ERROR: INVALID OPERANDS.
  1583.         $CMP CX,E*256+R
  1584.         $JE O21
  1585.         $CMP CX,R*256+R
  1586.         $JNE LE1
  1587.         AL=OPDATA[1];
  1588.         CREATE_EA();
  1589.         AL=OPDATA[0];
  1590.         CREATE_R();
  1591. O21:
  1592.         BL=AH&TRANSBITS;
  1593.         $CMP OPCONSTFLAG[2],1
  1594.         $JNE NEAR NA3
  1595.         $CMP BL,CC3
  1596.         $JNE N52
  1597.         $CMP OPCONST[8],0xFFFFFF80
  1598.         $JL NEAR LE1
  1599.         $CMP OPCONST[8],0x7F
  1600.         $JG NEAR LE1
  1601.         OPCONSTSIZE[2]=_B;
  1602.         $JMP CreateCode
  1603. N52:
  1604.         $CMP BL,CB3
  1605.         $JNE N62
  1606.         $CMP OPCONST[8],0xFF
  1607.         $JA NEAR LE1
  1608.         OPCONSTSIZE[2]=_B;
  1609.         $JMP CreateCode
  1610. N62:
  1611.         $CMP BL,CW3
  1612.         $JNE NA3
  1613.         $CMP OPCONST[8],0xFFFFFFFF
  1614.         $JA NEAR LE1
  1615.         $CMP RANDFLAG,1
  1616.         $JNE NA2
  1617.         OPCONSTSIZE[2]=_W;
  1618.         $JMP CreateCode
  1619. NA2:
  1620.         OPCONSTSIZE[2]=_D;
  1621. NA_2:
  1622.         $JMP CreateCode
  1623. NA3:
  1624.         $CMP BL,CL3
  1625.         $JNE NEAR LE1
  1626.         $CMP OPDESC[2],R
  1627.         $JNE NEAR LE1
  1628.         $CMP OPDATA[2],rCL
  1629.         $JE NA_2
  1630.         illegaloperand();
  1631. }
  1632.  
  1633. CreateConstants()
  1634. {
  1635.         $CMP EA_SIBFLAG,1 // Флаг наличия Sib в 32-битном EA
  1636.         $JNE L3                 // Sib отсутствует
  1637.         $CMP ADDRFLAG,1
  1638.         $JE L3          //NO, NORMAL XRM
  1639. // Запись SIB - байта
  1640.         AL=EA_I<<3|EA_R2|EA_SCALING;
  1641.         OP();
  1642. L3:
  1643.         $CMP OPCONSTFLAG[0],1
  1644.         $JNE NEAR N1
  1645.         IF(OPPOST[0])SetPost(OPPOSTREF[0],OPPOST[0]);
  1646.         ECX=OPCONSTSIZE[0];
  1647.         EDI=#OPCONST; // Значение disp в EA
  1648.         WRITECONST();
  1649. N1:
  1650.         $CMP OPCONSTFLAG[1],1
  1651.         $JNE NEAR N41
  1652.         ECX=OPCONSTSIZE[1];
  1653.         $CMP CL,AF              //ABSOLUTE FAR ?
  1654.         $JNE D21
  1655.         EDI=#OPCONST+4; //YES, CREATE ADDRESS.
  1656.         CL=_W;          //(32 BIT)
  1657.         $CMP ADDRFLAG,1
  1658.         $JNE D2
  1659.         ECX=_D;         //(48 BIT)
  1660. D2:
  1661.         WRITECONST();
  1662.         EDX+=output;
  1663.         EBX=EDX>>4;
  1664.         $AND EDX,15
  1665.         $PUSH EBX,EDX
  1666.         $POP EDX        //???
  1667.         EAX=opDescInd;
  1668.         DSDWORD[EAX]=EDX;
  1669.         ECX=_W;
  1670.         /* AFSEG нигде не определен, надо будет разбираться
  1671.         EDI=#AFSEG; //(SEGMENT/SELECTOR)                                                                         */
  1672.  
  1673.         WRITECONST();
  1674.         $STC
  1675.         $RET
  1676. D21:
  1677.         IF(OPPOST[1])SetPost(OPPOSTREF[4],OPPOST[1]);
  1678.         EDI=#OPCONST+4;
  1679.         WRITECONST();
  1680. N41:
  1681.         IF(OPCONSTFLAG[2]==1){
  1682.                 ECX=OPCONSTSIZE[2];
  1683.                 EDI=#OPCONST+8;
  1684.                 WRITECONST();
  1685.         }
  1686. }
  1687.  
  1688. // ----
  1689. illegaloperand()
  1690. {
  1691.         preerror("ASM: Illegal operand\n");
  1692. }
  1693. // ----
  1694. toomuchoperands()
  1695. {
  1696.         preerror("ASM: Illegal number of operands\n");
  1697. }
  1698.  
  1699. // JUMP TABLES
  1700. dword Jmp_Mov={#Mov_R,#Mov_E,#Mov_ERR,#Mov_S,
  1701.         #Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR};
  1702. dword Jmp_Mov_R={#Mov_R2R,#Mov_R2E,#Mov_R2C,#Mov_S,
  1703.         #Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR,#Mov_SYSR};
  1704. dword Jmp_Mov_E={#Mov_E2R,#Mov_ERR,#Mov_E2C,#Mov_S,
  1705.                                 #Mov_ERR,#Mov_ERR,#Mov_ERR,#Mov_ERR,#Mov_ERR,#Mov_ERR};
  1706.  
  1707. dword Jmp_Op1={#Op1R,#Op1E,#Op1C,#Op1S,
  1708.                                 #Op1ERR,#Op1ERR,#Op1ERR,#Op1ERR,#Op1ERR,#Op1AF};
  1709. dword Jmp_Op2={#Op2R,#Op2E,#Op2C,#Op2ERRS,
  1710.                                 #Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRAF};
  1711. dword Jmp_Op2R={#OpR2R,#OpR2E,#OpR2C,#Op2ERRS,
  1712.                                 #Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRAF};
  1713. dword Jmp_Op2E={#OpE2R,0,#OpE2C,#Op2ERRS,
  1714.         #Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRSYS,#Op2ERRAF};
  1715. //dword TC_JMP={#T_JMPSHORT,#T_JMPNEAR,#T_JMPFAR};
  1716. //dword TC_CALL={0,#T_CALL,#T_CALLFAR};
  1717. //dword TC_J={#T_J,#T_JN,1};
  1718. dword Dsc_Jump={#CreateConstants,#Dsc_O,#Dsc_OW,#Dsc_OS,#Dsc_S,#Dsc_XRM,#Dsc_XPM,#Dsc_XSM};
  1719.