전공 과목/컴퓨터 구조

Lecture 05: Instructions - Language of the Computer - 2

arsenic-dev 2024. 9. 29. 23:53

경희대학교 김정욱 교수님의 컴퓨터 구조 수업을 기반으로 정리한 글입니다.

Signed and Unsigned Numbers

우리는 10진법을 사용하지만 컴퓨터는 2진법을 사용한다. (0 or 1)

▶ base 2 -> base 10

▶ MSB - LSB

  • Least significant bit (LSB): The right most bit in a MIPS word (작다)
  • Most significant bit (MSB): The left most bit in a MIPS word (크다)

※ signed bit의 경우, MSB가 0이면 양수, 1이면 음수가 되기에 MSB가 중요하다.

Signed and Unsigned Numbers

비트만 봐서는 signed bit인지, unsigned bit인지 알 수 없고,

unsigned bit으로 인식하고 연산을 수행하라, 이런 식으로 명령을 하는 것이다.

 

즉, 명령어에 따라 해석이 달라진다.

 

Unsigned binary numbers (32 bit)

부호 구분 없이 다 양수이다.

▶ Unsigned bit 수식

▶ Unsigned bit 예시

 

Signed binary numbers (32 bit)

MSB가 0이면 양수, 1이면 음수로, 부호가 있다.

▶ Signed bit 수식 1

▶ Signed bit 예시

▶ ⭐ Signed bit 수식 2

 

signed bit 값을 구할 땐 'Signed bit 수식 1'으로 일일이 구하는 것 보단,

'Signed bit 수식 2' 법칙을 사용하면 더 쉽게 구할 수 있다.

 

※ 'x바'는 x를 다 뒤집은 값을 말한다.

MIPS Fields

값은 유지한 채로, 32 bit로 늘리고 싶을 때,

unsign의 경우, 그냥 0으로 확장하면 된다.

 

하지만 sign extension의 경우

양수면 unsign과 동일하게 0을, 음수면 1을 그대로 복사하여 확장해야 한다.

▶ 양수 -> 0으로 extension

▶ 음수 -> 1로 extension

Hexadecimal

2진법 4개를 묶어서 16진법, Hexadecimal로 표현한다. (8 - 4 - 2 - 1)

이때, 16진법은 10 ~ 15는 a ~ f로 나타낸다.

 

최근에는 컴퓨터가 64 bit를 많이 사용하는데,

이를 조금이라도 더 간략화하기 위해 16진법을 사용한다고 볼 수 있다.

 

ex) 주소값 표현

▶ 16진법 - 2진법

▶ 16진법 <-> 2진법 Example

 

※ a는 10, b는 11, c는 12, d는 13, e는 14, f는 15를 의미한다.

Representing Instructions in the Computer

▶ assembly language -> binary machine language

 

assembly language를 binary machine language로 바꿀 때는,

각각에 대응 하는 값으로 그대로 바꿔주기만 하면 된다.

1. R-Format

사칙 연산을 하는 format을 말한다.

ex) add, sub

▶ R - Format

 

register가 32비트이기에 2^5, 즉 shift 5bits로 끝까지 다 밀어 버릴 수 있기 때문에 shamt도 5bits이다. 때문에 op, funct는 32bits 중 남은 12bits를 나눠 6bits씩 가져간 것이다.

 

MIPS Fields

  • op: operation code (명령 코드), 명령어가 수행할 연산의 종류를 나타낸다.
  • rs: register source 1 (5bits - 32registers)
  • rt: register source 2 (5bits - 32registers)
  • rd: register destination (5bits - 32registers)
  • shamt: shift amount, 시프트 연산에서 이동의 크기로 곱셈, 나눗셈에 이용된다.
  • funct: function code, op field가 나타낸 연산의 종류 중 어떤 연산을 나타내는지 연산을 구체적으로 지정한다.

※ register 개수는 3개로 총 15bits이고, instruction과 관련된 bit는 12bits이다. (op + funct)

 

 
 

op, funct field 보충 설명

예를 들어, add의 경우, op 값은 000000이다.

하지만 덧셈, 뺄셈의 사칙연산의 경우 op 값은 모두 0이기에 정확히 어떤 연산을 의미하는지 알 수 없다.

 

이때, funct 값을 사용하여 add, sub 중 어떤 연산을 나타내는지 구체적으로 표현할 수 있다.

 

Example

add $t0,$s1,$s2

▶ Assembly Language (Compiled MIPS Code)

▶ Machine Language

 

※ Register 별로 대응하는 Register number가 있다.

▶ Name - Register number

 

※ funct code에서 add는 32, sub은 34를 의미한다.

2. I-Format

상수 연산을 하는 format을 말한다.

ex) lw, sw

▶ I - Format

 

