Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пояснительная записка2.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
338 Кб
Скачать
☆

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

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