Chapter 2 -- SAL
ABOUT SAL
---------
MOTIVATION for SAL:
hiding the details of MAL, MIPS asm. lang. (on purpose!)
SAL code will look more like HLL code -- to make student's transition
easier.
Introducing one more level of abstraction in order to postpone
discussion of several topics.
HLL SAL assembly machine code
each HLL statement maps into 1 or MORE SAL instructions
each SAL instruction maps into 1 or MORE MAL instructions
for this course, there is actually one more layer that
students will be given
HLL SAL MAL TAL MIPS RISC machine code
GROUND RULES FOR PRESENTATION:
1. I'll use Pascal. If those students who don't know any Pascal
are confused, then ASK!!!
2. syntax doesn't really matter -- I'll probably get my Pascal
all messed up. . .
SAL
A subset of the functionality of Pascal --
no records/structures
no formal arrays (see chapter 7 for their implementation)
What is required by a programming language?
declarations
arithmetic operations
conditional execution (if then else)
looping control structures
communication w/user. . .(write statement)
About SAL:
-- one instruction, declaration per line
-- comments are anything on a line following `#'
(comments may not span lines)
DECLARATIONS
------------
- they give information about how much memory space is needed
- they assign a name to the memory space
SAL has 3 basic types: integer, real, character
can build other types out of these,
for example, boolean is really an integer with only 2 defined values.
Pascal:
var variablename: type;
SAL:
variablename: type value
type is .word if integer
.byte if character
.float if real (floating point)
value is optional -- it gives the variable an initial value
examples:
flag: .word 0
counter: .word 0
e: .float 2.71828
uservalue: .byte
letter: .byte 'a'
other useful rules:
-- one declaration per line.
-- default initial value is 0.
DIRECTIVES
----------
a way to give information to the assembler.
- all directives start with `.' (period)
examples:
.byte
.word
.float
.data # identifies the start of the declaration section
# there can be more than 1 .data section in
# a program
.text # identifies where instructions are
# there can be more than 1 .text section in
# a program
ARITHMETIC operations
----------------------
SAL Pascal
move x, y x := y;
add x, y, z x := y + z;
sub x, y, z x := y - z;
mul x, y, z x := y * z;
div x, y, z x := y div z;
rem x, y, z x := y mod z;
NOTES: 1. the operation result depends on the type of the variables.
2. cannot increase the number of operands.
3. y and/or z can be IMMEDIATES
examples:
move count, 0
mult product, mult1, mult2
add sum, 2, addend
NOTE: there are other instructions that implement boolean functions,
but we don't cover them yet.
CONDITIONAL EXECUTION
---------------------
sometimes an instruction (or a set of instructions) should
be executed, and sometimes it (they) shouldn't.
HLL -- simplest form is a go-to. (Always discouraged.)
Pascal if-then-else
(a conditional go-to!)
if (condition) then
statement
else
statement;
SAL 'ifs' and 'gotos'
--------------------------------
SAL Pascal
b label goto label;
bltz x, label if x < 0 then goto label;
bgtz x, label if x > 0 then goto label;
blez x, label if x <= 0 then goto label;
bgez x, label if x >= 0 then goto label;
beqz x, label if x = 0 then goto label;
bnez x, label if x <> 0 then goto label;
beq x, y, label if x = y then goto label;
bne x, y, label if x <> y then goto label;
blt x, y, label if x < y then goto label;
bgt x, y, label if x > y then goto label;
ble x, y, label if x <= y then goto label;
bge x, y, label if x >= y then goto label;
EXAMPLE:
--------
Pascal if-then-else:
if (count < 0) then
begin
count := count + 1;
end;
SAL equiv to if-then-else:
bltz x, ifstuff
b endif
ifstuff: add count, count, 1
endif: # next program instruction goes here
-- OR --
bgez x, endif
add count, count, 1
endif: # next program instruction goes here
WHICH ONE OF THESE IS BETTER?
Structured loops can be built out of IF's and GOTO's
(test and branch)
EXAMPLES:
---------
while loop example
Pascal:
while ( count > 0 ) do
begin
a := a mod count;
count := count - 1;
end;
BAD STYLE Pascal:
while: if (count <= 0) then goto endwhile;
a := a mod count;
count := count - 1;
goto while;
endwhile:
SAL:
while: blez count, endwhile
rem a, a, count
sub count, count, 1
b while
endwhile: # next program instruction goes here
repeat loop example
Pascal:
repeat
if (a < b) then
a := a + 1;
if (a > b) then
a := a - 1;
until a = b;
SAL:
repeat: bge a, b, secondif
add a, a, 1
secondif: ble a, b, until
sub a, a, 1
until: bne repeat
while loop example
Pascal:
while (count < limit) and (c = d) do
begin
/* loop's code goes here */
end;
SAL:
while: bge count, limit, endwhile
bne c, d, endwhile
# loop's code goes here
b while
endwhile:
for loop example
Pascal:
for i:= 3 to 8 do
begin
a := a + i;
end;
SAL:
move i, 3
for: bgt i, 8, endfor
add a, a, i
add i, i, 1
b for
endfor:
COMMUNICATION WITH THE USER (I/O operations)
--------------------------------------------
SAL Pascal
put x write(x);
get x readln(x);
puts 'string' write('string');
SAL doesn't have any oddities about
testing for eoln or eof. A carriage return is just another
character to be read or written. It is '\n'
get has the most irregularities!
---
get intvariable
places first integer variable it "finds" into intvariable,
then throws away the rest of the line.
get charvariable
placed the first character variable it has into charvariable
EXAMPLES:
INPUT:
23 abc
-13
1234fgh!
SAL CODE:
get int1 # int1 <- 23
get int2 # int2 <- -13
get int3 # int3 <- 1234
OR:
get char1 # char1 <- '2'
get int1 # int1 <- 3
get char2 # char2 <- 'a'
So, if you want to get more than one non-character value from
a single line, you must read in character by character, and
convert to whatever form is desired. More about this in
chapter 4.
PROGRAM EXAMPLE:
----------------
# this simple program adds up 2 integers and prints their sum and products.
.data
prompt1: .asciiz "Enter an integer: "
prompt2: .asciiz "Enter a second integer: "
linefeed: .byte '\n'
msg1: .asciiz "The sum of "
msg2: .asciiz " and "
msg3: .asciiz " is "
msg4: .asciiz "The product of "
int1: .word 0
int2: .word 0
sum: .word
product: .word
.text
# get the 2 integers from user
puts prompt1
get int1
put linefeed
puts prompt2
get int2
put linefeed
# calculate the sum and products
add sum, int1, int2
mul product, int1, int2
# print out the sum and products
puts msg1
put int1
puts msg2
put int2
puts msg3
put sum
put linefeed
puts msg4
put int1
puts msg2
put int2
puts msg3
put product
put linefeed
done
Another simple SAL example program
----------------------------------
# A SAL program to print out a multiplication table
.data
start: .word 0 # entered by user
finish: .word 0 # entered by user
ii: .word # loop induction variable
jj: .word # loop induction variable
product: .word
prompt1: .asciiz "Enter starting value: "
prompt2: .asciiz "Enter ending value: "
newline: .byte '\n'
x_symbol: .byte 'X'
equals: .byte '='
space: .byte ' '
.text
__start: puts prompt1
get start
puts prompt2
get finish
move ii, start
for: bgt ii, finish, all_done
move jj, start
nested: bgt jj, finish, next_iter
mul product, ii, jj
# print line of table
put ii
put space
put x_symbol
put space
put jj
put space
put equals
put space
put product
put newline
add jj, jj, 1
b nested
next_iter: add ii, ii, 1
put newline
b for
all_done: done
PROCEDURES
----------
SAL has a rudimentary method for procedure call and return.
There is no mechanism for parameter passing or function return
values.
procedure parts:
1. call
SAL procedure call:
b procname
2. execute procedure
procname: #code for procedure goes here
3. return
"the hard part"
could be a branch, if we had a label for the return place.
b procname
rtn1: # more code here
procname: # procedure code here
.
.
.
b rtn1
This does not work. It just jumps to a different place in the
code! It cannot be called from more than one location.
Needed: an ADDRESS to return to!
Convenient SAL instruction:
la var1, label
la stands for Load Address
Operation: the address implied by label is placed into var1.
NOTE: var1 must be declared as an integer (.word)
Notice difference between address and contents of
the address.
label address contents
aa: 103 6
bb: 104 'a'
cc: 105 2001
The SAL instruction
la cc, bb
changes the table above to be:
label address contents
aa: 103 6
bb: 104 'a'
cc: 105 ** 104 **
For procedure call and return, save a return address
before branching to the procedure.
la procname_ret, rtn1
b procname
rtn1: # more code here
.
.
.
procname: # procedure code here
.
.
.
b procname_ret
THIS STILL DOESN'T WORK!
It branches to label procname_ret. But, procname_ret
is a variable! Can't branch to a variable!
To solve the problem, there is a special form of the b
instruction used just for procedure return.
b (var1) #parentheses identify the special form
branches to the contents of var1, not to var1 itself.
So, the complete call/return code is:
la procname_ret, rtn1
b procname
rtn1: # more code here
.
.
.
la procname_ret, rtn2
b procname
rtn2: # more code here
.
.
.
procname: # procedure code here
.
.
.
b (procname_ret)