ZÁPADOČESKÁ UNIVERZITA V PLZNI FAKULTA APLIKOVANÝCH VĚD KATEDRA INFORMATIKY A VÝPOČETNÍ TECHNIKY SEMESTRÁLNÍ PRÁCE Z PŘEDMĚTU KIV/UPA 3. ÚLOHA ZADÁNÍ Č. 6 PETR THÜR 10.12.2006 A04236 FAV INIB/INF PETR.THUR@POST.CZ
OBSAH: 1) Zadání 2) Analýza úlohy 3) Popis algoritmu řešení 4) Zdrojový kód programu 5) Popis jednotlivých modulů 6) Výpis instrukcí 7) Závěr
1) ZADÁNÍ Úkolem je naprogramovat v assembleru pro procesor MIPS jednoduchou úlohu a odladit ji s použitím simulátoru SPIM. Jelikož se zadání mělo shodovat se zadáním pro předmět KIV/POT, v mém případě je takovéto: Zadání č. 6 Program odstraní 2 velká písmena na začátku slova (SLovo --> Slovo). Ostatní slova ponechá. 2) ANALÝZA ÚLOHY Program má za úkol v případě, že slovo obsahuje první 2 písmena velká, druhé písmeno změnit na malé. V případě, že je velké pouze první písmeno (a další je již malé) či je první písmeno malé či jsou velká první 3 písmena či má slovo jen 2 písmena, tak se nic neděje (resp. program dané slovo nijak nemění). Slovem se rozumí jakákoliv posloupnost písmen oddělená mezerami, tečkou, čárkou, vykřičníkem, pomlčkou,... Mezi slovy jsou povoleny vícenásobné mezery či jiné oddělovače. 3) POPIS ALGORITMU ŘEŠENÍ Program nejprve uloží adresu začátku ASCII řetězce a posléze zkoumá jednotlivé znaky podle ASCII hodnoty (program rozděluje znaky na malá písmena, velká písmena a ostatní znaky). Mezerou či jakýmkoliv ostatním znakem se hodnota registru t2 nastaví na nulu (a znak je beze změny zkopírován na výstup) a indikuje tak budoucí začátek slova, pokud na prvním místě přijde velké písmeno, tak se tato hodnota změní na 1 (a znak je opět zkopírován na výstup). Pokud po něm přijde opět velké písmeno, je dočasně zkopírováno do t3 a hodnota t2 se zvětší na 2. Pokud nyní přijde třetí písmeno malé, je předchozí (2.) písmeno zmenšeno a zapsáno na výstup, hodnota t2 se změní na 4 a tím již jsou všechna další písmena až do nejbližšího oddělovacího znaku zkopírována beze změny (nejbližší dělící znak opět změní t2 na 0). Pokud v průběhu zkoumání každého slova (1., 2. či 3. znak) dojde k nalezení jiného znaku než takového, který povede ke zmenšování 2. písmena ve slově, tak je hodnota t2 rovnou změněna na 4 a všechna písmena jen beze změny přepsána. Ošetřeny jsou i případy, kdy by slovo mělo jen 1 či 2 písmena, stejně jako vícenásobné mezery (resp. jakékoliv oddělovací znaky).
4) ZDROJOVÝ KÓD PROGRAMU.data pozdrav:.asciiz "Vstup: " data:.space 64 output:.space 64 konec:.asciiz "Vystup: ".text.globl main main: li $v0,4 la $a0,pozdrav syscall li $v0,8 la $a0,data li $a1,64 syscall move $t0,$a0 la $a0,output move $t6,$a0 SUB: lb $t1,($t0) beq $t1,'.',vyskoczpodprogramu ble $t1,'/',interpunkce beq $t2,0,prvniznak beq $t2,1,druhyznak beq $t2,2,tretiznak interpunkce: beq $t2,2,predzapis move $t2,$t8 predzapis: sb $t3,($t6) addi $t6,1 move $t2,$t8 j SUB prvniznak: bge $t1,'a',kozapis j okzapis druhyznak: bge $t1,'a',kozapis move $t3,$t1 addi $t0,1 addi $t2,$t2,1 j SUB tretiznak: ble $t1,'z',kotreti addi $t2,$t8,4 addi $t3,$t3,32 sb $t3,($t6) addi $t6,1 kotreti: sb $t3,($t6) addi $t6,1 addi $t2,$t8,4 okzapis: addi $t2,$t2,1 kozapis: addi $t2,$t8,4 zapis: sb $t1,($t6) addi $t6,1 addi $t0,1 j SUB vyskoczpodprogramu: beq $t2,2,zapisr2loutput j finish zapisr2loutput: sb $t3,($t6) j finish finish: li $v0,4 la $a0,konec syscall li $v0,4 la $a0,output syscall j $ra POUŽITÉ REGISTRY A JEJICH FUNKCE: t0: adresa aktuálně procházeného znaku t1: aktuální načtený znak t2: 4/2/1/0 v závislosti druhu, pozici a velikosti předchozího písmena t3: dočasné uložení druhého znaku t6: adresa výstupu
5) POPIS JEDNOTLIVÝCH MODULŮ SUB: funkce, která zajišťuje průchod celým řetězcem interpunkce: nastavuje t2 na 0 a zapisuje znak na výstup predzapis: zajišťuje zápis 2. znaku ve slově pouze se 2 písmeny prvniznak: zajišťuje otestování a zápis prvního písmena druhyznak: otestuje, popř. dočasně uloží druhé písmeno tretiznak: testuje třetí znak, volá fce pro zápis předch. písmena kotreti: uloží druhý znak bez zmenšení, uloží třetí znak, t2=4 okzapis: zapíše aktuální znak, t2++ kozapis: zapíše aktuální znak, t2=4 zapis: zapíše znak a inkrementuje ukazatele vstupu i výstupu o 1 vyskoczpodprogramu: vyskočí z podprogramu zapisr2loutput: zapisuje 2. znak pokud je úplně na konci celého řetětce _start: start je globální návěští (.global_start) finish: nekonečná smyčka na konci programu UKÁZKOVÉ VSTUPY A VÝSTUPY:
6) VÝPIS INSTRUKCÍ [0x00400000] 0x8fa40000 lw $4, 0($29) ; 174: lw $a0 0($sp)# argc [0x00400004] 0x27a50004 addiu $5, $29, 4 ; 175: addiu $a1 $sp 4# argv [0x00400008] 0x24a60004 addiu $6, $5, 4 ; 176: addiu $a2 $a1 4# envp [0x0040000c] 0x00041080 sll $2, $4, 2 ; 177: sll $v0 $a0 2 [0x00400010] 0x00c23021 addu $6, $6, $2 ; 178: addu $a2 $a2 $v0 [0x00400014] 0x0c100009 jal 0x00400024 [main] ; 179: jal main [0x00400018] 0x00000000 ; 180: [0x0040001c] 0x3402000a ori $2, $0, 10 ; 182: li $v0 10 [0x00400020] 0x0000000c syscall ; 183: syscall# syscall 10 (exit) [0x00400024] 0x34020004 ori $2, $0, 4 ; 13: li $v0,4 [0x00400028] 0x3c041001 lui $4, 4097 [pozdrav] ; 14: la $a0,pozdrav [0x0040002c] 0x0000000c syscall ; 15: syscall [0x00400030] 0x34020008 ori $2, $0, 8 ; 16: li $v0,8 [0x00400034] 0x3c011001 lui $1, 4097 [data] ; 17: la $a0,data [0x00400038] 0x34240008 ori $4, $1, 8 [data] [0x0040003c] 0x34050040 ori $5, $0, 64 ; 18: li $a1,64 [0x00400040] 0x0000000c syscall ; 19: syscall [0x00400044] 0x00044021 addu $8, $0, $4 ; 20: move $t0,$a0 [0x00400048] 0x00000000 ; 21: [0x0040004c] 0x3c011001 lui $1, 4097 [output] ; 22: la $a0,output [0x00400050] 0x34240048 ori $4, $1, 72 [output] [0x00400054] 0x00047021 addu $14, $0, $4 ; 23: move $t6,$a0 [0x00400058] 0x00000000 ; 24: [0x0040005c] 0x81090000 lb $9, 0($8) ; 27: lb $t1,($t0) [0x00400060] 0x00000000 ; 28: [0x00400064] 0x3401002e ori $1, $0, 46 ; 29: beq $t1,'.',vyskoczpodprogramu [0x00400068] 0x5029003d beql $1, $9, 244 [vyskoczpodprogramu-0x00400068] [0x0040006c] 0x29210030 slti $1, $9, 48 ; 30: ble $t1,'/',interpunkce [0x00400070] 0x14200008 bne $1, $0, 32 [interpunkce-0x00400070] [0x00400074] 0x500a0012 beql $0, $10, 72 [prvniznak-0x00400074]; 31: beq $t2,0,prvniznak [0x00400078] 0x34010001 ori $1, $0, 1 ; 32: beq $t2,1,druhyznak [0x0040007c] 0x502a0014 beql $1, $10, 80 [druhyznak-0x0040007c] [0x00400080] 0x34010002 ori $1, $0, 2 ; 33: beq $t2,2,tretiznak [0x00400084] 0x502a001a beql $1, $10, 104 [tretiznak-0x00400084] [0x00400088] 0x08100051 j 0x00400144 [zapis] ; 34: [0x0040008c] 0x00000000 ; 35: [0x00400090] 0x34010002 ori $1, $0, 2 ; 38: beq $t2,2,predzapis [0x00400094] 0x502a0005 beql $1, $10, 20 [predzapis-0x00400094] [0x00400098] 0x00000000 ; 39: [0x0040009c] 0x00185021 addu $10, $0, $24 ; 40: move $t2,$t8 [0x004000a0] 0x08100051 j 0x00400144 [zapis] ; 41: [0x004000a4] 0x00000000 ; 42: [0x004000a8] 0xa1cb0000 sb $11, 0($14) ; 45: sb $t3,($t6) [0x004000ac] 0x00000000 ; 46: [0x004000b0] 0x21ce0001 addi $14, $14, 1 ; 47: addi $t6,1 [0x004000b4] 0x08100017 j 0x0040005c [SUB] ; 48: j SUB [0x004000b8] 0x00000000 ; 49: [0x004000bc] 0x29210061 slti $1, $9, 97 ; 53: bge $t1,'a',kozapis [0x004000c0] 0x5020001e beql $1, $0, 120 [kozapis-0x004000c0] [0x004000c4] 0x0810004b j 0x0040012c [okzapis] ; 54: j okzapis [0x004000c8] 0x00000000 ; 55: [0x004000cc] 0x29210061 slti $1, $9, 97 ; 58: bge $t1,'a',kozapis [0x004000d0] 0x5020001a beql $1, $0, 104 [kozapis-0x004000d0] [0x004000d4] 0x00000000 ; 59: [0x004000d8] 0x00095821 addu $11, $0, $9 ; 60: move $t3,$t1 [0x004000dc] 0x21080001 addi $8, $8, 1 ; 61: addi $t0,1 [0x004000e0] 0x214a0001 addi $10, $10, 1 ; 62: addi $t2,$t2,1 [0x004000e4] 0x08100017 j 0x0040005c [SUB] ; 63: j SUB [0x004000e8] 0x00000000 ; 64: [0x004000ec] 0x2921005b slti $1, $9, 91 ; 67: ble $t1,'z',kotreti [0x004000f0] 0x14200009 bne $1, $0, 36 [kotreti-0x004000f0] [0x004000f4] 0x230a0004 addi $10, $24, 4 ; 68: addi $t2,$t8,4 [0x004000f8] 0x216b0020 addi $11, $11, 32 ; 69: addi $t3,$t3,32 [0x004000fc] 0x00000000 ; 70:
[0x00400100] 0xa1cb0000 sb $11, 0($14) ; 71: sb $t3,($t6) [0x00400104] 0x00000000 ; 72: [0x00400108] 0x21ce0001 addi $14, $14, 1 ; 73: addi $t6,1 [0x0040010c] 0x08100051 j 0x00400144 [zapis] ; 74: [0x00400110] 0x00000000 ; 75: [0x00400114] 0xa1cb0000 sb $11, 0($14) ; 78: sb $t3,($t6) [0x00400118] 0x00000000 ; 79: [0x0040011c] 0x21ce0001 addi $14, $14, 1 ; 80: addi $t6,1 [0x00400120] 0x230a0004 addi $10, $24, 4 ; 81: addi $t2,$t8,4 [0x00400124] 0x08100051 j 0x00400144 [zapis] ; 82: [0x00400128] 0x00000000 ; 83: [0x0040012c] 0x214a0001 addi $10, $10, 1 ; 86: addi $t2,$t2,1 [0x00400130] 0x08100051 j 0x00400144 [zapis] ; 87: [0x00400134] 0x00000000 ; 88: [0x00400138] 0x230a0004 addi $10, $24, 4 ; 91: addi $t2,$t8,4 [0x0040013c] 0x08100051 j 0x00400144 [zapis] ; 92: [0x00400140] 0x00000000 ; 93: [0x00400144] 0xa1c90000 sb $9, 0($14) ; 96: sb $t1,($t6) [0x00400148] 0x00000000 ; 97: [0x0040014c] 0x21ce0001 addi $14, $14, 1 ; 98: addi $t6,1 [0x00400150] 0x21080001 addi $8, $8, 1 ; 99: addi $t0,1 [0x00400154] 0x08100017 j 0x0040005c [SUB] ; 100: j SUB [0x00400158] 0x00000000 ; 101: [0x0040015c] 0x34010002 ori $1, $0, 2 ; 104: beq $t2,2,zapisr2loutput [0x00400160] 0x502a0003 beql $1, $10, 12 [zapisr2loutput-0x00400160] [0x00400164] 0x0810005f j 0x0040017c [finish] ; 105: j finish [0x00400168] 0x00000000 ; 106: [0x0040016c] 0xa1cb0000 sb $11, 0($14) ; 109: sb $t3,($t6) [0x00400170] 0x00000000 ; 110: [0x00400174] 0x0810005f j 0x0040017c [finish] ; 111: j finish [0x00400178] 0x00000000 ; 112: [0x0040017c] 0x34020004 ori $2, $0, 4 ; 115: li $v0,4 [0x00400180] 0x3c011001 lui $1, 4097 [konec] ; 116: la $a0,konec [0x00400184] 0x34240088 ori $4, $1, 136 [konec] [0x00400188] 0x0000000c syscall ; 117: syscall [0x0040018c] 0x34020004 ori $2, $0, 4 ; 118: li $v0,4 [0x00400190] 0x3c011001 lui $1, 4097 [output] ; 119: la $a0,output [0x00400194] 0x34240048 ori $4, $1, 72 [output] [0x00400198] 0x0000000c syscall ; 120: syscall [0x0040019c] 0x03e00008 jr $31 ; 122: j $ra [0x004001a0] 0x00000000 ; 123: PŘÍKLAD DATOVÉHO HAZARDU: [0x00400090] 0x34010002 ori $1, $0, 2 ; 38: beq $t2,2,predzapis [0x00400094] 0x502a0005 beql $1, $10, 20 [predzapis-0x00400094] [0x00400098] 0x00000000 ; 39: [0x0040009c] 0x00185021 addu $10, $0, $24 ; 40: move $t2,$t8 PŘÍKLAD ZPOŽDĚNÉHO ČTENÍ DAT: [0x0040005c] 0x81090000 lb $9, 0($8) [0x00400060] 0x00000000 [0x00400064] 0x3401002e ori $1, $0, 46 ; 27: lb $t1,($t0) ; 28: ; 29: beq $t1,'.',vyskoczpodprogramu PSEUDOINSTRUKCE: [0x00400024] 0x34020004 ori $2, $0, 4 [0x00400028] 0x3c041001 lui $4, 4097 [pozdrav] ; 13: li $v0,4 ; 14: la $a0,pozdrav [0x00400044] 0x00044021 addu $8, $0, $4 ; 20: move $t0,$a0
7) ZÁVĚR Ačkoliv zadání bylo poměrně jednoduché, samotná realizace pro mne již jednoduchá nebyla. Konečným produktem mé práce je však program, který zcela splňuje zadání a je plně funkční. Byl úspěšně odladěn na simulátoru SPIM. Tento simulátor je však ve srovnání se simulátorem HEW poněkud nepřehledný má především nepříliš průhledné krokování, kdy simulátor překládá pseudoinstrukce do instrukcí MIPSu. Práce v assembleru byla zajímavá a poučná, nicméně obávám se, že v budoucnu kromě školní výuky již takto získané znalosti nevyužiji.