컴퓨터구조 전공수업 ch02

2023. 3. 26. 01:20컴퓨터구조

728x90

2.1 MIPS Instructions Set 

MIPS(Microprocessor without Interlocked Pipeline Stages)란 MIPS Technologies에서 개발한 RISC 계열의 명령어 집합 체계이다.

 

2.2 Arithmetic Operations(산술 연산)

add a, b, c   // b+c를 a에 대입해라

sub a, b, c   // b-c를 a에 대입해라

 

2.3 Register

  • MIPS는 32개의 레지스터로 구성 (0~31까지 번호가 매겨져 있음)
  • 각 레지스터는 32비트의 데이터를 가질 수 있다.
    -> word라고 함 (32비트=4바이트)
  • 레지스터에서 데이터에 접근하는 게 메모리에 접근하는 것보다 훨씬 빠름.
  • $t0~$t9 : temporary values (임시로 값을 보관할 레지스터)
  • $s0~$s7 : saved variables (값을 저장할 레지스터)
  • 상수 0은 레지스터 $zero를 이용한다. (이 레지스터에 다른 값은 저장불가)
MIPS에는 move 명령어가 없기 때문에 레지스터 사이에 값을 옮기고 싶다면?
-> add $t2, $s1, $zero

 

Memory

  • 메모리 주소는 8비트=1바이트로 식별된다.
  • Word: 4바이트 
  • Big Endian: 낮은 주소부터 높은 주소 순으로 최상위비트부터 차례로 메모리에 저장하는 방법
    Little Endian: 빅인디언 반대 방식 (높은 주소부터 터 저장)
예) 주소가 0x123456이라면 Big Endian: 12        Little Endian: 56
                                                                 34                             34
                                                                 56                             12                                 

 

Memory Operand

C code:
A[12] = h + A[8];

h in $s2, base address of A in $s3라면 

-> MIPS code로는? 

lw $t0, 32($s3)  //load word
/* 인덱스 8의 위치는 배열 A가 저장된 주소로부터 8*4=32바이트만큼 떨어져있음
왜 4를 곱하느냐? 메모리의 기본 단위인 Word가 4바이트이므로 */
add $t0, $s2, $t0   // $t0레지스터 재활용 
sw $t0, 48($s3)  //store word
  • lw   a,  b    // b로부터 데이터를 가져와서  a에 저장
  • sw  a, b   //  a로부터 데이터를 가져와서  b에 저장

 

Immediate Operands

  • addi $s3, $s3, 4 //레지스터에 즉각적으로 접근해서 상수를 더해주는 명령어 
  • 뺄셈은 지원 안 하기 때문에 음수를 더해서 뺄셈 진행
  • load 명령을 이용하지 않는다.

 

2.4 Signed and Unsigned Numbers

  • 2진수 음수 만드는 법
    -> 보수 취하고 +1하기 
  • Sign Extension
    -> 부호 비트를 왼쪽으로 계속 복사
예) 8 bit to 16 bit 
+2: 0000 0010 => 0000 0000 0000 0010 
-2 : 1111  1110 => 1111 1111 1111 1110

 

2.5  명령어 표현하기

  • Hexadecimal
    -> 16진수 숫자 하나당 4비트

 

MIPS R-format Instructions

  • MIPS 명령어는 32비트로 이루어져 있다
  • op: operation code (opcode)
  • rs: first source register number
  • rt: second source register number
  • rd: destination register number
  • shamt: how many positions to shift (쉬프트 할 비트의 개수) 
  • funct: function code (extends opcode)
예)
$s1은 레지스터 17번
$s2는 레지스터 18번
$t0는 레지스터 8번

 

 

MIPS I-format Instructions

Immediate arithmetic(즉각 연산) 명령어와  load/store 명령어에 사용

 

* op코드로 R 포맷인지 I 포맷인지 구별가능하다

-> R포맷은 op코드가 0

 

 

2.6 논리 연산 (다 이항 연산)

  • sll $t0,$t0,4 : shift left //쉬프트 1당 2를 곱하는 것과 같다.
  • srl : shift right //쉬프트 1당 2를 나누는 것과 같다. (양수에서만 가능)
쉬프트 하고 빈자리는 0으로 채운다
  • and, andi : 비트 사이 AND 연산
  • or, ori : 비트 사이 OR 연산
