목차
3. 기본 실행 환경(Basic Execution Environment)
3.1. 작동 방식(Modes of Operation)
3.1.1. Intel® 64 아키텍처(Intel® 64 Architecture)
3.2. 기본 실행 환경의 개요(Overview of the Basic Execution Environment)
3.2.1. 64비트 모드 실행 환경(64-Bit Mode Execution Environment)
3.3. 메모리 조직(Memory Organization)
3.3.1. IA-32 메모리 모델(IA-32 Memory Models)
3.3.2. 페이징과 가상 메모리(Paging and Virtual Memory)
3.3.3. 64비트 모드의 메모리 조직(Memory Organization in 64-Bit Mode)
3.3.4. 동작 모드 vs 메모리 모델(Modes of Operation vs. Memory Model)
3.3.5. 32비트 및 16비트 주소와 피연산자 크기(32-Bit and 16-Bit Address and Operand Sizes)
3.3.6. 보호 모드에서 확장된 물리적 주소 배정(Extended Physical Addressing in Protected Mode)
3.3.7. 64 비트 모드에서 주소 계산(Address Calculations in 64-Bit Mode)
3.3.7.1. 표준 주소 배정(Canonical Addressing)
3.4. 기본 프로그램 실행 레지스터(Basic Program Execution Registers)
3.4.1. 범용 레지스터(General-Purpose Registers)
3.4.1.1. 64비트 모드에서 범용 레지스터(General-Purpose Registers in 64-Bit Mode)
3.4.2. 세그먼트 레지스터(Segment Registers)
3.4.2.1. 64 비트 모드에서 세그먼트 레지스터(Segment Registers in 64-Bit Mode)
3.4.3. EFLAGS 레지스터(EFLAGS Register)
3.4.3.3. 시스템 플래그와 IOPL 필드(System Flags and IOPL Field)
3.4.3.4. 64 비트 모드에서 RFLAGS 레지스터(RFLAGS Register in 64-Bit Mode)
3.5. 명령 포인터(Instruction Pointer)
3.5.1. 64 비트 모드에서 명령 포인터(Instruction Pointer in 64-Bit Mode)
3.6. 피연산자 크기와 주소 크기 속성(Operand-Size And Address-Size Attributes)
3.6.1. 64비트 모드의 피연산자 크기와 주소 크기(Operand Size and Address Size in 64-Bit Mode)
3.7. 피연산자 주소 배정(OPERAND ADDRESSING)
3.7.1. 직접 피연산자(Immediate Operands)
3.7.2. 레지스터 피연산자(Register Operands)
3.7.2.1. 64-비트 모드에서 레지스터 피연산자(Register Operands in 64-Bit Mode)
3.7.3. 메모리 피연산자(Memory Operands)
3.7.3.1. 64 비트에서 메모리 피연산자(Memory Operands in 64-Bit Mode)
3.7.4. 세그먼트 셀렉터 지정(Specifying a Segment Selector)
3.7.4.1. 64-비트 모드에서 세그먼테이션(Segmentation in 64-Bit Mode)
3.7.5. 오프셋 지정(Specifying an Offset)
3.7.5.1. 64-비트 모드에서 오프셋 지정(Specifying an Offset in 64-Bit Mode)
3.7.6. 어셈블러와 컴파일러 주소 배정 모드(Assembler and Compiler Addressing Modes)
3.7.7. I/O 포트 주소 배정(I/O Port Addressing)
3. 기본 실행 환경(Basic Execution Environment)
이 장에서는 어셈블리 프로그래머가 볼 수 있는 Intel 64나 IA-32 프로세서의 기본 실행 환경을 설명한다. 프로세서가 명령어를 실행하는 방법과 데이터를 저장하고 조작하는 방법을 설명한다. 여기서 설명하는 실행 환경은 메모리 (주소 공간), 범용 데이터 레지스터, 세그먼트 레지스터, 플래그 레지스터 그리고 명령 포인터 레지스터다.
3.1. 작동 방식(Modes of Operation)
IA-32 아키텍처는 보호 모드, 실제 주소 모드 그리고 시스템 관리 모드라는 세 가지 기본 작동 모드를 지원한다. 운영 모드는 접근할 수 있는 명령어와 아키텍처 기능을 결정한다.
- 보호 모드(Protected Mode) - 이 모드는 프로세서의 기본 상태(native state)다. 보호 모드의 기능에는 다중 작업 환경에서 "실제 주소 모드" 8086 소프트웨어를 직접 실행할 수 있는 기능이 있다. 이 기능은 Virtual-8086 모드로 불리는데, 실제 프로세서 모드는 아니다. Virtual-8086 모드는 모든 작업을 활성화 할 수 있는 보호 모드 속성이다.
- 실제 주소 모드(Real-address Mode) - 이 모드는 확장 기능(보호되거나 시스템 관리 모드로 전환하는 기능)이 있는 Intel 8086 프로세서의 프로그래밍 환경을 구현한다. 프로세서는 전원을 켜거나 재부팅 후 실제 주소 모드에 위치한다.
- 시스템 관리 모드(SMM, System Management Mode) - 이 모드는 전력관리나 시스템 보안과 같은 플랫폼의 특정 기능을 구현하기 위해 투명한 메커니즘을 운영체제나 executive에게 제공한다. 외부 SSM 인터럽트 핀 (SMI#)이 활성화되거나 고급 프로그래밍이 가능한 인터럽트 제어기(APIC, Advanced Programmable Interrupt Controller)에서 SMI를 수신하면 프로세서는 SMM으로 진입한다.
SMM에서 프로세서는 현재 실행중인 프로그램이나 작업의 기본 문맥을 저장하는 동안 별도의 주소 공간으로 전환한다. 그래야 SMM 관련 코드를 투명하게 실행할 수 있다. SMM에서 복귀할 때, 프로세서는 시스템 관리 인터럽트 이전 상태로 돌아간다. SMM은 Intel386™SL과 Intel486™SL 프로세서와 함께 소개되었고, 펜티엄 프로세서 제품군의 표준 IA-32로 자리잡았다.
3.1.1. Intel® 64 아키텍처(Intel® 64 Architecture)
인텔 64 아키텍처는 IA-32e 모드를 추가한다. IA-32e 모드에는 두 가지 하위 모드가 있는데 이는 다음과 같다.
- 호환 모드(Compatibility Mode) / IA-32e 모드의 하위 모드 - 호환 모드는 64비트 운영체제에서 오래된 16비트와 32비트 응용프로그램을 다시 컴파일하지 않고 실행할 수 있다. 단순하게, 호환성 하위 모드를 IA-32 아키텍처에서 호환 모드라고 부른다. 호환 모드의 실행 환경은 3.2절에서 설명한 것과 동일하다. 호환 모드는 64비트와 보호 모드에서 지원하는 모든 권한 레벨을 지원한다. Virtual-8086 모드에서 실행되거나 하드웨어 작업 관리를 사용하는 오래된 응용프로그램은 이 모드에서 작동하지 않는다.
호환 모드는 코드 세그먼트 단위로 운영체제에서 사용할 수 있다. 이는 단일 64비트 OS가 64비트 모드에서 실행되는 64비트 응용프로그램을 지원하고, 오래된 32비트 응용프로그램(64비트 용으로 다시 컴파일하지 않고)을 지원할 수 있음을 의미한다.
호환 모드는 32비트 보호 모드와 유사하다. 응용프로그램은 처음 4GB 선형 주소 공간에만 접근한다. 호환 모드는 16비트와 32비트 주소 그래고 피연산자 크기를 사용한다. 보호 모드처럼 이 모드에서 응용프로그램이 물리 메모리 확장(PAE, Physical Address Extensions)를 사용하여 4GB가 넘는 실제 메모리에 접근할 수 있다. - 64비트 모드 / IA-32e 모드의 하위 모드 - 이 모드는 64비트 운영체제가 64비트 선형 주소 공간에 접근하여 작성된 응용프로그램을 실행할 수 있게 한다. 단순하게, 64비트 하위 모드는 IA-32 아키텍처에서 64비트 모드라고 부른다.
64비트 모드는 범용 레지스터와 SIMD 확장 레지스터의 수를 8에서 16으로 확장한다. 범용 레지스터는 64비트로 확장된다. 또한 모드는 레지스터 확장에 액세스하는 새로운 opcode 접두어 (REX)를 도입한다. 자세한 설명은 3.2.1 절을 참조한다.
64비트 모드는 코드 세그먼트 단위로 운영체제에서 사용할 수 있다. 기본 주소 크기는 64비트고 기본 연산자 크기는 32비트다. 기본 피연산자 크기는 피연산자 크기만큼 덮어쓰는 접두어와 함께 REX opcode 접두어를사용하여 명령별로 재정의할 수 있다.
REX 접두어를 허용하면 64비트 모드에서 작동할 때 64비트 피연산자를 지정할 수 있다. 이 메커니즘을 이용하여 64비트 레지스터와 64비트 주소를 사용할 수 있도록 기존의 많은 명령이 승격된다.
3.2. 기본 실행 환경의 개요(Overview of the Basic Execution Environment)
Intel 64 프로세서는 IA-32 프로세서의 기본 실행 환경을 지원하며, 64비트 프로그램(64비트 하위 모드)와 32비트 프로그램(호환 하위 모드) 실행할 수 있는 IA-32e 모드와 유사한 환경을 지원한다.
IA-32 프로세서에서 실행되는 모든 프로그램이나 작업은 명령을 실행하고 코드, 데이터 그리고 상태 정보를 저장하기 위한 자원의 집합을 제공한다. 이러한 자원은 (그림 3-1에서 볼 수 있고 다음 단락에서 간략하게 설명 함) IA-32 프로세서의 기본 실행 환경을 구성한다.
기본 실행 환경은 응용프로그램과 운영체제나 executive이 실행한 프로세서가 공동으로 사용한다.
- 주소 공간(Address Space) - IA-32 프로세서에서 실행되는 모든 프로그램이나 작업은 최대 4GB (232 바이트) 선형 주소 공간과 최대 64GB (236 바이트) 물리 주소 공간을 주소로 쓸 수 있다. 4GB 보다 큰 주소 공간을 주소로 쓸 수 있는 자세한 정보는 3.3.6 절 "Extended Physical Addressing in Protected Mode"를 참조한다.
- 기본 프로그램 실행 레지스터(Basic Program Execution Registers) - 8개의 범용 레지스터, 6개의 세그먼트 레지스터, EFLAGS 레지스터 그리고 EIP (명령 포인터) 레지스터는 범용적인 명령의 집합을 실행하는 기본 실행 환경을 구성한다. 이러한 명령은 바이트, 워드, 더블워드 정수에 대한 기본 산술 연산, 프로그램 흐름 제어를 처리, 비트와 바이트 문자열을 처리, 메모리 주소를 지정하는 수행한다. 이러한 레지스터에 대한 자세한 정보는 3.4 절 "Basic Program Execution Registers"를 참조한다.
- x87 FPU 레지스터 - 8개의 x87 FPU 데이터 레지스터, x87 FPU 제어 레지스터, 상태 레지스터, x87 FPU 명령 포인터 레지스터, x87 FPU 피연산자 (데이터) 포인터 레지스터, x87 FPU 태그 레지스터 그리고 x87 FPU opcode 레지스터는 단정밀도(single-precision), 배정밀도(double-precision) 그리고 확장된 배정밀도(double extended-precision)를 통한 부동소수점 값, 워드 정수, 더블 워드 정수, 쿼드 워드 정수 그리고 BCD(Binary Coded Decimal) 값을 포함한 실행 환경을 제공한다.
- MMX 레지스터 - 8 개의 MMX 레지스터는 64비트로 포장 된 바이트, 워드 그리고 더블 워드 정수에 대한 단일 명령, 다중 데이터(SIMD) 연산을 실행하도록 지원한다. 이 레지스터에 대한 자세한 내용은 9.2 절 "The MMX Technology Programming Environment"을 참조한다.
- XMM 레지스터 - 8개의 XMM 데이터 레지스터와 MXCSR 레지스터는 128비트로 포장킹된 바이트, 워드, 더블 워드 그리고 쿼드 워드 정수와 128비트로 포장된 단정밀도와 배정밀도 부동소수점 값을 SIMD 연산으로 지원한다. 이 레지스터에 대한 자세한 내용은 10.2 절 "SSE Programming Environment"을 참조한다.
- YMM 레지스터 - YMM 데이터 레지스터는 256비트로 포장된 단정밀도와 배정밀도 부동소수점 값과 256비트로 포장된 바이트, 워드, 더블워드 그리고 쿼드 워드 정수를 256비트 SIMD 연산으로 지원한다.
- 바운드 레지스터(Bounds registers) - BND0-BND3 레지스터 각각은 메모리 버퍼에 대한 포인터를 지지하는 하위 및 상위 바운드(bounds) (각각 64비트)를 저장한다. 인텔 MPX 명령의 실행을 지원한다.
- BNDCFGU와 BNDSTATUS - BNDCFGU는 경계(Bound) 검사시 사용자 모드 MPX 작업을 구성한다. BNDSTATUS는 MPX 작업으로 인한 #BR의 추가 정보를 제공한다.
- 스택(Stack) - 프로 시저나 서브 루틴 호출 그리고 프로 시저나 서브 루틴 사이의 매개 변수 전달을 지원하기 위해 스택과 스택 권리 리소스는 실행 환경에 포함된다. 스택 (그림 3-1에 표시하지 않음)은 메모리에 위치한다. 스택 구조에 대한 자세한 정보는 6.2 절 "Stacks"를 참조한다.
기본 실행 환경에서 제공되는 자원 외에도 IA-32 아키텍처는 시스템 레벨 아키텍처의 일부로 다음과 같은 자원을 제공한다. 이들은 운영체제와 시스템 개발 소프트웨어에 대한 광범위하게 지원한다. I/O 포트를 제외하고 시스템 자원은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volumes 3A & 3B에 자세히 설명되어 있다.
- I/O 포트 - IA-32 아키텍처는 입력/출력 (I/O) 포트와 데이터 전송을 지원한다. 자세한 내용은 18 장 "Input/Output"을 참조한다.
- 제어 레지스터(Control Registers) - 5 개의 제어 레지스터 (CR0부터 CR4)는 프로세서의 작동 모드와 현재 실행중인 작업의 특성을 결정한다. 자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 2장 "System Architecture Overview"를 참조한다.
- 메모리 관리 레지스터(Memory Management Registers) - GDTR, IDTR, 작업 레지스터 그리고 LDTR은 보호 모드 메모리 관리에 사용되는 데이터 구조의 위치를 지정한다. 자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 2장 "System Architecture Overview"를 참조한다.
- 디버그 레지스터(Debug Registers) - 디버그 레지스터 (DR0부터 DR7)는 프로세서의 디버깅 작업을 제어하고 모니터링을 허용한다. 자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3B를 참조한다.
- 메모리 유형 범위 레지스터(MTRRs, Memory Type Range Registers) - MTRRs는 메모리 유형을 메모리 영역에 할당하기 위해 사용한다. 자세한 정보는 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volumes 3A & 3B의 MTRRs 절을 참조한다.
- 기계 고유 레지스터(MSRs, Machine Specific Registers) - 프로세서는 프로세서 성능을 제어하고 보고하는데 사용되는 다양한 기계 고유 레지스터를 제공한다. 가실상 모든 MSRs는 시스템 관련 기능을 처리하며 응용프로그램에서 접근할 수 없다. 이 규칙의 한 가지 예외는 타임 스탬프 카운터다. MSR은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3C의 35장 "Model-Specific Registers (MSRs)"에 설명되어 있다.
- 기계 점검 레지스터(Machine Check Registers) - 기계 점검 레지스터는 하드웨어 (기계) 오류를 감지하고 보고하는데 사용되는 일련의 제어, 상태 그리고 오류 보고 MSR로 구성된다. 자세한 정보는 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 15장 "Machine Check Architecture"를 참고한다.
- 성능 모니터링 카운터(Performance Monitoring Counters) - 성능 모니터링 카운터를 사용하여 프로세서 성능 이벤트를 모니터링 할 수 있다. 자세한 정보는 Intel® 64 and IA-32 Architectures Software developer’s Manual, Volume 3B의 18장 "Performance Monitoring"을 참고한다.
이 장의 나머지 부분에서는 메모리와 주소 공간의 구성, 기본 프로그램 실행 레지스터 그리고 주소 배정 모드를 설명을 한다. 그림 3-1에 표시된 다른 프로그램 실행 자원에 대한 설명은 이 볼륨의 다음 장을 참조한다.
- x87 FPU 레지스터 - 8장, "Programming with the x87 FPU"를 참조
- MMX 레지스터 - 9장, "Programming with Intel® MMX™ Technology"를 참조
- XMM 레지스터 - 10장, "Programming with Intel® Streaming SIMD Extensions (Intel® SSE)" 11장, "Programming with Intel® Streaming SIMD Extensions 2 (Intel® SSE2)" 그리고 12장, "Programming with Intel® SSE3, SSSE3, Intel® SSE4 and Intel® AESNI"을 참조
- YMM 레지스터 - 14장, "Programming with AVX, FMA and AVX2"을 참조
- BND 레지스터, BNDCFGU, BNDSTATUS - 13장, "Managing State Using the XSAVE Feature Set" 그리고 17장, "Intel® MPX"을 참조
- 스택 구현 및 프로 시저 호출 - 6장, "Procedure Calls, Interrupts, and Exceptions"를 참조
3.2.1. 64비트 모드 실행 환경(64-Bit Mode Execution Environment)
64비트 모드를 위한 실행 환경은 3.2 절에서 설명한 것과 유사하다. 다음 단락에서 적용되는 차이점을 설명한다.
- 주소 공간(Address Space) - IA-32 프로세서에서 64비트 모드로 실행되는 작업이나 프로그램은 최대 264 바이트(3.3.7.1 절에 설명된 표준 주소 배정 요구 사항에 적용 받음)의 선형 주소 공간과 최대 246 바이트의 물리 주소 공간을 처리할 수 있다. 소프트웨어는 프로세서에 의해 지원받는 물리 주소 크기에 대해 CPUID를 쿼리할 수 있다.
- 기본 프로그램 실행 레지스터(Basic Program Execution Registers) - 사용할 수 있는 범용 레지스터 (GPRs)는 16개다. GPRs는 64비트 폭이며 바이트, 워드, 더블 워드, 쿼드 워드 정수에 대한 연산을 지원한다. 바이트 레지스터에 접근하는 것은 가장 낮은 8비트로 균일하게 수행된다. 명령 포인터 레지스터는 64비트다. EFLAGS 레지스터는 64비트 폭으로 확장되면 RFLAGS 레지스터로 바꿔 부른다. RFLAGS의 상위 32비트는 예약된 영역이다. RFLAGS의 하위 32비트는 EFLAGS와 동일하다. 그림 3-2를 참조하자.
- XMM 레지스터 - SIMD 연산을 위한 16개의 XMM 레지스터가 있다. 이러한 레지스터에 대한 자세한 내용은 10.2 절 "SSE Programming Environment"를 참조한다.
- YMM 레지스터 - SIMD 연산을 위한 16개의 YMM 데이터 레지스터가 있다. 이러한 레지스터에 대한 자세한 내용은 14장 "Programming with AVX, FMA and AVX2"을 참조한다.
- BND 레지스터, BNDCFGU, BNDSTATUS - 13장 "Managing State Using the XSAVE Feature Set" 와 17장 "Intel® MPX"을 참조한다.
- 스택 - 스택 포인터 크기는 64비트다. 스택 크기는 SS 디스크립터(비 64비트 모드이기 때문에) 의 비트에 의해 제어되거나 포인터의 크기가 명령 접두사에 의해 무시되지 않는다.
- 제어 레지스터(Control registers) - 제어 레지스터는 64비트로 확장된다. 새로운 제어 레지스터 (작업 우선 순위 레지스터: CR8 또는 TPR)가 추가되었다. 자세한 정보는 2장 "Intel® 64 and IA-32 Architectures"을 참고한다.
- 디버그 레지스터(Debug registers) - 디버그 레지스터는 64비트로 확장된다. 자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 17장 "Debug, Branch Profile, TSC, and Quality of Service"을 참고한다.
- 디스크립터 테이블 레지스터(Descriptor table registers) - 글로벌 디스크립터 테이블 레지스터 (GDTR, Global Descriptor Table Register)과 인터럽트 디스크립터 테이블 레지스터 (IDTR, Interrupt Descriptor Table Register)은 10자이르토 확장되어 완전한 64비트 기반 주소를 유지할 수 있다. 로컬 디스크립터 테이블 레지스터 (LDTR, Local Descriptor Table Register)와 작업 레지스터(TR, Task Register)도 확장되어 전체 64비트 기반 주소를 보유한다.
3.3. 메모리 조직(Memory Organization)
프로세서그 버스에서 주소를 지정하는 메모리를 물리 메모리라고 부른다. 물리 메모리는 일련의 8비트 바이트로 구성된다. 각 바이트에는 물리적 주소라는 고유 주소가 할당된다. 프로세서가 Intel 64 아키텍처가 지원하지 않는 경우 물리 주소 공간의 범위는 0에서 최대 236 - 1 (64GB)이다. Intel 64 아키텍처는 물리와 선형 주소 공간을 변경을 소개한다. 이는 3.3.3절, 3.3.4절 그리고 3.3.7절에서 설명되어 있다.
실제로 IA-32나 Intel 64 프로세서와 함께 작동하도록 설계된 운영체제나 executive는 프로세서의 메모리 관리 기능을 사용하여 메모리에 접근한다. 이러한 기능은 메모리를 효율적이고 안정적으로 관리할 수 있는 세그먼테이션과 페이징 같은 기능을 제공한다. 메모리 관리에 대한 자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 3장 "Protected-Mode Memory Management"를 참조한다. 다음 단락에서는 메모리 관리를 사용할 때 메모리 주소를 지정하는 기본적인 방법을 설명한다.
3.3.1. IA-32 메모리 모델(IA-32 Memory Models)
프로세서의 메모리 관리 기능을 사용하면, 프로그램은 물리 메모리를 직접 처리하지 못한다. 대신 세 가지 메모리 모델 중 하나를 사용 하여 메모리에 접근하는데 이는 평면(Flat), 분할(Segmented) 그리고 실제 주소 모드(Real Address Mode)다.
- 평면 메모리 모델(Flat Memory Model) - 메모리는 하나의 프로그램을 연속적인 주소 공간(그림 3-3)으로 표현한다. 이 공간을 선형 주소 공간(Linear Address Space)이라고 부른다. 코드, 데이터 그리고 스택은 모두 이 주소 공간에 포함된다. 선형 주소 공간은 바이트 크기만큼 주소 배정이 가능하며, 주소는 0에서 232 - 1(64비트 모드가 아닌 경우)까지 연속적으로 실행된다. 선형 주소 공간에서 모든 바이트를 위한 주소를 선형 주소라 부른다.
- 분할된 메모리 모델(Segmented Memory Model) - 메모리는 프로그램에 세그먼트라고 불리는 독립적인 주소 공간의 그룹으로 나타낸다. 코드, 데이터 그리고 스택은 일반적으로 별도의 세그먼트에 포함된다. 세그먼트의 바이트 주소를 지정하기 위해 프로그램은 논리적 주소를 발행한다. 이 논리적 주소는 세그먼트 셀렉터와 오프셋 (논리적 주소는 종종 원거리 포인터라고 함)으로 구성된다. 세그먼트 셀렉터는 접근할 세그먼트를 식별하고 오프셋은 세그먼트의 주소 공간에서 바이트를 식별한다. IA-32 프로세서에서 실행되는 프로그램은 크기와 유형이 다른 최대 16,383개의 세그먼트를 처리할 수 있으며, 각 세그먼트는 232 바이트로 클 수 있다.
내부적으로, 시스템에 정의된 모든 세그먼트는 프로세서의 선형 주소 공간에 매핑된다. 메모리 위치에 접근하기 위해서 프로세서는 각 논리 주소를 선형 주소로 변환한다. 이 변환은 응용프로그램에 있어 투명하다.
분할된 메모리를 사용하는 주된 이유는 프로그램과 시스템의 신뢰성을 높이는데 있다. 예를 들어 프로그램의 스택을 별도의 세그먼트로 배치하면 스택이 코드나 데이터 공간으로 확장되거나 명령이나 데이터를 덮어쓰지 못하게 된다. - 실제 주소 모드 메모리 모델(Real-Address Mode Memory Model) - 이것은 Intel 8086 프로세서의 메모리 모델이다. Intel 8086 프로세서에서 실행되도록 작성된 기존의 응용프로그램과의 호환성을 지원한다. 실제 주소 모드는 분할된 메모리의 특정 구현을 사용하는데, 여기서 선형 주소 공간에 프로그램과 운영체제/executive는 각각 최대 64 KB 크기의 세그먼트의 배열로 구성된다.
자세한 정보는 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3B의 20장 "8086 Emulation"를 참조한다.
3.3.2. 페이징과 가상 메모리(Paging and Virtual Memory)
평면 또는 분할된 메모리 모델을 사용하면 선형 주소 공간은 직접 또는 페이징을 통해 프로세서의 물리적 주소 공간으로 매핑된다. 직접 매핑(페이징 비활성화)을 사용할 때, 각 선형 주소는 물리적 주소와 일대일로 대응한다. 선형 주소는 변환하지 않고 프로세서의 주소 행에 전달된다.
IA-32 아키턱처의 페이징 메커니즘 (페이징 활성화)를 사용할 때 선형 주소 공간은 가상 메모리에 매핑되는 페이지로 구분된다. 가상 메모리의 페이지는 필요에 따라 물리 메모리에 매핑된다. 운영체제나 executive이 페이징을 사용할 때, 페이징 메커니즘은 응용프로그램에 투명하다. 모든 응용프로그램이 보는 모든 것은 선형 주소 공간이다.
또한, IA-32 아키턱처의 페이징 메커니즘에는 다음을 지원하도록 확장된다.
- 물리 주소 확장 (PAE, Physical Address Extensions)을 사용하여 4GB 보다 큰 물리 주소 공간을 처리한다.
- 페이지 크기 확장(PSE, Page Size Extensions)을 사용하여 선형 주소를 4메가 바이트 페이지 물리 주소에 매핑한다.
자세한 정보는 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 3장 "Protected-Mode Memory Management"를 참조한다.
3.3.3. 64비트 모드의 메모리 조직(Memory Organization in 64-Bit Mode)
Intel 64 아키텍처는 64GB보다 큰 물리적 주소 공간을 지원한다. IA-32 프로세서의 실제 물리 주소 공간은 구현에 따라 다르다. 64비트 모드 아키텍처는 64비트 선형 주소 공간을 지원한다. 하지만 Intel 64 아키텍처를 지원하는 프로세서는 64비트보다 작게 구현할 수 있다. (3.3.7.1절 참조) 선형 주소 공간은 PAE 페이징 메커니즘을 통해 프로세서 물리 메모리 공간에 매핑된다.
3.3.4. 동작 모드 vs 메모리 모델(Modes of Operation vs. Memory Model)
IA-32나 Intel 64 프로세서 용 코드를 작성할 때, 프로그래머는 사용중인 코드와 메모리 모델을 작동시킬 때 프로세서가 작동 할 운영 모드를 알아야한다. 동작 모드와 메모리 모델간의 관계는 다음과 같다.
- 보호 모드(Protected Mode) - 보호 모드에 있을 때, 프로세서는 이 절에서 설명하는 메모리 모델 중 하나를 사용할 수 있다. (실제 주소 배정 모드 메모리 모델은 일반적으로 프로세서가 virtual-8086 모드에 있을 때만 사용) 사용되는 메모리 모델은 운영 시스템이나 executive의 설계에 따라 다르다. 멀티 태스킹이 구현되면, 개별 작업은 다른 메모리 모델을 사용할 수 있다.
- 시스템 관리 모드(System Management Mode) - SMM에서 프로세서는 시스템 관리 RAM (SMRAM)이라고 하는 별도의 주소 공간으로 전환한다. 이 주소 공간에서 바이트를 주소로 지정하는데 사용되는 메모리 모델은 실제 주소 모드 모델과 유사하다. 더 자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3C의 34장 "System Management Mode"을 참조한다.
- 호환 모드(Compatibility Mode) - 호환성 모드에서 실행할 필요가 있는 소프트웨어는 32비트 보호 모드에서 실행되도록 지정된 메모리 모델과 동일한 메모리 모델을 준수한다. 세그먼트화의 효과는 32비트 보호 모드 의미와 동일하다.
- 64비트 모드(64-bit Mode) - 세그먼트화는 일반적으로 (하지만 완전하지 않게) 비활성화 되고, 평면 64비트 선형 주소 공간에 생성한다. 구체적으로, 프로세서는 64비트 모드에서 CS, DS, ES 그리고 SS의 세그먼트 기준을 0으로 처리한다. (이로 인해 선형 주소가 유효한 주소와 같게 만든다) 64비트 모드에서 분할 및 실제 주소 모드를 사용할 수 없다.
3.3.5. 32비트 및 16비트 주소와 피연산자 크기(32-Bit and 16-Bit Address and Operand Sizes)
보호 모드에서 IA-32 프로세서는 32비트 또는 16비트 주소와 피연산자 크기로 구성 된다. 32비트 주소와 피연산자 크기에서 최대 선형 주소나 세그먼트 오프셋은 FFFFFFFFH (232 -1)을 가진다. 피연산자 크기는 일반적으로 8비트 이거나 32비트다. 16비트 주소와 피연산자 크기에서 최대 선형 주소나 세그먼트 오프셋은 FFFFH (216 - 1)을 가진다. 피연산자 크기는 일반적으로 8비트 이거나 16비트다.
32비트 주소로 배정할 때, 논리 주소 (또는 원거리 포인터)는 16비트 세그먼트 셀렉터와 32비트 오프셋으로 구성된다. 16비트 주소 배정을 사용할 때, 주소는 16비트 세그먼트 셀렉터와 16비트 오프셋으로 구성된다.
명령 접두사를 사용하면 프로그램 내에 기본 주소 및/또는 피연산자 크기를 임시로 대체하도록 허용한다.
보호 모드에서 동작할 때, 현재 실행중인 코드 세그먼트를 위한 세그먼트 디스크립터가 기본 주소와 피연산자 크기를 정의한다. 세그먼트 디스크립터는 응용 프로그램 코드에서 일반적으로 볼 수 없는 데이터 구조다. 어셈블러 지시문을 사용하면 프로그램에서 기본 주소 배정과 피연산자 크기를 선택하도록 허용한다. 어셈블러와 다른 도구는 코드 세그먼트에 대한 세그먼트 디스크립터를 적절하게 설정한다.
실제 주소 모드에서 동작할 때 기본 주소 배정과 피연산자 크기는 16비트다. 32비트 주소 배정을 사용하려면 실제 주소 모드에서 주소 크기만큼 대체하여 사용할 수 있다. 그러나 최대로 허용되는 32비트 선형 주소는 여전히 000FFFFFH (220 - 1)이다.
3.3.6. 보호 모드에서 확장된 물리적 주소 배정(Extended Physical Addressing in Protected Mode)
P6 제품군 프로세서부터 시작한 IA-32 아키텍처는 최대 64GB(236 바이트)의 물리 메모리 주소 배정을 지원한다. 프로그램이나 작업이 주소 공간에 직접적으로 배정할 수 없다. 대신, 가상 메모리 관리 메커니즘을 통해 64GB 물리적 주소 공간에 매핑되는 최대 4GB 개별 선형 주소 공간으로 처리한다. 이 메커니즘을 사용하면 운영 체제는 프로그램이 64GB 물리 주소 공간 안에 4GB 선형 주소 공간 전환이 가능하다.
확장된 물리 주소 배정을 사용하려면 프로세서가 보호 모드에서 작동해야하며, 운영 체제는 가상 메모리 관리 시스템을 제공한다. 더 자세한 정보는 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 3장 "36-Bit Physical Addressing Using the PAE Paging Mechanism"과 "Protected-Mode Memory Management"를 살펴본다.
3.3.7. 64 비트 모드에서 주소 계산(Address Calculations in 64-Bit Mode)
대부분의 경우, 64비트 모드는 코드, 데이터 그리고 스택을 위해 평면 데이터 주소를 사용한다. 64비트 모드(주소 크기만큼 대체하지 않는 경우), 유효하게 주소를 계산한 크기는 64비트다. 유효한 주소 계산은 64비트 기반 및 인덱스 레지스터를 사용하고, 변위를 64비트로 부호 확장한다.
64비트 모드의 평면 주소 공간에서, 선형 주소는 기본 주소가 0이기 때문에 유효 주소와 같다. FS나 GS 세그먼트가 0 기반이 아닌 형태와 함께 사용되는 경우 규칙은 적용되지 않는다. 64비트 모드에서 유효 주소 구성 요소가 추가되고 전체 64비트 세그먼트 기반을 추가하기 전에 유효 주소가 절단(명령어 LEA를 참조)된다. 64비트 모드에서 주소 배당 모드에 관계없이 기본은 절대로 절단되지 않는다.
명령 포인터는 64비트 코드 오프셋을 지원하기 위해 64비트로 확장된다. 64비트 명령 포인터는 RIP로 불린다. 표 3-1은 RIP, EIP 그리고 IP 사이의 관계를 보여준다.
일반적으로, 64비트에서 변위적이고 즉각적인 것은 64비트로 확장되지 않는다. 유효 주소 계산 중에는 여전히 32비트와 부호 확장으로 제한된다. 하지만 64비트 모드에서는 MOV 명령의 변위적이고 즉각적인 64비트를 위한 형태를 제공하여 지원한다.
모든 16비트와 32비트 주소 계산은 IA-32e 모드에서 제로 베이스로 확장되어 64비트 주소를 형성한다. 주소 계산은 현재 모드의 유효 주소 크기(64비트 모드나 호환 모드)로 잘려지며, 모든 주소 크기 접두사에 의해 덮어쓰인다. 그 결과 전체 64비트 주소 폭으로 제로 기반으로 확장된다. 이 때문에 호환 모드에서 16비트와 32비트 응용 프로그램 실행은 64비트 모드 유효 주소의 하위 4GB에서만 접근할 수 있다. 마찬가지로, 64비트 모드에서 생성된 32비트 주소는 64비트 모드 유효 주소의 하위 4GB에만 접근할 수 있다.
3.3.7.1. 표준 주소 배정(Canonical Addressing)
64 비트 모드에서 주소는 마이크로 아기텍처에 의해 63 비트 내지 최상위로 구현된 비트가 모두 1 또는 0으로 설정되면 정식 형식으로 간주한다.
Intel 64 아키텍처는 64 비트 선형 주소를 정의한다. 구현은 더 작은 비트를 지원할 수 있다. Intel 64 아키텍처를 사용하는 IA-32 프로세서의 첫 번째 구현은 48 비트 선형 주소를 지원한다. 다시 말해서, 표준 주소는 64에서 48 비트를 0 또는 1로 설정해야 한다. (비트 47이 0인지 1인지에 따라 다름)
구현은 64 비트의 선형 주소를 모두 사용할 수 없지만, 최상위 구현 비트를 통해 63 비트를 검사하여 주소가 표준 형식인지 확인한다. 선형 메모리 참조가 표준 형식이 아닌 경우, 구현시 예외를 생성한다. 대부분의 경우 일반 보호 예외(#GP)가 생성된다. 그러나 명시적이거나 묵시적 스택 참조의 경우, 스택 오류 (#SS)가 생성된다.
묵시적인 스택 참조하는 명령은 기본적으로 SS 세그먼트 레지스터를 사용한다. 여기에는 PUSH/POP 관련 명령과 RSP/RBP를 사용하는 명령을 포함한다. 이 경우 표준 오류는 #SS다.
명령어가 기본 레지스터 RSP/RBP를 사용하고 세그먼트 재지정 접두사를 사용하여 비-SS 세그먼트를 지정하는 경우 표준 오류로 (#SS 대신) #GP를 생성한다. 64 비트 모드에서 FS와 GS 세그먼트 재지정만 이 상황에서 적용된다. 다른 세그먼트 재지정 접두사 (CS, DS, ES 그리고 SS)는 무시된다. 이 또한 "비-스택" 레지스터 참조에 적용된 SS 세그먼트 재정의가 무시된다는 것을 의미한다. 이러한 시퀀스는 여전히 표준 오류 (#SS가 아닌) #GP를 생성한다.
3.4. 기본 프로그램 실행 레지스터(Basic Program Execution Registers)
아키텍처는 일반 시스템과 애플리케이션 프로그래밍에서 사용하기 위해 16개의 기본 프로그램 실행 레지스터를 제공한다. 이 레지스터는 다음과 같이 그룹화 할 수 있다.
- 범용 레지스터(General-purpose registers) - 이 8개의 레지스터는 피연산자의 포인터를 저장하는데 사용한다.
- 세그먼트 레지스터(Segment registers) - 이 레지스터는 최대 6개의 세그먼트 셀렉터를 보유한다.
- EFLAGS (프로그램 상태 및 제어) - 레지스터 EFLAGS 레지스터는 실행된 프로그램의 상태를 보고하고 프로세서의 제한된 (응용 프로그램 레벨) 제어를 허용한다.
- EIP (명령 포인터) - 레지스터 EIP 레지스터는 실행될 다음 명령에 대한 위치를 32비트 포인터의 크기만큼 가진다.
3.4.1. 범용 레지스터(General-Purpose Registers)
32 비트 범용 레지스터 EAX, EBX, ECX, EDX, ESI, EDI, EBP, 그리고 ESP는 다음 항목의 기능을 제공한다.
- 논리 및 산술 연산자 용 피연산자
- 주소 계산을 위한 피연산자
- 메모리 포인터
이러한 모든 레지스터는 피연산자, 결과(result) 그리고 포인터의 일반적인 저장에 사용할 수 있으며, ESP 레지스터를 참조할 때는 주의해야한다. ESP 레지스터는 스택 포인터를 가지고 있으며, 일반적으로 다른 목적으로 사용해서는 안된다.
많은 명령이 특정 레지스터에 할당하여 피연산자를 보유한다. 예를 들어, 문자열 명령은 ECX, ESI 그리고 EDI 레지스터의 내용을 피연산자로 사용한다. 분할된 메모리 모델을 사용할 때 일부 명령은 어떤 레지스터의 포인터가 특정 세그먼트와 관련있다고 가정한다. 예를 들어, 일부 명렁은 EBX 레지스터의 포인터가 DS 세그먼트의 메모리 위치를 가리키는 것으로 가정한다.
명령으로 범용 레지스터를 특수하게 사용하는 방법은 5장 "Instruction Set Summary"을 참고한다. 또한 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volumes 2A, 2B & 2C의 3장, 4장, 5장을 참조한다. 다음은 특수 용도에 대한 요약이다.
- EAX - 피연산자와 결과 데이터 누산기
- EBX - DS 세그먼트의 데이터에 대한 포인터
- ECX - 문자열 및 반복 연산을 위한 카운터
- EDX - I/O 포인터
- ESI - DS 레지스터가 가리키는 세그먼트의 데이터에 대한 포인터. 문자열 연산을 위한 소스 포인터
- EDI - ES 레지스터가 가리키는 세그먼트의 데이터 (또는 대상)에 대한 포인터. 문자열 연산을 위한 대상 포인터
- ESP - 스택 포인터 (SS 세그먼트에서)
- EBP - 스택의 데이터에 대한 포인터 (SS 세그먼트에서)
그림 3-5에서 보듯이 범용 레지스터의 하위 16 비트는 8086과 인텔 286 프로세서에 있는 레지스터 집합에 직접적으로 매핑되며 AX, BX, CX, DX, BP, SI, DI 그리고 SP 이름으로 참조될 수 있다. EAX, EBX, ECX 그리고 EDX 레지스터의 각각의 하위 2 바이트는 AH, BH, CH, DH (상위 바이트)와 AL, BL, CL, DL (하위 바이트) 이름으로 참조된다.
3.4.1.1. 64비트 모드에서 범용 레지스터(General-Purpose Registers in 64-Bit Mode)
64비트 모드에서, 16 개의 범용 레지스터가 있고, 기본 피연산자 크기는 32비트다. 그러나, 범용 레지스터는 32비트나 64비트 피연산자로 작업할 수 있다. 피연산자 크기가 32비트로 지정된 경우 EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP, R8D - R15D를 사용할 수 있다. 피연산자 크기가 64비트로 지정된 경우 RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP, R8-R15를 사용할 수 있다. R8D-R15D/R8-R15는 새로운 범용 레지스터를 나타낸다. 이 모든 레지스터는 바이트, 워드, d워드 그리고 q워드 수준에서 접근할 수 있다. REX 접두어는 피연산자 크기를 64비트로 생성하거나 레지스터 R8-R15를 참조하는데 사용된다.
64비트 모드(R8-R15와 XMM8-XMM15)에서만 사용 가능한 레지스터는 64비트 모드에서 호환 모드로 전환 한 후 64비트 모드로 다시 전환되는 동안 보존된다. 그러나, R8-R15와 XMM8-XMM15의 값은 64비트 모드에서 옛날의 호환 모드나 실제 모드로 전환한 후에나 호환 모드를 통해 64비트 모드로 돌아가면 정의되지 않는다.
64비트 모드에서 바이트 레지스터 접근하는 것을 제한한다. 명령은 예전의 상위 바이트(예, AH, BH, CH, DH)와 새 바이트 레지스터 중 하나를 동시에 참조할 수 없다. (예, RAX 레지스터의 하위 바이트) 하지만, 명령은 예전의 하위 바이트(예, AL, BL, CL 또는 DL)와 새로운 바이트 레지스터(예, R8 레지스터의 하위 바이트나 RBP)를 동시에 참조 할 수 있다. 아키텍처는 접두사 REX를 사용하는 명령에 대해 상위 바이트(AH, BH, CH, DH) 참조를 하위 바이트(BPL, SPL, DIL, SIL: RBP, RSP, RDI 그리고 RSI의 하위 8비트) 참조로 변경함으로써 제한적으로 적용한다.
64비트 모드에서 피연산자 크기는 대상(destination) 범용 레지스터의 유효 비트수를 결정한다.
- 64비트 피연산자는 대상 범용 레지스터에서 64비트 결과를 생성한다.
- 32비트 피연산자는 대상 범용 레지스터에서 64비트 결과로 제로 기반으로 확장된 32비트 결과를 생성한다.
- 8비트와 16비트 피연산자는 8비트와 16비트 결과를 생성한다. 대상 범용 레지스터의 48비트나 56비트 이상은 연산에 의해 수정되지 않는다. 8비트나 16비트 연산의 결과가 64비트 주소 계산을 위해 예정된 경우 명시적으로 레지스터를 전체 64비트로 부호 확장한다.
64비트 범용 레지스터의 상위 32비트는 32비트 모드에서 정의되지 않았으므로 64비트 모드에서 32비트 모드로 전환 할때 범용 레지스터의 상위 32비트는 모존되지 않는다. (보호 모드 또는 호환 모드) 64비트에서 32비트 모드로 전환한 후에는 소프트웨어가 이 비트에 의존해서는 안된다.
3.4.2. 세그먼트 레지스터(Segment Registers)
세그먼트 레지스터 (CS, DS, SS, ES, FS 그리고 GS)는 16 비트 세그먼트 셀렉터를 보유한다. 세그먼트 셀렉터는 메모리의 세그먼트를 식별하는 특수 포인터다. 메모리의 특정 세그먼트에 접근하는 것은, 해당 세그먼트의 세그먼트 셀렉터가 세그먼트 레지스터에 있어야 한다.
응용프로그램 코드를 작성할 때, 프로그래머는 일반적으로 어셈블러 지시문과 심볼을 사용하여 세그먼트 선택기를 만든다.어셈블러와 기타 도구는 이러한 지시문과 심볼과 관련된 실제 세그먼트 셀렉터 값을 만든다. 시스템 코드를 작성하는 경우, 프로그래머는 세그먼트 셀렉터를 직접 작성해야 할 수 있다. 자세한 정보는 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 3장 "Protected-Mode Memory Management"를 참조한다.
세그먼트 레지스터를 사용하는 방법은 운영체제나 executive가 사용하는 메모리 관리 모델 유형에 따라 다르다. 평면(비분할) 메모리 모델을 사용할 때, 세그먼트 레지스터는 중첩 세그먼트를 가리키는 세그먼트 셀렉터를 로드하며, 각 세그먼트는 선형 주소 공간의 주소 0에서 시작한다. (그림 3-6) 이러한 중첩 세그먼트는 프로그램의 선형 주소 공간을 구성한다. 일반적으로 두 개의 중첩 세그먼트는 정의된다. 하나는 코드고 다른 하나는 데이터와 스택이다. CS 세그먼트 레지스터 포인터는 코드 세그먼트를 가리키고, 모든 다른 세그먼트 레지스터 포인터는 데이터와 스택 세그먼트를 가리킨다.
분할된 메모리 모델을 사용할 때, 각 세그먼트 레지스터는 일반적으로 다른 세그먼트 셀렉터로 로드되어 각 세그먼트 레지스터는 선형 주소 공간 안에 다른 세그먼트를 가리킨다. (그림 3-7을 참조) 따라서 프로그램은 언제든지 선형 주소 공간에서 최대 6 개의 세그먼트에 접근할 수 있다. 세그먼트 레지스터 중 하나를 가리키고 있지 않은 세그먼트에 접근하는 것은, 프로그램이 먼저 접근할 세그먼트의 세그먼트 셀렉터를 세그먼트 레지스터에 로드해야 한다.
각 세그먼트 레지스터는 코드, 데이터 또는 스택의 세 가지 유형 중 하나와 연결된다. 예를 들어, CS 레지스터에는 실행되었거나 저장된 코드 세그먼트에 대한 세그먼트 셀렉터가 포함된다. EIP 레지스터에는 실행 될 다음 명령어의 코드 세그먼트 안에 오프셋이 포함된다. CS 레지스터는 응용프로그램에 의해 명시적으로 로드될 수 없다. 대신, 프로그램 제어(예, 프로시저 호출, 인터럽트 처리 또는 작업전환)를 변경하는 내부 프로세서 동작이나 명령에 의해 암시적으로 로드된다.
DS, ES, FS 그리고 GS 레지스터는 네 개의 데이터 세그먼트를 가리킨다. 네 개의 데이터 세그먼트를 사용할 수 있으므로, 서로 다른 유형의 데이터 구조에 효율적이고 안전하게 접근할 수 있다. 예를 들어, 네 개의 개별 데이터 세그먼트가 생성될 수 있다. 하나는 현재 모듈의 데이터 구조, 다른 하나는 상위 모듈에서 보낸 데이터, 또 다른 하나는 동적으로 생성된 데이터 구조, 마지막 네번째는 다른 프로그램과 함께 공유된 데이터다. 추가 데이터 세그먼트에 접근하는 것은 응용프로그램이 필요에 따라 이러한 세그먼트에 대한 세그먼트 셀렉터를 DS, ES, FS 그리고 GS 레지스터에 로드해야 한다.
SS 레지스터에는 현재 실행중인 프로그램, 작업이나 처리기에 대한 프로시저 스택이 저장되는 스택 세그먼트에 대한 세그먼트 셀렉터가 포함된다. 모든 스택 연산은 SS 레지스터를 사용하여 스택 세그먼트를 찾는다. CS 레지스터와 달리 SS 레지스터는 명시적으로 로드할 수 있으므로, 응용 프로그램이 여러 스택과 이들 사이를 전환하도록 설정할 수 있다.
세그먼트 레지스터가 실제 주소 모드에서 사용되는 방법에 대한 내용은 3.3 절 "Memory Organization"을 참조한다.
4 개의 세그먼트 레지스터 CS, DS, SS 그리고 ES는 Intel 8086과 Intel 286 프로세서에 있는 세그먼트 레지스터와 동일하며, FS와 GS 레지스터는 Intel 386™ 프로세서 제품군의 IA-32 아키텍처에 도입되었다.
3.4.2.1. 64 비트 모드에서 세그먼트 레지스터(Segment Registers in 64-Bit Mode)
64비트 모드에서 CS, DS, ES, SS는 연관된 세그먼트 디스크립트 기준의 값과 관계없이 각 세그먼트 기준이 0인것 처럼 처리된다. 이렇게 하면 코드, 데이터, 스택에 대한 평면 주소 공간이 만들어진다. FS와 GS는 예외다. 두 세그먼트 레지스터는 선형 주소 계산(로컬 데이터와 특정 운영 체제 데이터 구조의 주소 배정)에서 추가 기본 레지스터로 사용될 수 있다.
분활화가 일반적으로 불가능 하더라도, 세그먼트 레지스터로 인해 프로세서가 세그먼트 접근을 돕도록 수행할 수 있다. 이러한 작업을 수행하는 동안 활성화된 프로세서는 로드된 값에 대한 기존(legacy) 검사를 지속적으로 대부분 수행한다. (검사가 64 비트 모드에서 적용되지 않은 경우에도) 64 비트 모드에서 로드된 세그먼트 레지스터가 호환 모드에서 실행되는 응용프로그램에서 사용될 수 있기에 이러한 검사가 필요하다
64비트 모드에서 CD, DS, ES, SS, FS 그리고 GS의 검사 한계가 비활성화 된다.
3.4.3. EFLAGS 레지스터(EFLAGS Register)
32비트 EFLAGS 레지스터는 상태 플래그, 제어 플래그, 그리고 시스템의 그룹 플래그를 포함한다. 그림 3-8은 이 레지스터 안의 플래그를 정의한다. 프로세서 초기화 (RESET 핀 또는 INIT 핀을 주장함(asserting)으로써) 후 EFLAGS 레지스터의 상태는 00000002H다. 이 레지스터 비트는 1, 3, 5, 15 그리고 22 부터 31은 예약되어 있다. 소프트웨어는 이러한 비트의 상태를 사용하거나 종속해서는 안된다.
EFLAGS 레지스터의 일부 플래그는 특수 목적 명령(다음 절에서 설명)을 사용하여 직접 수정할 수 있다. 전체 레지스터를 직접 검토하거나 수정할 수 있는 명령은 없다. LAHF, SAHF, PUSHF, PUSHFD, POPF 그리고 POPFD 명령은 절차(procedure) 스택이나 EAX 레지스터에서 플래그의 그룹을 옮기는데 사용할 수 있다. EFLAGS 레지스터의 내용이 절차(procedure) 스택이나 EAX 레지스터로 부터 전송 받은 후 플래그는 프로세서의 비트 조작 명령 (BT, BTS, BTR 그리고 BTC0를 사용하여 검사하고 수정할 수 있다.
작업을 일시 중단 할 때 (프로세서의 멀티 태스킹 기능 사용), 프로세서는 일시 중단되는 작업에 대한 EFLAGS 레지스터의 상태를 작업 상태 세그먼트(TSS)에 자동으로 저장한다. 새로운 작업에 자체적으로 바인딩 할 때, 프로세서는 새로운 작업의 TSS로부터 데이터와 함께 EFLAGS 레지스터를 로드한다.
인터럽트 또는 예외 처리기 프로시저에 대한 호출이 발생하면, 프로세서는 EFLAGS 레지스터의 상태를 프로시저 스택에 자동 저장한다. 인터럽트나 예외를 태스크 스위치와 함께 처리될 때, EFLAGS 레지스터의 상태는 일시 중단된 작업을 위해 TSS에 저장된다.
IA-32 아키텍처가 발전함에 따라, 플래그가 EFLAGS 레지스터에 추가되었지만, 기존 플래그의 기능과 배치는 IA-32 프로세서 제품군에서 다음 버전으로 동일하게 유지되었다. 결과적으로, IA-32 프로세서의 한 패밀리에 대해 이러한 플래그에 접근하거나 수정하는 코드는 나중에 프로세서의 제품군에서 실행될 때 예상대로 동작한다.
3.4.3.1. 상태 플래그(Status Flags)
EFLAGS 레지스터의 상태 플래그 (비트 0, 2, 4, 6, 7 그리고 11)은 ADD, SUB, MUL 그리고 DIV 명령과 같은 산술 명령의 결과를 나타낸다. 상태 플래그 기능은 다음과 같다.
CF (bit 0) / 캐리 플래그 (Carry Flag) - 산술 연산이 결과의 최상위 비트에서 carry나 borrow를 생성하는 경우 set되며 그렇지 않으면 clear 된다. 이 플래그는 부호 없는 정수 연산의 오버플로우 조건을 나타낸다. 또한 다중 정밀도 산술에도 사용된다.
PF (bit 2) / 패리티 플래그(Parity Flag) - 결과의 최하위 바이트가 1 비트의 짝수를 포함하면 set되며 그렇지 않으면 clear된다.
AF (bit 4) / 보조 캐리 플래그(Auxiliary Carry Flag) - 산술 연산이 결과의 비트 3에서 carry나 borrow를 생성하는 경우 set되며 그렇지 않으면 clear된다. 이 플래그는 이진화 십진법(BCD, Binary-Coded Decimal) 산술에 사용된다.
ZF (bit 6) / 제로 플래그(Zero Flag) - 결과가 0인 경우 set되며 그렇지 않으면 clear된다.
SF (bit 7) / 사인 플래그(Sign Flag) - 부호있는 정수의 부호 비트인 결과의 최상위 비트와 동일하게 set한다. (0은 양수이고 1은 음수다.)
OF (bit 11) / 오버플로우 플래그(Overflow Flag) - 정수 결과가 대상 피연산자에 맞도록 양수가 너무 크거나 음수가 너무 작으면 (부호 비트 제외) set한고 그렇지 않으면 clear한다. 이 플래그는 부호 있는 정수 (2의 보수) 산술에 대한 오버플로우 조건을 나타낸다.
이 상태 플래그 중에서 STC, CLC 그리고 CMC 명령을 사용하여 CF 플래그만 직접 수정할 수 있다. 또한 비트 명령 (BT, BTS, BTR 그리고 BTC)는 지정된 비트를 CF 플래그에 복사한다.
상태 플래그는 단일 산술 연산이 부호 없는 정수, 부호 있는 정수 그리고 BCD 정수 세 가지 다른 데이터 유형에 대한 결과를 생성할 수 있다. 산술 연산의 결과가 부호 없는 정수로 처리되면, CF 플래그는 범위를 벗어난 조건(carry나 borrow)을 나타낸다. 부호 있는 정수 (2의 보수)로 취급 될 경우, F 플래그는 carry 또는 borrow를 나타낸다. 그리고 BCD 자리로 처리되면 AF 플래그는 carry 또는 borrow를 나타낸다. SF 플래그는 부호 있는 정수의 부호를 나타낸다. ZF 플래그는 부호가 있거나 부호가 없는 정수 0을 나타낸다.
정수에 대해 다중 정밀도 산술 연산을 수행할 때, CF 플래그는 carry를 추가(ADC)와 borrow 제거(SBB) 명령과 함께 사용되어 하나의 계산에서 다음 계산으로 carry 또는 borrow를 전달한다.
조건 명령 Jcc (jump on condition code cc), SETcc (byte set on condition cod ecc), LOOPcc 그리고 CMOVcc (conditional move)는 하나 이상의 상태 플래그를 조건 코드로 사용하여 분기(branch), 셋바이트(setbyte) 또는 엔드 루프 조건(end-loop conditions)를 테스트한다.
3.4.3.2. DF 플래스(DF Flag)
방향 플래그(Direction Flag) (DF, EFLAGS 레지스터의 비트 10에 위치)는 문자열 명령(MOVS, CMPS, SCAS, LODS 그리고 STOS)을 제어한다. DF 플래그를 set하면 문자열 명령이 자동으로 감소한다. (높은 주소에서 낮은 주소로 문자열을 처리하기 위해) DF 플래그를 clear하면 문자열 명령이 자동으로 증가한다. (낮은 주소에서 높은 주소로 문자열을 처리)
STD와 CLD 명령은 각 DF 플래그를 set하고 clear한다.
3.4.3.3. 시스템 플래그와 IOPL 필드(System Flags and IOPL Field)
EFLAGS 레지스터의 시스템 플래그와 IOPL 필드는 운영체제나 executive operations을 제어한다. 응용 프로그램에 의해 수정되어서는 안된다. 시스템 플래그의 기능은 다음과 같다.
TF (bit 8) / 트랩 플래그 - 디버깅을 위한 단일 단계 모드를 활성화하기 위해서 set되고 그렇지 않으면 clear한다.
IF (bit 9) / 인터럽트 활성 플래그 - 마스킹 가능한 인터럽트 요청에 대한 프로세서의 응답을 제어한다. 마스킹이 가능한 인터럽트에 응답하려면 set하고, 그렇지 않으면 clear한다.
IOPL (bits 12 and 13) / I/O 권한 레벨 필드 - 현재 실행중인 프로그램이나 작업의 I/O 권한 레벨을 나타낸다. 현재 실행중인 프로그램이나 작업의 현재 권한 레벨(CPL, Current Privilege Level)은 I/O 주소 공간에 접근하기 위해 I/O 권한 레벨보다 작거나 같아야한다. POPF와 IRET 명령은 CPL이 0일 때만 필드를 수정할 수 있다.
NT (bit 14) / 중첩 작업 플래그 - 중단 및 호출된 작업의 연결을 제어한다. 현재 작업이 이전에 실행된 작업에 연결될 때 set된다. 연결되어 있지 않으면 clear된다.
RF (bit 16) / 재시작 플래그 - 디버그 예외에 대한 프로세서의 응답을 제어한다.
VM (bit 17) / Virtual-8086 모드 플래그 - virtual-8086 모드 활성화하면 set하고 virtual-8086 모드의 의미없이 보호 모드로 돌아가려면 clear한다.
AC (bit 18) / 계열 점검 (또는 접근 제어) 플래그 - AM 비트가 CR0 레지스터에 set되면 플래그가 1인 경우에만 사용자 모드 데이터 접근의 계열 검사가 활성화된다.
SMAP 비트가 CR4 레지스터에 설정된 경우 비트가 1이면 사용자 모드 페이지에 대한 명시적 감독 모드(supervisor-mode)의 데이터 접근이 허용된다. 자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 4.6절 "Access Rights"를 참고한다.
VIF (bit 19) / 가상 인터럽트 플래그 - IF 플래그의 가상 이미지다. VIP 플래그와 함께 사용된다. (이 플래그와 VIP 플래그를 사용하려면 제어 레지스터 CR4의 VME 플래그를 설정하여 가상 모드 확장을 사용할 수 있다.)
VIP (bit 20) / 가상 인터럽트 보류 플래그 - 인터럽트가 보류중임을 나타낼때 set하고 아닐땐 clear한다. (소프트웨어는 이 플래그를 set과 clear하고 프로세서는 읽을 수만 있다.) VIF 플래그와 함께 사용된다.
ID (bit 21) / 식별 플래그 - 이 플래그를 설정하거나 지울 수 있는 프로그램의 기능은 CPUID 명령에 대한 지원을 나타낸다.
이러한 플래그의 자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 3장 "Protected-Mode Memory Management"을 참조한다.
3.4.3.4. 64 비트 모드에서 RFLAGS 레지스터(RFLAGS Register in 64-Bit Mode)
64 비트 모드에서 EFLAGS는 64 비트로 확장되어 RFLAGS로 불린다. RFLAGS 레지스터의 상위 32 비트는 예약되어 있다. RFLAGS의 하위 32 비트는 EFLAGS와 동일하다.
3.5. 명령 포인터(Instruction Pointer)
명령 포인터(EIP) 레지스터는 실행될 다음 명령에 대한 현재 코드 세그먼트의 오프셋을 포함한다. JMP, Jcc, CALL, RET 그리고 IRET 명령을 실행할 때 하나의 명령 경계에서 다음 직선 코드로 진행되거나 여러 명령어로 앞뒤로 이동한다.
EIP 레지스터는 소프트웨어로 직접 접근할 수 없다. 제어 전달 명령, 인터럽트 그리고 예외에 대해 묵시적으로 제어된다. EIP 레지스터를 읽는 유일한 방법은 CALL 명령을 실행한 다음 프로시저 스택에서 반환 명령 포인터의 값을 읽는 것이다. EIP 레지스터는 프로시저 스택의 반환 명령 포인터 값을 수정하고 반환 명령 (RET나 IRET)를 실행하여 간접적으로 로드할 수 있다. 자세한 정보는 6.2.5.2 절 "Returen Instruction Pointer"를 참조한다.
모든 IA-32 프로세서는 명령을 프리페치(prefetch)한다. 명령 프리페치로 인해 명령을 로드하는 동안 버스로 부터 읽은 명령 주소가 EIP 레지스터의 값과 일치하지 않는다. 다른 프로세서 세대가 다른 프리페치 메커니즘을 사용하더라도 프로그램 흐름을 지시하는 EIP 레지스터의 기능은 IA-32 프로세서에서 실행되도록 작성된 모든 소프트웨어와 완벽하게 호환된다.
3.5.1. 64 비트 모드에서 명령 포인터(Instruction Pointer in 64-Bit Mode)
64 비트 모드에서 RIP 레지스터가 명령 포인터다. 이 레지스터는 실행된 다음 명령의 64 비트 오프셋을 유지한다. 64 비트 모드는 RIP 상대 주소 배정이라는 기술도 지원한다. 이 기술을 사용하면, 유표 주소는 다음 명령의 RIP에 변위를 추가하도록 결정된다.
3.6. 피연산자 크기와 주소 크기 속성(Operand-Size And Address-Size Attributes)
프로세서가 보호 모드에서 실행할 때 모든 코드 세그먼트는 주소 크기 속성과 피연산자 크기 속성이 있다. 이러한 속성은 코드 세그먼트를 위한 세그먼트 디스크립터의 D (기본 크기)플래그로 선택된다. (자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A의 3장 "Protected-Mode Memory Management"를 참조한다. D 플래그가 set되면 32 비트 피연산자 크기와 주소 크기 속성이 선택된다. 플래그가 clear할 때, 16 비트 크기 속성은 선택된다. 프로세서가 실제 주소 모드, virtual-8086 모드 또는 SMM에서 실행할 때, 기본 피연산자 크기와 주소 크기 속성은 항상 16 비트로 구성된다.
피연산자 크기 속성은 피연산자의 크기를 선택한다.16 비트 피연산자 크기 속성으로 적용할 때, 피연산자는 일반적으로 8 비트나 16 비트일 수 있으며, 32 비트 피연산자 크기 속성으로 적용한 경우, 피연산자는 일반적으로 8 비트 또는 32 비트가 될 수 있다.
주소 크기 속성은 메모리 주소 배정에 사용되는 주소의 크기 16비트나 32비트를 선택한다. 16 비트 주소 크기 속성으로 적용할 때, 세그먼트 오프셋과 변위는 16비트다. 이 제한 사항은 세그먼트의 크기를 64KB로 제한한다. 32 비트 주소 크기 속성으로 적용될 때 세그먼트 오프셋과 변위는 32 비트이므로 최대 4GB를 처리할 수 있다.
기본 피연산자 크기 속성과 또는 주소 크기 속성은 명령에 피연산자 크기 속성과 주소 크기 속성 접두사를 추가하여 특정 명령을 무시할 수 있다. 자세한 내용은 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2A의 2장 "Instruction Format"을 참조한다. 이 접두어의 효과는 대상 명령에만 적용된다.
표 3-4는 D 플래그와 피연산자 크기 그리고 주소 크기 접두어의 설정에 따라 유효한 피연산자 크기와 주소 크기(보호 모드나 호환 모드에서 실행한 경우)를 보여준다.
3.6.1. 64비트 모드의 피연산자 크기와 주소 크기(Operand Size and Address Size in 64-Bit Mode)
64 비트 모드에서 기본 주소 크기는 64 비트고 기본 피연산자 크기는 32 비트다. 접두사를 사용하여 기본값을 무시할 수 있다. 주소 크기와 피연산자 크기 접두사를 사용하면 명령별 32/64 비트 데이터와 32/64 비트 주소를 혼합할 수 있다. 표 3-4는 64 비트 모드에서 피연산자 크기를 무시하는데 사용할 수 있는 66H 명령 접두어와 REX.W 접두어 유효한 조합을 보여준다. 64 비트 모드에서 16 비트 주소는 지원하지 않는다.
REX 접두어는 16개의 다른 값으로 구성하는 4비트 필드로 구성된다. REX 접두어에서 W 비트 필드는 REX.W로 부른다. REX.W 필드가 올바르게 set한 경우, 접두사는 64 비트의 피연산자 크기를 무시하도록 지정한다. 소프트웨어는 여전히 피연산자 크기 66H 접두어를 사용하여 16 비트 피연산자 크기로 껏다 켰다할 수 있다. 그러나 REX.W를 설정하면 피연산자 크기 접두사 (66H)보다 우선한다.
SSE/SSE2/SSE3/SSSE3 SIMD 명령의 경우, 66H, F2H, F3H 접두사는 opcode 확장에 필수다. 이 경우 유효한 REX.W 접두어와 66H opcode 확장 접두사 사이에 상호작용은 존재하지 않는다.
자세한 정보는 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2A의 2장 "Instruction Format"을 참조한다.
3.7. 피연산자 주소 배정(OPERAND ADDRESSING)
IA-32 기계 명령은 0개 이상의 피연산자에서 동작한다. 일부 피연산자는 명시적으로 지정되고, 다른 피연산자는 묵시적으로 지정된다. 근원지(Source) 피연산자에 대한 데이터는 다음 위치에 있다.
- 명령 자체 (즉시 피연산자)
- 레지스터
- 메모리 위치
- I/O 포트
명령에 대한 목적지(Destination) 피연산자에 데이터를 반환할 때, 다음과 같이 반환될 수 있다.
- 레지스터
- 레모리 위치
- I/O 포트
3.7.1. 직접 피연산자(Immediate Operands)
일부 명령은 명령 자체에서 인코딩된 데이터를 근원지(Source) 피연산자로 사용한다. 이러한 피연산자는 직접 피연산자(또는 단순히 즉각 연산(immediates))로 불린다. 예를 들어 다음 ADD 명령은 EAX 레지스터의 내용에 즉시 값 14를 추가한다.
ADD EAX, 14
모든 산술 명령 (DIV와 IDIV 명령은 제외)은 근원지(Source) 피연산자는 즉시 해당 값을 연산하도록 허용한다. 직접 피연산자에 허용되는 최대 값은 명령에 따다 다르지만 절대 부호 없는 더블 워드 정수(232)의 최대 값보다 클 수 없다.
3.7.2. 레지스터 피연산자(Register Operands)
근원지(Source)와 목적지(Destination) 피연산자는 실행중인 명령에 따라 다음 레지스터 중 하나가 될 수 있다.
- 32-비트 범용 레지스터 (EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP)
- 16-비트 범용 레지스터 (AX, BX, CX, DX, SI, DI, SP, BP)
- 8-비트 범용 레지스터 (AH, BH, CH, DH, AL, BL, CL, DL)
- 세그먼트 레지스터 (CS, DS, SS, ES, FS, GS)
- EFLAGS 레지스터
- x87 FPU 레지스터 (ST0부터 ST7, status word, control word, tag word, data operand pointer, and instruction pointer)
- MMX 레지스터 (MM0부터 MM7)
- XMM 레지스터 (XMM0부터 XMM7)와 the MXCSR 레지스터
- 제어 레지스터 (CR0, CR2, CR3, CR4)와 시스템 테이블 포인터 레지스터(GDTR, LDTR, IDTR, 작업 레지스터)
- 디버그 레지스터 (DR0, DR1, DR2, DR3, DR6, and DR7)
- MSR 레지스터
일부 명령은 한쌍의 32 비트 레지스터에 포함된 쿼드워드 피연산자를 사용한다. 레지스터 쌍은 이를 구분하기 위해 콜론으로 표시된다. 예를 들어, 레지스터 쌍 EDX:EAX에서 쿼드워드 피연산자의 EDX는 상위 명령 비트를 포함하고, EAX는 하위 명령 비트를 포함한다.
EFLAGS 레지스터의 내용을 로드하고 저장하거나 레지스터의 개별 플래그를 set하거나 clear하는데 필요한 몇 가지 명령(PUSHFD와 POPFD 명령 같은)이 제공된다. 다른 명령(Jcc 명령과 같은)은 분기 또는 기타 의사 결정 작업을 위한 조건 코드로 EFLAGS 레지스터에서 상태 플래그의 상태를 사용한다.
프로세서는 메모리 관리, 인터럽트와 예외 처리, 작업 관리, 프로세서 관리 그리고 디버깅 활동을 제어하는데 사용되는 시스템 레지스터의 집합을 포함한다. 이러한 시스템 레지스터의 일부는 시스텀 명령의 집합을 통해 응용프로그램, 운영 체제 또는 executive가 접근할 수 있다. 시스템 명령과 함께 시스템 레지스터에 접근할 때, 레지스터는 일반적으로 명령의 묵시적인 피연산자다.
3.7.2.1. 64-비트 모드에서 레지스터 피연산자(Register Operands in 64-Bit Mode)
64 비트 모드의 레지스터 피연산자는 다음 중 하나 일 수 있다.
- 64-비트 범용 레지스터 (RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP, or R8-R15)
- 32-비트 범용 레지스터 (EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP, or R8D-R15D)
- 16-비트 범용 레지스터 (AX, BX, CX, DX, SI, DI, SP, BP, or R8W-R15W)
- 8-비트 범용 레지스터: AL, BL, CL, DL, SIL, DIL, SPL, BPL, 그리고 R8L-R15L은 REX 접두어를 사용할 수 있다. AL, BL, CL, DL, AH, BH, CH, DH는 REX 접두어 없이 사용할 수 있다.
- 세그먼트 레지스터 (CS, DS, SS, ES, FS, and GS)
- RFLAGS 레지스터
- x87 FPU 레지스터 (ST0부터 ST7까지, 상태 워드, 제어 워드, 태그 워드, 데이터 피연산자 포인터, 명령 포인터)
- MMX 레지스터 (MM0 through MM7)
- XMM 레지스터 (XMM0 through XMM15) and the MXCSR register
- 제어 레지스터 (CR0, CR2, CR3, CR4, and CR8) and system table pointer registers (GDTR, LDTR, IDTR, and task register)
- 디버그 레지스터 (DR0, DR1, DR2, DR3, DR6, and DR7)
- MSR 레지스터
- RDX:RAX 레지스터 128 비트 피연산자를 나타내는 쌍
3.7.3. 메모리 피연산자(Memory Operands)
메모리에서 근원지(Source)와 목적지(Destination) 피연산자는 세그먼트 셀렉터와 오프셋을 통해 참조된다. (그림 3-9) 세그먼트 셀렉터는 피연산자를 포함하는 세그먼트를 지정한다. 오프셋은 피연산자의 선형 또는 유효 주소를 지정한다. 오프셋은 32 비트 (표기법 m16:32로 표시)나 16 비트(표기법 m16:16으로 표시)가 될 수 있다.
3.7.3.1. 64 비트에서 메모리 피연산자(Memory Operands in 64-Bit Mode)
64-비트 모드에서 메모리 피연산자는 세그먼트 셀렉터와 오프셋에 의해 참조될 수 있다. 오프셋은 16 비트, 32 비트 또는 64 비트일 수 있다. (그림 3-10)
3.7.4. 세그먼트 셀렉터 지정(Specifying a Segment Selector)
세그먼트 셀렉터는 명시적이나 묵시적으로 지정할 수 있다. 세그먼트 셀렉터 지정의 일반적인 방법은 세그먼트 레지스터에 로드한 다음 프로세서가 수행중인 작업 유형에 따라 묵시적으로 레지스터를 선택하도록 허용한다. 프로세서는 표 3-5에서 주어진 규칙에 따라 세그먼트를 자동으로 선택한다.
메모리로부터 데이터를 로드하거나 메모리에 데이터를 저장할 때 DS 세그먼트 기본값은 다른 세그먼트에 접근될 수 있도록 무시할 수 있다. 어셈블러 내에서 세그먼트 재정의는 일반적으로 콜론 ":" 연산자로 처리된다. 예를 들어, 다음 MOV 명령은 EAX 레지스터에서 ES 레지스터가 가리키는 세그먼트로 값을 이동한다. 세그먼트의 오프셋은 EBX 레지스터에 포함된다.
MOV ES:[EBX], EAX;
기계 레벨에서 세그먼트 재정의는 세그먼트-재정의 접두어로 지정되며, 이는 명령의 시작 부분에 배치된 바이트다. 다음 기본 세그먼트 집합은 재정의 할 수 없다.
- 명령 페치(fetch)는 코드 세그먼트에서 만들어야 한다.
- 문자열 명령의 목적지 문자열은 ES 레지스터가 가리키는 데이터 세그먼트에 저장해야 한다.
- push와 pop 동작은 SS 세그먼트를 참조해야 한다.
일부 명령은 세그먼트 셀렉터를 명시적으로 지정되도록 요구한다. 이러한 경우 16-비트 세그먼트 셀렉터는 메모리 위치나 16-비트 레지스터에 위치할 수 있다. 예를 들어, 다음 MOV 명령은 레지스터 BX에 있는 세그먼트 셀렉터를 세그먼트 레지스터 DS로 이동한다.
MOV DS, BX
세그먼트 셀렉터는 메모리에 48-비트 원거리 포인터의 일부로 명시적으로 지정될 수도 있다. 여기서 메모리의 첫번째 더블 워드는 오프셋을 포함하고 다음 워드는 세그먼트 셀렉터를 포함한다.
3.7.4.1. 64-비트 모드에서 세그먼테이션(Segmentation in 64-Bit Mode)
IA-32e 모드에서 세그먼테화의 영향은 프로세서가 호환 모드 또는 64-비트 모드에서 실행되는지 여부에 따라 다르다. 호환 모드에서, 세그먼트화 기능은 기존 IA-32 모드와 동일하게 동작하며, 위에서 설명한 16-비트나 32-비트 보호 모드 의미를 사용한다.
64-비트 모드에서 세그먼트화는 일반적으로 (하지만 완벽하진 않음)비활성화되고, 평면 64-비트 선형 주소 공간을 생성한다. 프로세서는 CS, DS, ES, SS의 세그먼트 기준을 0으로 처리하여 실효 주소와 동일한 선형 주소를 만든다. 예외적으로 FS와 GS 세그먼트가 있으며, 세그먼트 레지스터 (세그먼트 기준을 유지)는 일부 선형 주소 계산에서 추가 기본 레지스터로 사용될 수 있다.
3.7.5. 오프셋 지정(Specifying an Offset)
메모리 주소의 오프셋 부분은 정적인 값 (변위라 부름)으로 직접 지정하거나 다음 구성 요소 중 하나 이상의 방법으로 주소를 계산하여 지정할 수 있다.
- 변위(Displacement) - 8-비트, 16-비트 또는 32-비트 값
- 베이스(Base) - 범용 레지스터의 값
- 인덱스(Index) - 범용 레지스터의 값
- 축척 계수(Scale factor) - 인젝스 값을 곱한 2, 4 또는 8의 값
이러한 구성 요소를 추가하여 생성한 오프셋을 실효 주소(Effective Address)라고 한다. 이들 각 구성 요소는 긍정과 부정 (2s complement) 값을 가질 수 있으며, scaling factor는 예외다. 그림 3-11은 이러한 구성 요소를 결합하여 선택한 세그먼트에서 유효한 주소를 생상하는 가능한 모든 방법을 보여준다.
base 또는 index 구성 요소로서의 범용 레지스터의 사용은 다음과 같은 방식으로 한정된다.
- ESP 레지스터는 인젝스 레지스터로 사용할 수 없다.
- ESP 또는 EBP 레지스타가 base로 사용될 때, SS 세그먼트는 기본 세그먼트이다. 다른 모든 경우에 DS 세그먼트는 기본 세그먼트다.
base, index 그리고 displacement 구성 요소는 어떤 조합으로도 사용될 수 있으며, 이러한 구성 요소 중 무언가는 NULL이 될 수 있다. scale factor는 index가 사용되는 경우에만 사용될 수 있다. 가능한 각 조합은 프로그래머가 고급 언어와 어셈블리 언어에서 일반적으로 사용하는 데이터 구조에 유용하다.
다음 주소 배정 모드는 주소 구성 요소의 일반적인 조합에 대한 사용을 시사한다.
- Displacement - displacement만이 피연산자에 대한 직접적인(계산되지 않은) 오프셋을 나타낸다. displacement가 명령에서 인코딩되므로, 이 주소 형태를 절대 주소 또는 정적 주소로 부른다. 일반적으로 정적으로 할당된 스칼라 피연산자(scalar operand)에 접근하는데 사용된다.
- Base - base 만으로 피연산자에 대한 간접 오프셋을 나타낸다. 기본 레지스터의 값이 변경될 수 있으므로 변수와 데이터 구조의 동적 저장에 사용할 수 있다.
- Base + Displacement - base 레지스터와 displacement를 두 가지 목적으로 함께 사용할 수 있다.
- 요소 크기가 2, 4 또는 8 바이트가 아닌 경우 배열의 index—displacement 구성 요소는 정적 오프셋을 배열의 시작 부분으로 인코딩한다. base 레지스터는 배열의 특정 요소에 대한 오프셋을 결정하기 위해 계산 결과를 유지한다.
- 레코드의 필드에 접근하는 것: base 레지스터는 레코드 시작의 주소를 보유하고, displacement는 필드에 대한 정적 오프셋이다.
특별히 이 조합이 중요한 경우는 프로시저 활성화 레코드의 매개 변수에 대한 접근이다. 프로시저 활성화 레코드는 프로시저가 입력 될 때 생성되는 스택 프레임이다. 여기서, EBP 레지스터는 스택 세그먼트를 자동으로 선택하기에 base 레지스터에 가장 적합한 옵션이다. 이는 이러한 공통 기능을 위한 간결한 인코딩이다.
- (Index ∗ Scale) + Displacement - 이 주소 모드는 요소 크기가 2, 4 또는 8 바이트일 때 정적 배열에 효율적으로 index할 수 있는 방법을 제공한다. displacement는 배열의 시작 부분을 찾고, 인덱스 레지스터는 원하는 배열 요소의 첨자를 유지하고, 프로세서는 scaling factor를 적용하여 첨자(subscript)를 idnex로 자동 변환한다.
- Base + Index + Displacement - 두 개의 레지스터를 함께 사하는 것은 2 차원 배열 (displacement가 배열의 시작 주소를 유지함)이나 레코드 배열의 여러 인스턴스 중 하나(displacement는 내부 필드의 오프셋)를 지원한다.
- Base + (Index ∗ Scale) + Displacement - 모든 주소 배정 구성 요소를 함께 사용하면 배열의 요소가 2, 4 또는 8 바이트 크기일 때 2차원 배열을 효율적으로 인덱싱하도록 허용한다.
3.7.5.1. 64-비트 모드에서 오프셋 지정(Specifying an Offset in 64-Bit Mode)
64 비트 모드에서 메모리 주소의 오프셋 부분은 다음 구성 요소 중 하나 이상으로 직접적으로 정적 값이나 주소 계산을 통해 구성되어 지정 될 수 있다.
- Displacement - 8-비트, 16-비트 또는 32-비트 값
- Base - 64-bit 범용 레지스터의 값
- Index - 64-bit 범용 레지스터의 값
- Scale factor - 인젝스 값을 곱한 2, 4 또는 8의 값
대부분의 경우 16개의 사용 가능한 범용 레지스터 중 하나에서 인덱스 값을 지정할 수 있다. 자세한 정보는 Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2A의 2장 "Instruction Format"을 참고한다.
다음과 같은 고유한 주소 구성 요소 조합도 사용할 수 있다.
- RIP + Displacement - 64-비트 모드에서 RIP-상대 주소 배정은 부호있는 32 비트 displacement를 사용하여 32-비트 값을 부호 확장하고 RIP에서 64-비트 값을 더하여 다음 명령의 실효 주소를 계산한다.
3.7.6. 어셈블러와 컴파일러 주소 배정 모드(Assembler and Compiler Addressing Modes)
기계 코드 레벨에서 displacement, base 레지스터, 인덱스 레지스터, scale factor의 선택된 조합이 명령어로 인코딩된다. 모든 어셈블러는 프로그래머가 이러한 주소 배정 구성 요소의 허용 가능한 조합을 허용하여 피연산자를 처리할 수 있다. 고급 언어 컴파일러는 프로그래머가 정의한 언어 구성에 따라 이러한 구성 요소의 적절한 조합을 선택한다.
3.7.7. I/O 포트 주소 배정(I/O Port Addressing)
프로세서는 최대 65,536개의 8-비트 I/O 포트를 포함하는 I/O 주소 공간을 지원한다. 16-비트와 32-비트 포트는 I/O 주소 공간에 정의될 수 있다. I/O 포트는 즉시 피연산자나 DX 레지스터의 값으로 주소가 배정될 수 있다. I/O 포트 주소 배정에 대한 자세한 내용은 18장 "Input/Output"을 참조한다.
'Information Technology > System Architecture' 카테고리의 다른 글
CPU(Central Processing Units) 기초 (0) | 2014.04.06 |
---|