leehyeon-dv 님의 블로그
2.10 MIPS Addressing for 32-Bit Immediates and Addresses 본문
2.10 MIPS Addressing for 32-Bit Immediates and Addresses
leehyeon-dv 2024. 11. 17. 16:10🔑Table of Contents
- 32-bit Constants - 32비트 상수, lui사용
- Branch Addressing - 분기대상 주소계산
- Jump Addressing - 32비트의 jump주소
- Target Addressing Example - MIPS계산(분기 명령어에서 오프셋사용)
- Branching Far Away - 이동할 주소가 먼경우 j사용
- Addressing Memory Summary -
- 궁금한점
📌32-bit Constants
- 대부분의 상수는 작은 크기임
- 16비트 immediate로도 충분하다
- 가끔 32-bit 상수가 쓰임
- MIPS에서는 16비트상수만 한번에 로드가능해서, 32비트 상수를 다루기위해 상위/하위 16비트를 따로 로드한다
- lui rt, constant
- 16비트 상수를 레지스터(rt)의 상위 16비트에 복사한다
- 하위 16비트는 모두 0으로 채워진다
※MIPS는 lui, ori 명령어를 사용해 32비트 상수를 로드한다
📝예시
lui $s0, 61
0000 0000 0111 1101 0000 0000 0000 0000
ori $s0, $s0, 2304
0000 0000 0111 1101 0000 1001 0000 0000
📌Branch Addressing
- branch instructions에 사용되는
- opcode, 2registers, target address
- 대부분의 branch target(분기대상, 분기 조건에 따라 이동하게 되는 곳)은 branch(지금루틴) 근처에 존재한다
- 앞 혹은 뒤로
- PC-relative addressing (pc가 가리키는 주소를 활용)
- target address = PC + offset*4
- MIPS에서 PC는 어떤 루틴에 들어가면, 다음에 실행할 명령의 주소값을 가리키게 되어있다 (즉, 이미 이번 분기에 진입할 때 4만큼 증가했었음 그러므로 타겟 주소를 계산할 때 고려해야한다)
📌Jump Addressing
- 점프(j, jal) 대상은 어디든 가능하다 (branch 타겟과 달리 멀리로도 가는편)
- MIPS에서 j와 jal은 j-type 명령어로 다음과 같은 구조를 가집니
- (Pseudo) Direct Jump Addressing
- PC-relative branching과 다르게 절대 주소를 사용하는 방식
- (Pseudo) Direct Jump Addressing = 유사 직접 주소 지정 방식(완전 절대주소를 사용하는 것은 아니지만 PC의 상위 4비트와 명령어의 주소 26비트를 결합해 절대주소처럼 동작해 이렇게 부른다)
- MIPS명령어가 4바이트 단위로 정렬되기 때문에 26비트를 2비트 shift(x4)해서 PC의 상위 4비트와 28비트 주소를 결합해 32비트의 절대주소를 만듭니다
📌Target Addressing Example
- 2.7장의 Compiling Loop Statememts를 다시 생각해보자 (Loop의 메모리 주소는 80000이라고 가정한다)
- C code :
while (save[i] == k) i += 1;
//i,k,save -> $s3, $s5, $s6
- 컴파일된 MIPS code:
Loop : sll $t1, $s3, 2 #i 인텍스만큰의 주소(4 byte)를 위해 4곱하기
add $t1, $t1, $s6 #offset(위에서 구해둔 i*4)에 시작 주소를 더하면 save[i]주소
lw $t0, 0($t1)
bne $t0, $s5, Exit
addi $s3, $s3, 1
j Loop
Exit: ...
🔦자세한 계산과정 아래참조
80000 | 0 | 0 | 19 | 9 | 4 | 0 |
80004 | 0 | 9 | 22 | 9 | 0 | 32 |
80008 | 35 | 9 | 8 | 0 | ||
80012 | 5 | 8 | 21 | 2 | ||
80016 | 8 | 19 | 19 | 1 | ||
80020 | 2 | 20000 | ||||
80024 |
📌 Branching Far Away
분기 대상 주소가 멀어서 16bit의 offset으로도 표현불가능하다면, 어셈블러는 코드를 다시 작성하게된다
예)
beq $s0, $s1, L1이 아닌
👇
beq $s0, $s1, L2
j L1
L2: ...
*jump addressing 방식은 PC의 상위 4비트를 유지하고 나머지 28비트를 사용해 더 먼 주소로 이동가능하
📌Addressing Memory Summary
1. 즉시 주소 지정 (상수값 더하거나 빠르게 초기화할때 사용)
2. 레지스터 주소 지정방식 (간단한 산술연산, 논리연산)
- 연산은 레지스터 간에서만 수행, 메모리 접근이없다
3. 기준주소 지정방식
- 기준 주소로 사용하는 레지스터와 오프셋을 더해 메모리 주소를 계산한다
4. PC 상대주소 지정방식
- 현재 pc값을 기준으로 오프셋을 더해 분기할 주소를 계산한다
5. 유사 직접주소 지정방식
- jump 명령어에서 사용되며, 명령어에 포함된 주소 필드를 사용해 분기할 주소를 계산한다
📍?<궁금한점>📍
🔎lui란?
Load Upper Immediate : 상위 16비트에 즉시값을 로드하고 하위비트에 0으로 채우는 명령
🔎lb와 lui의 차이
lb = 메모리에서 8/16비트 데이터를 읽어와서 부호 확장한다 (바이트 데이터를 메모리에서 읽어올때 사용)
lui = 즉시값(immediate Value)을 상위 16비트에 로드하고, 하위 16비트를 0으로 설정한다
🔎Pseudo란?
라틴어에서 유래된 단어로, "가짜의" 또는 "유사한"이라는 뜻( 즉, 실제는 아니지만 비슷하게 동작한다는 것)
🔎왜 주소에서 데이터를 로드해야할까?($t1으로 바로 사용할수없나)
MIPS 어셈블리에서는 레지서터와 메모리가 분리되어있다 (레지스터는 빠르고 메모리는 느림)
따라서, 데이터 사용 시 메모리에서 바로 연산할 수 없고, 반드시 메모리에서 데이터를 레지스터로 로드한 후에 연산해야한다
MIPS의 설계철학
- 연산은 반드시 레지스터에서 만 수행
- MIPS 모든 연산 명령어(add, sub, mul등)는 레지스터간의 연산만 가능하다
- 메모리에 있는 데이터를 직접 연산할 수 없다
- 메모리 접근은 lw(load word)와 sw(store word)통해서만 가능
- 메모리에서 데이터읽기 : lw
- 메모리에 데이터 저장: sw
사용예시 :
main:
la $t1, array # $t1에 배열의 시작 주소 로드
lw $t2, 0($t1) # 배열의 첫 번째 요소 (10)를 $t2에 로드
addi $t2, $t2, 5 # $t2 = $t2 + 5
sw $t2, 0($t1)
🔎계산 자세히
80000 | 0 | 0 | 19 | 9 | 4 | 0 |
80004 | 0 | 9 | 22 | 9 | 0 | 32 |
80008 | 35 | 9 | 8 | 0 | ||
80012 | 5 | 8 | 21 | 2 | ||
80016 | 8 | 19 | 19 | 1 | ||
80020 | 2 | 20000 | ||||
80024 |
rs : 첫번째 소스 레지스터. 주로 연산에 사용될 입력값이 들어있음
rt : 두번째 소스 레지스터 or 대상 레지스터. 연산에 사용되거나 값을 저장할 목적지
rd : 결과를 저장할 레지스터. 연산의 결과값 들어있다
target address 계산공식 : PC + 4 + (offset * 4)
- PC + 4 = 다음명령어의 주소 (현재 명령어 주소 + 4바이트)
- offset = 몇 개의 명령어를 건너뛸지 나타냄
'컴퓨터구조 및 설계 > 2장. language of the computer' 카테고리의 다른 글
2.9 Communicating with People (0) | 2024.11.16 |
---|---|
2.8 Supporting Procedures in Computer Hardware (0) | 2024.11.16 |
2.7 Instructions for Making Desicions (0) | 2024.11.16 |