Иди на текст

Трећа вежба

SimpSim - једноставан симулатор процесора

Преузимање и инсталација

Линк за преузимање | Сајт пројекта

Преузета извршна датотека је сама по себи цео програм у коме се ради - није потребно инсталирати, већ само покренути извршну датотеку и користити програм.

Уколико сте на macOS или GNU+Linux платформама, можете покренути овај програм коришћењем 🍷 WINE (Wine Is Not Emulator), односно CrossOver (комерцијална верзија WINE-a са подршком за нове везије macOS-a, Free Trial сасвим довољан за ове потребе) програма. WINE и CrossOver транслирају Windows системске позиве у POSIX позиве које разуму Linux и macOS, те је могуће на тај начин покренути апликације за Windows на овим платформама. Подршака за апликације путем WINE-a знатно варира, али SimpSimp ради без видних проблема с обзиром на то да је апликација из :simple-windows95: Windows 98 ере.

✨ FUN FACT: Steam Deck не користи Windows, већ Linux кернел и Proton (Valve-ова верзија WINE-a са DXVK и VKD3D) како би било могуће покренути Windows видео-игре на Linux платформи.

Задаци

1.

Доделити вредност 5 регистру R1, а вредност 8 регистру R2. Сумирати садржаје регистара R1 и R2, а резултат сместити у регистар R3. Приказати садржај регистра R3 након извршења програма, као и вредност регистра инструкције. Приказати изглед главне меморије.

1
2
3
4
load R1,5       ;Додели декадну вредност "5" регистру "R1"
load R2,8       ;Додели декадну вредност "8" регистру "R2"
addi R3,R1,R2   ;Сумирај регистре "R1" и "R2", смести резултат у "R3"
halt            ;Крај програма.

2.

Доделити вредност 5 регистру R1, а вредност 8 регистру R2. Одузети садржаје регистара R1 и R2, а резултат сместити у регистар R1. Приказати садржај регистра R1 након извршења програма, као и вредност регистра инструкције. Дати објашњење садржаја регистра R1. Приказати изглед главне меморије.

1
2
3
4
5
6
7
8
load R1,5        ;Додели декадну вредност "5" регистру "R1"
load R2,8        ;Додели декадну вредност "8" регистру "R2"
load RF,11111111b;Попуна регистра "RF" јединицама
load RE,1        ;Додели 1 регистру "RE"
xor  R2,R2,RF    ;Негација регистра "R2" ексклузивним ИЛИ (НК)
addi R2,R2,RE    ;Додај 1 (ПК)
addi R1,R1,R2    ;Сумирај регистре "R1" и "R2", смести резултат у "R1"
halt             ;Крај програма.

Тражи се разлика два броја, међутим SimpSim (колико проверих) нема инструкцију одузимања! Како се у задатку тражи да се регистру R2 додели вредност 8, потребно је да се на неки начин тај број пребаци у негативан. SimpSim памти бројеве у потпуном комплементу (ПК), стога да би се број представио као негативан, потребно је да се битови регистра R2 прво „изврну”, тј. да се комплементирају/негирају. Поново, ни негација (колико видех) не постоји у SimpSim-у, па као замена се може користити XOR (ексклузивно ИЛИ).

Употребом xor над регистром R2 и неким помоћним регистром RF који је попуњен јединицама (1111 1111) негирамо/комплементирамо садржај R2, јер је \(1 \oplus x\) (1 XOR x) исто што и \(\overline{x}\) (x комплемент). Тиме се добија непотпун комплемент (НК).
Затим, додамо 1 (који чувамо у помоћни регистар RE) на регистар R2 и тиме се добија потпун комплемент (ПК) вредности регистра R2.
Напослетку, сабрати регистре R1 и R2, резултат сместити у R1.

Резултат програма би требало да буде 5 - 8 = -3, па је онда декадна вредност регистра R1 = -3, што је хексадекадно FD у потпуном комплементу.

То би било „комплетно коректно” решење, али можемо и „варати” и директрно регистру R2 доделити вредност-8 и асистенти би и такво решење признали:

1
2
3
4
load R1,5       ;Додели декадну вредност "5" регистру "R1"
load R2,-8      ;Додели декадну вредност "-8" регистру "R2"
addi R1,R1,R2   ;Сумирај регистре "R1" и "R2", смести резултат у "R1"
halt            ;Крај програма.

3.

