เนื่องจากระบบ 32 บิตไม่สามารถจัดการหมายเลข 2 ^ 33 (เนื่องจากขีด จำกัด 32 บิตที่เห็นได้ชัด) วิธีจัดการหมายเลขทศนิยม 80 บิตได้อย่างไร
มันควรจะต้องมี "80-bit" ...
เนื่องจากระบบ 32 บิตไม่สามารถจัดการหมายเลข 2 ^ 33 (เนื่องจากขีด จำกัด 32 บิตที่เห็นได้ชัด) วิธีจัดการหมายเลขทศนิยม 80 บิตได้อย่างไร
มันควรจะต้องมี "80-bit" ...
คำตอบ:
หนึ่งในความหมายของ CPU แบบ 32 บิตคือการลงทะเบียนของมันมีความกว้าง 32 บิต นี่ไม่ได้หมายความว่ามันไม่สามารถจัดการกับการพูดตัวเลข 64 บิตเพียงว่ามันต้องจัดการกับ 32 บิตครึ่งแรกก่อนแล้ว 32 วินาทีครึ่งบน (นั่นเป็นสาเหตุที่ CPU มีแฟลกพกพา ) มันช้ากว่าหาก CPU สามารถโหลดค่าในการลงทะเบียน 64 บิตที่กว้างขึ้น แต่ยังคงเป็นไปได้
ดังนั้น "bitness" ของระบบจึงไม่จำเป็นต้อง จำกัด ขนาดของหมายเลขที่โปรแกรมสามารถจัดการได้เนื่องจากคุณสามารถแยกการทำงานที่ไม่เหมาะสมกับการลงทะเบียน CPU ในการดำเนินการหลาย ๆ ครั้ง ดังนั้นจึงทำให้การทำงานช้าลงใช้หน่วยความจำมากขึ้น (ถ้าคุณต้องใช้หน่วยความจำเป็น "scratchpad") และเขียนโปรแกรมได้ยากขึ้น แต่การดำเนินการยังคงเป็นไปได้
อย่างไรก็ตามไม่มีสิ่งใดที่เกี่ยวข้องกับตัวประมวลผล Intel 32 บิตและทศนิยมเนื่องจากส่วนจุดลอยของ CPU มีการลงทะเบียนของตัวเองและมีความกว้าง 80 บิต (ในช่วงต้นของประวัติศาสตร์ x86 ความสามารถของจุดลอยตัวเป็นชิปแยกต่างหากมันถูกรวมเข้ากับซีพียูที่เริ่มต้นด้วย 80486DX)
คำตอบของ @ Breakthrough เป็นแรงบันดาลใจให้ฉันเพิ่มสิ่งนี้
ค่าจุดลอยตัวตราบเท่าที่พวกเขาจะถูกเก็บไว้ในการลงทะเบียน FPU ทำงานแตกต่างจากค่าจำนวนเต็มไบนารี
80 บิตของค่าทศนิยมจะถูกแบ่งระหว่าง mantissa และเลขชี้กำลัง (นอกจากนี้ยังมี "ฐาน" ในจำนวนจุดลอยตัวซึ่งเป็น 2 เสมอ) แมนทิสซามีเลขนัยสำคัญและเลขชี้กำลังเป็นตัวกำหนดว่าเลขนัยสำคัญเหล่านั้นใหญ่แค่ไหน ดังนั้นไม่มี "ล้น" ในการลงทะเบียนอีกถ้าจำนวนของคุณมีขนาดใหญ่เกินไปที่จะพอดีใน mantissa เพิ่มขึ้นของคุณและคุณสูญเสียความแม่นยำ - เช่นเมื่อคุณแปลงเป็นจำนวนเต็มคุณจะสูญเสียตำแหน่งทศนิยมที่ถูกต้อง - นี่คือสาเหตุที่เรียกว่าจุดลอย
หากเลขชี้กำลังของคุณใหญ่เกินไปคุณจะมีจุดลอยตัวมากเกินไป แต่คุณไม่สามารถขยายไปยังการลงทะเบียนอื่นได้อย่างง่ายดายเนื่องจากเลขชี้กำลังและแมนทิสซาเชื่อมโยงกัน
ฉันอาจไม่ถูกต้องและผิดเกี่ยวกับบางอย่าง แต่ฉันเชื่อว่านั่นเป็นส่วนสำคัญของมัน ( บทความ Wikipedia นี้แสดงให้เห็นข้างต้นอีกเล็กน้อยอย่างสังเขป)
มันก็โอเคที่จะใช้งานได้แตกต่างกันอย่างสิ้นเชิงเนื่องจากส่วน "floating-point" ทั้งหมดของ CPU นั้นอยู่ในโลกของตัวเอง - คุณใช้คำสั่ง CPU พิเศษเพื่อเข้าถึงและเช่นนั้น ยิ่งไปกว่านั้นเมื่อถามถึงประเด็นเพราะมันแยกจากกันพยานของ FPU ไม่ได้เชื่อมโยงอย่างแน่นแฟ้นกับพยานหลักฐานของซีพียูพื้นเมือง
-fomit-frame-pointer
เพื่อรับการลงทะเบียนกลับ
ทั้งหมด 32- บิต, 64- บิตและ 128- บิตอ้างถึงความยาวของตัวประมวลผลซึ่งอาจเรียกได้ว่าเป็น "ชนิดข้อมูลพื้นฐาน" บ่อยครั้งนี่คือจำนวนบิตที่ถ่ายโอนไปยัง / จาก RAM ของระบบและความกว้างของพอยน์เตอร์ (แม้ว่าจะไม่มีอะไรหยุดคุณจากการใช้ซอฟต์แวร์เพื่อเข้าถึง RAM เพิ่มเติมจากนั้นตัวชี้เดียวสามารถเข้าถึงได้)
สมมติว่าความเร็วสัญญาณนาฬิกาคงที่ (รวมถึงทุกอย่างในสถาปัตยกรรมเป็นค่าคงที่) และสมมติว่าหน่วยความจำการอ่าน / เขียนมีความเร็วเท่ากัน (เราถือว่า 1 รอบสัญญาณนาฬิกาที่นี่ แต่นี่ไกลจากกรณีในชีวิตจริง) คุณสามารถ เพิ่มตัวเลข 64- บิตสองตัวในรอบสัญญาณนาฬิกาเดียวบนเครื่อง 64 บิต (สามถ้าคุณนับจำนวนตัวเลขจาก RAM):
ADDA [NUM1], [NUM2]
STAA [RESULT]
เราสามารถทำการคำนวณแบบเดียวกันบนเครื่อง 32- บิต ... อย่างไรก็ตามบนเครื่อง 32- บิตเราจำเป็นต้องทำสิ่งนี้ในซอฟแวร์เนื่องจากต้องเพิ่ม 32 บิตที่ต่ำกว่าก่อนชดเชยการล้นแล้วเพิ่ม 64- บิตบน:
ADDA [NUM1_LOWER], [NUM2_LOWER]
STAA [RESULT_LOWER]
CLRA ; I'm assuming the condition flags are not modified by this.
BRNO CMPS ; Branch to CMPS if there was no overflow.
ADDA #1 ; If there was overflow, compensate the value of A.
CMPS ADDA [NUM1_UPPER], [NUM2_UPPER]
STAA [RESULT_UPPER]
ด้วยการใช้ไวยากรณ์แอสเซมบลีที่สร้างขึ้นของฉันคุณสามารถดูว่าการดำเนินการที่มีความแม่นยำสูงสามารถใช้เวลานานขึ้นอย่างมากในเครื่องที่มีความยาวของคำที่ต่ำกว่า นี่คือคีย์ตัวจริงสำหรับโปรเซสเซอร์ 64 บิตและ 128 บิต: ช่วยให้เราสามารถจัดการบิตจำนวนมากขึ้นในการดำเนินการครั้งเดียว เครื่องบางเครื่องมีคำแนะนำสำหรับการเพิ่มปริมาณอื่น ๆ ด้วยการพกพา (เช่นADC
x86) แต่ตัวอย่างข้างต้นมีค่าความแม่นยำในใจ
ตอนนี้เพื่อขยายคำถามนี้มันง่ายที่จะดูว่าเราสามารถเพิ่มตัวเลขที่ใหญ่กว่าทะเบียนที่เรามีได้อย่างไร - เราแค่แบ่งปัญหาให้เป็นขนาดของทะเบียนและทำงานจากที่นั่น แม้ว่าดังกล่าวโดย@MatteoItalia , สแต็ค x87 FPU มีการสนับสนุนสำหรับปริมาณ 80 บิตในระบบการขาดการสนับสนุนนี้ (หรือโปรเซสเซอร์ขาดหน่วยจุดลอยทั้งหมด!) ที่คำนวณเทียบเท่า / การดำเนินงานจะต้องดำเนินการในซอฟแวร์
ดังนั้นสำหรับตัวเลข 80 บิตหลังจากเพิ่มเซ็กเมนต์ 32 บิตแต่ละอันแล้วหนึ่งอันก็จะตรวจสอบโอเวอร์โฟลว์ลงในบิตที่ 81 และเลือกที่จะบิตบิตที่สูงกว่า การตรวจสอบ / เลขศูนย์เหล่านี้จะดำเนินการโดยอัตโนมัติสำหรับคำแนะนำ x86 และ x86-64 บางอย่างโดยที่ระบุขนาดตัวถูกดำเนินการต้นทางและปลายทาง (แม้ว่าสิ่งเหล่านี้จะถูกระบุเฉพาะในพาวเวอร์ 2 เริ่มจาก 1 ไบต์กว้าง)
แน่นอนว่าด้วยจำนวนจุดลอยตัวเราไม่สามารถทำการเพิ่มไบนารีได้อย่างง่ายดายเนื่องจาก mantissa และตัวเลขที่สำคัญถูกรวมเข้าด้วยกันในรูปแบบออฟเซ็ต ใน ALU บนโปรเซสเซอร์ x86 มีวงจรฮาร์ดแวร์เพื่อทำสิ่งนี้สำหรับ IEEE 32- บิตและ 64- บิตลอย; แม้กระนั้นแม้จะไม่มีหน่วยจุดลอยตัว (FPU) การคำนวณแบบเดียวกันก็สามารถทำได้ในซอฟต์แวร์ (เช่นผ่านการใช้ห้องสมุดวิทยาศาสตร์ของGNUซึ่งใช้ FPU เมื่อรวบรวมสถาปัตยกรรมด้วยกลับไปสู่อัลกอริธึมซอฟต์แวร์ หากไม่มีฮาร์ดแวร์แบบ floating-point [เช่นสำหรับไมโครคอนโทรลเลอร์แบบฝังที่ขาด FPU])
เมื่อให้หน่วยความจำเพียงพอผู้ใช้สามารถคำนวณจำนวนความแม่นยำโดยพลการ (หรือ "ไม่ จำกัด " - ภายในขอบเขตที่เหมือนจริง) ได้โดยใช้หน่วยความจำเพิ่มเติมตามที่ต้องการความแม่นยำมากขึ้น การใช้งานสิ่งนี้มีอยู่ในไลบรารี GNU Multiple Precisionช่วยให้มีความแม่นยำไม่ จำกัด (จนกว่า RAM ของคุณจะเต็มแน่นอน) กับการดำเนินการจำนวนเต็มเหตุผลและจุดลอยตัว
สถาปัตยกรรมหน่วยความจำของระบบอาจอนุญาตให้คุณย้าย 32 บิตในครั้งเดียว - แต่นั่นไม่ได้หยุดจากการใช้ตัวเลขขนาดใหญ่
คิดว่าการคูณ คุณอาจรู้ตารางการคูณของคุณสูงถึง 10x10 แต่คุณอาจไม่มีปัญหาในการดำเนินการ 123x321 บนกระดาษ: คุณแค่แบ่งมันเป็นปัญหาเล็ก ๆ จำนวนมากคูณตัวเลขแต่ละตัวและดูแลการพกพาเป็นต้น
โปรเซสเซอร์สามารถทำสิ่งเดียวกัน ใน "สมัยก่อน" คุณมีตัวประมวลผล 8 บิตที่สามารถคำนวณเลขทศนิยมได้ แต่พวกเขาก็พูดเหลวไหล
"32 บิต" เป็นวิธีการจัดหมวดหมู่ตัวประมวลผลไม่ใช่การตั้งค่าภายใน ตัวประมวลผล "32 บิต" โดยทั่วไปจะมีการลงทะเบียนวัตถุประสงค์ทั่วไป 32 บิตเพื่อทำงานกับ
อย่างไรก็ตามไม่มีการกำหนดความต้องการหินให้ทุกอย่างในโปรเซสเซอร์ดำเนินการเป็น 32 บิต ตัวอย่างเช่นไม่เคยได้ยินมาก่อนว่าคอมพิวเตอร์ "32- บิต" มีบัสแอดเดรส 28- บิตเพราะราคาถูกกว่าในการสร้างฮาร์ดแวร์ คอมพิวเตอร์ 64 บิตมักจะมีบัสหน่วยความจำ 40 บิตหรือ 48 บิตด้วยเหตุผลเดียวกัน
เลขทศนิยมเป็นอีกที่ที่ขนาดแตกต่างกัน โปรเซสเซอร์ 32 บิตจำนวนมากรองรับหมายเลขทศนิยม 64 บิต พวกเขาทำเช่นนั้นโดยเก็บค่าจุดลอยตัวในรีจิสเตอร์พิเศษที่กว้างกว่ารีจิสเตอร์ทั่วไป ในการจัดเก็บหนึ่งในจำนวนจุดลอยตัวขนาดใหญ่เหล่านี้ในการลงทะเบียนพิเศษอันดับแรกเราจะแบ่งจำนวนให้กับการลงทะเบียนวัตถุประสงค์ทั่วไปสองรายการจากนั้นจึงออกคำสั่งเพื่อรวมเข้ากับการลงทะเบียนแบบพิเศษ หนึ่งครั้งในการลงทะเบียนจุดลอยตัวค่าเหล่านั้นจะถูกจัดการเป็นแบบ 64- บิตลอยแทนที่จะเป็นคู่ครึ่ง 32 บิต
เลขคณิต 80 บิตที่คุณพูดถึงเป็นกรณีพิเศษของเรื่องนี้ หากคุณได้ทำงานกับหมายเลขจุดลอยตัวคุณจะคุ้นเคยกับความไม่แน่ชัดที่เกิดจากปัญหาจุดลอยตัว ทางออกหนึ่งสำหรับ roundoff คือต้องมีความแม่นยำมากขึ้น แต่แล้วคุณต้องเก็บตัวเลขที่ใหญ่กว่าและบังคับให้ผู้พัฒนาใช้ค่าทศนิยมขนาดใหญ่ผิดปกติในหน่วยความจำ
วิธีการแก้ปัญหาของ Intel คือการลงทะเบียนทศนิยมทั้งหมด 80 บิต แต่คำแนะนำในการย้ายค่าไปยัง / จากการลงทะเบียนเหล่านั้นทำงานกับหมายเลข 64 บิตเป็นหลัก ตราบใดที่คุณดำเนินการทั้งหมดภายในสแต็คจุดลอยตัว x87 ของ Intel การดำเนินการทั้งหมดของคุณจะทำด้วยความแม่นยำ 80 บิต หากรหัสของคุณต้องการดึงหนึ่งในค่าเหล่านั้นออกจากการลงทะเบียนทศนิยมและเก็บไว้ที่ใดที่หนึ่งมันจะตัดให้เหลือ 64- บิต
คุณธรรมของเรื่องราว: หมวดหมู่เช่น "32 บิต" นั้นอันตรายกว่าเสมอเมื่อคุณเจาะลึกลงไปในสิ่งต่างๆ!
ซีพียู "32- บิต" เป็นหนึ่งในการลงทะเบียนข้อมูลส่วนใหญ่คือการลงทะเบียน 32- บิตและคำแนะนำส่วนใหญ่ทำงานกับข้อมูลในการลงทะเบียน 32- บิตเหล่านั้น CPU แบบ 32 บิตมีแนวโน้มที่จะถ่ายโอนข้อมูลไปยังและจากหน่วยความจำแบบ 32 บิตในแต่ละครั้ง การลงทะเบียนส่วนใหญ่เป็น 32- บิตไม่ได้หมายความว่าการลงทะเบียนทั้งหมดเป็น 32- บิต คำตอบสั้น ๆ คือ CPU แบบ 32 บิตสามารถมีคุณสมบัติบางอย่างที่ใช้ bitcount อื่น ๆ เช่นการลงทะเบียนจุดลอยตัว 80 บิตและคำแนะนำที่เกี่ยวข้อง
ตามที่ @ spudone กล่าวในความเห็นเกี่ยวกับคำตอบของ @ ultrasawblade ซีพียู x86 ตัวแรกที่ได้รวมการดำเนินการจุดลอยตัวคือ Intel i486 (โดยเฉพาะ 80486DX แต่ไม่ใช่ 80486SX) ซึ่งตามหน้า 15-1 ของโปรแกรมเมอร์ไมโครโปรเซสเซอร์ i486 คู่มืออ้างอิงรวมถึงการลงทะเบียนเป็นตัวเลข "การลงทะเบียนตัวเลขแปดหลักแบบ 80 บิตแปดรายการ" i486 มีบัสหน่วยความจำ 32 บิตดังนั้นการถ่ายโอนค่า 80- บิตจะใช้เวลาดำเนินการ 3 หน่วยความจำ
รุ่นก่อนของรุ่น 486 คือ i386 ไม่มีการดำเนินการจุดรวมใด ๆ แต่มันได้รับการสนับสนุนสำหรับการใช้ภายนอก floating point "ประมวลผลร่วม" การประมวลผลร่วม 80387. นี้มีเกือบทำงานเดียวกันที่ถูกรวมเข้ากับ i486 ตามที่คุณสามารถดูจากหน้า 2-1 ของ 80387 อ้างอิงของโปรแกรมเมอร์คู่มือการใช้งาน
รูปแบบจุดลอยตัว 80 บิตดูเหมือนว่าเกิดขึ้นกับ 8087 ตัวประมวลผลทางคณิตศาสตร์สำหรับ 8086 และ 8088 8086 และ 8088 เป็นซีพียู 16 บิต (โดยมีบัสหน่วยความจำ 16 บิตและ 8 บิต) และยังคงสามารถ เพื่อใช้รูปแบบจุดลอยตัว 80 บิตโดยใช้ประโยชน์จากการลงทะเบียน 80 บิตในตัวประมวลผลร่วม