Для вычитания чисел с плавающей точкой 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.