[Computer Architecture] MIPS assembly programming(2)
Addressing Modes
How do we address the operands?(In MIPS)
- Register Only
- Immediate
- Base Addressing
- PC-Relative
- Pseudo Direct
Register Only
- Operands found in registers
- Example: add $s0, $t2, $t3
- Example: sub $t8, $s1, $0
- Immediate
- 16-bit immediate used as an operand
- Example:addi $s4, $t5, -73
- Example: ori $t3, $t7 0xFF
- 16-bit immediate used as an operand
Base Addressing
-
Address of operand is: base address + sign-extended immediate
- Example: lw $s4, 72($0)
- $0은 data memory의 address
- address = $0 + 72
- Example: sw $t2, -25($t1)
- address = $t1 - 25
PC-Relative Addressing
-
Program memory
-
우리는 label을 그냥 사용하면 되지만 예를 들어
else:
로 가야할 때 PC에서 얼마만큼 떨어진 곳으로 가야 하는 지를 알아야 한다. -
Program memory address
0x10 beq $t0, $0, else
0x14 addi $v0, $0, 1
0x18 addi $sp, $sp, i
0x1C jr $ra
0x20 else: addi $a0, $a0, -1
0x24 jal factorial
위와 같은 경우에 beq에서 $t0와 $0가 같으면 else로 jump하는데 이 때 4칸을 뛰어야 한다.
그런데 PC에서는 미리 다음 주소로 이동하기 위해 값을 다음으로 지정해 놓고 있기 때문에 3칸만 뛰어도 되는 것이다.
BTA(Branch Target Address) = (PC + 4) + (Imm«2)
- 4를 더한 것은 PC가 다음으로 이동하기 위해 미리 한 칸 가 있는 것이고 imm(3)에 left shift를 2번하면 x4의 효과가 있기 때문에 한 것이다.(따라서 (PC+4) + 12)
Pseudo-direct Addressing
0x0040005C jal sum
...
0x004000A0 sum: add $v0, $a0, $a1
-
26bit밖에 없는데 32bit를 만들어야 하는 경우
-
JTA(Jump Target Address)
-
맨 뒤에 2 비트를 0으로 채움
-
맨 앞의 4bit(한 바이트)는 PC에서 그대로 가져온다.
-
J타입은 원래 어디로 jump 할 지를 바로 정해주는 direct addressing인데 여기서 32bit를 만들기 위해 앞의 4bit는 PC에서 왔기 때문에 Pseudo-direct addressing이라고 한다.
-
How to Compile & Run a Program
What is Stored in Memory?
-
Instructions (also called text)
-
Data
-
Global/static: allocated before program begins
-
Dynamic: allocated within program
-
-
How big is memory?
- At most 232 = 4 gigabytes (4 GB)
- From address 0x00000000 to 0xFFFFFFFF
MIPS Memory Map
- Text segment: 256MB
- Global data segment: 64 KB, accessed by $gp
- $gp does not change during execution (unlike $sp)
- Reserved: I/O 영역(위) 과 OS(아래)가 사용하는 공간
Example RISC-V Memory Map
address는 다르지만 기본적인 구조는 매우 유사함(MIPS와)
Example Program: C Code
int f, g, y; // global variables
int main(void)
{
f = 2;
g = 3;
y = sum(f, g);
return y;
}
int sum(int a, int b) {
return (a + b);
}
Example Program: compiling
.data
f:
g:
y:
.text
main:
addi $sp, $sp, -4 # stack frame
sw $ra, 0($sp) # store $ra
addi $a0, $0, 2 # $a0 = 2
sw $a0, f # f = 2 ; label을 그냥 그대로 써도 됨
addi $a1, $0, 3 # $a1 = 3
sw $a1, g # g = 3
jal sum # call sum
sw $v0, y # y = sum()
lw $ra, 0($sp) # restore $ra
addi $sp, $sp, 4 # restore $sp
jr $ra # return to OS
sum:
add $v0, $a0, $a1 # $v0 = a + b
jr $ra # return
Example Program: Symbol Table
f,g,y : data memory
main, sum: program memory(text memory)
Example Program: linking (Executable)
sw $a0, 0x8000($gp)
가 의미하는 것:
global pointer는 memory의 global data 공간을 가리키고 있는데 이 공간에서 0x8000만큼 떨어진 곳으로 store하라는 것인데 0x8000은 맨 앞의 8이 이진수로 ‘1000’을 나타내고 이는 -8이기 때문에 -8000을 의미하는 것이기 때문에 0x10008000에 있던 $gp 가 0x10000000으로 가서 f를 저장하고 g를 저장할 때는 0x8004만큼 움직이면 -7996을 의미하는 것이기 때문에 f를 저장한 곳보다 4만큼 위의 공간에 저장하는 것이다.
Example Program: loading (in memory)
- OS loads the program from storage
- OS sets $gp=0x10008000, and $sp= 0x7ffffffc, and jump to the beginning of the program (jal 0x00400000).
- Reserved area: memory-mapped I/O, interrupt vector
Lab 1: MIPS Assembly Programming
MIPS을 해보는 것처럼 실행할 수 있는 runtime simulator인 MARS로 구동시킬 것임
Odds & Ends (Misc.)
- Pseudo-instructions
- Not a part of ISA, but commonly used
- assembler가 진짜 instruction으로 바꿔줌
- Exceptions(interrupt)
- Unscheduled function call(예기치 않은 function call)
- Exception handler is at 0x80000180
- Signed and unsigned instructions
- Floating-point instructions
Pseudoinstruction
- li $s0, 0x1234AA77 (load immediate) : 32bit를 immediate로 쓸 때에는 두 과정으로 나누어 준다.
- lui / ori
Exception
- Unscheduled function call to exception handler
- Caused by:
- Hardware, also called an interrupt, e.g., keyboard
- Software, also called traps, e.g., undefined instruction
- When exception occurs, the processor:
- Records the cause of the exception (원인을 저장)
- Jumps to exception handler (at instruction address 0x80000180)
- Returns to program
Exception Registers
-
Not part of register clk
-
Cause: Records cause of exception
-
EPC (Exception PC): Records PC where exception occurred
- exception handler에서 다 처리한 후 다시 돌아올 자리
-
-
EPC and Cause: part of Coprocessor 0
-
Move from Coprocessor 0
- mfc0 $t0, EPC
- Moves contents of EPC into $t0
Exception Causes
Exception Flow
- Processor saves cause and exception PC in Cause and EPC
- Processor jumps to exception handler (0x80000180)
- Exception handler:
- Saves registers on stack
- 내가 사용할 register 저장(어떤 register가 문제인지 모르기 때문에)
- Reads Cause register
mfc0 $k0, Cause
- Handles exception
- Restores registers
- Returns to program
- mfc0 $k0, EPC
//$k0, $k1 reserved by OS jr $k0
- jr $k0
- Saves registers on stack
Exception Example
- Example: read one input from a keyborad (assum interrupt is enabled)
$k0-$k1 : OS temporaries
Signed & Unsigned Instructions
- Addition and subtraction
- Multiplication and division
- Set less than
Addition & Subtraction
- Signed: add, addi, sub
- Same operation as unsigned versions
- But processor takes exception on overflow
- Unsigned: addu, addiu, subu
- Doesn’t take exception on overflow
Note: addiu sign-extends the immediate (two versions are identical except exception is triggered.
Mul
- Signed: mult, div
- Unsigned: multu, divu
ex) 0xFFFF_FFFF * 0xFFFF_FFFF
=> 0xFFFFFFFE00000001 (unsigned)
=> 0x0000000000000001 (signed)
Set Less Than
- Signed: slt, slti
- Unsigned: sltu, sltiu
Note: sltiu sign-extends the immediate before comparing it to the register.
Loads
- Signed:
- Sign-extends to create 32-bit value to load into register
- Load halfword: lh
- Load byte: lb
- Unsigned:
- Zero-extends to create 32-bit value
- Load halfword unsigned: lhu
- Load byte: lbu
Floating-Point Coprocessor(or Accelerator)
별로 중요하지 않음, 내부가 중요함
Example design
Floating-Point Instructions
- Floating-point coprocessor(Coprocessor 1)
- 32 32-bit floating-pointer registers($f0-$f31)
- Double-precision values held in two floating point registers
- e.g., $f0 and $f1,$f2 and $f3, etc.
- Double-precision floating point registers: $f0, $f2, $f4, etc.
F-Type Instruction Format
- Opcode = 17 (0100012)
- Single-precision:
- cop = 16 (0100002)
- add.s , sub.s, div.s, neg.s, abs.s, etc.
- Double-precision:
- cop = 17 (0100012)
- add.d, sub.d, div.d, neg.d, abs.d, etc.
Floating-Point Branches
- Set/clear condition flag: fpcond
- Equality: c.seq.s, c.seq.d
- Less than: c.lt.s, c.lt.d
- Less than or equal: c.le.s, c.le.d
- Conditional branch
- bclf: branches if fpcond is FALSE
- bclt: branches if fpcond is TRUE
- Loads and stores
- lwc1: lwc1 $ft1, 42($s1) ; load coprocessor 1
- swc1: swc1 $fs2, 17($sp)
ARM & MIPS instruction set
난이도: MIPS < RISC-V < ARM
ARM은 복잡, MIPS은 비교적 쉬움, 이 사이에 있는 것이 RISC-V
Q)
A)handling하는 방식이 processor마다 조금씩 다를 수 있다.
Q)floating point /single, double
A)
범위가 틀린 것
single precision
- 32 bit
- float a;
double precision
- 64bit
- double b;
Q)unsigned에서는 overflow가 일어나지 않는데 이를 어떻게 처리하는 것인가?
A)있을 수 있으나 무시하여 발생하지 않도록 설계하는 것이다.
댓글남기기