Yığınlar neden tipik olarak aşağı doğru büyüyor?


99

Kişisel olarak aşina olduğum mimarilerde (x86, 6502, vb.), Yığının tipik olarak aşağı doğru büyüdüğünü biliyorum (yani, yığına itilen her öğe artırılmış bir SP değil, azaltılmış bir SP ile sonuçlanır).

Bunun tarihsel gerekçesini merak ediyorum. Birleştirilmiş bir adres alanında, yığını veri segmentinin karşı ucunda başlatmak (diyelim ki) uygun olduğunu biliyorum, bu nedenle yalnızca iki taraf ortada çarpışırsa bir sorun olur. Ama neden yığın geleneksel olarak en üst kısmı alıyor? Özellikle bunun "kavramsal" modelin tersi olduğu göz önüne alındığında?

(Ve 6502 mimarisinde, 256 baytlık tek bir sayfaya sınırlı olmasına rağmen yığının da aşağı doğru büyüdüğünü ve bu yön seçiminin keyfi göründüğünü unutmayın.)

Yanıtlar:


54

Tarihsel mantığa gelince, kesin olarak söyleyemem (çünkü onları ben tasarlamadım). Benim düşüncelerim konuda erken CPU'lar 0'a orijinal program sayacı seti var ve diğer ucunda yığını başlatmak ve bunların kod doğal olarak yukarı doğru büyüyeceği için aşağıya büyümeye karşı doğal bir istek olduğunu vardır.

Bir kenara, sıfırlamada program sayacının 0 olarak ayarlanmasının tüm eski CPU'lar için geçerli olmadığını unutmayın . Örneğin, Motorola 6809 program sayacını adreslerden alır, 0xfffe/fböylece o adreste neyin sağlandığına bağlı olarak (genellikle, ancak hiçbir şekilde ROM ile sınırlı değildir) rastgele bir konumda çalışmaya başlayabilirsiniz.

Bazı tarihsel sistemlerin yapacağı ilk şeylerden biri, hafızayı en baştan, aynı değeri okuyacak bir konum bulana kadar taramak olacaktır, böylece kurulu gerçek RAM'i bilecektir (örneğin, 64K adres alanına sahip bir z80 64K veya RAM olması gerekmiyordu, aslında 64K ilk günlerimde çok büyük olurdu ). En üst gerçek adresi bulduktan sonra, yığın işaretçisini uygun şekilde ayarlayacak ve ardından alt rutinleri çağırmaya başlayabilecektir. Bu tarama genellikle başlatmanın bir parçası olarak ROM'da CPU çalıştıran kod tarafından yapılır.

Yığın büyümesi ile ilgili olarak, hepsi aşağı doğru büyümez, ayrıntılar için bu yanıta bakın.


1
Z80 RAM algılama stratejisi hikayesini beğendim. Metin bölümlerinin yukarı doğru büyümekte olduğu biraz mantıklı geliyor - eski programcıların bunun sonuçlarıyla uğraşmakla yığından daha fazla doğrudan teması vardı. Teşekkürler paxdiablo. Yığın uygulamalarının alternatif formları kümesine işaretçi de çok ilginçtir.
Ben Zotto

Erken dönem hafızasının boyutunu bildirmenin bir yolu yok mu ve bunu manuel olarak hesaplamak zorunda mıyız?
phuclv

1
@ LưuVĩnhPhúc, arkamda bir (veya iki) nesil olduğunuzu varsaymalıyım. Kullanıcıdan açılış sırasında sormak için tarih ve saati almak için TRS-80 model 3 yöntemini hala hatırlıyorum . Üst bellek sınırını ayarlayacak bir bellek tarayıcısına sahip olmak, günümüzde en son teknoloji olarak kabul edildi :-) Windows her başlattığınızda saati sorsa ne olacağını veya ne kadar belleğiniz olduğunu hayal edebiliyor musunuz?
paxdiablo

1
Aslında, Zilog Z80 dokümantasyonu, parçanın PC kaydını 0000h'ye ayarlayıp çalıştırarak başladığını söylüyor. Kesme modunu 0'a ayarlar, kesmeleri devre dışı bırakır ve I ve R kayıtlarını da 0'a ayarlar. Bundan sonra çalışmaya başlar. 0000h'de kodu çalıştırmaya başlar. Bu kodun, bir alt yordamı çağırmadan veya kesmeleri etkinleştirmeden önce yığın işaretçisini başlatması gerekir. Hangi satıcı sizin tarif ettiğiniz gibi davranan bir Z80 satıyor?
MikeB

1
Mike, üzgünüm, daha net olmalıydım. CPU'nun belleği taradığını söylediğimde, bunun CPU'nun kendisinin bir özelliği olduğunu kastetmemiştim. Aslında ROM'daki bir programdan kontrol edildi. Açıklığa kavuşturacağım.
paxdiablo

21

Duyduğum iyi bir açıklama, geçmişte bazı makinelerin sadece işaretsiz ofsetlere sahip olabileceğiydi, bu yüzden yığının aşağı doğru büyümesini isteyeceksiniz, böylece negatif bir ofset taklit etmek için fazladan talimatı kaybetmek zorunda kalmadan yerlilerinizi vurabilirsiniz.


9

Stanley Mazor (4004 ve 8080 mimarı) "Intel Mikroişlemciler: 8008 ila 8086" da 8080 (ve sonunda 8086 için) yığın büyüme yönünün nasıl seçildiğini açıklıyor :

