Intel x86 Assembly Language & Microarchitecture
등록 기초
수색…
16 비트 레지스터
인텔이 원래 8086을 정의했을 때, 20 비트 주소 버스를 가진 16 비트 프로세서였습니다 (아래 참조). 그들은 8 개의 범용 16 비트 레지스터를 정의했지만 특정 명령어에 대해 특정 역할을 수행했습니다.
-
AXAccumulator 레지스터.
많은 opcode가이 레지스터를 사용하거나 지정된 경우 더 빠릅니다. -
DX데이터 레지스터.
이것은 때때로AX와 32 비트 값의 상위 16 비트로 결합되었습니다 (예 : 곱셈의 결과). -
CXCount 레지스터.
이것은LOOPNE(동일하지 않은 경우 루프) 및REP(반복 된 이동 / 비교)와 같은 루프에 대한 암시 적 카운터로 많은 루프 지향 명령어에서 사용되었습니다. -
BX베이스 레지스터.
이것은 메모리에서 구조체의 기본을 인덱싱하는 데 사용할 수 있습니다. 위의 레지스터 중 어느 것도 메모리에 직접 인덱싱하는 데 사용할 수 없습니다. -
SI소스 인덱스 레지스터.
이것은 특정 이동 및 비교 작업을위한 메모리에 대한 암시 적 소스 인덱스였습니다. -
DI목적지 인덱스 레지스터.
이것은 특정 이동 및 비교 작업을위한 메모리에 대한 암시 적 대상 인덱스였습니다. -
SP스택 포인터 레지스터.
이것은 세트에서 가장 적은 범용 레지스터입니다! 스택의 현재 위치는PUSH및POP작업에 명시 적으로 사용되었으며 암시 적으로 서브 루틴과 함께CALL및RET대해서는 암시 적으로, 인터럽트 동안에는 암시 적으로 VERY로 지정되었습니다. 따라서 다른 용도로 사용하면 프로그램에 위험합니다! -
BP베이스 포인터 레지스터.
서브 루틴이 다른 서브 루틴을 호출하면 스택은 여러 "스택 프레임"을 보유합니다.BP는 현재 스택 프레임을 유지하는 데 사용될 수 있으며 새 서브 루틴이 호출되면 스택에 저장 될 수 있고 새로운 스택 프레임이 생성되어 사용되며 내부 서브 루틴에서 반환 될 때 이전 스택 프레임 값이 복원 될 수 있습니다 .
노트:
처음 세 레지스터는 메모리로 인덱싱하는 데 사용할 수 없습니다.
BX,SI및DI를 기본적으로 현재 데이터 세그먼트에 색인화합니다 (아래 참조).MOV AX, [BX+5] ; Point into Data Segment MOV AX, ES:[DI+5] ; Override into Extra SegmentDI는MOVS및CMPS와 같은 메모리 - 메모리 연산에서 사용되는 경우에만 Extra Segment를 사용합니다 (아래 참조). 이것은 무시 될 수 없습니다.SP와BP는 기본적으로 스택 세그먼트 (아래 참조)를 사용합니다.
32 비트 레지스터
인텔은 80386을 생산할 때 16 비트 프로세서에서 32 비트 프로세서로 업그레이드했습니다. 32 비트 처리는 두 가지를 의미합니다. 조작되는 데이터는 모두 32 비트 였고 액세스되는 메모리 주소는 32 비트였습니다. 이를 위해 이전 프로세서와의 호환성을 유지하면서 완전히 새로운 프로세서 모드를 도입했습니다. 그것은 16 비트 모드 또는 32 비트 모드 중 하나 였지만 데이터, 어드레싱 또는 둘 모두에 대해 명령어별로이 모드를 오버라이드 할 수있었습니다!
우선, 32 비트 레지스터를 정의해야했습니다. 그들은 기존의 8 비트를 16 비트에서 32 비트로 확장하고 E 접두사 EAX , EBX , ECX , EDX , ESI , EDI , EBP 및 ESP 와 함께 "확장"이름을 제공함으로써이를 수행했습니다. 이러한 레지스터의 하위 16 비트는 이전과 동일하지만 레지스터의 상반부는 ADD 및 CMP 와 같은 32 비트 연산에 사용할 수있었습니다. 상반부는 8 비트 레지스터와 마찬가지로 별도로 액세스 할 수 없었습니다.
Intel은 CMP AX,DX 16 비트 및 CMP EAX,EDX 32 비트 모드에서 동일한 연산 코드를 사용했기 때문에 별도의 16 비트 및 32 비트 모드가 있어야했습니다. ! 즉, 동일한 코드를 어느 모드에서도 실행할 수 없습니다.
"즉시 즉시
AX로 이동"에 대한 opcode는0xB8이며 즉시 값의 2 바이트가 뒤에옵니다 :0xB8 0x12 0x34
"Move immediate into
EAX"에 대한 opcode는0xB8이며 그 뒤에 4 바이트 즉시 값0xB8 0x12 0x34 0x56 0x78.0xB8 0x12 0x34 0x56 0x78
따라서 assember는 코드를 실행할 때 프로세서가 어떤 모드인지 알고 올바른 바이트 수를 출력해야합니다.
8 비트 레지스터
처음 네 개의 16 비트 레지스터 는 상위 및 하위 하프 바이트를 직접 고유 한 레지스터로 액세스 할 수 있습니다.
-
AH와AL은AX레지스터의 상한과 하한입니다. -
BH및BL은BX레지스터의 상한 및 하한입니다. -
CH및CL은CX레지스터의 상한 및 하한입니다. -
DH와DL은DX레지스터의 상한과 하한입니다.
이는 AH 또는 AL 을 변경하면 AX 도 즉시 AX 을 의미합니다. 또한 8 비트 레지스터의 모든 연산은 0xFF 에서 0x00 오버플로되어 AH 변경하지 않도록 AL 증가시키는 "파트너"에 영향을 미치지 않습니다.
64 비트 레지스터 에는 하위 바이트를 나타내는 8 비트 버전이 있습니다.
-
RSI용SIL -
RDI위한DIL -
RBP대한BPL -
RSP용SPL
레지스터 R8 ~ R15 에도 동일하게 적용됩니다. 각각의 하위 바이트 부분의 이름은 R8B ~ R15B 입니다.
세그먼트 레지스터
분할
인텔이 원래 8086을 설계 할 때 이미 16 비트 기능을 갖춘 8 비트 프로세서가 있었지만 진정한 16 비트 프로세서를 생산하려고했습니다. 그들은 또한 이미 존재했던 것보다 더 훌륭하고 능력있는 것을 생산하기를 원했기 때문에 16 비트 주소 지정 레지스터에 의해 암시 된 최대 65,536 바이트 이상의 메모리에 액세스 할 수 있기를 원했습니다.
원 세그먼트 레지스터
그래서 그들은 16 비트 주소 레지스터에 의해 인덱싱 된 64KB의 메모리 블록 인 "세그먼트"개념을 구현하여 총 메모리의 여러 영역을 다룰 수있었습니다. 이러한 세그먼트 기반을 유지하기 위해 세그먼트 레지스터가 포함되었습니다.
-
CS코드 세그먼트 레지스터.
이것은 현재 실행중인 코드의 세그먼트를 포함하며 암시 적IP(명령어 포인터) 레지스터에 의해 인덱싱됩니다. -
DS데이터 세그먼트 레지스터.
이것은 프로그램이 조작하는 데이터의 기본 세그먼트를 보유합니다. -
ES엑스트라 세그먼트 레지스터.
전체 메모리에서 동시에 데이터를 조작하기 위해 두 번째 데이터 세그먼트를 보유합니다. -
SS스택 세그먼트 레지스터.
현재 스택을 보유하는 메모리 세그먼트를 보유합니다.
세그먼트 크기?
세그먼트 레지스터는 모든 크기 일 수 있지만 16 비트 너비로 만들면 다른 레지스터와 쉽게 상호 운용 될 수 있습니다. 다음 질문은 : 세그먼트가 겹치면 그 세그먼트가 겹치게됩니까? 이 질문에 대한 대답은 액세스 할 수있는 총 메모리 크기를 결정합니다.
중복이 전혀 없다면 주소 공간은 32 비트 - 4 기가 바이트가 될 것입니다 - 당시로서는 전례가 없었습니다! 8 비트의 "자연스러운"오버랩은 24 비트 주소 공간 또는 16 메가 바이트를 생성합니다. 결국 인텔은 12 비트 오버랩으로 1 메가 바이트의 주소 공간을 만들어 프로세서에 4 개의 주소 핀을 추가로 저장하기로 결정했습니다.
더 많은 세그먼트 레지스터!
인텔은 80386을 설계 할 때 기존의 4 세그먼트 레지스터 세트가 지원할 수있는 프로그램의 복잡성으로 충분하지 않다는 사실을 알고있었습니다. 그래서 그들은 두 가지 더 추가했습니다.
-
FS원거리 세그먼트 레지스터 -
GS글로벌 세그먼트 등록
이 새로운 세그먼트 레지스터는 프로세서가 강제로 사용하지 않고 프로그래머가 원했던 용도로만 사용할 수있었습니다.
어떤 이들은 이름이 단순히 기존 세트의
C,D,E테마를 계속하기로 선택되었다고 말합니다 ...
64 비트 레지스터
AMD는 호환 가능하지만 경쟁 버전을 만들기 위해 Intel에서 80386의 디자인을 라이센스 한 프로세서 제조업체입니다. 디자인에 대한 내부적 인 변경을 수행하여 처리량을 개선하거나 디자인에 대한 다른 개선 사항을 적용하면서도 동일한 프로그램을 실행할 수있었습니다.
인텔과의 협력을 통해 인텔 32 비트 디자인을 64 비트 확장하고 32 비트 x86 코드를 실행할 수있는 최초의 64 비트 칩을 생산했습니다. 인텔은 64 비트 아키텍처 버전에서 AMD의 디자인을 따라 잡았습니다.
64 비트 디자인은 여전히 이전 버전과 호환되는 반면 레지스터 세트를 여러 가지로 변경했습니다.
- 기존의 범용 레지스터는 64 비트로 확장되었으며
R접두사 인RAX,RBX,RCX,RDX,RSI,RDI,RBP및RSP명명되었습니다.다시 말하지만,이 레지스터의 아래쪽 반은 이전과 같은
E프리픽스 레지스터 였고, 위쪽 반쪽은 독립적으로 액세스 할 수 없었습니다. -
R8,R9,R10,R11,R12,R13,R14및R15는 더 많은 64 비트 레지스터가 추가되고 이름이 지정되지 않고 번호가 매겨졌습니다.- 이들 레지스터는 32 비트 절반은 낮은
R8D통해R15D(평소 DWORD 용 D). - 이 레지스터의 하위 16 비트는 레지스터 이름에
W를R8W에서R15W까지 액세스 할 수 있습니다.
- 이들 레지스터는 32 비트 절반은 낮은
- 모든 16 개의 레지스터 중 가장 낮은 8 비트가 이제 액세스 될 수 있습니다 :
- 전통적인
AL,BL,CL및DL; - (전통적으로) 포인터 레지스터의 하위 바이트 :
SIL,DIL,BPL및SPL; - 그리고 8 개의 새로운 레지스터의 하위 바이트 :
R8B에서R15B. - 그러나
AH,BH,CH및DH는 REX 접두사를 사용하는 명령어 (64 비트 피연산자 크기 또는 R8-R15 액세스 또는SIL,DIL,BPL또는SPL액세스)에서 액세스 할 수 없습니다. REX 접두사를 사용하면 대신AH를 의미하는 기계 코드 비트 패턴은SPL등을 의미합니다. 인텔의 지침 참조 설명서 (볼륨 2)의 표 3-1을 참조하십시오.
- 전통적인
32 비트 레지스터에 쓰는 것은 8 비트 또는 16 비트 레지스터에 쓰는 것과는 달리 전체 너비 레지스터의 상위 32 비트를 항상 0으로 만듭니다 (이전 값과 병합 됨, 이는 순서가 잘못된 실행에 대한 추가 종속성입니다) ).
플래그 등록
x86 산술 논리 단위 (ALU)가 NOT 및 ADD 와 같은 연산을 수행하면 특수 16 비트 FLAGS 레지스터에서 이러한 연산의 결과에 플래그를 지정합니다 ( "0", "오버플로", "음수가되었습니다"). 32 비트 프로세서는이를 32 비트로 업그레이드하여 EFLAGS 라고 불렀지 만 64 비트 프로세서는이를 64 비트로 업그레이드하여 RFLAGS 라고 불렀습니다.
조건 코드
그러나 이름에 관계없이 등록부는 직접 액세스 할 수 없습니다 (몇 가지 지침 제외 - 아래 참조). 대신 Jcc 및 SETcc 라고하는 Jcc 또는 조건부 집합과 같은 특정 지침에서 개별 플래그가 참조됩니다. 여기서 cc 는 "조건 코드"를 의미하며 다음 표를 참조합니다.
| 조건 코드 | 이름 | 정의 |
|---|---|---|
E , Z | 평등, 제로 | ZF == 1 |
NE , NZ | 평등하지 않고 0이 아닙니다. | ZF == 0 |
O | 과다 | OF == 1 |
NO | 오버플로 없음 | OF == 0 |
S | 서명 됨 | SF == 1 |
NS | 서명되지 않음 | SF == 0 |
P | 둥가 | PF == 1 |
NP | 패리티 없음 | PF == 0 |
| -------------- | ---- | ---------- |
C , B , NAE | 따라 가기, 위에 있지 않거나 같음 | CF == 1 |
NC , NB , AE | 나르 지 않거나, 아래 또는 같지 않음 | CF == 0 |
A , NBE | 위, 아래 또는 같지 않음 | CF == 0 및 ZF == 0 |
NA , BE | 위, 아래 또는 같지 않음 | CF == 1 또는 ZF == 1 |
| --------------- | ---- | ---------- |
GE , NL | 보다 크거나 같음, 덜 나아지지 않음 | SF == OF |
NGE , L | 크거나 같지 않음, 덜 | SF ! = OF |
G , NLE | 크거나 작거나 같지 않음 | ZF == 0이고 SF == OF |
NG , LE | 크거나 작거나 같음 | ZF == 1 또는 SF ! = OF |
16 비트에서 0 에서 1 을 빼는 것은 부호없는 또는 부호가있는 산술이 사용되는지 여부에 따라 65,535 또는 -1 이지만 대상은 0xFFFF 어느 방향 으로든 보유합니다. 의미가 명확하다는 조건 코드 만 해석하면됩니다. 경우 더욱 말하고 1 에서 제외되기 0x8000 : 부호없는 산술에서, 즉 단순히 변경 32,768 에 32,767 ; 서명 연산에있는 동안은 변경 -32,768 에 32,767 훨씬 더 주목할만한 오버 플로우 -!
조건 코드는 테이블에서 세 가지 블록으로 그룹화됩니다 (부호없는 페이지, 서명되지 않은 페이지 및 서명 된 페이지). 후자의 두 블록 내의 이름은 서명되지 않은 경우에는 "Above"와 "Below"를 사용하고 서명 된 경우에는 "Greater"또는 "Less"를 사용합니다. 따라서 JB 는 "뛰어 오르는 경우"(서명되지 않음)이고, JL 은 "작아 진다면"(서명 된) 것입니다.
FLAGS 직접 액세스하기
위의 조건 코드는 사전 정의 된 개념을 해석하는 데 유용하지만 실제 플래그 비트는 다음 두 가지 명령어로 직접 사용할 수도 있습니다.
-
LAHFAH레지스터에 플래그를로드합니다. -
SAHFAH레지스터를 플래그에 저장
이 명령어로 특정 플래그 만 복사됩니다. 전체 FLAGS / EFLAGS / RFLAGS 레지스터는 스택에 저장하거나 복원 할 수 있습니다.
-
PUSHF/POPF스택에 / 스택에서 16 비트FLAGS푸시 / 팝 -
PUSHFD/POPFD스택에 /에서 32 비트EFLAGS푸시 / 팝 -
PUSHFQ/POPFQ푸쉬 / 팝 64 비트RFLAGS스택에서 상 /
인터럽트는 현재 [R/E]FLAGS 레지스터를 자동으로 저장 및 복원합니다.
기타 플래그
위에서 설명한 ALU 플래그뿐만 아니라 FLAGS 레지스터는 다른 시스템 상태 플래그를 정의합니다.
-
IF인터럽트 플래그.
인터럽트를 전역 적으로 활성화하는STI명령어로 설정되며 인터럽트를 전역 적으로 비활성화하는CLI명령어로 해제됩니다. -
DF방향 플래그.
CMPS및MOVS와 같은 메모리 - 메모리 연산 (메모리 위치를 비교하고 이동)은 명령어의 일부로 인덱스 레지스터를 자동으로 증가 또는 감소시킵니다.DF플래그는 어느 것이 발생하는지 지시합니다 :CLD명령으로 지워지면 증가합니다.STD명령어로 설정하면 감소합니다. -
TF트랩 플래그. 이것은 디버그 플래그입니다. 이것을 설정하면 프로세서가 "single-step"모드가됩니다. 각 명령어가 실행 된 후 디버거에서 처리 할 것으로 예상되는 "Single Step Interrupt Handler"를 호출합니다. 이 플래그를 설정하거나 지우는 방법은 없습니다 : 메모리에있는 동안 비트를 조작해야합니다.
80286 플래그
인텔은 80286의 새로운 멀티 태스킹 기능을 지원하기 위해 FLAGS 레지스터에 플래그를 추가했습니다.
-
IOPLI / O 특권 레벨.
멀티 태스킹 코드를 보호하기 위해 일부 작업에서는 I / O 포트에 액세스 할 수있는 권한이 필요했지만 일부 작업에는 I / O 포트 액세스가 중지되어야했습니다. 인텔은 4 수준의 권한 등급을 도입했으며002 는 권한이 가장 높고112 는 가장 적은 권한을가집니다.IOPL이 현재 권한 수준보다 낮 으면 I / O 포트에 액세스하거나 인터럽트를 활성화 또는 비활성화하려는 시도는 대신 일반 보호 오류를 발생시킵니다. -
NT중첩 작업 플래그.
이 플래그는 한 태스크가 다른 태스크를CALL하여 컨텍스트 전환을 유발 한 경우에 설정되었습니다. 설정 플래그는RET가 실행될 때 컨텍스트 전환을 다시 수행하도록 프로세서에 지시합니다.
80386 플래그
'386은 프로세서에 설계된 추가 기능을 지원하기 위해 여분의 플래그가 필요했습니다.
-
RF이력서 플래그.
`386은 특정 메모리 위치의 읽기, 쓰기 또는 실행과 같은 다양한 하드웨어 액세스에서 디버거를 호출 할 수있는 디버그 레지스터를 추가했습니다. 그러나 디버그 처리기가 명령을 실행하기 위해 반환 되면 액세스가 즉시 디버그 처리기를 다시 호출합니다! 또는 디버그 핸들러에 진입 할 때 자동으로 설정되고 모든 명령어가 실행될 때마다 자동으로 지워지는 재개 플래그가 아닌 경우 적어도 발생합니다. Resume 플래그가 설정되어 있으면 Debug 핸들러가 호출되지 않습니다. -
VM가상 8086 플래그.
새로운 32 비트 코드뿐만 아니라 더 오래된 16 비트 코드를 지원하기 위해 80386은 가상 8086 집행부의 도움을 받아 "가상 8086"모드에서 16 비트 작업을 실행할 수 있습니다.VM플래그가이 작업이 가상 8086 작업임을 나타냅니다.
80486 플래그
인텔 아키텍처가 개선됨에 따라 캐시 및 슈퍼 스칼라 실행과 같은 기술을 통해 빨라졌습니다. 그것은 가정을함으로써 시스템에 대한 액세스를 최적화해야했습니다. 이러한 가정을 제어하기 위해 더 많은 플래그가 필요했습니다.
-
AC정렬 검사 플래그 x86 아키텍처는 크기가 조정되어야하는 아키텍처 (4 바이트 값이 4 바이트 경계에 있어야 함)와 달리 모든 바이트 경계에서 멀티 바이트 메모리 값에 항상 액세스 할 수 있습니다. 그러나 정렬되지 않은 데이터에 액세스하려면 여러 메모리 액세스가 필요했기 때문에 그렇게하는 것이 덜 효율적이었습니다.AC플래그가 설정된 경우 정렬되지 않은 액세스는 코드를 실행하지 않고 예외를 발생시킵니다. 이렇게하면AC세트로 개발하는 동안 코드를 향상시킬 수 있지만 프로덕션 코드에서는 사용할 수 없습니다.
펜티엄 플래그
펜티엄은 가상화에 대한 추가 지원과 CPUID 명령 지원을 추가했습니다.
-
VIF가상 인터럽트 플래그.
이것은이 작업의IF의 가상 복사본입니다.이 작업이 인터럽트를 사용하지 않도록 설정했는지 여부는 실제로 전역 인터럽트에 영향을 미치지 않습니다. -
VIP가상 인터럽트 보류 플래그.
이는 인터럽트가VIF에 의해 사실상 차단되었으므로 태스크가STI수행 할 때 가상 인터럽트를 발생시킬 수 있음을 나타냅니다. -
IDCPUID허용 된 플래그.
이 태스크가CPUID명령을 실행할 수 있도록 허용할지 여부. 가상 모니터는이를 허용하지 않을 수도 있고 명령을 실행하는 경우 요청한 태스크에 "거짓말"할 수도 있습니다.