Šta je novo?

Inline assembler WIN64

genuine

Slavan
Učlanjen(a)
17.02.2006
Poruke
1,906
Poena
350
Zasto u Microsoft-ovom VC++ 2005 nema podrske za inline assembler? Hoce li biti u opste?
 
Nema i nece. Jedino sto mozes je da koristis eksterne asm fajlove i ml64.exe asembler koji stize uz Visual Studio 2005.
Namerno je izbacena kako be se ljudi naterali da revidiraju kod za 64-bitnu platformu.
S obzirom na razlike izmedju ABI-ja (drasticne) i prenosa parametara za f-je i dodatnih direktiva za podrsku C++ exception-a i ispravnog odmotavanja steka cak iako se greska desi u asembleru, moraces dobro da se pomucis da napises kod za 64 bita, a sumnjam da ces videti neki znacajan dobitak u performansama osim ako pre toga nije koriscen obican 32-bitni kod bez SIMD instrukcija.
 
Poslednja izmena:
Znaci kada mi treba sse1 i 2 koristim intrinsic funkcije umesto inline asm-a...?

I jedno pitanjce.. koliko sam primetio pri pozivu funkcija argumenti se predaju redom rcx,rdx,r8,r9... jel ovo tacno?
 
Poslednja izmena:
genuine je napisao(la):
Znaci kada mi treba sse1 i 2 koristim intrinsic funkcije umesto inline asm-a...?

Ako hoces portabilan kod, onda koristis asembler u odvojenom asm fajlu koji prevodis sa ml.exe ili sa nasmw.exe.

genuine je napisao(la):
I jedno pitanjce.. koliko sam primetio pri pozivu funkcija argumenti se predaju redom rcx,rdx,r8,r9... jel ovo tacno?

Calling convention jeste registarska, ali nazalost nije bas tako jednostavno. Zavisi od tipa i velicine parametra preko kog registra ce parametar biti prenet. Ako imas f-ju:

void somefun(int a, float b);

a ce ici u rcx
b ce ici u prvi slobodan xmm registar

void somefun(int a, float b, int c, double d);

a ce ici u rcx
b ce ici u prvi slobodan xmm registar
c ce ici u rdx
d ce ici u drugi slobodan xmm registar

Sve preko 4 parametra ide na stek ako se dobro secam, a registre si duzan da prospes na stek u za to predvidjen prostor a ako hoces da ti C++ exception handling radi kako treba moras imati prolog i epilog napisan prema "pravilniku" i f-ja mora biti u .asm fajlu sa odgovarajucim direktivama za kontrolu stack unwindinga. Dakle, sta i ja serem -- ako hoces da uradis po PS-u onda je ultra komplikovano, do te mere da je mene mrzelo da se bakcem iako sam veliki asm fan. Sreca pa mi za sada nije potrebno, mozda se kasnije posvetim tome malo vise nikad se ne zna za sta moze da zatreba.

Moj stav je da su napravili nevidjenu zbrku sa tim ABI-jem i konvencijom. To me i ne cudi me jer je AMD kumovao kako sam cuo od jednog M$ developera zaduzenog za kompajler, a za AMD barem kad je programiranje u pitanju od uvek vazi maksima "zasto jednostavno kad moze komplikovano i nestandardno".
 
uf... komplikacija ^2 ..
isto me muci pitanje ako u programu u asm koristim ostale registre Rx jel moram da ih cuvam na stek ili ne(bilo bi glupo da moram)... pre je bilo da Eax,Ebx,ecx,i edx ne moram a ostale moram.. kako je sad stanje posto je upotreba registara znatno pojacana... hoce li kompajler da brine o tome ili ja ili se podrazumeva da R registre mogu da koristim kako hocu....
postoji li neki nacin da kazem kompajleru koje sam registre koristio da bi on bolje rasporedio podatke po registrima ili on to sam vidi iz obj fajla?
u gcc je jako lepo resen inline asm.. ja samo navodim da hocu podatak da bude u registru i onda ga koristim kao %0,%1 i sl. a on posle vodi racuna o alokaciji registara... moze li nesto slicno da se uradi u VC++...
 
