Önceki başlık :: Sonraki başlık |
Yazar |
Mesaj |
Black_Knight
Kayıt: Oct 23, 2002 Mesajlar: 286 Nereden: İstanbul/İzmir
|
Tarih: Thu Sep 29, 2005 10:55 pm Mesaj konusu: __asm,naked vs. |
|
|
Can sıkıntısında biraz assembly kurcalamaya başladım.Şöyle birşeyle karşılaştım.
Kod: |
__declspec(naked) int add(int a,int b)
{
__asm
{
mov eax, [esp + 4]
add eax, [esp + 8]
ret
}
}
|
Şimdi burda fonksiyondan deger dondurmenin bir yolu var.
Acaba başka turlu yapilabilirmi?
mesela degişken tanımlayip :
Kod: |
__declspec(naked) int add(int a,int b)
{
int iReturn = 0;
__asm
{
mov eax, [esp + 4]
add eax, [esp + 8]
mov iReturn,eax;
}
return iReturn;
}
|
Falan gibi bişiler.Bide başa naked koydugumuz zaman her fonksiyonda olan bazi gormedigimiz zımbırtıların cıkarildigini okudum biyerde.Mesela naked oldugunda fonksiyon icinde yerel degisken yaratilamiyor.Bunu bilen varsa biraz daha detaylı bir açıklama iyi olurdu...Assembly de yeniyim o yuzden cosup anlatmayin lutfen |
|
Başa dön |
|
|
Black_Knight
Kayıt: Oct 23, 2002 Mesajlar: 286 Nereden: İstanbul/İzmir
|
Tarih: Thu Sep 29, 2005 10:59 pm Mesaj konusu: |
|
|
Kod: |
int add2(int a,int b)
{
int iReturn= 0;
__asm
{
mov eax, a
add eax, b
mov iReturn,eax
}
return iReturn;
}
|
Ancak böyle calıstı digeri.Acaba farkları ne bunların?? |
|
Başa dön |
|
|
ebleda
Kayıt: Dec 30, 2004 Mesajlar: 183 Nereden: usa
|
Tarih: Fri Sep 30, 2005 2:10 am Mesaj konusu: |
|
|
naked keywordunu kullandiginda compiler sadece epilog ve prolog'lari koymaz. Bu sekilde cagiriyorsan kullandigin calling convention'a cok dikkat et. Benim hatirladigim kadariyla naked ifadesi ansi degil bunun icin portable kod yazarken bu iyi bir tercih degil(gerci genellikle at&t syntaxi kullaniliyor ya, o da ayri bir olay). Bir baska husus ise geri donerken sadece sonucu eax icersine atman yeterli. Fonksiyonlar eax registerinin degerini geri doner (floating point'lerde ise stack'e koyar). Bunun icin ayrica bir degisekene atamana gerek yok. ret'i cagirmanada gerek yok. Cunku }'den sonra zaten o kod cagirilacak. Butun bunlar kadar onemli baska bir husus ise kullandigin registerlari kullanimdan once stack'e koy ve isin bittiginde eski degerlerini oradan geri al. Bu muhtemel sakatliklari engeller. |
|
Başa dön |
|
|
ebleda
Kayıt: Dec 30, 2004 Mesajlar: 183 Nereden: usa
|
Tarih: Fri Sep 30, 2005 2:25 am Mesaj konusu: |
|
|
naked kullandigin icin compiler prolog/epiloglari koymadi. Bundan dolayi stack pointeri initialize edilmedi. Ilk sekli ile kullanima cok dikkat etmek lazim (eger stack'ten direkt alacaksaniz). Kullanilan calling convention'a gore argumanlarin stack uzerine yazim sirasi degisir. a+b'de bu fark etmez ama a-b 'de cok sey degisir. |
|
Başa dön |
|
|
Black_Knight
Kayıt: Oct 23, 2002 Mesajlar: 286 Nereden: İstanbul/İzmir
|
Tarih: Fri Sep 30, 2005 9:12 am Mesaj konusu: |
|
|
Registeri stack a koyma isini push pop ile yapiyoruz dimi?
Su dogru olur mu peki?
Kod: |
int add2(int a,int b)
{
__asm
{
push ecx
mov ecx, a
add ecx, b
mov eax, ecx
pop ecx
}
|
|
|
Başa dön |
|
|
devreci
Kayıt: Mar 04, 2005 Mesajlar: 256
|
Tarih: Fri Sep 30, 2005 11:32 am Mesaj konusu: |
|
|
dostum düz fonksiyonda ebp resigteri push edilir fonk'un başlangıcında
bu nedenle mov eax,[esp+4] dersen elinde farklı bir sayı olur ret ederden bilgisayar kitlenir. o yüzden naked kullanılır. nakedde c++ fonksiyona başka hiçbirsey eklemez. Sadece adresi bellidir. o kadar |
|
Başa dön |
|
|
devreci
Kayıt: Mar 04, 2005 Mesajlar: 256
|
Tarih: Fri Sep 30, 2005 11:39 am Mesaj konusu: |
|
|
unutmadan c 'de winde ebp registeri önemlidir heleki proclarda ebp'yi
ters bi yerde kullanırsan bilgisayarı kitleyebilirsin (bi değer atıyor) . bu nedenle c de program yazarken ebp 'yi kullanma saf asm de yazarsan kesinlikle kullan zaten kullanacağın yeri bilirsin o zaman
dönüşte ise herhangi bir registere yada stack'a değeri yükle fonk dönerken mainde tekrar asm kullan ölmezsin ya aha asm nin bir faydası fonk dönüşünde birsürü sayıyı döndürebilirsin reglerle ama naked kullanacan. |
|
Başa dön |
|
|
devreci
Kayıt: Mar 04, 2005 Mesajlar: 256
|
Tarih: Fri Sep 30, 2005 11:53 am Mesaj konusu: |
|
|
tekrar bişey daha yazıyım unutmadan sonya gidiyim
nakedde inta intb tanımlamısın ya onlar normal int a int b gibi değildir onlar stack'ı gösterir normalde ise int a , int b hafızada ayrılmış yerdir
gördüğüm kadarıyla galiba
neyse c'yi fazla bilmiyorum saçmalamıyım |
|
Başa dön |
|
|
Black_Knight
Kayıt: Oct 23, 2002 Mesajlar: 286 Nereden: İstanbul/İzmir
|
Tarih: Fri Sep 30, 2005 5:06 pm Mesaj konusu: |
|
|
Bende oyle biliyorum yani fonksiyon parametresi olarak yazilanlar stackte yer aliyor.zaten ESP stack e pointer etmiyor mu? esp+4 aya denk geliyor 4 byte oldugu icin +8 de b degiskeni var. |
|
Başa dön |
|
|
ebleda
Kayıt: Dec 30, 2004 Mesajlar: 183 Nereden: usa
|
Tarih: Fri Sep 30, 2005 5:44 pm Mesaj konusu: |
|
|
fonksiyon parametresi olarak yazilan seyler her zaman stacke gonderilmez!! bunun icin stackten direkt okumak inline assembly de dogru degil. ornek: __fastcall'de ilk 3 arguman stack uzerinden degil, register uzerinden gonderilir. Inline assembly'de naked'in kullaniminin temel nedenlerinden biri calling conventionlar arasindaki stack duzenlemeyi kontrol etmek ve register kontrolunu serbestlemektir. Eger inline olarak kullaniyorsan naked kullanmani ve stack'ten direkt okumani hic tavsiye etmiyorum. |
|
Başa dön |
|
|
devreci
Kayıt: Mar 04, 2005 Mesajlar: 256
|
Tarih: Sat Oct 01, 2005 10:34 am Mesaj konusu: |
|
|
Black_Knight demiş ki: |
Bende oyle biliyorum yani fonksiyon parametresi olarak yazilanlar stackte yer aliyor.zaten ESP stack e pointer etmiyor mu? esp+4 aya denk geliyor 4 byte oldugu icin +8 de b degiskeni var. |
normal fonksiyonda int a diyosunya stack dan alınıp onun içine yazılıyo
ve int a 'yı kullanıyorsun yoksa en küçük bir push, pop desen sistem çöker , direk esp+4 den kullansan yani normal fonkda
asm öğrenmek istiyosan FASM,TASM,MASM,NASM,HIEW bunları internetten indir içlerinde birsürü örnek var direk asmde kod yaz derim öğrenmek için bunlarla uğraşma |
|
Başa dön |
|
|
Black_Knight
Kayıt: Oct 23, 2002 Mesajlar: 286 Nereden: İstanbul/İzmir
|
Tarih: Sat Oct 01, 2005 11:53 am Mesaj konusu: |
|
|
MASM cektim ama kurcalamaya vakit bulamadim daha okul yuzunden
Bu donem bitiriyorum insallah ondan sonra bol bol ugrasabilirim |
|
Başa dön |
|
|
ebleda
Kayıt: Dec 30, 2004 Mesajlar: 183 Nereden: usa
|
Tarih: Sat Oct 01, 2005 5:33 pm Mesaj konusu: |
|
|
devreci'nin dedigi gibi en iyisi pure assembly kodu yazmak! hic C icersinde falan yazma. Kendi programlarimda asm kullanirken genelde harici bir modul olarak yaziyorum daha sonra link asamasinda projeye ilave ediyorum. (ornek: www.ebleda.com/public/odl_src.zip )
Assembler konusunda tavsiyem TASM'dir. MASM heap alani kullaniminda biraz abzurt davraniyor.
Ust duzey dillerle asm yi birlestirirken dikkat edecegin 2 onemli nokta var:
1) calling convention'nin ne oldugu. (normalde __cdecl kullanir ama bazi durumlarda; basic, fortran gibi dillerle birlestirirken __stdcall kullanimida oldukca yaygin. Bu da stack uzerine yazilan argumanlarin sirasinin degismesine sebeb olur. C'de main icin __cdecl kullanmak zorundasin. Ama diger fonksiyonlarin calling conventionlari tamamen kullaniciya birakilmis. Ben cogunlukla __fastcall kullaniyorum. Aslinda olaya cok daha temelden yaklasmak mumkun. C'de main fonksiyonunu tamamen devreden cikartip, onun yerine bir entry point tanimlarsan boylece asm'kodunu degistirmeden C'ye sorunsuz adapte edebilirsin. Tabi buradaki problem C'nin runtime librarylerini initialize edilmesini engellemis olacaksin. Ama api'ler ve intrisinc C komutlarini kullandigin surece bu problem bile olmuyor. Boylece bir win32 uygulamasi acip MessageBox(0, "", "", 0); yazip compile ettiginde kodun uzunluugnu 700 byte'a kadar indirebiliyorsun. Normalde bu 24K)
2) Diger onemli husus ise kullandigin registerlari stack uzerine yigman. Cunku asm kullanilmadan once assign edilmis bir register senin asm kodun icersinde degistirillir ve asm'den sonra C hala registerin degerini korudugunu sanirsa bu da cok ciddi sorunlara sebeb olabiliyor. Ve bir baska husus ise compiler optimizasyonunu olduruyorsun. Asm yazarken sadece komutlari arka arkaya siralamak yeterli degil. Bunu compiler'da yapiyor. Onemli olan her bir instructiioni pipe'ler icersinde paralellestirmek, cpu'nun branch prediction mekanizmasina uygun kod olusturmak vs.. Bunlari intel'in sayfasindan elde edebilirsin. Bir de Intel's secret diye bir sey vardi (en azindan eskiden vardi) orada bu mekanizmalarin tam olarak nasil calistigini anlatiyordu. Cunku intel'in dokumanlarinda yazilanlar "tam" olarak dogru degil. Branch prediction icersinde cok enterasan pattern recognitionlar var. Bu gercekte tam dokumanlarda anlatildigi gibi degil.
Asm yi hiz icin kullanacaksan bence oturup biraz daha dusun. Cunku %90 compiler senin yazacagin asm'den cok daha iyi asm kodu olusturacaktir. Ancak MMX/XMM gibi compilerin uretmedigi instructionlar icin kullanmak mantikli, kaldi ki bunada artik gerek kalmadi cunku makrolarla direkt bu instructionlarin opcode'larini olusturmak mumkun. |
|
Başa dön |
|
|
|