ทำไมสแต็กจึงเติบโตลง


96

ฉันรู้ว่าในสถาปัตยกรรมที่ฉันคุ้นเคยเป็นการส่วนตัว (x86, 6502 ฯลฯ ) โดยทั่วไปสแต็กจะเติบโตลง (กล่าวคือทุกรายการที่ถูกผลักลงในสแต็กจะส่งผลให้ SP ลดลงไม่ใช่เพิ่มขึ้น)

ฉันสงสัยเกี่ยวกับเหตุผลทางประวัติศาสตร์สำหรับเรื่องนี้ ฉันรู้ว่าในพื้นที่ที่อยู่แบบรวมนั้นสะดวกในการเริ่มต้นสแต็กที่ปลายด้านตรงข้ามของส่วนข้อมูล (พูด) ดังนั้นจะมีปัญหาหากทั้งสองฝ่ายชนกันตรงกลาง แต่ทำไมสแต็กจึงได้ส่วนบนสุด? โดยเฉพาะอย่างยิ่งวิธีนี้เป็นสิ่งที่ตรงกันข้ามกับรูปแบบ "แนวคิด"?

(และโปรดทราบว่าในสถาปัตยกรรม 6502 สแต็กจะเติบโตลงเช่นกันแม้ว่าจะถูก จำกัด ไว้ที่หน้า 256 ไบต์เดียวและการเลือกทิศทางนี้ดูเหมือนจะเป็นไปโดยพลการ)

คำตอบ:


52

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

นอกจากนี้โปรดทราบว่าการตั้งค่านี้ของโปรแกรมนับเป็น 0 เมื่อรีเซ็ตไม่ใช่กรณีสำหรับซีพียูรุ่นแรกทั้งหมด ตัวอย่างเช่น Motorola 6809 จะดึงตัวนับโปรแกรมจากที่อยู่0xfffe/fเพื่อให้คุณสามารถเริ่มทำงานในตำแหน่งที่ตั้งโดยพลการขึ้นอยู่กับสิ่งที่ให้มาในที่อยู่นั้น (โดยปกติ แต่ไม่ จำกัด เฉพาะ ROM)

หนึ่งในสิ่งแรกที่ระบบในอดีตจะทำคือสแกนหน่วยความจำจากด้านบนจนกว่าจะพบตำแหน่งที่จะอ่านค่าเดียวกันที่เขียนไว้เพื่อให้ทราบว่ามีการติดตั้ง RAM จริง (เช่น z80 ที่มีพื้นที่แอดเดรส 64K ไม่จำเป็นต้องมี 64K หรือ RAM ในความเป็นจริง 64K จะมีขนาดใหญ่ในช่วงแรก ๆ ของฉัน) เมื่อพบที่อยู่จริงบนสุดแล้วก็จะตั้งค่าตัวชี้สแต็กอย่างเหมาะสมจากนั้นจะเริ่มเรียกรูทีนย่อย โดยทั่วไปการสแกนนี้จะทำได้โดย CPU ที่รันโค้ดใน ROM เป็นส่วนหนึ่งของการเริ่มต้น

เกี่ยวกับการเติบโตของสแต็คไม่ใช่ทั้งหมดที่เติบโตลงดูรายละเอียดคำตอบนี้


1
ฉันชอบเรื่องราวกลยุทธ์การตรวจจับแรม Z80 ทำให้รู้สึกว่ามีการจัดวางส่วนข้อความที่เติบโตขึ้น - โปรแกรมเมอร์ในสมัยก่อนค่อนข้างติดต่อโดยตรงกับการจัดการกับผลกระทบของสิ่งนั้นมากกว่าสแต็กขอบคุณ paxdiablo ตัวชี้ไปยังชุดของรูปแบบทางเลือกของการใช้งานสแต็กก็น่าสนใจมากเช่นกัน
Ben Zotto

หน่วยความจำวันแรกไม่มีวิธีแจ้งขนาดและเราต้องคำนวณด้วยตนเองหรือไม่?
phuclv

