หมายเลขที่เซ็นชื่อและไม่ได้ลงนาม


17

ALU ในไมโครโปรเซสเซอร์จะแยกความแตกต่างระหว่างหมายเลขที่เซ็นชื่อ -7 ที่แสดงด้วย 1111 และหมายเลขที่ไม่ได้ลงนาม 15 และแสดงด้วย 1111 ได้อย่างไร


3
ดูคำตอบของคำถามที่เกี่ยวข้อง: cs.stackexchange.com/a/30047/28999 โดยวิธีการลงนาม -7 ไม่ได้เป็น 1111 นั่นคือ -1 จากนั้นเช่น 1111 - 0001 = 1110 ทั้งในกรณีที่ลงชื่อและไม่ได้ลงชื่อ (-2 vs 14)
Albert Hendriks

2
@AlbertHendriks ในความเป็นธรรมคอมพิวเตอร์เก่าบางรุ่นใช้ "sign-magnitude Representation" (บิตหนึ่งสัญญาณและบิตขนาด) และเรายังคงใช้รูปแบบนั้นเช่น IEEE ลอย พวกมันไม่สุภาพและทำงานหนักเมื่อเทียบกับส่วนประกอบสองอย่าง n1
Draconis

1
ความแตกต่างที่สำคัญคือวิธีการที่ผู้ประกอบการมากขึ้น / น้อยกว่า / ตันและพฤติกรรมการเปลี่ยนขวาเติมด้วยบิตสูงสุด เมื่อคุณคูณและหารผลที่ได้จะเหมือนกัน
Rob


2
@ Rob นั่นไม่ถูกต้องทั้งหมด การบวกการลบและการคูณนั้นเหมือนกันระหว่างส่วนเติมที่ไม่ได้ลงนามและส่วนเติมเต็ม - สมมติว่าอินพุตและเอาต์พุตของคุณมีขนาดเท่ากัน การหารไม่เหมือนกัน 6/2 คือ 3 แต่ -2/2 คือ -1 และซีพียูจำนวนมากมีคำแนะนำการคูณที่อินพุตทั้งสองมีขนาดเท่ากัน แต่เอาต์พุตจะมีขนาดใหญ่เป็นสองเท่า
kasperd

คำตอบ:


14

คำตอบที่สั้นและง่ายคือมันไม่ ไม่มีซีพียูกระแสหลัก ISA ที่ใช้งานได้ตามที่คุณคิด

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

โดยทั่วไป ISAs จะไม่แยกความแตกต่างระหว่างชนิดข้อมูลที่แตกต่างกันเมื่อมันมาถึงการจัดเก็บ (ไม่สนใจการลงทะเบียนวัตถุประสงค์พิเศษเช่นการลงทะเบียนแบบลอยใน FPU) มันเป็นเพียงรูปแบบบิตที่ไร้ความหมายต่อซีพียู แต่อกหักจะมีหลายชนิดที่แตกต่างกันของคำสั่งที่อาจตีความรูปแบบบิตในรูปแบบที่แตกต่างกัน ยกตัวอย่างเช่นคำแนะนำทางคณิตศาสตร์เช่นMUL, DIV, ADD, SUBตีความรูปแบบบิตเป็นชนิดของบางหมายเลขในขณะที่คำแนะนำการใช้ตรรกะเช่นAND, OR, XORตีความว่ามันเป็นอาร์เรย์ของ booleans ดังนั้นขึ้นอยู่กับโปรแกรมเมอร์ (หรือผู้เขียนล่ามหรือคอมไพเลอร์หากคุณใช้ภาษาระดับสูงกว่า) เพื่อเลือกคำแนะนำที่ถูกต้อง

อาจมีคำแนะนำแยกต่างหากสำหรับหมายเลขที่เซ็นชื่อและที่ไม่ได้ลงชื่อเช่น ISAs บางตัวยังมีคำแนะนำสำหรับการคำนวณทางคณิตศาสตร์ด้วยทศนิยมทศนิยม