MIPS Fields

  • op: operation code (명령 코드), 명령어가 수행할 연산의 종류를 나타낸다.
  • rs: register source 1, base address를 나타낸다.  (5bits - 32registers)
  • rt: register source 2, target(destination)을 나타낸다.. (5bits - 32registers)
  • constant or address: constant는 immediate 연산을 할 때 사용하는 상수 값을 ± 2^15 범위에서 나타내고, address는 접근할 수 있는 주소, 즉 base address에서 어느 정도 떨어질 수 있는지를 ± 2^15 을 통해 나타낸다.

※ register 개수는 2개로 총 10bits이고, constant or address는 16bits로 고정되어 있다.

 

Example

lw $t0,32($s3) # Temporary reg $t0 gets A[8]

▶ Assembly Language (Compiled MIPS Code)

▶ Machine Language

 

※ operation code에서 lw는 35, sw은 43을, addi는 8을 의미한다. (subi는 존재 X, addi로 음수를 더하는 식으로 표현)

MIPS Fields

▶ R - format, I - format MIPS Fields

 

※ machine binary code 값을 봤을 때, 맨 앞이 다 000000이면 R-format임을 알 수 있다. 즉, 맨 앞 6bits를 보고 R-format인지, I-format인지 해석할 수 있다. 이러한 해석을 통해 뒤에 rd가 와야할지 constant or address가 와야할지 알 수 있다.

 

※ n.a.는 없다는 의미이다.

 

※ R - format, I - format 외에, J - format도 있다.

Representing Instructions (Example)

A[300] = h + A[300];

▶ High-level Language

 

 h는 $s2에 저장되어 있으며, array A의 base address는 $t1에 저장되어 있다고 가정한다.

lw $t0,1200($t1) # Temporary reg $t0 gets A[300]
add $t0,$s2,$t0 # Temporary reg $t0 gets h + A[300]
sw $t0,1200($t1) # Stores h + A[300] back into A[300]

▶ Assembly Language

▶ Machine Language

 

※ lw, sw 명령어 수행시, 구분없이 둘 다 rs에 base address가 들어가야 한다.

 

※ Instruction 별로 대응하는 op 값이 정해져 있다.

Logical Operations

▶ Logical operation (논리 연산)

 

※ bit by bit: 각 비트 위치별로 연산한다는 의미이다.

 

※ R-Format 중 shamt field에 Shift left와 Shift right가 사용된다. (5bits)

Logical Operations (Example)

Example 1 (Shift left - sll)

ex) Multiply 2^4 by shifting 4 bits left 

▶ binary code

sll $t2,$s0,4 $ reg $t2 = reg $s0 << 4 bits

▶ Compiled MIPS code

▶ Machine code (R-format)

 

※ sll은 op code와 funct bit을 둘 다 0이고, srl은 funct는 2이다. (R-format -> op code 무조건 0)

Shift 연산은 왜 rs가 0일까?

 

sll, srl은 다른 R-format과 달리, rs를 비워두고 shamt에 이동할 만큼의 값을 넣어 주기로 약속했기 때문이다.

이때, register가 2개라고 I-format이라고 착각하지 말아야 한다.

Example 2 (Shift right - srl)

ex) Divide 2^n by shifting n-bits right

▶ Shift Right 8-bit (>>)

 

※ 나누기에서 나머지는 버려지고 몫만 남는다.

▶ Shift Right 16-bit (>>) (Signed Int)

 

※ Signed의 경우, 음수(MSB == 1)는 0이 아니라 1로 채워진다. 하지만 Unsigned로 해석하고자 한다면 MSB가 1인 것과 상관없이, 0으로 채워진다.

Example 3 (AND)

and $t0,$t1,$t2 # reg $t0 = reg $t1 & reg $t2

▶ Compiled MIPS code

 

※ register 3개이므로 R-format임을 알 수 있다.

▶ binary code

 

※ register끼리 연산한다는 것은 register에 있는 '값'끼리 연산한다는 의미이다.

Example 4 (OR)

or $t0,$t1,$t2 # reg $t0 = reg $t1 | reg $t2

▶ Compiled MIPS code

▶ binary code

Example 5 (NOT = NOT OR)

nor $t0,$t1,$t3 # reg $t0 = ~ (reg $t1 | reg $t3)

▶ Compiled MIPS code

 

※ OR: 둘 다 0일 때만 0 -> NOR: 둘 다 0일 때만 1

▶ binary code

Instructions for Making Decisions

1. Conditional branches

if문을 컴파일링하기 위한 instruction에는, beq와 bne가 있다. (if statement with go to)

 

beq(branch if equal)

beq register1, register2, L1

▶ register1과 register2의 값이 같으면 L1으로 이동(go to)해라. (만약 값이 다르면 그냥 그다음 명령어 수행)

 

bne(branch if not equal)

bne register1, register2, L1

▶ register1과 register2의 값이 다르면 L1으로 이동해라. (만약 값이 같으면 그냥 그다음 명령어 수행)

 

