첫 번째 BIOS 명령어가 0xFFFFFFF0 (RAM의 "맨 위")에있는 이유는 무엇입니까?


51

BIOS가 0xFFFFFFF0에서 첫 번째 명령을로드한다는 것을 알고 있지만 왜이 특정 주소입니까? 나는 많은 질문을 가지고 있으며 적어도 당신이 그들 중 일부를 도울 수 있기를 바랍니다.

내 질문 :

  • 첫 번째 BIOS 명령어가 4GB RAM의 "맨 위"에있는 이유는 무엇입니까?
  • 컴퓨터에 1GB의 RAM 만 있으면 어떻게됩니까?
  • RAM이 4GB를 초과하는 시스템 (예 : 8GB, 16GB 등)은 어떻습니까?
  • 왜 스택이 어떤 값 (이 경우 0xFFFFFFF0에있는 값)으로 초기화됩니까?

나는 오늘 오후에 그것에 대해 읽었지만 여전히 얻지 못합니다.


28
질문 당 하나의 질문하십시오.
Monica와의 가벼움 경주

4
나는 수용 된 답변이 세그먼트 메모리 또는 주소 지정 모드를 전혀 언급하지 않는 방법을 좋아하며 A20 라인이 만지는 유일한 위치는 주석에 있습니다.
imallett

Atmel AVR은 주소 0에서 실행을 시작하고 Freescale HCS08은 0xFFFE, iirc에서 시작합니다. 각 프로세서 제품군에는 고유 한 특성이 있습니다.
Nick T

2
@imallett 저는 포스터에 추가 정보로 답변을 업데이트하도록 요청하는 대신 여기에 대해 불만을 표명하는 방법을 좋아합니다. 또한 질문을 할 목적으로 OP가 발견 할 수있는 이러한 지식이 이제 완전히 이해하고있는 것들에 대한 지식을 얻는 것입니다.
MonkeyZeus

2
@MonkeyZeus는 지금까지 9 명의 다른 주석가가 이미 그 작업을 수행했지만 여전히 변경되지 않았습니다. 냉담한 동안 나의 의견은 공허하지 않았다. 미래 네티즌과 OP에게 경고입니다.
imallett

답변:


57

0xFFFFFFF0x86 호환 CPU는 전원이 켜질 때 명령어 실행을 시작하는 곳입니다. 이는 하드웨어의 하드웨어 연결없이 하드 와이어 방식으로 변경되며 다른 유형의 CPU는 다르게 동작합니다.

첫 번째 BIOS 명령어가 4GB RAM의 "맨 위"에있는 이유는 무엇입니까?

4GB 주소 공간 의 "맨 위"에 있으며 전원을 켜면 BIOS 또는 UEFI ROM이 해당 주소의 읽기에 응답하도록 설정됩니다.

이것이 왜인지에 대한 나의 이론 :

프로그래밍의 거의 모든 것이 인접한 주소로 더 잘 작동합니다. CPU 설계자는 시스템 빌더가 CPU로 무엇을하고 싶은지 알지 못하므로, CPU가 공간의 중간에 주소를 다양한 목적으로 요구하도록 요구하는 것은 나쁜 생각입니다. 주소 공간의 맨 위나 맨 아래에 "비정형"상태를 유지하는 것이 좋습니다. 물론이 결정은 MMU 가없는 8086이 새로 만들어 졌을 때 이루어졌습니다 .

8086에서 인터럽트 벡터는 메모리 위치 0 이상에 존재했습니다. 인터럽트 벡터는 알려진 주소에 있어야하고 유연성을 위해 RAM에 있어야했지만 CPU 디자이너는 시스템에 얼마나 많은 RAM이 있는지 알 수 없었습니다. 따라서 80에서 발명 된 1978 년에 시스템에 4GB의 RAM이 없으므로 RAM이 0xFFFFFFF0에있을 것으로 기대하는 것은 좋은 생각이 아니기 때문에 0부터 시작하여 그에 대한 작업이 합리적이었습니다. 상단 경계에서.