Доделити вредност 8 регистру R1, а потом извршити ротирање садржаја регистра R1 за једно место улево. Који је сада садржај регистра R1 и регистара инструкције? Мењати вредност регистара R1 и видети шта се добија.

1
2
3
load R1,8;Додели декадну вредност "8" регистру "R1"
ror  R1,7;Ротирање садржаја R1 за 7 места удесно
halt     ;Крај програма.

Како инструкција ротирања улево не постоји, мора се користити ротирање удесно (ror). Може се ротирати 7 пута удесно, што је еквивалентно ротирању једном улево (битови ће кружити, бит с краја при ротирању ће прећи на почетак). Број 8 представљен бинарно је 0000 1000; при ротирању за једно место улево биће 0001 0000, што је еквивалентно декадном броју 16, односно 10 хексадекадно, што ће управо и бити садржај регистра R1.

4.

Након извршења наредног скупа инструкција, шта се налази у регистрима R1, R2, R3 и R4? Објаснити садржај регистра R2 и пратити регистар инструкција у току извршавања програма корак по корак.

1
2
3
4
5
6
load R1,0Ah
load R2,[R1]
load R3,04d
addi R4,R2,R3
halt
db   1,2,3,4,5

Садржај регистара R1 и R3 се јасно види из ко̑да програма. R1 је , а R3 je 04.
Регистру R2 ће бити додељена вредност која се налази на меморијској адреси/локацији на коју указује вредност регистра R1. Вредност R1 je , па ће регистар R2 добити вредност записану на адреси 0A (00 ред, ..А колона главне меморије). При асембловању програма на тој адреси ће бити записана вредност 01, па је онда R2 = 01.
Одакле вредност 01 у меморији? За то је крива инструкција db 1,2,3,4,5, која редом уписује у меморију 01, 02, ... , 05 при асембловању програма.
Коначно, R4 ће добити вредност збира регистара R2 и R3, а то је 04 + 01 = 05 (обратити пажњу да су поменуте вредности регистара изражене хексадекадно!).
Дакле, R1 = 0A; R2 = 01; R3 = 04; R4 = 05.

5.

Након извршења наредног скупа инструкција, шта се налази у регистрима R1, R2 и R3? Објаснити садржај регистра R2 и пратити регистар инструкција у току извршавања програма корак по корак.

1
2
3
4
5
load R1,8d
load R2,-12d
addi R3,R1,R2
ror  R3,2
halt

Садржај регистра R1 биће 08, a R2 ће бити F4 (потпуни комплемент декадног броја -12 у хексадекадном запису).
Регистар R3 ће прво придобити збир регистара R1 и R2, што ће бити FC (-4).
Ротирањем битоvа R3 за 2 места удесно добија се: 1111110000111111, тј. FC3F.
Дакле, R1 = 08; R2 = F4; R3 = 3F.

6.

Ако је садржај регистра R1 једнак 48 хексадекадно, а садржај регистра R2 једнак 11 хексадекадно, одредити садржај регистра R3 након извршења следећег низа наредби. Пратити регистар инструкција у току извршавања програма корак по корак.

1
2
3
4
load R1,48h
load R2,11h
xor  R3,R1,R2
ror  R3,1

xor R3,R1,R2 ће применити XOR (ексклузивно ИЛИ) операцију бит-по-бит над регистрима R1 и R2 и резултат операције сместити у R3.
48h = 01001000
11h = 00010001
XOR = 01011001 = 59 (хексадекадно)

Напослетку, ротирањем битова регистра R3 за једно место удесно (ror R3,1):
0101100110101100 = AC (хексадекадно).
То јест, R1 = 48; R2 = 11; R3 = AC.

7.

Ако је садржај регистра R1 једнак 48 хексадекадно, а садржај регистра R2 једнак 77 хексадекадно, одредити садржај регистра R1 након извршења следећег низа наредби. Пратити регистар инструкција у току извршавања програма корак по корак.

1
2
3
4
load R1,48h
load R2,77h
or   R1,R1,R2
ror  R1,2

or R1,R1,R2 ће применити OR (ИЛИ) операцију бит-по-бит над регистрима R1 и R2 и резултат операције сместити у R1.
48h = 01001000
77h = 01110111
OR = 01111111 = 7F (хексадекадно)

Напослетку, ротирањем битова регистра R1 за два место удесно (ror R1,2):
0111111111011111 = DF (хексадекадно).
То јест, R1 = DF; R2 = 77.

