2014-10-24 2 views
2

x86 용 부트 로더의 일부 코드를 읽었습니다. 이 부트 로더의 첫 번째 부분은 대개 가스를 사용하여 작성됩니다. 그들은 ".code16"을 사용하여 가스가 16 비트 코드를 생성하도록 지시합니다.x86 용 부트 로더가 16 비트 코드를 사용하는 이유는 무엇입니까?

그러나 32 비트 코드가 REAL MODE에서 실행 가능하다는 것을 알았습니다. 왜 그들은 16 비트 코드를 사용합니까? ".code16"이 필요합니까?

+0

UEFI 모드로 부팅하는 경우 16 비트 코드를 사용할 필요가 없음 –

답변

3

32 비트 코드를 사용할 수 있지만 그럼에도 리얼 모드 세분화 및 BIOS 서비스가 필요합니다. 그러나 CPU가 16 비트 모드에서 실행 중이기 때문에 .code16이 필요합니다. 따라서 32 비트 명령어를 사용하려면 피연산자 및 주소 크기 오버라이드 접두사를 사용해야합니다. 지시문은 어셈블러에 지시를 추가하도록 지시합니다.

mov edx, eax.code16없이 쓰면 어셈블러에서 89 C2 기계 코드를 생성합니다. 그러나 CPU가 16 비트 모드에있을 때, 그것은 mov dx, ax으로 해석 할 것입니다. 실제로 32 비트에서 작동하려면 이라는 접두어 66이 필요합니다. .code16을 사용하면 어셈블러에서이를 수행합니다. 66 접두어는 기본적으로 "다른"모드로 전환됩니다. 즉, 16 비트 모드에서는 32 비트를 사용하고 그 반대의 경우도 사용합니다. 즉, mov dx, ax을 32 비트 코드로 작성하면 66 89 C2이되며, 16 비트 모드에서 실행하면 mov edx, eax이됩니다. 따라서 어셈블러에서 코드가 실행될 모드를 알려줘야합니다.

TL : .code16 어셈블러가 16 비트 모드에서 CPU로 실행될 때 의도 한대로 코드를 생성하도록 보장합니다.

+0

또한 32 비트 코드의 큰 장점은 세그먼트 화되지 않은 메모리 액세스라는 점을 언급해야합니다. 그러나 리얼 모드에서 메모리 주소 지정은 세그먼트 화되지 않은 방식으로 작동하지 않습니다. 'mov eax, [ebx]'는 ebx의 값이 0x10000보다 작은 경우에만 작동합니다. –

+2

왜 이런 맥락에서 언급할만한 가치가 있을까요? CPU는 16 비트 모드로되어 있으며 인코딩이 한 번에 하나의 명령을 오버라이드 할 수 있다고하더라도 기계 코드를 16 비트로 디코딩합니다. CPU가 16 비트 모드이므로, .code16은 일관성을 위해 필수입니다. –

+0

@MartinRosenau 여러분이 pmode를 빠르게 돌아가서 세그먼트 제한을 0xFFFFFFFF로 설정하면 작동 할 수 있습니다 (실제 모드로 돌아 가면 붙어 있습니다) – harold

1

인텔 :

명령 접두어는 코드 세그먼트의 기본 피연산자의 크기와 주소 크기를 대체 할 수 있습니다. 이 접두어는 보호 모드 및 가상 8086 모드뿐 아니라 실제 주소 모드에서도 사용할 수 있습니다. 피연산자 크기 또는 주소 크기 접두어는 명령어 기간 동안 크기 만 변경합니다.

다음 두 명령 프리픽스는 한 세그먼트 내에서의 32 비트 및 16 비트 연산 혼합 허용 : 를 오퍼랜드 크기 프리픽스 • (66H) 주소 크기 프리픽스 • ((67h) 안에)

이러한 접두사 코드 세그먼트 설명자에서 D 플래그로 선택된 기본 크기를] 전하십시오. 예를 들어 프로세서는 다음 네 가지 방법으로 (MOV mem, reg) 명령어를 해석 할 수 있습니다. • 32 비트 코드 세그먼트에서 : - 32 비트 레지스터를 사용하여 32 비트 레지스터에서 메모리로 32 비트 유효 주소. -operand-size 접두어가 앞에 오면 32 비트 유효 주소를 사용하여 16 비트 레지스터에서 메모리로 16 비트를 이동합니다. - 주소 크기 접두어가 앞에 붙는 경우 32 비트 레지스터에서 16 비트 유효 주소를 사용하여 메모리로 32 비트를 이동합니다. - 주소 크기 접두사와 피연산자 크기 접두사가 모두 선행 된 경우 16 비트 유효 주소를 사용하여 16 비트 레지스터에서 메모리로 16 비트를 이동합니다.

• 16 비트 코드 세그먼트에서 : - 16 비트 유효 주소를 사용하여 16 비트 레지스터에서 메모리로 16 비트를 이동합니다. -operand-size 접두사가 앞에 오면 16 비트 유효 주소를 사용하여 32 비트 레지스터에서 메모리로 32 비트를 이동합니다. - 주소 크기 접두어가 앞에 붙는 경우 32 비트 유효 주소를 사용하여 16 비트 레지스터에서 메모리로 16 비트를 이동합니다. - 주소 크기 접두사와 피연산자 크기 접두사가 모두 선행 된 경우 32 비트 유효 주소를 사용하여 32 비트 레지스터에서 메모리로 32 비트를 이동합니다.

