ABOUT

성능과 운영 안정성을 함께 끌어올리는 개발자입니다.

92% Positional Error Reduction
79% p95 Latency Improvement
90%+ Long Tasks Reduction

2022.02 · 한국장학재단

우수 멘티

한국장학재단 사회 리더 대학생 멘토링 IT

2022.10 · 동작구청

우수 인재상

동작구청 우수 SW 인재

2025.05 · (주) 그랩

프로그래밍 우수상

(주) 그랩 우수 프로그램 개발

2025.05 · AWSKRUG

AWS한국사용자모임 발표

AI agent 스크립트 튜닝 관련 발표

ComputerScience

Development

Engineering

Trouble Shooting

GUESTBOOK

첫 마음부터
함께 나누는 온기

방명록 작성하러 가기

SUBSCRIBE

최신소식을
편하게 만나보세요.

ISA (Instruction Set Architecture)

도입

ISA는 소프트웨어와 CPU 사이에서 “어떤 명령을 이해하고 어떤 규칙으로 실행할 것인가”를 정의하는 공식적인 실행 계약이다

프로그램이 실제로 CPU에서 실행되려면, 프로세서는 프로그램이 담고 있는 명령을 해석할 수 있어야 합니다. 이때 CPU가 어떤 명령어를 지원하는지, 어떤 레지스터를 제공하는지, 메모리를 어떤 방식으로 다루는지, 예외나 분기를 어떻게 처리하는지를 정한 규칙이 바로 ISA (Instruction Set Architecture)입니다.

즉, ISA는 단순히 명령어 목록만 뜻하는 것이 아니라, 소프트웨어가 하드웨어를 어떻게 볼 수 있는지 정의하는 인터페이스입니다. 컴파일러는 이 규칙을 기준으로 기계어를 만들고, 운영체제는 이 규칙을 기준으로 프로세스를 관리하며, CPU는 이 규칙에 맞춰 명령을 실행합니다.

필요성

ISA를 이해하면 왜 같은 소스 코드가 x86과 ARM에서 다르게 컴파일되는지, 왜 어떤 바이너리는 특정 CPU에서만 실행되는지가 구조적으로 설명된다

ISA는 컴파일러, 운영체제, 디버거, 바이너리 도구가 모두 의존하는 공통 기준입니다. 그래서 ISA를 이해하면 소스 코드가 기계어로 바뀌는 과정, 바이너리 호환성, 레지스터 기반 실행, 분기와 메모리 접근의 구조를 더 명확하게 볼 수 있습니다.

ISA 이해가 특히 중요한 분야
  • 컴파일러와 어셈블러 동작 이해
  • 운영체제와 시스템 콜 구조 이해
  • 바이너리 호환성과 크로스 컴파일
  • 리버스 엔지니어링과 보안 분석
  • 성능 최적화와 저수준 디버깅
  • 임베디드 시스템과 펌웨어 개발

정의

ISA는 CPU가 외부에 공개하는 명령어·레지스터·메모리 접근 규칙의 집합이며, 소프트웨어가 의존할 수 있는 프로세서의 공식 사양이다

여기서 핵심은 ISA가 소프트웨어에서 보이는 CPU의 모습이라는 점입니다. 즉, 내부적으로 CPU가 얼마나 복잡하게 구현되었는지는 몰라도, 소프트웨어는 ISA가 약속한 명령어와 레지스터 모델을 기준으로 프로그램을 작성하고 컴파일합니다.

항목 ISA가 정의하는가 예시
명령어 ADD, LOAD, STORE, JMP
레지스터 모델 범용 레지스터 개수와 이름 체계
메모리 접근 방식 load/store 규칙, addressing mode
예외 / 특권 명령 trap, interrupt, privileged instruction
파이프라인 깊이 아니오 구현마다 다름
캐시 크기 아니오 마이크로아키텍처 차이

왜 “계약”이라고 부르는가

ISA는 소프트웨어가 기대하는 동작과 CPU가 반드시 보장해야 하는 동작을 연결하는 약속이기 때문에, 시스템 설계에서는 흔히 “계약”에 비유된다

