CS/컴퓨터구조

[컴퓨터구조] 논리연산 명령어와 판단을 위한 명령어

하루아아한잔 2022. 9. 30. 11:07

*컴퓨터 구조 및 설계 5th Edition (저자 David A. Patterson 과 John L. Hennessy)를 기반으로 작성되었습니다.

*MIPS 어셈블리언어 기반으로 작성되었습니다.

 

논리연산 명령어

초기의 컴퓨터는 워드 전체에 대한 처리에만 관심을 가졌습니다. 하지만 곧 워드 내 일부 비트에 대한 연산 , 심지어는 개개 비트에 대한 연산도 필요하다는 것이 명백해졌습니다. 이를 위해 만들어진 명령어들을 논리연산 명령어 라고 부릅니다.

 

  • 자리이동(shift)

$$0000\,0000\,0000\,0000\,0000\,0000\,0000\,1001_{two} = 9_{ten}$$

위와 같은 값이 있을 때 왼쪽으로 4번 shift 시키는 명령어를 실행하면 다음과 같이 됩니다.

$$0000\,0000\,0000\,0000\,0000\,0000\,1001\,0000_{two} = 14_{ten}$$

 

이렇게 왼쪽으로 자리이동을 하는 명령어를 sll(shift left logical)이라고 하며, 반대로 오른쪽으로 자리이동하는 명령어를 srl(shift right logical) 이라고 부릅니다. R 형식의 명령어와 기계어 형식으로 표현하면 다음과 같습니다.

$$ sll \quad \$t2,\$s0,4$$

op rs rt rd shamt funct
0 0 16 10 4 0

*shamt필드는 shift amount를 나타내는 것으로 자리이동 명령어에서 사용됩니다. 

sll 명령은 또 다른 용도로 사용될 수 있는데 왼쪽으로 $i$비트 자리이동을 하면 $2^i$을 곱한 것과 같은 결과가 됩니다.

 

  • AND

AND 연산은 비트대 비트 연산자로서 두 비트 값이 모두 1일 경우에만 결과가 1이 되는 연산입니다.

$$0000\,0000\,0000\,0000\,0000\,1101\,1100\,0000_{two} $$

$$0000\,0000\,0000\,0000\,0011\,1100\,0000\,0000_{two} $$

위와 같은 t1, t2 값이 있을 때, 다음과 같은 MIPS 명령어를 실행하고 나면

$$and \quad \$t0,\$t1,\$t2$$

t0 레지스터의 값은 다음과 같이 됩니다.

$$0000\,0000\,0000\,0000\,0000\,1100\,0000\,0000_{two}$$

 

  • OR

OR 연산은 AND와 대칭되는 연산으로 두 비트 중 하나만 1이면 결과가 1이 되는 연산자입니다. 

$$or \quad \$t0,\$t1,\$t2$$

위와 같은 명령어를 수행하면 t0 레지스터 값은 다음과 같이 됩니다.

$$0000\,0000\,0000\,0000\,0011\,1101\,1100\,0000_{two}$$

 

  • NOT

NOT연산은 0을 1로, 1을 0으로 바꾸는 연산입니다.

 

판단을 위한 명령어

컴퓨터가 단순한 계산기와 다른 점은 판단 기능이 있다는 점입니다. 프로그래밍 언어에서는 보통 if 문으로 판단 기능을 표현하는데, MIPS의 경우 beq, bne 명령어를 통해 표현합니다.

 

  • beq: branch if equal

$$beq\quad\,register1\,,register2\,,L1$$

예를 들면 위와 같은 명령어는 'register1과 register2가 같다면 L1에 해당하는 문장으로 이동.' 이라는 뜻입니다.

 

  • bne: branch if not equal

$$bne\quad\,register1\,,register2\,,L1$$

register1과 register2가 다르다면 L1으로 이동하라는 뜻입니다.

 

*beq, bne 두 명령어를 조건부 분기(conditional branch) 라고 부릅니다.

