Системски софтвер/Пројекат
Пројекат на предмету Системски софтвер је обавезан и састоји се од 3 програма који чине скуп алата за развој софтвера на апстрактном рачунарском систему. Овај водич тежи да буде независан од поставке, која се незнатно мења из године у годину.
Подела по целинама
Због свог великог обима, препоручује се детаљна разрада захтева на лако разумљиве целине и кораке. Препоручује се следећи редослед задатака:
- Табеларно представљање машинских инструкција и адресирања у склопу симболичког машинског језика асемблера и самог машинског кода. Пре него што се крене са имплементацијом лексера и парсера неопходно је детаљно прегледати тражене захтеве у језику.
- Израда модела симболичког машинског језика у софтверу. Овде се може применити објектно оријентисани приступ моделовању, или структурни приступ налик излазном формату.
- Развој лексера и парсера користећи генераторе flex и bison или писањем свог лексера и парсера.
- Израда модела излазних података асемблера. Ово укључује секције, релокације, симболе и све што није било покривено моделовањем језика.
- Имплементација самог асемблирања. Пролази се кроз излаз парсера и попуњава излазни модел.
- Опционо текстуално/графичко представљање излазних података налик readelf и objdump олакшава дебаговање.
- Тестирање асемблера.
- Моделовање и имплементација излазног бинарног формата асемблера
- Модел улазних података линкера. Могу се користити и структуре из асемблера, али није препоручљиво јер су неопходни подаци за рад линкера и асемблера знатно различити - све постојеће енкапсулације и интерфејси вероватно нису довољно универзални или су ограничавајући.
- Имплементација линкера
- Имплементација исписа радне меморије у текстуални фајл, као и исписа у претходно осмишљени објектни формат, за шта код не би требало да се знатно разликује.
- Тестирање линкера.
- Моделовање меморије у емулатору. Учитавање меморије из фајла.
- Моделовање процесора, регистара, обраде прекида.
- Имплементација емулирања инструкција. Са нагласком на пажљиво писање кода и разумевање поставке.
- Имплементација периферије терминал. Поставка препоручује termios библиотеку.
- Имплементација периферије тајмер.
- Тестирање емулатора.
Асемблер
Табеларно представљање машинских инструкција и адресирања
Поставка пројекта садржи много информација које нису нарочито квалитетно организоване и представљене. Табеларна реорганизација пројекта помаже при изради и зато се препоручује. Дат је пример за пројекат из 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 |
Овакве табеле одлично представљају шта је дати излаз у машинском коду за дати улаз у језику. Препорука је користити их при моделирању улазних података и лексичке анализе.
Моделовање језика
Парсер уклапа улазни текст у претходно написана правила (више о томе на преводиоцима). Како се улаз уклопи у правило, изврши се одређена радња. Радња парсера у нашем случају је конструкција структура/објеката које представљају делове језика, и евентуално спајање тих језичких елемената у листу кроз коју пролази сам асемблер. На слици десно је дат пример модела.
Парсер попуњава листу елемената језика (намерно се не зову линије јер је могуће имати више њих у једној линији). Из елемената се изводе директиве и инструкције. Свака специјализација директиве садржи неки њој битан податак (назив симбола, литерали, изрази и слично) који ће парсер проследити из лексема (језичких јединица, нпр. литерал, идентификатор) при конструкцији. Слично важи и за инструкције, где су намерно одвојена адресирања као одвојени објекти које парсер креира пре уклапања у саму инструкцију. Касније, при настанку инструкцију, она постаје власник објекта адресирања. Асемблер ће, помоћу оваквог модела, у својим пролазима (или пролазу) имати доступне све детаље из улазног фајла. Корисно је при конструкцији памтити и број линије на ком се елемент налази, ради лепшег извештавања грешака.