컴파일러는 ISA 문서를 기준으로 “이 명령을 이런 바이너리로 인코딩하면 CPU가 이렇게 동작한다”고 믿고 코드를 생성합니다. CPU 제조사는 그 ISA를 구현해, 해당 바이너리를 실제로 약속된 의미대로 실행해야 합니다. 이 때문에 ISA는 소프트웨어와 하드웨어 사이의 공통 언어라고도 설명됩니다.

핵심 포인트
같은 ISA를 정확히 구현한 CPU라면, 적어도 해당 ISA 수준에서 정의된 명령 의미는 동일해야 합니다. 그래서 ISA는 바이너리 호환성의 출발점이 됩니다.

핵심 구성 요소

ISA는 단순히 opcode 목록만 모아 둔 것이 아니라, 레지스터 구조와 메모리 모델과 시스템 수준 제어까지 포함하는 소프트웨어 가시적 규칙의 묶음이다
구성 요소 의미 왜 중요한가
명령어 집합 CPU가 이해하는 연산 종류 컴파일러가 어떤 기계어를 만들 수 있는지 결정
레지스터 집합 소프트웨어가 사용할 수 있는 내부 저장소 코드 생성과 호출 규약에 직접 영향
데이터 크기와 형식 정수, 부동소수점, 벡터 연산 단위 연산 정확도와 성능 특성에 영향
Addressing Mode 피연산자를 어떻게 해석할지 정하는 방식 메모리 접근 표현력과 코드 밀도에 영향
메모리 규칙 정렬, 접근 규칙, 메모리 모델 등 멀티스레드와 시스템 코드 안정성에 중요
특권 / 예외 모델 운영체제 모드와 예외 처리 규칙 시스템 콜, 인터럽트, 보호 구조의 기반
확장 명령 SIMD, 벡터, 암호화 같은 추가 기능 특정 워크로드에서 성능을 크게 좌우

명령어 형식

ISA는 “어떤 연산을 할지”뿐 아니라 그 연산을 비트 수준에서 어떤 형식으로 인코딩할지까지 규정한다

하나의 명령어는 보통 연산 종류를 나타내는 opcode와, 대상 레지스터나 메모리 위치를 나타내는 operand, 그리고 경우에 따라 상수값이나 오프셋 같은 추가 정보를 담습니다. ISA는 이 요소들을 어떤 규칙으로 배치할지 정의합니다.

[ opcode ][ register ][ register ][ immediate / offset ]

모든 ISA가 같은 형식을 쓰는 것은 아닙니다. 어떤 ISA는 고정 길이 명령어를 선호하고, 어떤 ISA는 가변 길이 명령어를 허용합니다. 이 차이는 디코딩 난이도, 코드 크기, 하드웨어 복잡도에 직접 영향을 줍니다.

주소 지정 방식

ISA에서 중요한 것은 값을 어디서 가져오느냐보다, 그 값을 어떤 규칙으로 해석하느냐이며 이것이 addressing mode로 드러난다

같은 명령이라도 피연산자를 즉시값으로 볼지, 레지스터 값으로 볼지, 메모리 주소로 볼지에 따라 의미가 달라집니다. 이 규칙을 ISA가 정의합니다.

방식 의미 개념 예시
Immediate 명령어 안에 값이 직접 들어 있음 ADD R1, 5
Register 레지스터 값을 사용 ADD R1, R2
Register Indirect 레지스터가 가리키는 주소의 메모리를 사용 LOAD R1, [R2]
Base + Offset 기준 주소에 변위를 더한 위치 접근 LOAD R1, [R2 + 16]
PC-relative 현재 명령 위치 기준 상대 주소 사용 JMP label

명령어 종류

ISA를 실제로 보면 수많은 명령이 있지만, 기능적으로는 데이터 이동, 연산, 제어 흐름, 시스템 제어 같은 몇 가지 큰 범주로 정리할 수 있다
  • 데이터 이동 → register 간 이동, load/store, push/pop
  • 산술 / 논리 연산 → add, sub, and, or, xor, shift
  • 비교와 분기 → cmp, branch, jump, call, return
  • 부동소수점 / 벡터 연산 → floating-point, SIMD, vector instruction
  • 시스템 제어 → trap, interrupt, privileged instruction
  • 동기화 / 원자 연산 → atomic increment, compare-and-swap 등

이 분류는 고급 언어 코드가 실제로 어떤 종류의 기계 명령으로 분해되는지 이해하는 데 매우 유용합니다. 예를 들어 if 문은 비교와 분기 명령으로, 배열 접근은 주소 계산과 load/store 명령으로 내려갑니다.

