컴퓨터 구조

C코드에서부터 어셈블리 프로그램 연산까지

kidmillionaire1998 2023. 3. 9. 00:32

- 프로세서는 소량의 데이터만을 레지스터에 저장이 가능하지만, 컴퓨터 메모리는 수십억개의 데이터를 저장할 수 있다. 

배열이나 구조체 같은 자료구조가 이러한 메모리에 저장되어있다. 

 

- MIPS의 산술 연산은 레지스터에서만 이루어지기 때문에,

메모리에 저장되어 있는 데이터와 레지스터 간의 데이터를 주고 받는 명령어가 있어야 한다. 

MIPS에서의 이러한 메모리 참조 명령어는  적재 명령어인 load와 저장 명령어인 store가 있다. 

 

명령어 종류 

1. load (lw) 

메모리에서 레지스터로 데이터를 복사해 오는 데이터 전송 명령 

 

- 연산자 이름 (lw) 

- 메모리에서 읽어 온 값을 저장할 레지스터 ($t0) 

- 메모리 접근에 사용할 상수(8)와 레지스터($s3)  

 

lw $t0, 32($s3)

해당 명령어는 쉽게 말해서, 

레지스터 $t0에 메모리에 있는 값을 가져와 저장하는 명령어인데, 

메모리에 있는 값은 $s3레지스터에서부터 32바이트 떨어진 주소의 값에 저장되어있는 값이다. 

 

메모리에서 레지스터로부터 값을 가져와야하는데 메모리 주소는 어디있고 왜 레지스터 주소가 있느냐라고 의아해 할 수 있는데, 

메모리의 주소 값이 특정 레지스터 ($s3)에 기억되어있다고 가정한 것이다. 

 

$s3를 베이스 레지스터라고 하며, 명령이 시작되는 메모리의 주소 번지이며, 

32바이트는 변위(offset)라고 하며, 베이스 레지스터로 부터 얼마만큼 주소가 떨어져있는지를 나타내며,

베이스 레지스터에 변위를 더한 값의 주소에 있는 값에 접근하여 명령어가 실행된다. 

 

2. store (sw)

레지스터에서 메모리로 데이터를 보내는 명령 

 

- 연산자 이름(sw) 

- 저장할 데이터를 갖고 있는 레지스터 ($t0) 

- 배열 원소 선택에 사용할 변위 (48) 

- 베이스 레지스터 ($s3) 

 

sw $t0, 48($s3)

해당 명령어는 $t0레지스터에 있는 값이 메모리 주소로 저장하게 하는 명령어이다. 

 

해당 명령어의 피연산자 역시, 메모리에 관한 주소가 아닌 레지스터 주소가 있는데, 

우리가 저장하고자 하는 값의 메모리 주소가, $s3레지스터 주소에서 48바이트 만큼 떨어져 있는 값과 일치한다고 가정하기 때문이다. 이는 뒤의 예시를 통해 자세히 설명하기로 한다. 

 

 

예시 과정 

이제 하나의 예시를 보면서, 어떻게 C코드가 어셈블리어로 번역이 되며, 이러한 어셈블리어 명령어가 레지스터와 메모리 사이에서 어떠한 역할을 하는지 보자. 

명령어 예시는 앞에서 나온 명령어와 같다. 

 

다음 문장을 어셈블리어 프로그램으로 바꿔보자 

 

A[12] = h + A[8]

A는 100워드 배열이며, 배열 A의 시작 주소 (base address)는 $s3에 기억되어 있다.  

g, h는 각각 레지스터 $s1, $s2에 할당되었다. 

 

=> 이와 같이 배열 A의 시작주소가 $3레지스터에 기억되어있기 때문에, 

해당 베이스 레지스터로부터의 계산을 통해 A[8], A[12]와 같은 메모리 주소 값도 계산하여 접근할 수 있으며, 

이는 앞에서 나온 어셈블리 명령어에서 메모리 주소가 없고 모두 레지스터 주소가 써져 있었던 이유가 된다. 

 

 

1. 

lw $t0, 32($s3)

피연산자 A[8]의 값이 메모리에 있으므로, 해당 값을 레지스터로 옮겨야한다. 

 

배열 A의 시작주소를가 $3에 저장되어있으므로, 베이스 레지스터 주소인 $3에 변위를 더한 주소 값에 있는 값을 가져오면 된다. 

변위는 32인데, 이는 MIPS에서의 워드값이 4바이트이고, 해당 원소가 8만큼 떨어져있기 때문에, 8 x 4 = 32가 변위가 된다. (메모리 A[8] <=> 레지스터 $s3 + 32) 

해당 원소 값을 임시 레지스터인 $t0에 저장한다. 

 

 

2. 

add $t0, $s2, $t0

앞선 lw 연산을 통해, 임시 레지스터인 $t0에 저장되어있는 A[8]의 값과

레지스터 $s2에 저장되어있는 h값을 더한 후, 

다시 임시 레지스터인 $t0에 해당 값을 저장한다.

 

 

3. 

sw $t0, 48($s3)

앞선 add 연산의 값이 저장되어있는 $t0 레지스터에서 A[12] 메모리로 저장되어 있는 값을 저장하기 위해,

A의 시작 주소가 할당된 $s3 베이스 레지스터에 변위 값인 48을 더한 주소 값에 store 연산이 진행된다. 

(메모리 A[12] <=> 레지스터 $s3 + 48) 

 

해당 변위가 48인 이유도 앞에서 마찬가지로, MIPS에서의 워드값이 4이고 배열 시작으로부터 12번째 원소의 주소값에 이를 저장해야하기 때문에, 4 x 12 = 48이 변위가 된다. 

 

이러한 과정들을 거치면서 메모리 A[8]에 있는 값과 변수 h값이 레지스터에서 연산이 되고 난 후, 

다시 메모리 A[12]에 저장된다.