64 bit assembler není to samé co 32 bit

vložil Radek Červinka 28. prosince 2010 21:59

Hodně toho bylo napsáno ohledně 64bit Delphi. Aktuální stav je takový, že další verze Delphi by měla být i s 64bit kompilátorem (pokud se nestane něco hooodně nepředvídatelného jako zemětřesení atp).

Následující informace je čistě informativní a bez záruky a jen jako ukázka, vše se může změnit do doby vydání další verze Delphi.

Update

Jak na tom bude ale integrovaný assembler (původně znám jako BASM - Built-in ASM, od dob Kylixu jako CHASM - Chuck Jazdzewski ho přepsal pro podporu Kylixu a pak byl jen zlepšován - tj. Chuck ASM)? Od začátku bylo (aspoň někomu) jasné, že vzhledem ke změnám architektury, volacím konvencím (64bit má jen jednu) a kýho šlaka nebude stačit jen nahradit např. EAX (32bit registr) za RAX (64bit registr).

Allen Bauer ukázal pravděpodobné řešení. Osobně (můj názor) si myslím, že větší část kódu psaného v asm bude v 64bit psaná v pascalu (PUREPASCAL) a pravděpodobně jen kritické části budou v CHASM. Proč? Už dříve jsem psal o výhodách ne ASM kódu vzhledem k lepším možnostem inline kódu, navíc nyní vstupuje do hry i počet nutných změn.

Malá ukázka změn:

CHASM 64 preview

nahoře 32bit kód, dole 64bit

Další čtení: x64 ABI vs. x86 ABI aneb volací konvence pro AMD64 a EM64T (o rozdílech mezi 64bit procesory jsem psal už dříve).

Update

Jedná se o Classes.StdWndProc

aktuální deklarace:

function StdWndProc(Window: HWND; Message, WParam: Longint;
  LParam: Longint): Longint; stdcall; assembler

Tagy: , ,

Novinky v Delphi

Komentáře

29.12.2010 8:08:50 #

pepak

Tedy možná jsem úplně slepý, ale zrovna tahle ukázka vypadá jako přesný opak toho, co píšeš - rozdíl *v této části programu* je pouze ve volací konvenci (tj. v tom, jak se předají parametry), ale jinak to je doslova a do písmene "to samé, stačí nahradit EAX za RAX". Zdánlivý rozdíl v tom, že v 32bitovém kódu se jako parametry posílají přímo komponenty TMsg, zatímco v 64bitovém kódu se posílá odkaz na TMsg, je dán čistě jen deklarací *volané* metody, ne odlišností 32bitového a 64bitového assembleru; kdyby obě volané metody měly stejnou deklaraci, byla by "náhrada EAX za RAX" do očí bijící.

pepak

29.12.2010 10:31:36 #

radekc

Právě to je problém. Všechna volání funkcí se musí změnit díky jiné volací konvenci (nová je jiná). Navíc se musí zachovávat jiné registry, takže i kod bez call se bude muset projít. Ale uznavám, že v případě, že někdo má jen výpočet v ASM a nepoužívá koprocesor (který není v módu 64 MS doporučován), tak bude mít úprav méně.

Jinak TMessage je stuktura z API windows.

radekc

29.12.2010 10:54:17 #

pepak

Myslím si, že směšuješ dvě nesouvisející věci:

1) Volací konvence.
2) Konkrétní deklarace funkce.

Problém je v tom, že v tomto příkladu se v přechodu z 32 do 64 bitů evidentně měnilo obojí: 32bitová funkce podle všeho byla deklarována jako:
procedure Neco32(Message, wParam, lParam, ResultCode: longint); stdcall;
Zatímco 64bitová funkce byla deklarována jako:
procedure Neco64(var Msg: TMessage); volaci_konvence_pro_64bit;
Pokud by se měnila jen jedna část, tzn. jen volací konvence nebo jen parametry, byl by ten assemblerový kód v obou verzích podstatně podobnější. Je jasné, že pokud 64bitový kód používá jinou volací konvenci, tak ta se měnit musí, ale nevidím rozumný důvod, proč by se při přechodu mezi různě bitovým kódem měla měnit i deklarace - proč bych nemohl mít:
procedure Neco64(Message, wParam, lParam, ResultCode: NativeInt); volaci_konvence_pro_64bit;

pepak

29.12.2010 11:30:02 #

radekc

Nemám jinou ukázku než tu co jsem uvedl. Ale předpokládám, že volaná funkce je z API. A obávám se, že veškeré šachování není kvůli změně deklarace, ale právě k vůli změně volací konvence. Schválně jsem dával do článku odkaz na ten (podle mne vyčerpávající) článek - zkus se do něj kouknout. Samozřejmě se to týká asi jen volání API, ne vlastních funkcí, ale zde jsem opravdu už na tenkém ledu.

Citace:

The x64 Windows ABI is a 4 register ‘fast-call’ calling convention, with stack-backing for those registers. There is a strict one-to-one correspondence between arguments in a function, and the registers for those arguments. Any argument that doesn’t fit in 8 bytes, or is not 1, 2, 4, or 8 bytes, must be passed by reference. There is no attempt to spread a single argument across multiple registers. The x87 register stack is unused. It may be used, but must be considered volatile across function calls. All floating point operations are done using the 16 XMM registers. The arguments are passed in registers RCX, RDX, R8, and R9. If the arguments are float/double, they are passed in XMM0L, XMM1L, XMM2L, and XMM3L. 16 byte arguments are passed by reference.

Navíc podle dostupných informací je tam problém i se zachováním struktury pro "unwind exception", tj. informacích o call stacku při vyjímce - viz stejný blog, a stěžoval si na to i Allen Bauer.

radekc

29.12.2010 11:37:06 #

radekc

Takže pro mne pokud bych měl něco volat z API tak se na to vykašlu, v ostatních případech bych to velmi zvážil.

radekc

1.1.2011 20:07:00 #

radekc

Mimochodem se jedná o Classes.StdWndProc

function StdWndProc(Window: HWND; Message, WParam: Longint;
  LParam: Longint): Longint; stdcall; assembler;

viz zdrojaky classes

radekc

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců