Skip to main content
Department of Information Technology

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

Updated  2004-11-15 16:39:51 by Erik Berg.