A20 라인

A20 게이트가 활성화된 경우 80286 프로세서의 리얼 모드에서만 고위 메모리 영역을 사용할 수 있다. **A20 라인**(A20 line) 또는 **주소 라인 20**(address line 20)은 x86 기반 컴퓨터 시스템의 시스템 버스를 구성하는 전기 라인 중 하나이다. 특히 A20 라인은 주소 버스에서 21번째 비트를 전송하는 데 사용된다. 마이크로프로세서는 일반적으로 물리적 주소 공간 내 워드 수의 2를 밑으로 하는 로그와 같은 수의 주소선을 가진다. 예를 들어, 4 GB의 바이트 주소 지정 가능 물리적 공간을 가진 프로세서에는 32개의 라인(log2(4 GB) = log2(232 B) = 32)이 필요하며, 이 라인들은 A0부터 A31까지 이름이 붙여진다. 이 라인들은 전송하는 주소 비트의 0 기반 숫자에 따라 이름이 붙여진다. 최하위 비트가 첫 번째이므로 비트 0으로 번호가 매겨지고 A0 라인에서 신호가 발생한다. A20은 비트 20(21번째 비트)을 전송하며, 주소가 1 MB 또는 220에 도달하면 활성화된다.
# 개요
인텔 8086, 인텔 8088, 인텔 80186 프로세서는 20개의 주소 라인을 가졌으며, A0부터 A19까지 번호가 매겨졌다. 이 라인들을 통해 프로세서는 220바이트, 즉 1 MB에 접근할 수 있었다. 이러한 프로세서의 내부 주소 레지스터는 16비트만을 가졌다. 20비트 주소 공간에 접근하기 위해 외부 메모리 참조는 16비트 세그먼트 번호에 4비트 왼쪽으로 시프트된 16비트 오프셋 주소를 더하여 20비트 물리적 주소를 생성했다. 결과적인 주소는 세그먼트 × 16 \+ 오프셋과 같다. 동일한 20비트 물리적 주소를 생성하는 많은 세그먼트 및 오프셋 조합이 존재했다. 따라서 메모리에서 동일한 바이트를 주소 지정하는 다양한 방법이 있었다. 예를 들어, 물리적 주소가 0x000FFFFF (1 MB 메모리 공간의 마지막 바이트)인 바이트를 참조하는 4096가지 세그먼트:오프셋 조합 중 4가지가 있다. : F000:FFFF : FFFF:000F : F555:AAAF : F800:7FFF 마지막 방식으로 참조하면, 오프셋을 1 증가시키면 F800:8000이 되는데, 이는 프로세서에게 올바른 주소이지만 물리적 주소 0x00100000 (1 MB를 넘는 첫 번째 바이트)로 변환되기 때문에 프로세서는 해당 바이트에 실제로 접근하려면 다른 주소 라인이 필요했다. 8086 계열 프로세서에는 그러한 라인이 없으므로, 위의 21번째 비트는 설정되어도 제거되어 주소 F800:8000이 "랩어라운드"되어 실제로 물리적 주소 0x00000000을 가리키게 된다. IBM이 IBM PC AT (1984) 기계를 설계했을 때, 새로운 고성능 인텔 80286 마이크로프로세서를 사용하기로 결정했다. 80286은 보호 모드에서 최대 16 MB의 시스템 메모리를 주소 지정할 수 있었다. 그러나 CPU는 리얼 모드 (시작 모드)에서 8086의 동작을 에뮬레이트하여 보호 모드용으로 작성되지 않은 운영체제 및 프로그램을 실행할 수 있어야 했다. 그러나 80286은 리얼 모드에서 A20 라인을 0으로 강제하지 않았다. 따라서 조합 F800:8000은 더 이상 물리적 주소 0x00000000을 가리키지 않고, 주소 0x00100000을 가리키게 되었다. 결과적으로 주소 랩어라운드에 의존하는 프로그램은 더 이상 작동하지 않았다. 그러한 프로그램과의 호환성을 유지하기 위해 IBM은 메인보드에서 문제를 해결하기로 결정했다. 이는 프로세서와 시스템 버스 사이의 A20 라인에 논리 회로를 삽입하여 이루어졌으며, 이 회로는 Gate-A20으로 명명되었다. Gate-A20은 주소 버스가 A20에서 신호를 받도록 허용하거나 방지하기 위해 소프트웨어로 활성화 또는 비활성화할 수 있다. 랩어라운드에 의존하는 오래된 프로그램을 실행하기 위해 비통과(non-passing)로 설정된다. 부팅 시 바이오스는 시스템 메모리 전체를 계산하고 테스트할 때 먼저 Gate-A20을 활성화한 다음, 운영체제로 제어를 넘기기 전에 비활성화한다. 원래 논리 회로는 인텔 8042 키보드 컨트롤러에 연결된 게이트였다. 이를 제어하는 것은 비교적 느린 과정이었다. 이후 이 랩어라운드를 필요로 하는 프로그램과 시스템 메모리 전체에 접근하는 프로그램의 보다 효율적인 다중작업을 허용하기 위해 다른 방법들이 추가되었다. A20 라인을 제어하는 여러 가지 방법이 있다. A20을 분리하면 1 MB를 넘는 모든 메모리 접근이 랩어라운드되는 것이 아니라, 1–2 MB, 3–4 MB, 5–6 MB 등과 같은 범위에서만 랩어라운드된다. 리얼 모드 소프트웨어는 1 MB 바로 위의 영역에만 관심이 있었으므로 Gate-A20 라인으로 충분했다. Gate-A20 라인을 활성화하는 것은 보호 모드 x86 운영체제가 부팅 과정에서 수행하는 첫 번째 단계 중 하나이며, 종종 커널로 제어가 넘어가기 전 (예: 리눅스의 경우)에 이루어진다. 인텔 80386에서 도입된 가상 86모드는 프로세서의 가상 메모리 기능을 사용하여 A20 랩어라운드를 시뮬레이션할 수 있도록 한다. 물리적 메모리를 여러 가상 주소에 매핑할 수 있다. 따라서 가상 메모리의 첫 번째 메가바이트에 매핑된 메모리는 가상 메모리의 두 번째 메가바이트에 다시 매핑될 수 있다. 운영체제는 Gate A20의 변경 사항을 가로채서 가상 메모리 주소 공간에 해당하는 변경 사항을 적용할 수 있으며, 이는 Gate-A20 라인 토글링의 효율성을 무의미하게 만든다.
# A20 게이트
A20 라인을 제어하는 것은 IBM PC 아키텍처 성장의 한 단계에서 중요한 기능이었는데, 이는 중요한 소프트웨어 변경 없이 리얼 모드에서 추가적인 65,520바이트 (64 KB − 16 바이트)의 메모리에 접근을 가능하게 했다. 논쟁의 여지가 있지만 "핵"이라고 할 수 있는 A20 게이트는 원래 메인보드의 키보드 컨트롤러의 일부였으며, 원하는 동작에 따라 게이트를 열거나 닫을 수 있었다. 인텔 8086과의 완벽한 호환성을 유지하기 위해 A20 게이트는 2008년까지 인텔 CPU에 여전히 존재했다.access-date=22 May 2023 게이트는 부팅 직후 처음에 닫혔기 때문에 보호 모드 운영체제는 일반적으로 부팅 과정 초기에 A20 게이트를 열고 다시 닫지 않았다. 이러한 운영체제는 게이트를 닫아둘 호환성 이유가 없었고, 게이트를 열어 사용 가능한 물리적 주소의 전체 범위에 접근할 수 있었다. 인텔 80486과 펜티엄은 A20M#이라는 특수 핀을 추가했는데, 이 핀이 낮게 설정되면 모든 온칩 캐시 또는 외부 메모리 접근에 대해 물리적 주소의 20번째 비트를 0으로 강제한다. 80486은 온칩 캐시를 도입했으므로 외부 로직에서 이 비트를 마스킹하는 것이 더 이상 불가능했기 때문에 필요했다. 소프트웨어는 여전히 게이트를 조작해야 하며, 이를 위해 여전히 외부 주변 장치(칩셋)를 다루어야 한다. PC 시스템 디자인 가이드 PC 2001은 A20 라인에 대한 호환성을 제거한다. "시스템에 A20M# 생성 로직이 여전히 존재한다면, 이 로직은 I/O 포트 92, 비트 1에 대한 소프트웨어 쓰기가 A20M#이 프로세서로 어설트되지 않도록 종료되어야 한다."access-date=2023-06-03 A20 게이트에 대한 지원은 네할렘 마이크로아키텍처에서 변경되었다 (일부 소스는 A20 지원이 제거되었다고 잘못 주장한다). CPU가 A20 비트를 마스크할지 여부에 대한 신호를 받는 전용 A20M# 핀을 가지는 대신, 이 정보는 특수 버스 사이클을 사용하여 주변 하드웨어에서 CPU로 전송되도록 가상화되었다. 소프트웨어 관점에서 메커니즘은 이전과 똑같이 작동하며, 운영체제는 여전히 외부 하드웨어 (이는 다시 앞서 언급된 버스 사이클을 CPU로 보냄)를 프로그래밍하여 A20 마스킹을 비활성화해야 한다. 인텔은 하스웰부터 A20 게이트를 더 이상 지원하지 않는다. 2013년 6월 인텔 시스템 프로그래머 매뉴얼 3A권 271페이지에는 "A20M#의 기능은 주로 구형 운영체제에서 사용되며 최신 운영체제에서는 사용되지 않는다. 최신 인텔 64 프로세서에는 A20M#이 없을 수 있다."고 명시되어 있다.
# A20 핸들러
**A20 핸들러**는 IBM PC 메모리 관리자 소프트웨어로, 고위 메모리 영역(HMA)에 대한 접근을 제어한다. 확장 메모리 관리자는 일반적으로 이 기능을 제공한다. A20 핸들러는 마이크로프로세서의 21번째 주소 라인인 A20 라인에서 이름을 따왔다. 도스에서 HIMEM.SYS와 같은 HMA 관리자는 A20을 관리하는 "추가적인 작업"을 수행한다. HIMEM.SYS는 A20을 열고 닫는 API를 제공했다. 도스 자체도 일부 저장 요구 사항에 이 영역을 사용하여 프로그램에 더 많은 기존 메모리를 확보할 수 있었다. 이 기능은 CONFIG.SYS 구성 파일의 `DOS=HIGH` 또는 `HIDOS=ON` 지시문에 의해 활성화되었다.
# CALL 5영향을 받는 프로그램
1980년부터 주소 랩어라운드는 86-도스와 MS-DOS에 의해 내부적으로 프로그램 세그먼트 접두사(PSP)의 오프셋 +5에서 +9에 CALL 5 진입점을 구현하는 데 사용되었다 (이는 CP/M-80 스타일 CALL 5 BDOS API 진입점을 오프셋 +5에서 +7에 에뮬레이션한다) (이는 부분적으로 CP/M-80의 제로 페이지와 유사하다). 이는 특히 시애틀 컴퓨터 프로덕츠의 TRANS86과 같은 어셈블리어 변환기를 통해 CP/M-80에서 기계 번역된 프로그램에 의해 활용되었다. 이 진입점이 참조하는 CALL 5 핸들러는 기계의 물리적 주소 0x000000C0에 위치한다 (따라서 인터럽트 서비스 루틴 진입점 중 INT 30h 및 x86 리얼 모드 인터럽트 벡터 테이블의 INT 31h의 첫 번째 바이트에 예약된 4바이트와 겹친다). 그러나 응용 프로그램이 실행될 수 있는 메모리 바로 위에 운영체제를 로드하는 CP/M-80의 설계에 따라, 제로 페이지의 오프셋 +6에서 +7에 저장된 8080/Z80 16비트 대상 주소는 의도적으로 첫 번째 메모리 세그먼트의 크기로도 해석될 수 있었다. DOS의 8086 세그먼트:오프셋 주소 지정 방식에서 이를 에뮬레이션하려면, 파 콜 진입점의 16비트 오프셋이 이 세그먼트 크기 (즉, 0xFEF0)와 일치해야 했으며, 이는 PSP의 오프셋 +6에서 +7에 저장되어 CALL 5의 일부와 겹쳤다. 이러한 요구 사항을 조화시키는 유일한 방법은 0xFEF0에 더할 때 0x001000C0 주소를 생성하고, 8086에서 0x000000C0로 랩어라운드되는 세그먼트 값을 선택하는 것이었다. 랩어라운드가 발생하고 이 인터페이스를 사용하는 DOS 프로그램이 작동하려면 A20을 비활성화해야 했다. 자신들의 일부를 HMA로 재배치할 수 있는 최신 DOS 버전은 일반적으로 HMA의 FFFF:00D0 (이는 물리적 0x001000C0으로 다시 해석된다)에 진입점 사본을 만들어, A20 상태와 관계없이 인터페이스가 작동할 수 있도록 한다. CALL 5 인터페이스를 사용하는 것으로 알려진 프로그램 중 하나는 Small-C 컴파일러의 DOS 버전이다. 또한 마이크로소프트의 워드 3.0 (1987)의 SPELL 유틸리티는 CALL 5 인터페이스가 그에 따라 설정되어야 하는 프로그램 중 하나이다. 썬 마이크로시스템즈의 PC-NFS (1993)도 CALL 5 픽스업을 필요로 한다. 또한 프로그램 공간을 절약하기 위해 일부 바이오스 및 DOS 프로그래머들은 예를 들어, 프로그램 데이터 (예: F800:0000부터 F800:7FFF까지, 물리적 주소 0x000F8000–0x000FFFFF를 가리킴)와 첫 번째 메모리 세그먼트에 위치한 I/O 데이터 (예: 키보드 버퍼, 주소 F800:8000부터 F800:FFFF까지, 물리적 주소 0x00000000부터 0x00007FFF를 가리킴)에 모두 접근할 수 있는 하나의 세그먼트를 가지는 트릭을 사용했다. 이 트릭은 코드가 RAM의 첫 64 KB인 낮은 메모리에서 실행되지 않는 한 작동한다. 이는 로드-하이 기능이 없는 구형 DOS 버전에서 항상 사실인 조건이었다. DOS 커널이 더 높은 메모리 영역으로 재배치되면서 낮은 메모리가 프로그램에 점점 더 많이 사용 가능해졌고, 이는 랩어라운드에 의존하는 프로그램이 실패하는 원인이 되었다. 최신 DOS 버전의 실행 파일 로더는 영향을 받는 일부 일반적인 유형의 프로그램을 감지하여 저메모리에서도 작동하도록 즉시 패치하거나 실행을 넘기기 전에 첫 64 KB 위에 로드하려고 시도한다. 자동으로 감지되지 않는 프로그램의 경우, LOADFIX 또는 MEMMAX -L을 사용하여 프로그램이 첫 64 KB 위에 로드되도록 강제할 수 있다. 이 트릭은 IBM/마이크로소프트 파스칼 자체와 이 언어로 컴파일된 프로그램에 의해 활용되었으며, 마이크로소프트의 MASM도 포함된다. 이 기능을 사용하는 다른 일반적으로 사용되는 개발 유틸리티는 Realia의 Spacemaker (로버트 B. K. 데워가 1982년에 작성했으며 초기 노턴 유틸리티를 압축하는 데 사용됨)와 마이크로소프트의 EXEPACK (루벤 보먼이 1985년에 작성)와 같은 실행 압축기뿐만 아니라 마이크로소프트의 LINK 3.02 이상 버전의 동등한 /E[XEPACK] 옵션도 포함되었다. EXEPACK으로 처리된 프로그램은 "압축된 파일이 손상되었습니다"라는 오류 메시지를 표시할 것이다. 압축된 실행 파일을 수정하기 위한 다양한 타사 유틸리티가 존재하며, 문제의 압축 해제 루틴을 재스텁을 통해 교체하거나 원본 파일을 확장 및 복원하려고 시도한다. 최신 레거시 바이오스 부트 로더 (예: GNU GRUB)는 A20 라인을 사용한다. 통일 확장 펌웨어 인터페이스 부트 로더는 32비트 보호 모드 또는 64비트 롱 모드를 사용한다.