물론 최소 80286부터 인터럽트 벡터를 0이 아닌 다른 시작 위치로 옮길 수는 있지만 최신 64 비트 x86 CPU는 여전히 8086 모드로 부팅되므로 모든 것이 여전히 낡은 방식으로 호환됩니다 (어리석게도) 2015 년에도 DOS를 실행할 수있는 x86 CPU가 필요하다는 소리가납니다).

따라서 인터럽트 벡터는 0에서 시작하여 위로 작동하므로 ROM은 위에서 시작하여 아래로 작동해야합니다.

컴퓨터에 1GB의 RAM 만 있으면 어떻게됩니까?

32 비트 CPU에는 4,294,967,296 개의 주소가 있으며 0 (0x00000000)부터 4294967295 (0xFFFFFFFF)까지 번호가 매겨집니다. ROM은 일부 주소에있을 수 있고 RAM은 다른 주소에있을 수 있습니다. CPU의 MMU를 사용하면 즉시 전환 할 수도 있습니다. RAM이 모든 주소에서 작동 할 필요는 없습니다.

1GB의 RAM 만 있으면 일부 주소는 읽거나 쓸 때 응답이 없습니다. 이로 인해 해당 주소에 액세스하거나 시스템이 잠길 때 유효하지 않은 데이터를 읽을 수 있습니다.

RAM이 4GB를 초과하는 시스템 (예 : 8GB, 16GB 등)은 어떻습니까?

약간 단순하게 유지 : 64 비트 CPU는 더 많은 주소 (예를 들어 0x0000000000000000에서 0xFFFFFFFFFFFFFFFFFF로 64 비트를 만드는 것 중 하나)를 가지므로 여분의 RAM이 "적합"합니다. CPU가 긴 모드 라고 가정 합니다 . 그때까지는 RAM이 존재할 수 있으며 주소 지정이 불가능합니다.

스택이 어떤 값으로 초기화되는 이유 (이 경우 0xFFFFFFF0에있는 값)?

전원을 켤 때 x86이 스택 포인터를 할당하는 항목에서 즉시 아무것도 찾을 수 없지만 일단 루틴이 시스템에 얼마나 많은 RAM이 있는지 알게되면 초기화 루틴에 의해 다시 할당되어야합니다. (아래 의견의 @Eric Towers는 전원을 켤 때 0으로 설정되어 있다고보고합니다.)


7
주소 공간을 하드웨어로 할당 할 수있는 큰 공간으로 생각하는 것이 가장 좋습니다. CPU가 메모리를 읽고 쓸 때 실제로 버스를 통해 통신을 수행하며 하드웨어는 RAM 또는 ROM과 같은 것이 특정 주소 범위에서 응답하는지 확인할 수 있습니다. 따라서 이러한 하드웨어는 CPU가 재설정 될 때 ROM이 0xFFFFFFF0에서 응답하는지 확인해야합니다. RAM이 ROM 바로 다음에 나타나는 고유 한 의무는 없습니다. 하드웨어의 기능에 따라 하드웨어가 나타내는 모든 위치에 나타날 수 있습니다.
LawrenceC

4
ROM, RAM 등에서 사용하지 않는 "구멍"또는 할당되지 않은 공간이있을 수 있습니다. 일반적으로이 공간에 액세스하면 시스템 잠금이 발생합니다.
LawrenceC

16
이 답변은 CPU가 16 비트 모드에서 32 개의 주소 비트를 사용할 수 있다고 가정합니다. 그러나 16 비트 모드에서는 20 개의 주소 비트 만 사용할 수 있습니다. 0xFFFFFFF0CPU가 32 비트 모드로 전환 될 때까지 주소 에 도달 할 수 없습니다. 지난번 BIOS 코드를 자세히 살펴보면 진입 점은이었습니다 0xFFFF0.
kasperd

