ทะเบียน“ FS” /“ GS” มีไว้เพื่ออะไร?


105

ดังนั้นฉันจึงรู้ว่าการลงทะเบียนต่อไปนี้และการใช้งานควรจะเป็นอย่างไร:

  • CS = กลุ่มรหัส (ใช้สำหรับ IP)

  • DS = กลุ่มข้อมูล (ใช้สำหรับ MOV)

  • ES = ส่วนปลายทาง (ใช้สำหรับ MOVS ฯลฯ )

  • SS = Stack Segment (ใช้สำหรับ SP)

แต่การลงทะเบียนต่อไปนี้มีไว้เพื่อใช้ทำอะไร?

  • FS = "ส่วนของไฟล์"?

  • GS = ???

หมายเหตุ: ฉันไม่ได้ถามเกี่ยวกับระบบปฏิบัติการใด ๆ - ฉันกำลังถามเกี่ยวกับสิ่งที่พวกเขาตั้งใจจะใช้กับ CPU ถ้ามีอะไร


25
เท่าที่ฉันรู้ F และ G ในสองตัวนี้ไม่ได้มีไว้เพื่ออะไร เพียงแค่มีที่ว่างบน CPU (และในชุดคำสั่ง) สำหรับรีจิสเตอร์เซ็กเมนต์ที่ผู้ใช้ระบุได้หกตัวและมีคนสังเกตว่านอกจากส่วนแทค "S" แล้วตัวอักษร "C" และ "D" (รหัสและข้อมูล) เรียงตามลำดับดังนั้น "E" จึงเป็นส่วน "พิเศษ" จากนั้น "F" และ "G" จะเรียงลำดับตาม
torek

3
เป็นไปได้ยากที่จะรู้ว่าเกิดอะไรขึ้นในหัวของคนอื่นเว้นแต่คุณจะอยู่ที่นั่นในเวลานั้น (และฉันอยู่อีกฝั่งไม่มีที่ไหนใกล้ทีมออกแบบของ Intel)
torek

21
ลองนึกดูสิว่าเราจะสนุกแค่ไหนกับการลงทะเบียน BS: -}
Ira Baxter

5
ฉันมักจะใช้ GS เป็น "กลุ่มกราฟิก" :-)
Brian Knoblauch

3
แล้ว egment "G" eneral "S" ล่ะ?
SS Anne

คำตอบ:


113

มีวัตถุประสงค์เพื่ออะไรและ Windows และ Linux ใช้เพื่ออะไร

ความตั้งใจเดิมที่อยู่เบื้องหลังการลงทะเบียนเซ็กเมนต์คือการอนุญาตให้โปรแกรมเข้าถึงเซ็กเมนต์หน่วยความจำ (ขนาดใหญ่) ที่แตกต่างกันจำนวนมากซึ่งตั้งใจให้เป็นอิสระและเป็นส่วนหนึ่งของที่เก็บเสมือนถาวร แนวคิดนี้นำมาจากระบบปฏิบัติการ Multics ในปี 1966ซึ่งถือว่าไฟล์เป็นเพียงส่วนหน่วยความจำที่ระบุแอดเดรสได้ ไม่มี BS "เปิดไฟล์เขียนบันทึกปิดไฟล์" เพียงแค่ "เก็บค่านี้ไว้ในส่วนข้อมูลเสมือน" ด้วยการล้างหน้าที่สกปรก

ระบบปฏิบัติการปี 2010 ในปัจจุบันของเราก้าวถอยหลังไปอีกก้าวหนึ่งซึ่งเป็นสาเหตุที่เรียกว่า "ขันที" คุณสามารถระบุเฉพาะส่วนเดียวของพื้นที่กระบวนการของคุณโดยให้สิ่งที่เรียกว่า "พื้นที่ที่อยู่แบบแบน (IMHO หมอง)" การลงทะเบียนเซ็กเมนต์บนเครื่อง x86-32 ยังสามารถใช้สำหรับการลงทะเบียนเซกเมนต์จริงได้ แต่ไม่มีใครใส่ใจ (แอนดี้โกรฟอดีตประธาน Intel มีชื่อเสียงในระดับสาธารณะเมื่อศตวรรษที่แล้วเมื่อเขาพบว่าหลังจากที่วิศวกร Intel ทั้งหมดใช้พลังงานและ เงินของเขาในการใช้คุณสมบัตินี้ซึ่งไม่มีใครจะใช้มันไปเลยแอนดี้!)

