- •Введение
- •1 Постановка и формулировка задачи
- •1.2 Формулирование требований к представлению исходных данных и выходных результатов.
- •2 Проектирование
- •3 Кодирование
- •3.1 Уточнение структуры входных и выходных данных и определение ассемблерного формата их представления
- •4 Отладка и тестирование
- •5 Список используемой литературы
- •Приложение а
- •Приложение б
- •2. Функциональное назначение
- •3. Описание логической структуры
- •4. Вызов и загрузка
- •5. Входные и выходные данные
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