อย่างไรก็ตามโปรดทราบว่าฉันเขียน "modern กระแสหลัก ISA" ด้านบน ในความเป็นจริงมี ISA ที่ไม่สำคัญหรือมีคุณค่าทางประวัติศาสตร์ที่ทำงานแตกต่างกัน ตัวอย่างเช่นทั้ง CISC ISA แบบ 48 บิตดั้งเดิมของ IBM AS / 400 เช่นเดียวกับ RISC ISA แบบ 64 บิตที่ใช้พลังงานในปัจจุบันซึ่งปัจจุบันเรียกว่า IBM i แยกแยะความแตกต่างระหว่างตัวชี้และค่าอื่น ๆ พอยน์เตอร์จะถูกติดแท็กเสมอและรวมถึงข้อมูลประเภทและการจัดการสิทธิ์ CPU รู้ว่าค่าเป็นตัวชี้หรือไม่และเคอร์เนล i / OS ที่มีสิทธิ์เท่านั้นที่ได้รับอนุญาตให้จัดการพอยน์เตอร์ได้อย่างอิสระ แอปพลิเคชั่นของผู้ใช้สามารถจัดการพอยน์เตอร์ที่ตนเป็นเจ้าของให้ชี้ไปที่หน่วยความจำของตนเองโดยใช้คำแนะนำที่ปลอดภัยเพียงเล็กน้อย

นอกจากนี้ยังมีการออกแบบ ISA ในอดีตที่รวมรูปแบบการรับรู้ประเภทอย่างน้อยบางรูปแบบ


โปรดทราบว่า Java bytecode ยังนับเป็น ISA และมันค่อนข้างสนใจเรื่องชนิดของข้อมูล ...
John Dvorak

Java bytecode นั้นนับได้ว่าเป็น ISA ในแง่ที่ว่ามันถูกนำไปใช้ในซิลิคอน อย่างไรก็ตามการตรวจสอบชนิดพื้นฐานของประเภทนี้คือการตรวจสอบดำเนินการโดย classloader ดังนั้นประเภทส่วนใหญ่สามารถละเว้นในเวลาทำงาน และแน่นอนว่า Java bytecode ไม่มีประเภทที่ไม่ได้ลงนามในตอนแรก
นามแฝง

@Pseudonym: ดีในทางเทคนิคก็ไม่ได้charซึ่งเป็น 16 บิตชนิดที่ไม่ได้ลงชื่อ แน่นอนว่ายังไม่มีคำแนะนำเกี่ยวกับเลขคณิตที่ไม่ได้ลงชื่อใน Java bytecode เนื่องจากcharค่าใด ๆจะได้รับการส่งเสริมโดยอัตโนมัติint(ลงนามแบบ 32 บิต) สำหรับเลขคณิต
Ilmari Karonen

42

เวอร์ชั่นสั้น: ไม่รู้ ไม่มีทางที่จะบอกได้

หาก1111แสดงถึง -7 แสดงว่าคุณมีการแทนค่า sign-magnitudeโดยที่บิตแรกเป็นสัญญาณและบิตที่เหลือเป็นขนาด ในกรณีนี้เลขคณิตค่อนข้างซับซ้อนเนื่องจากการเพิ่มที่ไม่ได้ลงชื่อและการเพิ่มที่เซ็นชื่อใช้ตรรกะที่แตกต่างกัน ดังนั้นคุณอาจจะมีSADDและUADDopcode และถ้าคุณเลือกผิดคุณได้รับผลลัพธ์ที่ไร้สาระ

บ่อยขึ้น แต่1111หมายถึง -1 ในสิ่งที่เรียกว่าเป็นตัวแทน two's-สมบูรณ์ ในกรณีนี้ ALU จะไม่สนใจว่าหมายเลขถูกเซ็นชื่อหรือไม่ได้ลงนาม! 1110 + 0001ตัวอย่างเช่นลองมาการดำเนินงานของ ในเลขคณิตที่ลงนามหมายถึง "-2 + 1" และผลลัพธ์ควรเป็น -1 ( 1111) ในเลขคณิตที่ไม่ได้ลงชื่อหมายความว่า "14 + 1" และผลลัพธ์ควรเป็น 15 ( 1111) ดังนั้น ALU จึงไม่ทราบว่าคุณต้องการผลลัพธ์ที่ลงชื่อหรือไม่ได้ลงชื่อและไม่สนใจ มันเป็นเพียงการเพิ่มราวกับว่ามันไม่ได้ลงนามและถ้าคุณต้องการที่จะถือว่าเป็นจำนวนเต็มหลังจากนั้นนั่นก็ขึ้นอยู่กับคุณ