8.

Ако је садржај регистра R1 једнак 4F хексадекадно, а садржај регистра R2 једнак 15 хексадекадно, одредити садржај регистра R3 након извршења следећег низа наредби. Пратити регистар инструкција у току извршавања програма корак по корак.

1
2
3
4
load R1,4Fh
load R2,15h
and  R3,R1,R2
ror  R3,3

and R3,R1,R2 ће применити AND (И) операцију бит-по-бит над регистрима R1 и R2 и резултат операције сместити у R3.
4Fh = 01001111
15h = 00010101
AND = 00000101 = 05 (хексадекадно)

Напослетку, ротирањем битова регистра R3 за три место удесно (ror R3,1):
0000010110100000 = А0 (хексадекадно).
То јест, R1 = 4F; R2 = 15; R3 = А0.

9.

Ако је садржај регистра R1 једнак 47 хексадекадно, а садржај регистра R2 једнак 73 хексадекадно, одредити садржај регистра R1 након извршења следећег низа наредби. Пратити регистар инструкција у току извршавања програма корак по корак.

1
2
3
4
5
load R1,47h
load R2,73h
ror  R1,1
xor  R1,R1,R2
addi R1,R1,R2

ror R1,1 ће ротирати битове регистра R1 за једно место удесно:
47h = 01000111
0100011110100011 = A3 (хексадекадно)

xor R1,R1,R2 ће применити XOR (ексклузивно ИЛИ) операцију бит-по-бит над регистрима R1 и R2 и резултат операције сместити у R1.
A3h = 10100011
73h = 01110011
XOR = 11010000 = D0 (хексадекадно)

Напослетку, збир регистара R1 и R2 се смести у регистар R1 (addi R1,R1,R2):
(хексадекадно) D0 + 73 = 143208 + 115 = 323 (декадно)

ВАЖНО

Подсетимо се да SimpSim ради са 8-битним бројевима, па је највећи број који можемо сместити FF хексадекадно, тј. 255 декадно (28) . Приметимо да је 143 > FF, није могуће да број у целости буде смештен у регистру, па ће бити запамћен као 43 (дошло је до overflow-a)!!

Дакле, вредности уписане у регистрима биће: R1 = 43; R2 = 73.

10.

Након извршења наредног скупа инструкција, шта се налази у регистрима R0, R1, R2 и RF? Пратити вредност регистара наредбу по наредбу, као и садржај регистра инструкција.

1
2
3
4
5
6
7
8
         load R1,5d
         load R2,1d
         load R0,7d
Labela1: load RF,[R1]
         addi R1,R1,R2
         jmpEQ RF=R0,KrajProg
         jmp Labela1
KrajProg:halt

НАПОМЕНА

Изгледа да постоји грешка код ко̑да овог задатка на 4. линији у документу са cs Moodle-a. Пазите од дакле гледате кодове! У документу лаб. вежбе је 4. линија написана као load RF,R1, што није валидна синтакса, већ треба бити load RF,[R1] као што је то исправно написано у наредном задатку.

У регистру R1 биће учитана вредност 05, у R2 вредност 01 и у регистру R0 вредност 07. Регистар RF ће добити вредност меморијске адресе на коју указује вредност регистра R1; како је вредност регистра R1 = 05, RF ће добити вредност која је уписана на меморијској адреси 05 (00 ред, ..5 колона главне меморије). По асембловању програма, на тој меморијској адреси ће се налазити вредност 07 (што је заправо операнд 7d из наредбе load R0,7d)

Резултат збира регистара R1 и R2 се потом смешта у регистар R1 (addi R1,R1,R2):
R1 = 05 + 01 = 06 (хексадекадно)

Условни скок jmpEQ RF=R0,KrajProg ће бити задовољен, јер су вредности регистара RF и R0 једнаке и износе 07, и програм ће прећи на линију обележену лабелом KrajProg где се завршава.

Вредности регистара су онда: R0 = 07; R1 = 06; R2 = 01; RF = 07.

11.

Након извршења наредног скупа инструкција, шта се налази у регистрима R0, R1, R2 и RF? Пратити вредност регистара инструкцију по инструкцију, као и садржај регистра инструкција. Колико пута се изврши наредба addi?

1
2
3
4
5
6
7
8
         load R1,8d
         load R2,-1d
         load R0,5d
Labela1: load RF,[R1]
         addi R1,R1,R2
         jmpEQ RF=R0,KrajProg
         jmp Labela1
