Вычитание чисел с плавающей точкой в FPU

Последнее обновление: 02.07.2023

Для вычитания чисел с плавающей точкой FPU предоставляет инструкции fsub, fsubp, fsubr, fsubrp, fisub и fisubr. Они могут принимать различные формы. Они могут вообще не принимать операндов:

fsub
fsubp
fsubr
fsubrp

Без операндов fsub аналогична fsubp. В этом случае они извлекают ST(0) и ST(1) из стека регистров, вычисляют ST(1) – ST(0) и затем помещают разницу обратно в стек. Инструкции fsubr и fsubrp также извлекают значения ST(0) и ST(1), только вычисляют ST(0) – ST(1).

Еще одна форма инструкций принимает два операнда - два регистра стека FPU:

fsub st(i), st(0)
fsub st(0), st(i)
fsubp st(i), st(0)
fsubr st(i), st(0)
fsubr st(0), st(i)
fsubrp st(i), st(0)

С двумя операндами инструкция fsub из первого операнда вычитает второй и результат присваивает первому операнду. При этом оба операнда должны быть регистрами, и один них должен быть ST(0). fsubp также из первого операнда вычитает второй и результат присваивает первому операнду, но после этого также извлекает значение ST(0) из стека. Для инструкции fsubp второй операнд должен быть ST(0). Инструкции fsubr и fsubrp работают так же, как fsub и fsubp, за исключением того, что они из второго операнда вычитают первый и результат присваивает первому операнду.

И еще одна форма принимает один операнд - переменную:

fsub mem32
fsub mem64
fsubr mem32
fsubr mem64
fisub mem16
fisub mem32
fisubr mem16
fisubr mem32

Инструкции fsub и fsubr принимают 32- или 64-битные переменные, которые представляют числа с плавающей точкой. Они преобразуют операнд в 80-битное значение расширенной точности и вычитают его из ST(0) (fsub) или вычитают ST(0) из этого значения (fsubr) и сохраняют результат обратно в ST(0). Инструкции fisub и fisubr принимают для 16- и 32-битные переменные, которые представляют целые числа, и вычитают их из ST(0): .

Применение вычитания на примере инструкции fsub. Без параметров:

.data
    st1 real8 3.6
    st0 real8 5.6
    result dword ? 
.code
main proc
    fld st1              ; загружаем число st1 в стек FPU
    fld st0              ; загружаем число st2 в стек FPU
    fsub                ; ST(0) = ST(1) - ST(0) = 3.6 - 5.6 = -2
    fistp result        ; Преобразуем число из ST(0) в dword
    mov eax, result     ; EAX = -2
    ret
main endp
end

Здесь в стек FPU последовательно загружаются переменные st1 и st0. Поскольку больше ничего не загружается в стек, то эти переменные будут располагаться в регистрах ST(0) (st0) и ST(1)(st1). И инструкция fsub выполнит вычитание ST(1) - ST(0) и поместит результат в ST(0).

Другой пример - вычтем из значения одного регистра значение второго:

.data
st0 real8 5.4
st1 real8 4.6
st2 real8 1.2
result dword ? 
.code
main proc
    fld st2              
    fld st1              
    fld st0              
    fsub st(0), st(2)   ; вычитаем ST(0) = ST(0) - ST(2)
    fistp result        
    mov eax, result     ; EAX = 4
    ret
main endp
end

Здесь вычитаем из значения регистра ST(0) значение регистра ST(2). Результатом будет число 4.0, которое помещается в первый регистр - ST(0).

Вычитание переменной-числа с плавающей точкой:

.data
st0 real8 10.6
n real4 3.3
result dword ? 
.code
main proc             
    fld st0              
    fsub n              ; вычитаем из ST(0) значение переменной n
    fistp result        
    mov eax, result     ; EAX = 7
    ret
main endp
end

В ST(0) загружается число st0, и из него вычитается значение переменной n.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850