6
@ MichaelKjörling 계산이 잘못되었습니다. 이동 된 세그먼트와 오프셋은 OR되지 않으며 추가됩니다. 따라서 논리적 FFFF : FFF0은 물리적 (1) 0FFE0입니다 (A20이 활성화 된 경우 선행 1이 존재 함).
Ruslan

9
@kasperd 해킹이 있습니다. 메모리 관리자는 첫 번째 긴 점프가 발생할 때까지 12 비트가 1로 설정됩니다. 그렇습니다. 논리적으로는으로 작업하고 0xFFFF0있지만 실제로는로 매핑됩니다 0xFFFFFFF0. 나는 이것이 8086과의 호환성을 위해 이루어 졌다고 생각합니다. 더 많은 최신 CPU 사용하는 것처럼0xFFFF0 보이지만 32 비트 CPU는 실제로 액세스합니다 0xFFFFFFF0(BIOS ROM에 매핑).
Luaan

26

RAM 상단에 있지 않습니다. 이더넷 컨트롤러와 같은 확장 카드의 모든 메모리와 함께 주소가 메모리 주소 공간의 맨 위에있는 ROM에 있습니다. 적어도 4GB가 설치 될 때까지 RAM과 충돌하지 않도록하십시오. 4GB 이상의 RAM이있는 시스템은 충돌을 해결하기 위해 두 가지 작업을 수행 할 수 있습니다. 저렴한 마더 보드는 ROM의 위치와 충돌하는 RAM 부분을 무시합니다. 괜찮은 사람들은 해당 RAM의 주소가 4GB 이상인 것으로 재 맵핑합니다.

스택에 대해 무엇을 묻는 지 잘 모르겠습니다. ROM에 있도록 초기화되지 않았습니다. CPU가 재설정되면 처음에는 "실제 모드"에 있으며 원래 8086과 동일하게 작동하며 16 비트 세그먼트 주소 지정을 사용하여 1MB의 메모리에만 액세스 할 수 있습니다. BIOS 코드는 1MB의 맨 위에 있습니다. BIOS는 스택을 설정하기 위해 RAM의 어느 곳을 선택하고 첫 번째 부팅 가능한 드라이브의 첫 번째 섹터를로드하고 실행합니다. 인계하고 자체 스택 (태스크 / 스레드 당 하나)을 설정하면 32 또는 64 비트 모드로 전환하는 것은 OS에 달려 있습니다.


1
답변 주셔서 대단히 감사하지만 @LawrenceC는 그의 답변에 대한 자세한 내용을 제공하고 모든 것이 어떻게 작동하는지 나에게 도움이되었습니다. 어쨌든 고마워! 3 : 나는 당신에게 upvote에 제공
페르난도 Paladini

13

첫째, 이것은 실제로 RAM과 관련이 없습니다. 우리에 대해 얘기하고 주소 공간 여기에 - 당신은 전용 메모리의 16 MiB 크기를 소유하고있다해도 32 비트 CPU의 주소 공간의 전체 32 비트를 가지고있다.

이것은 이미 귀하의 첫 번째 질문에 대한 답입니다. 실제로 이것이 설계되었을 때 실제 PC는 전체 4GiB 메모리 근처에 없었습니다. 그들은 1-16 MiB의 메모리 범위에서 더 많았습니다. 주소 공간은 모든 의도와 목적을 위해 무료였습니다.

