Системски софтвер/Пројекат

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу

Пројекат на предмету Системски софтвер је обавезан и састоји се од 3 програма који чине скуп алата за развој софтвера на апстрактном рачунарском систему. Овај водич тежи да буде независан од поставке, која се незнатно мења из године у годину.

Подела по целинама

Због свог великог обима, препоручује се детаљна разрада захтева на лако разумљиве целине и кораке. Препоручује се следећи редослед задатака:

  1. Табеларно представљање машинских инструкција и адресирања у склопу симболичког машинског језика асемблера и самог машинског кода. Пре него што се крене са имплементацијом лексера и парсера неопходно је детаљно прегледати тражене захтеве у језику.
  2. Израда модела симболичког машинског језика у софтверу. Овде се може применити објектно оријентисани приступ моделовању, или структурни приступ налик излазном формату.
  3. Развој лексера и парсера користећи генераторе flex и bison или писањем свог лексера и парсера.
  4. Израда модела излазних података асемблера. Ово укључује секције, релокације, симболе и све што није било покривено моделовањем језика.
  5. Имплементација самог асемблирања. Пролази се кроз излаз парсера и попуњава излазни модел.
  6. Опционо текстуално/графичко представљање излазних података налик readelf и objdump олакшава дебаговање.
  7. Тестирање асемблера.
  8. Моделовање и имплементација излазног бинарног формата асемблера
  9. Модел улазних података линкера. Могу се користити и структуре из асемблера, али није препоручљиво јер су неопходни подаци за рад линкера и асемблера знатно различити - све постојеће енкапсулације и интерфејси вероватно нису довољно универзални или су ограничавајући.
  10. Имплементација линкера
  11. Имплементација исписа радне меморије у текстуални фајл, као и исписа у претходно осмишљени објектни формат, за шта код не би требало да се знатно разликује.
  12. Тестирање линкера.
  13. Моделовање меморије у емулатору. Учитавање меморије из фајла.
  14. Моделовање процесора, регистара, обраде прекида.
  15. Имплементација емулирања инструкција. Са нагласком на пажљиво писање кода и разумевање поставке.
  16. Имплементација периферије терминал. Поставка препоручује termios библиотеку.
  17. Имплементација периферије тајмер.
  18. Тестирање емулатора.

Не треба заборавити писање make скрипте за прављење пројекта при самом почетку израде, зато што се знатно убрзава време превођења. Презентација која објашњава како користити GNU make се налази у одељку Вежбе 2.

Субјективно гледано, делови пројекта који највише одузимају времена су: лексичка анализа (време учења алата или писање својих), формат излазног фајла (неопходно је наћи баланс између лаког генерисања и лаког читања) и тестирање емулатора (мале грешке у понашању инструкција).

Асемблер

Табеларно представљање машинских инструкција и адресирања

Поставка пројекта садржи много информација које нису нарочито квалитетно организоване и представљене. Табеларна реорганизација пројекта помаже при изради и зато се препоручује. Дат је пример за пројекат из 2022. године. Приметити да је у овој поставци податак у инструкцији big endian, а податак у меморији little endian. Подебљана слова означавају поља која се замењују при генерисању машинског кода. Значења су: D - одредишни регистар S - изворни регистар.

Инструкције у асембли језику
Инструкција Дужина у бајтовима InstrDescr RegsDescr AddrMode DataHigh DataLow
0 1 2 3 4
HALT 1 00
IRET 1 20
RET 1 40
INT 2 10 DF
PUSH 3 B0 6S 12
POP 3 A0 D6 42
NOT 2 80 D0
XCHG 2 60 DS
ADD 2 70 DS
SUB 2 71 DS
MUL 2 72 DS
DIV 2 73 DS
CMP 2 74 DS
AND 2 81 DS
OR 2 82 DS
XOR 2 83 DS
TEST 2 84 DS
SHL 2 90 DS
SHR 2 91 DS
CALL 3/5 30 FS Адресирање за скок
JMP 3/5 50 FS Адресирање за скок
JEQ 3/5 51 FS Адресирање за скок
JNE 3/5 52 FS Адресирање за скок
JGT 3/5 53 FS Адресирање за скок
LDR 3/5 A0 DS Адресирање за податке
STR 3/5 B0 DS Адресирање за податке

У табелама адресирања, поља су: L - део литерала S - део вредности симбола, D - одредишни регистар, R - изворни регистар.

Адресирање за скок
Нотација Адресирање 1 2 3 4
<literal> Непосредно F0 00 LL LL
<symbol> Непосредно F0 00 SS SS
%<symbol> PC релативно F7 05 SS SS
*<literal> Мем. директно F0 04 LL LL
*<symbol> Мем. директно F0 04 SS SS
*<reg> Рег. директно FR 01
*[<reg>] Рег. индиректно FR 02
*[<reg>+<lit>] Рег. инд. са померајем FR 03 LL LL
*[<reg>+<sym>] Рег. инд. са померајем FR 03 SS SS
Адресирање за податке
Нотација Адресирање 1 2 3 4
$<literal> Непосредно D0 00 LL LL
$<symbol> Непосредно D0 00 SS SS
%<symbol> PC релативно D7 03 SS SS
<literal> Мем. директно D0 04 LL LL
<symbol> Мем. директно D0 04 SS SS
<reg> Рег. директно DR 01
[<reg>] Рег. индиректно DR 02
[<reg>+<lit>] Рег. инд. са померајем DR 03 LL LL
[<reg>+<sym>] Рег. инд. са померајем DR 03 SS SS

Овакве табеле одлично представљају шта је дати излаз у машинском коду за дати улаз у језику. Препорука је користити их при моделирању улазних података и лексичке анализе.

Моделовање језика

Пример модела језика

Препорука је упознати се са алатима flex и bison пре писања било ког кода и даљег читања водича. Корисно је наћи туторијал:

Примена ових алата за асемблер није тривијална, и боље је издвојити време на писању простијих примера пре почетка писања асемблера, нпр. учитавање меморије из hex излаза линкера у емулатор.

Парсер уклапа улазни текст у претходно написана правила (више о томе на преводиоцима). Правила изгледају слично синтаксним нотацијама као на П1. Правила се уклапају од мањих до већих. Како се улаз уклопи у правило, изврши се одређена радња. Радња парсера у нашем случају је конструкција структура/објеката које представљају делове језика, и евентуално спајање тих језичких елемената у листу кроз коју пролази сам асемблер. На слици десно је дат пример модела.

Парсер попуњава листу елемената језика (намерно се не зову линије јер је могуће имати више њих у једној линији). Из елемената се изводе директиве и инструкције. Свака специјализација директиве садржи неки њој битан податак (назив симбола, литерали, изрази и слично) који ће парсер проследити из лексема (језичких јединица, нпр. литерал, идентификатор) при конструкцији. Слично важи и за инструкције, где су намерно одвојена адресирања као објекти које парсер креира пре уклапања у саму инструкцију, зато што парсер уклапа адресирања пре него што уклопи инструкцију са адресирањем. Касније, при настанку (уклапању) инструкције, она постаје власник објекта адресирања. Асемблер ће, помоћу оваквог модела, у својим пролазима (или пролазу) имати доступне све детаље из улазног фајла. Корисно је при конструкцији памтити и број линије на ком се елемент налази, ради лепшег извештавања грешака.

Линкер

Емулатор

Тестови