Formati i Instruksioneve ne arkitekturen MIPS

Atomi ne Computing perfaqsohet nga 1 bit, e cila eshte njesia me e vogel me te cilen mund te paraqiten te dhena.
Siç e kemi then dhe tek Binary – Bit te verteta dhe sekrete

1 bit perfaqsohet nga nje impuls elektrik i cili mund te kete vlere nga 3-5 v e ne kete rast do te thote 1, ose kalon rryme ose mund te kete  nje vlere nga 0-3 v e ne kete rast do te thote 0, ose s’kalon rryme.
Menyra se si njeriu i jep instruksione makines ndryshon nga menyra se si kompiuteri i shikon instruksionet.
Meqenese kemi nje Set Insturksionesh atehere kemi dhe nje format instruksionesh perderisa gati per ç’do instruksion ne arkitekture duhet te perdoren rregjistrat.
Regjistrat ne MIPS kane secili nga nje numer, duke filluar nga $zero apo $0 e deri tek te fundit fillojn nga 0 deri tek numri 31, psh nga $t0 deri tek $t7 i konrespondojn 8 – 15.

Meqenese kemi ecur me shembujt :D, po marim nje pseudocode, te cilin do e kthejm ne instruksion assembly (ne kete rast bejm rolin e kompilatorit) e pastaj do e shohim instruksionin me syrin e kompiuterit i cili shikon “ne binar” dhe “shikon” ashtu siç eshte programuar per te “pare”. Me “menyren e shikimit” nenkuptohet ne menyre simbolike Formati i Instruksionit dhe Seti i Instruksioneve.

1.Njeriu Mendon

A[8] = h + A[8];

Lexojm pseudinstruksionin dhe shohim qe ne te kemi vetem 1 shkronje te pashoqeruar me konstante ([8]) e cila eshte h-ja kurse A[8] ne te dy rastet na tregon qe do te kemi pune me memorjen.
Marrim dhe interpretojm A[8]
A, ne kete rast eshte nje array (grup, tog, te dhenash) e cila ka dhe nje konstante 8 , pra eshte adresa e cila punton konstanten 8. E perkthyer, eshte nje rregjister ne proçesor i cili permban lidhjen me fillimin e nje adrese ne memorje e kete rregjister do e shenojm me $t1. Kurse h do e lidhim me rregjistrin $s2.
Ok, tani qe njohem se me ke kemi te bejm te interpretojm pak ate qe kerkohet.
ne na thuhet ne fjale te tjera a = c + a ku te dy a-te na kerkojn qe te seleksionojm ne memorje nje qeli dhe te dhenat e saj ti mbledhim me nje rregjister c pastaj kete shume ta depozitojm perseri ne te njejten qeli.
Pra, do te nxjerrim te dhena nga memorja, dhe do te fusim te dhena ne te.
Te nxjerresh te dhena nga memorja ne Mips nuk mund te behet vetem se me lw (load word) dhe te fusesh te dhena ne te nuk behet vetem se me sw (store word).

2.Njeriu perkthen (ne kod assembly)

Le te kthejm tani pseudokodin ne kod assembly ne menyre qe pastaj assembleri te perkthej kete kod ne machine code apo kod makine i cili interpretohet ne baze te Instruction Set dhe instruksionet nuk kalojn limitet apo me sakt nuk dalin nga formati i tyre i percaktuar nga ata qe kane dizenjuar hardwerin.
Kishim :

A[8] = h + A[8];

Marrim pjesen e djathte h + A[8]; ku kemi h-n ($s2) por na mungon A[8].
A-ja eshte ne regjistrin $t1 ne te cilin mbahet base address e cila punton ne nje qeli te memorjes.
[8] eshte nje konstante qe ne kete rast do e quajm offset dhe na thote qe nga adresa baze, do te spostohemi 8 dhe do te selektojm ate qeli te memorjes qe na intereson por ne kete rast do e shumezojm me 4 ne menyre qe te selektoj qeline e plote te memorjes (32 bit) dhe jo vetem 1 byte.

Ne kete rast kemi 32($t1).
E shpjegojm me mire,

Proçesori  (rregjistri $t1 – 32 bit)

$t1  (ketu qendron dhe base address e cila shenon fillimin e nje qelie ne memorje)

Memorja siç e dime ndahet ne qeli dhe qelia qe shenon fillimin ne instruksionin qe na intereson do te selektohet nga adresa e depozituar ne rregjistrin e proçesorit, kesaj do ti shtohet nje offset prej 32.
Rezultatin po e depozitojm ne $t0 dhe kemi:

