[assembly] “FS”/ “GS”레지스터의 용도는 무엇입니까?

그래서 다음 레지스터와 그 용도가 무엇인지 알고 있습니다.

  • CS = 코드 세그먼트 (IP에 사용됨)

  • DS = 데이터 세그먼트 (MOV에 사용됨)

  • ES = 대상 세그먼트 (MOVS 등에 사용됨)

  • SS = 스택 세그먼트 (SP에 사용됨)

그러나 다음 레지스터는 어떤 용도로 사용됩니까?

  • FS = “파일 세그먼트”?

  • GS = ???

참고 : 난 하지 특정 운영 체제에 대해 물어 – 나는 그들이이 CPU에 의해 사용하기위한 있었는지에 대해 부탁 해요, 무엇이든합니다.



답변

그들이 의도 한 것과 Windows 및 Linux에서 사용되는 용도가 있습니다.

세그먼트 레지스터의 원래 의도는 프로그램이 독립적이고 영구적 인 가상 저장소의 일부가되도록 의도 된 여러 다른 (대형) 메모리 세그먼트에 액세스 할 수 있도록하는 것이 었습니다. 이 아이디어는 파일을 단순히 주소 지정이 가능한 메모리 세그먼트로 취급 하는 1966 Multics 운영 체제 에서 가져 왔습니다 . BS 없음 “파일 열기, 레코드 쓰기, 파일 닫기”, 더티 페이지 플러싱으로 “이 값을 해당 가상 데이터 세그먼트에 저장”.

현재 2010 년 운영 체제는 거대 한 단계 뒤로 물러 서기 때문에 “Eunuchs”라고 불립니다. 당신은 당신의프로세스 공간의 단일 세그먼트 소위 “플랫 (IMHO 둔) 주소 공간”을 제공 할 수 있습니다. x86-32 시스템의 세그먼트 레지스터는 여전히 실제 세그먼트 레지스터에 사용할 수 있지만 아무도 신경 쓰지 않았습니다 (전 인텔 사장 인 앤디 그 로브는 지난 세기에 인텔 엔지니어들이 에너지를 소비하고 이 기능을 구현하기위한 그의 돈은 아무도 사용하지 않을 것입니다. Go, Andy!)

AMD는 64 비트로 이동하면서 Multics를 선택 항목으로 제거해도 상관하지 않기로 결정했으며 (자선적인 해석이며, Unariable 한 것은 Multics에 대한 단서가 없다는 것입니다) 64 비트 모드에서 세그먼트 레지스터의 일반 기능을 비활성화했습니다. 스레드 로컬 저장소에 액세스하려면 스레드가 여전히 필요했고 각 스레드에는 즉시 액세스 할 수있는 스레드 상태 어딘가 (예 : 레지스터) … 스레드 로컬 저장소에 대한 포인터가 필요했습니다. Windows와 Linux는 모두 32 비트 버전에서 이러한 목적으로 FS와 GS (설명에 대해 Nick에게 감사드립니다)를 사용했기 때문에 AMD는 64 비트 세그먼트 레지스터 (GS 및 FS)를 기본적으로이 목적으로 만 사용하도록하기로 결정했습니다. 프로세스 공간의 어느 곳이든 가리켜 야합니다. 애플리케이션 코드가로드 할 수 있는지 여부는 알 수 없습니다.

각 스레드의 메모리 맵이 스레드 로컬 스토리지 ([세그먼트] 레지스터 포인터가 필요하지 않음) 인 절대 가상 주소 (예 : 0-FFF)를 갖도록 만드는 것이 구조적으로 더 예뻤을 것입니다. 1970 년대에 8 비트 OS에서이 작업을 수행했으며 작업 할 또 다른 큰 레지스터 스택을 갖는 것처럼 매우 편리했습니다.

따라서 세그먼트 레지스터는 이제 부록과 비슷합니다. 그들은 흔적적인 목적을 가지고 있습니다. 우리의 집단적 손실에.

역사를 모르는 사람들은 그것을 반복 할 운명이 아닙니다. 그들은 멍청한 일을 할 운명에 처해 있습니다.


답변

레지스터 FSGS세그먼트 레지스터입니다. 프로세서 정의 목적이 없지만 대신 OS가 실행하는 목적이 있습니다. Windows 64 비트에서 GS레지스터는 운영 체제 정의 구조를 가리키는 데 사용됩니다. FS그리고 GS일반적으로 액세스 스레드 특정 메모리에 OS 커널에 의해 사용됩니다. Windows에서 GS레지스터는 스레드 별 메모리를 관리하는 데 사용됩니다. Linux 커널은 GSCPU 특정 메모리에 액세스 하는 데 사용 합니다.


답변

FS 는 Windows 프로세스의 스레드 정보 블록 (TIB)을 가리키는 데 사용됩니다.

하나의 전형적인 예는 ( SEH )에 콜백 함수에 대한 포인터를 저장하는 것입니다 FS:[0x00].

GS 는 일반적으로 스레드 로컬 저장소 (TLS)에 대한 포인터로 사용됩니다. 이전에 보았을 수있는 한 가지 예는 스택 카나리아 보호 (stackguard)입니다. gcc에서는 다음과 같은 내용을 볼 수 있습니다.

mov    eax,gs:0x14
mov    DWORD PTR [ebp-0xc],eax


답변

