Computer Architecture, First Course
Assembly 1
Before You Begin!
We strongly recommend to start with the following "Getting Started" exercises:
This assignment is mandatory and must be satisfactory solved to get credits for the course. All source code must be well commented and well structured. There will be an oral examination/presentation of the assignment to the teacher(s). All participants in a group (one or two students) must be able to explain how the program works and how parameters are transferred from the main function to the subroutines. Bring printout of your code to the examination, and make sure there is a working version of your solution in your home account on the department computer system. In case two students work together, both must be able to demonstrate and run the program.
NOTE: You will also get questions about general assembly programming at the examination.
SLIDES: The slides from the lectures are available as pdf intro_assm2.pdf.
EXAMPLE: An additional example from the lecture: exempel2.s.
Del 1: Stacken, subrutiner och register-konventionen
Laborationen syftar till att ge kunskap och förståelse för hur (1) stacken hanteras i MIPS-processorn, (2) hur subrutiner skrivs i MIPS-assembler, samt introducerar (3) register-konventionen.
1. Bakgrund
I högnivåspråk är det vanligt att parametrar till funktioner och procedurer överförs via en underliggande maskinens stack. Ett delsyfte med laborationen är att ge förståelse för de mekanismer som på maskinnivå ligger bakom parameteröverföring. När parametrar överförs via stacken i den första uppgiften nedan ska det tolkas som att subrutinen får lokala kopior av parametervärdena. I den andra deluppgiften överförs en pekare (adress/referens) till originaldatat vilket då innebär att subrutinen inte använder lokalt data. Två förenklade liknelser i C/C++:
int sum_1(int antal, int tal1, int tal2, int tal3, int tal4, ...); int sum_2(int antal, int tal[]);
OBS: Subrutinerna ska betraktas som autonoma enheter helt frikopplade från anropande kodavsnitt. Konventionerna för parameteröverföring och register-användning för MIPS-assembler (se t.ex. Patterson & Hennessy, Appendix A.6) måste följas.
2. Uppgifter
Ni ska skriva två subrutiner (sum_1 och sum_2) som kan addera heltal. Parametrar till subrutinen är antalet tal som ska adderas samt samtliga tal som ska adderas. Varje subrutin ska returnera summan av talen. Sedan ska ni skriva klart ett huvudprogram som använder subrutinerna för att summera tal. Utgå från följande kod-exempel (använd "cut-and-paste" och spara texten i t.ex. filen lab1_del1.s).
############################################################ ############################################################ ## ## DARK1, Fall 2004, Distance -- Lab #1, part 1 ## ## AUTHOR(S): ... write your name(s) and email(s) here ... ## DATE: ... write current date ... ## ############################################################ ############################################################ ############################################################ ## Data Segment ############################################################ .data antal: .word 10 tal: .word 1,2,3,4,5,6,7,8,9,10 NL: .ascii "\n" ############################################################ ## Text Segment ############################################################ .text .globl main #----------------------------------------------------------- # Main Start #----------------------------------------------------------- main: addi $sp, $sp, -4 # make room for 1 item on stack sw $ra, 0($sp) # save return address ### ... write your code here ... jal sum_1 # call sum_1 add $a0, $v1, $zero # integer to print, the total sum li $v0, 1 # system call code for print_int syscall # print the integer ## print new-line li $v0, 4 # system call for print_str la $a0, NL # address of string to print syscall # print the string ### ... write your code here ... jal sum_2 # call sum_2 add $a0, $v1, $zero # integer to print, the total sum li $v0, 1 # system call code for print_int syscall # print the integer lw $ra, 0($sp) # restore return address addi $sp, $sp, 4 # pop sp jr $ra # return to caller #----------------------------------------------------------- # Main End #----------------------------------------------------------- #----------------------------------------------------------- # PROCEDURE: sum_1 # # DESCRIPTION: This procedure returns the total sum for # given numbers. All numbers are passed to this # subroutine via the stack. # # INPUT: All numbers are placed on the stack. The top # of the stack contains the amount of numbers # to sum. # # OUTPUT: $v1 - the total sum #----------------------------------------------------------- sum_1: addi $v1, $zero, 0 # $v1 = sum = 0 ### ... write your code here ... jr $ra # return to caller #----------------------------------------------------------- # PROCEDURE: sum_2 # # DESCRIPTION: This procedure returns the total sum for # given numbers. All numbers are passed to the # subroutine via a special/standard MIPS- # registers for parameter passing. # # INPUT: $a0 - the amount of numbers to sum # $a1 - the start address of given numbers # # OUTPUT: $v1 - the total sum #----------------------------------------------------------- sum_2: addi $v1, $zero, 0 # $v1 = sum = 0 ### ... write your code here ... jr $ra # return to caller
Följande uppgifter skall lösas:
- Skriv klart sum_1. Skriv en subrutin som tar all sin data från stacken. Antalet tal ska även det ges till subrutinen via stacken. Tänk på att antalet tal ska kunna variera så antalet tal måste ligga överst på stacken! Glöm inte att återställa stacken efter exekveringen av sum_1.
- Rita hur stacken ser ut för talen 1,2,3,4,5 (inkl. $ra och antal=5) precis innan proceduren sum_1 skall anropas (se t.ex. Hennessy & Patterson, Appendix A.5 -- Memory Usage).
- Skriv klart sum_2. Att skicka med alla tal som ska summeras till subrutinen är både omständigt och inte heller effektivt. I stället gör man så att man endast skickar två parametrar: antalet tal samt adressen till talen som ska summeras (det vill säga adressen "tal" i exemplet ovan). Notera att det i detta fall handlar om att referera data som inte är lokalt för subrutinen.
- Motivera kort (med max. 3 meningar) varför register $s0-$s7 och $ra måste sparas på stacken i fall dessa ändras i subrutiner (se t.ex. Hennessy & Patterson, Appendix A.6).
- På vad (vilken adress) pekar $ra på då funktionen main börjar exekveras? Med andra ord, vad är innehållet i registret $ra i början av programmet ovan? Tips: använd step-funktionen i SPIM-simulatorn.
Del 2: MIPS: Addition och strängar
Den här uppgiften syftar till att ge ännu mera övning i att skriva MIPS-assembler, introducera SPIM-systemanrop för inläsning och att hantera strängar i assembler. Konvertering från sträng till tal och från tal till sträng kommer att beröras.
1. Uppgift
Skriv ett program som frågar efter och läser in en sträng bestående av flera heltal separerade av plustecken. Strängen kan antas vara maximalt 80 tecken lång (inkl. null-byte symbolen som markerar strängens slut). Programmet ska sedan skriva ut hela additionen inklusive talens summa. Programmet behöver inte klara av att summera tal vars summa blir större än 2147483647 och det får bara använda systemanropen read_string och print_string. I SPIM-manualen (Appendix A.9) beskrivs SPIM:s systemanrop (syscalls).
En viktig del av programmet blir att tolka vad den inmatade strängen innehåller och att konstruera en ny sträng från ett heltal. Alltså, ni ska behöva använda er av ASCII-tabellen för att kunna utföra konverteringen. En ASCII-tabell hittas i nästan alla dator-arkitektur böcker, och även på http://www.asciitable.com.
Efter en körning ska programmet fråga ifall en ny addition ska göras, det vill säga om programmet ska börja om från början eller om det ska avsluta.
Programmet ska hantera felaktig inmatning och meddela att inmatningen var på felaktigt form, se exempel nedan.
2. Exempel på en körning med programmet
Ge en addition: 123+456+789 Summan är: 123+456+789=1368 Vill du göra en addition till? (j/n) j Ge en addition: 123+456+789+10000+20000 Summan är: 123+456+789+10000+20000=31368 Vill du göra en addition till? (j/n) j Ge en addition: hej+hopp Felaktig inmatning! Vill du göra en addition till? (j/n) j Ge en addition: 123++456 Felaktig inmatning! Vill du göra en addition till? (j/n) j Ge en addition: 123+456+ Felaktig inmatning! Vill du göra en addition till? (j/n) n Tack och hej!
3. Utförande
Programmet skall använda sig av minst två procedurer: check_string och int_to_string.
Utgå från följande kod-exempel:
############################################################ ############################################################ ## ## DARK1, Fall 2004, Distance -- Lab #1, part 2 ## ## AUTHOR(S): ... write your name(s) and email(s) here ... ## DATE: ... write current date ... ## ############################################################ ############################################################ ############################################################ ## Data Segment ############################################################ .data buffer: .space 80 # the place for the input-string MSG1: .asciiz "\nGe en addition:\n" MSG2: .asciiz "Summan är: " MSG3: .asciiz "Vill du göra en addition till? (j/n) " ### ... reserve your additional data here ... ############################################################ ## Text Segment ############################################################ .text .globl main #----------------------------------------------------------- # Main Start #----------------------------------------------------------- main: addi $sp, $sp, -4 # make room for 1 item on stack sw $ra, 0($sp) # save return address ## The s0-register should contain the total sum addi $s0, $zero, 0 # $s0 = the total sum = 0 ### ... write your code here ... exit: lw $ra, 0($sp) # restore return address addi $sp, $sp, 4 # pop sp jr $ra # return to caller #----------------------------------------------------------- # Main End #----------------------------------------------------------- #----------------------------------------------------------- # PROCEDURE: check_string # # DESCRIPTION: This procedure checks if the string contains # integers separated with a plus-signs, e.g, # # int+int+int+...+int # # INPUT: $a0 - the address of the string # $a1 - the length of the string # # OUTPUT: $v0 = 1 if the string is invalid # $v0 = 0 if the string is valid #----------------------------------------------------------- check_string: ### ... write your code here ... jr $ra # return to caller #----------------------------------------------------------- # PROCEDURE: int_to_string # # DESCRIPTION: This procedure converts an integer to a # string. It assumes that the string is large # enough for the number, and that the number # is smaller than 2147483648. The end-of-string # should be marked with a null-byte. The # maximum string length should though be 11 # bytes. # # INPUT: $a0 - the number to be converted # $a1 - the address of the string # # OUTPUT: None. #----------------------------------------------------------- int_to_string: ### ... write your code here ... jr $ra # return to caller