Анимация
JavaScript
|
Главная Библионтека реализованы довольно эффективно... обычно очень сложно улучшить код, сгенерированный для IF или WHILE. Но практически каждый компилятор, который я когда-либо видел, генерирует ужасный код, по сравнению с ассемблером, для вычисления булевых функций и особенно отношений. Причина как раз в том, о чем я упомянул выше. Когда я пишу код на ассемблере, я двигаюсь вперед и выполняю проверку наиболее удобным для меня способом, и затем подготавливаю ветвление так чтобы переход был выполнен на нужную ветку. Фактически, я "подстраиваю" каждое ветвление под ситуацию. Компилятор не может сделать этого (практически) и он также не может знать, что нам не нужно сохранять результат проверки как булевскую переменную. Поэтому он должен генерировать код по очень строгим правилам и часто заканчивает сохранением результата как булевой переменной, которая никогда не будет использована для чего-либо. В любом случае мы теперь готовы рассмотреть код для Relation. Он показан ниже с сопровождающими процедурами: { Recognize and Translate a Relational "Equals" } procedure Equals; begin Match(=); Expression; EmitLnCCMP (SP) + ,D0); EmitLn(SEQ D0); end; { Recognize and Translate a Relational "Not Equals" } procedure NotEquals; begin Match(#); Expression; EmitLn(CMP (SP)+,D0); EmitLn(SNE D0); end; { Recognize and Translate a Relational "Less Than" } procedure Less; begin Match(<); Expression; EmitLn(CMP (SP)+,D0); EmitLn(SGE D0); end; { Recognize and Translate a Relational "Greater Than" } procedure Greater; begin Match(>); Expression; EmitLn(CMP (SP)+,D0); EmitLn(SLE D0); end; { Parse and Translate a Relation } procedure Relation; begin Expression; if IsRelop(Look) then begin EmitLn(MOVE D0,-(SP)); case Look of =: Equals; #: NotEquals; <: Less; >: Greater; end; EmitLnCTST D0); end; end; Теперь этот вызов Expression выглядит знакомым! Вот где редактор вашей системы оказывается полезным. Мы уже генерировали код для Expression и его близнецов на предыдущих уроках. Теперь вы можете скопировать их в ваш файл. Не забудьте использовать односимвольную версию. Просто чтобы быть уверенным, я продублировал арифметические процедуры ниже. Если вы наблюдательны, вы также увидите, что я их немного изменил чтобы привести в соответствие с последней версией синтаксиса. Эти изменения не являются необходимыми, так что вы можете предпочесть оставить все как есть до тех пор, пока не будете уверены, что все работает. { Parse and Translate an Identifier } procedure Ident; var Name: char; begin Name:= GetName; if Look = ( then begin MatchCC); Match()); EmitLn(BSR + Name); end else EmitLnCMOVE + Name + (PC),D0); end; { Parse and Translate a Math Factor } procedure Expression; Forward; procedure Factor; begin if Look = ( then begin MatchCC); Expression; Match()); end else if IsAlpha(Look) then Ident else EmitLnCMOVE # + GetNum + ,D0); end; { Parse and Translate the First Math Factor } procedure SignedFactor; begin if Look = + then GetChar; if Look = - then begin GetChar; if IsDigit(Look) then EmitLn(MOVE #- + GetNum + ,D0) else begin Factor; EmitLn(NEG D0); end; else Factor; end; { Recognize and Translate a Multiply } procedure Multiply; begin Match(*); Factor; EmitLn(MULS (SP)+,D0); end; { Recognize and Translate a Divide } procedure Divide; begin Match(/); Factor; EmitLn(MOVE (SP)+,D1); EmitLn(EXS.L D0); EmitLn(DIVS D1,D0); end; { Parse and Translate a Math Term } procedure Term; begin SignedFactor; while Look in [*, /] do begin EmitLnCMOVE D0,-(SP)); case Look of *: Multiply; /: Divide; end; end; end; { Recognize and Translate an Add } procedure Add; begin Match(+); Term; EmitLn(ADD (SP)+,D0); end; { Recognize and Translate a Subtract } procedure Subtract; begin Match(-); Term; EmitLn(SUB (SP)+,D0); EmitLn(NEG D0); end; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [ 22 ] 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |