Справочник от Автор24
Поделись лекцией за скидку на Автор24

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

  • 👀 267 просмотров
  • 📌 223 загрузки
Выбери формат для чтения
Загружаем конспект в формате docx
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Вычисления с плавающей точкой» docx
Глава 3. Вычисления с плавающей точкой Все операции с плавающей точкой выполняет специальное устройство – сопроцессор – FPU (Floating Point Unit) (собственные регистры и команды). В начале – отдельная микросхема. Начиная с i486 – блок, встроенный в процессор. § 3.1. Типы данных FPU Тип данных Бит Пределы Короткое вещественное 32 1.1810-38 — 3.401038 Длинное вещественное 64 2.2310-308 — 1.7910308 Расширенное вещественное 80 3.3710-4932 — 1.18104932 0,625 = 0,101b = (нормализация в процессорах Intel) 1,01b × 2-1 мантисса = 1,01 порядок = -1 Первая цифра мантиссы всегда равна 1 ее можно не писать точность увеличивается на 1 бит. Значение порядка хранят не в виде целого со знаком, а в виде суммы с некоторым числом так, чтобы хранить всегда только положительное число легко сравнивать вещественные числа. Как хранится действительное число, разберем на примере короткого вещественного числа s e f 31 30 23 22 порядок + смещение = характеристика p + 127 = e V = (-1)s × 2(e-127) × 1.f (0 < e < 255) V = (-1)s × 2(-126) × 0.f (e = 0, f ≠ 0) (денормализация, для работы с очень маленькими числами) V = (-1)s × 0 (e = 0, f = 0) V = (-1)s × ∞ (e = 255, f = 0) V = NAN (e = 255, f ≠ 0) (не-число) A C 1 1 1 1 31 30 23 22 V = (-1)1×2(78-127) × 1.0 = -2-49 короткое вещественное: бит 31 знак мантиссы биты 30 – 23  8-битная экспонента + 127 биты 22 – 0  23-битная мантисса без первой цифры длинное вещественное: бит 63  знак мантиссы биты 62 – 52  11-битная экспонента + 1024 биты 51 – 0 52-битная мантисса без первой цифры расширенное вещественное: бит 79  знак мантиссы биты 78 – 64  15-битная экспонента + 16 383 биты 63 – 0  64-битная мантисса с первой цифрой (то есть бит 63 равен 1). FPU выполняет все вычисления в 80-битном расширенном формате, а 32- и 64-битные числа используются для обмена данными с основным процессором и памятью. § 3.2. Регистры FPU Регистры данных – 8 основных регистров r0, r1, …, r7 (физические номера). Эти регистры рассматриваются как стек FPU (кольцо!). Вершина стека FPU – st(0), а более глубокие элементы – st(1), st(2), …, st(7) (логические номера). r0 st(3) r1 st(4) r2 st(5) r3 st(6) r4 st(7) r5 st(0) top (3-битовое поле) = 5 r6 st(1) r7 st(2) 79 Если, регистр r5 называется st(0), то при записи в стек FPU числа, оно будет записано в регистр r4, который станет называться st(0), r5 станет называться st(1) и т.д. К регистрам r0, r1, …, r7 нельзя обращаться напрямую (по именам). Служебные регистры Регистр состояния Status Word Register swr Регистр управления Control Word Register cwr Регистр тегов Tags Word Register twr 15 Регистры указателей адрес последней выполненной команды ipr адрес ее операнда dpr 47 Регистр состояния swr – отражает текущее состояние FPU 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 b c3 top c2 c1 c0 es sf pe ue oe ze de ie c3, c2, c1, c0 - условные флаги (используются для условных переходов, аналог eflags) top - номер регистра, являющегося вершиной стека FPU es - общий флаг ошибки = 1, если произошло хотя бы одно из 6 исключений sf - ошибка работы стека FPU (попытка писать в непустую позицию в стеке FPU или считать число из пустой позиции в стеке FPU) 6 флагов исключительных ситуаций: pe - флаг неточного результата - результат не может быть представлен точно ue  - флаг антипереполнения - результат слишком маленький oe - флаг переполнения - результат слишком большой ze  - флаг деления на ноль - выполнено деление на ноль de  - флаг денормализованного операнда - выполнена операция над денормализованным числом ie  - флаг недопустимой (недействительной) операции: - ∞ - ∞, ∞ + ∞ Регистр управления cwr – определяет особенности обработки численных данных 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 ic rc pc pm um om zm dm im 6 масок исключений: pm - маска неточного результата um - маска антипереполнения om - маска переполнения zm - маска деления на ноль dm - маска денормализованного операнда im - маска недопустимой операции Если маскирующий бит установлен, исключения не происходит. rc - управление округлением m - значение в st, a < m < b 00 к ближайшему числу 01 к - ∞ (m = a) 10 к + ∞ (m = b) 11 к 0 (отбрасывается дробная часть) pc - управление точностью 00 одинарная точность (32-битные числа) 10 двойная точность (64-битные числа) 11 расширенная точность (80-битные числа) Регистр тегов twr содержит восемь пар бит, описывающих содержание каждого регистра данных 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 r7 r6 r5 r4 r3 r2 r1 r0 00 регистр содержит число 01 регистр содержит 0 10 регистр содержит нечисло, бесконечность, денормализованное число, NAN 11 регистр пуст Регистры ipr и dpr содержат адрес последней выполненной команды (за некоторым исключением) и адрес ее операнда. Используются в обработчиках исключений для анализа вызвавшей его инструкции. Принцип работы сопроцессора § 3.3. Инструкции (команды) FPU Основные правила образования названий команд 1. Все названия инструкций начинаются с f – float 2. Вторая буква определяет тип операнда в памяти: i – целое двоичное число b – целое десятичное число отсутствие буквы – вещественное число 3. Последняя буква p означает, что последним действием инструкции является извлечение (выталкивание) из стека FPU: st(0) помечается как пустой, top = top + 1. 4. Последняя или предпоследняя буква r (reversed) означает реверсионное следование операндов. Инструкции пересылки данных fld источник Загрузить вещественное число в стек FPU. top = top – 1 st(0)= источник Источник: - переменная - st(i) double x = -0.25, y = 1, z; _asm{ finit ;инициализация сопроцессора fld x ;st(0) = x ;... fld st(0) ;копия вершины стека } fst приемник Скопировать вещественное число из стека FPU. приемник = st(0) Приемник: - переменная - st(i) fstp приемник Считать вещественное число из стека FPU. приемник = st(0) st(0) помечается как пустой top = top + 1 fild источник Загрузить целое число в стек FPU. ...Преобразовывает целое число со знаком из источника (16-, 32- или 64-битная переменная) в вещественный формат. fist приемник Скопировать целое число из стека FPU. ...Попытка записи слишком большого числа, бесконечности или не-числа приводит к исключению «недопустимая операция». fistp приемник Считать целое число из стека FPU. ...Попытка записи слишком большого числа, бесконечности или не-числа приводит к исключению «недопустимая операция». fxch [приемник] Обменять местами два регистра стека FPU. st(0) приемник (регистр стека FPU st(i)) st(0) st(1) (если приемник не указан) fcmovxx приемник, источник (Pentium Pro, Pentium II и выше) Условная пересылка данных. Это набор инструкций, которые копируют содержимое источника (st(i)) в приемник (st(0)), если удовлетворяется то или иное условие (условная пересылка данных). Каждое условие соответствует тем или иным значениям флагов регистра flags. Подробнее – далее... Арифметические инструкции fadd [[приемник,] источник ] Сложение вещественных чисел. приемник = приемник + источник Приемник Источник не указан переменная st(0)= st(0)+ переменная st(0) st(i) st(0)= st(0)+ st(i) st(i) st(0) st(i)= st(i)+ st(0) не указан не указан st(1)= st(1)+ st(0) st(0) помечается как пустой top = top + 1 faddp приемник, источник Сложение с выталкиванием из стека FPU. Приемник Источник st(i) st(0) st(i)= st(i)+ st(0) st(0) помечается как пустой top = top + 1 fiadd источник Сложение целых чисел. Источник: переменная, содержащая целое число. st(0) = st(0) + переменная int i = 10; double y = 10; _asm{ finit fld y fadd y ;st(0)==20 int i = 10; double y = 10; _asm{ finit fld i fadd i ;в st(0)«мусор» int i = 10; double y = 10; _asm{ finit fild i fiadd i ;st(0)==20 fsub [[приемник,] источник] Вычитание вещественных чисел. приемник = приемник – источник Приемник Источник не указан переменная st(0)= st(0)- переменная st(0) st(i) st(0)= st(0)- st(i) st(i) st(0) st(i)= st(i)- st(0) не указан не указан st(1)= st(1)- st(0) st(0) помечается как пустой top = top + 1 fsubp приемник, источник Вычитание с выталкиванием из стека FPU. Приемник Источник st(i) st(0) st(i)= st(i)- st(0) st(0) помечается как пустой top = top + 1 fisub источник Вычитание целых чисел. Источник: переменная, содержащая целое число. st(0) = st(0) – переменная fsubr [[приемник,] источник] Обратное вычитание вещественных чисел. приемник = источник – приемник Приемник Источник не указан переменная st(0)= переменная - st(0) st(0) st(i) st(0)= st(i)- st(0) st(i) st(0) st(i)= st(0)- st(i) не указан не указан st(1)= st(0)- st(1) st(0) помечается как пустой top = top + 1 fsubrp приемник, источник Обратное вычитание с выталкиванием из стека FPU. Приемник Источник st(i) st(0) st(i)= st(0)- st(i) st(0) помечается как пустой top = top + 1 fisubr источник Обратное вычитание целых чисел. Источник: переменная, содержащая целое число. st(0) = переменная – st(0) double a = 5, b = 2; _asm{ finit fld a fld b ;st(1)==5 st(0)==2 fsub st(0),st(1) ;st(0)==-3 double a = 5, b = 2; _asm{ finit fld a fld b ;st(1)==5 st(0)==2 fsubr st(0),st(1) ;st(0)==3 fmul [[приемник,] источник ] Умножение вещественных чисел. приемник = приемник × источник Приемник Источник не указан переменная st(0)= st(0) × переменная st(0) st(i) st(0)= st(0) × st(i) st(i) st(0) st(i)= st(i) × st(0) не указан не указан st(1)= st(1) × st(0) st(0) помечается как пустой top = top + 1 fmulp приемник, источник Умножение с выталкиванием из стека FPU. Приемник Источник st(i) st(0) st(i)= st(i) × st(0) st(0) помечается как пустой top = top + 1 fimul источник Умножение целых чисел. Источник: переменная, содержащая целое число. st(0) = st(0) × переменная fdiv [[приемник,] источник] Деление вещественных чисел. приемник = приемник / источник Приемник Источник не указан переменная st(0)= st(0) / переменная st(0) st(i) st(0)= st(0) / st(i) st(i) st(0) st(i)= st(i) / st(0) не указан не указан st(1)= st(1) / st(0) st(0) помечается как пустой top = top + 1 fdivp приемник, источник Деление с выталкиванием из стека FPU. Приемник Источник st(i) st(0) st(i)= st(i) / st(0) st(0) помечается как пустой top = top + 1 fidiv источник Деление целых чисел. Источник: переменная, содержащая целое число. st(0) = st(0) / переменная fdivr [[приемник,] источник] Обратное деление вещественных чисел. приемник = источник / приемник Приемник Источник не указан переменная st(0)= переменная / st(0) st(0) st(i) st(0)= st(i)/ st(0) st(i) st(0) st(i)= st(0)/ st(i) не указан не указан st(1)= st(0)/ st(1) st(0) помечается как пустой top = top + 1 fdivrp приемник, источник Обратное деление с выталкиванием из стека FPU. Приемник Источник st(i) st(0) st(i)= st(0)/ st(i) st(0) помечается как пустой top = top + 1 fidivr источник Обратное деление целых чисел. Источник: переменная, содержащая целое число. st(0) = переменная / st(0) fabs Абсолютное значение. st(0)=|st(0)| fchs Изменить знак. st(0) = – st(0) frndint Округлить до целого. st(0) = [st(0)] (или ]st(0)[) в rc режим округления fsqrt Извлечь квадратный корень. st(0) = √ st(0) и другие инструкции... double x = -0.25, y = 1, z; _asm{ finit ;инициализация сопроцессора fld x ;st(0) = x fabs ;st(0) = |x| fsqrt ;st(0) = sqrt(|x|) fsub y ;st(0) = sqrt(|x|) - y fst st(1) ;или fld st(0): st(1) == st(0) fmul ;st(0) = (sqrt(|x|) - y)^2 fst z ;z = st(0) } При вычислениях с плавающей точкой следите, чтобы не происходило заполнение всех 8 регистров данных. В случае переполнения стека FPU регистров данных результат вычислений не определен. Следует, где это возможно, использовать команды с выталкиванием из стека FPU (заканчивающиеся символом p). int i = 10; double z = 0; _asm{ finit ;инициализация сопроцессора mov ecx, i ;ecx = i (счетчик для команды loop) l1: fld1 ;st(0) = 1 fadd z ;st(0) = st(0) + z fstp z ;z = st(0) и вытолкнуть ;при fst z результат после 10 итераций не определен! loop l1 } //y = 1/1! + 1/2! + ... + 1/i! int i = 10; double y; _asm{ finit ;инициализация сопроцессора fld1 ;st(0) = 1 fld1 ;st(0) = 1 ;st(1) == 1 st(0) == 1 fst y ;y = st(0) ;теперь y == 1 == 1!/1 (первое слагаемое) ;st(1) == 1! st(0) == 1 mov ecx, i ;ecx = i dec ecx ;ecx = ecx - 1 (счетчик для команды loop) l1: ;сейчас st(1) == (i-1)! st(0) == i-1 fld1 ;st(0) = 1 ;st(2)==(i-1)! st(1) == i-1 st(0) == 1 faddp st(1), st(0) ;st(1) = st(1)+st(0) и вытолкнуть ;st(1)==(i-1)! st(0) == i fmul st(1), st(0) ;st(1) = st(1)st(0) ;st(1) == i! st(0) == i fld1 ;st(0) = 1 ;st(2) == i! st(1) == i st(0) == 1 fdiv st(0), st(2) ;st(0) = st(0)/st(2) ;st(2) == i! st(1) == i st(0) == 1/i! fadd y ;st(0) = st(0) + y ;st(2) == i! st(1) == i st(0) == y + 1/i! fstp y ;y = st(0) и вытолкнуть ;y == 1/1! + 1/2! + ... + 1/i! ;[st(1) == i! st(0) == i] loop l1 } Инструкции сравнения fcom [источник ] Сравнить вещественные числа fcomp [источник] Сравнить и вытолкнуть из стека FPU fcompp [источник] Сравнить и вытолкнуть из стека FPU два числа Источник переменная st(0) <> переменная st(i) st(0) <> st(i) не указан st(0) <> st(1) Инструкции устанавливают флаги c0, c2 и c3 Условие c3  zf c2  pf c0  cf st(0) > источник st(0) < источник 1 st(0) = источник 1 не сравнимы 1 1 1 Если один из операндов не-число, происходит исключение «недопустимая операция», а если оно замаскировано (флаг im == 1 регистра управления cwr), все три флага устанавливаются в 1. fcom ;или другие команды сравнения fstsw ax ;ax = swr sahf ;flags = ah: zf = c3, pf = c2, cf = c0 Теперь можно использовать условные команды (например jxx) как после команды cmp. xx n – not – не b – before – меньше e – равно u – несравнимы (флаг pf == 1) int key = 0; double x = -0.25, y = 0, z; _asm{ finit ;инициализация сопроцессора fldz ;st(0) = 0 fcom y ;st(0) <> y fstsw ax ;ax = sr sahf ;flags = ah: zf = c3, pf = c2, cf = c0 je error fld y fld x fdiv st(0), st(1) ;st(0) = st(0)/st(1) fst z ;z = x / y jmp fin error: mov key, 1 fin: } if (!key) printf("%lf\n", z); else printf("Division by 0\n"); fucom [источник] Сравнить вещественные числа без учета порядков fucomp [источник] Сравнить без учета порядков и вытолкнуть из стека FPU fucompp [источник] Сравнить … и вытолкнуть из стека FPU два числа Источник st(i) st(0) <> st(i) не указан st(0) <> st(1) ficom источник Сравнить целые числа ficomp источник Сравнить целые и вытолкнуть из стека FPU. Источник: переменная, содержащая целое число. st(0) <> переменная fcomi приемник, источник (Pentium Pro, Pentium II и выше) Сравнить вещественные числа и установить eflags. fcomip приемник, источник Сравнить, установить eflags и вытолкнуть из стека FPU. Приемник Источник st(0) st(i) st(0) <> st(i) Не изменяют содержимого регистра ax и выполняются быстрее fldz ;st(0) = 0 fcom y ;0 <> y fstsw ax ;ax = sr sahf ;flags = ah je error fldz ;st(0) = 0 fld y;st(0) = y, st(1) = 0 fcomi st(0), st(1);0 <> y je error ftst Проверить, не содержит ли st(0) ноль. Инструкция устанавливает флаги c0, c2 и c3 fld y ;st(0) = y ftst ;y <> 0 fstsw ax ;ax = sr sahf ;flags = ah je error и другие инструкции... § 3.4. Примеры Ввод / вывод Ввод/вывод вещественного числа практически не отличается от ввода/вывода, рассмотренного ранее. double x = 0; char s[] = "%lf", s1[] = "%lf\n"; _asm{ finit ;инициализация сопроцессора ;=====Ввод===== lea eax, x ;поместить адрес переменной x в eax push eax ;поместить eax (адрес x) в сегмент стека, ;автоматически уменьшится указатель сегмента ;стека esp на 4 байта lea eax, s ;поместить адрес строки s в eax push eax ;поместить eax (адрес s) в сегмент стека, ;автоматически уменьшится указатель сегмента ;стека esp еще на 4 байта call scanf_s ;вызвать функцию scanf_s(s,&x) add esp, 8 ;вернуть указатель сегмента стека esp в ;исходное состояние (увеличить на 8) ;=====Вывод=====надо бы push x, но нельзя fld x ;st(0) = x sub esp, 8 ;указатель сегмента стека esp уменьшить на 8 fstp qword ptr [esp] ;st(0) (то есть x) загрузить в сегмент стека ;по адресу, который указан в регистре esp, ;и вытолкнуть lea eax, s1 ;поместить адрес строки s1 в eax push eax ;поместить eax (адрес s1) в сегмент стека, ;автоматически уменьшится указатель сегмента ;стека esp еще на 4 байта call printf ;вызвать функцию printf(s1,x) add esp,12 ;вернуть указатель сегмента стека esp в ;исходное состояние (увеличить на 12) } Вычисление значений функции на заданном отрезке Необходимо вывести на консоль таблицу значений функции на отрезке [-10; 10,4] с шагом 0,5 при значениях параметров a = 0,5; b=0; c=1. Реализацию программы разобьем на несколько этапов. Этап I double a=0.5, b=0, c=1, x1=-10, x2=10.4, t=0.5; double x, y; int key; char m1[]="-----------------------------\n"; char m2[]="| x | y |\n"; char m3[]="-----------------------------\n"; char s0[]="| %11.3lf | %11.3lf |\n"; char s1[]="| %11.3lf | ----------- |\n"; _asm{ ;=== Заголовок таблицы === ... ;=== Таблица значений функции y === ... } Этап II _asm{ ;=== Заголовок таблицы === lea ebx,m1 push ebx call printf add esp,4 lea ebx,m2 push ebx call printf add esp,4 lea ebx,m3 push ebx call printf add esp,4 ;=== Таблица значений функции y === } Этап III ;=== Таблица значений функции y === finit ;инициализация сопроцессора fld x1 ;st(0) = x1 fstp x ;x = st(0) и вытолкнуть (x == x1) ;стек FPU пуст fldz ;st(0) = 0 ;st(0) == 0 begin: fld x2 ;st(0) = x2 ;st(1) == 0 st(0) == x2 fsub x ;st(0) = st(0)-x ;st(1) == 0 st(0) == (x2–x) fcomip st(0),st(1) ;st(0) сравнить с st(1) и вытолкнуть ;st(0) == 0 jb end ;если (x2-x)<0 (выход за правую границу), ;то переход на метку end ;===== Вычисление y(x) ===== . . . ;===== Вывод строки таблицы ===== . . . fld x ;st(0) = x ;st(1) == 0 st(0) == x fadd t ;st(0) = st(0)+t ;st(1) == 0 st(0) == (x+t) fstp x ;x = st(0) и вытолкнуть ;x увеличился на шаг t ;st(0) == 0 jmp begin ;переход на метку begin end: Этап IV ;===== Вычисление y(x) ===== ;если x<0, b!=0, то y=a*x*x+b ;если x>0, b==0, то y=(x-a)/(x-c) ; но если (x-c)==0 – деление на 0 ;иначе y=x/c ; но если c==0 - деление на 0 ;Стратегия: если значение функции в точке x ;определено, то результат помещаем в y ;и key присваиваем 0, иначе key присваиваем 1. ;В стеке FPU st(0) == 0 ;случай x<0, b!=0, y=a*x*x+b fld x ;st(0) = x ;st(1) == 0 st(0) == x fcomip st(0),st(1) ;st(0) сравнить с st(1) и вытолкнуть ;st(0) == 0 jnb l2 ;если x >= 0 (x не меньше 0), ;то переход на метку l2 fld b ;st(0) = b ;st(1) == 0 st(0) == b fcomip st(0),st(1) ;st(0) сравнить с st(1) и вытолкнуть ;st(0) == 0 je l2 ;если b == 0, то переход на метку l2 fld a ;st(0) = a ;st(1) == 0 st(0) == a fmul x ;st(0) = st(0)*x ;st(1) == 0 st(0) == a*x fmul x ;st(0) = st(0)*x ;st(1) == 0 st(0) == a*x*x fadd b ;st(0) = st(0)+b ;st(1) == 0 st(0) == a*x*x+b fstp y ;y = st(0) и вытолкнуть (y == a*x*x+b) ;st(0) == 0 mov key,0 ;key = 0 (значение y определено) jmp l1 ;переход на метку l1 l2: ;случай x>0, b==0, y=(x-a)/(x-c) fld x ;st(0) = x ;st(1) == 0 st(0) == x fcomip st(0),st(1) ;st(0) сравнить с st(1) и вытолкнуть ;st(0) == 0 jbe l3 ;если x <= 0 (x меньше или равно 0), ;то переход на метку l3 fld b ;st(0) = b ;st(1) == 0 st(0) == b fcomip st(0),st(1) ;st(0) сравнить с st(1) и вытолкнуть ;st(0) == 0 jne l3 ;если b != 0 (b не равно 0), ;то переход на метку l3 fld x st(0) = x ;st(1) == 0 st(0) == x fsub c ;st(0) = st(0)-c (st(0) == x-c) fcomip st(0),st(1) ;st(0) сравнить с st(1) и вытолкнуть ;st(0) == 0 je l4 ;если (x-c) == 0, ;то переход на метку l4 fld x ;st(0) = x ;st(1) == 0 st(0) == x fsub a ;st(0) = st(0)-a ;st(1) == 0 st(0) == x-a fld x ;st(0) = x ;st(2) == 0 st(1) == x-a st(0) == x fsub c ;st(0) = st(0)-c ;st(2) == 0 st(1) == x-a st(0) == x-c fdivp st(1),st(0) ;st(1) = st(1)/st(0) и вытолкнуть ;st(1) == 0 st(0) == (x-a)/(x-c) fstp y ;y = st(0) и вытолкнуть (y == (x-a)/(x-c)) ;st(0) == 0 mov key,0 ;key = 0 (значение y определено) jmp l1 ;переход на метку l1 l3: ;случай y=x/c fld c ;st(0) = c ;st(1) == 0 st(0) == c; fcomip st(0),st(1) ;st(0) сравнить с st(1) и вытолкнуть ;st(0) == 0 je l4 ;если c == 0, ;то переход на метку l4 fld x ;st(0) = x ;st(1) == 0 st(0) == x fdiv c st(0) = st(0)/c ;st(1) == 0 st(0) == x/c fstp y ;y = st(0) и вытолкнуть (y == x/c) ;st(0) == 0 mov key,0 ;key = 0 (значение y определено) jmp l1 ;переход на метку l1 l4: ;деление на 0 mov key,1 ;key = 1 (значение y не определено) l1: Этап V ;===== Вывод строки таблицы ===== ;Напомним, что если значение функции в точке x ;определено, то результат лежит в y и key == 0, ;иначе key == 1. В стеке FPU st(0) == 0 cmp key,0 ;сравнить key c 0 je l5 ;если равны, переход на метку l5 ;~~~случай, когда y(x) не определен (key == 1)~~~ sub esp,8 ;указатель сегмента стека esp уменьшить на 8 fld x ;st(0) = x st(1) == 0 st(0) == x fstp qword ptr [esp] ;st(0) (то есть x) загрузить в сегмент стека ;в соответствии с указателем сегмента стека esp ;и вытолкнуть st(0) == 0 lea eax,s1 ;поместить адрес строки s1 в eax push eax ;поместить eax (адрес s1) в сегмент стека, ;автоматически уменьшится указатель сегмента ;стека esp еще на 4 байта call printf ;вызвать функцию printf(s1,x) add esp,12 ;вернуть указатель сегмента стека esp в ;исходное состояние (увеличить на 12) jmp l6 ;переход на метку l6 l5: ;~~~случай, когда y(x) определен (key == 0)~~~ sub esp,8 ;указатель сегмента стека esp уменьшить на 8 fld y ;st(0) = y st(1) == 0 st(0) == y fstp qword ptr [esp] ;st(0) (то есть y) загрузить в сегмент стека ;в соответствии с указателем сегмента стека esp ;и вытолкнуть st(0) == 0 sub esp,8 ;указатель сегмента стека esp уменьшить на 8 fld x ;st(0) = x st(1) == 0 st(0) == x fstp qword ptr [esp] ;st(0) (то есть x) загрузили в сегмент стека ;в соответствии с указателем сегмента стека esp ;и вытолкнуть st(0) == 0 lea eax,s0 ;поместить адрес строки s0 в eax push eax ;поместить eax (адрес s0) в сегмент стека, ;автоматически уменьшится указатель сегмента ;стека esp еще на 4 байта call printf ;вызвать функцию printf(s0,x,y) add esp,20 ;вернуть указатель сегмента стека esp в ;исходное состояние (увеличть на 20) l6:
«Вычисления с плавающей точкой» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Решение задач от ИИ за 2 минуты
Решить задачу
Найди решение своей задачи среди 1 000 000 ответов
Найти
Найди решение своей задачи среди 1 000 000 ответов
Крупнейшая русскоязычная библиотека студенческих решенных задач

Тебе могут подойти лекции

Смотреть все 588 лекций
Все самое важное и интересное в Telegram

Все сервисы Справочника в твоем телефоне! Просто напиши Боту, что ты ищешь и он быстро найдет нужную статью, лекцию или пособие для тебя!

Перейти в Telegram Bot