Perfundoi Niveli 1 tek projekti Mips Assembly

Sot perfundoi dhe niveli i pare tek projekti online open-source Mips Assembly.
Ne te jane pasqyruar nje pjese e mire instruksionesh assembly MIPS dhe gjate leximit te kodit do te hasni:

  • Komentim te ‘egzagjeruar’ do te thoja, por kjo vetem per te sqaruar mire kodin
  • 2 Stile kodimi, i pari me pseudinstruksione dhe me regjistrat te emertuar “user friendly” $s0, $t0 etj dhe ate te Hard Core Assembly Programmer me instruksione Assembly puro duke ju drejtuar dhe regjistrave me $8, $9, $12 e keshtu me rradhe.
  • Origjinalitetin shqiptar, pasi kodet nuk jane kopiuar ne ndonje vend pasi edhe nese kerkoni ne ç’faredo lloj GJUHE te botes qofte anglisht, frengjisht, italisht, kinezçe, arabisht nuk do gjeni shembuj te tille pasi kam kerkuar personalisht per diçka te tille dhe nuk e kam gjetur xD.

PS.
Universitet ne shqiperi (ashtu si ketu ku jam une) nuk eshte se zgjerohen shume per ta ber nxenesin nje programator assembly porse dihet qe te dish te programosh ne gjuhe assembly kupton ne teresi sistemin , programon duke synuar performancat me te larta, dhe kjo çon ne perpunimin e algoritmeve thuajse perfekt dhe ndonjehere programatori assembly garon me vet kompilatorin.
Nuk me mbetet vetem te them i gezofshi, jane falas dhe open-source, mund te modifikohen porse kujtohuni qe ti ridrejtoni dhe studentet e tjere ketu. (kjo per te miren e tyre se mua pak me intereson xD , eci me parullen “don’t shave it xD :D:D” ).

http://albanianwizard.org/mips_assembly_source_code_examples/fillestar/