แก้ไข: เนื่องจาก Ruslan และ Daniel Schepler ชี้ให้เห็นอย่างถูกต้องในความคิดเห็นผู้ดำเนินการบางคนยังต้องการรุ่นที่เซ็นชื่อและไม่ได้ลงชื่อแยกจากกันแม้ในเครื่องเสริมสองเครื่อง การบวกการลบการคูณความเสมอภาคและสิ่งต่าง ๆ เหล่านี้ทำงานได้ดีโดยไม่ทราบว่ามีการลงชื่อหมายเลขหรือไม่ แต่การหารและการเปรียบเทียบที่มากกว่า / น้อยกว่านั้นจะต้องมีรุ่นแยกต่างหาก

แก้ไขแก้ไข: มีตัวแทนบางส่วนเช่นกันของเสริมแต่โดยทั่วไปสิ่งเหล่านี้ไม่เคยใช้อีกดังนั้นคุณไม่ควรกังวลเกี่ยวกับพวกเขา


อ้า gotcha ขอบคุณสำหรับสิ่งนี้ :)
noorav

10
ในการเป็นตัวแทนที่สมบูรณ์ของสองการดำเนินการทางคณิตศาสตร์สามประการคือการไม่เชื่อเรื่องพระเจ้า: การบวกการลบและการคูณ (ด้วยผลิตภัณฑ์ที่มีความยาวเท่ากับตัวถูกดำเนินการ) การแบ่งเท่านั้นจะต้องจัดการแตกต่างกันสำหรับตัวถูกดำเนินการลงนาม
Ruslan

4
นอกจากนี้ยังมีการเปรียบเทียบ: < <= >= >จะแตกต่างกันสำหรับตัวถูกดำเนินการที่ลงชื่อและไม่ได้ลงชื่อในขณะที่==และ!=ผู้ไม่เชื่อเรื่องพระเจ้า
Daniel Schepler

การคูณบ่อยครั้งมีการเซ็นชื่อและการลงนามที่ไม่ได้ลงชื่อ: 0xFFFFFFFF * 0xFFFFFFFF คือ 0xFFFFFFFE00000001 ถ้าไม่มีการลงชื่อและ 0x00000000000000000001 ถ้าลงชื่อแล้ว โปรเซสเซอร์เช่น Intel คืนผลลัพธ์ในการลงทะเบียน 2 ครั้งและการลงทะเบียนด้านบนจะแตกต่างกันสำหรับการเซ็นชื่อและการลงนาม การลงทะเบียนด้านล่างคือ 1 ในทั้งสองสถานการณ์
Rudy Velthuis

9

ข้อดีอย่างหนึ่งของคณิตศาสตร์เสริมสองอย่างซึ่งสถาปัตยกรรมสมัยใหม่ทั้งหมดใช้คือคำแนะนำการบวกและการลบเหมือนกันสำหรับตัวถูกดำเนินการทั้งที่ลงชื่อและไม่ได้ลงชื่อ

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

โดยทั่วไปแล้วซีพียูยังมีคำแนะนำต่าง ๆ สำหรับการเปรียบเทียบที่ลงชื่อหรือไม่ได้ลงชื่อ ตัวอย่างเช่น x86 อาจตามCMPด้วยJL(กระโดดถ้าน้อยกว่า) หากการเปรียบเทียบควรลงนามหรือJB (กระโดดถ้าด้านล่าง) หากการเปรียบเทียบควรไม่ได้ลงนาม อีกครั้งคอมไพเลอร์หรือโปรแกรมเมอร์จะเลือกคำสั่งที่เหมาะสมสำหรับประเภทข้อมูล

คำแนะนำอื่น ๆ สองสามอย่างมักจะมาในรูปแบบที่มีการเซ็นชื่อและไม่ได้ลงนามเช่นการกะขวาหรือการโหลดค่าในการลงทะเบียนที่กว้างขึ้นโดยมีหรือไม่มีส่วนขยายสัญญาณ