lw $t0, 32($t1)  #Regjitri temporan t0 merr A[8]
add $t0, $s2, $t0 #Rezultatin e mbledhim me h-n dhe e depozitojm ne $t0

Tani na duhet qe kete h +A[8] ta sjellim perseri aty ku ishte , pra ne A[8] e per kete na duhet sw

sw $t0, 32($t1) #Permbajtjen e $t0 e futem perseri ne qeline e memorjes $t1+32 offset qe ndodhet ne RAM

Pra ne fjale te tjera, formati i nje instruksioni lw sw eshte i tipit lw $rregjistri $Adresa_RAM e cila mund te jete e lloit vetem nje rregjister psh lw $s2 ($s1) [ne kete rast $s1 permban adresen qe gjendet ne RAM] ose mund te jete e nje formati pak me te komplikuar te tipit lw $s1 4($s2) ku 4($s2) do te thote adresa_RAM + 4

3.Kompilatori (assembler) Perkthen

Tani qe e kemi kodin ne assembly;

lw $t0, 32($t1)
add $t0, $s2, $t0
sw $t0, 32($t1)

Mund tja japim makines ta interpretoj ne baze te formatit te instruksioneve dhe Instruction Set.
Marim nje instruksion te thjesht nga kodi i mesiperm;
add $t0, $s2, $t0
Secila nga ato qe jane shkruatjur ka hapesiren e vet dhe ne nje perfaqsim decimal do te ishte:

0   (add) 18  ($s2) 8         ($t0) 8        ($t0) 0       32      

Secili nga segmentet quhet fushe.
Pse egzistojn keto “formate” ?
Sikur mos te egzistonin atehere kompiuteri nuk do te merrte vesh a duhet te bej add, kush jane operandet e cili eshte rregjistri i destinacionit.. Per kete po e shpjegojm pak..
Fusha e pare (0) dhe e fundit (32) te kombinuara me njera-tjetren i thone kompiuterit se ç’fare instruksioni duhet te egzekutoje, ne kete rast qe duhet te egzekutoj add e jo diçka tjeter.
18 tregon operandin e pare, ne kete rast rregjistrin $s2, 8 tregon operandin e dyte qe eshte $t0 dhe 8tjeter tregon rregjistrin e destinacionit, ne kete rast fusha e peste eshte e pa perdorur keshtu qe po e lem 0.
Por kjo normalisht eshte qe ne ta kuptojm me mire, le te shohim se si e interpreton makina pasi siç e tham eshte pak e trashe 😀 dhe merr vesh vetem impulse elektrike me intensitet nga 3-5v (1) e impulse nga 0-3v (0)

4.Kompiuteri Interpreton

Ne realitet ate qe shkruajtem ne decimal siper (e kam fjalen per formatin) kompiuteri e shikon ne kete form:

000000 [6 bit] 10010 [5 bit qe perfaqsojn 18-ten
pra regjistrin $s2 ]
01000 [regjistri 8 / $t0] 01000 [regjistri 8 / $t0] 00000 [5 bite te paperdorur] 100000 [=32 / 6 bit kod funksioni]

Siç e shohim numri i rregjistrit per kompiuterin eshte i paraqitur ne kod binar, dhe ka secila prej instruksioneve madhesine e saj, ç’do regjister qe ne e emerojm me decimal kompiuteri e emeron gjithashtu por me binar.
Lind pyetja, si arrin te dalloj kompiuteri se kush eshte operandi i pare, kush i dyti dhe kush rregjistri i destinacionit?
Per kete, kemi fushat dhe emertimet e tyre:

op [6 bit] rs [5 bit] rt [5 bit] rd [5 bit] shamt [5 bit]] funct [6 bit]
  • op: Operacioni i instruksionit, tradicionalisht i quajtur opcode
  • rs:  Regjistri i pare, (operandi i pare)
  • rt: Regjistri i dyte, (operandi i dyte)
  • rd: Regjistri i Destinacionit
  • shamt: Shift amount (perdoret per instruksione te tjera kur duam te levizim bitet)
  • funct: Funksioni, Ky kod selekton variantin e opcode , dhe ndonjehere quhet dhe function code.

