Opening Mips Code to Read in C
C: Associates Language (MIPS)
Didactics Gear up Architectures |
A typical mod CPU has
- a ready of data registers
- a set of command registers (incl PC)
- an arithmetic-logic unit (ALU)
- access to random admission retentiveness (RAM)
- a set of simple instructions
- transfer data between memory and registers
- push button values through the ALU to compute results
- brand tests and transfer command of execution
Different types of processors take different configurations of the above
- e.1000. unlike # registers, different sized registers, dissimilar instructions
Why Study Assembler? | three/114 |
Useful to know assembly language because ...
- sometimes you are required to use it (e.g. device handlers)
- improves your agreement of how C programs execute
- very helpful when debugging
- able to avoid using known inefficient constructs
- uber-nerdy performance tweaking (squeezing out terminal nano-s)
- re-write that disquisitional (ofttimes-used) office in assembler
Two broad families of education fix architectures ...
RISC (reduced didactics set computer)
- small(ish) set of uncomplicated, full general instructions
- split up 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 circuitry to decode/process instructions
- e.g. PDP, VAX, Z80, Motorola 68xxx, Intel x86, ...
... Instruction Sets | 5/114 |
Automobile-level instructions ...
- typically accept 1-two 32-flake words per pedagogy
- division bits in each give-and-take into operator & operands
- #bits for each depends on #instructions, #registers, ...
Operands and destination are typically registers
... Instruction Sets | 6/114 |
Common kinds of instructions
-
load
,
- copy value stored in retention at address into named register
-
loadc
,
- re-create value into named register
-
store
,
- re-create value stored in named annals into retentivity at address
-
jump
- transfer execution of plan to instruction at address
-
jumpif
,
- transfer execution of program if e.m. register holds zero value
... Instruction Sets | 7/114 |
Other common kinds of instructions
-
add
,
,
sub
mul
div
- Register3 = Registerone
+
- Register3 = Registerone
-
and
,
,
or
xor
- Annalsthree = Registeri
&
- Annalsthree = Registeri
-
neg
,
- Annals2 =
~
- Annals2 =
-
shiftl
,
,
shiftr
- Register2 = Registerane
<<
- Register2 = Registerane
-
syscall
- invoke a system service; which service determined by Value
... Instruction Sets | eight/114 |
All CPUs have plan execution logic similar:
while (1) { instruction = memory[PC] PC++// motion to next instr if (instruction == HALT) break else execute(instruction) }
PC = Program Counter, a CPU register which keeps track of execution
Note that some instructions may change PC farther (e.1000. Jump)
... Fetch-Execute Cycle | ten/114 |
Executing an instruction
- decide what the operator is
- make up one's mind which registers, if whatsoever, are involved
- determine which retentiveness location, if any, is involved
- carry out the functioning with the relevant operands
- store effect, if any, in appropriate register
Instructions are simply chip patterns inside a 32-bit bit-string
Could depict car programs equally a sequence of hex digits, e.thou.
Address Content 0x100000 0x3c041001 0x100004 0x34020004 0x100008 0x0000000c 0x10000C 0x03e00008
Often call "assembly language" as "assembler"
Slight notational abuse, considering "assembler" also refers to a plan that translates assembly language to motorcar code
... Assembly Language | 12/114 |
Assembler = symbolic language for writing machine code
- write instructions using mnemonics rather than hex codes
- reference registers using either numbers or names
- can associate names to retentivity addresses
Mode of expression is significantly unlike to e.g. C
- need to utilise fine-grained control of memory usage
- required to dispense data in registers
- control structures programmed via explicit jumps
MIPS is a well-known and relatively simple compages
- very popular in a range of computing devices in the 1990'south
- e.thousand. Silicon Graphics, NEC, Nintendo64, Playstation, supercomputers
- using two variants of the open-source SPIM emulator
-
qtspim
-
spim
-
xspim
Source lawmaking for browsing under /dwelling/cs1521/spim/spim
MIPS is a machine architecture, including instruction set
SPIM is an emulator for the MIPS instruction set
- reads text files containing instruction + directives
- converts to machine code and loads into "memory"
- provides debugging capabilities
- unmarried-step, breakpoints, view registers/retentivity, ...
- provides machinery to interact with operating system (syscall)
- provide convenient/mnemonic means to do common operations
- e.thousand.
movement $s0,$v0
addu $s0,$0,$v0
Three ways to execute MIPS lawmaking with SPIM
-
spim
- load programs using
-file
- collaborate using stdin/stdout via login final
- load programs using
-
qtspim
- load programs via a load button
- collaborate via a pop-up stdin/stdout terminal
-
xspim
- similar to
qtspim
- requires X-windows server
- similar to
Command-line tool:
GUI tool:
MIPS Machine Archtecture | eighteen/114 |
MIPS CPU has
- 32 × 32-flake general purpose registers
- sixteen × 64-bit double-precision registers
- PC ... 32-bit register (always aligned on 4-byte purlieus)
- Hullo,LO ... for storing results of multiplication and division
$0..$31
Some registers have special uses e.k.
- register
$0
- registers
$1
$26
$27
... MIPS Car Archtecture | 19/114 |
Registers and their usage
Reg | Proper noun | Notes | ||
$0 | naught | the value 0, not changeable | ||
$1 | $at | assembler temporary; used to implement pseudo-ops | ||
$2 | $v0 | value from expression evaluation or role return | ||
$3 | $v1 | value from expression evaluation or function render | ||
$iv | $a0 | start argument to a part/subroutine, if needed | ||
$5 | $a1 | 2nd argument to a function/subroutine, if needed | ||
$6 | $a2 | third argument to a function/subroutine, if needed | ||
$7 | $a3 | 4th argument to a office/subroutine, if needed | ||
$viii $xv | $t0 $t7 | temporary; must be saved by caller to subroutine; subroutine can overwrite |
... MIPS Auto Archtecture | twenty/114 |
More than register usage ...
Reg | Proper noun | Notes | ||
$16 | $s0 $s7 | southwardafe part variable; must not exist overwritten by called subroutine | ||
$24 $25 | $t8 $t9 | temporary; must be saved by caller to subroutine; subroutine can overwrite | ||
$26 $27 | $k0 $k1 | for chiliadernel use; may change unexpectedly | ||
$28 | $gp | global pointer | ||
$29 | $sp | stack pointer | ||
$thirty | $fp | frame pointer | ||
$31 | $ra | return address of about recent caller |
... MIPS Machine Archtecture | 21/114 |
Floating indicate register usage ...
Reg | Notes | |
$f0 $f2 | agree floating-point function results | |
$f4 $f10 | temporary registers; not preserved across function calls | |
$f12 $f14 | used for beginning ii double-precision function arguments | |
$f16 $f18 | temporary registers; used for expression evaluation | |
$f20 $f30 | saved registers; value is preserved across part calls |
Notes:
- registers come up in pairs of two × 32-bits
- but even registers are addressed for double-precision
MIPS Assembly Linguistic communication | 22/114 |
MIPS assembly language programs incorporate
- comments ... introduced by
#
- labels ... appended with
:
- directives ... symbol beginning with
.
- associates language instructions
- data objects that alive in the information region
- functions (pedagogy sequences) that live in the code/text region
... MIPS Associates Linguistic communication | 23/114 |
Case MIPS assembler plan:
# hello.southward ... print "Hello, MIPS" .data# the data segment msg: .asciiz "How-do-you-do, MIPS\n" .text# the code segment .globl main main: la $a0, msg# load the argument string li $v0, iv# load the organisation call (print) syscall# print the string jr $ra# render to caller (__start)
Color coding: label, directive, annotate
... MIPS Assembly Language | 24/114 |
Generic structure of MIPS programs
# Prog.south ... annotate giving description of office # Writer ... .data# variable declarations follow this line # ... .text# instructions follow this line .globl master main:# indicates start of code # (i.e. first user instruction to execute) # ... # End of plan; leave a blank line to make SPIM happy
... MIPS Assembly Linguistic communication | 25/114 |
Some other instance MIPS assembler program:
.data a: .word 42# int a = 42; b: .space four# int b; .text .globl master main: lw $t0, a# reg[t0] = a li $t1, eight# reg[t1] = eight 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 retentiveness layout
Region | Address | Notes | ||
text | 0x00400000 | contains just instructions; read-simply; cannot expand | ||
data | 0x10000000 | data objects; readable/writeable; can exist expanded | ||
stack | 0x7fffefff | grows down from that address; readable/writeable | ||
k_text | 0x80000000 | kernel lawmaking; read-only; simply attainable kernel mode | ||
k_data | 0x90000000 | kernel data; read/write; simply attainable kernel mode |
MIPS has several classes of instructions:
- load and shop .. transfer information between registers and memory
- computational ... perform arithmetic/logical operations
- jump and branch ... transfer control of programme execution
- coprocessor ... standard interface to various co-processors
- special ... miscellaneous tasks (due east.g. syscall)
- between memory and register (straight, indirect)
- constant to register (firsthand)
- register + register + destination register
... MIPS Instructions | 28/114 |
MIPS instructions are 32-bits long, and specify ...
- an operation (e.1000. load, store, add, co-operative, ...)
- ane or more operands (e.m. registers, retentiveness addresses, constants)
Retentiveness addresses can be given by
- symbolic name (label) (effectively, a constant)
- indirectly via a register (effectively, pointer dereferencing)
prog: a: lw $t0, var# accost via proper noun b: lw $t0, ($s0)# indirect addressing c: lw $t0, 4($s0)# indexed addressing
If $s0
0x10000000
&var
0x100000008
- computed address for
a:
0x100000008
- computed accost for
b:
0x100000000
- computed address for
c:
0x100000004
... Addressing Modes | thirty/114 |
Addressing modes in MIPS
Format | Address ciphering | |
(annals) | address = *register = contents of annals | |
thou | address = k | |
1000(register) | address = k + *register | |
symbol | address = &symbol = address of symbol | |
symbol ± g | address = &symbol ± one thousand | |
symbol ± k(register) | accost = &symbol ± (k + *register) |
where k is a literal constant value (east.g. 4
0x10000000
... Addressing Modes | 31/114 |
Examples of load/store and addressing:
.data vec: .space 16# int vec[4], xvi bytes of storage .text __start: la $t0, vec# reg[t0] = &vec li $t1, 5# reg[t1] = v sw $t1, ($t0)# vec[0] = reg[t1] li $t1, 13# reg[t1] = xiii sw $t1, 4($t0)# vec[1] = reg[t1] li $t1, -7# reg[t1] = -7 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 tin dispense different-sized operands
- unmarried bytes, two bytes ("halfword"), 4 bytes ("discussion")
Leads to many opcodes for a (conceptually) unmarried operation, due east.g.
-
LB
-
LBU
-
LH
-
LHU
-
LW
-
LA
MIPS Pedagogy Prepare | 33/114 |
The MIPS processor implements a base set of instructions, due east.thousand.
-
lw
sw
add
sub
and
or
sll
slt
beq
j
jal
-
move
rem
la
li
blt
Pseudo-didactics Base instruction(south) li $t5, const ori $t5, $0, const la $t3, characterization lui $at, &characterization[31..16] 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, characterization
Notation: apply of $at
... MIPS Instruction Set | 34/114 |
In describing instructions:
Syntax | Semantics |
$Reg | equally source, the content of the annals, reg[Reg] |
$Reg | as 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.one thousand. Label($Reg)) |
Addr | as source, the content of memory jail cellmemory[Addr] |
Addr | equally destination, value is stored inretentiveness[Addr] = value |
Finer ...
- treat registers asunsigned int reg[32]
- treat memory asunsigned char mem[232]
... MIPS Educational activity Fix | 35/114 |
Examples of data movement instructions:
la $t1,label# reg[t1] = &label lw $t1,characterization# reg[t1] = memory[&label] sw $t3,label# memory[&characterization] = reg[t3] # &label must be 4-byte aligned lb $t2,label# reg[t2] = memory[&label] sb $t4,label# retention[&label] = reg[t4] move $t2,$t3# reg[t2] = reg[t3] lui $t2,const# reg[t2][31:16] = const
Examples of bit 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 Instruction Set | 36/114 |
Examples of arithmetics instructions:
add $t0,$t1,$t2# reg[t0] = reg[t1] + reg[t2] # add together as signed (2's complement) ints sub $t2,$t3,$t4# reg[t2] = reg[t3] + reg[t4] addi $t2,$t3, v# 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 as unsigned integers mult $t3,$t4# (Hi,Lo) = reg[t3] * reg[t4] # store 64-bit result in registers Hullo,Lo div $t5,$t6# Lo = reg[t5] / reg[t6] (integer quotient) # Hi = reg[t5] % reg[t6] (remainder) mfhi $t0# reg[t0] = reg[Hullo] mflo $t1# reg[t1] = reg[Lo] # used to get result of MULT or DIV
... MIPS Didactics Set | 37/114 |
Examples of testing and branching instructions:
seq $t7,$t1,$t2# reg[t7] = one 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] = 1 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 = &label if (reg[t1] != reg[t2]) bgt $t1,$t2,label# PC = &characterization if (reg[t1] > reg[t2]) bltz $t2,characterization# PC = &characterization if (reg[t2] < 0) bnez $t3,label# PC = &label if (reg[t3] != 0)
After each branch instruction, execution continues at new PC location
... MIPS Instruction Set | 38/114 |
Special jump instruction for invoking functions
jal characterization# make a subroutine call # relieve PC in $ra, fix PC to &label # use $a0,$a1 as params, $v0 as return
... MIPS Instruction Gear up | 39/114 |
SPIM interacts with stdin/stdout via syscall
Service | Code | Arguments | Result |
print_int | 1 | $a0 = integer | |
print_float | 2 | $f12 = float | |
print_double | iii | $f12 = double | |
print_string | 4 | $a0 = char * | |
read_int | 5 | integer in $v0 | |
read_float | half-dozen | bladder in $f0 | |
read_double | 7 | double in $f0 | |
read_string | viii | $a0 = buffer, $a1 = length | cord in buffer (including "\northward\0") |
... MIPS Pedagogy Set | xl/114 |
Directives (instructions to assembler, not MIPS instructions)
.text# following instructions placed in text .data# following objects placed in data .globl# brand symbol available globally a: .infinite 18# uchar a[18]; or uint a[iv]; .marshal 2# align next object on 22-byte addr i: .word two# unsigned int i = 2; v: .discussion 1,iii,5# unsigned int v[3] = {1,3,v}; h: .half 2,4,half-dozen# unsigned short h[3] = {2,4,6}; b: .byte 1,2,iii# unsigned char b[iii] = {one,ii,3}; f: .float 3.xiv# float f = 3.14; due south: .asciiz "abc"# char s[4] {'a','b','c','\0'}; t: .ascii "abc"# char s[3] {'a','b','c'};
Writing direct in MIPS assembler is difficult (impossible?)
Strategy for producing likely right MIPS code
- develop the solution in C
- map to "simplified" C
- interpret each simplified C statement to MIPS instructions
- does not have
while
switch
- does have uncomplicated
if
goto
- does not accept function calls and auto local variables
- does have jump-and-remember-where-you-came-from
... MIPS Programming | 42/114 |
Example translating C to MIPS:
C Simplified C MIPS Assembler ------------ ------------ -------------- int ten = 5; int x = 5; ten: .word 5 int y = 3; int y = 3; y: .word 3 int z; int z; z: .space iv int t; lw $t0, 10 lw $t1, y z = 5*(x+y); t = 10+y; add $t0, $t0, $t1 li $t1, 5 t = 5*t; mul $t0, $t0, $t1 z = t; sw $t0, z
... MIPS Programming | 43/114 |
Simplified C makes all-encompassing employ of
- labels ... symbolic proper noun for C statement
- goto ... transfer control to labelled statement
Standard C Simplified C ------------------ ------------------ i = 0; due north = 0; i = 0; due north = 0; while (i < 5) { loop: north = n + i; if (i >= 5) goto stop; i++; n = n + i; } i++; goto loop; end:
... MIPS Programming | 44/114 |
Beware: registers are shared past all parts of the code.
One function can overwrite value set up by another function
int x;// first global variable int y;// 2d global variable int chief(void) int f(int n) { { ten = 5; y = 1; y = f(x); for (x = 1; x <= north; 10++) printf("...",x,y); y = y * x; return 0; return y; } }
Later the office, x == vi
y == 120
It is sheer coincidence that y
... MIPS Programming | 45/114 |
Need to be careful managing registers
- follow the conventions implied by register names
- preserve values that need to be saved across function calls
- you manage register usage every bit you like
- typically making employ of
$t?
- you transfer control to a dissever piece of code
- which may modify the value of whatever non-preserved annals
-
$s?
-
$a?
$5?
$t?
Rendering C in MIPS | 46/114 |
C provides expression evaluation and assignment, eastward.1000.
-
ten = (1 + y*y) / 2; z = 1.0 / 2;
-
move Rd,Rs
li Rd,Const
add
div
and
- sequence (
;
if
while
for
pause
continue
-
seq
slti
sltu
beq
bgtz
bgezal
j
jr
jal
Sequence is easy S1 ; Southward2
mips(South1) mips(Southward2)
... Rendering C in MIPS | 47/114 |
Simple example of consignment and sequence:
int x; x: .infinite 4 int y; y: .space 4 x = 2; li $t0, 2 sw $t0, ten y = x; lw $t0, x sw $t0, y y = x+3; lw $t0, x addi $t0, 3 sw $t0, y
Arithmetic Expressions | 48/114 |
Expression evaluation involves
- describing the process as a sequence of binary operations
- managing data menses between the operations
# x = (1 + y*y) / 2 lw $t0, y mul $t0, $t0, $t0 addi $t0, $t0, ane li $t1, ii div $t0, $t1 mflo $t0 sw $t0, x
Information technology 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) { Statementsi } if (t0 == 0) else goto else_part; { Statementstwo } Statementsi goto end_if; else_part: Statements2 end_if:
... Conditional Statements | 50/114 |
Conditional statements (e.g. if
if_stat: if (Cond) t0 = evaluate (Cond) { Statementsane } beqz $t0, else_part else execute Statements1 { Statementsii } j end_if else_part: execute Statements2 end_if:
... Conditional Statements | 51/114 |
Example of if-then-else:
int x; 10 is $t0 int y; y is $t1 char z; z is $a0 x = getInt(); li $v0, 5 syscall move $t0, $v0 y = getInt(); li $v0, five syscall move $t1, $v0 if (ten == y) bne $t0, $t1, printN z = 'Y'; setY: li $a0, 'Y' j print else setN: z = 'Northward'; li $a0, 'N' j print# redundant print: putChar(z); li $v0, 11 syscall
... Provisional Statements | 52/114 |
Could make switch
if
switch (Expr) { tmp = Expr; example Val1: if (tmp == Vali) Statements1 ; break; { Statements1; } instance Val2: else if (tmp == Valii example Val3: || tmp == Val3 case Val4: || tmp == Val4) Statements2 ; break; { Statementstwo; } case Valfive: else if (tmp == Valfive) Statements3 ; break; { Statements3; } default: else Statements4 ; break; { Statements4; } }
... Conditional Statements | 53/114 |
Bound table: an alternative implementation of switch
- works all-time for pocket-size, dense range of case values (e.g. 1..ten)
jump_tab: .word c1, c2, c2, c2, c3 switch: t0 = evaluate Expr switch (Expr) { if (t0 < 1 || t0 > 5) case one: spring to default Statementsone ; break; dest = jump_tab[(t0-1)*4] case 2: bound to dest case 3: c1: execute Statements1 case 4: spring to end_switch Statements2 ; break; c2: execute Statements2 case 5: jump to end_switch Statements3 ; break; c3: execute Statements3 default: jump to end_switch Statements4 ; break; default: } execute Statementsfour end_switch:
Boolean Expressions | 54/114 |
Boolean expressions in C are curt excursion
(Cond1 && Cond2 && ... && Condn)
Evaluates by
- evaluate
Condane
- evaluate
Cond2
- ...
- evaluate
Condn
- otherwise, return 1
C99 standard defines return value for booleans expressions as 0 or 1
... Boolean Expressions | 55/114 |
Similarly for disjunctions
(Cond1 || Cond2 || ... || Conddue north)
Evaluates past
- evaluate
Condane
- evaluate
Cond2
- ...
- evaluate
Condn
- otherwise, render ane
C99 standard defines render value for booleans expressions as 0 or 1
Iteration Statements | 56/114 |
Iteration (e.one thousand. 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 < Due north; i++) { while (i < N) { Statements; Statements; } i++; }
... Iteration Statements | 57/114 |
Example of iteration over an array:
int sum, i; sum: .word 4 int a[5] = {1,3,v,vii,9}; a: .word 1,3,5,7,9 ... ... sum = 0; li $t0, 0 li $t1, 0 li $t2, 4 for (i = 0; i < Northward; 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, i j for end_for: sw $t1, sum move $a0, $t1 li $v0, ane syscall
When we telephone call a function:
- the arguments are evaluated and ready up for function
- command is transferred to the code for the function
- local variables are created
- the function lawmaking is executed in this environment
- the return value is set up
- command transfers back to where the role was called from
- the caller receives the return value
Data associated with part calls is placed on the MIPS stack.
Each function allocates a small-scale section of the stack (a frame)
- used for: saved registers, local variables, parameters to callees
- created in the role prologue (pushed)
- removed in the function epilogue (popped)
Why we use a stack:
- part
f()
g()
h()
-
h()
g()
-
g()
f()
How stack changes equally functions are called and render:
Register usage conventions when f()
g()
- caller saved registers (saved past
f()
-
f()
thou()
-
g()
f()
- east.g.
$t0
$t9
$a0
$a3
$ra
-
- callee saved registers (saved by
k()
-
f()
k()
-
thou()
f()
- eastward.m.
$s0
$s7
$sp
$fp
-
Contents of a typical stack frame:
Aside: MIPS Branch Delay Slots | 64/114 |
The real MIPS compages is "pipelined" to ameliorate efficiency
- one pedagogy can first before the previous one finishes
jal
- instruction following branch is executed earlier branch completes
nop
A trouble scenario, and its solution (branch filibuster slot):
# Implementation of print(compute(42)) li $a0, 42 li $a0, 42 jal compute jal compute move $a0, $v0 nop jal print move $a0,$v0 jal print
Since SPIM is not pipelined, the nop
Bated: Why practise we demand both $fp and $sp? | 65/114 |
During execution of a part
-
$sp
- may need to reference local vars on the stack
- useful if they can be defined by an get-go relative to fixed point
-
$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; }
Function Calling Protocol | 66/114 |
Earlier one role calls another, it needs to
- identify 64-bit double args in
$f12
$f14
- identify 32-bit arguments in the
$a0
$a3
- if more than iv args, or args larger than 32-bits ...
- button value of all such args onto stack
- salvage whatsoever non-
$due south?
- push value of all such registers onto stack
-
jal
$t0
addi $sp, $sp, -4 sw $t0, ($sp)
... Function Calling Protocol | 67/114 |
Example: uncomplicated function call
int main() {// 10 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; }
... Office Calling Protocol | 68/114 |
Simple function phone call:
... Role Calling Protocol | 69/114 |
Execution of sum()
... Function Calling Protocol | lxx/114 |
Example: function f()
g(a,b,c,d,due east,f)
int f(...) { int a,b,c,d,eastward,f; ... a = thou(a,b,c,d,e,f); ... } int thou(int u,five,w,10,y,z) { render u+five+w*due west*x*y*z; }
... Function Calling Protocol | 71/114 |
Function call in MIPS:
... Function Calling Protocol | 72/114 |
Execution of g()
Structure of Functions | 73/114 |
Functions in MIPS have the following general structure:
# start of part FuncName: # function prologue # gear up up stack frame ($fp, $sp) # save relevant registers (incl. $ra) ... # part trunk # perform computation using $a0, etc. # leaving consequence in $v0 ... # role epilogue # restore saved registers (esp. $ra) # clean up stack frame ($fp, $sp) jr $ra
Aim of prologue: create environs for function to execute in.
Before a function starts working, it needs to ...
- create a stack frame for itself (change
$fp
$sp
- save the return address (
$ra
- save whatsoever
$southward?
- four bytes for saved
$fp
$ra
- + four bytes for each saved
$s?
$fp
$sp
- new
$fp
$sp
- new
$sp
$sp
... Function Prologue | 75/114 |
Example of part fx()
$s0
$s1
$s2
... Role Prologue | 76/114 |
Alternatively ... (more than explicit push button
... Function Prologue | 77/114 |
Alternatively ... (relative to new $fp
Before a function returns, it needs to ...
- identify the return value in
$v0
$v1
- pop whatever pushed arguments off the stack
- restore the values of whatever saved
$south?
- restore the saved value of
$ra
- remove its stack frame (change
$fp
$sp
- render to the calling part (
jr $ra
$fp
Changing $fp
$sp
- new
$sp
$fp
- new
$fp
retentiveness[
$fp]
... Function Epilogue | 79/114 |
Example of function fx()
$s0
$s1
$s2
Information Structures and MIPS | 80/114 |
C information structures and their MIPS representations:
-
char
-
int
-
double
$f?
- arrays ... sequence of memory bytes/words, accessed by index
- structs ... clamper of memory, accessed by fields/offsets
- linked structures ... struct containing address of another struct
char
int
double
- could exist implemented in annals if used in pocket-size scope
- could be implemented on stack if local to office
- could be implemented in
.data
Static vs Dynamic Allocation | 81/114 |
Static allocation:
- uninitialised retentiveness allocated at compile/assemble-time, east.g.
int val; val: .space 4 char str[20]; str: .space 20 int vec[20]; vec: .space 80
- initialised memory allocated at compile/gather-fourth dimension, e.g.
int val = v; val: .give-and-take 5 int arr[four] = {9,8,7,6}; arr: .give-and-take 9, 8, 7, six char *msg = "Hello\n"; msg: .asciiz "Hello\n"
... Static vs Dynamic Allocation | 82/114 |
Dynamic allocation (i):
- variables local to a function
- use space allocated on stack during role prologue
- referenced during function relative to
$fp
- infinite reclaimed from stack in function epilogue
int fx(int a[]) { int i, j, max; i = 1; j = 2; max = i+j; ... }
... Static vs Dynamic Allocation | 83/114 |
Case of local variables on the stack:
... Static vs Dynamic Allotment | 84/114 |
Dynamic allocation (ii):
- uninitialised block of memory allocated at run-fourth dimension
int *ptr = malloc(sizeof(int)); char *str = malloc(20*sizeof(char)); int *vec = malloc(twenty*sizeof(int)); *ptr = 5; strcpy(str, "a string"); vec[0] = ane;
// or *vec = 1; vec[one] = six; - initialised block of memory allocated at run-time
int *vec = calloc(20, sizeof(int));
// vec[i] == 0, for i in 0..xix
... Static vs Dynamic Allocation | 85/114 |
SPIM doesn't provide malloc()
free()
- merely provides
syscall
.data
- before
syscall
$a0
- afterwards
syscall
$v0
li $a0, 20# $v0 = malloc(20) li $v0, 9 syscall movement $s0, $v0# $s0 = $v0
Cannot access allocated information by name; demand to retain address.
No way to free allocated data, and no way to align data accordingly
... Static vs Dynamic Allocation | 86/114 |
Implementing C-similar malloc()
complimentary()
- a complete implementation of C's heap direction, i.due east.
- a large region of retention to manage (
syscall
- ability to marker chunks of this region equally "in utilise" (with size)
- ability to maintain list of gratis chunks
- ability to merge free chunks to prevent fragmentation
Can be named/initialised equally noted higher up:
vec: .space 40# could be either int vec[10] or char vec[xl] nums: .word 1, iii, five, 7, 9# int nums[6] = {1,three,5,7,9}
Can access elements via index or cursor (arrow)
- either arroyo needs to business relationship for size of elements
- must also pass assortment size, since not available elsewhere
sumOf()
... one-d Arrays in MIPS | 88/114 |
Scanning beyond an array 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 >= 10) pause mul $t0, $s0, $s2# index -> byte get-go lw $a0, vec($t0)# a0 = vec[i] jal impress# impress a0 addi $s0, $s0, one# i++ j loop end_loop:
Assumes the existence of a print()
printf("%d\due north",x)
... 1-d Arrays in MIPS | 89/114 |
Scanning across an array of N
# int vec[10] = {...}; # int *cur, *end = &vec[x]; # for (cur = vec; cur < cease; cur++) # printf("%d\n", *cur); la $s0, vec# cur = &vec[0] la $s1, vec+twoscore# end = &vec[10] loop: bge $s0, $s1, end_loop# if (cur >= end) break lw $a0, ($s0)# a0 = *cur jal print# print a0 addi $s0, $s0, 4# cur++ j loop end_loop:
Assumes the existence of a print()
printf("%d\northward",10)
... one-d Arrays in MIPS | 90/114 |
Arrays that are local to functions are allocated space on the stack
fun: int fun(int x)# prologue { addi $sp, $sp, -4 sw $fp, ($sp) motility $fp, $sp addi $sp, $sp, -4 sw $ra, ($sp) // push a[] onto stack addi $sp, $sp, -40 int a[10]; move $s0, $sp int *s0 = a;# function body ... compute ... // compute using s0# epilogue // to access a[] addi $sp, $sp, forty // pop a[] off stack lw $ra, ($sp) addi $sp, $sp, 4 lw $fp, ($sp) addi $sp, $sp, 4 jr $ra }
2-d arrays could exist represented two ways:
... two-d Arrays in MIPS | 92/114 |
Representations ofint matrix[4][four]
# for strategy (a) matrix: .space 64# for strategy (b) row0: .space 16 row1: .infinite xvi row2: .space 16 row3: .infinite 16 matrix: .discussion row0, row1, row2, row3
At present 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];
... 2-d Arrays in MIPS | 93/114 |
Accessing elements:
... 2-d Arrays in MIPS | 94/114 |
Computing sum of all elements for strategy (a)int matrix[iv][4]
li $s0, 0# sum = 0 li $s1, 4# s1 = iv (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 = 4*4*i + 4*j mul $t1, $s3, $s1# matrix[i][j] is add together $t0, $t0, $t1# done as *(matrix+off) lw $t0, matrix($t0)# t0 = matrix[i][j] add $s0, $s0, $t0# sum += t0 addi $s3, $s3, 1# j++ j loop2 end2: addi $s2, $s2, 1# i++ j loop1 end1:
... ii-d Arrays in MIPS | 95/114 |
Computing sum of all elements for strategy (b)int matrix[4][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 >= four) interruption 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 >= four) break mul $t0, $s3, $s1# off = 4*j add together $t0, $t0, $s4# int *p = &row[j] lw $t0, ($t0)# t0 = *p add $s0, $s0, $t0# sum += t0 addi $s3, $s3, ane# 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 chosen Student typedef struct _student Educatee;
Instances of structures can be created by allocating space:
// sizeof(Educatee) == 56 stu1: Student stu1; .infinite 56 stu2: Student stu2; .infinite 56 stu: .infinite 4 Student *stu;
... Structs in MIPS | 98/114 |
Accessing structure components is by offset, not proper name
li $t0 5012345 sw $t0, stu1+0 # stu1.id = 5012345; li $t0, 3778 sw $t0, stu1+44 # stu1.programme = 3778; la $s1, stu2 # stu = & stu2; li $t0, 3707 sw $t0, 44($s1) # stu->programme = 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 ten)# prologue { addi $sp, $sp, -iv sw $fp, ($sp) move $fp, $sp addi $sp, $sp, -4 sw $ra, ($sp) // button onto stack addi $sp, $sp, -56 Student st; move $t0, $sp Student *t0 = &st;# function body ... compute ... // compute using t0# epilogue // to admission 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 pass whole structures to functions, eastward.g.
# Student stu; ... # // set values in stu struct # showStudent(stu); .data stu: .space 56 .text ... la $t0, stu addi $sp, $sp, -56# push Pupil object onto stack lw $t1, 0($t0)# allocate space and copy all sw $t1, 0($sp)# values in Educatee object lw $t1, 4($t0)# onto stack sw $t1, four($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 |
Tin can also laissez passer a pointer to a struct
# Student stu; # // prepare values in stu struct # changeWAM(&stu, float newWAM); .data stu: .space 56 wam: .infinite 4 .text ... la $a0, stu lw $a1, wam jal changeWAM ...
Conspicuously a more efficient way to laissez passer a big struct
Likewise, required if the part 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 non provide an automatic style of translating
- this is provided by a compiler (e.g.
dcc
- convert
#include
#define
- parse lawmaking to bank check syntactically valid
- manage a list of symbols used in plan
- determine how to stand for information structures
- allocate local variables to registers or stack
- map control structures to MIPS instructions
Maps C→C, performing diverse substitutions
-
#include
- replace
#include
-
"
.h"
.h
-
<
.h>
.h
/usr/include
- replace
-
#define
- replace all occurences of symbol Name by Constant
- e.thousand
#define MAX 5
char array[MAX]
char array[v]
-
#define
(
)
- replace Name
(
)
- e.m.
#define max(x,y) ((ten > y) ? x : y)
a = max(b,c)
a = ((b > c) ? b : c)
- replace Name
... C Pre-processor | 105/114 |
More C pre-processor substitions
Before cpp After cpp ten = v; x = 5; #if 0 x = x + 2; x = 10 + 1; printf("ten=%d\n",ten); #else ten = x * 2; 10 = x + 2;
0 Response to "Opening Mips Code to Read in C"
Postar um comentário