Сделай Сам Свою Работу на 5

ПОСТАНОВКА И ФОРМУЛИРОВКА ЗАДАЧИ





ВВЕДЕНИЕ

 

Данная курсовая работа состоит в создании законченного программного про­дукта, выполняющего вычисление заданного количества значений функции вида y = f(x), в определён­ном интервале значений X. Количество значений (число интервалов разбиения) вводится пользователем с клавиатуры при поступлении соответствующего запроса. Максимальное число интервалов – 100. Программно проверяются введенные значение на соответствие тому или иному интервалу. Функция является разрывной и состоит из трёх частей, определённых на интервалах заданной величины. После вычисления значения Y заносятся в оперативную память последовательно, для каждого значения выделяется по 4 байта. Поиск нужного значения осуществляется путём задания величины смещения от начала таблицы (массива данных). Этот способ обеспечивает существенную экономию оперативной памяти (почти в два раза), так как не требует хранения соответствующих значений Х. После этого пользователю предлагается ввести зна­чение X в определённом диапазоне значений. Далее, путём интерполирования, опи­раясь на заполненную структуру данных, производиться вычисление значения функ­ции для введённого значения X. Результат вычисления выводиться на экран.



Программа написана на языке Assembler с использованием функций математи­ческого сопроцессора.

При разработке программы использовались следующие программные продукты:

1) Файловый и архивный менеджер FAR для написания кода программы.

2) Пакет Turbo Assembler 5.0 для трансляции и компоновки программы.

3) Microsoft Word, используемый для написания исходного кода программы.

 

 

 

ПОСТАНОВКА И ФОРМУЛИРОВКА ЗАДАЧИ

 

1.1 Задание на разработку программного продукта

Программа, которую необходимо разработать в процессе выполнения курсовой работы должна по полученной формульной зависимости вида сформировать программный продукт, который бы выполнял следующие функции:

В данной курсовой работе необходимо по полученной формульной зависимости вида сформировать программный продукт, который бы выполнял следующие функции:

– Запрашивал у пользователя количество участков разбиения интервала n;



- запрашивал у пользователя начальное значение и шаг изменения этого параметра ;

- производила вычисление значений функции для всех значений аргумента от = 15,9 до = 263

Первый интервал (x0 £ x£ x0+0.2l) y(x)=хsin(x)

Второй интервал (x0+0.2l< x£ x0+0.6l) y(x)=sin х2

Третий интервал (x0+0.6l< x£ xn) y(x)=х3

где l = xn - x0 –длина общего интервала;

- занесение пар значений х, у в структуру хранения данных;

- вывести на экран приглашения для ввода значения параметра х с указанием пределов варьирования;

- по введенному значению х вычислить функцию , опираясь на данные структуры путем интерполяции;

- вывести результат на экран в требуемом формате;

- запрос на повторение действий в формате «Y/N».

Программа должна быть оформлена с использованием процедур.

 

 

1.2 Формулирование требований к представлению исходных данных и выходных результатов.

 

Исходные данные и выходные результаты должны быть представлены в формате вещественных чисел с плавающей точкой. Для изображения чисел c плавающей точкой в сопроцессоре существует три формата данных. Короткий формат имеет 32 бита, а длинный 64 бита. Третий формат определяет 80-битовые числа. Сопроцессор использует такой формат "промежуточного дейст­вительного числа", чтобы обеспечить очень высокую точность для промежу­точных результатов вычислений.

Целые числа — лучший способ представления многих величин. Целые числа просто понимать и использовать, а также легко преобразовывать в двоичное представление. Однако c целыми числами плохо работать в случае очень боль­ших значений. Очень большое целое число обычно оканчивается длинной строкой нулей. Целые числа, кроме того, не способны представить значение, содержащее дробную часть, т. e. ЭВМ не может запомнить число 1/2 в целом представлении. Любые другие дроби, меньше 1, также невозможно предста­вить, используя целые числа.



Ученые и математики давным-давно разработали способ представления этих чисел в достаточно удобном виде. На первом этапе вводится десятичная точка (.), которая будет показывать границу между целой и дробной частями числа. В случае целого числа позиция, представляющая единицы, всегда находится на правом краю числа; в случае, когда используется десятичная точка, цифры справа от нее представляют значения, меньше 1.

У целых чисел каждая позиция числа соответствует степени числа 10.

Десятичная точка показывает границу между позицией, соответствующей 100, и дробной частью. В дробной части позиции снова являются степенями числа 10, но теперь эти степени - отрицательные.

