How To Assign A Char To A Register Mips
C: Assembly Language (MIPS)
Pedagogy Fix Architectures |
A typical modern CPU has
- a gear up of data registers
- a gear up of control registers (incl PC)
- an arithmetics-logic unit (ALU)
- admission to random access retentivity (RAM)
- a set of elementary instructions
- transfer data between memory and registers
- push button values through the ALU to compute results
- make tests and transfer command of execution
Dissimilar types of processors have different configurations of the above
- e.g. different # registers, different sized registers, different instructions
Why Study Assembler? | 3/114 |
Useful to know assembly language because ...
- sometimes you are required to utilise information technology (e.g. device handlers)
- improves your understanding of how C programs execute
- very helpful when debugging
- able to avert using known inefficient constructs
- uber-nerdy performance tweaking (squeezing out last nano-due south)
- re-write that disquisitional (frequently-used) function in assembler
Two wide families of instruction set architectures ...
RISC (reduced educational activity set computer)
- small(ish) set of unproblematic, general instructions
- dissever computation & data transfer instructions
- leading to simpler processor hardware
- e.g. MIPS, RISC, Alpha, SPARC, PowerPC, ARM, ...
- large(r) set of powerful instructions
- each instruction has multiple actions (comp+store)
- more than circuitry to decode/process instructions
- e.g. PDP, VAX, Z80, Motorola 68xxx, Intel x86, ...
... Instruction Sets | 5/114 |
Machine-level instructions ...
- typically have one-2 32-bit words per teaching
- segmentation bits in each word into operator & operands
- #bits for each depends on #instructions, #registers, ...
Operands and destination are typically registers
... Education Sets | half-dozen/114 |
Common kinds of instructions
-
load
,
- copy value stored in retentiveness at address into named register
-
loadc
,
- copy value into named register
-
shop
,
- copy value stored in named register into memory at address
-
leap
- transfer execution of program to instruction at address
-
jumpif
,
- transfer execution of program if east.g. register holds goose egg value
... Instruction Sets | 7/114 |
Other mutual kinds of instructions
-
add together
,
,
sub
mul
div
- Annals3 = Register1
+
- Annals3 = Register1
-
and
,
,
or
xor
- Register3 = Register1
&
- Register3 = Register1
-
neg
,
- Annalsii =
~
- Annalsii =
-
shiftl
,
,
shiftr
- Register2 = Annalsone
<<
- Register2 = Annalsone
-
syscall
- invoke a system service; which service adamant by Value
... Instruction Sets | 8/114 |
All CPUs have programme execution logic like:
while (1) { instruction = memory[PC] PC++// move to next instr if (instruction == HALT) intermission else execute(teaching) }
PC = Program Counter, a CPU register which keeps rails of execution
Note that some instructions may alter PC further (eastward.g. JUMP)
... Fetch-Execute Bike | ten/114 |
Executing an pedagogy
- decide what the operator is
- decide which registers, if any, are involved
- determine which retentiveness location, if any, is involved
- deport out the operation with the relevant operands
- shop result, if any, in appropriate annals
Instructions are only scrap patterns within a 32-bit bit-string
Could draw motorcar programs as a sequence of hex digits, e.grand.
Address Content 0x100000 0x3c041001 0x100004 0x34020004 0x100008 0x0000000c 0x10000C 0x03e00008
Often call "assembly language" every bit "assembler"
Slight notational abuse, because "assembler" besides refers to a program that translates assembly language to auto code
... Assembly Language | 12/114 |
Assembler = symbolic language for writing machine lawmaking
- write instructions using mnemonics rather than hex codes
- reference registers using either numbers or names
- tin can associate names to memory addresses
Style of expression is significantly unlike to eastward.chiliad. C
- need to use fine-grained control of memory usage
- required to manipulate information in registers
- control structures programmed via explicit jumps
MIPS is a well-known and relatively simple architecture
- very pop in a range of computing devices in the 1990's
- due east.yard. Silicon Graphics, NEC, Nintendo64, Playstation, supercomputers
- using ii variants of the open up-source SPIM emulator
-
qtspim
-
spim
-
xspim
Source code for browsing under /habitation/cs1521/spim/spim
MIPS is a automobile compages, including educational activity prepare
SPIM is an emulator for the MIPS education set
- reads text files containing instruction + directives
- converts to machine code and loads into "memory"
- provides debugging capabilities
- single-pace, breakpoints, view registers/retentivity, ...
- provides mechanism to interact with operating organisation (syscall)
- provide convenient/mnemonic ways to exercise common operations
- east.1000.
move $s0,$v0
addu $s0,$0,$v0
3 ways to execute MIPS code with SPIM
-
spim
- load programs using
-file
- interact using stdin/stdout via login terminal
- load programs using
-
qtspim
- load programs via a load button
- interact via a pop-upward stdin/stdout final
-
xspim
- like to
qtspim
- requires X-windows server
- like to
Control-line tool:
GUI tool:
MIPS Machine Archtecture | 18/114 |
MIPS CPU has
- 32 × 32-bit general purpose registers
- 16 × 64-bit double-precision registers
- PC ... 32-scrap register (ever aligned on 4-byte boundary)
- HI,LO ... for storing results of multiplication and division
$0..$31
Some registers take special uses e.thou.
- register
$0
- registers
$1
$26
$27
... MIPS Car Archtecture | xix/114 |
Registers and their usage
Reg | Name | Notes | ||
$0 | zero | the value 0, non changeable | ||
$1 | $at | assembler temporary; used to implement pseudo-ops | ||
$two | $v0 | value from expression evaluation or function return | ||
$three | $v1 | value from expression evaluation or function return | ||
$4 | $a0 | first argument to a role/subroutine, if needed | ||
$5 | $a1 | second argument to a function/subroutine, if needed | ||
$6 | $a2 | third argument to a function/subroutine, if needed | ||
$7 | $a3 | fourth argument to a role/subroutine, if needed | ||
$eight $15 | $t0 $t7 | temporary; must exist saved by caller to subroutine; subroutine can overwrite |
... MIPS Motorcar Archtecture | 20/114 |
More register usage ...
Reg | Proper name | Notes | ||
$16 | $s0 $s7 | southwardafe office variable; must non be overwritten by called subroutine | ||
$24 $25 | $t8 $t9 | temporary; must exist saved by caller to subroutine; subroutine can overwrite | ||
$26 $27 | $k0 $k1 | for kernel use; may modify unexpectedly | ||
$28 | $gp | global pointer | ||
$29 | $sp | southwardtack pointer | ||
$30 | $fp | frame pointer | ||
$31 | $ra | return address of most recent caller |
... MIPS Motorcar Archtecture | 21/114 |
Floating point register usage ...
Reg | Notes | |
$f0 $f2 | hold floating-point function results | |
$f4 $f10 | temporary registers; not preserved across role calls | |
$f12 $f14 | used for first 2 double-precision function arguments | |
$f16 $f18 | temporary registers; used for expression evaluation | |
$f20 $f30 | saved registers; value is preserved across role calls |
Notes:
- registers come in pairs of 2 × 32-bits
- merely even registers are addressed for double-precision
MIPS Associates Language | 22/114 |
MIPS assembly language programs comprise
- comments ... introduced past
#
- labels ... appended with
:
- directives ... symbol kickoff with
.
- assembly language instructions
- information objects that live in the data region
- functions (instruction sequences) that live in the code/text region
... MIPS Assembly Language | 23/114 |
Example MIPS assembler program:
# hello.southward ... print "Hello, MIPS" .data# the information segment msg: .asciiz "Hello, MIPS\north" .text# the code segment .globl primary main: la $a0, msg# load the argument cord li $v0, iv# load the system call (impress) syscall# print the cord jr $ra# return to caller (__start)
Color coding: label, directive, comment
... MIPS Assembly Language | 24/114 |
Generic structure of MIPS programs
# Prog.southward ... annotate giving clarification of part # Author ... .data# variable declarations follow this line # ... .text# instructions follow this line .globl primary main:# indicates start of code # (i.eastward. start user instruction to execute) # ... # Terminate of plan; leave a blank line to make SPIM happy
... MIPS Associates Language | 25/114 |
Another example MIPS assembler program:
.data a: .word 42# int a = 42; b: .space four# int b; .text .globl main primary: lw $t0, a# reg[t0] = a li $t1, 8# reg[t1] = viii add $t0, $t0, $t1# reg[t0] = reg[t0]+reg[t1] li $t2, 666# reg[t2] = 666 mult $t0, $t2# (Lo,Hi) = reg[t0]*reg[t2] mflo $t0# reg[t0] = Lo sw $t0, b# b = reg[t0] ....
... MIPS Associates Language | 26/114 |
MIPS programs assume the following memory layout
Region | Address | Notes | ||
text | 0x00400000 | contains but instructions; read-only; cannot expand | ||
data | 0x10000000 | data objects; readable/writeable; tin exist expanded | ||
stack | 0x7fffefff | grows downwardly from that address; readable/writeable | ||
k_text | 0x80000000 | kernel lawmaking; read-only; only accessible kernel mode | ||
k_data | 0x90000000 | kernel data; read/write; only accessible kernel mode |
MIPS has several classes of instructions:
- load and store .. transfer information between registers and memory
- computational ... perform arithmetics/logical operations
- bound and branch ... transfer control of program execution
- coprocessor ... standard interface to diverse co-processors
- special ... miscellaneous tasks (e.thousand. syscall)
- between retention and register (direct, indirect)
- constant to annals (immediate)
- register + annals + destination register
... MIPS Instructions | 28/114 |
MIPS instructions are 32-bits long, and specify ...
- an performance (eastward.g. load, shop, add, branch, ...)
- one or more operands (e.grand. registers, retentiveness addresses, constants)
Memory addresses tin be given by
- symbolic name (label) (effectively, a constant)
- indirectly via a register (effectively, arrow dereferencing)
prog: a: lw $t0, var# address via proper noun b: lw $t0, ($s0)# indirect addressing c: lw $t0, 4($s0)# indexed addressing
If $s0
0x10000000
&var
0x100000008
- computed accost for
a:
0x100000008
- computed accost for
b:
0x100000000
- computed accost for
c:
0x100000004
... Addressing Modes | 30/114 |
Addressing modes in MIPS
Format | Address ciphering | |
(annals) | accost = *register = contents of register | |
chiliad | address = k | |
k(annals) | accost = k + *annals | |
symbol | address = &symbol = address of symbol | |
symbol ± k | address = &symbol ± k | |
symbol ± k(register) | address = &symbol ± (m + *register) |
where thou is a literal abiding value (east.thousand. 4
0x10000000
... Addressing Modes | 31/114 |
Examples of load/store and addressing:
.data vec: .space 16# int vec[4], 16 bytes of storage .text __start: la $t0, vec# reg[t0] = &vec li $t1, 5# reg[t1] = five sw $t1, ($t0)# vec[0] = reg[t1] li $t1, 13# reg[t1] = 13 sw $t1, 4($t0)# vec[ane] = reg[t1] li $t1, -7# reg[t1] = -vii sw $t1, 8($t0)# vec[2] = reg[t1] li $t2, 12# reg[t2] = 12 li $t1, 42# reg[t1] = 42 sw $t1, vec($t2)# vec[three] = reg[t1]
MIPS instructions can manipulate dissimilar-sized operands
- unmarried bytes, two bytes ("halfword"), four bytes ("discussion")
Leads to many opcodes for a (conceptually) single operation, due east.g.
-
LB
-
LBU
-
LH
-
LHU
-
LW
-
LA
MIPS Instruction Set | 33/114 |
The MIPS processor implements a base of operations gear up of instructions, east.thousand.
-
lw
sw
add
sub
and
or
sll
slt
beq
j
jal
-
move
rem
la
li
blt
Pseudo-educational activity Base education(south) li $t5, const ori $t5, $0, const la $t3, label lui $at, &label[31..xvi] ori $t3, $at, &label[15..0] bge $t1, $t2, label slt $at, $t1, $t2 beq $at, $0, label blt $t1, $t2, label slt $at, $t1, $t2 bne $at, $0, label
Note: use of $at
... MIPS Instruction Set | 34/114 |
In describing instructions:
Syntax | Semantics |
$Reg | as source, the content of the register, reg[Reg] |
$Reg | every bit destination, value is stored in register, reg[Reg] = value |
Label | references the associated address (in C terms, &Label) |
Addr | any expression that yields an address (e.g. Label($Reg)) |
Addr | as source, the content of memory cellmemory[Addr] |
Addr | as destination, value is stored inmemory[Addr] = value |
Effectively ...
- treat registers asunsigned int reg[32]
- care for memory asunsigned char mem[two32]
... MIPS Instruction Ready | 35/114 |
Examples of data movement instructions:
la $t1,label# reg[t1] = &characterization lw $t1,label# reg[t1] = memory[&label] sw $t3,label# memory[&label] = reg[t3] # &label must be four-byte aligned lb $t2,characterization# reg[t2] = retentiveness[&characterization] sb $t4,label# memory[&characterization] = reg[t4] move $t2,$t3# reg[t2] = reg[t3] lui $t2,const# reg[t2][31:16] = const
Examples of fleck manipulation instructions:
and $t0,$t1,$t2# reg[t0] = reg[t1] & reg[t2] and $t0,$t1,Imm# reg[t0] = reg[t1] & Imm[t2] # Imm is a abiding (immediate) or $t0,$t1,$t2# reg[t0] = reg[t1] | reg[t2] xor $t0,$t1,$t2# reg[t0] = reg[t1] ^ reg[t2] neg $t0,$t1# reg[t0] = ~ reg[t1]
... MIPS Teaching Gear up | 36/114 |
Examples of arithmetic instructions:
add $t0,$t1,$t2# reg[t0] = reg[t1] + reg[t2] # add equally signed (ii's complement) ints sub $t2,$t3,$t4# reg[t2] = reg[t3] + reg[t4] addi $t2,$t3, 5# reg[t2] = reg[t3] + 5 # "add immediate" (no sub firsthand) addu $t1,$t6,$t7# reg[t1] = reg[t6] + reg[t7] # add every bit unsigned integers subu $t1,$t6,$t7# reg[t1] = reg[t6] + reg[t7] # subtract every bit unsigned integers mult $t3,$t4# (Hi,Lo) = reg[t3] * reg[t4] # shop 64-bit result in registers Hello,Lo div $t5,$t6# Lo = reg[t5] / reg[t6] (integer quotient) # Hi = reg[t5] % reg[t6] (remainder) mfhi $t0# reg[t0] = reg[Hello] mflo $t1# reg[t1] = reg[Lo] # used to get effect of MULT or DIV
... MIPS Didactics Set up | 37/114 |
Examples of testing and branching instructions:
seq $t7,$t1,$t2# reg[t7] = 1 if (reg[t1]==reg[t2]) # reg[t7] = 0 otherwise (signed) slt $t7,$t1,$t2# reg[t7] = 1 if (reg[t1] < reg[t2]) # reg[t7] = 0 otherwise (signed) slti $t7,$t1,Imm# reg[t7] = ane if (reg[t1] < Imm) # reg[t7] = 0 otherwise (signed) j label# PC = &label jr $t4# PC = reg[t4] beq $t1,$t2,label# PC = &label if (reg[t1] == reg[t2]) bne $t1,$t2,label# PC = &characterization if (reg[t1] != reg[t2]) bgt $t1,$t2,label# PC = &label if (reg[t1] > reg[t2]) bltz $t2,label# PC = &label if (reg[t2] < 0) bnez $t3,label# PC = &label if (reg[t3] != 0)
Later on each co-operative didactics, execution continues at new PC location
... MIPS Educational activity Set | 38/114 |
Special jump instruction for invoking functions
jal label# brand a subroutine phone call # save PC in $ra, fix PC to &label # utilise $a0,$a1 equally params, $v0 as return
... MIPS Pedagogy Prepare | 39/114 |
SPIM interacts with stdin/stdout via syscall
Service | Code | Arguments | Result |
print_int | ane | $a0 = integer | |
print_float | 2 | $f12 = float | |
print_double | 3 | $f12 = double | |
print_string | 4 | $a0 = char * | |
read_int | 5 | integer in $v0 | |
read_float | 6 | float in $f0 | |
read_double | 7 | double in $f0 | |
read_string | 8 | $a0 = buffer, $a1 = length | string in buffer (including "\northward\0") |
... MIPS Educational activity Set | twoscore/114 |
Directives (instructions to assembler, non MIPS instructions)
.text# following instructions placed in text .data# following objects placed in information .globl# make symbol bachelor globally a: .space 18# uchar a[18]; or uint a[four]; .align ii# align next object on 2ii-byte addr i: .word 2# unsigned int i = two; v: .word i,3,5# unsigned int five[3] = {1,3,5}; h: .one-half 2,iv,6# unsigned short h[3] = {2,iv,six}; b: .byte 1,2,3# unsigned char b[3] = {1,ii,3}; f: .float 3.14# float f = iii.14; due south: .asciiz "abc"# char s[4] {'a','b','c','\0'}; t: .ascii "abc"# char s[3] {'a','b','c'};
Writing straight in MIPS assembler is difficult (impossible?)
Strategy for producing likely correct MIPS code
- develop the solution in C
- map to "simplified" C
- interpret each simplified C statement to MIPS instructions
- does non have
while
switch
- does have simple
if
goto
- does not have function calls and auto local variables
- does accept jump-and-remember-where-you-came-from
... MIPS Programming | 42/114 |
Example translating C to MIPS:
C Simplified C MIPS Assembler ------------ ------------ -------------- int x = five; int ten = 5; x: .discussion v int y = iii; int y = 3; y: .word three int z; int z; z: .space iv int t; lw $t0, 10 lw $t1, y z = 5*(x+y); t = ten+y; add $t0, $t0, $t1 li $t1, 5 t = five*t; mul $t0, $t0, $t1 z = t; sw $t0, z
... MIPS Programming | 43/114 |
Simplified C makes extensive use of
- labels ... symbolic proper noun for C statement
- goto ... transfer control to labelled statement
Standard C Simplified C ------------------ ------------------ i = 0; n = 0; i = 0; due north = 0; while (i < v) { loop: north = n + i; if (i >= 5) goto end; i++; northward = n + i; } i++; goto loop; stop:
... MIPS Programming | 44/114 |
Beware: registers are shared by all parts of the lawmaking.
Ane function can overwrite value set by another office
int x;// commencement global variable int y;// second global variable int main(void) int f(int n) { { 10 = five; y = 1; y = f(10); for (10 = ane; ten <= n; x++) printf("...",10,y); y = y * x; return 0; return y; } }
After the role, x == half dozen
y == 120
It is sheer coincidence that y
... MIPS Programming | 45/114 |
Demand to be careful managing registers
- follow the conventions implied by register names
- preserve values that need to be saved across function calls
- yous manage annals usage every bit you like
- typically making use of
$t?
- you transfer control to a separate slice of code
- which may alter the value of any non-preserved register
-
$s?
-
$a?
$v?
$t?
Rendering C in MIPS | 46/114 |
C provides expression evaluation and consignment, e.g.
-
x = (1 + y*y) / 2; z = i.0 / 2;
-
move Rd,Rdue south
li Rd,Const
add
div
and
- sequence (
;
if
while
for
break
go along
-
seq
slti
sltu
beq
bgtz
bgezal
j
jr
jal
Sequence is like shooting fish in a barrel Due south1 ; S2
mips(Sone) mips(S2)
... Rendering C in MIPS | 47/114 |
Elementary case of assignment and sequence:
int x; x: .space 4 int y; y: .infinite 4 x = 2; li $t0, 2 sw $t0, 10 y = x; lw $t0, ten sw $t0, y y = x+3; lw $t0, x addi $t0, 3 sw $t0, y
Arithmetics Expressions | 48/114 |
Expression evaluation involves
- describing the procedure as a sequence of binary operations
- managing data flow between the operations
# ten = (ane + y*y) / 2 lw $t0, y mul $t0, $t0, $t0 addi $t0, $t0, one li $t1, 2 div $t0, $t1 mflo $t0 sw $t0, ten
It is useful to minimise the number of registers involved in the evaluation
Conditional Statements | 49/114 |
Conditional statements (e.g. if
Standard C Simplified C ------------------------ ------------------------ if_stat: if (Cond) t0 = (Cond) { Statements1 } if (t0 == 0) else goto else_part; { Statementsii } Statements1 goto end_if; else_part: Statementstwo end_if:
... Conditional Statements | 50/114 |
Conditional statements (due east.g. if
if_stat: if (Cond) t0 = evaluate (Cond) { Statements1 } beqz $t0, else_part else execute Statementsi { Statementsii } j end_if else_part: execute Statementsii end_if:
... Provisional Statements | 51/114 |
Example of if-then-else:
int ten; ten is $t0 int y; y is $t1 char z; z is $a0 x = getInt(); li $v0, five syscall move $t0, $v0 y = getInt(); li $v0, 5 syscall motility $t1, $v0 if (ten == y) bne $t0, $t1, printN z = 'Y'; setY: li $a0, 'Y' j impress else setN: z = 'N'; li $a0, 'N' j print# redundant print: putChar(z); li $v0, xi syscall
... Conditional Statements | 52/114 |
Could make switch
if
switch (Expr) { tmp = Expr; instance Valone: if (tmp == Val1) Statements1 ; break; { Statements1; } case Val2: else if (tmp == Val2 instance Valiii: || tmp == Valiii example Val4: || tmp == Val4) Statements2 ; interruption; { Statements2; } case Val5: else if (tmp == Valv) Statements3 ; interruption; { Statements3; } default: else Statements4 ; pause; { Statements4; } }
... Provisional Statements | 53/114 |
Jump table: an alternative implementation of switch
- works best for minor, dense range of case values (e.g. ane..10)
jump_tab: .word c1, c2, c2, c2, c3 switch: t0 = evaluate Expr switch (Expr) { if (t0 < i || t0 > 5) instance 1: jump to default Statements1 ; break; dest = jump_tab[(t0-1)*4] case ii: jump to dest case 3: c1: execute Statements1 case 4: bound to end_switch Statements2 ; break; c2: execute Statementstwo instance 5: jump to end_switch Statements3 ; break; c3: execute Statements3 default: jump to end_switch Statements4 ; break; default: } execute Statementsiv end_switch:
Boolean Expressions | 54/114 |
Boolean expressions in C are short circuit
(Condane && Cond2 && ... && Condn)
Evaluates by
- evaluate
Cond1
- evaluate
Cond2
- ...
- evaluate
Condn
- otherwise, return 1
C99 standard defines return value for booleans expressions equally 0 or ane
... Boolean Expressions | 55/114 |
Similarly for disjunctions
(Cond1 || Condii || ... || Condnorth)
Evaluates by
- evaluate
Cond1
- evaluate
Condtwo
- ...
- evaluate
Condn
- otherwise, render 1
C99 standard defines render value for booleans expressions as 0 or 1
Iteration Statements | 56/114 |
Iteration (east.g. while
top_while: while (Cond) { t0 = evaluate Cond Statements; beqz $t0,end_while } execute Statements j top_while end_while:
Treat for
while
i = 0 for (i = 0; i < Northward; i++) { while (i < North) { Statements; Statements; } i++; }
... Iteration Statements | 57/114 |
Example of iteration over an array:
int sum, i; sum: .word 4 int a[5] = {1,3,5,7,9}; a: .discussion 1,three,5,7,9 ... ... sum = 0; li $t0, 0 li $t1, 0 li $t2, iv for (i = 0; i < N; i++) for: bgt $t0, $t2, end_for move $t3, $t0 mul $t3, $t3, 4 sum += a[i]; add $t1, $t1, a($t3) printf("%d",sum); addi $t0, $t0, 1 j for end_for: sw $t1, sum move $a0, $t1 li $v0, 1 syscall
When nosotros call a function:
- the arguments are evaluated and set upwardly for function
- command is transferred to the code for the part
- local variables are created
- the function lawmaking is executed in this environment
- the render value is set up
- control transfers dorsum to where the office was called from
- the caller receives the render value
Data associated with function calls is placed on the MIPS stack.
Each part allocates a pocket-sized section of the stack (a frame)
- used for: saved registers, local variables, parameters to callees
- created in the function prologue (pushed)
- removed in the function epilogue (popped)
Why we use a stack:
- function
f()
g()
h()
-
h()
g()
-
grand()
f()
How stack changes as functions are called and return:
Register usage conventions when f()
g()
- caller saved registers (saved by
f()
-
f()
g()
-
g()
f()
- due east.one thousand.
$t0
$t9
$a0
$a3
$ra
-
- callee saved registers (saved by
g()
-
f()
1000()
-
g()
f()
- eastward.g.
$s0
$s7
$sp
$fp
-
Contents of a typical stack frame:
Aside: MIPS Branch Delay Slots | 64/114 |
The real MIPS architecture is "pipelined" to better efficiency
- one instruction tin can outset before the previous i finishes
jal
- didactics following branch is executed earlier branch completes
nop
A problem scenario, and its solution (branch delay slot):
# Implementation of print(compute(42)) li $a0, 42 li $a0, 42 jal compute jal compute move $a0, $v0 nop jal print motion $a0,$v0 jal impress
Since SPIM is not pipelined, the nop
Aside: Why practise we need both $fp and $sp? | 65/114 |
During execution of a function
-
$sp
- may demand to reference local vars on the stack
- useful if they can be divers by an offset relative to stock-still betoken
-
$fp
int f(int x) { int y = 0;// y created in prologue for (int i = 0; i < 10; i++)// i created in for-loop y += i;// which changes $sp return y; }
Part Calling Protocol | 66/114 |
Before one office calls some other, information technology needs to
- place 64-bit double args in
$f12
$f14
- place 32-bit arguments in the
$a0
$a3
- if more than four args, or args larger than 32-bits ...
- push value of all such args onto stack
- relieve whatsoever non-
$s?
- push value of all such registers onto stack
-
jal
$t0
addi $sp, $sp, -four sw $t0, ($sp)
... Function Calling Protocol | 67/114 |
Instance: simple function telephone call
int principal() {// x is $s0, y is $s1, z is $s2 int x = five; int y = 7; int z; ... z = sum(x,y,30); ... } int sum(int a, int b, int c) { return a+b+c; }
... Function Calling Protocol | 68/114 |
Simple function phone call:
... Role Calling Protocol | 69/114 |
Execution of sum()
... Role Calling Protocol | 70/114 |
Example: function f()
g(a,b,c,d,e,f)
int f(...) { int a,b,c,d,e,f; ... a = g(a,b,c,d,e,f); ... } int thousand(int u,v,w,10,y,z) { return u+v+westward*w*x*y*z; }
... Function Calling Protocol | 71/114 |
Function call in MIPS:
... Function Calling Protocol | 72/114 |
Execution of chiliad()
Structure of Functions | 73/114 |
Functions in MIPS have the following general structure:
# outset of function FuncName: # function prologue # prepare stack frame ($fp, $sp) # save relevant registers (incl. $ra) ... # part body # perform computation using $a0, etc. # leaving issue in $v0 ... # function epilogue # restore saved registers (esp. $ra) # clean up stack frame ($fp, $sp) jr $ra
Aim of prologue: create environment for function to execute in.
Before a part starts working, it needs to ...
- create a stack frame for itself (change
$fp
$sp
- save the return address (
$ra
- save any
$due south?
- 4 bytes for saved
$fp
$ra
- + 4 bytes for each saved
$southward?
$fp
$sp
- new
$fp
$sp
- new
$sp
$sp
... Function Prologue | 75/114 |
Example of function fx()
$s0
$s1
$s2
... Function Prologue | 76/114 |
Alternatively ... (more explicit push
... Function Prologue | 77/114 |
Alternatively ... (relative to new $fp
Before a function returns, it needs to ...
- place the return value in
$v0
$v1
- popular any pushed arguments off the stack
- restore the values of whatsoever saved
$s?
- restore the saved value of
$ra
- remove its stack frame (change
$fp
$sp
- return to the calling function (
jr $ra
$fp
Changing $fp
$sp
- new
$sp
$fp
- new
$fp
memory[
$fp]
... Function Epilogue | 79/114 |
Instance of function fx()
$s0
$s1
$s2
Data Structures and MIPS | 80/114 |
C data structures and their MIPS representations:
-
char
-
int
-
double
$f?
- arrays ... sequence of memory bytes/words, accessed past index
- structs ... chunk of memory, accessed by fields/offsets
- linked structures ... struct containing address of another struct
char
int
double
- could be implemented in register if used in pocket-sized scope
- could be implemented on stack if local to function
- could be implemented in
.data
Static vs Dynamic Allocation | 81/114 |
Static allotment:
- uninitialised memory allocated at compile/gather-time, e.yard.
int val; val: .infinite 4 char str[20]; str: .infinite 20 int vec[20]; vec: .space eighty
- initialised memory allocated at compile/assemble-time, e.one thousand.
int val = five; val: .word five int arr[4] = {9,8,7,6}; arr: .word 9, 8, 7, vi char *msg = "Hello\n"; msg: .asciiz "Hello\north"
... Static vs Dynamic Allocation | 82/114 |
Dynamic allocation (i):
- variables local to a function
- use space allocated on stack during part prologue
- referenced during function relative to
$fp
- space reclaimed from stack in role epilogue
int fx(int a[]) { int i, j, max; i = 1; j = two; max = i+j; ... }
... Static vs Dynamic Allocation | 83/114 |
Example of local variables on the stack:
... Static vs Dynamic Resource allotment | 84/114 |
Dynamic allocation (ii):
- uninitialised cake of memory allocated at run-time
int *ptr = malloc(sizeof(int)); char *str = malloc(20*sizeof(char)); int *vec = malloc(20*sizeof(int)); *ptr = five; strcpy(str, "a cord"); vec[0] = 1;
// or *vec = one; vec[i] = 6; - initialised block of memory allocated at run-time
int *vec = calloc(20, sizeof(int));
// vec[i] == 0, for i in 0..19
... Static vs Dynamic Allocation | 85/114 |
SPIM doesn't provide malloc()
free()
- simply provides
syscall
.information
- before
syscall
$a0
- later on
syscall
$v0
li $a0, 20# $v0 = malloc(20) li $v0, 9 syscall move $s0, $v0# $s0 = $v0
Cannot admission allocated data by name; need to retain address.
No mode to free allocated data, and no way to align data appropriately
... Static vs Dynamic Allocation | 86/114 |
Implementing C-similar malloc()
free()
- a complete implementation of C's heap management, i.e.
- a big region of memory to manage (
syscall
- power to mark chunks of this region as "in utilize" (with size)
- ability to maintain listing of complimentary chunks
- ability to merge free chunks to prevent fragmentation
Can be named/initialised as noted in a higher place:
vec: .space 40# could exist either int vec[10] or char vec[xl] nums: .word 1, iii, v, 7, ix# int nums[6] = {1,3,five,seven,9}
Tin access elements via index or cursor (arrow)
- either approach needs to account for size of elements
- must besides pass assortment size, since not bachelor elsewhere
sumOf()
... i-d Arrays in MIPS | 88/114 |
Scanning across an assortment of N
# int vec[10] = {...}; # int i; # for (i = 0; i < 10; i++) # printf("%d\n", vec[i]); li $s0, 0# i = 0 li $s1, 10# no of elements li $s2, 4# sizeof each element loop: bge $s0, $s1, end_loop# if (i >= ten) interruption mul $t0, $s0, $s2# index -> byte start lw $a0, vec($t0)# a0 = vec[i] jal print# print a0 addi $s0, $s0, 1# i++ j loop end_loop:
Assumes the existence of a print()
printf("%d\n",10)
... 1-d Arrays in MIPS | 89/114 |
Scanning beyond an array of N
# int vec[10] = {...}; # int *cur, *finish = &vec[10]; # for (cur = vec; cur < end; cur++) # printf("%d\n", *cur); la $s0, vec# cur = &vec[0] la $s1, vec+40# cease = &vec[10] loop: bge $s0, $s1, end_loop# if (cur >= end) interruption lw $a0, ($s0)# a0 = *cur jal impress# print a0 addi $s0, $s0, four# cur++ j loop end_loop:
Assumes the being of a print()
printf("%d\northward",x)
... ane-d Arrays in MIPS | 90/114 |
Arrays that are local to functions are allocated infinite on the stack
fun: int fun(int x)# prologue { addi $sp, $sp, -4 sw $fp, ($sp) move $fp, $sp addi $sp, $sp, -4 sw $ra, ($sp) // push button a[] onto stack addi $sp, $sp, -40 int a[10]; move $s0, $sp int *s0 = a;# office trunk ... compute ... // compute using s0# epilogue // to admission a[] addi $sp, $sp, forty // pop a[] off stack lw $ra, ($sp) addi $sp, $sp, iv lw $fp, ($sp) addi $sp, $sp, 4 jr $ra }
2-d arrays could be represented ii ways:
... 2-d Arrays in MIPS | 92/114 |
Representations ofint matrix[4][4]
# for strategy (a) matrix: .space 64# for strategy (b) row0: .space 16 row1: .infinite 16 row2: .infinite 16 row3: .infinite 16 matrix: .discussion row0, row1, row2, row3
Now consider summing all elements
int i, j, sum = 0; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) sum += matrix[i][j];
... two-d Arrays in MIPS | 93/114 |
Accessing elements:
... ii-d Arrays in MIPS | 94/114 |
Calculating sum of all elements for strategy (a)int matrix[4][four]
li $s0, 0# sum = 0 li $s1, 4# s1 = 4 (and sizeof int) li $s2, 0# i = 0 li $s3, 16# sizeof row in bytes loop1: beq $s2, $s1, end1# if (i >= 4) break li $s3, 0# j = 0 loop2: beq $s3, $s1, end2# if (j >= 4) break mul $t0, $s2, $s3# off = iv*4*i + 4*j mul $t1, $s3, $s1# matrix[i][j] is add $t0, $t0, $t1# done equally *(matrix+off) lw $t0, matrix($t0)# t0 = matrix[i][j] add $s0, $s0, $t0# sum += t0 addi $s3, $s3, ane# j++ j loop2 end2: addi $s2, $s2, i# i++ j loop1 end1:
... ii-d Arrays in MIPS | 95/114 |
Computing sum of all elements for strategy (b)int matrix[four][4]
li $s0, 0# sum = 0 li $s1, 4# s1 = 4 (sizeof(int)) li $s2, 0# i = 0 loop1: beq $s2, $s1, end1# if (i >= 4) suspension li $s3, 0# j = 0 mul $t0, $s2, $s1# off = 4*i lw $s4, matrix($t0)# row = &matrix[i][0] loop2: beq $s3, $s1, end2# if (j >= 4) pause mul $t0, $s3, $s1# off = four*j add $t0, $t0, $s4# int *p = &row[j] lw $t0, ($t0)# t0 = *p add $s0, $s0, $t0# sum += t0 addi $s3, $s3, i# j++ j loop2 end2: addi $s2, $s2, 1# i++ j loop1 end1:
C struct
... Structs in MIPS | 97/114 |
C struct
// new type called struct _student struct _student {...};// new type called Student typedef struct _student Educatee;
Instances of structures can exist created by allocating space:
// sizeof(Student) == 56 stu1: Student stu1; .space 56 stu2: Student stu2; .space 56 stu: .space 4 Student *stu;
... Structs in MIPS | 98/114 |
Accessing structure components is by offset, non proper name
li $t0 5012345 sw $t0, stu1+0 # stu1.id = 5012345; li $t0, 3778 sw $t0, stu1+44 # stu1.program = 3778; la $s1, stu2 # stu = & stu2; li $t0, 3707 sw $t0, 44($s1) # stu->program = 3707; li $t0, 5034567 sw $t0, 0($s1) # stu->id = 5034567;
... Structs in MIPS | 99/114 |
Structs that are local to functions are allocated space on the stack
fun: int fun(int x)# prologue { addi $sp, $sp, -4 sw $fp, ($sp) movement $fp, $sp addi $sp, $sp, -4 sw $ra, ($sp) // push onto stack addi $sp, $sp, -56 Pupil st; motion $t0, $sp Student *t0 = &st;# function trunk ... compute ... // compute using t0# epilogue // to access struct addi $sp, $sp, 56 // pop st off stack lw $ra, ($sp) addi $sp, $sp, 4 lw $fp, ($sp) addi $sp, $sp, 4 jr $ra }
... Structs in MIPS | 100/114 |
C can laissez passer whole structures to functions, e.g.
# Pupil stu; ... # // ready values in stu struct # showStudent(stu); .information stu: .space 56 .text ... la $t0, stu addi $sp, $sp, -56# button Student object onto stack lw $t1, 0($t0)# allocate space and copy all sw $t1, 0($sp)# values in Student object lw $t1, 4($t0)# onto stack sw $t1, 4($sp) ... lw $t1, 52($t0)# and once whole object copied sw $t1, 52($sp) jal showStudent# invoke showStudent() ...
... Structs in MIPS | 101/114 |
Accessing struct
... Structs in MIPS | 102/114 |
Can likewise pass a pointer to a struct
# Student stu; # // set values in stu struct # changeWAM(&stu, float newWAM); .data stu: .infinite 56 wam: .space 4 .text ... la $a0, stu lw $a1, wam jal changeWAM ...
Clearly a more efficient way to pass a large struct
Likewise, required if the function needs to update the original struct
Compiling C to MIPS | 103/114 |
Using simplified C as an intermediate language
- makes things easier for a human to prodcue MIPS lawmaking
- does not provide an automatic way of translating
- this is provided by a compiler (east.thousand.
dcc
- catechumen
#include
#ascertain
- parse code to check syntactically valid
- manage a list of symbols used in program
- decide how to represent information structures
- allocate local variables to registers or stack
- map control structures to MIPS instructions
Maps C→C, performing various substitutions
-
#include
- replace
#include
-
"
.h"
.h
-
<
.h>
.h
/usr/include
- replace
-
#ascertain
- replace all occurences of symbol Name by Constant
- e.g
#define MAX v
char array[MAX]
char array[5]
-
#define
(
)
- supercede Proper name
(
)
- e.g.
#define max(x,y) ((x > y) ? 10 : y)
a = max(b,c)
a = ((b > c) ? b : c)
- supercede Proper name
... C Pre-processor | 105/114 |
More C pre-processor substitions
Before cpp Afterward cpp x = 5; x = 5; #if 0 ten = x + 2; x = x + 1; printf("x=%d\n",x); #else x = x * 2; x = x + 2;
0 Response to "How To Assign A Char To A Register Mips"
Post a Comment