EBP çerçeve işaretçi kaydının amacı nedir?


96

Derleme dilinde yeni başlayan biriyim ve derleyiciler tarafından yayılan x86 kodunun, EBPkaydı başka bir şey için kullanabildiğinde yayın / optimize modda bile çerçeve işaretçisini genellikle etrafta tuttuğunu fark ettim .

Çerçeve işaretçisinin kodun hata ayıklamasını neden kolaylaştırabileceğini ve alloca()bir işlev içinde çağrıldığında gerekli olabileceğini anlıyorum . Ancak, x86'da çok az yazmaç var ve bunlardan ikisini yığın çerçevesinin konumunu tutmak için kullanmak yeterli olduğunda bana mantıklı gelmiyor. Optimize edilmiş / yayınlanmış yapılarda bile çerçeve işaretçisini çıkarmak neden kötü bir fikir olarak kabul edilir?


20


1
C99 VLA da bundan yararlanabilir.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功


1
Çerçeve işaretçisi yığın işaretçisini gereksiz hale getirmiyor mu? . TL; DR: 1. önemsiz yığın hizalama 2. yığın tahsisi ( alloca) 3. çalışma zamanı uygulama kolaylığı: istisnai durum işleme, korumalı alan, GC
Alexander Malakhov

Yanıtlar:


102

Çerçeve işaretçisi, bir hata ayıklayıcının yerel değişkenin veya bir bağımsız değişkenin tek bir sabit ofset ile nerede olduğunu bilmesini sağlayan bir referans göstericidir. ESP'nin değeri yürütme sırasında değişse de, EBP aynı kalır ve aynı değişkene aynı ofsette ulaşmayı mümkün kılar (örneğin, ilk parametre her zaman EBP + 8'de olurken ESP ofsetleri önemli ölçüde değişebilir çünkü itiyor olacaksınız / haşhaş şeyler)

Derleyiciler neden çerçeve işaretçisini atmıyor? Çerçeve işaretçisi ile hata ayıklayıcı, yerel değişkenlerin ve argümanların sembol tablosunu nerede kullandığını bulabilir çünkü EBP'ye göre sabit bir ofsette olmaları garanti edilir. Aksi takdirde, kodun herhangi bir noktasında yerel bir değişkenin nerede olduğunu anlamanın kolay bir yolu yoktur.

Greg'in bahsettiği gibi, EBP ters bağlantılı yığın çerçeveleri listesi sağladığından, hata ayıklayıcının işlevin yığın çerçevesinin (yerel değişkenler + argümanlar) boyutunu bulmasına izin verdiğinden, bir hata ayıklayıcı için yığın çözülmesine de yardımcı olur.

Çoğu derleyici, hata ayıklamayı gerçekten zorlaştırsa da kare işaretleyicilerini atlamak için bir seçenek sunar. Bu seçenek, sürüm kodunda bile asla global olarak kullanılmamalıdır. Bir kullanıcının çökmesinde ne zaman hata ayıklamanız gerekeceğini bilmiyorsunuz.


10
Derleyici muhtemelen ESP'ye ne yaptığını biliyor. Diğer puanlar da geçerli +1
erikkallen

8
Modern hata ayıklayıcılar, ile derlenen kodda bile yığın geri izleme yapabilir -fomit-frame-pointer. Bu ayar, son gcc'de varsayılan ayardır.
Peter Cordes

2
@SedatKapanoglu: Bir veri bölümü gerekli bilgileri kaydeder: yosefk.com/blog/…
Peter Cordes

3
@SedatKapanoglu: Bu .eh_frame_hdrbölüm çalışma zamanı istisnaları için de kullanılıyor. Bunu objdump -hbir Linux sistemindeki çoğu ikili dosyada (ile ) bulacaksınız /bin/bash, GNU için yaklaşık 16k , GNU için 572B ,. Oluşturmayı devre dışı bırakmak için bir gcc seçeneği vardır, ancak bu "normal" bir veri bölümüdür, varsayılan olarak kaldırılan bir hata ayıklama bölümü değildir . Aksi takdirde, hata ayıklama sembollerine sahip olmayan bir kütüphane işlevi üzerinden geriye doğru izleme yapamazsınız. Bu bölüm, değiştirdiği talimatlardan daha büyük olabilir , ancak sıfıra yakın çalışma süresi maliyetine sahiptir (örneğin, uop önbellek). /bin/trueffmpegstrippush/mov/pop
Peter Cordes

3
"İlk parametre her zaman EBP-4'te olacaktır" ile ilgili olarak: İlk parametre EBP + 8'deki (x86'da) değil mi?
Aydın K.

31

Sadece iki sentimi zaten iyi cevaplara ekledim.

Bir yığın çerçeveler zincirine sahip olmak iyi bir dil mimarisinin parçasıdır. BP, alt rutin-yerel değişkenlerin depolandığı geçerli çerçeveye işaret eder. (Yereller negatif göreli konumdadır ve bağımsız değişkenler pozitif uzaklıktadır.)

Optimizasyonda mükemmel derecede iyi bir kaydın kullanılmasını engellediği fikri şu soruyu gündeme getiriyor: Optimizasyon gerçekte ne zaman ve nerede değerli?