1
แม้คูณจะเหมือนกันสำหรับจำนวนเต็มไม่ได้ลงนามและลงนาม (เติมเต็มสอง) ตราบใดที่คุณไม่จำเป็นต้องมีผลที่จะมีบิตมากกว่าปัจจัยการผลิต หากคุณกำลังทำอะไรเช่น 8 × 8 → 16 บิต (หรือ 16 × 16 → 32 บิต ฯลฯ ) คูณ แต่คุณจะต้องลงนามขยายปัจจัยการผลิต (หรือผลกลาง)
Ilmari Karonen

@IlmariKaronen นี่เป็นเรื่องจริง ARM A32 / A64 เป็นชุดคำสั่งที่มีหลายรูปแบบของคำแนะนำการคูณรวมถึงการลงชื่อแบบไม่เชื่อเรื่องพระเจ้าคูณเพิ่มที่เขียนเพียงบิตลำดับต่ำกว่า แต่ยังsmulhและumulhที่ส่งกลับเฉพาะบิตบนของการคูณและคำแนะนำการลงนามและไม่ได้ลงนาม ส่งคืนผลลัพธ์ในรีจิสเตอร์สองเท่าของตัวถูกดำเนินการต้นทาง
Davislor

6

มันไม่ได้ โปรเซสเซอร์ใช้การตั้งค่าคำสั่งเพื่อบอกประเภทของข้อมูลที่ต้องการดูและตำแหน่งที่จะส่ง ไม่มีอะไรเกี่ยวกับ 1s และ 0s ในตัวถูกดำเนินการเองซึ่งสามารถส่งสัญญาณไปยัง ALU โดยเนื้อแท้ไม่ว่าจะเป็นข้อมูลถ่าน, ลอย, int, เซ็นชื่อ int เป็นต้นหาก 1111 กำลังไปยังวงจรไฟฟ้าที่คาดว่าจะเป็นส่วนประกอบ 2 วินาที ที่จะตีความว่าเป็นส่วนเสริม 2s


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

3

ฉันต้องการเพิ่มคำตอบที่ทำไปแล้ว:

ในคำตอบอื่น ๆ ส่วนใหญ่มีการบันทึกไว้ว่าในเลขคณิตประกอบสองทางผลลัพธ์จะเหมือนกันสำหรับตัวเลขที่ลงนามและไม่ได้ลงนาม:

-2 + 1 = -1     1110 + 0001 = 1111
14 + 1 = 15     1110 + 0001 = 1111

อย่างไรก็ตามมีข้อยกเว้น:

Division:
  -2 / 2 = -1     1110 / 0010 = 1111
  14 / 2 = 7      1110 / 0010 = 0111
Comparison:
  -2 < 2 = TRUE   1110 < 0010 = TRUE
  14 < 2 = FALSE  1110 < 0010 = FALSE
"Typical" (*) multiplication:
  -2 * 2 = -4     1110 * 0010 = 11111100
  14 * 2 = 28     1110 * 0010 = 00011100

(*) สำหรับซีพียูจำนวนมากผลลัพธ์ของการคูณตัวเลขสองบิตคือความกว้างบิต (2 * n)

สำหรับการดำเนินการดังกล่าว CPU มีคำแนะนำที่แตกต่างกันสำหรับเลขคณิตที่ลงชื่อและไม่ได้ลงชื่อ

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

ยกตัวอย่างเช่นซีพียู x86 มีคำสั่งที่ระบุชื่อdivสำหรับการแบ่งส่วนที่ไม่ได้ลงนามและคำสั่งที่ระบุชื่อidivสำหรับการแบ่งส่วนที่ลงชื่อ

นอกจากนี้ยังมีคำแนะนำ "เงื่อนไข" ที่แตกต่างกัน (การกระโดดตามเงื่อนไขการตั้งค่าบิตบนเงื่อนไข) รวมถึงคำแนะนำการคูณสำหรับเลขคณิตที่ลงนามและไม่ได้ลงนาม

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