이전 예제는 명령이 16 비트 또는 32 비트 세그먼트에 있는지 여부에 관계없이 모든 명령이 피연산자 크기와 주소 크기의 조합을 생성 할 수 있음을 보여줍니다. 코드 세그먼트에 대한 16 비트 또는 32 비트 기본값의 선택은 일반적으로 다음 기준을 기반으로합니다. • 성능 - 가능한 경우 항상 32 비트 코드 세그먼트를 사용하십시오. P6 계열 프로세서에서 16 비트 코드 세그먼트보다 훨씬 빠르게 실행되며 이전 IA-32 프로세서에서는 다소 빨라졌습니다. • 코드 세그먼트가 실행될 운영 체제 - 운영 체제가 16 비트 운영 체제 인 경우 32 비트 프로그램 모듈을 지원하지 않을 수 있습니다. • 작동 모드 - 코드 세그먼트가 실제 주소 모드, 가상 8086 모드 또는 SMM에서 실행되도록 디자인되는 경우 16 비트 코드 세그먼트 여야합니다. • 이전 IA-32 프로세서와의 하위 호환성 - 코드 세그먼트가 Intel 8086 또는 Intel 286 프로세서에서 실행될 수 있어야하는 경우에는 16 비트 코드 세그먼트 여야합니다.

코드 세그먼트 설명자의 D 플래그는 코드 세그먼트의 명령어에 대한 기본 오퍼랜드 크기와 주소 크기를 결정합니다. (세그먼트 설명자를 사용하지 않는 실제 주소 모드와 가상 8086 모드에서 기본값은 16 비트입니다.) D 플래그가 설정된 코드 세그먼트는 32 비트 세그먼트입니다. D 플래그가 클리어 된 코드 세그먼트는 16 비트 세그먼트입니다.

실행 코드 세그먼트. 이 플래그는 D 플래그라고하며 세그먼트의 명령어가 참조하는 유효 주소와 피연산자의 기본 길이를 나타냅니다. 플래그가 설정되면 32 비트 주소와 32 비트 또는 8 비트 피연산자가 사용됩니다. 명확한 경우 16 비트 주소와 16 비트 또는 8 비트 피연산자가 사용됩니다. 명령어 접두어 66H는 기본값 이외의 피연산자 크기를 선택하는 데 사용할 수 있으며 접두사 67H는 기본값 이외의 주소 크기를 선택하는 데 사용할 수 있습니다.

32 비트 피연산자 접두어는 실제 주소 모드 프로그램에서 32 비트 형식의 명령을 실행하는 데 사용할 수 있습니다. 이 접두사는 또한 실제 주소 모드 프로그램이 프로세서의 32 비트 범용 레지스터를 사용할 수있게합니다. 32 비트 주소 접두사는 실제 주소 모드 프로그램에서 사용할 수 있으므로 32 비트 오프셋을 허용합니다.

Intel386 프로세서로 시작하는 IA-32 프로세서는 주소 오버라이드 접두사를 사용하여 32 비트 오프셋을 생성 할 수 있습니다. 그러나 실제 주소 모드에서 32 비트 오프셋 값은 예외없이 FFFFH를 초과 할 수 없습니다.

어셈블러 사용법 : 실제 주소 모드에서 실행될 코드 세그먼트가 정의되면 USE 16 특성으로 설정해야합니다. 이 코드 세그먼트 (예 : MOV EAX, EBX)의 명령어에 32 비트 피연산자가 사용되면 어셈블러는 자동으로 해당 명령어의 피연산자 접두어를 생성하여 프로세서가 32 비트 연산을 실행하도록합니다. 기본 코드 세그먼트 속성은 16 비트입니다.

32 비트 피연산자 접두사를 사용하면 실제 주소 모드 프로그램에서 32 비트 범용 레지스터 (EAX, EBX, ECX, EDX, ESP, EBP, ESI 및 EDI)를 사용할 수 있습니다.

세그먼트 레지스터와 32 비트 범용 레지스터 사이에서 32 비트 모드로 데이터를 이동할 때 펜티엄 프로 프로세서는 16 비트 피연산자 크기 접두어를 사용할 필요가 없습니다. 그러나 일부 어셈블러에서는이 접두어가 필요합니다. 프로세서는 범용 레지스터의 가장 중요한 16 비트 인 비트가 대상 또는 소스 피연산자라고 가정합니다. 값을 세그먼트 선택기에서 32 비트 레지스터로 이동할 때 프로세서는 의 상위 바이트 두 개를 0으로 채 웁니다.

+0

인용문 참조 문서는 분명히 유용하지만 현재로서는 ** TL이 없기 때문에 상당히 길지만 DR **, 더 읽기 쉽도록 http://stackoverflow.com/help/formatting – xmojmr

0

첫 번째 인텔 프로세서가 모두 16 비트 코드를 사용하게되면 32 비트가 사용되지 않습니다.386 프로세서가 32 비트로 생성 될 때 인텔은 기본 시작 상태가 이전 프로세서와의 역 호환성을 위해 16 비트가되도록 지정했습니다. 그런 다음 OS 또는 부트 로더 개발자는 16 비트 명령어를 사용하여 보호 된 (32 비트) 모드에 액세스 할 수 있습니다. Intel은 이전 버전과의 호환성을 좋아하는 것으로 보이며 이전 버전의 소프트웨어와의 호환성을 유지할 수 있도록 모든 x86 프로세서에 부착되었습니다.

관련 문제