Poslednja izmena:
genuine je napisao(la):
isto me muci pitanje ako u programu u asm koristim ostale registre Rx jel moram da ih cuvam na stek ili ne (bilo bi glupo da moram)...

Bilo bi glupo ali ipak moras. :d

genuine je napisao(la):
pre je bilo da Eax,Ebx,ecx,i edx ne moram a ostale moram..

Nece biti, pre je bilo eax/edx ne mora (preko njih se vraca 64-bitni rezultat kad si u 32-bitnom modu pa su volatile), sve ostalo mora.

postoji li neki nacin da kazem kompajleru koje sam registre koristio da bi on bolje rasporedio podatke po registrima ili on to sam vidi iz obj fajla?

genuine je napisao(la):
u gcc je jako lepo resen inline asm.. ja samo navodim da hocu podatak da bude u registru i onda ga koristim kao %0,%1 i sl. a on posle vodi racuna o alokaciji registara... moze li nesto slicno da se uradi u VC++...

Ta gcc sintaksa je blago receno odvratna. Inace to ne moze u drugim kompajlerima, ali ne treba da brines -- kompajler uopste ne zanima koje si ti registre koristio u funkciji dokle god si sacuvao sve non-volatile registre. Drugim recima, on ce ih koristiti sve kako nadje za shodno (unutar specifikacije naravno), a na tebi je da "sve sto koristis vratis kako je bilo" i nece biti problema.

Nazalost, ako malo bolje proanaliziras novu registarsku konvenciju videces da imas isti ili u nekim slucajevima cak i manji broj registara na raspolaganju za asemblerski kod nego ranije. Znaci, veci broj GPR registara u praksi donosi nista ili jako malo jer vecinu moras cuvati eksplicitno na steku ako hoces da ih koristis.

Moje misljenje je da je dodavanje 8 GPR i 8 XMM registara u 64-bitnom modu zapravo samo marketingski potez firme AMD po sistemu "daj da dupliramo jos nesto osim broja bitova" -- samo su ih "odobrili za spoljnu upotrebu" iz register file-a koji je odavno imao veci broj registara interno. Na primer Intel P4 je imao 128 GPR registara interno za renaming. Hardware register renaming inace odavno resava sve probleme manjka registara u x86 procesorima.
 
pa jeste malo cudno.. koliko mi se cini registar ili dva vise nego pre sto se tice eksternih asm programa ali opet mnogo je bolje na nivou celog programa...
za vece aritmeticke izraze posebno( manja potraznja ka memoriji u svakom slucaju)...
Mada nikad mi nije bilo jasno zasto ni intel ni amd nisu u arhitekturu ubacili recimo skolskih 32 GPR ili vec kojih registra... razumem da u organizaciji ima 128 ili koliko vec rename registara za razresavanje hazarda ali opet kad programiram ja to ne vidim....
Znam da dosta zavisi od konkretnog slicaja ali koliko je poboljsanje brzine za prosecan program koji nema inline SSE i sl vec samo obican C kod kada se rekompajlira kao 64-bitni program?

e da i jos nesto ..
kada koristim intrinsic funkcije i rezultat mi je recimo u u promenljivoj tmp deklarisanoj kao __m128 tmp; kako da vratim najnizi float iz te promenljive kao rezultat procedure....
u spec. kaze da rezultat ako je float ili double treba da se vrati kroz xmm0 registar... ako probam da kazem return tmp.m128_f32[0]; onda koliko sam video u disasembleru rezultat vraca kroz stek pa tu nesto jos istumba sto u opste ne valja.... jel mogu eksplicitno da naznacim na koji xmm registar hocu da mi se mapira odredjena promenljiva....
 
Poslednja izmena:
genuine je napisao(la):
Znam da dosta zavisi od konkretnog slicaja ali koliko je poboljsanje brzine za prosecan program koji nema inline SSE i sl vec samo obican C kod kada se rekompajlira kao 64-bitni program?