Bukur, tani kompiuteri mund te dalloj shapin nga sheqeri dhe mund te egzekutoj kodin pa problem ne baze te Instruction Set, psh nese e marrim te njejtin kod dhe perpiqemi ta egzskutojm ne nje kompiuteri me arkitekture x86 kompiuteri do te na thote:
R U CRAZY?!!
Kjo sepse ai nuk njeh formatin e instruksionit dhe regjistrat jane te tjere… ne fjale te tjera vetem tabloja konceptuale mund te kete ngjashmeri, praktika eshte komplet e ndryshme.
Problem,
Po me instruksionet e tjera si i behet hallit ?, Si ja ben kompiuteri kur i duhen me shume bit per ndonje instruksion ose si ne rastin e lwsw ku kemi te bejm vetem me 2 rregjistra?

Per kete nuk egziston vetem ky format instruksioni por 3 formate te tilla (ne realitet 4, por neve 3 na duhen per momentin)

  • Formati R

Ky grup formati perfshin te gjith ato instruksione qe nuk kerkojn nje vlere imediate , nje offset apo nje adrese memorjeje (pra nuk shkruajn apo lexojn ne memorje) Pra ky grup perfshin instruksione logjike – aritmetike si dhe jalr jr.
Per me teper:

opcode (6) rs (5) rt (5) rd (5) sa (5) function (6)
Instruksioni Funksioni
add rd, rs, rt 100000
addu rd, rs, rt 100001
and rd, rs, rt 100100
break 001101
div rs, rt 011010
divu rs, rt 011011
jalr rd, rs 001001
jr rs 001000
mfhi rd 010000
mflo rd 010010
mthi rs 010001
mtlo rs 010011
mult rs, rt 011000
multu rs, rt 011001
nor rd, rs, rt 100111
or rd, rs, rt 100101
sll rd, rt, sa 000000
sllv rd, rt, rs 000100
slt rd, rs, rt 101010
sltu rd, rs, rt 101011
sra rd, rt, sa 000011
srav rd, rt, rs 000111
srl rd, rt, sa 000010
srlv rd, rt, rs 000110
sub rd, rs, rt 100010
subu rd, rs, rt 100011
syscall 001100
xor rd, rs, rt 100110
  • Formati I

Ne ndryshim nga formati i mesiperm ka vetem 4 fusha, ku njera eshte e rezervuar per Immediate (vlera te tipit konstante prej 16 bitesh).
Pra direkt besoj se kuptojm qe perdoret per branch-e offsete, lexime dhe shkrime ne memorje.

opcode (6) rs (5) rt (5) immediate (16)

Instruksione te ketij formati jane:

Instruksioni Opcode Shenime per opcode
addi rt, rs, immediate 001000
addiu rt, rs, immediate 001001
andi rt, rs, immediate 001100
beq rs, rt, label 000100
bgez rs, label 000001 rt = 00001
bgtz rs, label 000111 rt = 00000
blez rs, label 000110 rt = 00000
bltz rs, label 000001 rt = 00000
bne rs, rt, label 000101
lb rt, immediate(rs) 100000
lbu rt, immediate(rs) 100100
lh rt, immediate(rs) 100001
lhu rt, immediate(rs) 100101
lui rt, immediate 001111
lw rt, immediate(rs) 100011
lwc1 rt, immediate(rs) 110001
ori rt, rs, immediate 001101
sb rt, immediate(rs) 101000
slti rt, rs, immediate 001010
sltiu rt, rs, immediate 001011
sh rt, immediate(rs) 101001
sw rt, immediate(rs) 101011
swc1 rt, immediate(rs) 111001
xori rt, rs, immediate 001110
  • Formati J

Ketu kemi vetem instruksionin jal dhe j (jump) te cilat kerkojn 26 bite dhe kane nevoj vetem per opcode dhe adresen ku duhet te behet jump.
Instruksioni Opcode       Target
j   emri            000010        adresa e koduar e emrit
jal   emri        000011         adresa e koduar e emrit

Tani qe shpjeguam dhe formatin e instruksioneve mund te perfundojm duke perkthyer per kompiuterin kodin tone :)

Instruksionet ne kodin tone ishin lw, add, sw pra kemi 2 instruksione te formatit I dhe 1 te formatit R.
Le te bejm nje tabele me kodin e tyre ne binar pra, ashtu siç e interpreton kompiuteri instruksionin.

op (code) rs rt rd address/shamt funct
100011 [35 – lw] 01001 [9 – $t1] 01000   [8 – $t0] 0000000000100000  [32]
0   (add) 18  ($s2) 01000   [8 – $t0] 01000   [8 – $t0] 0 0000000000100000  [32]
101011 [43 – sw] 01001 [9 – $t1] 01000   [8 – $t0] 0000000000100000  [32]

Mire, ja ku mesuam dhe se si makina interpreton kodin ton 😉
Ka ndonje paqartesi?