AMD ในการไปที่ 64 บิตตัดสินใจว่าพวกเขาไม่สนใจว่าพวกเขากำจัด Multics เป็นตัวเลือกหรือไม่ (นั่นคือการตีความเพื่อการกุศลสิ่งที่ไม่สามารถคิดได้คือพวกเขาไม่รู้เรื่อง Multics) และปิดใช้งานความสามารถทั่วไปของการลงทะเบียนเซ็กเมนต์ในโหมด 64 บิต ยังคงมีความจำเป็นสำหรับเธรดในการเข้าถึงที่เก็บเธรดในท้องถิ่นและแต่ละเธรดต้องการตัวชี้ ... ที่ใดที่หนึ่งในสถานะเธรดที่เข้าถึงได้ทันที (เช่นในรีจิสเตอร์) ... เนื่องจาก Windows และ Linux ทั้งคู่ใช้ FS และ GS (ขอบคุณ Nick สำหรับคำชี้แจง) เพื่อจุดประสงค์นี้ในเวอร์ชัน 32 บิต AMD จึงตัดสินใจให้ส่วนทะเบียน 64 บิต (GS และ FS) ใช้เพื่อจุดประสงค์นี้เท่านั้น (ฉันคิดว่าคุณ สามารถทำให้ชี้ไปที่ใดก็ได้ในพื้นที่กระบวนการของคุณอย่าลืมว่ารหัสแอปพลิเคชันสามารถโหลดได้หรือไม่)

มันน่าจะเป็นสถาปัตยกรรมที่สวยงามกว่า IMHO ที่จะทำให้แผนที่หน่วยความจำของแต่ละเธรดมีแอดเดรสเสมือนจริง (เช่น 0-FFF พูด) ซึ่งเป็นพื้นที่จัดเก็บเธรดในเครื่อง (ไม่จำเป็นต้องใช้ตัวชี้การลงทะเบียน [เซ็กเมนต์]!) ฉันทำสิ่งนี้ในระบบปฏิบัติการ 8 บิตย้อนกลับไปในปี 1970 และมีประโยชน์อย่างมากเช่นมีการลงทะเบียนกองใหญ่อีกชุดเพื่อใช้

ดังนั้นการลงทะเบียนกลุ่มจึงเป็นเหมือนภาคผนวกของคุณ พวกเขาทำหน้าที่เป็นร่องรอย ต่อการสูญเสียโดยรวมของเรา

ผู้ที่ไม่รู้ประวัติศาสตร์จะไม่ต้องทำซ้ำ พวกเขาถึงวาระที่จะทำอะไรบางอย่างที่โง่เขลา


11
@supercat: รูปแบบที่เรียบง่ายและยอดเยี่ยมยิ่งขึ้นซึ่งจะทำให้พวกเขาจัดการกับพื้นที่เก็บข้อมูลได้มากถึง 65536 เท่าจะถือว่าการลงทะเบียนเซกเมนต์เป็นส่วนขยาย 16 บิตบนของ 16 บิตที่ต่ำกว่าซึ่งโดยพื้นฐานแล้ว 286, 386 และ Multics ทำ
Ira Baxter

5
@IraBaxter: ปัญหาของวิธีการดังกล่าวคือเซ็กเมนต์สไตล์ 80286 มีค่าใช้จ่ายสูงพอสมควรกว่าจะจบลงด้วยการเก็บวัตถุจำนวนมากในแต่ละส่วนดังนั้นจึงจัดเก็บทั้งเซ็กเมนต์และออฟเซ็ตในทุกตัวชี้ ในทางตรงกันข้ามถ้าใครเต็มใจที่จะจัดสรรหน่วยความจำแบบทวีคูณถึง 16 ไบต์การแบ่งส่วนแบบ 8086 จะอนุญาตให้ใช้เซ็กเมนต์เพียงอย่างเดียวเป็นวิธีในการระบุวัตถุ การจัดสรรการปัดเศษสูงสุด 16 ไบต์อาจเป็นเรื่องที่น่ารำคาญเล็กน้อยในปี 1980 แต่จะแสดงถึงการชนะในวันนี้หากลดขนาดของการอ้างอิงแต่ละวัตถุจาก 8 ไบต์เป็นสี่
supercat

