명령어 집합
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
명령어 집합 구조(ISA)는 CPU가 이해하고 실행하는 명령어들의 모음, 형식 및 의미를 정의하며, 하드웨어와 소프트웨어 간의 인터페이스 역할을 한다. ISA는 프로세서의 설계 기술인 마이크로아키텍처와 구분되며, 복잡도, 명령어 형식, 피연산자 수 등에 따라 분류된다. 명령어는 연산 코드(opcode)와 피연산자(operand)로 구성되며, 명령어 길이는 마이크로컨트롤러의 4비트에서 VLIW 시스템의 수백 비트까지 다양하다. ISA는 복잡도에 따라 CISC, RISC, VLIW 등으로, 명령어 길이에 따라 고정 길이와 가변 길이로, 피연산자 수에 따라 0-피연산자, 1-피연산자, 2-피연산자, 3-피연산자로 분류될 수 있다. 명령어 집합은 하드웨어적으로 구현되거나, 마이크로코드 또는 에뮬레이터를 통해 소프트웨어적으로 구현될 수 있으며, 설계 시 코드 밀도, 성능, 전력 소비 등을 고려해야 한다.
더 읽어볼만한 페이지
- 명령어 처리 - 멀티스레딩
멀티스레딩은 프로세스 내에서 여러 스레드를 동시 실행하여 처리 능력을 향상시키는 기술로, 응답성 향상과 자원 공유 등의 장점이 있지만, 자원 간섭과 소프트웨어 복잡성 증가 등의 단점도 존재하며, 다양한 모델과 구현 방식, 스레드 스케줄러, 가상 머신 활성화 가능성 등을 고려해야 한다. - 명령어 처리 - 마이크로아키텍처
마이크로아키텍처는 명령어 집합 아키텍처를 구현하는 프로세서의 구성 요소, 상호 연결, 작동 방식을 포괄하는 개념으로, 동일 ISA에서 반도체 기술 발전과 새로운 구조 및 회로를 통해 성능 향상을 가능하게 한다. - 명령어 집합 구조 - ARM 아키텍처
ARM 아키텍처는 저전력 설계로 모바일 기기에서 널리 쓰이는 RISC 기반 프로세서 아키텍처로서, IP 코어 라이선스 모델과 ARM Flexible Access를 통해 다양한 분야로 확장되고 있다. - 명령어 집합 구조 - PA-RISC
PA-RISC는 휴렛 팩커드에서 개발한 RISC 기반 명령어 집합 아키텍처로, HP 서버 및 워크스테이션에 사용되었으며 대용량 L1 캐시와 SIMD 명령어 확장 등의 특징을 가졌으나 아이테니엄 아키텍처로의 전환으로 단종되었다. - 중앙 처리 장치 - 마이크로컨트롤러
마이크로컨트롤러는 프로세서, 메모리, 입출력 기능을 단일 칩에 통합하여 임베디드 시스템의 핵심이 되는 부품으로, 프로그램 내장 방식을 통해 소프트웨어만으로 제어 기능 변경이 가능하며, 현재는 32비트 ARM, MIPS 아키텍처 기반 제품이 주를 이루고, 저전력 소모, 소형화, 다양한 기능 통합을 특징으로 다양한 분야에서 활용된다. - 중앙 처리 장치 - NX 비트
NX 비트는 하드웨어 기반 보안 기능으로, 메모리 페이지의 실행 권한을 제어하여 특정 영역에서 코드 실행을 막아 버퍼 오버플로 공격과 같은 보안 위협을 줄이는 데 사용되며, AMD에서 처음 도입 후 다양한 프로세서와 운영체제에서 DEP 등의 이름으로 구현되었다.
명령어 집합 | |
---|---|
명령어 집합 구조 | |
정의 | 컴퓨터 프로그램의 연산을 프로세서에 설명하는 추상적인 심볼 집합 |
관련 | 컴퓨터 아키텍처 |
일반 개념 | |
명령어 집합 | 명령어 집합 |
명령어 코드 | 명령 코드 |
불법 명령어 코드 | 불법 명령 코드 |
명령어 코드 테이블 | 명령 코드 테이블 |
피연산자 | 피연산자 |
명령어 | |
NOP | NOP |
분기 | 분기 |
간접 분기 | 간접 분기 |
반복 명령어 | 반복 명령 |
실행 명령어 | 실행 명령 |
2. 명령어 집합 구조 (Instruction Set Architecture, ISA)
명령어 집합 구조(Instruction Set Architecture, ISA)는 CPU가 이해하고 실행하는 명령어들의 모음과 그 명령어들의 형식 및 의미를 정의한다. ISA는 하드웨어와 소프트웨어 사이의 인터페이스 역할을 하며, 프로그래밍 모델을 제공한다.[2]
ISA는 마이크로아키텍처와는 구별된다. 마이크로아키텍처는 특정 프로세서에서 명령어 집합을 구현하는 데 사용되는 기술이다. 서로 다른 마이크로아키텍처를 가진 프로세서들이 동일한 명령어 집합을 공유할 수 있다. 예를 들어, 인텔 펜티엄과 AMD 애슬론은 거의 동일한 버전의 x86 명령어 집합을 구현하지만, 내부 설계는 근본적으로 다르다.
''아키텍처''라는 개념은 프레드 브룩스가 IBM에서 System/360을 설계할 때 개발했다. 이전에는 컴퓨터 설계자들이 기술 선택뿐만 아니라 기능 및 아키텍처 개선을 통해 비용 목표를 달성했지만, SPREAD 호환성 목표는 광범위한 비용과 성능을 아우르는 5개의 프로세서 시리즈에 대한 단일 아키텍처를 가정했다. 이로 인해 5개의 엔지니어링 설계 팀은 아키텍처 사양을 조정하여 비용 및 성능 목표 달성의 어려움을 완화할 수 없었다.[2]
ISA는 복잡성에 따라 분류될 수 있다. 복합 명령어 집합 컴퓨터(CISC)는 많은 특수 명령어를 가지지만, 그 중 일부는 실제 프로그램에서 거의 사용되지 않을 수 있다. 축소 명령어 집합 컴퓨터(RISC)는 자주 사용되는 명령어만 효율적으로 구현하여 프로세서를 단순화하고, 덜 일반적인 연산은 서브루틴으로 구현한다.[3]
초장 명령어(VLIW), 장 명령어(LIW), 명시적 병렬 명령어 컴퓨팅(EPIC) 아키텍처는 컴파일러가 명령어 발행 및 스케줄링을 담당하게 함으로써 RISC 및 CISC보다 적은 하드웨어로 명령 수준 병렬성을 활용한다.[4]
최소 명령어 집합 컴퓨터(MISC) 및 단일 명령어 집합 컴퓨터(OISC)와 같이 복잡성이 훨씬 적은 아키텍처도 연구되었지만, 상용화되지는 않았다.[5][6]
Smalltalk, 자바 가상 머신, 마이크로소프트의 공용 언어 런타임과 같이 바이트 코드를 ISA로 지원하는 일부 가상 머신은 자주 사용되는 코드 경로에 대한 바이트 코드를 네이티브 머신 코드로 변환하여 구현한다. 또한, 덜 사용되는 코드 경로는 인터프리테이션 방식으로 실행한다. (참조: Just-in-time compilation (JIT)). 트랜스메타는 이러한 방식으로 VLIW 프로세서 위에 x86 명령어 집합을 구현했다.
2. 1. 명령어 형식
전통적인 아키텍처에서 명령어는 수행할 연산을 지정하는 오퍼코드(opcode)와 하나 이상의 피연산자(operand) 지정자를 포함한다. 오퍼코드는 "메모리의 내용을 레지스터에 더하기"와 같은 연산을 지정하며, 피연산자는 프로세서 레지스터, 메모리 위치, 또는 리터럴 데이터를 지정할 수 있다. 피연산자 지정자는 의미를 결정하는 어드레싱 모드를 가질 수 있거나 고정된 필드에 있을 수 있다.[7] VLIW(Very Long Instruction Word) 아키텍처에서는 여러 개의 동시 오퍼코드와 피연산자가 단일 명령어에 지정된다.일부 특이한 명령어 집합은 수송 트리거 아키텍처(TTA)와 같이 오퍼코드 필드가 없고 피연산자만 있기도 하다.
대부분의 스택 머신은 산술 및 논리 연산에 피연산자 지정자 필드가 없는 "0-피연산자" 명령어 집합을 가지고 있다. 이들은 표현식 스택에서만 작동하는 후위 표기법(역 폴란드 표기법) 연산으로 대부분의 ALU(산술 논리 장치) 작업을 수행한다.[7]
조건부 명령어는 종종 특정 조건을 인코딩하는 프레디케이트 필드를 갖는다. 예를 들어, 조건부 분기 명령은 조건이 참이면 프로그램의 다른 부분으로 실행을 이동시키고, 거짓이면 순차적으로 실행을 계속한다. 일부 명령어 집합은 조건부 이동이나 조건부 저장 명령어도 갖추고 있다. 모든 명령어에 프레디케이트 필드를 포함하는 경우도 있는데, 이를 분기 예측이라고 한다.
명령어 집합은 명령어에 명시적으로 지정된 최대 피연산자 수에 따라 분류될 수 있다. 예를 들어, 0-피연산자(영 주소 기계)는 모든 산술 연산을 스택의 맨 위 또는 두 개의 위치를 사용하여 수행하며, `push a`, `push b`, `add`, `pop c`와 같은 명령어를 사용한다. 1-피연산자(단일 주소 기계)는 초기 컴퓨터와 많은 소형 마이크로컨트롤러에서 사용되며, `load a`, `add b`, `store c`와 같은 명령어를 사용한다. 2-피연산자와 3-피연산자 명령어 집합도 존재하며, CISC와 RISC 머신에서 다양하게 사용된다.
명령어의 크기(길이)는 매우 다양하다. 일부 마이크로컨트롤러에서는 4비트 정도로 작을 수 있고, 일부 VLIW 시스템에서는 수백 비트에 이를 수 있다. 개인용 컴퓨터, 메인프레임 컴퓨터, 슈퍼컴퓨터에 사용되는 프로세서는 최소 8비트에서 64비트 사이의 명령어 크기를 갖는다. x86에서 가능한 가장 긴 명령어는 15바이트(120비트)이다.[11] 명령어 집합 내에서 서로 다른 명령어는 서로 다른 길이를 가질 수 있다.
일부 아키텍처, 특히 대부분의 축소 명령어 집합 컴퓨터(RISC)에서는 명령어가 고정된 길이를 가지며, 일반적으로 해당 아키텍처의 워드 크기에 해당한다. 다른 아키텍처에서는 명령어는 가변 길이를 가지며, 일반적으로 바이트 또는 하프워드의 정수 배수이다. ARM의 ''Thumb 확장''과 같이 혼합된 가변 인코딩을 가진 경우도 있다.
고정 길이 명령어는 가변 길이 명령어보다 처리하기가 덜 복잡하여 속도 최적화가 다소 쉽다.[8]
2. 2. 주소 지정 방식 (Addressing Mode)
주소 지정 방식은 명령어 내에서 피연산자(operand)의 위치를 지정하는 방법을 정의한다. 다양한 주소 지정 방식이 존재하며, CPU 종류 및 어셈블리어 표현 방식에 따라 차이가 있다.전통적인 아키텍처에서 명령어는 수행할 연산을 지정하는 오퍼코드(opcode)와 하나 이상의 피연산자 지정자를 포함한다. 피연산자 지정자는 프로세서 레지스터, 메모리 위치 또는 리터럴 데이터를 지정할 수 있으며, 의미를 결정하는 어드레싱 모드를 가질 수 있다. VLIW(Very Long Instruction Word) 아키텍처에서는 여러 개의 동시 오퍼코드와 피연산자가 단일 명령어로 지정된다.
번지는 데이터의 위치를 지정할 때와 다음 실행할 명령어가 있는 위치를 지정하는 경우가 있다.[1]
2. 2. 1. 데이터 지정
즉시 모드 (Immediate Mode): 명령어에 대상 데이터가 직접 포함된다.:* 68000: `moveq.l #$10,d0` ; 0x10을 D0에 넣는다.
:* x86: `mov eax,10H` ; 0x10을 EAX에 넣는다.
:
+------+-----+-----+----------------+
| add | reg1| reg2| constant | reg1 := reg2 + constant;
+------+-----+-----+----------------+
직접 지정 (Direct): 명령어에 유효 주소가 포함되어 데이터의 위치를 나타낸다.
:
+------+-----+--------------------------------------+
| load | reg | address |
+------+-----+--------------------------------------+
Effective address = address
:* x86: `mov eax, [0x00040222h]`
간접 지정 (Indirect): 명령어에 포함된 주소는 데이터의 주소를 가리키는 포인터 값이다. 즉, 명령어의 주소를 읽어 주소 포인터를 결정하고, 그 값을 다시 주소값으로 사용하여 데이터를 읽는다.
:
+------+-----+--------------------------------------+
| load | reg | address1 |
+------+-----+-----------------+--------------------+
Effective address = [address] |
|
+-----------------v--------------------+
address1 | address2 |
+-----------------+--------------------+
|
+-----------------v--------------------+
address2 | data |
+--------------------------------------+
: x86 등 많은 CPU에서 지원하지 않는다.
레지스터 직접 지정 (Register Direct): 레지스터의 값이 데이터이다.
:
+------+-----+-----+-----+
| add | reg1| reg2| reg3| reg1 := reg2 + reg3;
+------+-----+-----+-----+
레지스터 간접 지정 (Register Indirect): 레지스터의 값이 데이터의 위치를 가리키는 주소 값이다. 따라서 레지스터 값을 주소값으로 하여 데이터를 읽는다.
:
+------+------+-----+
| load | reg1 | base|
+------+------+-----+
Effective address = 베이스 레지스터(base register)
- 레지스터를 고정된 상수 값으로 설정한다.
- 메모리 위치 또는 레지스터에서 다른 메모리 위치 또는 레지스터로 데이터를 복사한다. (기계 명령어에서는 '이동'이라고 표현하지만, 오해의 소지가 있다.) 레지스터 내용, 다른 메모리 위치의 내용, 계산 결과를 저장하거나, 나중에 계산하기 위해 저장된 데이터를 검색하는 데 사용된다. 로드 또는 저장 연산이라고도 한다.
- 하드웨어 장치에서 데이터를 읽거나 쓴다.
2. 2. 2. 기계어 코드 위치 지정
기계어에서 주소를 지정하는 방식은 여러 가지가 있다. 명령어에서 번지를 지정하는 방식은 다양하며, CPU마다 존재하는 것도 다르고, 어셈블리어에서 표현하는 방식도 다르다. 번지는 데이터의 위치를 지정할 때와 다음 실행할 명령어가 있는 위치를 지정하는 경우가 있다.[1]절대 주소 지정 (Absolute/Direct) 방식에서는 점프 명령의 OP 코드 다음에 점프할 절대 주소값이 온다. OP코드 다음의 주소를 프로그램 카운터(PC)에 넣으면 흐름이 변경된다.[1]
```
+-------+--------------------------------------+
| JMP | address |
+-------+--------------------------------------+
Effective address = address(instruction 안에 존재)
```
프로그램 카운터 상대 지정 (Program Counter Relative with Displacement) 방식에서는 현재 PC 값에 오프셋을 더하여 주소를 결정한다. 따라서 현재 위치로부터 상대적인 위치가 된다.[1]
```
+----+------------------------------+
|jump| offset | jump relative
+----+------------------------------+
Effective PC address = next instruction address + offset (offset는 상대적을 음수일수도 있다)
```
레지스터 간접 지정 (Register Indirect) 방식에서는 레지스터의 값이 점프할 주소 값이다.[1]
```
+-------+-----+
|jumpVia| reg |
+-------+-----+
Effective PC address = 레지스터 reg의 값
3. 명령어의 기능 및 종류
명령어는 ALU를 이용한 산술 연산 및 논리 연산, 데이터 전송, 실행 제어 등 다양한 기능을 수행한다.
- 산술 연산: 더하기, 빼기 같은 기본적인 사칙연산을 수행한다. 대부분의 CPU는 ALU를 통해 정수형 계산을 처리하며,[1] FPU가 장착된 CPU는 부동소수점 연산도 가능하다.
- 논리 연산: 논리곱(AND), 논리합(OR), 논리 부정(NOT) 등의 논리 연산을 수행한다.
- 데이터 전송: 이동, 입력, 출력, 불러오기, 저장 등과 같이 레지스터와 메모리 간, 또는 메모리 간에 데이터를 이동시킨다.[1]
- 실행 제어: 분기(goto), 조건부 분기(if … goto), 호출(call), 복귀(return) 등을 통해 프로그램 실행 흐름을 제어한다.
- 기타: 인터럽트 제어, 실행 권한 설정, NOP(아무 작업도 하지 않음) 등의 명령어가 있다.
DSP용 CPU는 수학 계산 전용으로 설계되어, 일반 레지스터에 연결된 ALU가 정수형과 실수형(부동소수점) 계산을 모두 수행하기도 한다.
프로세서는 여러 명령어가 필요한 작업을 하나의 명령어로 처리하는 "복잡한" 명령어를 포함할 수 있다. 이러한 명령어는 여러 단계를 거치거나, 여러 기능 유닛을 제어하는 형태로 나타난다. "복잡한" 명령어의 예시는 다음과 같다.
- 여러 레지스터를 한 번에 메모리(특히 스택)로 또는 스택에서 전송
- 대용량 메모리 블록 이동 (예: 문자열 복사 또는 DMA 전송)
- 복잡한 정수 및 부동 소수점 연산 (예: 제곱근, 로그, 사인, 코사인 등 초월 함수)
- SIMD 명령어: 여러 동종 값에 대해 병렬로 작업을 수행하는 단일 명령어
- 원자적 테스트-앤-셋 명령어 또는 기타 읽기-수정-쓰기 원자적 명령어 수행
- 레지스터 대신 메모리에서 피연산자를 사용하여 ALU 연산을 수행하는 명령어
복잡한 명령어는 RISC 명령어 집합보다 CISC 명령어 집합에서 더 흔하지만, RISC 명령어 집합에도 포함될 수 있다. RISC 명령어 집합은 SIMD 또는 벡터 명령어를 포함하는 경우가 많으며, 이러한 명령어는 큰 벡터와 행렬을 효율적으로 조작할 수 있게 해준다. 다양한 SIMD 구현이 MMX, 3DNow!, AltiVec와 같은 상표명으로 출시되었다.
3. 1. ALU에 의한 연산 명령어
대부분의 CPU는 사칙연산을 지원하며, ALU는 정수형 계산을 담당한다. 나눗셈과 곱셈의 경우 계산 결과가 한 개의 레지스터에 들어가는 것이 불가능하므로 두 개의 레지스터를 사용하는 것이 일반적이다. 나눗셈의 결과는 몫과 나머지로 나누어져 두 개의 레지스터에 저장된다.ALU를 통해 연산이 끝나면 CPU 내의 FLAG 레지스터에 결과 값(C, Z, N, O)이 저장되고, 이는 다음 명령어에 적용될 수 있다. 조건 점프 명령어는 FLAG에 이미 설정된 값에 따라 조건이 판단된다. ALU와 관련된 명령어는 FLAG에 영향을 미친다.[1]
```
; i386 경우
mov eax,10 ; EAX 레지스터에 10을 저장
add eax,2 ; EAX+2->EAX - ALU을 통해 연산하고 결과와 FLAG 저장
; EAX는 10+2=>12으로 변경되고, FLAG Z=0, C=0, N=0, O=0으로 설정
mov ebx,eax
xor eax,eax ; EAX을 클리어. 12 XOR 12 -> 0, FLAG Z=1, C=0, N=0, O=0으로 설정
```
3. 1. 1. 더하기와 빼기
더하기와 나누기 명령어는 정수형 연산이다. 부호를 고려하여 signed와 unsigned 명령어가 존재한다.[1] 연산을 할 때, 플래그 중 C(Cary)를 사용하는 경우도 있고 사용하지 않고 레지스터 값 만으로 연산하는 경우도 있다.- 두 개의 레지스터 값을 ''더하고'', ''빼고'', ''곱하거나'', ''나누어'' 결과를 레지스터에 저장하며, 필요에 따라 조건 코드를 상태 레지스터에 설정한다.[1]
- 일부 ISA에서는 ''증가'', ''감소'' 연산을 지원하여 간단한 경우 피연산자 인출을 절약한다.
3. 1. 2. 곱하기와 나누기
곱셈과 나눗셈 연산은 종종 2개의 레지스터를 사용하여 몫과 나머지의 결과를 저장한다.i386의 경우 다음과 같다:
명령어 | 설명 | 비고 |
---|---|---|
imul bl | ax <- al * bl | 8비트 signed |
imul bx | dx:ax <- ax * bx | 16비트 signed |
imul ebx | edx:eax <- eax * ebx | 32비트 signed |
mul ebx | edx:eax <- eax * ebx | 32비트 unsigned |
idiv ebx | edx <- eax % ebx; eax <- eax / ebx | 32비트 signed |
div ebx | edx <- eax % ebx; eax <- eax / ebx | 32비트 unsigned |
3. 1. 3. 비교 명령어
CMP (어셈블리어에 따라 표현은 다름) 명령어는 ALU를 통해 계산을 하고, FLAG 결과 만을 FLAG 레지스터에 저장하고 결과값을 버린다.[1]컴파일러 환경과 상황에 따라 다음과 같은 개념으로 컴파일 될 수도 있다.
```
; x86 경우
mov eax,10 ; EAX 레지스터에 10을 저장
cmp eax,10 ; EAX-10, FLAG 저장 - ALU을 통해 비교를 위해 연산
; EAX 가 10일 경우 10-10의 결과는 Z=1, C=0, N=0, O=0으로 FLAG 설정
; EAX 값 변경은 없음
jne JumpNext ; NE(Not Equal, Z=0일 경우 같지 않음으로 판단), CMP결과가 Z=1이므로 점프하지 않음.
inc eax ; EAX 증가, EAX =11 - a++ 실행 a = 11.
JumpNext:
...
; ARM의 경우
CMP R1,#10
BNE skipNext
ADD R1, R1, #1 ; R1+1=>R1
skipNext:
또는
CMP R1,#10
ADDEQ R1, R1, #1
3. 1. 4. 논리 연산 명령어
각 비트별로 AND, OR, NOT, XOR 등 비트 연산을 수행한다.[12] 두 레지스터의 해당 비트끼리 연산하고, 레지스터의 각 비트를 NOT 연산하는 방식이다.3. 1. 5. 시프트 명령어
레지스터의 값을 왼쪽 또는 오른쪽으로 비트 시프트(shift)한다. 플래그 중 C(Cary)를 사용하는 경우도 있고, 레지스터 값만으로 연산하는 경우도 있다.부호를 고려하여 왼쪽으로 시프트할 때, 부호 비트가 유지되는 경우도 있다.
3. 2. 데이터 전송 명령어
데이터 전송 명령어는 레지스터와 메모리 간, 또는 메모리 간에 데이터를 이동하는 역할을 한다.[1] 이 작업은 데이터를 복사하는 방식으로 이루어지며, 기계 명령어에서는 '이동'이라고 표현되지만, 실제로는 데이터가 복사되는 것이다.[1]- 직접 데이터 설정 명령어: 레지스터를 특정 상수로 설정한다.
- 직접 주소 전송 명령어: 메모리 위치 또는 레지스터 간에 데이터를 복사한다. 이를 '로드' 또는 '저장' 연산이라고도 한다.[1]
- 레지스터 인덱스 주소 전송 명령어: 하드웨어 장치에서 데이터를 읽거나 쓴다.
이 외에도, 여러 레지스터를 한 번에 메모리(특히 스택)나 스택으로 전송하는 복잡한 명령어, 대용량 메모리 블록을 이동하는 명령어(예: 문자열 복사 또는 DMA 전송) 등이 있다.[1]
3. 2. 1. 스택
PUSH 명령을 통해 스택에 데이터를 저장하고, POP 명령을 통해 스택에 저장된 데이터를 가져온다.3. 3. 실행 제어 명령어
프로그램의 실행 흐름을 제어하는 명령어는 다음과 같다.- 프로그램 내의 다른 위치로 분기하여 해당 위치의 명령어를 실행한다.
- 특정 조건이 충족될 경우 다른 위치로 조건부 분기를 한다.
- 다른 위치로 간접 분기를 한다.
- 다음 명령의 위치를 반환 지점으로 저장하면서 다른 코드 블록을 호출한다.
3. 3. 1. 조건 점프 명령어
FLAG 레지스터 값에 따라 조건부 분기를 수행한다. ALU에 의한 연산 결과에 따라 FLAG 레지스터 값이 조건을 판단하고, 조건이 만족하면 점프한다. 따라서 조건 명령어가 실행되기 전에 FLAG 레지스터에 설정이 되어 있어야 한다.[1] 프로그램 내의 다른 위치로 분기하여 해당 위치의 명령어를 실행하며,[1] 특정 조건이 충족될 경우 다른 위치로 조건부 분기를 수행한다.[1] 조건부 분기는 다른 위치로 간접 분기를 수행 할 수 있다.[1] 다른 코드 블록을 호출하면서 다음 명령의 위치를 반환 지점으로 저장한다.[1]3. 3. 2. CALL-RETURN 명령어
CALL 명령어는 프로그램 내의 다른 위치로 분기하여 해당 위치의 명령어를 실행하며, 다음 명령의 위치를 반환 지점으로 저장하면서 다른 코드 블록을 호출한다. RET 명령어는 서브루틴에서 호출한 위치로 복귀하는 명령어이다. IRET 명령어는 인터럽트 서비스 루틴을 종료하는 데 사용된다.3. 4. 기타 명령어
NOP 명령어는 아무 작업도 수행하지 않고, 다음 명령어를 가져오는 패치(fetch)만 이루어진 후 다음 단계로 진행된다.[1]3. 4. 1. 인터럽트 명령
EI 명령어는 인터럽트를 처리하도록 설정한다. 이 명령어는 CPU의 특수 레지스터의 특정 비트를 설정한다.[1]DI 명령어는 인터럽트 신호를 무시하도록 설정한다. 이 명령어는 CPU의 특수 레지스터의 특정 비트를 초기화한다.[1]
INT v 명령어는 소프트웨어 인터럽트를 발생시킨다. 일반적으로 인터럽트는 하드웨어에 의해 발생하지만, 소프트웨어 명령어를 통해서도 인터럽트를 발생시킬 수 있다.[1]
x86 아키텍처에서는 `int 10` 명령어를 사용하여 벡터 10 인터럽트를 발생시킬 수 있다.[1]
인터럽트 벡터는 인터럽트의 고유 번호이다. x86 아키텍처의 경우, 메모리의 특정 영역에 ISR(Interrupt Service Routine)의 주소값을 순서대로 저장해 놓고, 각 주소에 대해 벡터를 지정한다. i386은 주소 공간이 32비트이므로 각 ISR 주소는 4바이트로 구성된다. 따라서 인터럽트 벡터로부터 읽어야 할 메모리 주소를 계산할 수 있다. 예를 들어, '벡터 * 4 + 주소 저장 공간 시작 주소'와 같은 방식으로 계산하면 인터럽트 발생 시 읽어야 할 주소를 얻을 수 있다. 이 주소를 읽어 자동으로 해당 ISR로 점프한다.[1]
이와 달리, ARM 아키텍처에서는 특정 주소가 인터럽트 ISR의 주소를 가리키는 방식이다. 해당 주소에는 주소와는 다른 B(branch) 명령어가 있어, 이 명령어를 통해 ISR로 점프한다. B 명령어는 32비트이므로, 정해진 공간에 다른 요소들이 순서대로 연결되어 있다.[1]
3. 4. 2. 입출력 전송 명령
입출력 맵 입출력 방식은 x86 계열에서 사용하는 입출력 전송 명령어이다.- IN : 하드웨어의 레지스터나 입출력 장치의 메모리에서 데이터를 읽는다.
- OUT : 하드웨어의 레지스터나 입출력 장치의 메모리에 데이터를 쓴다.
모토롤라 계열이나 ARM 등의 RISC에서는 주로 메모리 맵 입출력을 사용하므로, 입출력 장치 접근은 메모리 전송 명령어와 구별되지 않는다.
3. 4. 3. 특권 레벨 제어
CPU의 실행 권한을 설정한다. 저사양 CPU에는 없는 기능이지만, 고사양 CPU는 여러 수준의 실행 상태를 가진다. 실행 권한에 따라 실행될 수 있는 기계어가 제한되기도 한다. 운영 체제에서 커널과 응용 프로그램 실행 시 설정된다.CPU 종류 | 권한 레벨 | 설명 |
---|---|---|
x86 | 4레벨 | |
68K | 2레벨 | 유저 레벨, 슈퍼바이저(supervisor) 레벨 |
4. 명령어 집합 구조의 분류
ISA는 복잡도, 명령어 형식, 피연산자 수 등 다양한 기준으로 분류할 수 있다.
ISA는 ''복잡성''에 따라 복합 명령어 집합 컴퓨터(CISC), 축소 명령어 집합 컴퓨터(RISC), 초장 명령어(VLIW) 아키텍처, ''장 명령어''(LIW), ''명시적 병렬 명령어 컴퓨팅(EPIC) 아키텍처, 최소 명령어 집합 컴퓨터(MISC), 단일 명령어 집합 컴퓨터(OISC) 등으로 분류할 수 있다.[5][6]
명령어 집합은 명령어에 명시적으로 지정된 최대 피연산자 수에 따라 분류할 수도 있다.
(''a'', ''b'', ''c''는 메모리 셀을 참조하는 (직접 또는 계산된) 주소이며, ''reg1'' 등은 기계 레지스터를 참조한다.)
C = A+B
피연산자 수 | 설명 | 명령어 예시 | C = A+B 필요 명령어 수 | 예시 | |
---|---|---|---|---|---|
0-피연산자 | 스택 머신이라고 불린다. 모든 산술 연산은 스택의 맨 위 또는 두 개의 위치를 사용하여 수행된다. | push a , push b , add , pop c | 4개[8] | 자바 가상 머신 | |
1-피연산자 | 누산기 머신이라고도 불린다. 초기 컴퓨터와 많은 소형 마이크로컨트롤러가 여기에 해당된다. 대부분의 명령어는 단일 오른쪽 피연산자를 지정하며, 암시적인 누산기를 왼쪽 피연산자(그리고 대상)로 사용한다. | load a , add b , store c | 3개[8] | ||
2-피연산자 | 많은 복합 명령어 집합 컴퓨터(CISC) 및 축소 명령어 집합 컴퓨터(RISC) 머신이 이 범주에 속한다. | ||||
CISC | move A,C ; add B,C 또는load a,reg1 ; add b,reg1 ; store reg1,c | 2개 또는 3개 | |||
RISC | 명시적인 메모리 로드가 필요 | load a,reg1 ; load b,reg2 ; add reg1,reg2 ; store reg2,c | 4개 | ||
3-피연산자 | 데이터의 더 나은 재사용을 허용한다.[8] | ||||
CISC | add a,b,c 또는move a,reg1 ; add reg1,b,c | 1개 또는 2개 | |||
RISC | 산술 명령어는 레지스터만 사용하므로 명시적인 2-피연산자 로드/저장 명령어가 필요 | load a,reg1 ; load b,reg2 ; add reg1+reg2->reg3 ; store reg3,c | 4개 | ||
더 많은 피연산자 | 일부 CISC 머신은 3개 이상의 피연산자를 허용하는 다양한 어드레싱 모드를 허용 |
3-피연산자 명령어를 인코딩하는 데 필요한 많은 비트 때문에 16비트 명령어를 가진 RISC 아키텍처는 TI MSP430 및 일부 버전의 ARM Thumb와 같이 항상 2-피연산자 설계이다. 32비트 명령어를 가진 RISC 아키텍처는 일반적으로 ARM, AVR32, MIPS, Power ISA, SPARC 아키텍처와 같은 3-피연산자 설계이다.
4. 1. 복잡도에 따른 분류
복합 명령어 집합 컴퓨터(CISC)는 다양한 특수 명령어를 가지며, 그 중 일부는 실제 프로그램에서 거의 사용되지 않을 수 있다. 축소 명령어 집합 컴퓨터(RISC)는 프로그램에서 자주 사용되는 명령어만 효율적으로 구현하여 프로세서를 단순화하고, 덜 일반적인 연산은 서브루틴으로 구현한다. 이로 인해 빈번하지 않은 사용으로 발생하는 추가적인 프로세서 실행 시간은 상쇄된다.[3]초장 명령어(VLIW) 아키텍처와 밀접하게 관련된 ''장 명령어''(LIW) 및 ''명시적 병렬 명령어 컴퓨팅(EPIC) 아키텍처는 컴파일러가 명령어 발행 및 스케줄링을 담당하게 함으로써 RISC 및 CISC보다 적은 하드웨어로 명령 수준 병렬성을 활용한다.[4]
최소 명령어 집합 컴퓨터(MISC) 및 단일 명령어 집합 컴퓨터(OISC)와 같이 복잡성이 훨씬 적은 아키텍처도 연구되었으나, 이론적으로 중요한 유형일 뿐 상용화되지는 않았다.[5][6]
높은 코드 밀도를 가진 컴퓨터는 절차 진입, 매개변수화된 반환, 루프 등을 위한 복잡한 명령어를 갖는 경우가 많다. (사후적으로 ''복합 명령어 집합 컴퓨터'', CISC라고 명명됨) "CISC" 명령어는 기본적인 ALU 연산과 주소 지정 방식을 사용하여 메모리에서 하나 이상의 피연산자에 대한 접근을 결합하기도 한다. 특정 아키텍처는 직접 메모리에서 두 개 또는 세 개의 피연산자(결과 포함)를 허용하거나 자동 포인터 증가 등의 기능을 수행할 수 있다.
RISC는 메모리 서브 시스템이 빠르게 성장하는 기간 동안 처음 널리 구현되었다. RISC는 구현 회로를 단순화하기 위해 코드 밀도를 희생하고, 더 높은 클럭 주파수와 더 많은 레지스터를 통해 성능을 향상시키려 한다. 단일 RISC 명령어는 일반적으로 레지스터의 "더하기" 또는 메모리 위치에서 레지스터로의 "로드"와 같은 단일 연산만 수행한다. RISC 명령어 집합은 일반적으로 고정된 명령어 길이를 가지는 반면, 일반적인 CISC 명령어 집합은 길이가 크게 다른 명령어를 갖는다. RISC 컴퓨터는 주어진 작업을 구현하기 위해 더 많고 더 긴 명령어를 필요로 하므로 버스 대역폭과 캐시 메모리를 덜 최적으로 사용한다.
Thumb 및 AVR32와 같은 특정 임베디드 RISC ISA는 코드 압축 기술로 인해 일반적으로 매우 높은 밀도를 나타낸다.
최소 명령어 집합 컴퓨터(MISC)는 스택 머신 형태가 일반적이며, 별도의 명령어가 8~32개 정도로 적어 여러 명령어를 단일 기계어 워드에 맞출 수 있다.
4. 2. 명령어 형식에 따른 분류
축소 명령어 집합 컴퓨터(RISC)는 명령어의 길이가 고정되어 있으며, 이는 해당 아키텍처의 워드 크기와 일반적으로 일치한다. 고정 길이 명령어는 가변 길이 명령어보다 처리하기가 덜 복잡하여 속도 최적화가 쉽다는 장점이 있다.[8] 예를 들어, 명령어가 캐시 라인이나 가상 메모리 페이지 경계를 넘는지 확인할 필요가 없다.[8]반면, 복합 명령어 집합 컴퓨터(CISC)와 같은 다른 아키텍처에서는 명령어의 길이가 가변적이며, 일반적으로 바이트 또는 하프워드의 정수 배수이다. ARM의 ''Thumb 확장''과 같이 혼합된 가변 인코딩을 사용하는 경우도 있는데, 이 경우에는 32비트와 16비트의 두 가지 고정 인코딩을 사용하며, 명령어는 자유롭게 혼합될 수 없고 분기(또는 ARMv8의 예외 경계)에서 전환해야 한다.
4. 3. 피연산자 수에 따른 분류
명령어 집합은 명령어에 명시적으로 지정된 최대 피연산자 수에 따라 분류될 수 있다.(''a'', ''b'', ''c''는 메모리 셀을 참조하는 (직접 또는 계산된) 주소이며, ''reg1'' 등은 기계 레지스터를 참조한다.)
C = A+B
피연산자 수 | 설명 | 명령어 예시 | C = A+B 필요 명령어 수 | 예시 | |
---|---|---|---|---|---|
0-피연산자 | 스택 머신이라고 불린다. 모든 산술 연산은 스택의 맨 위 또는 두 개의 위치를 사용하여 수행된다. | push a , push b , add , pop c | 4개[8] | 자바 가상 머신 | |
1-피연산자 | 누산기 머신이라고도 불린다. 초기 컴퓨터와 많은 소형 마이크로컨트롤러가 여기에 해당된다. 대부분의 명령어는 단일 오른쪽 피연산자(상수, 레지스터 또는 메모리 위치)를 지정하며, 암시적인 누산기를 왼쪽 피연산자(그리고 대상)로 사용한다. | load a , add b , store c | 3개[8] | ||
2-피연산자 | 많은 복합 명령어 집합 컴퓨터(CISC) 및 축소 명령어 집합 컴퓨터(RISC) 머신이 이 범주에 속한다. | ||||
CISC | move A,C ; add B,C (명시적 저장 명령어 없이 결과를 저장) 또는load a,reg1 ; add b,reg1 ; store reg1,c (모든 메모리 이동에 로드/저장 쌍 필요) | 2개 또는 3개 | |||
RISC | 명시적인 메모리 로드가 필요 | load a,reg1 ; load b,reg2 ; add reg1,reg2 ; store reg2,c | 4개 | ||
3-피연산자 | 데이터의 더 나은 재사용을 허용한다.[8] | ||||
CISC | add a,b,c (단일 명령어) 또는move a,reg1 ; add reg1,b,c (명령어당 두 개의 메모리 피연산자로 제한) | 1개 또는 2개 | |||
RISC | 산술 명령어는 레지스터만 사용하므로 명시적인 2-피연산자 로드/저장 명령어가 필요 | load a,reg1 ; load b,reg2 ; add reg1+reg2->reg3 ; store reg3,c | 4개 | ||
더 많은 피연산자 | 일부 CISC 머신은 VAX "POLY" 다항식 평가 명령어와 같이 3개 이상의 피연산자(레지스터 또는 메모리 접근)를 허용하는 다양한 어드레싱 모드를 허용 |
3-피연산자 명령어를 인코딩하는 데 필요한 많은 비트 때문에 16비트 명령어를 가진 RISC 아키텍처는 Atmel AVR, TI MSP430 및 일부 버전의 ARM Thumb와 같이 항상 2-피연산자 설계이다. 32비트 명령어를 가진 RISC 아키텍처는 일반적으로 ARM, AVR32, MIPS, Power ISA, SPARC 아키텍처와 같은 3-피연산자 설계이다.
각 명령어는 (레지스터, 메모리 위치 또는 즉시 값) 피연산자 수를 ''명시적으로'' 지정한다. 일부 명령어는 암시적으로 하나 또는 두 개의 피연산자를 제공한다(예: 스택의 맨 위에 저장되거나 암시적 레지스터에 저장됨). 일부 피연산자가 암시적으로 제공되는 경우, 명령어에 지정해야 하는 피연산자가 더 적다. "대상 피연산자"가 대상을 명시적으로 지정하는 경우 추가 피연산자를 제공해야 한다. 결과적으로, 명령어에 인코딩된 피연산자 수는 논리 또는 산술 연산에 필요한 수학적 인수 수(항수)와 다를 수 있다. 피연산자는 명령어의 "opcode" 표현으로 인코딩되거나 opcode 다음에 오는 값 또는 주소로 제공된다.
5. 명령어 집합 구조의 설계 및 구현
명령어 집합 구조는 특정 프로세서에서 명령어 집합을 구현하는 데 사용되는 일련의 프로세서 설계 기술인 마이크로아키텍처와 구별된다. 서로 다른 마이크로아키텍처를 가진 프로세서는 공통 명령어 집합을 공유할 수 있다. 예를 들어, 인텔 펜티엄과 AMD 애슬론은 거의 동일한 버전의 x86 명령어 집합을 구현하지만 내부 설계는 근본적으로 다르다.[2]
Smalltalk, 자바 가상 머신, 마이크로소프트의 공용 언어 런타임과 같이 바이트 코드를 ISA로 지원하는 일부 가상 머신은 일반적으로 사용되는 코드 경로에 대한 바이트 코드를 네이티브 머신 코드로 변환하여 이를 구현한다. 또한, 이러한 가상 머신은 덜 사용되는 코드 경로를 인터프리테이션 방식으로 실행한다(참조: JIT). 트랜스메타는 이러한 방식으로 VLIW 프로세서 위에 x86 명령어 집합을 구현했다.
고속 디지털 신호 처리의 요구 사항은 특정 방식으로 명령어를 구현하도록 강요한다. 예를 들어, 디지털 필터를 충분히 빠르게 수행하려면, 일반적인 디지털 신호 프로세서 (DSP)의 MAC 명령어는 명령어와 두 개의 데이터 워드를 동시에 페치할 수 있는 일종의 하버드 아키텍처를 사용해야 하며, 단일 사이클 곱셈-누산 곱셈기가 필요하다.
5. 1. 설계
명령어 집합 설계는 복잡한 문제이다. 마이크로아키텍처와 구별되는 ''아키텍처''의 개념은 프레드 브룩스가 IBM System/360의 설계 단계에서 개발했다.[2]초기 컴퓨터는 메모리가 제한적이었기 때문에 코드 밀도(특정 작업을 수행하는 데 필요한 명령어 크기)가 중요했다. 높은 코드 밀도를 가진 컴퓨터는 복잡한 명령어를 갖는 경우가 많았으며(사후적으로 ''CISC''라고 명명됨), RISC는 코드 밀도를 희생하여 구현 회로를 단순화하고 성능을 향상시키려 했다. 특정 임베디드 RISC ISA는 코드 압축 기술로 인해 매우 높은 밀도를 나타낸다.[12] MISC의 코드 밀도는 RISC와 유사하지만, 작업을 수행하기 위해 더 많은 원시 명령어가 필요하다.[13]
실제로 코드 밀도는 컴파일러에도 의존한다. GCC과 같은 최적화 컴파일러는 코드 생성을 실행 속도 또는 코드 밀도에 맞게 최적화하는 옵션을 제공한다.
마이크로프로세서 역사에는 CISC와 RISC 두 단계가 있었다. CISC는 다양한 명령어를 가졌지만, 연구 결과 더 적은 수의 명령어를 사용하는 RISC 아키텍처가 더 높은 속도, 축소된 프로세서 크기, 전력 소비 감소를 가능하게 한다는 것을 발견했다. 그러나 더 복잡한 집합은 일반적인 연산을 최적화하고, 메모리 및 캐시 효율성을 향상시키거나, 프로그래밍을 단순화할 수 있다.
일부 명령어 집합 설계자는 시스템 콜 또는 소프트웨어 인터럽트를 위해 하나 이상의 opcode를 예약한다. 명령어 집합이 Popek and Goldberg 가상화 요구 사항을 충족하면 빠른 가상 머신을 구현하기 쉽다. 또한, 명령어 집합이 "fetch-and-add", "load-link/store-conditional"(LL/SC) 또는 원자적 compare-and-swap과 같은 것을 지원하면 비차단 동기화 알고리즘을 구현하기가 훨씬 쉽다.
5. 2. 구현
명령어 집합은 다양한 방식으로 구현될 수 있다. 특정 명령어 집합을 구현하는 모든 방식은 동일한 프로그래밍 모델을 제공하며, 해당 명령어 집합의 모든 구현은 동일한 실행 파일을 실행할 수 있다. 명령어 집합을 구현하는 다양한 방식은 비용, 성능, 전력 소비, 크기 등에서 서로 다른 균형점을 제공한다.프로세서의 마이크로아키텍처를 설계할 때, 엔지니어는 가산기, 멀티플렉서, 카운터, 레지스터, ALU 등과 같은 "하드 와이어드" 전자 회로 블록(별도로 설계되는 경우가 많음)을 사용한다. 그런 다음, 레지스터 전송 언어를 사용하여 이 물리적 마이크로아키텍처에서 ISA의 각 명령어의 디코딩 및 시퀀싱을 설명한다.
제어 장치를 구축하는 데는 두 가지 기본적인 방법이 있다(많은 설계에서 중간 방식 또는 절충점을 사용한다).
1. 일부 컴퓨터 설계는 전체 명령어 집합 디코딩 및 시퀀싱을 (나머지 마이크로아키텍처와 마찬가지로) "하드와이어"한다.
2. 다른 설계는 마이크로코드 루틴 또는 테이블(또는 둘 다)을 사용하여 이 작업을 수행하며, ROM, 쓰기 가능한 RAM(쓰기 가능한 제어 저장소), PLA 또는 둘 다를 사용한다.
쓰기 가능한 제어 저장소가 있는 일부 마이크로코드 CPU 설계는 이를 사용하여 명령어 집합을 변경할 수 있도록 한다.[15]
재구성 가능 컴퓨팅용으로 설계된 CPU는 필드 프로그래머블 게이트 어레이 (FPGA)를 사용할 수 있다.
ISA는 또한 에뮬레이터를 통해 소프트웨어에서 인터프리터로 에뮬레이션될 수 있다. 해석 오버헤드 때문에 에뮬레이터를 실행하는 하드웨어가 한 단계 더 빠르지 않다면, 에뮬레이션된 하드웨어에서 직접 프로그램을 실행하는 것보다 느리다. 오늘날에는 새로운 ISA 또는 마이크로아키텍처의 공급업체가 하드웨어 구현이 준비되기 전에 소프트웨어 개발자에게 소프트웨어 에뮬레이터를 제공하는 것이 일반적이다.
구현의 세부 사항은 종종 명령어 집합에 대해 선택된 특정 명령어에 강한 영향을 미친다. 예를 들어, 명령어 파이프라인의 많은 구현은 명령어당 단일 메모리 로드 또는 메모리 저장을 허용하므로 로드-스토어 아키텍처 (RISC)가 된다.
6. 한국의 IT 산업과 명령어 집합 구조
(이전 출력이 비어있으므로, 수정할 내용이 없습니다. 따라서 이전 출력과 동일하게 빈칸으로 출력합니다.)
참조
[1]
웹사이트
GLOSSARY: Instruction Set Architecture (ISA)
https://www.arm.com/[...]
2024-02-03
[2]
서적
IBM's 360 and Early 370 Systems
https://archive.org/[...]
MIT Press
[3]
웹사이트
RISC Architecture: RISC vs. CISC
https://web.archive.[...]
2006-12-16
[4]
간행물
EPIC: Explicitly Parallel Instruction Computing
2000-02
[5]
간행물
On the Classification of Computer Architecture
https://www.research[...]
2003
[6]
서적
Computer Architecture: A Minimalist Perspective
Springer Science+Business Media
2012-12-06
[7]
웹사이트
Instruction Set Architecture (ISA)
http://www.cs.kent.e[...]
[8]
간행물
The evolution of RISC technology at IBM
https://www.cis.upen[...]
1990-01
[9]
서적
A Practical Introduction to Computer Architecture
Springer
[10]
conference
Harnessing ISA Diversity: Design of a Heterogeneous-ISA Chip Multiprocessor
http://dl.acm.org/ci[...]
[11]
웹사이트
Intel® 64 and IA-32 Architectures Software Developer's Manual
https://www.intel.co[...]
Intel Corporation
2022-10-05
[12]
conference
Code density concerns for new architectures
[13]
웹사이트
RISC vs. CISC
https://cs.stanford.[...]
2021-12-18
[14]
웹사이트
Proactive Debugging
https://www.embedded[...]
2001-02-26
[15]
웹사이트
Great Microprocessors of the Past and Present (V 13.4.0)
http://cpushack.net/[...]
2014-07-25
[16]
웹인용
Instruction set architecture
https://en.wikipedia[...]
[17]
문서
Intel 80386 Programmer's Reference Manual
Intel Co.
1986
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com