자주 헷갈리는 개념과의 차이

ISA를 정확히 이해하려면 CPU 아키텍처, 마이크로아키텍처, ABI와의 경계를 먼저 분명히 해야 한다
개념 무엇을 뜻하나 ISA와의 관계
CPU 아키텍처 CPU 전체 설계 개념 ISA보다 넓게 쓰이는 경우가 많음
ISA 소프트웨어가 보는 명령어·레지스터 규칙 외부에 보이는 공식 인터페이스
마이크로아키텍처 ISA를 내부에서 실제 구현하는 방법 파이프라인, 캐시, 실행 유닛 수 등
ABI 함수 호출 규약, 바이너리 인터페이스 ISA 위에서 OS/툴체인이 정하는 규칙

예를 들어 “함수 인자를 어느 레지스터에 담는가”는 ISA만의 문제가 아니라 보통 ABI와 함께 정해집니다. 반면 “그 레지스터가 존재하는가”는 ISA의 문제입니다. 이 차이를 구분하면 시스템 소프트웨어 문서를 훨씬 정확히 읽을 수 있습니다.

소프트웨어와의 관계

ISA는 컴파일러가 기계어를 생성하는 기준이자, 운영체제가 프로세서 기능을 제어하는 기준이며, 디버거가 실행 상태를 해석하는 기준이기도 하다

고급 언어의 소스 코드는 직접 실행되지 않습니다. 컴파일러는 타깃 ISA에 맞는 명령어를 선택해 기계어를 만들고, 어셈블러와 링커는 이를 실행 가능한 바이너리로 구성합니다. 운영체제는 같은 ISA가 제공하는 특권 명령, 예외, 주소 변환 구조를 이용해 프로세스를 보호하고 스케줄링합니다.

고급 언어 코드
   ↓
컴파일러
   ↓
타깃 ISA 기준 기계어 생성
   ↓
어셈블 / 링크
   ↓
바이너리 실행
   ↓
CPU가 ISA 규칙대로 해석

다만 같은 ISA라고 해서 모든 바이너리가 무조건 서로 호환되는 것은 아닙니다. 운영체제, ABI, 실행 파일 형식까지 함께 맞아야 실제 실행 호환성이 성립하는 경우가 많습니다.

예시

같은 “덧셈”이라는 개념도 ISA가 달라지면 레지스터 이름과 피연산자 배치와 기계어 인코딩 방식이 모두 달라진다

아래 예시는 동일한 의미의 연산이 ISA별로 어떻게 다른 표현을 가질 수 있는지 보여 주는 개념 예시입니다.

[고급 언어]
c = a + b;

[x86-64 개념 예시]
add eax, ebx        // eax = eax + ebx 형태

[ARM64 개념 예시]
add w0, w1, w2      // w0 = w1 + w2 형태

[RISC-V 개념 예시]
add x10, x11, x12   // x10 = x11 + x12 형태

이처럼 “덧셈”이라는 연산의 의미는 비슷해도, 어떤 레지스터를 쓰는지, 목적지와 원본을 어떻게 배치하는지, 명령어를 몇 비트로 인코딩하는지는 ISA마다 달라집니다.

대표 ISA 계열

ISA는 하나의 보편 언어가 아니라 여러 계열로 나뉘며, 각 계열은 다른 설계 철학과 생태계를 바탕으로 발전해 왔다
  • x86-64 → 데스크톱과 서버에서 매우 강한 호환성과 긴 역사를 가진 ISA
  • ARM / AArch64 → 모바일, 임베디드, 저전력 환경에서 강하고 최근 범용 컴퓨팅에서도 영향력이 큰 ISA
  • RISC-V → 개방형 ISA로 교육, 연구, 임베디드, 맞춤형 설계에서 주목받는 계열

이 계열들은 단순한 문법 차이가 아니라, 역사적 호환성 전략, 확장 방식, 생태계, 툴체인, 타깃 시장까지 다르게 발전해 왔습니다.

RISC와 CISC 관점