KrajProg:halt

У регистру R1 биће учитана вредност 08, у R2 вредност FF (потпун комплемент броја -1 у хексадекадном запису) и у регистру R0 вредност 05.

1) Регистар RF ће добити вредност меморијске адресе на коју указује вредност регистра R1; како је вредност регистра R1 = 08, RF ће добити вредност која је уписана на меморијској адреси 08 (00 ред, ..8 колона главне меморије). По асембловању програма, на тој меморијској адреси ће се налазити вредност 51 (што је кôд инструкције addi, 5, и број регистра у који се смешта резултат инструкције, 1, са линије addi R1,R1,R2).

Резултат збира регистара R1 и R2 се потом смешта у регистар R1 (addi R1,R1,R2):
R1 = 08 + FF = 07 (хексадекадно)

Условни скок jmpEQ RF=R0,KrajProg неће бити задовољен,RFR05105, програм наставља са наредном линијом.
jmp Labela1, програм се враћа на линију означеном са лабелом Labela1.

2) RF узима вредност са меморијске адресе 07 (вредност регистра R1), што је вредност F1.
addi R1,R1,R2: R1 = 07 + FF = 06
jmpEQ RF=R0,KrajProg: RFR0F105, програм наставља са наредном линијом.
jmp Labela1: програм се враћа на линију означеном са лабелом Labela1.

3) RF узима вредност са меморијске адресе 06 (вредност регистра R1), што је вредност D0.
addi R1,R1,R2: R1 = 06 + FF = 05
jmpEQ RF=R0,KrajProg: RFR0D005, програм наставља са наредном линијом.
jmp Labela1: програм се враћа на линију означеном са лабелом Labela1.

4) RF узима вредност са меморијске адресе 05 (вредност регистра R1), што је вредност 05.
addi R1,R1,R2: R1 = 05 + FF = 04
jmpEQ RF=R0,KrajProg: RF = R005 = 05, услов је испуњен и програм прелази на линију означену лабелом KrajProg где се програм завршава.

Дакле, инструкција addi се извршила четири пута.
При том, вредности регистара су R0 = 05; R1 = 04; R2 = FF; RF = 05.

12.

Колико пута ће се извршити инструкција addi у наредном скупу инструкција? Након извршења наредног скупа инструкција, шта се налази у регистрима R1 и R2 након два извршења инструкције addi?

1
2
3
4
         load R1,0
         load R2,1
NextChar:addi R1,R1,R2
         jmp  NextChar

У регистру R1 биће учитана вредност 00 и у R2 вредност 01.

Инструкција addi ће се извршавати безброј пута. jmp инструкција ће враћати програм назад на линију обележеном NextChar лабелом, што је линија на којој је addi инструкција.

Након два извршења addi инструкцијe, садржај регистра R1 биће 02, а садржај R2 непромењен 01.

addi R1,R1,R2 ≡ R1 = R1 + R2

У почетном тренутку при извршавању пограма: R1 = 0; R2 = 1.
i = 1; R1 = 0 + 1 ⇒ R1 = 1; R2 = 1.
i = 2; R1 = 1 + 1 ⇒ R1 = 2; R2 = 1.

Ово се може проверити „степовањем” кроз програм и пратећи ред извршавања инструкција у дисемблер прозору. Чим се прође инструкција addi два пута, проверити вредности записане у регистрима.

13.

Након извршења наредног скупа инструкција, шта се налази у регистрима R0, R1, R2 и RF? Пратити вредност регистара инструкцију по инструкцију, као и садржај регистара инструкција. Колико пута се изврши наредба addi?

1
2
3
4
5
6
7
8
         load R1,15d
         load R2,4d
         load R0,5d
Labela1: load RF,[R1]
         addi R1,R1,R2
         jmpLE RF<=R0,KrajProg
         jmp Labela1
KrajProg:halt

У регистру R1 биће учитана вредност 0F, у R2 вредност 04 и у регистру R0 вредност 05.

Регистар RF ће добити вредност меморијске адресе на коју указује вредност регистра R1; како је вредност регистра R1 = 0F, RF ће добити вредност која је уписана на меморијској адреси 0F (00 ред, ..F колона главне меморије). По асембловању програма, на тој меморијској адреси ће се налазити вредност 00 (у тој меморији ништа није уписано).