뒤에 i가 붙은 연산은 상수와 레지스터 사이 연산
  •  nor : 비트 사이 NOT 연산( ~)  // NOT 연산: 비트를 반대로 바꾸는 것 (1 ->0, 0 ->1)
예) nor $t0, $t1, $zero  // $t1과 0 사이에  or 연산을 한 후 not연산을 한 것 

 

2.7  Conditional Operations

  • beq rs, rt, L1 
    -> if(rs==rt) 라면 L1 레이블 실행
  • bne rs, rt, L1
    -> if(rs!=rt) 라면 L1 레이블 실행
  • slt rd, rs, rt
    -> if(rs <rt) rd=1; else rd=0;
  • slti rt, rs, constant
    if(rs <constant) rt=1;else rt=0;
  • j  L1
    -> L1 레이블로 점프

예 1 )

예 2)

i인덱스에 접근하기 위해서 add 명령어를 사용하고 있다.

예 3) 

slt $t0, $s1, $s2  # if(s1 <s2) $t0=1; else $t0=0;

bne $t0, $zero, L # if($t0!=0) 레이블 L로 이동;
-> 즉, 레이블 L은 s1 <s2일 때 실행하는 레이블

 

  • <,>= 명령어 연산이 =,!=보다 느리다.

 

숫자 비교 명령어

  • slt $t0, $s0, $s1   #부호 있는 이진수 비교 
    -> $s0 <$s1이면 $t0=1, $s0>$s1이면 $t0=0
  • slti는 레지스터가 아닌 상수와 바로 비교
  • sltu $t0, $s0, $s1  #부호 없는 이진수 비교
  • sltui는 상수와 비교

slt일떈 $s0이 -1로 인식되고 sltu일땐 40억으로 인식됨

 

2.8 함수 콜 

<필요한 레지스터>

  • $a0 ~ $a3 : arguments 저장할 레지스터
  • $v0, $v1 : 결과 값 저장할 레지스터
  • $t0 ~ $t9 : 임시로 값 저장할 레지스터
  • $s0 ~$s7 : 값을 저장할 레지스터 
값을 저장하고 원래 함수로 돌아가기 전에 처음 값으로 반드시 복구해줘야 한다. 
  • $sp : stack pointer
  • $fp : frame pointer
  • $ra : return address

<필요한 명령어>

  • 함수 콜 명령어
    jal  procedureLabel : $ra에 다음에 수행해야 할 명령어의 주소를 넣어준 뒤 그 주소로 점프
  • 함수 리턴 명령어
    jr $ra : 프로그램 카운터에  리턴 주소 복사

예 1)

int leaf_example (int g, h, i, j)
{ int f = (g + h) -(i+j);
return f;
}
/* Arguments g, …, j in $a0, …, $a3
f in $s0 (hence, need to save $s0 on stack)
Result in $v0 */

 

# 스택 공간 확보
addi $sp, $sp, -4 
# 원래 f값 저장
sw $s0, 0($sp)

#함수 본문 실행
add $t0, $a0, $a1
add $t1, $a2, $a3
sub $s0, $t0, $t1
#결과 값 저장
add $v0, $zero, $s0
#원래 f값 복구
lw $s0, 0($sp)
#스택 복구
addi $sp, $sp, 4
# 다음에 실행할 명령어로 리턴
jr $ra

예 2)

int fact (int n)
{
if (n < 1) return 1;
else return n * fact(n-1);
}
/* Argument n in $a0
Result in $v0 */
# 스택 공간 확보
addi $sp, $sp, -8
# argument 레지스터 값 복원위해 원래 값 보관
sw $a0, 0($sp)
# 재귀함수라 리턴 주소를 복원하기 위해 저장
# -> 함수 호출이 끝나고 돌아갈 주소를 미리 저장해놓지 않으면 함수가 끝나지 않고 
# 계속 호출되는 무한루프에 빠질 수 있다.
sw $ra, 4($sp)

#본 함수 실행
slti $t0, $a0, 1    # n < 1 이면 $t0=1, 아니면 $t0=0
beq $t0, $zero, L1   # $t0=0이면 L1 실행. 즉, n > 1인경우
# n < 1 일때
addi $v0, $zero, 1  #결과값 1 저장
addi $sp, $sp, 8   # 스택 복원
jr $ra  #함수 리턴