자, 왜 정확히 0xFFFFFFF0입니까? CPU는 BIOS의 양을 모릅니다. 일부 BIOS는 몇 킬로바이트 만 필요한 반면 다른 BIOS는 전체 메가 바이트의 메모리를 사용할 수 있으며 다양한 옵션 RAM에 들어 가지 않습니다. CPU는 시작하기 위해 특정 주소로 하드 와이어되어야합니다. CPU를 구성 할 필요가 없습니다. 그러나 이것은 주소 공간의 매핑 일뿐입니다-주소는 BIOS ROM 칩에 직접 매핑됩니다 (그렇습니다.이 경우 많은 수의 RAM이 있으면이 시점에서 전체 4GiB RAM에 액세스 할 수 없습니다. 특별한 것은 아니지만 많은 장치가 주소 공간에서 자체 범위를 요구합니다). 32 비트 CPU에서이 주소는 16 비트를 제공하여 매우 기본적인 초기화를 수행합니다. 세그먼트를 설정하고 필요한 경우 주소 모드를 설정하기에 충분합니다.실제 부팅 "프로 시저". 이 시점에서, 당신은 전혀 RAM을 사용하지 않습니다-그것은 모두 단지 매핑 된 ROM입니다. 사실,이 시점에서 RAM을 사용할 준비가되지 않았습니다. 이는 BIOS POST의 작업 중 하나입니다! 16 비트 리얼 모드가 주소 0xFFFFFFF0에 어떻게 액세스합니까? 물론, 세그먼트가 있으므로 20 비트 주소 공간이 있지만 여전히 충분하지 않습니다. 글쎄, 거기에 트릭이 있습니다-첫 번째 긴 점프를 실행할 때까지 12 비트의 주소가 설정되어 높은 주소 공간에 액세스 할 수 있습니다 (0xFFF00000보다 낮은 액세스는 거부 함-긴 점프를 실행할 때까지) .

이 모든 것은 현대 운영 체제의 프로그래머 (사용자는 말할 것도없고)로부터 대부분 숨겨져있는 것입니다. 일반적으로 저수준에 액세스 할 수는 없습니다. 일부는 이미 구조를 넘어선 것입니다 (CPU 모드를 바꿀 수는 없음). 일부는 OS 커널에 의해 독점적으로 처리됩니다.

따라서 MS DOS의 구식 코딩에서 더 나은 시각을 얻을 수 있습니다. 주소 공간에 직접 매핑되는 장치 메모리의 다른 일반적인 예는 비디오 메모리에 직접 액세스하는 것입니다. 예를 들어, 텍스트를 디스플레이에 빠르게 쓰려면 주소에 직접 씁니다 B800:0000(80x25 텍스트 모드에서 오프셋을 더한 값 (y * 80 + x) * 2은 문자 당 2 바이트 씩 한 줄씩 메모리가 제대로 작동 하는 경우를 의미 함 ). 픽셀 단위로 그리려면 그래픽 모드와 시작 주소 A000:0000(일반적으로 픽셀 당 8 비트에서 320x200)를 사용했습니다. 고성능을 수행하는 것은 일반적으로 장치 설명서에 들어가서 직접 액세스하는 방법을 파악하는 것을 의미했습니다.

