Ezcho

[MIPS] MIPS연산자, 레지스터 정리 본문

Lecture/CSA

[MIPS] MIPS연산자, 레지스터 정리

Ezcho 2022. 11. 4. 22:41

Register

Reg 는 parameter 를 정의하는 역할을 한다. 

 

레지스터는 총 32개가 있으며 0~31 까지의 번호를 매긴다.

또한 레지스터는 word단위이다, 1 word = 4byte 이다.

 

$a0~ $a3: arguments

$v0~ $v1: return Value

$t0 ~ $9: temPvalue 임시 지정된 값이다.

$s0 ~ $s7: savedValue 미리 저장된 값이다.

$gp: 정적 데이터 접근을 위해 사용되는 global pointer 이다. 메모리 내 static data 영역 접근을 위해 사용된다.

$sp: 스택 포인터 이다. 스택메모리 접근을 위해 사용된다.

$fp: frame pointer

$ra: 리턴 포인터 이다.


Memory Layout(구조)

C 코드가 프로그램이 되고, 프로그램이 실행되면서 프로세서가 된다.

메모리 구조는 0~ 증가하는 메모리 구조를 띄고있고 Stack메모리 만이 감소하는 형태를 보인다.

 

Reversed: 우리가 프로그래밍 하면서 주어진 binary 값들을 저장하는 영역이다.

Text: MIPS instructions가 저장되는, 즉 직접적인 코드가 기록되는 영역이다.

Static data: 전역변수를 저장, constant array, String등 우리는 여기 접근을 위해 $gp를 사용한다.

Dynamic data: heap, malloc, new(java)등 동적으로 할당되는 데이터를 저장한다. 

Stack: 메모리의 가장 높은부분에서 내려오면서 할당한다. $sp로 접근한다.

 

Stack overflow문제가 발생할 수 있다.(Dynamic data, Stack)


Instruction Set

인스트럭션은 컴퓨터 연산의 가장 하위 부분이다.

HLL -> ABL -> HW representation 으로 연결된다.

HLL 은 우리가 잘 사용하는 C, C++, Java와 같은 언어이고 High-Leve Language 라고 부른다.

ABL 은 instruction을 텍스트화 한것입니다. Assembly Language 라고 부른다.

Hw representation은 bits(0과 1 로) instruction과 data를 인코딩 하는것을 말한다.

 

이중 ABL을 텍스트화 하고 그중에서도 명령어의 리스트가 Instructinon set이다.


add & sub

add &a, &b, &c 	 //a = b+c
sub &c, &d, &e 	 //c = d-e

 

좌측은 MIPS code ,우측은 C code 이다.


메모리연산 lw & sw

메모리는 1 word (4byte)단위로 구성되기 때문에 우리가 배열에 접근할 때도 메모리 주소를 이용해 주어야 한다.

 

Load Word 예시

//C code
g = h + A[8];
//g는 $s1에 , h는 $s2에, A의 first address는 $s3에 저장된다.


//MIPS code
lw 	$t0, 32($s3)
add	$s1, $s2, $t0

A[8] 이라는 원소에 접근하기 위해서는......

1. 우선 A[0]의 메모리주소 $s3, A[8]을 저장할 temp값 $t0를 준비한다.

2. lw 명령어를 사용해(load word) $s3의 값에서 32bytes shift 한 값을 $t0에 저장한다.

3. 이후 $t0와 $s2를 더해 $s1에 저장한다.

-왜 32인가?.. 메모리의 한 영역은 1word(4byte)로 이루어져있다 그래서 index_8에 접근하기 위해 4x8=32 를 해준것이다.

 

Store Word 예시

//C code
A[12] = h + A[8]
//h는 $s2에, A의 first address는 $s3에 저장된다.

//MIPS code
lw $t0, 32($s3)		//load word
add $t0, $s2, $t0
sw $t0. 48(s3)		//store word

A[8]에 접근하기위해 위와 같은 방식으로 lw 해주었다.

이후 더한값을 새로운 Temp 에 저장 후

48/4 = 12 ,12index에 $t0를 store해주었다.

 

레지스터 와  메모리

1. 레지스터는 메모리보다 더 빠른 접근이 가능하다.
2. 메모리 연산은 로드와 스토어를 필요로 한다, 이 과정에서 더 많은 instructions 이 실행된다.
3. 컴파일러는 변수에 레지스터를 가능한 적게 사용해야한다. 즉, 레지스터 최적화가 중요합니다.(메모리 접근은 불가피하니까..)

 


