Visual C++ x86 ABI: как VC++ връща стойност?

Знам, че 1/2/4-байтови цели числа се връщат в eax, а 8-байтови цели числа се връщат в eax:edx.

Между другото, как се връщат 4/8/16-байтови стойности с плаваща запетая (Може би си спомням, че long double може да е 16 байта..) в cdecl/stdcall?


Благодарение на @MatteoItalia знам, че long double на VC++ е 8-байтов; Тогава как мога да използвам 16-байтова плаваща запетая?

(Не ми казвайте „просто използвайте 8 байта!“. Наистина ми трябва.)

Хм, мисля, че трябва да се задоволя с 10-байтова плаваща запетая...


person ikh    schedule 26.01.2014    source източник


Отговори (2)


Връщаните стойности на FP се връщат в регистъра ST0 x87 (вижте напр. тук) .

Между другото, във VC++ long double (който в x87 е 80 бита) е ефективно синоним на double.

person Matteo Italia    schedule 26.01.2014
comment
@ikh: няма естествена 128-битова поддръжка на FP на x86 (или на която и да е широкоразпространена платформа, за която знам), вероятно ще трябва да потърсите някаква библиотека, която го внедрява в софтуера (но ще бъде значително по-бавна от хардуерно базираната FP ). Между другото, защо ви е нужен толкова точен тип? - person Matteo Italia; 26.01.2014
comment
@MetteoItalia хм, трябва да съм доволен от 10 байта с плаваща запетая.. Пиша малък байт код, интерпретиран език и има известна нужда от 16 байта с плаваща запетая..., но трябва да използвам 10 байта като 16 байта - person ikh; 26.01.2014
comment
@ikh: x87 поддържа 80 бита (=10 байта) FP, но VC++ не излага тази функционалност. g++ OTOH го предоставя (поне на Linux) чрез типа long double. Мисля, че дори и в този случай върнатата стойност ще остане в ST0. - person Matteo Italia; 26.01.2014

Не предоставихте архитектурата, но x86 връща стойности с плаваща запетая в ST(0), а x86_64 връща в XMM0. Вижте х86 конвенции за повикване

Но long double във VC за x86 и x86_64 е същият като double и няма да ви осигури повече точност. Така че в Windows, за да извършвате 80-битови операции с плаваща запетая, трябва да използвате друг компилатор като GCC, Clang или ICC. Също така, 80-bit long double се изчислява от x87, така че може да работи по-лошо от добра SSE библиотека.

Ако имате нужда от повече от 10-байтова двойна стойност, тогава трябва да внедрите своя собствена библиотека с плаваща запетая или да използвате някои външни библиотеки. GCC 4.3 и по-нови версии имат вградена поддръжка за __float128 чрез софтуерна библиотека. Вижте long double (специфично за GCC) и __float128

Друг подход е използването на double-double за прилагане на < em>стойности с почти четворна точност като в PowerPC или SPARC. Не е съвместим с IEEE, но можете да използвате хардуерна двойна поддръжка за ускоряване, така че ще бъде по-бърз от мекия __float128

person phuclv    schedule 26.01.2014
comment
Също така в Windows, MSVCRT кодът задава x87 significand precision на 53-bit (double) преди main, така че ако вашият GCC/Clang код е свързан с това, трябва ръчно да го зададете обратно на 64-bit significand пълна точност по подразбиране . randomascii.wordpress.com/2012/03/21/ - person Peter Cordes; 31.05.2019