Поскольку каждая позиция десятичного числа отличается от соседней на степень числа 10, умножение числа на 10 эквивалентно сдвигу десятичной точки на одну позицию вправо. Аналогично деление на 10 сдвигает десятичную точку на позицию влево. Это свойство можно использовать для сдвига десятичной точки на соответствующее место: мы сдвигаем десятичную точку и одновременно корректируем число на ту же степень числа 10. Такое представление чисел называется представлением c плавающей точкой, поскольку десятичная точка "плавает" в числе; она больше не помечает абсолютное место между целой и дробной частями. Положение десятичной точки можно выбрать из соображений удобства, а затем умножить число на нужную сте­пень числа 10, чтобы получить правильное значение.

Десятичное число c плавающей точкой состоит из двух частей. Значащая часть числа называется мантиссой. На практике мантисса обычно находится в пределах 1 < мантисса < 10. Другая часть числа c плавающей точкой - это порядок, степень, в которую нужно возвести число 10 перед умножением его на мантиссу, т. e. 9.3 х 107 имеет мантиссу 9.3 и порядок 7. Если основание системы счисления определено раз и навсегда, в нашем слу­чае это 10, то для восстановления первоначального числа должны быть заданы только два числа — мантисса и порядок.

Двоичные числа c плавающей точкой изображаются аналогично десятичным; отличие заключается в том, что основание системы счисления здесь 2, а не 10. Мантисса имеет значения 1 < мантисса < 2, а порядок показывает степень числа 2

Для того чтобы сохранить максимальную точность, вычислительные маши­ны почти всегда хранят мантиссу в нормализованном виде. Это означает, что мантисса есть число, лежащее между 1 и 2 (1 < мантисса < 2). Два соображе­ния говорят в пользу нормализации. Во-первых, ни один незначащий 0 не дает никакого вклада в точность числа. (Это несправедливо для нулей, лежа­щих в конце числа; мы считаем, что число 1.000 более точно, чем число 1.0.) Если в мантиссе c плавающей точкой появились незначащие нули, точность числа падает. Во-вторых, способ хранения мантиссы числа c плавающей точ­кой подразумевает, что двоичная точка находится на фиксированном месте. Фактически подразумевается, что двоичная точка следует после первой дво­ичной цифры, т. e. нормализация мантиссы делает единичным первый бит, помещая тем самым значение мантиссы между 1 и 2. Для выполнения норма­лизации ЭВМ корректирует порядок числа на соответствующее значение.

Точно так же, как длина мантиссы числа определяет его точность, длина поля порядка определяет диапазон числа. Поле порядка содержит степень числа 2, и чем больше бит в этом поле, тем большее число может быть пред­ставлено.

Важно отметить, что, хотя диапазон и расширяется c увеличением числа бит порядка, точность не увеличивается. Значение порядка хранится не как значение число, представленное в дополнительном коде. Для упрощения вычислений значение порядка в ЭВМ хранится в виде смещенного числа. Это означает, что к действительному значению порядка прибавляется смещение перед записью его в память. Значение смещения выбрано так, чтобы допустить сравнение порядков. В частности, это полезно при сравнении двух чисел c плавающей точкой. Значения порядка и мантиссы записываются в одном элементе данных, причем порядок записы­вается перед мантиссой. В случае смещенного значения порядка программа может сравнивать числа побитно, начиная со старших позиций. Первое же не­равенство показывает соотношение чисел, и больше не нужно учитывать ни­какие части чисел. Значение смещения определяется размером поля порядка.

 

1.3 Запись основных формул в формате ПОЛИЗ

 

Для того, чтобы написать программу для вычисления некоторого выражения, его необходимо предварительно преобразовать в удобный для программирования сопроцессора вид. Процесс преобразования напоминает подготовку выражения для метода трансляции, основанного на использовании обратной польской записи (ПОЛИЗ). Запись формул в формате ПОЛИЗ приведена в таблице 1.3.1.

 

Таблица 1.1.- Запись формул в формате ПОЛИЗ

Обычная формула Формат ПОЛИЗ
xsinx XSINX **
Sin(x^2) X ХSIN *
Х3 X Х X **

 

Использование польской записи в данном проекте обусловлено особенностью организации сопроцессора – хранением его операндов в стеке.

ПРОЕКТИРОВАНИЕ

 

 

Данный программный продукт написан на языке Turbo Assembler 5.0 с исполь­зованием команд математического сопроцессора. Математический сопроцессор представляет собой устройство, совмещённое в одном корпусе с основным процес­сором и предназначенное для выполнения операций над числами с плавающей точ­кой.