*어셈블러가 컴파일러나 어셈블리 언어 프로그래머가 지겨운 분기 주소 계산을 하지 않도록 해줍니다.

*컴파일러가 소스 프로그램에는 없는 분기 명령이나 레이블을 만들어 내는 경우가 많이 있습니다. 이를 통해, 필요한 레이블과 분기 명령을 일일이 표시하지 않아도 되는 것이 상위 수준 프로그래밍 언어의 장점 중 하나이며, 코딩이 더 빨라지는 이유이기도 합니다.

  • Loop

판단 기능은 둘 중 하나를 선택(if 문장 사용)하는 것도 중요하지만, 계산의 반복(순환문 사용)에도 중요합니다.

  • slt, slti: set on less than

비교 명령은 부호 있는 수와 부호 없는 수 사이의 이분법도 다루어야 한다. 어떤 때는 MSB가 1인 수가 음수를 나타내며, 이때는 MSB가 0인 어떤 양수보다도 작으며, 부호가 없는 정수의 경우에는 MSB가 1인 수가 MSB가 0인 어떤 양수보다도 더 큽니다. MIPS는 이 두가지 경우를 처리할 수 있도록 set on less than의 두가지 유형의 명령어를 제공합니다. 

*slt, slti는 부호 있는 수에, sltu, sltiu는 부호없는 정수에 사용합니다.

*blt(branch on less than) 명령어는 제외되었습니다. 이 명령어는 구현하게되면 클럭 속도가 느려지거나 이 명령 실행에 별도의 클럭 사이클이 더 필요하게 되므로 하드웨어는 간단해야 좋다는 von Neumann의 경고를 준수하여 MIPS 구조에서는 제외되었습니다.

 

MIPS에서는 부호 있는 수와 부호 없는 수에 대하여 MSB의 이중적 의미를 이용하여 배열 경계 검사 비용을 줄이는 방법이 있습니다. 부호 있는 정수를 부호없는 정수처럼 다루면 $0 <= x < y$ 검사비용을 낮출 수 있는데, 이 검사는 인덱스가 배열의 한계를 벗어났는지 확인하는 검사에 딱 맞습니다. 핵심은 2의 보수로 표현된 음수가 부호없는 정수에서의 큰 수 처럼 보인다는 것입니다. 

* 여기서 말하는 배열의 한계란 다음과 같습니다. 배열의 index는 배열의 length를 벗어날 수 없다. 즉, length보다 큰 index를 갖거나 음수인 index를 가질 수 없다는 것입니다.

 

$$ sltu \quad \, $t0\,,$s1\,,$t2$$

$$beq \, $t0\,,$zero\,,IndexOutOfBounds$$

위 명령어는 경계를 검사하는 명령어로 부호없는 정수 연산을 이용하여 한번에 두 가지 모두 검사하는 명령어입니다.

s1은 index를 t2는 배열 사이즈를 의미합니다. 

$sltu\quad \, \$t0\,,\$s1\,,\$t2$ 를 보면 s1(index) >= length or s1(index) < 0이라면 t0 = 0 가 되는 명령어 입니다.

$beq\quad \, \$t0\,,\$zero\,,IndexOutOfBounds$를 보면 t0 == 0 일 경우, Error를 발생시키도록 되어 있죠.

이렇게 MSB의 이중적 의미를 통해 한 명령어로 경계 검사를 한번에 수행할 수 있습니다.

 

  • case/switch 문장

대부분의 프로그래밍 언어는 특정 변수의 값에 따라 여러가지 중 하나를 선택하는 caseswitch 문장을 갖고 있습니다. 가장 간단한 방법은 계속적인 조건 검사를 통해 switch if-then-else의 연속으로 변환하는 것입니다.

다만, 여러 코드의 시작주소를 표로 만들면 더 효율적으로 구현할 수 있기 때문에, 프로그램은 점프 주소 테이블(jump address table) 또는 점프 테이블(jump table)의 인덱스만 계산해서 해당 루틴으로 점프할 수 있습니다.