ISA를 비교할 때 자주 나오는 관점이 RISC와 CISC이지만, 현대 CPU에서는 이 구분을 철학적 경향으로 보는 편이 더 정확하다
구분 RISC 경향 CISC 경향
기본 철학 명령어를 단순하고 규칙적으로 설계 더 다양한 고수준 기능을 명령어에 포함
설계 경향 파이프라인과 단순 디코딩에 유리한 방향 높은 표현력과 호환성 중시
대표 예시 ARM, RISC-V x86 계열

다만 현대 CPU는 내부적으로 명령을 더 작은 마이크로 연산으로 쪼개 실행하기도 하므로, RISC와 CISC를 절대적인 성능 비교 기준으로 단순화하는 것은 적절하지 않습니다.

자주 하는 오해

ISA를 처음 배울 때는 명령어 목록만 외우거나, CPU 내부 구현과 동일한 개념으로 착각하는 경우가 많다
  • ISA = 어셈블리 문법이라고 생각함 → 문법은 표현 방식이고, ISA는 그 아래의 실행 규칙까지 포함합니다.
  • ISA = CPU 내부 구조 전체라고 생각함 → 파이프라인, 캐시, 실행 유닛 수는 마이크로아키텍처 문제입니다.
  • 같은 ISA면 무조건 같은 성능이라고 생각함 → 구현 방식에 따라 성능 차이는 매우 큽니다.
  • 같은 ISA면 모든 바이너리가 어디서나 실행된다고 생각함 → OS와 ABI와 실행 파일 형식도 맞아야 합니다.
  • ISA는 명령어 개수만 많고 적은 문제라고 생각함 → 레지스터, 주소 지정, 예외 모델, 확장 구조도 중요합니다.
  • RISC는 무조건 빠르고 CISC는 무조건 느리다고 생각함 → 현대 구현은 훨씬 복합적입니다.

공부 루틴

ISA를 공부할 때는 어셈블리 문법을 외우기보다, 소프트웨어가 CPU를 어떤 모델로 보는지를 중심으로 단계적으로 이해하는 방식이 가장 효과적이다
  1. 기계어와 어셈블리어 관계부터 먼저 이해한다.
  2. 명령어, 레지스터, addressing mode를 핵심 축으로 잡는다.
  3. 한 개의 ISA를 정해 짧은 예제를 반복해서 본다.
  4. ISA와 마이크로아키텍처, ABI를 분리해서 이해한다.
  5. 같은 고급 언어 코드가 서로 다른 ISA에서 어떻게 달라지는지 비교해 본다.
  6. 디스어셈블 결과를 보면서 명령어 의미와 상태 변화를 추적하는 연습을 한다.

디버깅과 분석 포인트

ISA 관점에서 코드를 분석할 때는 명령어 이름보다도 레지스터 변화와 메모리 접근 규칙과 분기 의미를 정확히 읽는 것이 더 중요하다
1
현재 보고 있는 바이너리가 어느 ISA를 기준으로 만들어졌는지 먼저 확인한다.
2
명령어를 볼 때 목적지 레지스터와 원본 레지스터의 순서를 정확히 해석한다.
3
메모리 접근 명령이라면 addressing mode를 먼저 읽어야 한다.
4
분기 명령은 플래그, 비교 결과, 상대 주소 계산까지 함께 봐야 정확하다.
5
함수 호출 규약 문제인지, ISA 자체 문제인지, ABI 문제인지 구분해 접근한다.

요약

ISA는 소프트웨어가 CPU를 이해하는 공식 인터페이스이며, 명령어와 레지스터와 메모리 접근과 시스템 제어 규칙을 통해 실행 가능한 컴퓨팅의 공통 언어를 제공한다
  • ✅ ISA는 CPU가 외부에 공개하는 명령어·레지스터·메모리 규칙의 집합이다.
  • ✅ 컴파일러와 운영체제와 CPU가 모두 의존하는 공통 실행 계약이다.
  • ✅ ISA는 명령어뿐 아니라 addressing mode, 특권 명령, 예외 모델 같은 규칙도 포함한다.
  • ✅ 마이크로아키텍처는 ISA를 실제로 구현하는 내부 구조이며, ISA와 구분해야 한다.
  • ✅ 같은 고급 언어 코드라도 타깃 ISA가 다르면 생성되는 기계어는 달라진다.
  • ✅ x86-64, ARM, RISC-V 같은 대표 ISA는 서로 다른 설계 철학과 생태계를 가진다.
728x90