Программа написана в соответствии с принципами структурированного про­граммирования. Это означает, что код программы состоит из нескольких модулей, выполняющих определённые действия, которые в свою очередь состоят из проце­дур, выполняющих определённые действия на уровне модуля.

 

2.1 Разработка алгоритма реализации задачи

Для расчета интерполяции необходимо ввести число N, необходимое для определения величины каждого интервала разбиения (dx).

Для всех N+1 точек расстояния необходимо провести вычисления значений функции. При этом необходимо проверять, какому из 3-х интервалов заданного диапазона принадлежит текущая точка Хi.

Значения Хi и соответствующие им значения функции Yi образуют таблицу значений функции. Сформированная таблица позволяет осуществлять вычисления аппроксимированных значений функции во всем интервале ее изменения от Х0 до Хn. При этом для введенного пользователем значения Х аппроксимация значения вычисляется по формуле .

1) Началом программы является метка Start модуля main

2) Инициализация сегмента данных и сопроцессора.

3) Сообщение с просьбой ввода чисел и с помощью процедуры ввода вещественного числа ввести количество интервалов и X.

4) Вычисление значений функций в соответствии с шагом dx ( количество значений – не больше 100)

5) Каждая итерация сопровождается вводом вещественного числа в массив.

6) Затем выполняется вывод результата в соответствии с вводимым

числом по формуле:

 

Данный программный продукт состоит из 3 – х программных кодов модулей, а именно:

1) main.asm

2) input.asm

3) out.asm

 

Рассмотрим каждый из модулей

1) В этом модуле находятся все необходимые процедуры, используемые для вычисления функций представленных в задании курсового проекта в соответствии с вариантом. Рассмотрим подробнее каждую из процедур:

Ssearch_Y proc– данная процедура определяет интервал попадания значения Х и вычисляет значения Y по одной из формул: xsin(x) - на первом участке диапазона значений х; sin(x^2) на втором участке диапазона; х3 – на третьем участке диапазона.

Search_l proc– данная процедура вычисляет значение длины интервала L =Хn - X0.

Search_vdX proc –процедура приращения значения аргумента dX=L/n.

Next_X proc-вычисляет следующее значение Х, т. е. Х=Х+dX.

2) Что касается этого файла, то здесь находятся программа вывода вещественного числа короткого формата (32 бита). Вход: выводимое значение - в поле float32. Выход: вывод вещественного числа короткого формата на экран.

3) В этом модуле находится функция Input_Float для преобразования введённых символов в вещественное число. Ввод с клавиатуры вещественного числа, максимальное число состоит из 20 цифр (22 - с учетом 0d0ah).Выход: вещественное число в вершине стека сопроцессора - эквивалент своего исходного символьного представления.

2.2 Разработка структуры программы в соответствии с выбранной моделью

Итак, из всего выше сказанного можно сделать вывод, что данный программный продукт можно разбить на 3 модуля, каждый из которых выполняет свои функции и процедуры, а именно:

main.asm содержит все необходимые процедуры, используемые для вычисления функций представленных в задании курсового проекта;

v_simvol.asm содержит программу вывода вещественного числа короткого формата (32 бита);

v_Vesh.asm содержит ввод с клавиатуры вещественного числа.

КОДИРОВАНИЕ

3.1 Уточнение структуры входных и выходных данных и определение ассемблерного формата их представления

 

Представим структуры входных и выходных данных в виде таблицы

Таблица входных и выходных данных приведена в приложении Б.

 

Таблица 3. 1. – Структуры входных и выходных данных

Модуль Имя переменной Значение Формат
Main x0 6.0 dd
I1 24.6 dd
I2 80.4 dd
L 93.0 dd
Xn 99.0 dd
X 0.0 dd
Y 0.0 dd
n 150.0 dd
vdX 0.0 dd
Arrey 151 dup AR
v_simvol a1 dq
pow_dec dw
i_save dd
f_save 0.0 dq
c_05 0.5 dd
c_10 10.0 dd
i_tol dw
i_part dw
f_part dt
flag db
m_sign db
p_sign db
string 20 dup<“ ”> db
in_float NumTmp dw
cn10 dd
cn48 dd

 

3.2 Программирование задачи

 

Программная реализация данной задачи содержится в приложении А данного курсового проекта, где представлены листинги с соответствующими комментариями.

 

ОТЛАДКА И ТЕСТИРОВАНИЕ

4.1 Обнаружение, локализация и устранение ошибок в программе, выявленных в текстах

 

Отладка и тестирование производятся в отладчике, где при возникновении ошибки пользователь может отследить ее устранить в соответствии с установленными правилами синтаксиса языка Assembler.

 

 

Таблица 4.1. – Ошибки

