2013-11-10 2 views
6

В моем университете мы только что познакомились с IA32 x87 FPU. Но нам не сообщили, как очистить FPU-Stack от более не требуемых элементов.Бесплатно x87 FPU Stack (ia32)

Представьте, что мы выполняем простой расчет, например (5.6 * 2.4) + (3.9 * 10.3).

.data 
     value1: .float 5.6 
     value2: .float 2.4 
     value3: .float 3.8 
     value4: .float 10.3 

     output: .string "The result is: %f\n" 

.text 
.global main 

main: 
     fld  value1   # Load/Push 5.6 into FPU 
     fmul value2   # Multiply FPU's top (5.6) with 2.4 
     fld  value3   # Load/Push 3.8 into FPU 
     fmul value4   # Multiply the top element of the FPU's Stacks with 10.3 
     fadd %st(1)   # Add the value under the top element to the top elements value 

.output: 
     # Reserve memory for a float (64 Bit) 
     subl $8, %esp 
     # Pop the FPU's top element to the program's Stack 
     fstpl (%esp) 
     # Push the string to the stack 
     pushl $output 
     # Call printf function with the both parameters above 
     call printf 
     # Free the programs stack from the parameters for printf 
     addl $12, %esp 

.exit: 
     movl $1, %eax 
     int $0x80 

Проблема заключается в том: После выскакивают верхний элемент ПДП, который держит результат Расчетным в. Как освободить стек FPU от оставшегося недавно верхнего элемента, который содержит результат (5.6 * 2.4).

Единственный способ, который я могу себе представить, это освободить еще несколько стеков программ и выталкивать элементы из стека FPU, пока все ненужные элементы не будут удалены.

Есть ли способ напрямую манипулировать указателем верхнего уровня?

+2

Компилятор C обычно хорош для генерации кода, подобного этому. Шахта использует FMULP вместо FMUL, проблема решена. –

+0

Обратите внимание, что вы * можете * вручную перемещать вершину с помощью 'fincstp' и' fdecstp' и отмечать regs бесплатно с помощью 'ffree', но лучше этого избежать. – gsg

+0

Если вы знаете, сколько элементов у вас есть в стеке FPU, вы можете выполнить 'ffree st (0)' и 'fincstp' в цикле. – Michael

ответ

6

Для этого у вас нет предметов интерьера в стеке, вам необходимо использовать FADDP и FMULP и аналогичные инструкции.

+0

Итак, вы предлагаете провести предварительный результат в стеке программы? (Так как упомянутые операции вызывают результат сразу после оценки). – tmuecksch

+4

действительно, используйте стек для вашего преимущества, например. для вычисления A * B + C * D вы нажимаете A; mulp B; нажмите C; mulp D; addp – Quonux

1

Существует несколько инструкций, которые могут выполнять операции как те, которые вы ищете. FDECSTP уменьшает указатель стека (не делая ничего другого), FFREE отмечает слот как пустой (не касаясь указателя стека, хотя). Однако решение, упомянутое выше, с FADDP или FMULP, является более приятным.

Вы должны рассмотреть возможность загрузки Intel Architecture Manuals. Они содержат полный набор команд семейства процессоров Intel.

5

В случае кто-то вроде меня приходит сюда в поисках лучшего способа очистить стек Я нашел простое решение, чтобы быть лучшим:

fstp ST(0) ; just pops top of the stack 
+1

Или 'FNINIT', чтобы очистить * все * регистры FP, независимо от того, сколько из них использовалось ранее.Но да, 'fstp st (0)' - самый эффективный способ * просто * поместить верхнюю часть стека, отбрасывая результат. –

+1

@PeterCordes Я считаю, что даже восемь инструкций FSTP были бы быстрее, чем инструкция FNINIT, учитывая, что более поздняя версия является микрокодированной. Кроме того, с FSTP вам не нужно возвращать управляющее слово FP к тому, что должно быть. –

+0

@RossRidge: хороший пункт. На Skylake 'FNINIT' составляет 18 мкп с пропускной способностью по одному на 78 циклов. 'FFREE st (0)' имеет пропускную способность одного на 0,5 цикла. Будучи микрокодированным, автоматически не означает необычно медленное (например, «VGATHERQPD» составляет 5 мкп с одной пропускной способностью в 2 цикла на Skylake, и что-то большее, чем 4 юпа, означает, что он должен поступать с ПЗУ микрокода и храниться в кэше uop как указатель MS-ROM вместо uops напрямую), но оказывается, что 'FNINIT' специально является плохим предложением для Intel и AMD, за исключением кода. –

2

EMMS также может быть использован для обозначения каждого члена F.P. стек как свободный. Это имеет преимущество перед финитом, что он не изменяет никаких флагов в f.p. контрольные или статусные слова (маски исключений и т. д.)

+0

Согласно таблицам Агнера Фога, EMMS на AMD Bulldozer/Ryzen работает так же быстро, как 1 FFREE. Но на Intel это может быть довольно медленно: 31 выход, по одному на пропускную способность 18 циклов на Sandybridge. (Лучше на Skylake: 10 часов, по одному на 6c пропускную способность, так что это лишь несколько хуже, чем 8x 'FFREE st (i)' инструкций.) –

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

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