본문 바로가기

컴퓨터 구조론( MIPS )

명령어 : 컴퓨터 언어 1

728x90
반응형
반응형

안녕하세요. WH입니다.

 

적은 분들이지만, 제 글을 읽어주시는 분들이 생겨났네요.

정기적으로 찾아오시는 분들은 아니지만, 그 적은 분들을 위해서라도

열심히 꾸준히 써보겠습니다.

 

오늘은 명령어(instruction)와 명령어 집합(instruction set)에 대해 알아보려고 합니다.

컴퓨터에게 일을 시키려면 하드웨어가 알아듣게 말해야 겠죠?

그 언어를 기계어라고 하며, 기계어 역시 언어는 단어와 문장으로 이뤄질텐데

단어는 instruction에 문장은 instruction set에 해당합니다.

자 천천히 시작해보겠습니다.

컴퓨터 구조론을 왜 알아야 할까..

그 이유는 전 글을 참조해주시길 바랍니다

2022.01.31 - [컴퓨터 구조론( MIPS )] - 컴퓨터 구조론-기초 1( feat. 왜 배워야 할까 )

하드웨어 연산

하드웨어 연산이 뭐냐, 하드웨어는 산술 연산을 할 수 있어야하는 합니다. MIPS를 토대로 알려드리도록 할게요. 왜냐하면, 사실 다른 언어로 다뤄도 되지만, 대게 교재들에서 MIPS를 택했고 저도 MIPS로 된 교재를 봤었기 때문이랄까요? ARM을 쓰셔도 하나만 제대로 알고 있다면 금방하기 때문에, MIPS로 하도록 할게요.

 

특징

MIPS 산술 명령어는 한 종류의 여산만 지시하며 항상 변수 세개를 갖는 형식을 엄격히 지킨다.

 

하고 싶은것

a + b + c + d + e 이 연산이 하고 싶어요. 그럼 위에서 설명한 특징에 의거해서 다음과 같이 써야합니다.

 

add a, b, c ( b와 c를 더해서 a에 넣어라 )

add a, a, d ( a와 d를 더해서 a에 넣어라 )

add a, a, e ( a와 e를 더해서 a에 넣어라 )

 

와 이게 뭔데요? 컴파일러가 생성한 MIPS 코드입니다ㅎㅎMIPS 코드요?? 아직 안배웠는데요?? 특징을 설명하기 위해 적어놓은 예시이니까요. 괄호 안에 의미만 가져가면 됩니다.

 

Q ) a, b, c, d, e 다섯 개의 변수를 사용할 때, a= b + c, d = a - e  에 해당하는 C 컴파일러가 생성하는 MIPS 코드는?

 

A ) 

add a, b, c

sub d, a, e

여기까지 잘 하셨을까요? 그렇다면 괄호 안의 의미를 잘 이해했다고 보실 수 있겠네요.

 

그럼 조금 어렵게 갑니다.

 

Q ) a = ( b + c ) + ( d + e ) 에 해당하는 MIPS 코드는?

 

A )

add t0, b, c

add t1, d, e

add a, t0, t1

 

이걸 어떻게 알아요? t0,t1 안 알려줬잖아요. 맞아요. 다만 이번 예시에서 보여드리고 싶었던 것은, 사용하는 변수에는 값을 업데이트(?) 하는 변수와 임시 변수로 나눠짐을 알려드리고 싶었습니다

 

피연산자

산술 명령어( add, sub 와 같은 )의 피연산자에는 제약이 존재합니다. 첫 번째, 피연산자는 레지스터라고 하는 하드웨어로 직접 구현된 특수 위치 몇 곳에 있는 것만을 사용 할 수 있는데요. MIPS에서는 레지스터의 크기가 32비트입니다. 즉 32비트가 한 번에 처리되는 일이 매우 많기 때문에 이 묶음을 워드( word ) 라고 한답니다.

 