Ошибка Вид ошибки Устранение
Need expression FLD Arrey[si] Синтаксическая ошибка Не указано поле FLD Arrey[si].vX
Illegal indexing mode mov eax,Arrey[si*8].vX Ошибка адресации. mov eax,Arrey[si].vX

 

В программе возникали также незначительные синтаксические ошибки, которые не стоят внимательного рассмотрения.

Полученный программный продукт полностью соответствует поставленной за­даче, хотя и не является идеальным, так как он не лишён многих недостатков. Вот некоторые из них:

1) Одним из недостатков данного программного продукта является необхо­димость явного указания того, что вводимое число является веществен­ным. Например, для ввода числа «2» необходимо ввести «2.0». Решени­ем данной проблемы может быть изменение алгоритма преобразования числа, вводимого с клавиатуры, в его двоичный эквивалент.

2) Следующим недостатком является невысокая точность вычислений. Это связано с тем, что все вещественные числа в программе представлены в коротком (32 бита) формате. Для повышения точности вычисления необ­ходимо использовать расширенный формат представления веществен­ных чисел (64 бита).

 

При тестировании определяли точность работы нашей программы и проводили с учётом зависимости погрешности значений от количества разбиений интервала.

Тестирование проводили путём изменения количества разбиений интервала и проверки полученного значения Y с помощью программы MathCAD.

По полученным данным (табл.4.1.2.-4.1.4.) построили графики зависимости погрешности значений от количества разбиений интервала (рис. 4.1.1.-4.1.3.). На графиках видно, что при увеличении количества разбиений интервала, погрешность уменьшается, значит программа работает верно.

Таблица 4.2.

1-й интервал    
Кол-во интервалов Полученное значение Введенное число Истинное значение Погрешность
0,35695029     42,780116
0,307754446     23,10177852
0,280413658 0,25 12,16546328
0,2633504037     5,34016148
0,2517427139     0,69708556
0,2514255034     0,570201356

 

 

Рис. 4.1. – График зависимости погрешностей на 1-ом интервале.

 

Таблица 4.3.

2-й интервал    
Кол-во интервалов Полученное значение Введенное число Истинное значение Погрешность
0,03780605     61,89780261
0,092     7,279333333
0,099283057 0,099222755 -0,06077428
0,099312708     -0,090657988
0,09924271     -0,020111188
0,099313634     -0,091590332

 

Рис. 4.2. – График зависимости погрешностей на 2-ом интервале.

 

 

Таблица 4.4.

3-й интервал        
Кол-во интервалов Полученное значение Введенное число Истинное значение Погрешность
0,159999642     0,00022375
0,159999642     0,00022375
0,159999642 0,16 0,00022375
0,159999642     0,00022375
0,159999642     0,00022375
0,159999642     0,00022375

 

 

Рис. 4.3. – График зависимости погрешностей на 3-ем интервале.

 

 

Список используемой литературы

 

1) В.И.Юров «Assembler». Учебник для вузов.2-е издание – СПб.:Питер,2004. – 637 с.: ил.

2) В.И.Юров «Практикум» - СПб.:Питер,2003. – 400 с.: ил

 

ПРИЛОЖЕНИЕ А

 

Программный код

 

Программный код модуля Main.asm

 

_windowout macro _str,_count ; макрос установки параметров экрана и вывода ;строки

xor ax,ax ;очищаем регистр для работы

mov ah,03h ;получить позицию курсора

mov bh,0 ;номер видеостраницы

int 10h ;вызов BIOS

 

mov ah,13h ;команда вывода строки

mov al,00000001b ; после вывода ? курсор в конец строки

xor bh,bh ;номер видеостраницы

mov cx,_count ;длина выводимой строки

mov bl,00001001b ;атрибут

push ds

pop es

mov bp,offset _str ; в базовую точку стека положить строку

int 10h

endm ; конец макроса

 

_massiv macro ;макрос добавления X,Y в массив.

xor ax,ax ;очистка ах

mov al,index ;в al index

mov dl,8 ;в dl 8

mul dl ;умножаем al(index) на 8, результат - в ах

mov si,ax ;в si index*8

mov eax,X ; помещаем текущее значение Х

mov A[si].vX,eax

mov eax,Y ; помещаем текущее значение У

mov A[si].vY,eax

inc index ; увеличиваем счетчик массива

endm

 

;-------------------------------------------------------------------------------

 

EXTRN Input_Float:FAR ;подключение внешних процедур

EXTRN Out_Float:FAR

 

include macro.inc ; подключение макроса для вывода строки

 

AR struc ;структура для хранения данных(X,Y)

vX dd 0

vY dd 0