Резултат збира регистара R1 и R2 се потом смешта у регистар R1 (addi R1,R1,R2):
R1 = 0F + 04 = 13 (хексадекадно)

Условни скок jmpLE RF<=R0,KrajProg биће испуњен, RFR00005, па ће програм прећи на линију означеном са KrajProg лабелом где се програм и завршава.

Крајњи резултати регистара су R0 = 05; R1 = 13; R2 = 04; RF = 00.

14.

Након извршења наредног скупа инструкција, шта се налази у регистрима R0, R1, R2 и RF? Пратити вредност регистара инструкцију по инструкцију, као и садржај регистра инструкција. Колико пута се изврши наредба addi?

1
2
3
4
5
6
7
8
         load R1,5d
         load R2,3d
         load R0,15d
Labela1: load RF,[R1]
         addi R1,R1,R2
         jmpLE RF<=R0,KrajProg
         jmp Labela1
KrajProg:halt

У регистру R1 биће учитана вредност 05, у R2 вредност 03 и у регистру R0 вредност 0F.

Регистар RF ће узети вредност са меморијске локације на коју вредност регистра R1 указује (load RF,[R1]). R1 ће имати вредност 05 , значи да ће RF добити вредност записану у меморијској локацији 05 (00 ред, ..5 колона главне меморије). По извршавању програма, на тој меморијској локацији ће се налазити вредност 0F (што је заправо операнд 15d представљен хексадекадно из наредбе load R0,15d).
Условни скок jmpLE RF<=R0,KrajProg ће бити испуњен (вредности RF и R0 биће једнаке) и програм ће прећи на линију обележену лабелом KrajProg где се завршава.

Закључак, наредба addi ће се извршити само једном. Ово се може проверити „степовањем” кроз програм и пратећи ред извршавања инструкција у дисемблер прозору.

Извршавањем инструкције addi R1,R1,R2, резултат збира регистара R1 и R2 биће смештен у R1, што ће бити:
R1 = 05 + 03 = 08 (хексадекадно)

Сходно томе, вредности регистара су R0 = 0F; R1 = 08; R2 = 03; RF = 0F.

15.

Након извршења наредног скупа инструкција, шта се налази у регистрима R0, R1, R2 и RF? Пратити вредност регистара инструкцију по инструкцију, као и садржај регистара инструкција. Колико пута ће се извршити ротирање садржаја регистра R2 за једно место удесно?

1
2
3
4
5
6
7
8
9
         load R1,4d
         load R2,3d
         load R0,01d
Labela1: load RF,[R1]
         addi R1,R1,R2
         ror R2,1
         jmpLE RF<=R0,KrajProg
         jmp Labela1
KrajProg:halt

У регистру R1 биће учитана вредност 04, у R2 вредност 03 и у регистру R0 вредност 01.

1) Регистар RF ће добити вредност меморијске адресе на коју указује вредност регистра R1; како је вредност регистра R1 = 04, RF ће добити вредност која је уписана на меморијској адреси 04 (00 ред, ..4 колона главне меморије). По асембловању програма, на тој меморијској адреси ће се налазити вредност 20 (што је кôд инструкције load, 2, и број регистра у који се смешта резултат инструкције, 0, са линије load R0,01d).

Резултат збира регистара R1 и R2 се потом смешта у регистар R1 (addi R1,R1,R2):
R1 = 04 + 03 = 07 (хексадекадно)

Битови регистара R2 се ротирају за једну позицију удесно (ror R2,1): R2 = 03 = 0000 0011
0000 00111000 0001 = 81 (хексадекадно)
R2 постаје 81.

Условни скок jmpLE RF<=R0,KrajProg неће бити задовољен, RF > R020 > 01, програм наставља са наредном линијом.
jmp Labela1, програм се враћа на линију означеном са лабелом Labela1.

2) RF узима вредност са меморијске адресе 07 (вредност регистра R1), што је вредност F1.
addi R1,R1,R2: R1 = 07 + 81 = 88
ror R2,1: 811000 00011100 0000C0
jmpLE RF<=R0,KrajProg: RFR0F101, услов је испуњен (F1 би требало да је негативан број, представљен у потпуном комплементу, па је зато мањи од 1, те је услов испуњен, ако има смисла…) и програм прелази на линију означену лабелом KrajProg где се и завршава.

Дакле, инструкција ror (ротирања садржаја регистра R2) се извршила два пута.
При том, вредности регистара су R0 = 01; R1 = 88; R2 = C0; RF = F1.