기계어
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
기계어는 컴퓨터의 중앙 처리 장치(CPU)가 직접 실행할 수 있는 이진 코드 형태의 명령어 집합이다. 각 프로세서 또는 프로세서 계열은 고유한 명령어 집합을 가지며, 명령어는 연산 종류, 피연산자, 어드레싱 모드 등을 포함한다. 기계어는 어셈블리 언어보다 하위 수준이며, 어셈블러를 통해 어셈블리 언어로 변환하거나 디스어셈블러를 통해 어셈블리 언어로 역변환할 수 있다. 기계어는 CPU의 작동을 위한 기본 요소이지만, 현대에는 컴파일러, 어셈블러, 고급 언어의 발달로 인해 직접 다루는 경우는 드물며, 임베디드 시스템, 하드웨어 엔지니어, CPU 개발자 등 특정 분야에서 사용된다.
더 읽어볼만한 페이지
- 저급 프로그래밍 언어 - 어셈블리어
어셈블리어는 사람이 이해하기 쉬운 니모닉 기호로 기계어 명령을 표현하는 저수준 프로그래밍 언어로서, 각 프로세서마다 사양이 다른 어셈블리어가 존재하며 하드웨어 직접 제어, 성능 최적화, 저수준 시스템 프로그래밍 등에 활용된다. - 어셈블리어 - 주소 지정 방식
- 어셈블리어 - 웹어셈블리
웹어셈블리는 웹 브라우저에서 네이티브에 가까운 성능으로 코드를 실행하기 위해 설계된 이식 가능한 가상 스택 머신을 위한 명령어 집합으로, 다양한 프로그래밍 언어를 지원하며 웹 브라우저 환경을 넘어 다양한 분야에서 활용되고, 바이너리 및 텍스트 형식을 지원하며 성능, 보안, 이식성을 목표로 한다. - 기계어 - 브랜치 (컴퓨터 과학)
프로그램 실행 흐름을 제어하는 명령어인 브랜치는 점프, 호출, 반환 명령어로 나뉘며, CPU 플래그 레지스터와 주소 지정 방식을 활용하여 코드 분기 및 서브루틴 호출/반환을 수행하지만, 파이프라인 CPU에서 성능 저하를 유발하여 분기 예측 등의 기술로 해결합니다. - 기계어 - 주소 지정 방식
기계어 | |
---|---|
일반 정보 | |
![]() | |
유형 | 저수준 프로그래밍 언어 |
특징 | CPU에서 직접 실행 가능 하드웨어에 종속적 사람이 읽기 어려움 |
표현 | |
표현 방법 | 2진수 16진수 |
구성 요소 | |
구성 요소 | 연산 코드 (opcode) 피연산자 (operand) |
사용 | |
사용 목적 | 직접적인 하드웨어 제어 시스템 프로그래밍 임베디드 시스템 개발 역공학 |
장점 및 단점 | |
장점 | 실행 속도 빠름 하드웨어 자원 직접 제어 |
단점 | 프로그래밍 복잡 플랫폼 의존성 높음 가독성 낮음 |
예시 | |
예시 | 00000001 11100010 00000000 00000011 (덧셈 명령어) B8 0A00 0000 (x86 MOV 명령어) |
2. 명령어 집합
모든 프로세서는 고유한 명령어 집합을 가진다. 명령어는 기계 명령에 해당하는 비트, 숫자 또는 문자의 패턴으로 표현된다. 따라서 명령어 집합은 대부분 동일한 아키텍처를 사용하는 특정 클래스의 프로세서에 특화되어 있다. 후속 프로세서 설계는 이전 프로세서의 명령어를 포함하고 새로운 명령어를 추가할 수 있지만, 때때로 일부 명령어 코드의 의미를 중단하거나 변경하여 코드 호환성에 영향을 미치기도 한다.[9][8]
프로세서의 명령어 집합은 명령어 유형(예: 산술, 논리, 점프 등), 연산(예: 더하기, 비교), 피연산자 유형, 어드레싱 모드, 오프셋, 인덱스, 피연산자 값 자체 등을 지정하는 연산 코드 필드를 포함한다.
누산기를 사용하는 기계에서는 누산기가 대부분 산술 명령어에서 왼쪽 피연산자이자 결과로 암묵적으로 사용된다. x86 아키텍처와 같은 일부 아키텍처는 일반적인 명령어의 누산기 버전을 가지며, 누산기는 더 긴 명령어에서 일반 레지스터 중 하나로 간주된다. 스택 머신은 대부분 또는 모든 피연산자를 암묵적 스택에 가지고 있다. 특수 목적 명령어는 명시적 피연산자가 없는 경우도 있다(예: x86 아키텍처의 CPUID).
2. 1. 명령어 형식
프로세서의 명령어 집합은 고정 길이 또는 가변 길이 명령어를 가질 수 있다. 명령어 패턴은 특정 아키텍처 및 명령어 유형에 따라 다르게 구성된다. 대부분의 명령어에는 연산 코드, 피연산자 유형, 어드레싱 모드, 오프셋, 인덱스 또는 피연산자 값 자체를 지정하는 하나 이상의 필드가 있다.MIPS 아키텍처는 명령어가 항상 32비트 길이인 기계어의 구체적인 예시를 제공한다. 명령어는 R-type, I-type, J-type으로 구분된다.
유형 | 6비트 | 5비트 | 5비트 | 5비트 | 5비트 | 6비트 |
---|---|---|---|---|---|---|
R-type | op | rs | rt | rd | shamt | funct |
I-type | op | rs | rt | address/immediate | ||
J-type | op | target address |
- '''op''': 연산(operation)
- '''rs''', '''rt''', '''rd''': 레지스터 피연산자
- '''shamt''': 시프트 양
- '''address''', '''immediate''': 주소 또는 즉시 값
- '''funct''': 기능 (R-type에서 연산 코드를 보충)
예를 들어, 레지스터 1과 2를 더하여 레지스터 6에 저장하는 R-type 명령어는 다음과 같이 인코딩된다.
- 십진수: `0 1 2 6 0 32`
- 이진수: `000000 00001 00010 00110 00000 100000`
IBM 704, 709, 704x 및 709x는 각 명령어 단어에 하나의 명령어를 저장한다. 명령어는 대부분 다음 두 가지 형식 중 하나를 갖는다.
- 일반 명령어
- S, 1-11 비트: 연산 코드
- 12-13 비트: 플래그 (일부 명령어에서는 무시됨)
- 14-17 비트: 미사용
- 18-20 비트: 태그
- 21-35 비트: Y (주소)
- 인덱스 레지스터 제어 명령어 (TSX 제외)
- S, 1-2 비트: 연산 코드
- 3-17 비트: 감소
- 18-20 비트: 태그
- 21-35 비트: Y (주소)
유효 주소는 일반적으로 Y-C(T)이며, 여기서 C(T)는 태그에 따라 결정된다. 인덱스 레지스터 제어 명령어의 유효 주소는 Y이다. 플래그 비트(12-13)가 모두 1이면 간접 주소 지정을 사용한다.
3. 어셈블리 언어
어셈블리 언어는 기계어를 사람이 이해하기 쉬운 니모닉 코드를 사용하여 나타내고, 심볼릭 이름을 사용하여 저장 위치와 레지스터를 참조하여 사람이 좀 더 쉽게 이해할 수 있도록 만든 형태이다. 예를 들어, Zilog Z80 프로세서에서 CPU가 `B` 범용 레지스터의 값을 감소시키는 기계어 코드 `00000101`는 어셈블리 언어에서 DEC B
로 표현된다.
기계어는 0/1의 조합이나 16진수 표기이기 때문에 다루기 어려우므로, 대신 어셈블리어를 사용하는 것이 일반적이다. 어셈블리어는 프로그래밍 언어 중에서 기계어에 가장 가까우며, 기계어와 거의 1대 1로 대응하고, 인간이 이해하기 쉬운 니모닉으로 작성할 수 있다.
어셈블러는 어셈블리어로 작성된 프로그램을 기계어로 변환하는 소프트웨어이다. 반대로 디스어셈블러는 기계어 프로그램(기계어 코드)을 어셈블리어로 변환하는 소프트웨어이다. 어셈블러와 디스어셈블러를 사용하면 기계어와 어셈블리어 간의 변환을 자유롭게 수행할 수 있다.
사람이 직접 어셈블 작업을 수행하는 것을 핸드 어셈블이라고 한다. 컴퓨터 초기에는 핸드 어셈블이 자주 수행되었지만, CPU가 16비트, 32비트, 64비트로 발전하면서 최근에는 거의 수행되지 않는다. 1970년대 후반 마이크로컴퓨터와 1980년대 초반 퍼스널 컴퓨터 등장 당시, 어셈블러가 고가여서 개인 사용자는 핸드 어셈블을 하는 경우가 많았다.
기본적으로 어셈블리어는 기계어와 1대 1로 대응하지만, 간단한 매크로 등을 갖춘 예외도 있으며, 지연 슬롯을 이용하는 코드로 자동 변형되는 기능을 가진 것도 있다.
CASL의 페이퍼 머신 COMET에 관한 정보 처리 기술자 시험 출제 범위 자료에서, 처리계 작성자 편의를 위해 정의 뒤에 붙어 있는 참고 자료(정의는 아님)에 따른 기계어의 예는 아래와 같다.
주소 | 기계어 (16진수 표시) | CASL | ||
---|---|---|---|---|
valign="top" | | valign="top" | | valign="top" | | valign="top" | | valign="top" | |
4. 기계어의 구성
구성 요소 | 설명 |
---|---|
명령부 (오퍼코드) | CPU에 처리를 지시하기 위한 명령 번호이다. |
주소부 (오퍼랜드) | 처리할 데이터가 저장된 위치, 연산 결과 저장 위치, 레지스터, 점프 대상 등을 나타낸다. 즉시값도 여기에 포함될 수 있다. 명령어에 따라 개수와 길이가 다르며, 오퍼랜드 수에 따라 0 주소 방식, 1 주소 방식, 2 주소 방식, 3 주소 방식으로 나뉜다. 0 주소 방식은 오퍼레이션 코드만 있고 오퍼랜드는 없다. |
즉시값 | 오퍼랜드의 일부로 포함되기도 한다. 연산에 사용되는 정수 값 등의 데이터가 명령 뒤에 이어진다. |
데이터부 | 실행되지 않는 부분이다. 즉시값에 포함되지 않는 상수 데이터(문자열 리터럴 등), 전역 변수(기계어/어셈블리 언어 용어로 워크 영역), 힙 영역, 지역 변수 스택 영역 등이 여기에 해당한다. 보통 묶어서 배치된다. |
기계어 포맷은 아키텍처에 따라 다르지만, 1 명령을 구성하는 데이터 길이가 고정된 "고정 길이" 방식과, 명령 및 오퍼랜드 종류에 따라 변하는 "가변 길이" 방식으로 나뉜다. 가변 길이 방식에서는 명령어 종류에 따라 주소부, 데이터부, 심지어 명령부 길이까지 달라진다.
다음은 MIPS 아키텍처에서의 기계어 명령어 예시이다.
- R-type 명령어 (레지스터 1과 2를 더하여 레지스터 6에 저장):
```
[ op | rs | rt | rd |shamt| funct]
0 1 2 6 0 32 decimal
000000 00001 00010 00110 00000 100000 binary
```
- op: 명령어 종류 (덧셈)
- rs: 첫 번째 소스 레지스터 (레지스터 1)
- rt: 두 번째 소스 레지스터 (레지스터 2)
- rd: 목적지 레지스터 (레지스터 6)
- shamt: 시프트 양 (사용 안 함)
- funct: 기능 코드 (덧셈)
- I-type 명령어 (레지스터 3의 주소 + 68 위치의 값을 레지스터 8로 로드):
```
[ op | rs | rt | address/immediate]
35 3 8 68 decimal
100011 00011 01000 00000 00001 000100 binary
```
- J-type 명령어 (1024번지로 점프):
```
[ op | target address ]
2 1024 decimal
000010 00000 00000 00000 10000 000000 binary
```
대부분 명령어는 명령어 유형(산술, 논리, 점프 등), 연산(덧셈, 비교 등), 피연산자 유형, 어드레싱 모드, 오프셋, 인덱스, 피연산자 값 자체(상수 피연산자는 ''즉시값''이라고 함) 등을 지정하는 연산 코드 필드를 하나 이상 갖는다.
5. 기계어와 호환성
기본적으로 특정 아키텍처의 중앙 처리 장치용 기계어는 다른 아키텍처의 중앙 처리 장치에서는 전혀 사용할 수 없다. 예를 들어, 펜티엄 계열과 PowerPC 계열은 명령어 집합에 호환성이 없기 때문에 양쪽에서 모두 실행되는 기계어 프로그램은 없다.
같은 제조사의 중앙 처리 장치라도 아키텍처가 변경되면 이전 세대의 기계어가 실행되지 않을 수 있다. 기계어 프로그램이 그대로 실행되는지 여부를 "바이너리 호환성"이라고 한다.
1994년 IBM에서 x86과 PowerPC 명령어를 모두 지원하는 PowerPC 615를 공개했지만, 양산되지는 않았다.
5. 1. CPU 사양 차이
CPU마다 기계어 사양이 다른 이유는 다음과 같다.- CPU가 이해할 수 있는 명령어의 종류와 수가 다르다. (CISC, RISC, VLIW)
- 명령어의 길이가 다르다. (CISC와 RISC는 길이가 다를 수 있다. 또한, 같은 아키텍처에서도 명령어 비트 수의 차이가 영향을 미친다.)
- 명령어부의 명령어 번호가 일치하지 않는다.
- 같은 처리를 하는 명령이라도 처리 결과가 다르다.
- 연산 방법이 다르다. (레지스터 - 레지스터 간 연산이나 메모리 - 레지스터 간 연산의 차이. RISC에서는 후자의 연산을 할 수 없다.)
- 데이터 기록 방법이 다르다. (엔디안이나 정렬)
- 실행 파일의 바이너리 파일 기록 형식이 다르다. (PE, COFF, ELF 등)
6. 기계어 패턴
기계어로 작성된 코드에는 빈번하게 나타나는 패턴이 존재한다. 기계어에는 함수 구문은 존재하지 않지만, 함수에 상당하는 패턴이 존재한다.
함수는 인수를 받아들이고, 지역 변수를 확보하며, 본체의 명령을 실행하고, 반환값을 돌려주는 루틴이다. 이 루틴을 호출하는 경우, 제어가 돌아올 포인트를 적어두고, 인수를 준비하고, 루틴으로 제어를 넘겨 실행하고, 반환값을 기록하고, 복귀 포인트로 제어를 넘긴다.
함수 호출에 상당하는 패턴에는 다음과 같은 처리가 포함된다.
- 인수의 준비
- 서브루틴 종료 후의 복귀 포인트 메모
- 지역 변수의 확보
- 서브루틴 초입으로의 제어 이행
이러한 처리에 의해 서브루틴으로 제어가 이동하여, 함수 본체의 명령열이 실행된다. 함수 명령의 최종 행이 실행된 후, 다음 처리가 필요하게 된다.
함수로부터의 복귀에 상당하는 패턴에는 다음과 같은 처리가 포함된다.
- 지역 변수의 해제
- 인수의 해제
- 반환값의 저장
- 복귀 포인트로의 제어 이행
이러한 처리에 의해 메인 루틴으로 제어가 복귀한다.
이 패턴은 함수의 처리 내용에 관계없이 보편적이다. 전반의 함수 호출에 상당하는 패턴을 '''함수 프로로그'''(function prologue|펑션 프롤로그영어)라고 한다. 후반의 함수로부터의 복귀에 상당하는 패턴을 '''함수 에필로그'''(function epilogue|펑션 에필로그영어)라고 한다.
함수 프로로그·에필로그는 같은 결과가 얻어지는 몇 가지 패턴이 존재한다(호출 규약). 예를 들어 인수를 스택에 쌓는 패턴과 레지스터에 두는 패턴이 있다.
7. 기계어 프로그램 로딩
프로그램 내장 방식 컴퓨터에서 기계어 프로그램은 일반적으로 보조 기억 장치(하드 디스크 등)의 실행 파일 형태로 존재한다. 운영 체제는 실행 파일을 주 기억 장치(RAM)에 로드하고, CPU는 프로그램 카운터(PC) 레지스터를 통해 명령어를 실행한다. 공유 라이브러리를 실행 시점에 동적 링크하여 연결할 수도 있다. 최근에는 실행 시 컴파일(JIT) 기술이 발전하면서 프로그램 실행 방식이 다양해지고 있다.
8. 덤프 리스트
덤프 리스트는 기계어 코드를 16진수로 표현한 것이다. 1980년대 대한민국의 마이컴 잡지에서는 기계어 프로그램을 덤프 리스트 형태로 게재하기도 했다.
다음은 CASL의 페이퍼 머신 COMET에서 기계어 명령어의 예시이다.
주소 | 기계어 (16진수 표시) | CASL | |
---|---|---|---|
8000 | 7001 0000 7002 0000 | ||
8001 | 1210 800D 1220 800C | ||
8002 | F000 0002 7120 7110 | ||
800C | 000C | LEN | OUT TEXT,LEN |
800D | 0048 0065 006C 006C | TEXT | DC 12 |
800E | 006F 0020 0077 006F | DC 'Hello world!' | |
800F | 0072 006C 0064 0021 |
9. 기계어의 가독성 및 디버깅
기계어는 사람이 직접 읽고 이해하기 어렵다. 따라서, 디스어셈블리를 통해 사람이 읽을 수 있는 어셈블리 언어로 변환하여 분석하는 것이 일반적이다.[2]
디버거는 심볼 테이블을 이용하여 소스 코드 수준에서 기계어를 디버깅할 수 있도록 돕는다. 심볼 테이블은 실행 파일 내에 저장되거나 별도의 파일로 존재할 수 있다.[6][7] 심볼 테이블의 형식은 운영 체제에 따라 다르다.
- 마이크로소프트 윈도우: 프로그램 데이터베이스(.pdb) 파일
- 유닉스 계열 운영 체제: stabs, DWARF 형식 (예: macOS 및 Darwin 기반 운영 체제는 별도의 .dSYM 파일에 DWARF 형식으로 저장)
- IBM 메인프레임 운영 체제 (예: z/OS): ''연관 데이터''(ADATA) (IBM 고급 어셈블러(HLASM),[3] COBOL 컴파일러,[4] PL/I 컴파일러[5]에 의해 생성 가능)
과거 1980년대 초, 대한민국에서는 금성사(현 LG전자)의 FC-100과 같은 8비트 컴퓨터에서 기계어 모니터를 통해 직접 기계어 코드를 작성하고 디버깅하는 경우가 많았다.
10. 기계어가 사용되는 상황
현대에는 대부분의 경우 고급 언어와 컴파일러를 사용하지만, 다음과 같은 특수한 상황에서는 기계어를 직접 다루기도 한다.
- 새로운 프로세서: GNU Binutils와 같은 유틸리티나 라이브러리가 아직 없는 새로운 프로세서의 경우.
- 특수한 명령: 프로그래밍 언어에 익숙하지 않은 특수한 명령을 다루는 경우.
- trampoline: trampoline[13]과 같은 기술이 필요한 경우.
- 프로세서 버그: 프로세서의 버그에 걸렸거나 의심되는 경우.
- 코어 덤프: 어떤 이유로 코어 덤프를 직접 해석해야 하는 경우.
대한민국에서는 특히 임베디드 시스템 개발 분야에서 ARM 아키텍처 기반 프로세서에 대한 기계어 프로그래밍 수요가 높다.
참조
[1]
서적
Computer Organization and Architecture 10th edition
Pearson Prentice Hall
2015
[2]
서적
Structured Computer Organization, Third Edition
https://archive.org/[...]
Prentice Hall
[3]
웹사이트
Associated Data Architecture
https://www.ibm.com/[...]
[4]
웹사이트
COBOL SYSADATA file contents
https://www.ibm.com/[...]
[5]
웹사이트
SYSADATA message information
https://www.ibm.com/[...]
[6]
웹사이트
Symbols for Windows debugging
https://learn.micros[...]
2022-12-20
[7]
웹사이트
Querying the .Pdb File
https://learn.micros[...]
2024-01-12
[8]
간행물
"日本大百科全書』【機械語】 (コトバンク"
https://kotobank.jp/[...]
[9]
웹사이트
IT用語辞典 e-words【機械語】
https://e-words.jp/w[...]
[10]
웹사이트
入出力バスとは - コトバンク
https://kotobank.jp/[...]
[11]
웹사이트
データ実行防止
https://msdn.microso[...]
[12]
웹사이트
IPA ISEC セキュア・プログラミング講座:C/C++言語編 第10章 著名な脆弱性対策:バッファオーバーフロー: #5 運用環境における防御
https://web.archive.[...]
[13]
웹사이트
trampoline
http://catb.org/jarg[...]
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com