AR ends

 

model SMALL

.586

stack 256

.data

mes_intro db 13,10,'Курсовая работа по СП. Выполнил ст. гр. СКС-08- ',13,10

len_i =$-mes_intro

mes1 db 13,10,'Введите число участков (5-100): N = $'

mes2 db 13,10,'Повторить? ... y/n $'

mes3 db 13,10,'Введите X от 15.9 до 400 : X = $'

mesY db 13,10,'Y = $'

mes_er db 13,10,'Ошибка ввода! Приложение будет завершено. OK $'

 

index db 0 ;текущий индекс в массиве

X0 dd 15.9 ;начальное значение X

i1 dd 92.72 ; граница первого интервала

i2 dd 246.36 ;граница второго интервала

Xn dd 400.0 ;конечное хначение Х

 

L dd 384.1 ;длинна всего интервала

X dd ? ;текущее значение X

Y dd ? ;текущее значение Y

n dd ? ;количество участков

vdX dd ? ;dX, размер участка

A AR 101 dup (<>) ;массив для хранения Х и У

s db 0

const_1 dd 100.0

const_6 dd 6.0

const_12 dd 1200.0

const_16 dd 0.16

 

 

.code

 

mov ah,s

mov ah,1

mov s,ah

 

Calc_1 proc ;процедура расчёта Y на 1-ом участке У = 100/X^2

finit ;инициализацизировать сопроцессор

fld const_1

fld X ;загрузить X в вершину стека

fmul x

fdiv

fstp Y ;получаем Y

ret

Calc_1 endp

 

Calc_2 proc ;процедура расчёта Y на 2-ом участке Y=1200/(X^2-6)

finit ;инициализация FPU

fld const_12 ;загрузить X в вершину стека

fld x

fmul x

fsub const_6

fdiv

fstp Y ;снять значение из стека, получить Y

ret ; возврат из процедуры

Calc_2 endp

 

Calc_3 proc ;процедура расчёта Y на 3-ом участке 0.16

finit ;инициализация сопроцессора

fld const_16

fstp Y ;получаем Y

ret

Calc_3 endp

 

next_X proc ; обработка значения

finit

fld X

fadd vdX ; добавить в массив

fstp X

ret

next_X endp

 

start:

mov ax,@data

mov ds,ax

_windowout mes_intro,len_i

 

;------------------------- начало основной программы ------------------------------

 

Out_Str mes1 ;вывод прилашения на ввод

call Input_Float ;ввод преобразованного n

FISTP n ;сохраняем n как целое

cmp n,5 ;проверка введённого числа

jl er ;окончание программы если n < 5

cmp n,100 ;проверка введённого числа

jg er ;окончание программы если n > 100

mov index,0 ;index=0

FINIT ;иниц. сопроцессора

FILD n ;ST(0) = n

FLD L ;ST(0) = L; ST(1) = n

FDIV ST(0),ST(1) ;ST(0) = L/n (dX)

FSTP vdX ;получаем dX

mov edx,X0 ;установка нач. зн X

mov X,edx ;

 

interval_1:

call Calc_1 ;вычисляем Y на 1-вом участке

mov eax,X

cmp eax,i1 ; проверяем на принадлежность интервалу

jg interval_2 ;если Х больше границы 1-го интервала переходим

;на interval_2

_massiv ;заносим данные в массив

call next_X ;вычисляем следующие знач. X

jmp interval_1 ;выч. следующее значение Y в этом интервале

 

interval_2:

call Calc_2 ;вычисляем Y на 2-ом участке

mov eax,X ;

cmp eax,i2 ;проверяем на принадлеж. интервалу

jg interval_3 ;если Х больше границы 2-го интервала переход

;на interval_3

_massiv ;заносим данные в массив

call next_X ;вычисляем следующие знач. X

jmp interval_2 ; выч. следующее значение Y в этом интервале

 

interval_3:

call Calc_3 ;вычисляем Y на 3-вом участке

mov eax,X ;

cmp eax,Xn ;сравнение

jg iter ;если Х больше границы 3-го интервала переход

;на end_calc

_massiv ;заносим данные в массив

call next_X ;вычисляем следующие знач. X

jmp interval_3 ; выч. следующее значение Y в этом интервале

iter:

Out_Str mes3

call input_float ; ввод преобразованного n

fstp X

mov eax,X ;проверка введённого X

cmp eax,X0

jl er ; если меньше ,то перейти на метку ?ошибка?

cmp eax,Xn

jg er ; если больше, то переход на метку

 

mov index,0

 

m_loop1: ;поиск в массиве второй точки для интерполяции

