Трећа вежба¶
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
након извршења програма, као и вредност регистра инструкције. Приказати изглед главне меморије.
2.¶
Доделити вредност 5
регистру R1
, а вредност 8
регистру R2
. Одузети садржаје регистара R1
и R2
, а резултат сместити у регистар R1
. Приказати садржај регистра R1
након извршења програма, као и вредност регистра инструкције. Дати објашњење садржаја регистра R1
. Приказати изглед главне меморије.
Тражи се разлика два броја, међутим 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
и асистенти би и такво решење признали:
3.¶
Доделити вредност 8
регистру R1
, а потом извршити ротирање садржаја регистра R1
за једно место улево. Који је сада садржај регистра R1 и регистара инструкције? Мењати вредност регистара R1
и видети шта се добија.
Како инструкција ротирања улево не постоји, мора се користити ротирање удесно (ror
). Може се ротирати 7 пута удесно, што је еквивалентно ротирању једном улево (битови ће кружити, бит с краја при ротирању ће прећи на почетак). Број 8
представљен бинарно је 0000 1000
; при ротирању за једно место улево биће 0001 0000
, што је еквивалентно декадном броју 16
, односно 10
хексадекадно, што ће управо и бити садржај регистра R1
.
4.¶
Након извршења наредног скупа инструкција, шта се налази у регистрима R1
, R2
, R3
и R4
? Објаснити садржај регистра R2
и пратити регистар инструкција у току извршавања програма корак по корак.
Садржај регистара R1
и R3
се јасно види из ко̑да програма. R1
је 0А
, а R3
je 04
.
Регистру R2
ће бити додељена вредност која се налази на меморијској адреси/локацији на коју указује вредност регистра R1
. Вредност R1
je 0А
, па ће регистар 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
и пратити регистар инструкција у току извршавања програма корак по корак.
Садржај регистра R1
биће 08
, a R2
ће бити F4
(потпуни комплемент декадног броја -12
у хексадекадном запису).
Регистар R3
ће прво придобити збир регистара R1
и R2
, што ће бити FC
(-4
).
Ротирањем битоvа R3
за 2 места удесно добија се: 11111100
→ 00111111
, тј. FC
→ 3F
.
Дакле, R1
= 08
; R2
= F4
; R3
= 3F
.
6.¶
Ако је садржај регистра R1
једнак 48
хексадекадно, а садржај регистра R2
једнак 11
хексадекадно, одредити садржај регистра R3
након извршења следећег низа наредби. Пратити регистар инструкција у току извршавања програма корак по корак.
xor R3,R1,R2
ће применити XOR (ексклузивно ИЛИ) операцију бит-по-бит над регистрима R1
и R2
и резултат операције сместити у R3
.
48h
= 01001000
11h
= 00010001
XOR
= 01011001
= 59
(хексадекадно)
Напослетку, ротирањем битова регистра R3
за једно место удесно (ror R3,1
):
01011001
→ 10101100
= AC
(хексадекадно).
То јест, R1
= 48
; R2
= 11
; R3
= AC
.
7.¶
Ако је садржај регистра R1
једнак 48
хексадекадно, а садржај регистра R2
једнак 77
хексадекадно, одредити садржај регистра R1
након извршења следећег низа наредби. Пратити регистар инструкција у току извршавања програма корак по корак.
or R1,R1,R2
ће применити OR (ИЛИ) операцију бит-по-бит над регистрима R1
и R2
и резултат операције сместити у R1
.
48h
= 01001000
77h
= 01110111
OR
= 01111111
= 7F
(хексадекадно)
Напослетку, ротирањем битова регистра R1
за два место удесно (ror R1,2
):
01111111
→ 11011111
= DF
(хексадекадно).
То јест, R1
= DF
; R2
= 77
.
8.¶
Ако је садржај регистра R1
једнак 4F
хексадекадно, а садржај регистра R2
једнак 15
хексадекадно, одредити садржај регистра R3
након извршења следећег низа наредби. Пратити регистар инструкција у току извршавања програма корак по корак.
and R3,R1,R2
ће применити AND (И) операцију бит-по-бит над регистрима R1
и R2
и резултат операције сместити у R3
.
4Fh
= 01001111
15h
= 00010101
AND
= 00000101
= 05
(хексадекадно)
Напослетку, ротирањем битова регистра R3
за три место удесно (ror R3,1
):
00000101
→ 10100000
= А0
(хексадекадно).
То јест, R1
= 4F
; R2
= 15
; R3
= А0
.
9.¶
Ако је садржај регистра R1
једнак 47
хексадекадно, а садржај регистра R2
једнак 73
хексадекадно, одредити садржај регистра R1
након извршења следећег низа наредби. Пратити регистар инструкција у току извршавања програма корак по корак.
ror R1,1
ће ротирати битове регистра R1
за једно место удесно:
47h
= 01000111
01000111
→ 10100011
= 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
= 143
≡ 208
+ 115
= 323
(декадно)
ВАЖНО
Подсетимо се да SimpSim ради са 8-битним бројевима, па је највећи број који можемо сместити FF
хексадекадно, тј. 255
декадно (28) . Приметимо да је 143 > FF
, није могуће да број у целости буде смештен у регистру, па ће бити запамћен као 43
(дошло је до overflow-a)!!
Дакле, вредности уписане у регистрима биће: R1
= 43
; R2
= 73
.
10.¶
Након извршења наредног скупа инструкција, шта се налази у регистрима R0
, R1
, R2
и RF
? Пратити вредност регистара наредбу по наредбу, као и садржај регистра инструкција.
НАПОМЕНА
Изгледа да постоји грешка код ко̑да овог задатка на 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
?
У регистру 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
неће бити задовољен,RF
≠ R0
≡ 51
≠ 05
, програм наставља са наредном линијом.
jmp Labela1
, програм се враћа на линију означеном са лабелом Labela1
.
2) RF
узима вредност са меморијске адресе 07
(вредност регистра R1
), што је вредност F1
.
addi R1,R1,R2
: R1
= 07
+ FF
= 06
jmpEQ RF=R0,KrajProg
: RF
≠ R0
≡ F1
≠ 05
, програм наставља са наредном линијом.
jmp Labela1
: програм се враћа на линију означеном са лабелом Labela1
.
3) RF
узима вредност са меморијске адресе 06
(вредност регистра R1
), што је вредност D0
.
addi R1,R1,R2
: R1
= 06
+ FF
= 05
jmpEQ RF=R0,KrajProg
: RF
≠ R0
≡ D0
≠ 05
, програм наставља са наредном линијом.
jmp Labela1
: програм се враћа на линију означеном са лабелом Labela1
.
4) RF
узима вредност са меморијске адресе 05
(вредност регистра R1
), што је вредност 05
.
addi R1,R1,R2
: R1
= 05
+ FF
= 04
jmpEQ RF=R0,KrajProg
: RF
= R0
≡ 05
= 05
, услов је испуњен и програм прелази на линију означену лабелом KrajProg
где се програм завршава.
Дакле, инструкција addi
се извршила четири пута.
При том, вредности регистара су R0
= 05
; R1
= 04
; R2
= FF
; RF
= 05
.
12.¶
Колико пута ће се извршити инструкција addi
у наредном скупу инструкција? Након извршења наредног скупа инструкција, шта се налази у регистрима R1
и R2
након два извршења инструкције addi
?
У регистру 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
?
У регистру 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
биће испуњен, RF
≤ R0
≡ 00
≤ 05
, па ће програм прећи на линију означеном са KrajProg
лабелом где се програм и завршава.
Крајњи резултати регистара су R0
= 05
; R1
= 13
; R2
= 04
; RF
= 00
.
14.¶
Након извршења наредног скупа инструкција, шта се налази у регистрима R0
, R1
, R2
и RF
? Пратити вредност регистара инструкцију по инструкцију, као и садржај регистра инструкција. Колико пута се изврши наредба addi
?
У регистру 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
за једно место удесно?
У регистру 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 0011
→ 1000 0001
= 81
(хексадекадно)
R2
постаје 81
.
Условни скок jmpLE RF<=R0,KrajProg
неће бити задовољен, RF
> R0
≡ 20
> 01
, програм наставља са наредном линијом.
jmp Labela1
, програм се враћа на линију означеном са лабелом Labela1
.
2) RF
узима вредност са меморијске адресе 07
(вредност регистра R1
), што је вредност F1
.
addi R1,R1,R2
: R1
= 07
+ 81
= 88
ror R2,1
: 81
→ 1000 0001
→ 1100 0000
→ C0
jmpLE RF<=R0,KrajProg
: RF
≤ R0
≡ F1
≤ 01
, услов је испуњен (F1
би требало да је негативан број, представљен у потпуном комплементу, па је зато мањи од 1
, те је услов испуњен, ако има смисла…) и програм прелази на линију означену лабелом KrajProg
где се и завршава.
Дакле, инструкција ror
(ротирања садржаја регистра R2
) се извршила два пута.
При том, вредности регистара су R0
= 01
; R1
= 88
; R2
= C0
; RF
= F1
.