1
@ L assumeuVĩnhPhúcฉันต้องถือว่าคุณเป็นคนรุ่นหลัง (หรือสองคน) ที่อยู่ข้างหลังฉัน ฉันยังจำวิธี TRS-80 model 3 ในการรับวันที่และเวลาเพื่อขอผู้ใช้ในเวลาบูตได้ การมีเครื่องสแกนหน่วยความจำเพื่อกำหนดขีด จำกัด สูงสุดของหน่วยความจำถือเป็นสิ่งที่ล้ำสมัยในสมัยนั้น :-) คุณนึกออกไหมว่าจะเกิดอะไรขึ้นถ้า Windows ถามเวลาหรือคุณมีหน่วยความจำเท่าไหร่ทุกครั้งที่คุณบูต
paxdiablo

1
อันที่จริงเอกสาร Zilog Z80 กล่าวว่าชิ้นส่วนนี้เริ่มต้นขึ้นโดยตั้งค่าการลงทะเบียนพีซีเป็น 0000h และดำเนินการ มันตั้งค่าโหมดขัดจังหวะเป็น 0 ปิดใช้งานการขัดจังหวะและตั้งค่าการลงทะเบียน I และ R เป็น 0 เช่นกัน หลังจากนั้นจะเริ่มดำเนินการ เวลา 0000h จะเริ่มรันโค้ด รหัสนั้นต้องเริ่มต้นตัวชี้สแต็กก่อนจึงจะสามารถเรียกรูทีนย่อยหรือเปิดใช้งานอินเทอร์รัปต์ ผู้ขายรายใดขาย Z80 ที่มีพฤติกรรมตามที่คุณอธิบาย
MikeB

1
ไมค์ขอโทษฉันควรจะชัดเจนกว่านี้ เมื่อฉันพูดว่า CPU สแกนหน่วยความจำฉันไม่ได้หมายความว่านั่นเป็นคุณสมบัติของซีพียูเอง มันถูกควบคุมจากโปรแกรมใน ROM จริงๆ ฉันจะชี้แจง
paxdiablo

21

คำอธิบายที่ดีอย่างหนึ่งที่ฉันได้ยินมาคือเครื่องบางเครื่องในอดีตอาจมีเฉพาะออฟเซ็ตที่ไม่ได้ลงนามดังนั้นคุณต้องการให้กองซ้อนเติบโตลงเพื่อให้คุณสามารถตีคนในพื้นที่ได้โดยไม่ต้องเสียคำสั่งเพิ่มเติมเพื่อปลอมค่าชดเชยเชิงลบ


8

Stanley Mazor (สถาปนิก 4004 และ 8080) อธิบายถึงวิธีการเลือกทิศทางการเติบโตของสแต็กสำหรับ 8080 (และสุดท้ายสำหรับ 8086) ใน"Intel Microprocessors: 8008 ถึง 8086" :

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


6

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


1
คอมพิวเตอร์ไม่หักลบ พวกเขาเพิ่มคำชมเชย 2 สิ่งใดที่ทำได้โดยการลบก็ทำได้โดยการบวก ลองพิจารณาคอมพิวเตอร์มีส่วนเสริมไม่ใช่ตัวลบ
jww

1
@jww - นั่นคือความแตกต่างที่ไม่มีความแตกต่าง ฉันอาจจะอ้างว่าคอมพิวเตอร์ไม่ได้บวกลบเท่านั้น! สำหรับวัตถุประสงค์ของคำตอบนี้ไม่สำคัญ แต่ ALU ส่วนใหญ่จะใช้วงจรที่รองรับทั้งการบวกและการลบที่มีประสิทธิภาพเดียวกัน นั่นคือในขณะที่A - Bสามารถดำเนินการตามแนวคิดเป็นA + (-B)(เช่นขั้นตอนการปฏิเสธแยกต่างหากสำหรับB) แต่ก็ไม่ได้อยู่ในทางปฏิบัติ
BeeOnRope

@jww nitpick ของคุณผิดสำหรับคอมพิวเตอร์ยุคแรก - ต้องใช้เวลาพอสมควรกว่าจะชนะทั้งสองฝ่ายและจนกว่าจะเป็นเช่นนั้นมีคอมพิวเตอร์ที่ใช้ส่วนประกอบและเครื่องหมายและขนาดและอาจเป็นสิ่งอื่นแทน ด้วยการนำไปใช้งานเหล่านั้นอาจมีข้อดีในการบวกกับการลบ ดังนั้นในกรณีที่ไม่มีข้อมูลเพิ่มเติมจึงไม่ถูกต้องที่จะแยกแยะสิ่งนี้ออกเนื่องจากปัจจัยที่เป็นไปได้ที่มีอิทธิพลต่อตัวเลือกโครงการที่อยู่เช่นทิศทางกองซ้อน
mtraceur