xor ax,ax ;очистка ах

mov al,index ;в al текщий индекс в массиве

mov dl,8 ;в dl 8

mul dl ;умножаем al на 8, результат в ах

mov si,ax ;в si index*8

inc index

mov eax,A[si].vX ;в eax значение X2

cmp eax,X

jng m_loop1 ; если не больше, то возобновить поиск второй точки для ;интерполяции

 

;A[si-8].vX - первая точка интерполяции(X1)

;A[si].vX - вторая точка интерполяции(X2)

 

FINIT ;интерполяция y(x)~=Y1+((Y2-Y1)/(X2-X1))*(X-X1)

FLD A[si].vX

FSUB A[si-8].vX ;ST(0)=X2-X1

FLD A[si].vY

FSUB A[si-8].vY ;ST(0)=Y2-Y1,ST(1)=X2-X1

FDIV ST(0),ST(1) ;ST(0)=(Y2-Y1)/(X2-X1)

FLD X ; ST(0)=х , ST(1)=(Y2-Y1)/(X2-X1)

FSUB A[si-8].vX ;ST(0)=(X-X1), ST(1)=(Y2-Y1)/(X2-X1)

FMUL ; перемножить

FADD A[si-8].vY ;в ST(0) результат

 

 

Out_Str mesY ; вывести сообщение

call Out_Float ; вызвать внешнюю процедуру преобразования результата

 

ENDPROG:;------------------ окончание -----------------------------------------

 

Out_Str mes2 ; вывести запрос на повторение операции

Get_Char ; получить введенный символ

cmp al,'y' ; сравнить с у

je iter ; если ? да, перейти на повторении операции

cmp al,'Y'

je iter

cmp al,'N'

je exit

cmp al,'n'

jne ENDPROG ; если - нет, перейти на окончание программы

exit: ; стандартный выход

mov ax,4c00h

int 21h

er:

Out_Str mes_er ; вывод сообщ об ошибке

Get_Char

mov ax,4c01h

int 21h

end start
Программный код модуля OUT.asm

 

===Перевод вещественного числа в символьное представление===

 

;на входе – полученное в ходе выполнения расчетов вещественное число

;на выходе – переведенное в символьный формат число

 

;Перевод вещественного числа в символьное представление

masm

model use16 small

.586p

.stack 256h

PUBLIC Out_Float

.data

a1 dq 0

pow_dec dw 0

i_save dd 0

f_save dq 0.0

c_05 dd 0.5

c_10 dd 10.0

i_tol dw 10 ;точность представления дробной части

i_part dw 0

f_part dt 0

flag db 0

m_sign db 0 ;знак мантиссы

p_sign db 0 ;знак порядка

string db 20 dup(" ")

 

.code

Out_Float proc FAR

mov ax,@data

mov ds,ax

fstp a1

 

 

finit

fld a1 ;загрузка числа в st(0)

;-------проверка знака числа

ftst ;сравнение st(0) с нулем

fstsw ax ;сохранение слова состояния сопроцессора в ax

sahf ;отображение ah на регистр флагов

jnc posit_m ;если >= 0, то ничего не делать

fchs ;если меньше 0 - изменить знак

mov m_sign,1 ;установить флаг знака мантиссы

posit_m:

fxtract ;выделение мантиссы и порядка числа

;порядок в st(0), мантиссу в st(1)

fxch st(1) ;меняем знак мантиссы

 

;-------проверка знака порядка

ftst ;сравнение st(0) с нулем

fstsw ax ;сохранение слова состояния сопроцессора в ax

sahf ;отображение ah на регистр флагов

jnc posit_p ;если >= 0, не устанавливать флаг знака

mov p_sign,1 ;установить флаг знака порядка

posit_p:

fldlg2 ;загрузка в st(0) log10(2)

fmul ;переход от двоичного порядка к десятичному

fst f_save ;сохранение вещественного десятичного порядка

fsub c_05

fistp pow_dec ;сохранение целой части

;десятичного порядка

fld f_save ;восстанавливаем мантиссу в st(0)

fisub i_save

 

f2xm1 ;вычисление 2х-1

fld1 ;загрузить 1

fadd ;сложить

fild i_save ;результат загрузить в цел. Часть ч

fld1 ;загрузить 1

fscale ;выполнить масштабирование степени 2

fxch st(1)

fistp i_save

fmul

fmul

 

fcom c_10 ;сравнить мантиссу с 10

fstsw ax ;записать слово состояния сопроцессора в ах

sahf ;поместить в ah значение регистра флагов

jc m1 ;если десятичная мантисса меньше 10

;то не корректируем ее.