3
ลงทะเบียนผู้ที่จะถูกนำมาใช้ในระบบปฏิบัติการที่ทันสมัย ส่วนใหญ่มุ่งเน้นไปที่ข้อมูลเกี่ยวกับบล็อกควบคุมงานอย่างน้อยในสองระบบปฏิบัติการหลักที่มีให้สำหรับชิป x86 แล้ว และเนื่องจากสิ่งเหล่านี้ไม่ใช่ "วัตถุประสงค์ทั่วไป" อีกต่อไปแม้จะเป็นเจตนาเดิมคุณจึงไม่สามารถใช้ประโยชน์ได้มากนัก ดีกว่าที่จะแสร้งทำเป็นบนระบบ x86-64 ว่าไม่มีอยู่จริงจนกว่าคุณจะต้องการข้อมูลที่อนุญาตให้คุณเข้าถึงในบล็อกควบคุมเธรด
ไอราแบ็กซ์เตอร์

5
การเปรียบเทียบภาคผนวกนั้นแย่มากโดยอาศัยวิทยาศาสตร์ที่ล้าสมัย มันเกี่ยวข้องกับระบบภูมิคุ้มกันดังนั้นไม่ "ร่องรอย" อย่างแน่นอน มันเบี่ยงเบนไปจากโพสต์จริง นอกเหนือจากนั้นการตอบสนองที่ดี
code_dredd

5
ขอบคุณสำหรับการจัดการหน่วยความจำแบบแบ่งส่วนเทียบกับหน่วยความจำแบบแบนที่น่าขบขัน :) การเขียนโค้ดบน 6809 (มีและไม่มีหน่วยความจำแบบเพจ), 6502, z80, 68k และ 80 [123]? 86 มุมมองของฉันแบ่งออกเป็นส่วน ๆ memory คือการแสดงสยองขวัญและฉันดีใจที่มันถูกส่งไปที่ถังขยะแห่งประวัติศาสตร์ การใช้ FS และ GS เพื่อการเข้าถึงข้อมูล thread_local อย่างมีประสิทธิภาพเป็นผลที่ตามมาโดยไม่ได้ตั้งใจจากข้อผิดพลาดในอดีต
Richard Hodges

46

รีจิสเตอร์FSและGSเป็นเซกเมนต์รีจิสเตอร์ พวกเขาไม่มีวัตถุประสงค์ที่กำหนดโดยโปรเซสเซอร์ แต่จะได้รับจุดประสงค์จากระบบปฏิบัติการที่รันอยู่ ใน Windows 64 บิตรีGSจิสเตอร์จะใช้เพื่อชี้ไปที่โครงสร้างที่ระบบปฏิบัติการกำหนด FSและGSมักใช้โดยเคอร์เนล OS เพื่อเข้าถึงหน่วยความจำเฉพาะเธรด ใน windows GSรีจิสเตอร์ใช้เพื่อจัดการหน่วยความจำเฉพาะเธรด เคอร์เนล linux ใช้GSเพื่อเข้าถึงหน่วยความจำเฉพาะ cpu


1
พวกเขาตั้งใจจะใช้เพื่อวัตถุประสงค์ที่กำหนดโดยระบบปฏิบัติการหรือเพื่ออำนวยความสะดวกให้กับโค้ดที่ต้องทำอะไรบางอย่าง*dest++ = lookup[*src++];ซึ่งอาจจะค่อนข้างอึดอัดหากปลายทางการค้นหาและ src อยู่ในตำแหน่งที่ไม่เกี่ยวข้องกันสามแห่ง
supercat

8
บน Windows FS นั้นมีไว้สำหรับการจัดเก็บเฉพาะเธรด ดูเอกสารแผนที่ของบล็อกที่ FS ชี้ที่นี่en.wikipedia.org/wiki/Win32_Thread_Information_Block
Nedko

2
ไม่ใช่แค่บน Windows เท่านั้น GS ยังใช้สำหรับ TLS บน OS X อีกด้วย GS ยังใช้กับเคอร์เนล 64 บิตเพื่อติดตามโครงสร้างของระบบระหว่างสวิตช์บริบท ระบบปฏิบัติการจะใช้ SWAPGS เพื่อเอฟเฟกต์นั้น
ET

14

FSใช้เพื่อชี้ไปที่บล็อกข้อมูลเธรด (TIB) บนกระบวนการ windows

ตัวอย่างทั่วไปอย่างหนึ่งคือ ( SEH ) ซึ่งเก็บตัวชี้ไปยังฟังก์ชันเรียกกลับในรูปแบบ FS:[0x00] .