Optimizasyon yalnızca 1) işlevleri çağırmayan, 2) program sayacının zamanının önemli bir kısmını harcadığı ve 3) derleyicinin gerçekten göreceği kodda (yani kitaplık dışı işlevler) harcadığı sıkı döngülerde faydalıdır. Bu, özellikle büyük sistemlerde genellikle genel kodun çok küçük bir bölümüdür.

Diğer kodlar, döngülerden kurtulmak için bükülebilir ve sıkıştırılabilir ve bunun önemi yoktur, çünkü program sayacı pratikte hiçbir zaman orada değildir.

Bunu sormadığınızı biliyorum, ancak deneyimlerime göre, performans sorunlarının% 99'unun derleyici optimizasyonuyla hiçbir ilgisi yok. Aşırı tasarımla ilgili her şeyi var.


Teşekkürler @ Mike, cevabını çok yararlı buldum.
sixtyfootersdude

2
Çerçeve işaretçisinden uzaklaşmak, her işlev çağrısında size birkaç talimat kaydeder, bu da kendi başına küçük bir optimizasyondur. BTW, "soruyu sorar" ifadesini kullanmanız yanlıştır; "soruyu gündeme getiriyor" demek istiyorsun.
augurar

@augurar: Düzeltildi. Teşekkürler. Ben de biraz gramer
huysuzum

3
@augurar Dil gelişiyor: "Soru soruyor" artık sadece "soruyu gündeme getiriyor" anlamına geliyor. Modası geçmiş kullanım için kuralcı bir niteleyici olmak hiçbir şey katmaz.
user3364825

9

Elbette derleyiciye bağlıdır. EBP kaydını genel amaçlı bir kayıt olarak serbestçe kullanan x86 derleyicileri tarafından yayılan optimize edilmiş kod gördüm. (Yine de hangi derleyiciyi fark ettiğimi hatırlamıyorum.)

Derleyiciler ayrıca, istisna işleme sırasında yığının çözülmesine yardımcı olmak için EBP yazmacını korumayı da seçebilirler, ancak yine bu, derleyicinin tam olarak uygulanmasına bağlıdır.


Çoğu derleyici -fomit-frame-pointer, optimizasyonun etkinleştirildiği zamanı varsayar. (ABI izin verdiğinde). GCC, clang, ICC ve MSVC, 32 bit Windows hedeflenirken bile IIRC bunu yapar. Evet, benim cevabım Yığındaki parametreleri bulmak için neden ebp'yi esp yazmacından daha iyi kullanmak daha iyidir? 32 bit Windows'un bile çerçeve işaretçisini atlayabileceğini gösterir. 32-bit x86 Linux kesinlikle yapabilir ve yapar. Ve tabii ki 64 bit ABI'ler, baştan itibaren çerçeve işaretçisi ihmaline izin verdi.
Peter Cordes

4

Ancak, x86'nın çok az kaydı var

Bu, yalnızca işlem kodlarının yalnızca 8 kaydı adresleyebilmesi anlamında doğrudur. İşlemcinin kendisi aslında bundan çok daha fazla yazmacıya sahip olacak ve bu limiti aşmak için yazmaç yeniden adlandırma, ardışık düzen, spekülatif yürütme ve diğer işlemci terimlerini kullanacaktır. Wikipedia'da bir x86 işlemcisinin kayıt sınırını aşmak için neler yapabileceğine dair iyi bir giriş paragrafı var: http://en.wikipedia.org/wiki/X86#Current_implementations .


1
Asıl soru, opcode'lar tarafından atıfta bulunulabilen kayıtlarla kesinlikle sınırlı olan üretilen kod hakkındadır.
Darron

1
Evet, ancak bu nedenle çerçeve işaretçisini optimize edilmiş yapılarda kullanmak günümüzde o kadar önemli değil.
Michael

1
Register yeniden adlandırma, gerçekte daha fazla sayıda register mevcut olmakla aynı şey değildir. Register yeniden adlandırmanın yardımcı olmayacağı birçok durum vardır, ancak daha "normal" kayıtlar yardımcı olacaktır.
jalf

1

Yığın çerçevelerin kullanılması, uzaktan modern bile olsa herhangi bir donanımda inanılmaz derecede ucuz hale geldi. Ucuz yığın çerçeveleriniz varsa, birkaç kayıt kaydetmek o kadar önemli değildir. Eminim hızlı yığın çerçevelerine karşı daha fazla kayıt bir mühendislik değiş tokuşuydu ve hızlı yığın çerçeveleri kazandı.

Saf sicile geçişte ne kadar tasarruf ediyorsunuz? Buna değer mi?


Daha fazla kayıt, komut kodlamasıyla sınırlıdır. x86-64, komutların yazmaç belirleyen kısmını src ve dest yazmaçları için 3 bitten 4 bit'e genişletmek için REX önek baytındaki bitleri kullanır. Alan olsaydı, x86-64 muhtemelen 32 mimari kayda giderdi, ancak bağlam anahtarlarında bu kadar çok sayıda anahtarın kaydedilmesi / geri yüklenmesi toplanmaya başlasa da. 15, 7'den büyük bir adımdır, ancak çoğu durumda 31 çok daha küçük bir gelişmedir. (yığın işaretçisini genel amaçlı olarak saymaz.) Push / pop'u hızlı yapmak, yığın çerçevelerinden daha fazlası için harikadır. Yine de, regs sayısı ile bir değiş tokuş değil.
Peter Cordes
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.