본문 바로가기

IT개발/컴퓨터구조

컴퓨터 구조에 대한 설명(2-2) / LOAD & STORE 명령어 디자인

자, 오늘은 LOAD&STORE 명령어를 디자인하고, Direct와 InDirect 모드에 대해 알아보자. ^^

 

※ LOAD & STORE 명령어 디자인

 

우리는 어제 사칙연산과 관련된 명령어를 다자인하면서 명령어 포맷에 대한 이해에 포커스를 맞췄다.

이번에는 메인 메모리로부터 데이터를 읽어 오거나(LOAD) 저장(STORE)하는 기능과 관련된 명령어를 디자인하면서

레지스터의 필요성에 포커스를 맞추려 한다.

 

- LOAD & STORE 명령어의 필요성

 

앞서 명령어를 디자인하는 과정에서 "(사칙)연산의 결과를 레지스터에만 저장할 수 있도록 하겠다." 라는 제약사항을 두었다.

모든 피연산자에서 메인메모리의 주소값이 올수 없다는 제약과 동일한 의미다.

 

때문에 다음과 같은 연산은 할 수가 없다.

 

int a = 10;   // 0x10번지 할당

int b = 20;   // 0x20번지 할당

int c = 0;    // 0x30번지 할당

c =  a + b;

 

마지막 네번째 줄을 실행하기 위해서는 다음과 같은 문장을 명령어로 구성해야 한다.

 

"0x10번지(a)에 저장된 값과 0x20번지(b)에 저장된 값을 더해서 0x30번지(c)에 저장해라"

 

하지만, 잘 생각해보자. 아직 우리는 메인메모리의 주소정보를 사칙연산의 피연산자로 올 수 있도록 명령어 구조를 설계하지 않았다.

때문에 위와 같은 명령어는 만들지 못한다. (이것이 범용적으로 사용되는 RISC의 특징이다.)

 

따라서 메인메모리에 저장된 데이터를 레지스터로 일단 옮긴 후, 그 다음에 덧셈을 진행해야 한다.

 

즉, 레지스터 - 메인 메모리 사이에서 데이터 전송을 위한 명령어가 필요하다.

 

-------------------------------------

Register Set  ---------> 메인 메모리

                    (STORE)

                   <--------

                     (LOAD)

-------------------------------------

 

그럼, 다음과 같이 명령어를 디자인 해 보자.

 

-----------------------------------------------------

예약(2)   LOAD(3)  destination(3)   source(8)

              110            011             00000111 

-----------------------------------------------------

 

- destination   : 데이터를 저장한 레지스터 정보

- source         : 데이터를 읽어올 메모리 주소 정보

 

이런 구조면 다음 명령어의 뜻은 이렇다.

 

"LOAD r3, 0x07     -> 0x07번지에 존재하는 데이터를 레지스터 r3에 저장하라"

 

참고) 컨트롤 유닛은 명령어가 LOAD임을 판단하고 나면, 그 뒤에 오는 피연산자는 세 개가 아닌 두개임을 알고,

         그에 맞게 정보를 추출하는(해석하는)과정을 거칠 것이다. 명령어 형태에 따라서 컨트롤 유닛이 디자인된다는 것이

         보다 명확히 이해되지 않는가??

 

 

 

STORE 명령어도 아래와 같이 디자인 해보자.

-----------------------------------------------------

예약(2)   STORE(3)   source(3)    destination(8)

              110            010             00001000

-----------------------------------------------------

 

이런 구조면 다음 명령어의 뜻은 이렇다.

 

"STORE r2, 0x08     ->  레지스터 r2에 존재하는 데이터를 메인 메모리의 0x80번지에 저장하라"

 

이제 앞에서 제시했던 예제를 실행할 수 있도록 명령어를 구성해 보자~.

 

int a = 10;   // 0x10번지 할당

int b = 20;   // 0x20번지 할당

int c = 0;    // 0x30번지 할당

c =  a + b;

 

--------------------------

--------------------------

                 10                        0x10

--------------------------

--------------------------

                 20                        0x20

--------------------------

--------------------------

                 30                        0x30

--------------------------

--------------------------

 

c =  a + b; 는 지금까지 디자인해 온 명령어들로 구성하면 다음과 같다.

 

-------------------------------------------------------------------

LOAD   r1,   0x10    // 0x10번지에 저장된 데이터를 r1로 이동

LOAD   r2,   0x20    // 0x20번지에 저장된 데이터를 r2로 이동

ADD     r3, r1,  r2    // r1, r2에 저장된 값을 더해서 r3에 결과를 저장

STORE r3,   0x30    // r3에 저장된 값을 0x30번지에 저장

-------------------------------------------------------------------

 

 

지금 우리가 골치를 썩고있는 이유는? -> 덧셈의 피연산자는 숫자이거나 레지스터가 되어야 한다고 정의했기 때문이다.

그렇다면 해결책은?

 

피연산자가 레지스터가 되게끔 하기 위해서 메모리에 저장된 값을 레지스터에 옮겨다 놓은 후

덧셈 연산을 하면된다. 이것이 우리가 만든 명령어 구성의 주요내용이다.

 

명령어를 잘 보면 결과적으로 c = a + b;  연산이 수행된 것을 알수 있을것이다.

 

자 마지막으로 한번 더 정리해보자.

 

그림그리기가 까다로우니 상상해보자.

 

컨트롤 유닛은 명령어를 해석한다.

메모리에서 나와 입출력 버스를 타고, 레지스터에 저장된다.

ALU에 의해 연산이 진행되고, 그 결과값은 다시 입출력 버스를 타고 메모리에 STORE 된다.  자 이해가 되는가?^^