GSมักใช้เป็นตัวชี้ไปยังที่จัดเก็บเธรดในเครื่อง (TLS) และตัวอย่างหนึ่งที่คุณอาจเคยเห็นมาก่อนคือการป้องกันสแต็กคานารี่ (stackguard) ใน gcc คุณอาจเห็นสิ่งนี้:

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

2
นี่ไม่ได้ตอบคำถามจริง คำถามระบุหมายเหตุ: ฉันไม่ได้ถามเกี่ยวกับระบบปฏิบัติการใด ๆ - ฉันกำลังถามเกี่ยวกับสิ่งที่พวกเขาตั้งใจจะใช้กับ CPU ถ้ามีอะไร
Michael Petch

12
@MichaelPetch ยาฉันรู้ว่าฉันแค่ต้องการเพิ่มสิ่งนี้เป็นข้อมูลที่ดีสำหรับผู้ที่อ่าน q / s ใน SO
zerocool

3

ตามคู่มือ Intel ในโหมด 64 บิตการลงทะเบียนเหล่านี้มีจุดมุ่งหมายเพื่อใช้เป็นรีจิสเตอร์พื้นฐานเพิ่มเติมในการคำนวณที่อยู่เชิงเส้น ฉันดึงสิ่งนี้มาจากส่วน 3.7.4.1 (หน้า 86 ในชุดเสียง 4) โดยปกติเมื่อ CPU อยู่ในโหมดนี้ที่อยู่เชิงเส้นจะเหมือนกับที่อยู่ที่มีประสิทธิภาพเนื่องจากการแบ่งส่วนมักไม่ได้ใช้ในโหมดนี้

ดังนั้นในพื้นที่ที่อยู่แบบแบนนี้ FS & GS จึงมีบทบาทในการกำหนดแอดเดรสไม่ใช่แค่ข้อมูลในเครื่อง แต่โครงสร้างข้อมูลระบบปฏิบัติการบางอย่าง (หน้า 2793 ส่วน 3.2.4) ดังนั้นการลงทะเบียนเหล่านี้จึงมีจุดมุ่งหมายเพื่อใช้โดยระบบปฏิบัติการอย่างไรก็ตามนักออกแบบเหล่านั้นโดยเฉพาะ กำหนด.

มีกลอุบายที่น่าสนใจเมื่อใช้การแทนที่ทั้งในโหมด 32 และ 64 บิต แต่เกี่ยวข้องกับซอฟต์แวร์ที่มีสิทธิ์พิเศษ

จากมุมมองของ "ความตั้งใจเดิม" นั้นยากที่จะพูดได้ว่าเป็นเพียงการลงทะเบียนเพิ่มเติม เมื่อ CPU อยู่ในโหมดที่อยู่จริงจะเหมือนกับว่าโปรเซสเซอร์กำลังทำงานด้วยความเร็วสูง 8086 และโปรแกรมจะต้องเข้าถึงการลงทะเบียนเหล่านี้อย่างชัดเจน เพื่อประโยชน์ในการจำลอง 8086 ที่แท้จริงคุณจะต้องเรียกใช้ CPU ในโหมด virtual-8086และจะไม่ใช้การลงทะเบียนเหล่านี้


2

TL; DR;

ทะเบียน“ FS” /“ GS” มีไว้เพื่ออะไร?

เพียงเพื่อเข้าถึงข้อมูลนอกเหนือจากส่วนข้อมูลเริ่มต้น (DS) เหมือนกับ ES ทุกประการ


อ่านยาว:

ดังนั้นฉันจึงรู้ว่าการลงทะเบียนต่อไปนี้และการใช้งานควรจะเป็นอย่างไร:

[... ]

เกือบ แต่ DS ไม่ใช่กลุ่มข้อมูล 'บางส่วน' แต่เป็นกลุ่มข้อมูลเริ่มต้น การดำเนินการทั้งหมดเกิดขึ้นตามค่าเริ่มต้น (* 1) นี่คือตัวแปรเริ่มต้นทั้งหมดที่ตั้งอยู่ - โดยพื้นฐานdataแล้วและbssและเป็นส่วนหนึ่งของสาเหตุที่ทำให้รหัส x86 ค่อนข้างกะทัดรัด ข้อมูลที่จำเป็นทั้งหมดซึ่งเป็นสิ่งที่เข้าถึงบ่อยที่สุด (โค้ดบวกและสแต็ก) อยู่ในระยะทางสั้น 16 บิต

