2015-10-27 8 views
3

Я изучаю, как операции с плавающей запятой выполняются на 32-битной Intel-машине. Я разобрал следующие строки кода C, чтобы получить, как компилятор переводит эти строки на сборку.Плавающая точка сборки на процессоре Intel

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 и ФСНП инструкции. Из того, что я прочитал, приведенный выше код сохранит результат деления с плавающей запятой в регистре st (1), а затем вытащите верхнюю часть стека, делая st (1) вершиной, а не st (0). Однако следующая команда fstp сохраняет содержимое st (0) в ячейке памяти, указываемой адресом ebp-0x18, а затем выталкивает стек, делая st (1) вершиной. Я считаю, что неправильно понял документы о том, как эти инструкции работают, поскольку мое понимание не сохранит результат в памяти. Я был бы признателен, если кто-нибудь сможет объяснить, как работают эти две инструкции.

+0

Вершина стека всегда называется st (0). – apokryfos

+0

http://stackoverflow.com/tags/x86/info имеет ссылку на http://www.ray.masmcode.com/tutorial/index.html, который должен охватывать все. Если вам не приходится часто обращаться с кодом x87, я бы рекомендовал не тратить на него время, кроме случаев, когда это происходит на практике. x87 является устаревшим, за исключением того, что 32-битный ABI по-прежнему возвращает значения FP в 'st (0)'. В 64-битном ABI используются регистры SSE для пропуска/возврата поплавков и удвоения. 32-битный код может быть скомпилирован для использования SSE/SSE2, если вы не возражаете против совместимости с 13-летним аппаратным обеспечением (AMD Athlon XP был последним процессором, не имеющим SSE2). –

+0

Питер, я вижу, что вы регулярно обращаетесь к 32-битным ABI и 64-битным ABI. Имейте в виду, что существуют разные ABI для разных ОС, и не совсем понятно, что вы имеете в виду, вероятно, Linux или BDS? Обратите внимание, что в 32-битной Windows код x87 совсем не устарел. –

ответ

4

Регистры с плавающей точкой всегда адресуются относительно текущей вершины стека. Таким образом, st(0) всегда является вершиной стека. fdivrp st(1), st помещает результат в st(1), а затем сразу же всплывает st(0), поэтому стек содержит только один элемент, который является новым st(0), содержащим результат. fstp записывает его в память и удаляет из стека fpu, оставляя его пустым.

+0

Означает ли это, что fdivrp st (1), st pops st1 to st0? В документах указано, что для заполнения стека регистров процессор отмечает регистр ST (0) как пустой и увеличивает указатель стека (TOP) на 1. Я считаю, что эта фраза трудно понять. – MykelXIII

+1

С помощью popping стек 'TOP' изменяется, и поскольку индексирование индекса относится к' TOP', физический регистр, который ранее назывался 'st (1)', становится 'st (0)'. Движения данных не задействованы. – Jester

 Смежные вопросы

  • Нет связанных вопросов^_^