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. См. соглашения о вызовах x86.

Но long double в VC для x86 и x86_64 то же самое, что и double и не даст вам большей точности. Таким образом, в Windows для выполнения 80-битных операций с плавающей запятой вам нужно использовать другой компилятор, такой как GCC, Clang или ICC. Кроме того, 80-битная длинная двойная вычисляется 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 на 53-битную (double) перед main, поэтому, если ваш код GCC/Clang связан с этим, вам необходимо вручную установить для него 64-битную значащую точность по умолчанию. . randomascii.wordpress.com/2012/03/21/< /а> - person Peter Cordes; 31.05.2019