L1: addi $a0, $a0, -1
	jal fact     # fact 함수(자기 자신) 호출

# 원래값들 복원
lw $a0, 0($sp)
lw $ra, 4($sp)
# 스택 복원
addi $sp, $sp, 8
# 결과값 계산 후 리턴
mul $v0, $a0, $v0
jr $ra

 

2.9 byte/harlword(2바이트) 조작 명령어

  • lb rt, offset(rs)   
    lh rt, offset(rs)   
    -> rs에서 offset만큼 떨어진 주소에 저장된 값을 rt에 저장
    # b는 바이트, h는 2바이트 이동. 남은 비트는 sign extension
  • lbu rt, offset(rs)   
    lhu rt, offset(rs)
    -> rs에서 offset만큼 떨어진 주소에 rt를 저장
    # unsigned 버전. 남은 바이트 0으로 채우기(zero extension)
  • sb rt, offset(rs)   
    sh rt, offset(rs)
    -> rs에서 offset만큼 떨어진 주소에 rt값을 저장 

예) char은 1바이트이고 i는 양수이므로 lbu 사용

void strcpy (char x[], char y[])
{ int i ;
i=0;
while ((x[i]=y[i])!=' 0')
i += 1;
}
/* Addresses of x, y in $a0, $a1
   i in $s0  */
addi $sp, $sp, -4   #스택 공간 확보
sw $s0, 0($sp)      #원래 i값 스택 포인터 레지스터에 저장

#본 함수
L1: add $s0, $zero, $zero # i = 0
	add $t1, $s0, $a1   # $t1에 y[i] 주소 저장
    lbu $t2, 0($t1)     # $t2에 y[i] 값 저장
    add $t3, $s0, $a0   # $t3에 x[i] 주소 저장
    sb $t2, 0($t3)      # x[i]=y[i]
    beq $t2, $zero, L2  # y[i]값이 0과 같다면 L2레이블로 이동
    addi $s0, $s0, 1    # 같지않다면 i=i+1
    j L1                # L1레이블로 점프(loop)
# 함수 끝낼 준비
L2: lw $s0, 0($sp)      # 원래 i값 복구
    addi $sp, $sp, 4    # 스택 공간 복구
    jr $ra              # 함수 return

 

2.10 상수 작업 및 메모리 주소에 32비트 값을 사용하는 방법

32비트 상수

  • 대부분의 상수는 16비트로 커버가능
  • 16비트로 커버 불가능한 상수를 위한 명령어
    -> lui rt, constant  : 16비트의 상수를 rt레지스터의 왼쪽 16비트에 복사 후 오른쪽 16비트는 0으로 클리어

 

Branch Addressing

  • 대부분의 타깃 브랜치는 가까운 곳에 있다
  • 만약 타깃 브랜치가 멀리 있다면 어셈블러가 코드를 재작성한다. 

예) 만약 L1 레이블(타깃 브랜치)이 멀리 있다면

beq $s0,$s1, L1
↓
bne $s0,$s1, L2
j L1
L2: ....
  • 타깃 주소= PC(프로그램 카운터: 다음에 실행할 명령어 주소 저장되어 있다) + offset*4
    -> pc는 다음 명령을 수행하기 위해 항상 offset을 1 증가시킨다.
       따라서 원하는 offset 보다 1 낮게 써야 함.

Jump Addressing 

  • 타깃 주소 = address*4 

예)

  • 2*4=8만큼 가면 80020이지만 pc로 인해 1 offset 갔기 때문에 
    Exit 레이블 주소는 80024.
  • jump 명령어로 20000*4=80000 주소로 이동

 

Array  vs Ptr

*Induction variable: 반복문 안에서 계속 증가 또는 감소하는 변수

-> 이걸 포인터 방식에서는 사용하지 않음으로써 실행 속도 빨라짐.

p+1이 다음 인덱스 주소를 가리키도록 함.

 

728x90

'컴퓨터구조' 카테고리의 다른 글

Chap 5- Memory(1)  (0) 2023.05.31
Chap 4. Processor  (2) 2023.05.26
chap3 - Arithmetic for Computers  (0) 2023.04.12
컴퓨터구조 전공수업 ch01.  (0) 2023.03.26
CPU 캐시 메모리  (0) 2023.03.21