;------корректировка десятичной мантиссы

fidiv c_10

cmp p_sign,0 ;если порядок положительный

jz inc_pow ;то увеличиваем его на единицу

dec pow_dec ;в противном случае уменьшаем

jmp m1

inc_pow:

inc pow_dec

m1:

;------выделение целой части мантиссы

fst f_save ;пересылаем данные из st(0) в f_save

fsub c_05 ;округляем мантиссу до меньшего

;целого числа

fistp i_part ;и сохраняем

;------выделение дробной части мантиссы

fld f_save ;восстанавливаем мантиссу в st(0)

fisub i_part ;вычитаем целую часть

;------умножение дробной части на 10^i_tol

fldl2t ;в st(0) logе(10)

fimul i_tol

fst f_save ;промежуточно сохранение показателя степени

fsub c_05 ;округление до меньшего целого

fistp i_save ;и промежуточное сохранение

fld f_save ;сохраненное число в st(0)

fisub i_save ;определение дробной части показателя

f2xm1 ;возведение числа 2 в дробную часть степени

fld1 ;загрузка в st(0) числа 1

fadd ;корректировка результата на 1

fild i_save ;загрузка в st(0) целой части показателя ст.

fld1 ;в st(0) число 1

fscale ;возведени 2 в целую часть степени

fxch st(1) ;результат в st(1)

fistp i_save ;освобождение st(0)

fmul ;перемножение двух промежуточных результатов

 

fmul ;масштабирование дробной части мантиссы

;-------сохранение дробной части в BCD формате

fbstp f_part

 

mov di,0

;-------запись знака (в случае отрицательного числа)

cmp m_sign,0

jz setm ;если флаг знака =0, то обойти запись знака

mov string[di],"-"

inc di

 

;-------перевод мантиссы в символьную форму

setm:

mov al,byte ptr i_part

add al,30h

mov string[di],al

inc di

;-------добавление десятичной точки

mov string[di],"."

inc di

;-------перевод дробной части в символьную форму

mov si,9 ;указатель позиции на конец области памяти

mov cx,10 ;в счетчик цикла размер числового поля

 

cycl:

xor ax,ax ;очистка ax

mov al,byte ptr f_part[si] ;очередные две цифры числа в al

cmp al,0

jz m2

jmp m3

m2:

cmp flag,0

jz m4

m3:

ror ax,4

mov bl,al

add bl,30h

mov string[di],bl

inc di

shr ah,4

add ah,30h

mov string[di],ah

inc di

mov flag,1

m4:

dec si

loop cycl

;-------запись символа "Е"

mov string[di],"E"

inc di

;-------запись знака порядка(в случае отрицательного числа)

cmp p_sign,0

jz m5 ;если флаг знака =0, то порядок положителен

mov string[di],"-" ;записать в строку отрицательный знак порядка

mov ax,pow_dec ;и изменить знак порядка

not ax ;на положительный

add ax,1 ;для работоспособности

mov pow_dec,ax ;дальнейшего кода

jmp setpow

m5:

mov string[di],"+" ;записать в строку положительный знак порядка

 

;-------перевод порядка в символьную форму

setpow:

inc di ;продвинуть позицию в строке для записи

mov ax,word ptr pow_dec ;загрузить порядок в ax

mov bl,100

div bl ;выделение числа сотен в al

add al,30h ;перевод в ASCII код цифры

mov string[di],al ;запись символа в строку с результатом

inc di ;переход к следующему байту

 

mov pow_dec,ax ;дальнейшего кода

jmp setpow

 

m5:

mov string[di],"+" ;записать в строку положительный знак порядка

 

;-------перевод порядка в символьную форму

setpow:

inc di ;продвинуть позицию в строке для записи

mov ax,word ptr pow_dec ;загрузить порядок в ax

mov bl,100

div bl ;выделение числа сотен в al

add al,30h ;перевод в ASCII код цифры

mov string[di],al ;запись символа в строку с результатом

inc di ;переход к следующему байту

 

 

shr ax,8 ;остаток от деления в al

add al,30h ;перевод в ASCII код цифры

mov string[di],al ;запись символа в строку с результатом

inc di ;переход к следующему байту

mov string[di],"$" ;запись признака конца строки

 

mov ah,09h ;в al номер функции DOS вывода строки

mov dx,offset string ;запись признака конца строки

int 21h ;вывод строки на экран

ret

Out_Float endp

END


Программный код модуля INPUT.asm

 

 

;======= МОДУЛЬ ПРЕОБРАЗОВАНИЯ ВВЕДЁННЫХ СИМВОЛОВ В ВЕЩЕСТВЕННОЕ ЧИСЛО========

 

