Karh09 7

7. Инструкции за управление на програмата – условни и безусловни преходи. Преходи в подпрограми и връщане.


страницата се нуждае от дописване/преглеждане


Имаме специална група инструкции, които нарушават концептуалния ред на последователно изпълнение в Ноймановата архитектура. Тези инструкции включват инструкцията за условен преход (branch), безусловен преход (jump), за влизане в подпрограма (program calls), връщане на подпрограми (program return) също и командите system calls и system returns. Последните 2 команди са за достъп до системни програми и системните програми са достъпни само чрез system call.

Аспекти на управляващите инструкции

  • Ще/Няма да има преход.(прави се само при branch)
  • Как се изчислява адресът на прехода. (прави се при всички управляващи инструкции за да се види на къде продължава действието на програмата, следващата стойност на програмния брояч) Ще го разгледаме в следващата тема.
  • Link Return Address - връзване на адресите на връщане(прави се при преходи call - тоест при подпрограмите)
  • Как ще се запаси състоянието на общите регистри(прави се при call и return)

Инструкции за управление

  • jump за безусловен преход (unconditional);
  • branch за условен преход (conditional)
  • инструкции за извикване връщане на подпрограми
    • call
    • return
  • инструкции за системно извикване и връщане
    • system calls
    • system returns

Ще/Няма да има преход.

Заради конвейера казваме, че условните преходи са „убиец”. Устройството за предварително разпознаване не може да разпознае прехода, поради което инструкциите за условен преход прекъсват конвейера.
Условно преместване
blez(ако е по-малко или равно на нула) - пример за “compare and branch” инструкция
Aко имаме фрагмента if (a > 0) c = b*a; това със стандартни инструкции би изглеждало така

#0 blez r1, #2 ( Branch Less than or Equal to Zero )
#1 mul r3, r2, r1
#2 ...

Ако r1 е по-малко или равно на нула се отива директно на инструкция #2, т.е прескача се умножението. При условната инструкция blez се разкъса конвейера и целия се изчиства за да се почисти само стъпка #1. Изключително неудобно.
cmovgt (сравнява и мести ако е по-голямо от нула) – пример за отделни “compare” и “branch” инструкции
Ако има инструкция с условно местене:

#0 mul r4,r2,r1
#1 cmovgt r3,r4,r1 //Conditional MOVe Greater Than zero

Ако r1 <= 0 в r3 не отива резултатът - няма преход, нито нарушаване на конвейра.
При blez варианта умножението не се изпълнява ако не е нужно, докато при втория вариант само запазването на резултата се прескача. При по-дълги конвейри е по-добре да се направят излишни сметки (като във втория случай) само за да не се наложи изпразване на целия конвейр (защото това би било по-бавно). При втория вариянт е необходимо да се отдели място за флаг : Zero, Negative, oVerflow, Carry , който се слага „безплатно” от АЛУ-то при оценката на двата операнда.

Link Return Address - Преходи към подпрограми

Друга особеност на инструкциите за прехода е преходът към подпрограма. За да може да е динамично(извиканата подпрограма да се връща там откъдето е извикана), програмата трябва да знае с какъв преход да се върне – това става чрез link return register.
untitled25.JPG
В самата инструкция на извиканата подпрограма не се вижда адресът на връщането. Той може да се укаже експлицитно или да бъде в регистър по премълчаване (имплицитно указване). При извикването на подпрограмата програмният брояч се обновява със следващата инструкция в паметта, новополученият адрес се запомня във указания регистър Rx или регистър по премълчаване Re или в стека. Когато програмистът указва в кой регистър се запазва адреса на връщане, трябва да внимава подпрограмата да не промени стойността на този регистър.
Друга възможност е адресът за връщане директно да се записва в стек – тогава при всяко извикване на подпрограма адресът за връщане се вмъква във върха на стека и при връщане от подпрограмата този адрес се изважда от върха на стека и се записва в PC. По този начин се решава проблемът с извикването на няколко вложени подпрограми.
При всяко влизане в подпрограма се налага да се запазва състоянието на процесора. При извикване на call се запазват само регистрите, при извикване на system call освен регистрите се запазват указателите към стека и др.
untitled26.JPG
Най-често начинът за връзка между подпрограмите се осъществява с имплицитен регистър за връзка, в който се записва адресът за връщане.
При имплицитните регистри за връзка всяка инструкция за преход към подпрограма записва адреса на връщане в един и същи регистър – за това трябва да се внимава при последователни преходи да не се изгубят предишни адреси.
Софтуерното запазване на състоянието става преди инструкцията call, така че адресът за връщане не е бил запазен в запомненото състояние на регистрите. При последователни извиквания не е проблем новият адрес за връщане да се записва в същия регистър за връзка, поради запазването на състоянието – единственото ограничение е самите подпрограми да не променят регистъра за връзка по време на изпълнението си. В края на всяка подпрограма се извиква инструкция jump с номер регистъра за връзка и по този начин управлението се връща на извикващата програма.

Save or Restore State - Запазване на регистрите

untitled27.JPG

Последният аспект на управляващите инструкции е запазването на регистрите. За да работи по-бързо една програма се работи с операнди записани в регистрите. При всеки преход към подпрограма този контекст се губи и трябва да се възстанови при връщането. Тази програма трябва да има област на запазване (save area), в която временно се записва този контекст. Софтуерната конвенция е извикващата функция да има грижата да запази контекста си, и при връщане от подпрограмата да го възстанови. В мястото за връщане трябва да има инструкция за връщане на контекста, тоест всеки път се прави multiple load и multiple store, за запазване и зареждане на всички регистри. Има регистър Rsa, в който се пази адресът на тази save area. Има и друга конвенция(callee) при която подпрограмата се грижи преди return да попълни регистрите със информацията, такава каквато е била при нейното извикване.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License