어 그럼 잠깐만? 레지스터가 변수에요? 네 맞습니다. 다만 차이가 있는데요. 프로그램 언어 (c , java , python )과 가장 큰 차이는 개수가 한정되어 있다( 하드웨어로 직접 구성되어 있기 때문 )는 겁니다. 

 

또 다른 하나의 제약은 산술 명령어의 각 피연산자는 32개의 32 비트 레지스터 중 하나여야 한다는 겁니다. 이것은 하드웨어 설계 원칙과 연관이 있다라는 점만 알고 가시면 될 것 같아요. 레지스터가 뭐하는 건데요? 차차 설명해드리겠습니다. 다만 MIPS에서 레지스터를 나타내기 위한 관례는 달러 기호 뒤에 두 글자가 따라 나오는 이름을 사용한다는 겁니다. 위에 있던 예시에서 언어 프로그램( C나 java )에 해당 하는 변수는 $s0, $s1 등을 사용하고 명령어 프로그램에 사용하기 위한 임시 레지스터는 $t0, $t1를 사용하도록 할게요.

 

Q ) a = ( b + c ) + ( d + e ) 에 해당하는 MIPS 코드는?

 

A )

add t0, s1, s2

add t1, s3, s4

add s0, t0, t1

이런 식으로 약속을 해서 하겠다는 거에요ㅎㅎ 이해가 되실까요?

 

메모리 피연산자

단순히 하나의 값만 기억하는 단순 변수도 있고, 구조체나 배열 같은 복잡한 자료구조 역시 존재하는 데요. 이런 복잡한 자료구조에는 레지스터 개수보다 많은 데이터 원소가 있을 수 있겠죠? 때문에 이런 복잡한 자료구조는 메모리에 저장하게 됩니다. 그런데, 산술 연산은 레지스터에서 실행되죠? 그럼 메모리의 데이터는 어떻게 레지스터로 가져오죠? 그래서 데이터를 주고 받기 위한 명령어가 존재합니다. 이런 명령어를 데이터 전송 명령어 ( data transfer instruction )이라고 합니다. 즉 메모리에 기억된 데이터 워드에 접근 하려면 해당 데이터의 인덱스 역할을 하는 메모리 주소를 ( memory address )를 지정해야 합니다. 한마디로 메모리는 주소가 인덱스 역할을 하는 하나의 큰 배열이라고 생각하면 될 것 같아요. 

 

메모리 -> 데이터 복사 : load ( 적재 )

  - load 명령은 연산자 이름과 메모리에서 읽어 온 값을 저장할 레지스터, 메모리 접근에 사용할 상수와 레지스터로 구성되는데요 MIPS 에서는 lw( load word )를 사용합니다.

레지스터 -> 메모리 : store ( 저장 )

  - store 명령은 load 와 같은 형식이며 sw( store word )를 사용한답니다.

 

 

예시 : a는 $s1에 저장되어 있고 배열 A의 시작 주소가 $s3에 저장되었다고 가정할 때

A[ 10 ] = a + A[ 8 ]을 컴파일 과정을 보여드리겠습니다.

 

1. A[8]의 내용 가져오기

lw $t0, 32($s3) ( $3을 베이스 레지스터라 합니다. 8이 아니라 왜 32 인가? 워드 주소는 4 바이트 주소 중 하나를 사용함으로 4 ( 바이트 ) * 8 ( 8번째 값 ) = 32 가 되는 겁니다. 연속된 워드의 주소는 4씩 차이가 나며,  워드의 시작 주소는 4의 배수임을 알 수 있겠지요 )

 

2. 해당 내용 더하기

add $t0, $s1, $t0

 

3. 베이스 레지스터( $s3 )를 사용하여 저장하기

sw $t0, 40($s3)

 

용어 하나만 정리하고 갈게요. 자주 사용되는 변수는 가능한 많은 레지스터에 넣고 나머지 변수를 메모리에 저장했다가 필요할 때 꺼내 쓰는 데, 자주 사용하지 않는 변수를 메모리에 넣는 일을 레지스터 스필링이라고 한답니다.

728x90
반응형