; на входе – введенные пользователем с клавиатуры символы, хранящиеся в буфере

; на выходе – преобразованные в двоичный посредством комплекса команд числа

 

include macro.inc

 

model SMALL

 

.586 ; 586 проц

stack 256 ; стек

 

PUBLIC Input_Float

 

inp_buf struc ; описание структуры буфера

len_buf db 22 ; длина буфера

len_in db 0 ; действительная длина введенной строки (без 0dh)

buf_in db 23 dup (20h) ; буфер для ввода (с учетом 0dh)

buf_end db 13,10,'$'

inp_buf ends

 

.data

inp_str inp_buf<>

NumTmp dw 0

cn10 dd 10.0

cn48 dd 48.0

 

.code

Input_Float PROC FAR

mov ax,@data

mov ds,ax

 

xor al,al

mov ah,0Ah

mov dx,offset inp_str

int 21h

 

cmp inp_str.len_in,0 ;проверка длинны строки на 0

je ER

 

xor cx,cx ;очистка сх

xor dx,dx

mov cl,inp_str.len_in ;в cl кoлич. введённых символов

mov si,0

 

FINIT ;инициализация FPU-сопроцессора

FLDZ ;затолкнуть 0 в FPU

m1:

mov dl,inp_str.buf_in[si]

cmp dl,"."

je m2

FMUL cn10 ;st(0) = st(0)*ST(2)

mov NumTmp,dx

FIADD NumTmp ;сложение ST(0),NumTmp

FSUB cn48 ;вычитание ST(0) = ST(0) - 48

inc si

loop m1

cmp cx,0

je Exit_proc

m2:

xor cx,cx

mov cl,inp_str.len_in

mov si,cx

 

FLDZ ;поместить в стек (FPU) 0

m3: ;преобразование дробной части

mov dl,inp_str.buf_in[si-1]

cmp dl,"."

je end_f

mov NumTmp,dx

FIADD NumTmp

FSUB cn48

FDIV cn10

dec si

jmp m3

 

end_f:

FADD ST(0),ST(1) ;сложение дробной и целой частей

;------------------------------ введённое число в ST(0)-------------------------

Exit_proc:

RET

 

ER:

FLDZ

RET

 

Input_Float ENDP

END

 


Программный код модуля macro.inc

;===============================================================

;Макрос настройки DS на сегмент данных.

;===============================================================

Init_DS MACRO

MOV AX,@DATA

MOV DS,AX

XOR AX,AX

ENDM

 

;===============================================================

;Макрос вывода строки на экран. String - выводимая строка.

;===============================================================

Out_Str MACRO String

PUSH AX

MOV AH,09h

MOV DX,OFFSET String

INT 21h

POP AX

ENDM

 

;===============================================================

;Макрос завершения работы программы.

;===============================================================

Exit_Prog MACRO

MOV AX,4C00h

INT 21h

ENDM

 

;===============================================================

;Макрос вывода числа на экран.

;===============================================================

Out_Number MACRO Num

PUSH AX

MOV DX,WORD PTR Num

ADD DX,30h

MOV AH,02h

INT 21h

POP AX

ENDM

 

;===============================================================

;Макрос ввода символа с клавиатуры.

;===============================================================

Get_Char MACRO Char

MOV AH,01h

INT 21h

ENDM

 

;===============================================================

;Макрос определения цвета текста.

;===============================================================

_windowout macro _string,_count

xor ax,ax

mov ah,03h ;в ah заносим номер функции

mov bh,0 ;заносим в bh номер видеостраницы

int 10h ;считать координаты курсора в dh,dl

 

mov ah,13h

mov al,00000001b

mov cx,_count

mov bl,00000010b ;color

push ds

pop es

mov bp,offset _string

int 10h

 

endm

 

;===============================================================

;Макрос добавления Х и У в массив.

;===============================================================

in_massive macro

xor ax,ax ;очистка ах

mov al,indxX ;в al indx

mov dl,8 ;в dl 8

mul dl ;умножаем al на 8, рез, в ах

mov si,ax ;в si indx*8

mov eax,X

mov Arrey[si].vX,eax

mov eax,Y

mov Arrey[si].vY,eax

inc indxX

endm

 


 

ПРИЛОЖЕНИЕ Б

 

 

Содержание

 

1. Общие сведения. 33

2. Функциональное назначение. 34

3. Описание логической структуры. 34

4. Вызов и загрузка программы. 39

5. Входные данные и выходные данные. 39

 

1. Общие сведения

 

 








Не нашли, что искали? Воспользуйтесь поиском по сайту:



©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.