인텔 매뉴얼에 따르면 64 비트 모드에서 이러한 레지스터는 일부 선형 주소 계산에서 추가 기본 레지스터로 사용하기위한 것입니다. 나는 이것을 3.7.4.1 절 (4 권 세트의 86 페이지)에서 가져왔다. 일반적으로 CPU가이 모드에있을 때 선형 주소는이 모드에서 분할이 자주 사용되지 않기 때문에 유효 주소와 동일합니다.

따라서이 플랫 주소 공간에서 FS 및 GS는 로컬 데이터뿐만 아니라 특정 운영 체제 데이터 구조 (페이지 2793, 섹션 3.2.4)를 처리하는 역할을합니다. 따라서 이러한 레지스터는 운영 체제가 사용하도록 의도되었지만 특정 설계자 결정.

32 비트 및 64 비트 모드 모두에서 재정의를 사용할 때 흥미로운 속임수가 있지만 여기에는 권한있는 소프트웨어가 포함됩니다.

“원래 의도”의 관점에서 볼 때 추가 레지스터라는 것 외에는 말하기가 어렵습니다. CPU가 실제 주소 모드 에있을 때 이는 프로세서가 고속 8086으로 실행되는 것과 같으며 이러한 레지스터는 프로그램에서 명시 적으로 액세스해야합니다. 진정한 8086 에뮬레이션을 위해 가상 8086 모드 에서 CPU를 실행 하고 이러한 레지스터는 사용되지 않습니다.


답변

TL; DR;

“FS”/ “GS”레지스터의 용도는 무엇입니까?

기본 데이터 세그먼트 (DS)를 넘어서 데이터에 액세스하기 만하면됩니다. ES와 똑같습니다.


긴 읽기 :

그래서 다음 레지스터와 그 용도가 무엇인지 알고 있습니다.

[…]

글쎄, 거의 DS는 ‘일부’데이터 세그먼트가 아니라 기본 데이터 세그먼트입니다. 기본적으로 모든 작업이 수행 되었습니까 (* 1). 이것은 기본적으로 databss. x86 코드가 다소 간결한 이유의 일부입니다. 가장 자주 액세스되는 모든 필수 데이터 (코드 및 스택 포함)는 16 비트 단축 거리 내에 있습니다.

ES는 64KiB의 DS를 초과하는 모든 것 (* 2)에 액세스하는 데 사용됩니다. 워드 프로세서의 텍스트, 스프레드 시트의 셀, 그래픽 프로그램의 그림 데이터 등과 같습니다. 흔히 가정하는 것과 달리이 데이터는 많이 액세스되지 않으므로 접두사가 필요한 것은 긴 주소 필드를 사용하는 것보다 덜 아프다.

유사하게 문자열 연산을 수행 할 때 DS와 ES를로드 (및 다시로드)해야 할 수있는 사소한 성가심 일뿐입니다. 이것은 적어도 당시 최고의 문자 처리 명령어 세트 중 하나에 의해 오프셋됩니다.

정말 아픈 것은 사용자 데이터가 64KiB를 초과하고 작업을 시작해야 할 때입니다. 일부 작업은 한 번에 하나의 데이터 항목에 대해 간단히 수행되지만 (생각해보십시오 A=A*2) 대부분의 경우 2 개 ( A=A*B) 또는 3 개의 데이터 항목 ( A=B*C)이 필요합니다. 이러한 항목이 다른 세그먼트에 있으면 ES가 작업 당 여러 번 다시로드되어 상당한 오버 헤드가 추가됩니다.

처음에는 8 비트 세계 (* 3)의 작은 프로그램과 똑같이 작은 데이터 세트를 사용하여 큰 문제는 아니었지만 곧 주요 성능 병목이되었습니다. 프로그래머 (및 컴파일러). 386을 통해 Intel은 마침내 두 개의 세그먼트를 더 추가하여 안심을 제공했습니다. 따라서 요소가 메모리에 분산 되어있는 모든 시리즈 단항 , 이진 또는 삼항 연산은 항상 ES를 다시로드하지 않고도 수행 할 수 있습니다.

프로그래밍 (적어도 어셈블리에서) 및 컴파일러 디자인의 경우 이것은 상당한 이득이었습니다. 물론 더 많을 수도 있었지만 3 개를 사용하면 기본적으로 병목이 없어 졌으므로 과도하게 사용할 필요가 없습니다.

현명하게 이름을 짓는 문자 F / G는 E 뒤의 알파벳 연속입니다. 적어도 CPU 설계 시점에서는 아무 관련이 없습니다.


* 1-단순히 두 개의 세그먼트 레지스터가 필요하므로 ES를 문자열 대상으로 사용하는 것은 예외입니다. 없이는 그다지 유용하지 않거나 항상 세그먼트 접두사가 필요합니다. 놀라운 기능 중 하나를 죽일 수 있습니다. (반복적이지 않은) 문자열 명령어를 사용하면 단일 바이트 인코딩으로 인해 최고의 성능을 얻을 수 있습니다.

* 2-돌이켜 보면 ‘Everything Else Segment’는 ‘Extra Segment’보다 이름을 더 잘 지정했을 것입니다.

* 3-8086 은 8800 이 완성 될 때까지 스톱 갭 측정 용으로 만 사용 되었으며 주로 임베디드 세계에서 8080/85 고객을 유지하기위한 것임을 기억하는 것이 항상 중요합니다 .


답변