'''Instruction Set Architecture, ISA''' [include(틀:CPU 아키텍쳐)] [목차] == 개요 == 명령어 집합은 [[소프트웨어]]와 [[하드웨어]] 사이의 약속이다. ISA는 여러 명령어들을 정의하며 또한 현재 시스템의 상태가 어떻게 구성되어 있고 명령어를 실행할 때 그 상태가 어떻게 바뀌는지에 대해서 정의한다. 그래서 소프트웨어를 구현하는 프로그래머 입장에서는 ISA를 통해 작성한 프로그램이 컴퓨터에서 어떻게 실행될 것인지 알 수 있고, 하드웨어를 구현하는 설계자 입장에서 ISA는 어떤 명령이 수행되었을 때 어떻게 수행되도록 설계해야 하는지의 명세서가 된다. 이렇게 ISA를 정의함으로써 프로그래머 입장에서의 인터페이스와 하드웨어 설계자 입장에서의 구현을 분리할 수 있다. == 상세 == 컴퓨터의 상태를 저장하는 요소가 메모리이니, 컴퓨터의 상태는 현재 메모리에 무엇이 저장되어 있는지라고 해도 될 것이다. 이 가운데는 CPU 내부에서 빠르게 이용할 수 있는 메모리인 [[레지스터]]가 있다. 이 레지스터는 프로그램을 어디까지 실행했는지에 대한 정보를 담고 있는 프로그램 카운터(PC), 계산중에 만들어지는 값과 같은 데이터를 저장할 수 있는 데이터 레지스터 등 여러 종류가 있다. '''명령어'''(instruction)는 이진수 코드의 조합으로, 프로세서가 명령어를 실행하면 레지스터에 저장된 정보와 같은 시스템의 상태가 바뀐다. ISA는 효과적인 프로그램 실행을 위해 다양한 종류의 명령어를 보유한다. * 산술 논리 명령어 : 산술논리장치(ALU)를 이용하여 사칙연산이나 논리 연산 등을 수행한다. add, sub 등이 있다. * 데이터 전송 명령어 : 메모리 간에 데이터를 전송한다. load/store라고 하며, 특히 레지스터 간에 데이터를 전송하는 것은 보통 move 명령어라 한다. * 실행 흐름 제어 명령어 : 조건에 따라 서로 다른 실행 흐름으로 분기하는 branch 계열의 명령어, 서브루틴을 실행하는 call 명령어, [[운영체제]]에게 흐름을 전달하는 trap 명령어 등이 있다. * 부동소수점 연산 명령어 : [[부동소수점]] 실수의 연산을 하는 명령어들이다. === 명령어의 구성 === 명령어는 보통 다음 두 부분으로 구성된다. 각 부분들이 이진수로 표현되고 조합되어 하나의 명령어를 구성한다. * opcode : ADD, SUB와 같이 명령의 종류를 나타낸다. * operand : opcode, 어떤 대상에 대해 그 명령을 수행할 것인지에 대한 operand로 구성된다. 명령의 종류에 따라 함께 오는 operand의 구성은 다양하다. operand가 아예 없는 명령어도 있고, 하나, 둘, 심지어 셋 이상일 수도 있다. 흔히 오는 operand의 종류로는 레지스터, 메모리 주소, 상수 값 등이 있다. 예컨대, [[RISC-V]] ISA에 있는 ADDI 명령어는 지정한 레지스터에 들어 있는 정수 값에 특정한 정수 상수를 더하여 그 결과를 레지스터에 저장하는 명령어이다. 그러므로 이 명령어는 레지스터 둘과 상수 하나를 operand로 한다고 할 수 있다. 이 명령어의 길이는 4바이트(32비트)로, 비트 0-6과 12-14는 명령어의 종류(ADDI)를 나타내는 값이, 비트 7-11에는 결과를 담을 레지스터의 번호[* RISC-V의 기본 레지스터는 총 32개로, 5비트면 번호를 표현하는 데 충분하다. ]가, 비트 15-19는 어느 레지스터에 상수를 더할지를 나타내는 레지스터 번호가, 비트 20-31에는 부호 확장되는 12비트의 상수 값이 들어간다. 1번 레지스터에 저장되어 있는 값에 5를 더한 값을 2번 레지스터로 저장하는 명령어를 이진수로 표현한다고 하자. RISC-V는 기본적으로 리틀 엔디안을 사용하므로, 다음과 같이 조립된다. {{{ 31 20 19 15 14 12 11 7 6 0 +-----------------------+---------+-----+---------+-------------+ |0 0 0 0 0 0 0 0 0 1 0 1|0 0 0 0 1|0 0 0|0 0 0 1 0|0 0 1 0 0 1 1| +-----------------------+---------+-----+---------+-------------+ }}} 이렇게 조립된 00000000010100001000000100010011이 명령의 이진수 표현이 되고, 이것을 실행하는 프로세서는 1번 레지스터의 값과 상수 5를 더해 2번 레지스터에 저장하는 동작을 한다. 이런 식으로 명령어를 표현한 것이 [[기계어]]인데, 사람이 읽기 편하게 하기 위해 다음과 같이 기계어에 대응하는 [[어셈블리어]]를 사용하여 표현할 수도 있다. {{{ addi x2, x1, 0 }}} === 주소 지정 방식 (addressing mode) === 명령어가 어디에 있는 값을 읽고 써야 하는지 지정하는 방식을 주소 지정 방식이라 한다. 가능한 주소 지정 방식은 ISA마다, 명령어마다 다양하다. 아래에 다양한 주소 지정 방식을 설명하였다. Regs[r]는 레지스터 r에, Mem[x]는 메모리 주소 x에 있는 값을 의미한다. || 주소 지정 방식 || 명령어의 예시 || 예시의 의미 || 설명 || 사용될 수 있는 예 || || 레지스터(register) || add r1, r2 || Regs[r1] ← Regs[r1] + Regs[r2] || 레지스터에 저장된 값을 접근할 때 지정한다. || 연산 중간 결과의 저장 || || 상수 / 즉치(immediate) || add r1, 3 || Regs[r1]←Regs[r1] + 3 || 명령어 자체에서 상수 값을 읽어올 때 지정한다. || 상수 값과의 연산 || || 직접 지정(direct) || add r1, (1000) || Regs[r1]←Regs[r1] + Mem[1000] || 고정된 주소의 메모리를 접근할 때 지정한다. || 전역 변수 접근 || || 레지스터로 간접 지정(register indirect) || add r1, (r2) || Regs[r1]←Regs[r1] + Mem[Regs[r2]] || 레지스터에 있는 주소의 메모리를 접근할 때 사용한다. || 포인터 접근 || || 거리로 지정(displacement) || add r1, 4(r2) || Regs[r1]←Regs[r1] + Mem[4 + Regs[r2]] || 레지스터에 있는 주소에 일정 거리를 더한 주소의 메모리를 접근할 때 사용한다. || 지역 변수 접근 || || 레지스터로 거리 지정(index) || add r1, (r2+r3) || Regs[r1]←Regs[r1] + Mem[Regs[r2] + Regs[r3]] || 레지스터에 있는 주소에 다른 레지스터 값에 해당하는 거리를 더한 주소의 메모리를 접근할 때 사용한다. || 배열 접근 || == 관련 문서 == * [[기계어]] * [[마이크로아키텍처]] * [[CPU]] * [[RISC]] / [[CISC]] / [[VLIW]] * [[컴퓨터에서의 수 표현]] [[분류:컴퓨터 시스템 및 구조]]