Я изучал, как операции с плавающей запятой выполняются на 32-битной машине Intel. Я разобрал следующие строки кода C, чтобы понять, как компилятор транслирует эти строки при ассемблере.
a = 13;
b = 5;
d = (float) a / (float) b;
А вот дизассемблированная версия кода, показанного выше:
mov DWORD PTR [ebp-0x10],0xd
mov DWORD PTR [ebp-0x14],0x5
fild DWORD PTR [ebp-0x10]
fild DWORD PTR [ebp-0x14]
fdivrp st(1),st
fstp DWORD PTR [ebp-0x18]
Что меня смущает, так это инструкции fdivrp и fstp. Из того, что я прочитал, приведенный выше код сохранит результат деления с плавающей запятой в регистре st (1), а затем вытолкнет вершину стека, сделав st (1) вершиной, а не st (0). Однако следующая инструкция fstp сохраняет содержимое st(0) в ячейку памяти, на которую указывает адрес ebp-0x18, а затем выталкивает стек, делая st(1) вершиной. Я считаю, что неправильно понял документы о том, как работают эти инструкции, поскольку мое понимание не сохранит результат в памяти. Буду признателен, если кто-нибудь объяснит, как именно работают эти 2 инструкции.
st(0)
. 64-битный ABI использует регистры SSE для передачи/возврата чисел с плавающей запятой и двойных чисел. 32-битный код можно скомпилировать для использования SSE/SSE2, если вы не возражаете против нарушения совместимости с оборудованием 13-летней давности (AMD Athlon XP был последним процессором, в котором не было SSE2). - person Peter Cordes   schedule 28.10.2015