논리연산자

C 에서 AND, OR, NOT 은 MIPS로 어떻게 표현할까?

$t1 = 00...00 0000 0011

$t2 = 00...00 0000 0101

이라고 가정해보자.

MIPS 에서의 and연산은 아래와 같이 표현한다.

and $t0, $t1, $t2
or  $t0, $t1, $t2

 

항상 bits단위 연산을 하기 때문에

0011 & 0101 = 0001 이다.

따라서 $t0 == 0001 인 것이다.

 

Not 연산자

not 은 아래와 같이 표현한다.

nor $t0, $t1, $zero

 

Not 은 비트를 뒤집을 때 많이 사용한다 1's complement로 생각하면 편할 것 같다.

00..00 0000 1110 

11..11 1111 0001 

이렇게 뒤집힌다.


Shift 연산자

bits를 옮긴다고 생각하자. sll과 slr이 존재한다.

 

sll: Shift left logical의 경우 값이 왼쪽으로 이동하고 0비트로 채워진다.
slr: Shift right locical의 경우 값이 오른쪽으로 이동하고 0비트를 채워진다.

 

$t0 = 00/.../00 0111 일 때 

sll $t1 $t0 2

위와 같은 코드를 수행하면 

$t1 = 00/.../01 1100 이 된다.

왼쪽으로 2비트 옮긴것이다. 

 

slr은 그 반대이니까 잘 생각해보자.


Conditional operations (조건연산자)

덧셈 뺄셈은 대충 알겠고, 그럼 If문이나 while 문은 어떻게 구성될까?

if문을 알기위해 우선 조건문을 구성하는 조건 연산자가 존재한다.

 

1. 동등연산자

//C code 
if(a == b)
	L1;

//MIPS code
beq rs, rt, L1

//C code
if(a != b)
	L2;

//MIPS code
bne rs, rt, L1

틀린지 다른지 비교하는 연산자이다. 참일경우 L1으로 Jump한다.

beq(equal): 같을경우 L1으로 이동한다.

bne(not equal): 다를경우 L1으로 이동한다.

아래와 같이 동등연산자를 정의할 수 있다.

그럼 비교연산자는 어떻게 정의할까?

 

2. 비교연산자.

//C Code
if (rs < rt) rd = 1; 
else rd = 0;

//MIPS
slt rd, rs, rt	//rs와 rt를 비교해서 rd에 넣는데 참이면 1 거짓이면 0이다. rs<rt

//C Code
if (rs < constant) rt = 1; 
else rt = 0;

//MIPS
slti rt, rs, constant	//rs와 상수를 비교해서 rt에 넣는데 참이면 1 거짓이면 0이다.

//slt와 bne, beq를 함께 사용할 수 있다.

slt $t0, $s1, $s2 	//if ($s1 < $s2), t0는 1또는 0이 할당된다.
bne $t0, $zero, L   	// branch to L

비교연산자는 slt라는 연산자를 사용한다.

slt(set on less than)적은것을 찾는것이다. 

slt $t0, $s1, $s2 에서, s1<s2이면 참. 1을 $t0에 저장한다.

 

즉, slt $t0, $s1, $s2  => if($s1<$s2) $t0 = 1; else $t0 = 0; 이다.

이후 bne $t0,  $zero, L 해서 t0가 참이면 0과 다르니까 L로 이동하여 if문 내부 진입이 가능하다.

 


lb, lbu, sb, lh, lhu, sh 

기존의 lw, sw 는 offset에서 워드단위 연산을 한다.

근데 얘네는 word단위로 긁어오는게 아니라 byte 단위로 긁어온다.

lb: 1바이트를 가져와서 32bit(word)에 저장한다.

그럼 word의 구성은 상위24bits+가져온8bits(1byte),  상위 24bits가 MSB를 따라서 저장

즉 가져온 byte 가 1111 0001 일때 word는 MSB(최 상위 bit)값에 따라 111...111 1111 0001 이 된다.

 

lbu: 1바이트 긁어와서 word에 저장한다. 대신 unsigned leastBits를 0으로 한다. 1111 0001 일때,

상위24bits+가져온8bits 000...00 1111 0001 이다.


sb: 32bits 레지스터 값을 offset 에 1바이트 만큼 저장한다.

lh, lhu, sh 는 위와같다. 대신 half byte, 즉 4bits단위로 위 작업을 처리한다.

Comments