4

IIRC สแต็กจะลดลงเนื่องจากฮีปเติบโตขึ้น มันอาจจะเป็นวิธีอื่นก็ได้


5
ฮีปที่เติบโตขึ้นช่วยให้สามารถจัดสรรซ้ำได้อย่างมีประสิทธิภาพในบางกรณี แต่ฮีปที่เติบโตลดลงแทบไม่เคยทำ
Peter Cordes

@PeterCordes ทำไม?
Yashas

3
@Yashas: เนื่องจากrealloc(3)ต้องการพื้นที่เพิ่มเติมหลังวัตถุเพื่อขยายการแมปโดยไม่ต้องคัดลอก การปันส่วนซ้ำของวัตถุเดียวกันเป็นไปได้เมื่อตามด้วยจำนวนพื้นที่ที่ไม่ได้ใช้โดยพลการ
Peter Cordes

2

ฉันเชื่อว่ามันเป็นการตัดสินใจในการออกแบบเท่านั้น ไม่ใช่ทั้งหมดที่เติบโตลง - ดูหัวข้อ SO นี้สำหรับการสนทนาที่ดีเกี่ยวกับทิศทางของการเติบโตแบบสแต็กในสถาปัตยกรรมต่างๆ


1

ฉันเชื่อว่าการประชุมเริ่มต้นด้วย IBM 704 และ "การลงทะเบียนที่ลดลง" ที่น่าอับอาย คำพูดของโมเดิร์นจะเรียกมันว่าสนามชดเชยการเรียนการสอน แต่ประเด็นก็คือพวกเขาเดินลง , ไม่ ขึ้น


1

อีกเพียง 2c:

นอกเหนือจากเหตุผลทางประวัติศาสตร์ที่กล่าวมาทั้งหมดฉันค่อนข้างมั่นใจว่าไม่มีเหตุผลใดที่ใช้ได้กับโปรเซสเซอร์สมัยใหม่ โปรเซสเซอร์ทั้งหมดสามารถทำการออฟเซ็ตที่ลงนามได้และการเพิ่มระยะห่างฮีป / สแต็กให้มากที่สุดนั้นค่อนข้างจะเป็นที่น่าเบื่อนับตั้งแต่เราเริ่มจัดการกับเธรดหลายเธรด

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


0

ฉันไม่แน่ใจ แต่ฉันได้เขียนโปรแกรมสำหรับ VAX / VMS ในสมัยก่อน ดูเหมือนว่าฉันจะจำส่วนหนึ่งของความทรงจำได้ (ฮีป ??) ขึ้นไปและสแต็กจะลดลง เมื่อทั้งสองพบกันคุณก็ไม่ได้รับความทรงจำ


1
นี่เป็นเรื่องจริง แต่ทำไมกองถึงโตขึ้นและไม่อยู่ในทางอื่น?
Ciro Santilli 郝海东冠状病六四事件法轮功

0

ข้อดีอย่างหนึ่งของการเพิ่มจำนวนสแต็กจากมากไปหาน้อยในระบบฝังตัวที่น้อยที่สุดคือ RAM ชิ้นเดียวสามารถแมปซ้ำซ้อนลงในทั้งหน้า O และหน้าที่ 1 ทำให้สามารถกำหนดตัวแปรหน้าเป็นศูนย์ได้โดยเริ่มต้นที่ 0x000 และสแต็กที่เพิ่มขึ้นจาก 0x1FF ทำให้สูงสุด จำนวนเงินที่จะต้องเพิ่มขึ้นก่อนที่จะเขียนทับตัวแปร

หนึ่งในเป้าหมายการออกแบบดั้งเดิมของ 6502 คือสามารถใช้ร่วมกับตัวอย่างเช่น 6530 ทำให้เกิดระบบไมโครคอนโทรลเลอร์สองชิปที่มี ROM โปรแกรม 1 KB ตัวจับเวลา I / O และแรม 64 ไบต์ที่ใช้ร่วมกัน ระหว่างตัวแปรสแต็กและเพจศูนย์ จากการเปรียบเทียบระบบฝังตัวขั้นต่ำในเวลานั้นที่ใช้ 8080 หรือ 6800 จะเป็นชิปสี่หรือห้าตัว

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