※ branch(분기): 어디로 가라, 분기해라, 이동해라

 

※ L1은 존재하는 값이 아니라, instruction 주소값이다.

 

Example

if (i == j) f = g + h; else f = g - h;

▶ C code

▶ diagram

 

Conditional branches 2: If statement with go to

bne $s3,$s4,Else # go to Else if i ≠ j
add $s0,$s1,$s2 # f = g + h (skipped if i ≠ j)
j Exit # go to Exit
Else:sub $s0,$s1,$s2 # f = g - h (skipped if i = j)
Exit:

▶ MIPS code (bne)

 

Else는 instruction 주소이고, j는 jump로, J-format이다.

 

이때, 컴파일러 입장에서 같으면 내려가고 다르면 jump(branch, go to)한다는 직관 때문에 bne로 구현한 것일뿐,

beq 사용해도 문제 없다.

beq $s3,$s4,If
sub $s0,$s1,$s2 # f = g - h
j Exit # go to Exit
If: add $s0,$s1,$s2 # f = g + h 
Exit:

▶ MIPS code (beq)

 

 If도 instruction 주소이다.

 

※ f, g, h, i, j는 각각 $s0, $s1, $s2, $s3, $s4에 저장되어 있다고 가정한다.

2. While loop

while (save[i] ==k)
	i += 1;

▶ C code

Loop:sll $t1,$s3,2 # Temp reg $t1 = 4 * i, 2 -? 2^2 = 4
	add $t1,$t1,$s6 # $t1 = address of save[i]
    lw $t0,0($t1) # Temp reg $t0 = save[i], 0 -> save[i+0]
    bne $t0,$s5,Exit # go to Exit if save[i] ≠ k
    addi $s3,$s3,1 # i = i + 1
    j Loop # go to Loop
Exit:

▶ MIPS code

 

i에 4를 곱해주는 이유는 byte (4) addressing을 해주어야 하기 때문이다.

이렇게 함으로써 base address에 4의 배수값을 더해줌으로써 array의 i번째 주소로 접근한다.

 

※ i, k는 각각 $s3, $s5에 저장되어 있으며, array save의 base address는 $s6에 저장되어 있다고 가정한다.

 

lw로 같은 값을 굳이 불러오는 이유는 뭘까?

 

i 변수에 따라 base address가 달라지기에, 새로운 베이스 어드레스로 매핑해주어야 하기 때문이다.

i로부터  몇 번째, 즉 기준점이 계속 달라지니, i에 맞게 기준점을 계속 설정하는 과정이다.

 

원래는 array 자체의 base address(시작 주소, save[0])를 사용하지만,

i 값이 들어가면 i에 맞는 위치로 이동해야 하므로, i에 따라 다시 계산해서 새로운 주소를 찾아줘야 한다.

 

save[i]의 주소는 array의 시작 주소 + (i * 4)이다.

때문에 만약 0($t1)이 아니라 2($t1)이면 (i + 2) * 4로,

0이 아니라 save[i]의 주소에서 8 byte 더해진 곳을 의미하게 된다.

3. Comparison instruction

Comparison instruction에는, slt, slti, sltu, sltiu가 있다.

 

slt(set on less than)

slt $t0,$s3,$s4 # $t0 = 1 if $s3 < $s4 (else: $t0 = 0)

register1이 register2보다 값이 작으면 set(1로 만들기, on)해라.

 

이때 $t0의 값은 무조건 0 or 1이다.

 

※ register 3개이므로 R-format임을 알 수 있다.

 

slti(set on less than immediate)

slti $t0,$s2,10 # $t0 = 1 if $s2 < 10 (else: $t0 = 0)

 register의 값이 constant보다 작으면 set해라.

 

sltu(set on less than unsigned)

sltu $t0,$s3,s4 # $t0 = 1 if $s3 < s4 (else: $t0 = 0)

register1이 register2보다 값이 작으면 set해라.

 

'u'는 unsigned로 해석하라는 의미로, 'u'가 없으면 항상 signed으로 해석하지만 'u'가 있으면 unsigned로 해석해야 한다.

즉, 32bits를 unsigned로 보고 비교하라는 의미이다.

 

sltiu(set on less than immediate unsigned)

sltiu $t0,$s2,10 # $t0 = 1 if $s2 < 10 (else: $t0 = 0)

 register의 값이 constant보다 작으면 set해라.

 

Example (slt vs sltu)

▶ binary code 예시

▶ signed로 본 경우

 

MSB를 보고 부호를 판단하면 $s0는 음수, $s1은 양수이기에 $s1이 크다.

▶ unsigned로 본 경우

 

$s0는 엄청 큰 양수, $s1은 1이기에 $s0가 크다.

어떤 값이 큰지는 instruction에 따라 달라진다.

 

MSB가 1인 수는 instruction에 따라 음수일 수도, 엄청 큰 양수일 수도 있다.