Yığın işaretçisi, kullanıcının programından yığına endekslemeyi basitleştirmek (pozitif dizinleme) ve yığının içeriğinin bir ön panelden görüntülenmesini basitleştirmek için "yokuş aşağı" (yığın daha düşük belleğe doğru ilerleyerek) çalışacak şekilde seçildi.


6

Olası nedenlerden biri, hizalamayı basitleştirmesidir. Yığın üzerine 4 baytlık bir sınıra yerleştirilmesi gereken yerel bir değişken yerleştirirseniz, nesnenin boyutunu yığın işaretçisinden çıkarabilir ve ardından düzgün şekilde hizalanmış bir adres elde etmek için iki alt biti sıfırlayabilirsiniz. Yığın yukarı doğru büyürse, hizalamanın sağlanması biraz daha zor hale gelir.


1
Bilgisayarlar çıkarmaz; 2'nin iltifatını eklerler. Çıkarılarak yapılan her şey gerçekten toplanarak yapılır. Düşünün, bilgisayarların çıkarıcıları değil, toplayıcıları vardır.
jww

1
@jww - bu hiçbir farkın olmadığı bir ayrımdır. Bilgisayarların eklemediğini iddia edebilirim, sadece çıkarırlar! Bu cevabın amaçları için, gerçekten önemli değil - ancak çoğu ALU , aynı performansla hem toplama hem de çıkarmayı destekleyen bir devre kullanacaktır . Yani, A - Bkavramsal olarak A + (-B)(yani için ayrı bir olumsuzlama adımı B) olarak uygulanabilirken, pratikte değildir.
BeeOnRope

@jww Nitpick'iniz ilk bilgisayarlar için yanlış - ikinin tamamlayıcısının kazanması biraz zaman aldı ve kazanana kadar, birinin tamamlayıcı ve işaret ve büyüklüğünü kullanan bilgisayarlar ve bunun yerine belki başka şeyler vardı. Bu uygulamalarla, toplamaya karşı çıkarmanın bir avantajı olabilir. Dolayısıyla, ek bilginin yokluğunda, bunu yığın yönü gibi adresleme şema seçimlerini etkileyen olası bir faktör olarak dışlamak yanlıştır.
mtraceur

4

IIRC, yığın yukarı doğru büyüdüğü için yığın aşağı doğru büyür. Tersi de olabilirdi.


5
Yukarı doğru büyüyen bir yığın, bazı durumlarda verimli bir yeniden tahsise izin verir, ancak aşağı doğru büyüyen bir yığın hemen hemen hiç yapmaz.
Peter Cordes

@PeterCordes neden?
Yashas

3
@Yashas: çünkü eşlemeyi kopyalamadan genişletmek için bir nesneden sonrarealloc(3) daha fazla alana ihtiyaç vardır . Aynı nesnenin tekrar tekrar tahsisi, ardından gelişigüzel miktarda kullanılmayan alan geldiğinde mümkündür.
Peter Cordes

2

Bunun tamamen bir tasarım kararı olduğuna inanıyorum. Hepsi aşağı doğru büyümez - farklı mimarilerde yığın büyümesinin yönü hakkında iyi bir tartışma için bu SO başlığına bakın .


1

Konvansiyonun IBM 704 ve kötü şöhretli "eksiltme kaydı" ile başladığına inanıyorum. Modern konuşma öğretim bir ofset alan çağırır, ama mesele gittikleri olduğunu aşağı , değil yukarı .


1

Sadece 2c daha:

Bahsedilen tüm tarihsel mantığın ötesinde, modern işlemcilerde geçerli olan hiçbir neden olmadığından oldukça eminim. Tüm işlemciler işaretli ofsetleri alabilir ve birden fazla iş parçacığı ile uğraşmaya başladığımızdan beri yığın / yığın mesafesini en üst düzeye çıkarmak oldukça tartışmalıdır.

Ben şahsen bunu bir güvenlik tasarımı hatası olarak görüyorum. Diyelim ki, x64 mimarisinin tasarımcıları yığın büyüme yönünü tersine çevirmiş olsaydı, yığın arabellek taşmalarının çoğu ortadan kaldırılırdı - ki bu büyük bir mesele. (dizeler yukarı doğru büyüdüğü için).


0

Emin değilim ama günlerde VAX / VMS için bazı programlar yaptım. Belleğin bir kısmının (yığın ??) yukarı ve yığının aşağı indiğini hatırlıyorum. İkisi bir araya geldiğinde, hafızanız tükendi.


1
Bu doğru, ama o zaman neden yığın yukarı doğru büyüyor ve tersi olmuyor?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

0

Minimum gömülü sistemde azalan yığın büyümesinin bir avantajı, tek bir RAM öbeğinin yedekli olarak hem sayfa O hem de sayfa 1'e eşlenebilmesidir; bu, sıfır sayfa değişkenlerinin 0x000'den başlayarak atanmasına ve yığının 0x1FF'den aşağı doğru büyümesine izin vererek değişkenlerin üzerine yazmadan önce büyümesi gereken miktar.

6502'nin orijinal tasarım hedeflerinden biri, örneğin bir 6530 ile birleştirilebilmesiydi, bu da 1 KB program ROM'u, zamanlayıcı, G / Ç ve paylaşılan 64 bayt RAM ile iki çipli bir mikro denetleyici sistemi ile sonuçlandı. yığın ve sayfa sıfır değişkenleri arasında. Karşılaştırıldığında, 8080 veya 6800'e dayanan o zamanın minimum gömülü sistemi dört veya beş yonga olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.