Assemblimi i nje instruksioni assembly ne assembler (:?

Nuk eshte loje fjalesh,  mjafton te lexoni kodin dhe eshte i komentuar shume mire.
http://albanianwizard.org/Postokodin/37
Per te shkarkuar:
http://albanianwizard.org/mips_assembly_source_code_examples/programator/assembly.s

##################################

#albanianwizard.org #

#Licence GPLv3 #

#arditi – arditi{at}hush{pik}ai #

######################################################################################################################

#Asemblo instruksionin ori $8, $9, 0x0019 duke mbledhur 1 nga 1 pjeset e tij [opcode],[rt],[rs],[imm] #

#dhe duke e depozituar instruksionin ne menyre te rregullt duke respektuar formatin ne nje regjister ç’faredo. #

#########################################################################################################################################################

#Te assemblojm ORI-n #

#Formatin mund ta gjeni tek: #

#http://albanianwizard.org/informatika_shqiptare/arkitekture_kompiuterike/gjuha_e_programimit_assembly/formati-i-instruksioneve-ne-arkitekturen-mips/ #

#Ne kete ushtrim do te shohim se si duke mbledhur copeza kodi mund te arrijm tek instruksioni i deshiruar. #

#Ne rastin tone eshte: ori $8,$9,0×0019 #

#########################################################################################################################################################

.text

.globl main

######################################################################################

# INTRO #

#ori $8, $9, 0x0019 eshte i barabart me isntruksionin 0x35280019 #

#ori ka opcode 1101 == 13 ne dec ose D ne hex #

#Shohim qe ka 1 operand dhe 1 regjister destinacioni dhe 1 vlere te menjehershme #

#Operandi [rs]= $9 / 0x9 #

#Destinacioni [rt]= $8 / 0x8 #

#Vlera e menjehershme [Imm] = 0x0019 #

#Zgjedhim $24 si regjister per te asembluar instruksionin #

######################################################################################

main:

ori $11,$0,0xD # opcode /kodi i instruksionit ori (0xD)/13/1101 ===>$11

ori $12,$0,0×9 # operandi $9 / [rs] ===>$12

ori $13,$0,0×8 # destinacioni $8 /[rt] ===>$13

ori $14,$0,0×0019 # [Imm] = 0x0019 ===>$14

########################

# Rregullojm Bitet #

########################

sll $11,$11,26 # spostojm [opcode] ne pozicionin e vet pasi tani eshte 0000 0000 0000 0000 0000 0000 0000 1101

# dhe duhet te jete (si opcode) ne pozicionin e vet: 0011 0100 0000 0000 0000 0000 0000 0000

sll $12,$12,21 # spostojm [rs] ne pozicionin e vet duke e levizur majtas 21 njesi dhe kemi:

# 0000 0000 0000 0000 0000 0000 0000 1001 mbasi e spostojm 21 njesi majtas kemi

# 0000 0001 0010 0000 0000 0000 0000 0000 [kjo eshte pamja e regjistrit mbas egzekutimit te sll $12, $12, 21

sll $13,$13,16 # spostojm [rt] (destinacionin) ne vendin e vet pasi tani eshte :

# 0000 0000 0000 0000 0000 0000 0000 1000 dhe duhet te jete :

# 0000 0000 0000 1000 0000 0000 0000 0000 [kete e ben instruksioni 😉 ]

##################################################

#Fillojm spostojm bitet ne regjistrin e deshiruar#

##################################################

or $24,$24,$11 # Bejme OR [opcode] (R11) tek regjistri $24 i cili do te marri pamjen:

# 0011 0100 0000 0000 0000 0000 0000 0000

or $24,$24,$12 # Bejme OR [RS] qe e kemi “qendisur” tek regjistri 12 me $24 i cili tani duke u shtuar dhe [rs] do marri pamjen

# 0011 0101 0010 0000 0000 0000 0000 0000

or $24,$24,$13 # Kalojm me OR $13 [rt] (destinacionin) tek regjistri yne $24 qe tani do te mari pamje akoma me te kompletuar :

# 0011 0101 0010 1000 (0000 0000 0000 0000) == IMM 😀

######################################################

#Na ngelen vetem 16 bitet e vleres se menjehershme :D#

######################################################

or $24,$24,$14 # Se fundmi fusim dhe vleren tone 0x0019 qe ne sistemin binar paraqitet me : 0000 0000 0001 1001

# Dhe pamja perfundimtare e regjistrit do jete:

# 0011 0101 0010 1000 0000 0000 0001 1001

ori $2, $0, 10 # Po vdis re Vdis 😛

syscall # Mbyllja e programit

################################################################

# PERFUNDIM #

#######################################################################################

#ori $8,$9,0×0019 <===> 0x35280019 <===> 0011 0101 0010 1000 0000 0000 0001 1001 #

#######################################################################################


					

Lancohet projekti Mips Assembly

Sapo eshte lansuar projekti MIPS Assembly me source kode te gjuhes assembly per arkitekturen MIPS R3000.
Eshte i ndare ne 3 nivele, fillestar, normal, c0d3r ne baze te veshtiresise.
Meqenese eshte unik ne web dhe nuk egziston ndonje projekt i tille direktoria eshte emeruar ne gjuhen angleze ne menyre qe te perdoret dhe nga jo-shqiptaret.
Eshte ne perpunim dhe kodet do te shtohen pak nga pak.
Vizitojeni 😉
http://albanianwizard.org/mips_assembly_source_code_examples/ushtrime_assembly_mips.php

Porojekti java shtyhet.

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?

Regjistrat e proçesoreve Kaos apo thjeshtesi? [MIPS]

Gjejm shpesh te shkruhet ne kod, kur shikojm programet tona assembly kode te tipit:
add $s0, $s1, $s2
E na thone qe $s0 = $s1 + $s2 dhe kuptojm qe vlera e rregjistrave $s1 dhe $s2 do te mblidhet dhe do te depozitohet tek rregjistri $s0 por ku qendron “kaosi”?
Problemi qendron qe nderkoh qe lexojm kodin assembly nuk shohim as vleren e rregjistrit $s1 dhe as ate te $s2-shit dhe themi,
Nga dreqin doli 10001001 tek $s0?

Ne realitet proçesi eshte shume i thjesht, dhe detyren per te asociuar variabilat e programeve me rregjistrat e ka kompilatori [kujdes po flasim per kompilator assembler dhe jo kompilatorin qe perkthen gjuhen nga niveli i lart ne ate te voglin].

Marrim 2 ushtrime per te shpjeguar kete fenomen dhe thjeshtesine e tij.

Ushtrimi 1

Pseudokodi;
a = (b + c) – (d + e);
Si eshte kodi assembly i ketij pseudokodi?

Ne kete rast ne na takon te marrim persiper rolin e assemblerit dhe do i lidhim ne vlerat me rregjistrat dhe perkatesisht;
meqenese kemi te bejm me variabila siç e mesuam tek ;
http://albanianwizard.org/informatika_shqiptare/arkitekture_kompiuterike/gjuha_e_programimit_assembly/regjistri-file-register-file-mips/

Rregjistri qe perdoret ne te tilla raste eshte seria e rregjistrave $s keshtu qe:
a = $s0; b = $s1; c = $s2; d = $s3; e = $s4;
Tani vazhdojm te kryejm veprimet me elementare dhe e ndajm kodin ne 2 pjese (b+c) dhe (d+e) dhe i depozitojm vlerat ne rregjistra temporan $t0 pasi nuk na duhen per shume kohe keshtu qe kodi assembly i bie te jete:

add $t0, $s1, $s2       # t0 = $s1 + $s2 = b + c
add $t1, $s3, $s4       # t1 = $s3 + $s4 = d + e
sub $s0, $t0, $t1,      # s0 = $t0 - $t1 = (b + c) - (d + e)

Nga vet komentimi besoj se kuptuam se ç’fare ndodhi.. le te sjellim nje shembull tjeter..

Ushtrimi 2

Perpara se te shikojm se si zgjidhet le te fiksojm dy ligje qe na duhen;

  1. Ne ç’do instruksion Mips, egzekuton gjithmon vetem 1 funksion i cili pershkruhet medoemos nga 3 variabila ku secila nga ato variabila i perket nje rregjistri. psh sub $s0, $t1, $t2
  2. Te vetmet instruksione qe perdorin memorjen ne aritekturen MIPS jane lw (load word) dhe sw (store word) te cilat me ane te nje instruksioni te posatshem qe quhet Data Transfer Instruction jane ne gjendje te marrin dhe te japin informacione nga memorja RAM

Vazhdojm me ushtrimin,
Le te marrim qe assembleri (pasi e pame njehere kete proçes) ka asociuar variabilat t dhe y me rregjistrat $s1 dhe $s2 dhe le te marrim qe kemi nje array (ne kete rast grumbull te dhenash) qe “fshihet” mbas ‘adreses baze’ ( lokacioni ne memorje qe shenon fillimin e te dhenave) te quajtur G mbas te ciles gjenden 100 fjale dhe kete adrese baze asembleri ka caktuar qe te gjendet tek rregjistri $s3.
Kalojm tek pseudokodi:
t = y + G[8];
I kemi shpjeguar te gjitha perveç [8]-tes e cila eshte nje konstante. qe do te thote se do te selektohen 8 elemente.
Ç’fare po ndodh?
Ne po na jepet ne kete rast nje lokacion memorjeje, dhe na thuhet qe adresa per te selektuar tog-dateshin (tog-fjaleshin) e isntruksioneve qe gjendet ne memorje eshte e perbere nga adresa fillestare (baze) + elementet per tu selektuar qe jane 8.
Adresa = adresen baze + 8 elemente = g + [8] e te gjitha keto do te magazinohen ne regjistrin $s3
Mbas kesaj na duhet qe ta mbledhim me y ($s2) dhe shumen ta depozitojm ne t ($s1).
Nga ky pseudokod nxjerrim qe fillimisht duhet te terheqim te dhena nga memorja dhe kete e ben vetem lw (load word);

lw $t0, 8($s3) #Momentalisht rregjistri $t0 merr g -n qe ndodhet tek $s3 + 8 (konstanten)

mbas kesaj besoj qe eshte e thjeshte, duhet vetem te marrim ate qe gjendet ne $t0 (G[8]) ta mbledhim me y ($s2) dhe ta magazinojm tek ($s1).

add $s1, $s2, $t0     # t = y + G[8]

Konstantja ne kete rast (8) ne nje instruksion per levizje te dhenash quhet offset kurse regjistri qe i shtohet (G) quhet rregjistri baze.

Regjistri file (register file) /MIPS

Yep, jemi ne arkitekturen mips, per ata qe e nenvleftesojn ta dine se playstation, perdor proçesor MIPS si dhe gjen aplikim shume ne paisjet elektronike ne saj te arkitektures RISC (reduced instruction set architecture) per shkak se ka shume pak instruksion dhe sipas perkufizimit sa me pak instruksione aq me i shpejt eshte nje proçesor.

RI = Register File , ne shqip faili i regjistrave te sistemit eshte nje komponent elektrik per ruajtjen e te dhenave i ndertuar ne proçesor qe perdoret per veprimet e ndryshme te proçesorit gjat cikleve te tij.

RI ne MIPS eshte i perbere nga 32 rregjistra dhe secili nga keto rregjistra ka kapacitetin qe te ruaj 32 bit informacion te koduar ne numer binar. Keshtu qe ne total 32 rregjistra X 32 bit qe ka kapacitet secili atehere kemi 1024 bit memorje ne dispozicion.

Ja pamja e thjeshtuar e RF

Ne arkitekturen MIPS,  kemi perkufizimin qe ne situata te veçanta perdoren rregjistra te veçant, dhe kjo sepse rregjistrat kane funksione te veçanta.

Le ti shohim scecilin nga ata se ç’fare funksionesh kane, ne rradhe te pare themi se ç’do instruksion ne assembly te arkitektures mips ne pergjithesi vepron duke perdorur nje nga rregijstrat e sistemit dhe kemi dhe sintaksen psh:

add $v1, $s1, $s2  #qe ne pseudoinstruksion eshte ekuivalente me $v1 = $s1 + $s2

E ne shqip do te thote merr bitet qe jane ne rregjistrin $s1 dhe mblidhi me ato qe jane ne rregjistrin $s2 dhe shumen depozitoje ne rregjistrin $v1

Kjo ne fjale te tjera eshte gjuha assembly qe me sintaksen e saj vepron direkt me proçesorin ose me memorjen {ne rastin Mips kur perdorim komanen li (load immediate) } , add normalisht nuk njihet nga proçesori por njihet ekuivalentja e saj ne MIPS ISA dhe kjo enkodohet ne kod binar i cili eshte ekuivalent per ate instruksion te caktuar , perfaqesimin ne haxadecimal (0x) te atij kodi binar qe per arkitekturen do te thote “mblidh” do e quajm opcode ose operation code qe do te thote kodi operacional nese mund ta themi keshtu, pra eshte kod i cili i thote proçesorit te kryej nje veprim te caktuar e ne aspektin gjuhesor eshte ‘folja’ e cila tregon levizje apo nje veprim specifik.

Grupet e Rregjistrave

Siç e shohim ne figuren me siper, rregjistrat fillojn te gjith me $, dhe emertohen me emra te ndryshem , fillojm ti sqarojm 1 nga 1 ne baze grupi.

$zero / ky eshte nje rregjister qe qendron gjithmon 0 , pra eshte konstant dhe per ata te çmendur [ 😀 ] qe kane provuar ti japin nje vlere do te shohin qe eshte e pamundur pasi eshte i ndertuar ne hardware. E thene midis nesh (kush perdor linux) nje /dev/null

$at / ose assembler temporary , eshte i rezevuar nga assembleri (kompilatori assembler) dhe mban vlera te perkohshme te makro instruksioneve , ose pseudo instruksioneve.

$v / ose rregjistrat e vlerave, perdoren per te kthyer vlera nga funksionet, dhe gjen zbatim ne IO , ne rastet kur perdoret “syscall” per te kryer nje sherbim te caktuar dhe programatoret kane caktuar 10 sherbime te mundshme duke karikuar tek $v0 vlera nga 1 tek 10 ku secila nga keto ka nje funksion te caktuar psh nese perdorim komanden li $v0, 4 ku ne fjale te tjera karikojm ne rregjistrin $v0 vleren 4 sipas perkufizimit kodi 4 do te thote Print String, e kodi 5 Read Integer, kodi 1 eshte Print Integer e keshtu me rradhe.

$a / Regjistrat e argumenteve – qe jane shume te lidhur me rregjistrat me siper pasi $v ishte per te kthyer vlera nga funksionet kurse $a si grup perdoren per te kaluar vlera tek funksionet e le te shohim nje rast ku kombinohen te dy: li $v0 4 # thirrja e sistemit per te printuar string (tog fialesh) la $a0 , prsh # i themi load address te mesazhit prsh tek rregjistri a0 dhe prsh neve psh mund ta kemi percaktuar tek .data si prsh: .ascizz “n Pershendetjeeeee!! ”

$t / Rregjistrat temporan – jane rregjistra qe perdoren nga kompilatori assembler ose nga programatori (ne) per te magazinuar vlera te menjehershme e zakonisht jane rregjistrat qe perdoren me shume nga komanda li (load immediate).

$s / Regjistrat temporan te shpetuar – keto jane te ngjashem me me $t me ndryshimin qe vlera mbetet dhe perdoren per te magazinuar vlera akoma me te gjata. (zakonisht kur kemi te bejm me instruksione andi , addi, or, srl etj..

$k / Regjistrat e Kernelit – keto jane regjistra te rezervuar nga kerneli, pra zemra e sistemit operativ dhe nuk mund te perdoren modifikohen nga programatori.

$gp / Global Pointer – shenohet adres qe piketon piken globale ne memorje (do i shohim nese do kemi mundesi te shpjegojm memorjen RAM)

$sp / Stack Pointer – piketon adresen ne te cilen gjate egzekutimit te programit ndodhet stack-u

$fp / Frame Pointer – edhe ky nje rregjister qe vepron me memorjen ku vlera e tij tregon lokacionin e memorjes ne te vilen ndodhet frame. (Do e shohim me ne detaj tek shpjegimi i RAM-it)

$ra / Return Address – regjistri i adreses se kthimit apo pika e kthimit, perdoret per ti thene nje funksioni se ku duhet te kthete (gjithmon ne memorje) gjate egzekutimit te programit.

If Then Else ne Assembly /MIPS /R3000 RISC arch

If at first you don’t succeed, Skydiving is definitely not for you.

E nisa me kete thenie kategorine e re “Assembly” ne albanianwizard.org sepse dihet qe askush nuk eshte perfekt dhe sidomos ne assembly duhen shume shume shume shume… prova dhe deshtime perpara se te arrihet nje rezultat i deshiruara kjo sepse nuk eshte gjuhe si gjith te tjerat, per te njohur progarmimin ne kete gjuhe te nivelit te ulet duhet te njohesh mire rregjistrat e sistemit, formatin e instruksioneve dhe te njohesh ne detaj menyren se si punon arkiktektura e nje kompiuteri.

Po marrim perkthimin e nje instruksioni nga pseudocode ne kodin real ne assembly.

Ajo qe perdorim me shume ne programim jane if else dhe perkatesisht ; Nese bie shi (merr çader) tjeter (mos e merr çadren)

Fillojm :

if ($t5 < 0 ) {$s0 = 0 - $t5; $t1 = $t1 + 1}
else {$s0 = $t5; $t2 = $t2 + 1}

Formati i mesiperm quhet pseudocode pasi eshte thjesht per te na lehtesuar kuptimin ndersa kjo qe pason eshte kodi real ne assembly per arkitekturen MIPS

bgez $t5, else  #if /nese ($t5 eshte > ose = 0 ) branch /kalo to else /tek else
sub $s0, $zero, $t5  # $s0 merr negativen e $t8
addi $t1, $t1, 1 #Shtojm vleren e rregjistrit $t1 nga 1
b      next       #krijojm nje cikel (branch) verdallisemi rreth kodit else
else:
            ori   $s0 ,$t5 , 0   #$s0 merr nje kopje te $t5
            addi $t2, $t2, 1  #shtojm tek rregjistri $t2 nga 1
next:

Shpjegim per ato “gjerat e çuditshme qe ndodhen” , add, ori, li, beq, bgez etj jane instruksionet assembly dhe ato qe shenuam me $t0, apo $s1,2,3,4,5,6… jane rregjistrat e proçesorit te cilet jane nga 32 bit dhe secili nga ata kane funksion te caktuar te cilet do i shohim ne temat e ardhshme :)