Pa sam si ukapirao da zavisi od slucaja, sta da ti kazem?
Mogu samo da ti kazem da kad prevedes sa novim kompajlerom dobijas po defaultu umesto FPU float SEE, a umesto FPU double SSE2 kod. Sa starim si po defaultu imao samo FPU kod.
Medjutim ni to nije nesto narocito (iako vise znaci kod Intela nego kod AMD-a), jer se koristi samo skalarni format SIMD instrukcija.
Da bi se dobilo ubrzanje od vektorizacije treba ili raditi rucno ili pazariti Intel C++ compiler za 399$.
 
Evo jednog primera 64-bitnog koda:

Kod:
; call cpuid with args in eax, ecx
; store eax, ebx, ecx, edx to p
PUBLIC cpuid64
.CODE
       ALIGN     8
cpuid64	PROC FRAME
; void cpuid64(CPUID_ARGS* p);
; rcx <= p
        sub			rsp, 32
        .allocstack 32
        push		rbx
        .pushreg	rbx
        .endprolog
        
		mov	r8, rcx
		mov eax, DWORD PTR [r8+0]
		mov ecx, DWORD PTR [r8+8]
		cpuid
		mov DWORD PTR [r8+0], eax
		mov DWORD PTR [r8+4], ebx
		mov DWORD PTR [r8+8], ecx
		mov DWORD PTR [r8+12], edx

        pop      rbx         
        add      rsp, 32     
        
        ret                  
        ALIGN     8
cpuid64 ENDP
_TEXT ENDS
 
sta radi ova direktiva
sub rsp, 32
.allocstack 32?


alocirao si prostor na staku za 32 bajta sa sub...
a .allocstack 32?
 
genuine je napisao(la):
sta radi ova direktiva
sub rsp, 32
.allocstack 32?


alocirao si prostor na staku za 32 bajta sa sub...
a .allocstack 32?

Ne pratis na casu...

.allocstack 32 obavestava exception handlere da moraju da oduzmu 32 bajta od stack pointera da bi vratili stack u stanje pre ulaska u f-ju ukoliko se u istoj desi exception.
 
Aha... Ok probacu da primenim...Hvala na malom predavanju..🙂
 
hm.. to otvara nove mogucnosti ali za sada cu da ostanem na vc++ i gcc..
inace jel postoji noncommercial licenca intelovog c++ kompajlera za windows posto koliko sam ja gledao bilo je samo za linux?

i jos nesto da pitam... kolika je mogucnost da kod generisan intelovim c++ kompajlerom za pentium IV radi sporije na AMD-ovim Athlon64 nego sto treba... ( znam da pitanje nije bas najnormalnije ali opet da pitam )
 
Poslednja izmena:
genuine je napisao(la):
inace jel postoji noncommercial licenca intelovog c++ kompajlera za windows posto koliko sam ja gledao bilo je samo za linux?

Za Windows ne. Mora se izdvojiti 399$.

genuine je napisao(la):
kolika je mogucnost da kod generisan intelovim c++ kompajlerom za pentium IV radi sporije na AMD-ovim Athlon64 nego sto treba...

Sasvim je normalno da radi sporije. :d

Dva objasnjenja postoje:

1. Intelovce je mrzelo da pisu komplikovaniju detekciju procesora i njihovih mogucnosti. Kod AMD-a se dosta stvari razlikuje i neke mogucnosti se prijavljuju na drugom mestu ili se prijavljuju netacno kod starijih generacija procesora.

2. Mozda namerno usporavaju AMD mada im se ne moze zameriti zbog toga jer ipak su ulozili velike sredstva (sto novcana, sto u vidu ljudstva) u istrazivanje i razvoj kompajlera. Ne bi bilo fer da neko za dzaba profitira.

Moguce je lako promeniti kod da ne proverava. Medjutim i tada AMD bude nesto sporiji jer jednostavno neki mix instrukcija njemu losije lezi, a i SIMD kod izvrsava ipak i do 20% losije od Intela.

Evo Lukija je probao kod njega nesto sto smo ortak i ja pisali i preveli sa ICC (naravno patchovano), ~284 sekunde na Venice @ 2.5GHz, a kod mene na 3.0GHz P4 ~253 sekunde. Nemoj me drzati za rec bas u sekundu, mrzi me da gledam u history od messengera ali to je otprilike to.
 
Nazad
Vrh Dno