이것은 오늘날까지 살아 남았습니다. 숨겨져 있습니다. Windows에서는 장치 관리자에서 장치에 매핑 된 메모리 주소를 볼 수 있습니다. 네트워크 카드와 같은 속성을 열고 리소스 탭으로 이동하면 모든 메모리 범위 항목이 장치 메모리에서 기본 주소 공간으로 매핑됩니다. 그리고 32 비트에서 이러한 장치의 대부분은 2GiB (이후 3GiB) 표시 위에 다시 매핑되어 사용자가 사용할 수있는 메모리와의 충돌을 최소화하기 위해 가상 메모리의 문제는 아니지만 ( 응용 프로그램은 실제 하드웨어 주소 공간 근처에 있지 않습니다 . 예를 들어 RAM, ROM, 장치 또는 페이지 파일에 매핑 될 수있는 자체 가상화 된 메모리 청크가 있습니다.

스택에 관해서는, 기본적으로 스택이 맨 위에서 자라는 것을 이해하는 것이 좋습니다. 따라서을 수행 push하면 새 스택 포인터가됩니다. 0xFFFFFEC즉, BIOS 초기화 주소에 쓰려고 시도하지 않습니다. 물론 BIOS 초기화 루틴이 스택을 다시 매핑하기 전에 안전하게 사용할 수 있음을 의미합니다. 더 유용한 곳. 구식 프로그래밍에서 페이징이 사실상 기본값이되기 전에 스택은 일반적으로 RAM 끝에서 시작되었으며 응용 프로그램 메모리 덮어 쓰기를 시작하면 "스택 오버플로"가 발생했습니다. 메모리 보호는이 부분을 많이 바꾸었지만 일반적으로 가능한 한 이전 버전과의 호환성을 유지합니다. 최신 x86-64 CPU조차도 여전히 MS DOS 5로 부팅 할 수있는 방법에 유의하십시오 또는 Windows가 페이징에 대해 전혀 모르는 많은 DOS 응용 프로그램을 계속 실행할 수있는 방법.


3
훌륭한 대답은 확장하고 현대 프로세서가 A20 라인 마스킹 과 같은 해킹을 시작하기 시작 했기 때문에 오래된 엣지 케이스에 대한 지원은 죽어 가고 있습니다.
기본

2
마지막 단락 : BIOS는 스택을 "자유롭게"사용할 수 없습니다 : ROM에 0xFFFFFFEC매핑 할 수 없습니다 (매핑 될). 이것은 아니요 push뿐만 아니라 예를 들어 없음도 의미 call합니다. RAM이 준비 될 때까지 기다려야합니다.
Vee

7

언급 된 다른 사항 외에도 주소 무엇인지 이해하는 것이 도움이 될 수 있습니다 . 새로운 아키텍처는 복잡하지만, 역사적으로 머신은 각 메모리 사이클에서 원하는 주소를 20 ~ 32 개의 와이어로 출력 할 수 있습니다 (아키텍처에 따라, 한 쌍 또는 4 바이트의 바이트가 동시에 필요한지 여부를 기록하는 특별한 트릭). 메모리 시스템의 여러 부분은 해당 와이어의 상태를 검사하여 특정 값의 높은 값과 낮은 값의 조합을 보았을 때 활성화됩니다.

32 개의 주소 와이어가있는 머신이 1MB의 RAM과 64KB의 ROM (일부 임베디드 컨트롤러에 해당됨) 만 사용해야하는 경우, 상단 주소 와이어가 낮은 모든 주소에 대해 RAM을 활성화하고 모든 주소에 대해 ROM을 활성화 할 수 있습니다. 높은. 그러면 하단 20 주소 와이어가 RAM에 연결되어 1,048,576 바이트 중 하나를 선택하고 하단 16도 ROM에 연결되어 65,536 바이트 중 하나를 선택합니다. 나머지 11 개의 주소 와이어는 아무 것도 연결되지 않습니다.

이러한 시스템에서 주소 0x00100000-0x001FFFFF에 액세스하는 것은 RAM 주소 0x00000000-0x000FFFFF에 액세스하는 것과 같습니다. 주소 0x000200000-0x0002FFFFF 또는 0x7FF00000-0x7FFFFFFFF와 마찬가지로. 0x80000000 이상의 주소는 ROM 전체를 읽으며 64K 패턴이 공간 전체에서 반복됩니다.

프로세서에 4,294,967,296- 바이트의 주소 공간이 있더라도 하드웨어가 많은 고유 주소를 인식 할 필요는 없습니다. 주소 공간의 상단 근처에 리셋 벡터를 배치하는 것은 시스템이 얼마나 많은 RAM과 ROM을 가지고 있는지에 관계없이 잘 작동하며 주소 공간을 완전히 디코딩 할 필요가 없도록 설계되었습니다.


좋은 점-주소 지정 가능한 64 비트 메모리 공간 (또는 1x10 ^ -12)에 가까운 것을 지원하는 64 비트 하드웨어는 없습니다.
기본

3

나의 이론은 우리가 부정적인 논리를 사용하고 있기 때문에 디지털 1은 전혀 장력이 없다 (O 볼트) 초기화시 마지막 4 비트에만 장력을 가하면 프로그램 카운터 (또는 명령어 포인터)가 1111 1111에 젖을 수 있습니다. 1111 1111 1111 1111 1111 0000. 우리는 대부분의 (오래된) CPU가 16 비트이고 하위 니블이 옛날에는 단일 주소 칩으로 처리 될 수 있기 때문에 상위 28 비트를 처리 할 필요가 없습니다. 이제 32 비트 및 32 비트에서 16 비트와 호환되는 64 비트를 갖기 때문에 하드웨어가 개선되었지만 방법은 유지됩니다. 또한 바이오스는 항상 64 비트 또는 32 비트로 프로그래밍되지는 않습니다. 내 의견은 또한 기억이 항상 동일하지 않기 때문에 바이오스는 동일한 첫 번째 세그먼트에 위치해야한다는 것입니다. 우리가 바이오스가 처리되는 것을 보는 방식은 항상 실제 주소가 아닙니다. 나에게 가르쳐 준 것 ...


2

RESET시 8088/8086 호환 CPU는 0FFFF0에서 명령을 실행합니다. 이는 1MB 제한 아래 16 바이트입니다. 일반적으로이 위치 (PC 구현에서)의 ROM은 BIOS이므로 BIOS ROM의 끝에서 BIOS ROM 시작으로 이동합니다.

여기에 표시 : 시작 벡터 및 그 뒤에 '날짜'서명, IBM 5150 PC 8KB eprom 덤프 바이오스 날짜 : 1981 년 10 월 19 일

00001FEE  FF                db 0xff
00001FEF  FF                db 0xff
00001FF0  EA5BE000F0        jmp word 0xf000:0xe05b
00001FF5  3130              xor [bx+si],si
00001FF7  2F                das
00001FF8  3139              xor [bx+di],di

주소 지정은 8KB $ 2000 rom이며 시작 주소 (이 경우 롬 내에서 가능한 가장 낮은 주소는 아니지만 8KB 롬 내에서 시작 위치 (이 경우 8KB 롬 자체 내에서 절대 JMP))는 $ FFFF입니다. $ 0 세그먼트 또는 $ FFFF0 선형.

호환성과 관련하여 : 일부 '미래'또는 현재 프로세서가 주소 앞에 훨씬 더 많은 F를 가질 것으로 예상되면 중요하지 않습니다. 구형 시스템에서 최신 CPU의 호환성을 위해 추가 주소 라인은 연결되지 않은 상태로 유지되므로 데이터 버스의 데이터는 정확히 동일합니다. 최하위 비트가 FFFF0으로 유지되는 한.

(1mb 램과 그 롬의 끝에 롬이있는 시스템에서, 그 밖의 다른 것도 행복하게 생각합니다. 더 높은 주소와 대화하고 있지만 정확히 동일한 데이터를 얻는다는 것을 생각할 것입니다. A19보다 높은 주소 라인)

세계는 단지 'pcs'가 아니라는 점에 유의하십시오. ibm pc는 '사고'였습니다.이 프로세서는 'pcs'를 위해 특별히 설계되지 않았으며 PC (예 : 위성, 무기 시스템 등). 32 및 64 비트 보호 모드는 일반적으로 바람직하지 않습니다. (가상 8086 모드는 예를 들어 최신 (386+) 버전을 선택하는 이유로 훨씬 더 흥미 롭습니다). 따라서 '실행할 것'보다 '역방향 호환성'에 더 많은 것이 있습니다.


1

마더 보드는 리셋 벡터의 명령어가 BIOS 진입 점에 매핑 된 메모리 위치로 점프하는지 확인합니다. 이 점프는 전원을 켤 때 존재하는 숨겨진 기본 주소를 암시 적으로 지 웁니다. 이 모든 메모리 위치는 칩셋에 의해 유지되는 메모리 맵 덕분에 CPU에 필요한 올바른 내용을 갖습니다. 이 시점에서 RAM 모듈에는 랜덤 크랩이 있으므로 BIOS가 포함 된 플래시 메모리에 모두 매핑됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.