ES ใช้เพื่อเข้าถึงทุกสิ่งทุกอย่าง (* 2) ทุกอย่างที่อยู่นอกเหนือจาก 64 KiB ของ DS เช่นเดียวกับข้อความของโปรแกรมประมวลผลคำเซลล์ของสเปรดชีตหรือข้อมูลรูปภาพของโปรแกรมกราฟิกเป็นต้น ข้อมูลนี้ไม่ได้รับการเข้าถึงมากนักดังนั้นการใช้คำนำหน้าจึงเจ็บน้อยกว่าการใช้ฟิลด์ที่อยู่ที่ยาว

ในทำนองเดียวกันมันเป็นเพียงความน่ารำคาญเล็กน้อยที่อาจต้องโหลด DS และ ES (และโหลดซ้ำ) เมื่อดำเนินการกับสตริง - อย่างน้อยก็ชดเชยด้วยชุดคำสั่งการจัดการอักขระที่ดีที่สุดในเวลานั้น

สิ่งที่เจ็บปวดจริงๆคือเมื่อข้อมูลผู้ใช้เกิน 64 KiB และต้องเริ่มดำเนินการ แม้ว่าการดำเนินการบางอย่างจะทำเพียงครั้งละรายการข้อมูลเดียว (คิดว่าA=A*2) ส่วนใหญ่ต้องการข้อมูลสอง ( A=A*B) หรือสามรายการ ( A=B*C) หากรายการเหล่านี้อยู่ในส่วนต่างๆ ES จะถูกโหลดซ้ำหลายครั้งต่อการดำเนินการโดยเพิ่มค่าใช้จ่ายที่ค่อนข้างมาก

ในตอนแรกด้วยโปรแกรมขนาดเล็กจากโลก 8 บิต (* 3) และชุดข้อมูลที่มีขนาดเล็กเท่า ๆ กันมันไม่ใช่เรื่องใหญ่ แต่ในไม่ช้ามันก็กลายเป็นคอขวดที่มีประสิทธิภาพหลัก - และอื่น ๆ ก็เป็นความเจ็บปวดอย่างแท้จริงสำหรับ โปรแกรมเมอร์ (และคอมไพเลอร์) ด้วย 386 Intel บรรเทาส่งมอบในที่สุดโดยการเพิ่มสองกลุ่มมากขึ้นเพื่อให้ชุดใดเอก , ไบนารีหรือternaryมีองค์ประกอบที่กระจายออกไปในหน่วยความจำสามารถเกิดขึ้นได้โดยไม่ต้องโหลด ES ซ้ำ

สำหรับการเขียนโปรแกรม (อย่างน้อยในแอสเซมบลี) และการออกแบบคอมไพเลอร์สิ่งนี้ค่อนข้างได้เปรียบ แน่นอนว่าอาจมีมากกว่านี้ แต่คอขวดสามขวดก็หายไปโดยทั่วไปดังนั้นไม่จำเป็นต้องหักโหมมากเกินไป

การตั้งชื่อตัวอักษร F / G อย่างชาญฉลาดเป็นเพียงการต่อเนื่องตามตัวอักษรหลังจาก E อย่างน้อยก็จากจุดของการออกแบบ CPU ไม่มีอะไรเกี่ยวข้อง


* 1 - การใช้ ES สำหรับปลายทางสตริงเป็นข้อยกเว้นเนื่องจากจำเป็นต้องมีการลงทะเบียนเพียงสองส่วน หากไม่มีก็จะไม่มีประโยชน์มากนักหรือจำเป็นต้องมีคำนำหน้ากลุ่มเสมอไป ซึ่งสามารถฆ่าหนึ่งในคุณสมบัติที่น่าแปลกใจการใช้คำสั่งสตริง (ไม่ซ้ำซาก) ส่งผลให้เกิดประสิทธิภาพสูงสุดเนื่องจากการเข้ารหัสไบต์เดียว

* 2 - ดังนั้นในการมองย้อนกลับไป 'ทุกอย่างที่เหลือ' น่าจะเป็นวิธีการตั้งชื่อที่ดีกว่า 'กลุ่มเสริม'

* 3 - สิ่งสำคัญเสมอที่ต้องจำไว้ว่า 8086 มีความหมายเพียงการวัดช่องว่างหยุดจนกว่า8800จะเสร็จสิ้นและส่วนใหญ่มีไว้สำหรับโลกฝังตัวเพื่อให้ลูกค้า 8080/85 อยู่บนเรือ


1
ว้าวขอบคุณสำหรับการอธิบายทั้งหมดนี้! สิ่งนี้อธิบายได้มากและสมเหตุสมผลมาก! +1
user541686
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.