Advertisement
Guest User

Untitled

a guest
Jun 29th, 2017
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 42.18 KB | None | 0 0
  1.  
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.FileOutputStream;
  5. import java.io.FileReader;
  6. import java.io.IOException;
  7. import java.io.PrintWriter;
  8. import java.io.File;
  9. import java.util.ArrayList;
  10. import java.util.regex.Pattern;
  11. import java.util.StringTokenizer;
  12.  
  13. /**
  14.  * @author Selden
  15.  *
  16.  */
  17.  
  18. public class MyKurs {
  19.  
  20.     // абсолютные пути ко всем файлам
  21.     static String File_name_and_Path = "D:\\program.asm";  // "/media/Data/program.asm";
  22.     static String Listing_name_and_Path = "D:\\listing.txt";  // "/media/Data/listing.txt";
  23.     static String Obj_name_and_Path = "D:\\program.obj";  // "/media/Data/listing.txt";
  24.    
  25.     // настройка режима вывода ошибок (true - выводить все ошибки, false - останавливаться на первой ошибке)
  26.     static boolean errorMode=false;
  27.  
  28.     // Настройка режима отладки: писать отладочную инфо в терминал(debugMode=true), или нет(debugMode=false).
  29.     static boolean debugMode=true;
  30.    
  31.     static boolean error=false; // признак наличия ошибок в исходном тексте программы
  32.    
  33.     static BufferedReader in=null;
  34.     static FileOutputStream bin=null;
  35.     static PrintWriter out=null;
  36.     static String Line;
  37.     static String []Lines; // array with lines of current text file
  38.     static ArrayList<String> RawLines=new ArrayList<String>(); // массив, содержащий все строки текстового файла
  39.     static ArrayList<String> сommandLines=new ArrayList<String>(); // массив, содержащий все строки области команд
  40.     static ArrayList<String> dataLines=new ArrayList<String>(); // массив, содержащий все строки области данных
  41.    
  42.     static ArrayList<String> MetkiTemp=new ArrayList<String>();
  43.     // каждый элемент данного массива - "<имя метки> адрес"
  44.    
  45.     static ArrayList<String> ConstTemp=new ArrayList<String>();
  46.     // каждый элемент данного массива - "<имя константы> адрес"
  47.  
  48.     static String [][]TSI; // таблица символических имен
  49.    
  50.     static int Schak; // ну а это самое страшное - счетчик адреса команды =)
  51.    
  52.     static String CSName; // имя области команд (Задается директивой SEGMENT)
  53.     static String DSName; // имя области команд (Задается первым появившимся DB, который идет с именем сегмента ТОЛЬКО в одной строке)
  54.     static int startAddress ;  // адрес, указанный в ORG
  55.     static int linecount; // указатель текущей обрабатываемой строки
  56.     static String RegT[][] = { // имена регистров (код регистра==поле reg или r/m - при записи в бинарник равен индексу j колонки)
  57.         {"AL","CL","DL","BL","AH","CH","DH","BH"}, // w=0
  58.         {"AX","CX","DX","BX","SP","BP","SI","DI"}  // w=1
  59.         };
  60.        
  61.     static String Reg   =" AL CL DL BL AH CH DH BH AX CX DX BX SP BP SI DI ";
  62.     static String Reg8  =" AL CL DL BL AH CH DH BH ";
  63.     static String Reg16                        = " AX CX DX BX SP BP SI DI ";
  64.  
  65.         static String MnemoT[]={"MOV","SBB","MUL","JA", "DB", "INT"};
  66.     static int NumOfOperands[]={  2,    1,   1,     1,    1,     1};
  67. static String [] Types =       {"Com","Com","Com","Com","Dir", "Com"};
  68.  
  69. static String FormatOfOp[]={
  70.  // MOV
  71.  " R8,R8  R16,R16  R8,IMM8  R16,IMM16   R16,IMM8  R8,O8   R8,O16   R16,O8   R16,O16    O8,R8    O16,R8    O8,R16    O16,R16    R8,M    R16,M ",//O8,IMM8 O16,IMM8 O8,IMM16 O16,IMM16 O8,M O16,M ",  
  72.  // SBB
  73.  " R8,R8  R16,R16  R8,IMM8  R16,IMM16   R16,IMM8  R8,O8   R8,O16   R16,O8   R16,O16    O8,R8    O16,R8    O8,R16    O16,R16    R8,M    R16,M ",                 //SBB
  74.  " R16 R8 ",               //MUL
  75.  " M ",                    //JA
  76.  " IMM8 ",                 //DB
  77.  " IMM8 "};                //INT 20h
  78.  
  79. static String ByteSizeOp []={
  80. "2 2 2 3 2 4 4 4 4 4 4 4 4 2 2", //6 6 6 6 6 6", // MOV
  81. "2 2 2 3 2 4 4 4 4 4 4 4 4 2 2",
  82. "2 2",  //MUL
  83. "2",    //JA
  84. "1",    //DB
  85. "2"};   //INT 20h
  86.  
  87. // static String FormatOfOperands[][]= { // длина команды в оп
  88. //   { "R8,R8",     // 2
  89. //     "R16,R16",   // 2
  90. //     "R8,IMM8",   // 2
  91. //     "R16,IMM16", // 3
  92. //     "R16,IMM8",  // 2
  93. //     "R8,O8",     // 4
  94. //     "R8,O16",    // 4
  95. //     "R16,O8",    // 4
  96. //     "R16,O16",   // 4
  97. //     "O8,R8",     // 4
  98. //     "O16,R8",    // 4
  99. //     "O8,R16",    // 4
  100. //     "O16,R16",   // 4
  101. //     "R8,M",      // 2
  102. //     "R16,M"},    // 2          
  103. //       "O8,IMM8"  // 6
  104. //       "O16,IMM8" // 6
  105. //       "O8,IMM16" // 6
  106. //       "O16,IMM16"// 6
  107. //       "O8,M"     // 6
  108. //       "O16,M"    // 6      MOV
  109.        
  110.  
  111. //    
  112. //     {"R16",  // 2
  113. //      "R8"},  // 2  //MUL
  114. //  
  115. //     {"M"},  // 2           //JA
  116. //     {"IMM8"},   // 1       //DB
  117. //     {"IMM8"},   // 2       //INT 20h
  118. //};                
  119.  
  120.  
  121.     static String commands_in_line=" MOV ORG DB OFFSET MUL JA SEGMENT END ENDS INT "; //все команды и директивы в одной строке
  122.  
  123.     static String [][] commandsToWrite;
  124.     static ArrayList<String> ToWrite=new ArrayList<String>();
  125.    
  126.     public static void main(String[] args) throws IOException {
  127.     initFile();
  128.     checkForErrors(); // выйдет с помощью return если найдет любую ошибку в исходном коде и тогда просмотров не будет, а в листинг запишет      ся ближайшая ошибка
  129.    
  130.     if(error){ return; } // если была найдена хотя бы одна ошибка, компиляцию надо остановить
  131.    
  132.     firstPass();
  133.     //secondPass();
  134.     }
  135.  
  136.     private static void initFile() throws IOException { try {
  137.         File file=new File(File_name_and_Path);
  138. double InputFileSize=(double)(file.length())/1048576; // получаем размер исходного файла в мегабайтах
  139. if(InputFileSize>=0.5){error(14); if(!errorMode)return; }
  140.  
  141.         in = new BufferedReader(new FileReader(file));
  142.         while ((Line = in.readLine()) != null) {
  143.             if (Line.contains(";")) {Line = Line.substring(0, Line.indexOf(";"));}
  144.             if(!Del_spaces(Line).equals(""))RawLines.add(Line.toUpperCase());
  145.         }
  146.  
  147.         if(RawLines.size()==0){ // если входной файл пуст
  148.             error(4); if(!errorMode)return;      
  149.         }
  150.        
  151.         Lines = new String[RawLines.size()];
  152.         int currentItem = 0;
  153.         for(String temp:RawLines){
  154.             Lines[currentItem]=temp;
  155.             currentItem++;
  156.         }
  157.  
  158.         } catch (Exception e) {
  159.         } finally { if (in!=null)in.close();
  160. System.out.println("Входные данные:");
  161. if(RawLines.size()!=0){for(int i=0; i<Lines.length;i++)System.out.println((i+1)+"). "+delFirstSpaces(Lines[i]));}
  162. System.out.println();
  163.         }
  164.     }
  165.  
  166.     private static void firstPass() {
  167.        
  168.         String []tmp=null;
  169.         commandsToWrite=new String[ToWrite.size()][4]; // массив полей программы
  170.         for(int i=0;i<ToWrite.size();i++){ // для каждой строки
  171.         tmp=tokenize(ToWrite.get(i)," "); // разбили на слова
  172.         for(int j=0;j<=3;j++){
  173.         if(j==2&tmp[j].endsWith("H")&!Reg.contains(tmp[j])){
  174.             tmp[j]=hex2dec(tmp[j])+""; }
  175.             commandsToWrite[i][j]=tmp[j]; }}
  176.        
  177.         // печать вспомогательного массива
  178.         if(debugMode){System.out.println("\nМассив для первого проcмотра:");
  179.         for(int i=0;i<commandsToWrite.length;i++){for(int j=0;j<commandsToWrite[0].length;j++)System.out.print("{"+commandsToWrite[i][j]+"},");
  180.        
  181.  
  182.        
  183.         System.out.println(); }
  184.         //System.out.println("ArrayList меток"+MetkiTemp);
  185.         }
  186.        
  187.         // собственно погнали творить чудеса
  188.                          
  189.        
  190.        TSI=new String[MetkiTemp.size()+ConstTemp.size()][3]; // массив для проверки меток
  191.        
  192.        int k=0;
  193.        for(int i=0; i<MetkiTemp.size();i++,k++){
  194.            TSI[i][0]=tokenize(MetkiTemp.get(i)," ")[0];
  195.            TSI[i][1]=tokenize(MetkiTemp.get(i)," ")[1];
  196.            TSI[i][2]=tokenize(MetkiTemp.get(i)," ")[2];
  197.        k=i;
  198.        }
  199.              
  200.        for(int i=0; i<ConstTemp.size();i++){
  201.            TSI[k+i][0]=tokenize(ConstTemp.get(i)," ")[0];
  202.            TSI[k+i][1]=tokenize(ConstTemp.get(i)," ")[1];
  203.            TSI[k+i][2]=tokenize(ConstTemp.get(i)," ")[2];
  204.        }
  205.        
  206.        
  207.         if(debugMode){
  208.         System.out.println("\nТаблица символических имен:");
  209.         for(int i=0;i<TSI.length;i++){
  210.         for(int j=0;j<TSI[0].length;j++){
  211.         System.out.print("{"+TSI[i][j]+"}");}System.out.println();
  212.         }}
  213.          
  214.                
  215.            
  216.        
  217.        
  218.     }
  219.  
  220.  
  221.     private static void secondPass() {
  222.  
  223.     }
  224.  
  225.  
  226.     private static void checkForErrors() { try{
  227.     Schak=0;
  228.     startAddress=0;
  229.     linecount=0;
  230.     CSName="";
  231.     DSName="";
  232.    
  233. if(Lines.length==0){ error(4); if(!errorMode)return;  } // если в файле нет ничего, кроме пустых строк или файл вообще пуст
  234.  
  235. //анализ первой строки
  236. String []temp=Lines[linecount].trim().split("\\s+"); // получаем массив из слов первой строки
  237. if(temp.length==2){ // в первой строке должно быть 2 слова и никак иначе
  238. if("SEGMENT".equals(temp[1])){ // если директива "SEGMENT" на своем месте (вторым словом в строке)
  239. if(goodName(temp[0])){ //если имя сегмента соответствует формату,
  240.     CSName=temp[0]; // копируем его в переменную,
  241. } else {error(3); if(!errorMode)return;}  // если имя сегмента не соответствует формату (первой не может быть цифра)
  242. } else {error(2); if(!errorMode)return;} // иначе ошибка =)
  243. } else {error(1); if(!errorMode)return;} // и иначе, сука, тоже ошибка =)
  244.  
  245. linecount++; // анализ второй строки
  246. temp=Lines[linecount].trim().split("\\s+"); // получаем массив из слов второй строки
  247. if(temp.length==2){
  248. if("ORG".equals(temp[0])){ // если директива ORG на месте
  249. if(is2_byte_unsigned_Const(temp[1])==2){ // если выражение после ORG - нормальная 2-х байтная беззнаковая константа
  250.     // копируем адрес при ORG в переменную в десятеричном виде
  251.     if(temp[1].endsWith("H"))startAddress=hex2dec(temp[1]); else Integer.parseInt(temp[1]);
  252.     } else { // константа содержит ошибку
  253.     if(is2_byte_unsigned_Const(temp[1])==1){error(8);} // если константа выходит за пределы 2 байт
  254.     else error(5);if(!errorMode)return;}} // если константа записана неверно
  255.     else {error(6);if(!errorMode)return;}} // если во второй строке нет директивы ORG
  256.     else {error(7);if(!errorMode)return;} // если в строке №2 не 2 слова
  257.  
  258. linecount++; // старт собственно анализа команд
  259. if(linecount>=Lines.length){ // если после ORG ничего нет
  260. error(9); if(!errorMode)return;
  261. }
  262.  
  263. boolean hasINT20H=false;
  264. int tempLinecount=linecount;
  265. while(tempLinecount<Lines.length&&!(Lines[tempLinecount].contains("INT 20H"))){
  266. сommandLines.add(Lines[tempLinecount]);  // получаем arrayList из строк области команд
  267. try{if(delFirstSpaces(delLastSpaces(Lines[tempLinecount+1])).equals("INT 20H")){hasINT20H=true;}} catch (Exception m){}
  268. tempLinecount++;
  269. }
  270.  
  271. if(!hasINT20H){error(26); if(!errorMode)return;}
  272. // и проверяем, содержится ли вообще в файле "INT 20H". Если его нет - ошибка.
  273.  
  274.         // создаем массив, который будет содержать поля области команд 4 столбца на n строк
  275.        // commandsToWrite = new String[сommandLines.size()][3];
  276.  
  277. String Metka,Mnemo,OP1,OP2; // temp-поля
  278.  
  279. if(debugMode)System.out.println("\nОбласть команд");
  280. for(String str: сommandLines){// для каждой строки области команд
  281. // задача - разбить каждую строку области команд на 4 поля: метку, мнемокод, Оп1, Оп2.
  282.     Metka=Mnemo=OP1=OP2=null; // обнуление temp-полей
  283.  
  284. if(str.contains(":")){
  285. Metka=str.substring(0,str.lastIndexOf(":")); // отрезаем все до последнего двоеточия в строке, как метку
  286.  
  287. if((Del_spaces(Metka+":")).equals(Del_spaces(str))){ // если в строке нет ничего, кроме метки - ошибка
  288. error(31); if(!errorMode)return;
  289. }
  290.  
  291. while(Metka.endsWith(" "))Metka=Metka.substring(0,Metka.length()-1); // удаляем все пробелы В КОНЦЕ отрезанного куска
  292. while(Metka.startsWith(" "))Metka=Metka.substring(1); // удаляем все пробелы В НАЧАЛЕ отрезанного куска
  293. //а вдруг метка состоит не из одного слова, или ее имя начинается с цифры? Проверим...
  294. if(!goodName(Metka)){ // если метка задана неверно
  295. error(11); if(!errorMode)return; } else { // если же с меткой все в порядке
  296. str=str.substring(str.lastIndexOf(":")+1); // отрезать ее из строки к чертям, она уже есть у нас в переменной
  297. }
  298. if(debugMode)System.out.println("Встречена метка: "+Metka);
  299.  
  300. for(String h:MetkiTemp){   
  301. if((tokenize(h," ")[0]).equals(Metka)){error(32);if(!errorMode)return;}
  302. }
  303.  
  304. MetkiTemp.add(Metka+" "+Schak+" Label");
  305. }
  306.  
  307.  // остаток строки делим на слова по пробелам и запятой.
  308.  String []tempCommandLine=tokenize(str," ,\t");
  309.  
  310.  if(commands_in_line.contains(" "+tempCommandLine[0]+" ")){ // если первое слово является допустимым мнемокодом команды
  311.  Mnemo=tempCommandLine[0];
  312.  //System.out.print("Мнемокод: "+Mnemo+"   ");
  313. } else {error(12);if(!errorMode)return;}
  314.  
  315. int num=0;
  316. for(int i=0;i<MnemoT.length;i++){if(MnemoT[i].equals(Mnemo))num=NumOfOperands[i];} // определяем количество операндов текущей команды по ее мнемокоду
  317. if(tempCommandLine.length!=num+1){ // проверка на количество операндов
  318. error(13); System.out.println(" для команды "+Mnemo+"."); if(!errorMode)return;} // если у комады не может быть столько операндов
  319.  
  320. // определяем тип операндов и в кодированном виде проверяем то ТФК, могут ли у данной команды быть такие типы операндов
  321. String opCodes="";
  322. for(int i=0;i<num;i++){ // для всех операндов команды
  323. String op=tempCommandLine[i+1];
  324.  
  325. if(Reg8.contains(" "+op+" "))  { opCodes+="R8,";} else // если операнд - регистр
  326. if(Reg16.contains(" "+op+" ")) { opCodes+="R16,";} else
  327. if(goodName(op)){ // если операция == допустимое имя константы
  328. opCodes+="M,";
  329. } else
  330. if(is_Imm8(op)==2){ // если операнд - Imm8
  331. tempCommandLine[i+1]=hex2dec(op)+""; // дальше будем работать с 10-ричным представлением этого числа
  332. opCodes+="IMM8,";} else  // если не Imm8
  333. if(is_Imm16(op)==2){ // если операнд - Imm16
  334. tempCommandLine[i+1]=hex2dec(op)+""; // дальше будем работать с 10-ричным представлением этого числа
  335. opCodes+="IMM16,";} else
  336. // или может, это память (базовая адресация вида [BX+5h] или просто [BX] )?
  337. if(checkBaseAddressing(op)>1) {  // если операнд - адрес памяти с базовой адресацией      
  338.  
  339. // перевести метку в 10 - ричную систему
  340.      
  341. if(checkBaseAddressing(op)==3)opCodes+="O16,"; else // с 2-байтным смещением
  342. if(checkBaseAddressing(op)==4|checkBaseAddressing(op)==2)opCodes+="O8,"; // без смещения или с 1-байтным смещением
  343.  
  344.  
  345. String smeshenie=tokenize(op,"[]BXP \t+-")[0]; // отрезаем число, на которое идет смещение
  346. if(smeshenie.endsWith("H")){
  347. op=op.substring(0,op.indexOf(smeshenie))+hex2dec(smeshenie)+"]"; // если смещение задано в 16-ричном виде, переводим его в 10-ричный формат
  348. }
  349.  
  350. }
  351.  
  352. else{ // если формат операнда не опознан - проверяем возможные ошибки пользователя
  353. // проверка содержимого квадратных скобок, если это адрес
  354. if(checkBaseAddressing(op)==1){error(15); if(!errorMode)return;} // если смещение вышло за пределы 2-х байт
  355. if(checkBaseAddressing(op)==-1){error(17); if(!errorMode)return;} // в базовой адресации неверно указан регистр
  356. if(is_Imm16(op)==1){error(18); if(!errorMode)return;} // непосредственный операнд вышел за пределы 2-х байт
  357.  
  358. error(16); if(!errorMode)return; // ошибка "неизвестный формат операнда"
  359. }
  360. if(i==0)OP1=op; else OP2=op; // пишем проверенные операнды в подготовленные поля
  361. }
  362.  
  363. while(opCodes.endsWith(","))opCodes=opCodes.substring(0,opCodes.length()-1); // убираем запятую в конце формируемой строки
  364.  
  365. if(debugMode)System.out.print("Строка "+(linecount+1)+": мнемокод - "+Mnemo+", операнды:  {"+opCodes+"}, длина команды - ");
  366. // теперь строчка opCodes содержит порядок операндов в команде или один операнд в
  367. for(int i=0;i<MnemoT.length;i++){if(MnemoT[i].equals(tempCommandLine[0])){ // для текущей команды
  368. if(!FormatOfOp[i].contains(" "+opCodes+" ")){ // если у текущей команды не может быть такого порядка операндов
  369. error(19); if(!errorMode)return;}
  370. // если у текущей команды могут быть такие операнды,
  371. // проверка, сколько занимает команда с такими операндами в объектном файле и выполним увеличение СчАК
  372. String tmp[]=FormatOfOp[i].trim().split("\\s+");
  373. for(int j=0;j<tmp.length;j++){
  374. if(tmp[j].equals(opCodes)){
  375. int g=Integer.parseInt(ByteSizeOp[i].split("\\s+")[j]);
  376.  
  377. Schak+=g;
  378. if(debugMode){System.out.println(g); System.out.println("Счак="+Schak);}}
  379. }}}
  380.  
  381. String toWrite="";
  382. if(Metka!=null)Metka+=":";
  383. ToWrite.add(Metka+" "+Mnemo+" "+OP1+" "+OP2); // добавляем команду, не содержащую ошибок в ArrayList. К метке в конце приписываем ":"
  384. if(debugMode){System.out.print("To write: "); System.out.println(Metka+" "+Mnemo+" "+OP1+" "+OP2);}
  385.  
  386. //System.out.println("Строка "+(linecount+1)+": мнемокод - "+Mnemo+", операнды:  {"+opCodes+"}");
  387. linecount++;
  388. }
  389.  
  390. // теперь мы находимся в строке, где был встречен INT 20H (просто встречен в составе строки, он еще может быть неверно записан)
  391. if(!delFirstSpaces(delLastSpaces(Lines[linecount])).equals("INT 20H")){ // если кроме "INT 20H" и пробелов есть какой-то лишний мусор из символов
  392. error(25); if(!errorMode)return;
  393. } else { linecount++; // если ошибки нет переход к следующей строке
  394. if(debugMode)System.out.println("Строка "+linecount+": мнемокод - INT 20h, операнды:  {IMM8}, длина команды - 2.");
  395. ToWrite.add("null INT 20H null"); // добавляем INT 20h в ArrayList.
  396.  
  397. Schak+=2; // добавляем к Счак длину команды INT 20h
  398.  
  399. if(debugMode){
  400. System.out.println("Счак="+Schak);
  401. System.out.print("To write: ");
  402. System.out.println("null INT 20H null");
  403. System.out.println("Конец области команд.");
  404. }
  405.  
  406. }
  407.  
  408. // теперь мы находимся в строке, где находится первый DB
  409. if(debugMode)System.out.println("\nОбласть данных");
  410. while(linecount<Lines.length&&!Lines[linecount].contains("END")){ // для всех строк области данных, от "INT 20H" без него до ближайшего ENDS или, если ENDS не встречен - до конца файла
  411.  
  412. Metka=Mnemo=OP1=OP2=null; // обнуление temp-полей для каждой строки
  413.  
  414. dataLines.add(Lines[linecount]); // сохраняем строки в ArrayList
  415.  
  416. String []DataLine=Lines[linecount].trim().split("\\s+"); // получаем массив из слов этой строки
  417.  
  418. if(!goodName(DataLine[0])){error(20);if(!errorMode)return;} else {Metka=DataLine[0];}  // если у объявляемой переменной неверное имя
  419. if(DataLine.length>3){error(21);if(!errorMode)return;} // если в строке с DB больше, чем 3 слова
  420. if(DataLine.length<3){error(22);if(!errorMode)return;} // или меньше 2-х слов
  421. if(is_Imm8(DataLine[2])==0){error(23);if(!errorMode)return;} else {OP1=DataLine[2];} // неверно задана константа в DB
  422. if(is_Imm8(DataLine[2])==1){error(24);if(!errorMode)return;} // константа в DB вышла за пределы
  423.                            
  424. Mnemo=DataLine[1];  // !!!!!!!! DW ?
  425. ToWrite.add(Metka+" "+Mnemo+" "+OP1+" "+OP2);
  426. if(debugMode){System.out.print("To write: "); System.out.println(Metka+" "+Mnemo+" "+OP1+" "+OP2);}
  427.  
  428. if(OP1.endsWith("H"))OP1=hex2dec(OP1)+"";
  429. ConstTemp.add(Metka+" "+OP1+" VAR");
  430.  
  431. Schak+=1; // продвигаем Счак на 1 байт
  432. if(debugMode)System.out.println("Счак="+Schak);
  433. linecount++;
  434. }
  435.  
  436. if(debugMode)System.out.println();
  437.  
  438. // проверки наличия конца сегмента (<имя сегмента> ENDS) и команды END
  439. //если мы находимся в конце файла, но слово "ENDS" вообще не было встречено
  440. try{
  441. if(Lines[linecount]!=null){ // если есть хотя бы сама строка, которая должна содержать <Имя сегмента> "ENDS"
  442.  
  443. // проверка правильности строки с директивой <Имя сегмента> ENDS
  444. if(!delFirstSpaces(delLastSpaces(Lines[linecount])).equals(CSName+" ENDS")){ // если неверно указано имя сегмента в директиве ENDS или в строке есть всякий левый мусор
  445. error(29); if(!errorMode)return;
  446. }
  447.  
  448. if(Lines[linecount+1]!=null){ // если есть еще и строка, которая должна содержит "END" в любом виде
  449. // проверка правильности строки с директивой END
  450. if(!delFirstSpaces(delLastSpaces(Lines[linecount+1])).equals("END")){ // если неверно задана директива END
  451. error(30); if(!errorMode)return;}
  452. } else { error(28);if(!errorMode)return; } // ошибка "После директивы конца сегмента должна следовать директива END."
  453. }
  454. } catch(Exception m){ // исключение сработает, если уже конец файла, но еще не было "ENDS" и "END"
  455. error(27);if(!errorMode)return;} // ошибка "отутствует конец сегмента" // неверный конец программы
  456.  
  457.  
  458.  } catch(Exception r){System.out.println("Ошибка в работе программы. "+r);}
  459. } // конец обработки всех строк
  460.  
  461.     private static void error(int code) { System.out.println("\nОшибка ["+code+"] в строке "+(linecount+1)+"."); error=true;
  462.     switch(code){
  463.       case 1:  System.out.println("Первая строка должна иметь формат: <segment name> SEGMENT\nи не может содержать других директив, меток, команд или лишних сиволов."); break;
  464.       case 2:  System.out.println("Первая строка должна содержать директиву \"SEGMENT\"."); break;
  465.       case 3:  System.out.println("Неверное имя сегмента кода."); break;
  466.       case 4:  System.out.println("Исходный файл не содержит данных."); break;
  467.       case 5:  System.out.println("Неверно задан адрес при директиве ORG."); break;
  468.       case 6:  System.out.println("Отсутствует директива ORG."); break;
  469.       case 7:  System.out.println("Вторая строка должна иметь формат: <ORG выражение> \nи не может содержать других директив, меток, команд или лишних сиволов."); break;
  470.       case 8:  System.out.println("Константа при ORG выходит за пределы 2-х байт."); break;
  471.       case 9:  System.out.println("Отсутствует директива конца сегмента "+CSName+"."); break;
  472.      case 10:  System.out.println("Неверный формат строки, содержащей команду."); break;
  473.      case 11:  System.out.println("Неверное имя метки."); break;
  474.      case 12:  System.out.println("Недопустимый мнемокод команды."); break;
  475.      case 13:  System.out.print  ("Неверное количество операндов"); break;
  476.      case 14:  System.out.println("Размер исходного файла слишком велик. Выберите другой файл."); break;
  477.      case 15:  System.out.println("Смещение вышло за пределы 2-х байт."); break;
  478.      case 16:  System.out.println("Неверный формат операнда. "); break;
  479.      case 17:  System.out.println("Неверно указан регистр для базовой адресации. "); break;
  480.      case 18:  System.out.println("Непосредственный операнд вышел за допустимые пределы. "); break;
  481.      case 19:  System.out.println("Неверное задание операндов."); break;
  482.      case 20:  System.out.println("Неверное имя переменной."); break;
  483.      case 21:  System.out.println("Строка определения данных не может содержать ничего, кроме метки, директивы DB и задаваемой константы."); break;
  484.      case 22:  System.out.println("Неверный формат строки определения данных."); break;
  485.      case 23:  System.out.println("Константа задана неверно."); break;
  486.      case 24:  System.out.println("Константа вышла за допустимые пределы."); break;
  487.      case 25:  System.out.println("Данная строка долна иметь формат: <INT 20h>"); break;
  488.      case 26:  System.out.println("Программа должна содержать область команд и строку <INT 20h>."); break;
  489.      case 27:  System.out.println("Отсутствует директива конца сегмента кода или директива END."); break;
  490.      case 28:  System.out.println("После директивы конца сегмента должна следовать директива END."); break;
  491.      case 29:  System.out.println("Директива ENDS, либо имя сегмента не заданы, или указано неверно."); break;
  492.      case 30:  System.out.println("Неверно указана директива END."); break;
  493.      case 31:  System.out.println("В строке с меткой должна присутствовать команда."); break;
  494.      case 32:  System.out.println("Использовано дублирующееся имя метки."); break;
  495.      default:  stopWork(); break;
  496.     }
  497.  
  498.  
  499.     }
  500.  
  501.     private static void stopWork() { try{
  502.         if (in!=null)in.close();
  503.         if (out!=null)out.close();
  504.         System.exit(0);
  505.     } catch(Exception e){}}
  506.  
  507.     private static void WriteBin() throws IOException { }
  508.    
  509.  
  510.     static String Del_spaces(String line) {
  511.         String[] a=line.trim().split("\\s+");
  512.         String result="";
  513.         for (String temp:a){result+=temp;}
  514.         return result;
  515.     }
  516.    
  517.     static String delFirstSpaces(String line){ try{
  518.     while(line.startsWith(" "))line=line.substring(1);} catch (Exception m){}
  519.     return line; }
  520.    
  521.     static String delLastSpaces(String line){ try{
  522.     while(line.endsWith(" "))line=line.substring(0,(line.length()-1));} catch (Exception m){}
  523.     return line; }
  524.  
  525.     private static int hex2dec(String s) {
  526.         String digits="0123456789ABCDEF";
  527.         s=s.toUpperCase();
  528.         if(s.endsWith("H"))s=s.substring(0,s.indexOf("H"));
  529.         int val=0;
  530.         for (int i=0; i<s.length(); i++) {
  531.             char c=s.charAt(i);
  532.             int d=digits.indexOf(c);
  533.             val=16*val+d;
  534.         }
  535.         return val;
  536.     }
  537.    
  538.     private static String dec2hex(int d) {
  539.         String digits = "0123456789ABCDEF";
  540.         if (d==0)
  541.             return "0";
  542.         String hex = "";
  543.         while (d>0) {
  544.             int digit=d%16;
  545.             hex=digits.charAt(digit)+hex;
  546.             d=d/16;
  547.         }
  548.         return hex;
  549.     }
  550.  
  551.    static int checkBaseAddressing(String what){  // соответствует ли строка базовой адресации (со смещением, но без масштабирования)
  552.         // На выходе:
  553.         // -1 - все плохо, встретилось недопустимое имя регистра
  554.         // 0 - все плохо, входая строка однозначно не катит, как базовая адресация
  555.         // 1 - есть смещение, но оно выходит за пределы двух байт
  556.         // 2 - все отлично, вх. строка соответствует правильной базовой адресации без смещения
  557.         // 3 - все отлично, вх. строка соответствует правильной базовой адресации со смещением в пределах 2 байт(от 0 до +65536)
  558.         // 4 - все отлично, вх. строка соответствует правильной базовой адресации со смещением в пределах 1 байт(от 0 до +255)
  559. String temp1=what.split("\\s+")[0];
  560. if(!" BX BP ".contains(" "+temp1.substring(1,3)+" ")&what.startsWith("["))return -1; // если используется недопустимое имя регистра
  561.  
  562.  if(Pattern.compile("\\[B(P|X){1}\\]").matcher(what).matches()){ return 2;} else // без смещения  
  563.  if(Pattern.compile("\\[B(P|X){1}[\\+|-]\\d{1,}H{0,1}\\]").matcher(what).matches()){ // есть смещение
  564.     try{  String smeshenie=tokenize(what,"[]BXP \t+-")[0]; // отрезаем число, на которое идет смещение
  565.         if(smeshenie.endsWith("H"))smeshenie=hex2dec(smeshenie)+""; // если смещение задано в 16-ричном виде, переводим в 10-ричный формат
  566.         if(is1_byte_unsigned_Const(smeshenie)==2) return 4; else
  567.         if(is2_byte_unsigned_Const(smeshenie)==2) return 3;  //смещение в пределах 2 байт(от 0 до +65536), т.е. - является беззнаковой константой
  568.          else return 1; // выход смещения за пределы        
  569.     } catch (Exception r){} } else {
  570.     if(Pattern.compile("\\[B(P|X){1}\\]").matcher(what).matches()){ return 2; }} //правильная базовая адресация без смещения
  571.     return 0;  } // неправильная базовая адресация
  572.    
  573.        
  574.        static int checkIndexBaseAddressing(String what){  // соответствует ли строка базово-индексной адресации (со смещением, но без масштабирования)
  575.         // На выходе:
  576.         // 0 - все плохо, входая строка однозначно не катит, как базово-индексная адресация
  577.         // 1 - есть смещение, но оно выходит за пределы двух байт
  578.         // 2 - все отлично, вх. строка соответствует правильной базово-индексной адресации без смещения
  579.         // 3 - все отлично, вх. строка соответствует правильной базово-индексной адресации со смещением в пределах 2 байт(от 0 до +65536)
  580.         // 4 - все отлично, вх. строка соответствует правильной базово-индексной адресации со смещением в пределах 1 байт(от 0 до +255)
  581.        
  582.  if(Pattern.compile("\\[(B(P|X)){1}\\+{1}((D|S)I){1}\\]").matcher(what).matches()){ return 2;} else // без смещения
  583.  if(Pattern.compile("\\[(B(P|X)){1}\\+{1}((D|S)I){1}[\\+|-]\\d{1,}H{0,1}\\]").matcher(what).matches()){ // есть смещение
  584.     try{  String smeshenie=tokenize(what,"[]BXPDSI \t+-")[0]; // отрезаем число, на которое идет смещение
  585.         if(smeshenie.endsWith("H"))smeshenie=hex2dec(smeshenie)+""; // если смещение задано в 16-ричном виде, переводим в 10-ричный формат
  586.         if(is1_byte_unsigned_Const(smeshenie)==2) return 4; else
  587.         if(is2_byte_unsigned_Const(smeshenie)==2) return 3;  //смещение в пределах 2 байт(от 0 до +65536), т.е. - является беззнаковой константой
  588.          else return 1; // выход смещения за пределы        
  589.     } catch (Exception r){} } else {
  590.     if(Pattern.compile("\\[B(P|X){1}\\]").matcher(what).matches()){ return 2; }} //правильная базовая адресация без смещения
  591.     return 0;  } // неправильная базовая адресация
  592.    
  593.    
  594.    
  595.     private static boolean isRegistry(String what){ // проверка, является ли строка верным обозначением регистра
  596. if(Reg.contains(" "+what+" "))return true; return false;}
  597.  
  598.  
  599. private static int is2_byte_signed_Const(String what) { // проверка, является ли число 2-байтной знаковой константой (HEX или DEC в пределах от -32768 до +32767)
  600. int start=-32768; int end=32767;    
  601.    // На выходе:
  602.         // 0 - все плохо, входая строка однозначно не константа
  603.         // 1 - выход за пределы двух байт
  604.         // 2 - все отлично, вх. данные - 2-байтная знаковая константа
  605.         if(Pattern.compile("((\\d|[ABCDEF]){1,}H{1})").matcher(what).matches()){ // 16 - ричное число
  606.         if(hex2dec(what.substring(0,what.length()-1))<=end & hex2dec(what.substring(0,what.length()-1))>=start)return 2;else{return 1;}}
  607.         if(Pattern.compile("-{0,1}\\d{1,}").matcher(what).matches()){ // 10 - ричное число
  608.         if(Integer.parseInt(what)<=end & Integer.parseInt(what)>=start)return 2;else{return 1;}}
  609.         return 0;
  610. }
  611.  
  612. private static int is_Imm8(String what) { // проверка, является ли число 1-байтной знаковой константой (HEX или DEC в пределах от -127 до +255)
  613.        int start=-127; int end=255;
  614.         // На выходе:
  615.         // 0 - все плохо, входая строка  - не Imm8
  616.         // 1 - выход за пределы
  617.         // 2 - все отлично, вх. строка - Imm8
  618.         if(Pattern.compile("((\\d|[ABCDEF]){1,}H{1})").matcher(what).matches()){ // 16 - ричное число
  619.         if(hex2dec(what.substring(0,what.length()-1))<=end & hex2dec(what.substring(0,what.length()-1))>=start)return 2;else{return 1;}}
  620.         if(Pattern.compile("-{0,1}\\d{1,}").matcher(what).matches()){ // 10 - ричное число
  621.         if(Integer.parseInt(what)<=end&Integer.parseInt(what)>=start)return 2;else{return 1;}}
  622.         return 0;
  623. }
  624.  
  625. static int is_Imm16(String what) { // проверка, является ли число 1-байтной знаковой константой (HEX или DEC в пределах от -32768 до +65536)
  626.        int start=-32768; int end=65536;
  627.         // На выходе:
  628.         // 0 - все плохо, входая строка  - не Imm16
  629.         // 1 - выход за пределы
  630.         // 2 - все отлично, вх. строка - Imm16
  631.         if(Pattern.compile("((\\d|[ABCDEF]){1,}H{1})").matcher(what).matches()){ // 16 - ричное число
  632.         if(hex2dec(what.substring(0,what.length()-1))<=end & hex2dec(what.substring(0,what.length()-1))>=start)return 2;else{return 1;}}
  633.         if(Pattern.compile("-{0,1}\\d{1,}").matcher(what).matches()){ // 10 - ричное число
  634.         if(Integer.parseInt(what)<=end&Integer.parseInt(what)>=start)return 2;else{return 1;}}
  635.         return 0;
  636. }
  637.  
  638. static boolean goodName(String what){ // проверка на то, чтобы в строке первой не была цифра
  639. return Pattern.compile("[\\D&&[\\w]][\\w]*").matcher(what).matches();
  640. }
  641.  
  642.     private static int is2_byte_unsigned_Const(String what) { // проверка, является ли число беззнаковой 2-байтной константой (HEX или DEC в пределах 0..65536(FFFFH))
  643.         int start=0; int end=65536;
  644.         // На выходе:
  645.         // 0 - все плохо, входая строка однозначно не беззнаковая константа
  646.         // 1 - выход беззнаковой константы за пределы двух байт
  647.         // 2 - все отлично, вх. данные - 2-байтная беззнаковая константа        
  648.         if(Pattern.compile("((\\d|[ABCDEF]){1,}H{1})").matcher(what).matches()){ // 16 - ричное число
  649.         if(hex2dec(what.substring(0,what.length()-1))>=start & hex2dec(what.substring(0,what.length()-1))<=end)return 2;else{return 1;}}
  650.         if(Pattern.compile("\\d{1,}").matcher(what).matches()){ // 10 - ричное число
  651.         if(Integer.parseInt(what)>=start & Integer.parseInt(what)<=end)return 2;else{return 1;}}
  652.         return 0;
  653.         }
  654.        
  655.             private static int is1_byte_unsigned_Const(String what) { // проверка, является ли число беззнаковой 2-байтной константой (HEX или DEC в пределах 0..65536(FFFFH))
  656.         int start=0; int end=255;
  657.         // На выходе:
  658.         // 0 - все плохо, входая строка однозначно не беззнаковая константа
  659.         // 1 - выход беззнаковой константы за пределы двух байт
  660.         // 2 - все отлично, вх. данные - 2-байтная беззнаковая константа        
  661.         if(Pattern.compile("((\\d|[ABCDEF]){1,}H{1})").matcher(what).matches()){ // 16 - ричное число
  662.         if(hex2dec(what.substring(0,what.length()-1))>=start & hex2dec(what.substring(0,what.length()-1))<=end)return 2;else{return 1;}}
  663.         if(Pattern.compile("\\d{1,}").matcher(what).matches()){ // 10 - ричное число
  664.         if(Integer.parseInt(what)>=start & Integer.parseInt(what)<=end)return 2;else{return 1;}}
  665.         return 0;
  666.         }
  667.                
  668.     static int getAdressFromName(String name) {
  669.         int adress = 9999;
  670.         for (int i = 0; i < TSI.length; i++) {
  671.             if (TSI[i][0].equals(name)) {
  672.                 try {
  673.                     return Integer.parseInt(TSI[i][1]);
  674.                 } catch (Exception m) {
  675.                 }
  676.  
  677.             }
  678.  
  679.         }
  680.    
  681.            
  682.            
  683.             // метки - в массиве Metki, массив для записи - commandsToWrite
  684.        
  685.         return adress;
  686.     }
  687.          
  688.     private static String[] tokenize(String what, String razdeliteli){ // разделение токенайзером строки на массив String по поступившим разделителям
  689.         StringTokenizer st=new StringTokenizer(what,razdeliteli);
  690.         String []mas=new String[st.countTokens()];  int i=0;
  691.         while (st.hasMoreElements()) { mas[i] = st.nextElement().toString(); i++;}
  692.         return mas;
  693.        }
  694.  
  695.      private static void printMas(String [][]Mas){
  696.      for (int i = 0; i < Mas.length; i++) {
  697.             for (int j = 0; j < Mas[0].length; j++)
  698.                 System.out.printf("%8s ", "{"+Mas[i][j]+"},");
  699.             System.out.println();
  700.         }
  701.  
  702. }
  703.  
  704.        
  705. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement