Ikkinchi o'tish Ikkinchi o'tishning maqsadi - ob'ekt dasturini yaratish va yig'ish jurnalini chiqarish (agar kerak bo'lsa). Bundan tashqari, ikkinchi o'tish turli vaqtlarda yig'ilgan protseduralarni bitta bajariladigan faylga ulash uchun zarur bo'lgan ma'lumotlarni chiqarishi kerak. Ro'yxat 1.6 ikkinchi o'tish tartibini ko'rsatadi.
Ro'yxat 1.6. Oddiy assembler ikkinchi o'tish
public static void pass_two() { // Ushbu tartib assemblerning ikkinchi o'tishidir boolean morejnput = true; // ikkinchi o'tishni to'xtatuvchi bayroq String line, opcode; // buyruq maydonlari int location_counter, length, type; // o’zgaruvchilar final int END_STATEMENT = -2; // kirish yakuniy signallari final int MAX_CODE =16; // buyruqdagi baytlarning maksimal soni byte code[] = new byte[MAX_CODE]; // buyruqdagi baytlar soni // yaratilgan kodda location_counter = 0; // birinchi yig'ish // 0 manzilidagi buyruqlar while (more_input) { // more_input direktivasi orqali END // "yolg'on"qiymatini oladi type = read_type(); // keyingi qator turi maydonini o'qish opcode = read_opcode(); // opcode maydonini o'qing // keyingi qatorda length = read_length(); // uzunlik maydonini o'qish // keyingi qatorda line = read_line(); // kirish satrini o'zi o'qish if (type != 0) { // 0 turi izohni bildiradi switch(type) { // chiqish kodini yaratish case 1:eval_type1(opcode, length, line, code); break; case 2: eval_type2(opcode, length, line, code); break; // boshqa variantlar } } write_output(code); // ikkilik kodni yozish write_listing(code, line); // bitta qatorni chop etish location_counter = location_counter + length; // hisoblagichni yangilash // buyruq manzillari if (type == END_STATEMENT) { // Kirish tugallanganmi? more_input = false; // agar shunday bo'lsa, bajaring // xizmat ko'rsatish operatsiyalari finish_up(); //tugallash } } } Ikkinchi o'tish tartibi birinchisining tartibiga o'xshaydi: satrlar birma-bir o'qiladi va birma-bir qayta ishlanadi. Biz har bir satrning boshida tur, opcode va uzunlikni (vaqtinchalik faylda) yozganimiz sababli, ularning barchasi o'qiladi va shuning uchun biz satrlarni ikkinchi marta tahlil qilishimiz shart emas. Kodni yaratishning asosiy ishi eval_type1, eval_type2 va hokazo tartiblar orqali amalga oshiriladi.Ularning har biri ma'lum bir sxemani qayta ishlaydi (masalan, opcode va ikkita operand registrlari). Olingan ikkilik buyruq kodi kod o'zgaruvchisida saqlanadi. Keyin nazorat o'qishi amalga oshiriladi. write_code protsedurasi oddiygina to'plangan ikkilik kodni buferda saqlashi va faylni katta bo'laklarga bo'lib diskka yozishi ma'qul - bu diskdagi yukni kamaytiradi. Asl bayonot va undan olingan chiqish (ob'ekt) kodi (on oltilik tizimda) keyinroq chop etish uchun chop etilishi yoki buferlanishi mumkin. Buyruqlar manzili hisoblagichining qiymati o'zgartirilgandan so'ng, keyingi operator tanlanadi.
Hozirgacha biz asl dasturda xatolik yo'q deb taxmin qildik. Biroq, dasturlash bilan shug'ullangan har bir kishi bu taxmin qanchalik to'g'ri emasligini biladi. Bu erda faqat eng keng tarqalgan xatolar:
ishlatiladigan ramziy nom aniqlanmagan;
ramziy nom bir necha marta aniqlangan;
Opkod maydonidagi nom yaroqli operatsiya kodi emas.
Berilgan opkod uchun operandlar juda kam;
Berilgan opkod uchun juda ko'p operandlar mavjud;
sakkiztalik raqam 8 yoki 9 raqamini o'z ichiga oladi;
reestrdan noqonuniy foydalanish (masalan, reestrga o'tish);
END bayonoti mavjud emas.
Dasturchilar yangi xatolar haqida juda aqlli. Belgilanmagan ramziy nomga ega xatolar ko'pincha matn terish xatolarining natijasidir. Yaxshi assembler barcha belgilangan belgilarning qaysi biri aniqlanmaganga mos kelishini aniqlay oladi va uni aniqlanmagan belgilar o'rniga qo'yadi. Boshqa xatolarni tuzatish uchun hech qanday asosiy narsani taklif qilib bo'lmaydi. Assembler xato bayonotini aniqlaganida qila oladigan eng yaxshi narsa bu xato xabarini ekranda ko'rsatish va yig'ishni davom ettirishga harakat qilishdir.