Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RFpro.ru: Ассемблер? Это просто! Учимся программировать


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты по данной тематике

Коцюрбенко Алексей aka Жерар
Статус: Профессор
Рейтинг: 2758
∙ повысить рейтинг »
Boriss
Статус: Академик
Рейтинг: 2622
∙ повысить рейтинг »
Абаянцев Юрий Леонидович aka Ayl
Статус: Профессионал
Рейтинг: 2148
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / Assembler (Ассемблер)

Номер выпуска:1480
Дата выхода:08.10.2011, 22:00
Администратор рассылки:Лысков Игорь Витальевич (Старший модератор)
Подписчиков / экспертов:198 / 61
Вопросов / ответов:2 / 2

Консультация # 184131: Здравствуйте! Прошу помощи в следующем вопросе: Помогите, пожалуйста сопроцессорами. Необходимо написать программу одновременно считающая и рисующая часть графика по формуле. Формула: y=x*tan(x-1)-1 на отрезке a=1.5,b=1.6 Размер переменных : dw; Модуль памяти : tiny ; Использование TASM. ...


Консультация # 184132: Здравствуйте! Прошу помощи в следующем вопросе: Построить график по функции и показать результат. Формула: Использование только Tasm модель памяти tiny размер переменных dw. ...

Консультация # 184131:

Здравствуйте! Прошу помощи в следующем вопросе:
Помогите, пожалуйста сопроцессорами.
Необходимо написать программу одновременно считающая и рисующая часть графика по формуле.
Формула: y=x*tan(x-1)-1 на отрезке a=1.5,b=1.6
Размер переменных : dw; Модуль памяти : tiny ; Использование TASM.

Дата отправки: 03.10.2011, 01:46
Вопрос задал: Кирилл_Evker (Посетитель)
Всего ответов: 1
Страница онлайн-консультации »


Консультирует Лысков Игорь Витальевич (Старший модератор):

Здравствуйте, Кирилл_Evker!
Вот Вам программа:

Код :
;Программа, одновременно считающая и рисующая часть графика по формуле.
;Формула: y=x*tan(x-1)-1 на отрезке a=1.5,b=1.6
;Размер переменных : dw; Модуль памяти : tiny ; Использование TASM.

 .model tiny, C  ; модель памяти и порядок вызова параметров
 .286
 .code   ; сегмент кода
 .startup  ; точка входа

 mov ax, 0013h ; vga 320x200x256
 int 10h

 mov ax, 0a000h
 mov es, ax  ; es - сегмент видео

KOEF  equ 100 ;единица по X или Y соответствует KOEF точкам на экране
Y_OF_AXIS_X equ 100 ;ордината оси абсцисс
X_OF_AXIS_Y equ 0 ;абсцисса оси ординат

main:
 finit   ;проинициируем сопроцессор

;ось ординат (X_OF_AXIS_Y,0)-(X_OF_AXIS_Y,199) цвета 0ch
 call line, X_OF_AXIS_Y, 0, X_OF_AXIS_Y, 199, 0ch

;ось абсцисс (0,Y_OF_AXIS_X)-(319,Y_OF_AXIS_X) цвета 0ch
 call line, 0, Y_OF_AXIS_X, 319, Y_OF_AXIS_X, 0ch
;нарисуем "рисочки" для x = 1, 2, 3
 mov cx, 320/KOEF ;число рисочек
 mov si, X_OF_AXIS_Y+KOEF ;Х рисочки
ris_x_loop:
 call line, si, Y_OF_AXIS_X-1, si, Y_OF_AXIS_X+2, 0ch
 add si, KOEF ;на следующую
 loop ris_x_loop

;вывод графика 1.5<=x<=1.6, y=fun(x) цвета 0bh
 call Graph, offset a, offset b, offset fun, 0bh

 mov ah, 0  ;ждемнажатие на любую клавишу
 int 16h

;выход в DOS
Exit:
 mov ax, 0003h ; назад в текстовый режим
 int 10h

 mov ax, 4c00h ; bye-bye
 int 21h

;подпрограммы

;Функция вычисления y по x, x = ST, т.е. в стеке сопроцессора
;возвращает экранную координату по оси Y
;Х остается в стеке сопроцессора для последующего вычисления
fun proc
local y:word   ;переменная для получения значения из сопроцессора
 fld st  ;сохраним Х для последующих вычислений
 fld st  ;сохраним Х для умножения X*tg(x-1)
 fld1   ;st=1,st(1)=x,st(2)=x,st(3)=x
 fsubp st(1), st ;st=x-1,st(1)=x,st(2)=x
 fptan   ;st=1,st(1)=tg(x-1),st(2)=x,st(3)=x
 fxch st(1)  ;st=tg(x-1),st(1)=1,st(2)=x,st(3)=x
 fmulp st(2)  ;st=1,st(1)=x*tg(x-1),st(2)=x
 fsubp st(1)  ;st=x*tg(x-1)-1,st(1)=x
 fimul coef  ;масштабирование, st=coef*x*tg(x-1)-1,st(1)=x
 fistp y  ;сохраним в y, y=int(coef*x*tg(x-1)-1),st=x 
 mov ax, Y_OF_AXIS_X ;ордината оси абсцисс
 sub ax, y  ;ax = 100 - y
 ret
fun endp

;рисует график, последовательно соединяя точки отрезками
;параметры:
;xmin - адрес вещественной переменной левого значения интервала
;xmax - адрес вещественной переменной правого значения интервала
;pFun - адрес функции, вычисляющей экранную координату по вертикали
;col  - цвет линий
Graph proc xmin:word, xmax:word, pFun:word, col:word
local step:dword  ;шаг по Х
local cnt:word  ;переменная для получения из сопроцессора числа точек по Х
local xekr:word  ;экранная координата по Х

;посчитаем количество точек по Х
 mov si, xmax ;адрес Xmax
 fld dword ptr [si] ;st=Xmax=b
 mov si, xmin ;адрес Xmin
 fsub dword ptr [si] ;st=b-a
 fld st  ;st=b-a,st(1)=b-a
 fimul coef  ;длина в точках
 fist cnt  ;сохраним число точек = числу отрезков
 fdivp st(1), st ;шаг по Х = (b-a) / число точек
 fstp step  ;сохраним шаг по Х
 
 fld dword ptr [si] ;st=a, начальное значение Х
 fimul coef  ;в точках
 fistp xekr  ;сохраним в xekr
 add xekr, X_OF_AXIS_Y ;привяжем экранную координату Х к оси Y
 mov cx, cnt  ;число отрезков
 fld dword ptr [si] ;st=a, начальное значение Х
Graph_loop:   ;цикл рисования отрезков
 call word ptr [pFun] ;считаем y первой точки
 mov bx, ax  ;сохраним в bx

 fadd step  ;st=st+step
 call word ptr [pFun] ;ax = y второй точки

 test bx, bx  ;проверим, чтобы не выходить за 0 (за пределы экрана)
 jge Gr_ax
 xor bx, bx  ;отрицательные y меняем на 0
Gr_ax:
 test ax, ax  ;аналогично
 jge Gr_draw
 xor ax, ax
Gr_draw:
 mov dx, ax  ;когда оба 0, то игнорируем!
 or dx, cx
 jz Graph_next
;рисуем линию (xekr, cx)-(xekr+1,ax) цветом col
 mov dx, xekr
 inc dx
 call line, xekr, bx, dx, ax, col

Graph_next:
 inc xekr  ;готовим xekr для следующего шага
 loop Graph_loop

 fstp st  ;уберем из стека сопроцессора последний Х
 ret
Graph endp

;рисуем линию (x1,y1)-(x2,y2) цветом color
Line proc uses di bx cx, x1:word, y1:word, x2:word, y2:word, color:byte
local i:word,  \ ;для работы со сопроцессором
 delta_x:word, \ ;длина проекции на ось абсцисс
 delta_y:word, \ ;длина проекции на ось ординат
 incx:word, \ ;приращение по X
 incy:word  ;приращение по Y

;определим длину проекции на ось абсцисс и шаг по оси X
 mov ax, x2
 sub ax, x1  ;ax=x2-x1;

;определим шаг по X (+1 если вперед, -1 если назад, 0 если не меняется)
 mov incx, 0  ;пусть incx=0
 test ax, ax  ;ax=delta_x 
 jz set_delta_x ;не меняется
 jg set_x_1  ;вперед?
 dec incx  ;назад, значит incx=-1
 neg ax  ;найдем ax=abs(delta_x)
 jmp set_delta_x ;на сохранение
set_x_1:
 inc incx  ;вперед, значит incx=1;
set_delta_x:
 mov delta_x, ax ;delta_x = abs(x2-x1)

;определим длину проекции на ось ординат и шаг по оси Y
 mov ax, y2
 sub ax, y1  ;ax=y2-y1;

;определим шаг по Y (+1 если вперед, -1 если назад, 0 если не меняется)
 mov incy, 0  ;пусть incy=0
 test ax, ax  ;ax=delta_y
 jz set_delta_y ;не меняется
 jg set_y_1  ;вперед?
 dec incy  ;назад, значит incy=-1
 neg ax  ;найдем ax==abs(delta_y)
 jmp set_delta_y ;на сохранение
set_y_1:
 inc incy  ;вперед, значит incy=1;
set_delta_y:
 mov delta_y, ax ;delta_y=abs(y2-y1)
 
;определим большее из проекций как основное напрвление
 cmp ax, delta_x ;ax=delta_y
 jge from_y  ;y будет основным
 cmp delta_x, 0 ;проверим, чтобы не было delta_x=0 (для точки),
 jz to_Line_ret ; иначе будет деление на 0
;delta_x>delta_y && delta_x!=0
;основное направление - по оси X
 fild delta_y
 fidiv delta_x  ;st=k=(float)(delta_y/delta_x)

;for (int i=0;i<delta_x;i++)
 xor cx, cx  ;cx=i
 jmp cmp_i_x  ;на проверку i<delta_x 
x_loop:    ;тело цикла
 mov i, cx  ;запишем переменную цикла в память (для сопроцессора)
 fld st  ;st=st(1)=k
 fimul i  ;st=k*i
 fimul incy  ;st=incy*k*i
 call floor  ;округлим до целого в большую сторону
 fistp i  ;сохраним в переменной
 mov ax, i  ;относительный номер строки на экране
 add ax, y1  ;добавим до ординаты начальной точки
 mov dx, 320  ;получим индекс начала строки экрана в сегменте экрана
 imul dx  ; для этого умножим на длину в байтах одной стоки
 mov bx, ax  ;сохраним bx=y=(y1+floor(incy*k*i))*320
    ;посчитаем X
 mov ax, incx ;X меняется ровно на шаг приращения,
 imul cx  ; умноженному на индекс точки
 add ax, x1  ;добавим абциссу начальной точки ax=x=x1+incx*i

 add ax, bx  ;сложим с индексом начала строки
 mov di, ax  ;будем адресовать через di

 mov al, color ;цвет точки
 mov es:[di], al ;рисуем!

 inc cx  ;на следующую точку
cmp_i_x:
 cmp cx, delta_x ;дошли до конца?
 jl x_loop
to_Line_ret:
 jmp Line_ret ;на выход
 
from_y:    ;вдоль оси Y
 fild delta_x
 fidiv delta_y  ;st=k=(float)(delta_x/delta_y)

;for (int i=0;i<delta_y;i++)
 xor cx, cx  ;cx=i
 jmp cmp_i_y  ;на проверку i<delta_y 
y_loop:    ;тело цикла
 mov ax, incy ;Y меняется ровно на шаг приращения,
 imul cx  ; умноженному на индекс точки
 add ax, y1  ;добавим абциссу начальной точки ax=y=y1+incy*i
 mov dx, 320  ;получим индекс начала строки экрана в сегменте экрана
 imul dx  ; для этого умножим на длину в байтах одной стоки  
 mov bx, ax  ;сохраним bx=y=(y1+incy*i)*320
    ;посчитаем X
 mov i, cx  ;запишем переменную цикла в память (для сопроцессора)
 fld st  ;st=st(1)=k
 fimul i  ;st=k*i
 fimul incx  ;st=incx*k*i
 call floor  ;округлим до целого в большую сторону
 fistp i  ;сохраним в переменной
 mov ax, i  ;относительный номер строки на экране
 add ax, x1  ;ax=x=x1+floor(incx*k*i)

 add ax, bx  ;сложим с индексом начала строки
 mov di, ax  ;будем адресовать через di

 mov al, color ;цвет точки
 mov es:[di], al ;рисуем!

 inc cx  ;на следующую точку
cmp_i_y:
 cmp cx, delta_y ;дошли до конца?
 jl y_loop
Line_ret:
 fistp i  ;удалим из сопроцессора k
 ret
Line endp

;округление до целого в большую сторону
;округление по умолчанию, до ближайщего, не устраивает
floor proc
local CtrlWordOld:word, CtrlWordNew:word
 fstcw CtrlWordOld  ;сохраним управляющее слово
 fclex    ;сбросим исключения
 mov CtrlWordNew,0763h ;установим необходимое значение управляющего слова
 fldcw CtrlWordNew  ;загружаем управляющее слово
 frndint    ;округляем st до целого
 fclex    ;сбросим исключения
 fldcw CtrlWordOld  ;восстановим старое управляющее слово
 ret
floor endp

 .data
coef dw KOEF ;коэффициент масштабирования
a dd 1.5
b dd 1.6

 END

Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 03.10.2011, 16:21
Рейтинг ответа:

НЕ одобряю 0 одобряю!

Консультация # 184132:

Здравствуйте! Прошу помощи в следующем вопросе:

Построить график по функции и показать результат.
Формула:



Использование только Tasm модель памяти tiny размер переменных dw.

Дата отправки: 03.10.2011, 05:28
Вопрос задал: Посетитель - 382088 (Посетитель)
Всего ответов: 1
Страница онлайн-консультации »


Консультирует Лысков Игорь Витальевич (Старший модератор):

Здравствуйте, Посетитель - 382088!

Обращаю Ваше внимание, что выражение sin(x^3)^(2x) я рассматриваю, как (sin(x^3)^2)^x,
т.е. сначала возвожу в квадрат, а потом в степень х

Из-за большого разброса значений по X и Y применил разное масштабирование по осям абсцисс и ординат


Код :
;Программа,
одновременно считающая и рисующая часть графика по формуле.
;Формула: y=sin(x^3)^(2x) * 10^(10/sqrt(2))-1 на отрезке a=-1.3,b=-1.45
;Размер переменных : dw; Модуль памяти : tiny ; Использование TASM.

POWER MACRO     ;Макро для вычисления степени st^st(1)
 fyl2x     ;st=st(1)*log[2]st
 fld st    ;x*log[2]e->st(1)
 frndint     ;округляем st до целого
 fsub st(1),st   ;st(1)-=st
 fxch     ;st(1)<->st
 f2xm1     ;st=(2 в степени st) - 1
 fld1     ;1->st
 fadd     ;st+=1
 fscale     ;exp = st * (2 в степени st(1))
 fstp st(1)    ;чтобы убрать значение из st(1)
 ENDM

 .model tiny, C  ; модель памяти и порядок вызова параметров
 .386
 .code   ; сегмент кода
 .startup  ; точка входа

 mov ax, 0013h ; vga 320x200x256
 int 10h

 mov ax, 0a000h
 mov es, ax  ; es - сегмент видео

KOEF_X  equ 100 ;единица по X соответствует KOEF_X точкам на экране
KOEF_Y  equ 10 ;единица по Y соответствует KOEF_Y точкам на экране
Y_OF_AXIS_X equ 180 ;ордината оси абсцисс
X_OF_AXIS_Y equ 319 ;абсцисса оси ординат

main:
 finit   ;проинициируем сопроцессор

;ось ординат (X_OF_AXIS_Y,0)-(X_OF_AXIS_Y,199) цвета 0ch
 call line, X_OF_AXIS_Y, 0, X_OF_AXIS_Y, 199, 0ch
;нарисуем "рисочки" для y = 1, 2, 3,...
 mov si, KOEF_Y ;Y рисочки
ris_y_loop:
 call line, X_OF_AXIS_Y-1, si, X_OF_AXIS_Y, si, 0ch
 add si, KOEF_Y ;на следующую
 cmp si, 200
 jl ris_y_loop

;ось абсцисс (0,Y_OF_AXIS_X)-(319,Y_OF_AXIS_X) цвета 0ch
 call line, 0, Y_OF_AXIS_X, 319, Y_OF_AXIS_X, 0ch
;нарисуем "рисочки" для x = -1, -2, -3,...
 mov si, X_OF_AXIS_Y-KOEF_X ;Х рисочки
ris_x_loop:
 call line, si, Y_OF_AXIS_X, si, Y_OF_AXIS_X+2, 0ch
 sub si, KOEF_X ;на следующую
 jge ris_x_loop

;вывод графика -1.45<=x<=-1.3, y=fun(x) цвета 0bh
 call Graph, offset b, offset a, offset fun, 0bh

 mov ah, 0  ;ждемнажатие на любую клавишу
 int 16h

;выход в DOS
Exit:
 mov ax, 0003h ; назад в текстовый режим
 int 10h

 mov ax, 4c00h ; bye-bye
 int 21h

;подпрограммы

;Функция вычисления y по x, x = ST, т.е. в стеке сопроцессора
;возвращает экранную координату по оси Y
;Х остается в стеке сопроцессора для последующего вычисления
fun proc
local y:word   ;переменная для получения значения из сопроцессора
 fld st  ;для показателя степени

 fld st(1)  ;st=x,st(1)=x,st(2)=x
 fmul st,st(1) ;st=x^2,st(1)=x,st(2)=x
 fmul st,st(1) ;st=x^3,st(1)=x,st(2)=x
 fsin   ;st=sin(x^3),st(1)=x,st(2)=x

;возведем в степень sin(x^3)^(2x) = (sin(x^3)^2)^x
 fld st  ;st=sin(x^3),st(1)=sin(x^3),st(2)=x,st(3)=x
 fmulp st(1)  ;st=sin(x^3)^2,st(1)=x,st(2)=x
 POWER   ;st=(sin(x^3)^2)^x,st(1)=x

 fld st(1)  ;st=x,st(1)=(sin(x^3)^2)^x,st(2)=x
 fild c2  ;st=2,st(1)=x,st(2)=(sin(x^3)^2)^x,st(3)=x
 fsqrt   ;st=sqrt(2),st(1)=x,st(2)=(sin(x^3)^2)^x,st(3)=x
 fdivp st(1)  ;st=x/sqrt(2),st(1)=(sin(x^3)^2)^x,st(2)=x

 fild c10  ;st=10,st(1)=x/sqrt(2),st(2)=(sin(x^3)^2)^x,st(3)=x

 POWER   ;st=10^(x/sqrt(2)),st(1)=(sin(x^3)^2)^x,st(2)=x
 
 fmulp   ;st=10^(x/sqrt(2)) * (sin(x^3)^2)^x,st(1)=x

 fld1   ;st=1,st(1)=10^(x/sqrt(2))*(sin(x^3)^2)^x,st(2)=x
 fsubp st(1),st ;y=st=10^(x/sqrt(2))*(sin(x^3)^2)^x-1,st(1)=x

 fimul coef_y  ;масштабирование, st=coef_y*y,st(1)=x
 fistp y  ;сохраним в y, y=int(coef_y*y),st=x 
 mov ax, Y_OF_AXIS_X ;ордината оси абсцисс
 sub ax, y  ;ax = 0 - y
 ret
fun endp

;рисует график, последовательно соединяя точки отрезками
;параметры:
;xmin - адрес вещественной переменной левого значения интервала
;xmax - адрес вещественной переменной правого значения интервала
;pFun - адрес функции, вычисляющей экранную координату по вертикали
;col  - цвет линий
Graph proc xmin:word, xmax:word, pFun:word, col:word
local step:dword  ;шаг по Х
local cnt:word  ;переменная для получения из сопроцессора числа точек по Х
local xekr:word  ;экранная координата по Х

;посчитаем количество точек по Х
 mov si, xmax ;адрес Xmax
 fld dword ptr [si] ;st=Xmax=b
 mov si, xmin ;адрес Xmin
 fsub dword ptr [si] ;st=b-a
 fld st  ;st=b-a,st(1)=b-a
 fimul coef_x  ;длина в точках
 fist cnt  ;сохраним число точек = числу отрезков
 fdivp st(1), st ;шаг по Х = (b-a) / число точек
 fstp step  ;сохраним шаг по Х
 
 fld dword ptr [si] ;st=a, начальное значение Х
 fimul coef_x  ;в точках
 fistp xekr  ;сохраним в xekr
 add xekr, X_OF_AXIS_Y ;привяжем экранную координату Х к оси Y
 mov cx, cnt  ;число отрезков
 fld dword ptr [si] ;st=a, начальное значение Х
Graph_loop:   ;цикл рисования отрезков
 call word ptr [pFun] ;считаем y первой точки
 mov bx, ax  ;сохраним в bx

 fadd step  ;st=st+step
 call word ptr [pFun] ;ax = y второй точки

 cmp bx, 199
 jle Gr_ax_max
 mov bx, 199
Gr_ax_max:
 cmp ax, 199
 jle Gr_bx_min
 mov ax, 199
Gr_bx_min:
 test bx, bx  ;проверим, чтобы не выходить за 0 (за пределы экрана)
 jge Gr_ax
 xor bx, bx  ;отрицательные y меняем на 0
Gr_ax:
 test ax, ax  ;аналогично
 jge Gr_draw
 xor ax, ax
Gr_draw:
 mov dx, ax  ;когда оба 0 или 199, то игнорируем!
 or dx, bx
 jz Graph_next
 cmp dx, 199
 je Graph_next

;рисуем линию (xekr, cx)-(xekr+1,ax) цветом col
 mov dx, xekr
 inc dx
 call line, xekr, bx, dx, ax, col

Graph_next:
 inc xekr  ;готовим xekr для следующего шага
 loop Graph_loop

 fstp st  ;уберем из стека сопроцессора последний Х
 ret
Graph endp

;рисуем линию (x1,y1)-(x2,y2) цветом color
Line proc uses di bx cx, x1:word, y1:word, x2:word, y2:word, color:byte
local i:word,  \ ;для работы со сопроцессором
 delta_x:word, \ ;длина проекции на ось абсцисс
 delta_y:word, \ ;длина проекции на ось ординат
 incx:word, \ ;приращение по X
 incy:word  ;приращение по Y

;определим длину проекции на ось абсцисс и шаг по оси X
 mov ax, x2
 sub ax, x1  ;ax=x2-x1;

;определим шаг по X (+1 если вперед, -1 если назад, 0 если не меняется)
 mov incx, 0  ;пусть incx=0
 test ax, ax  ;ax=delta_x 
 jz set_delta_x ;не меняется
 jg set_x_1  ;вперед?
 dec incx  ;назад, значит incx=-1
 neg ax  ;найдем ax=abs(delta_x)
 jmp set_delta_x ;на сохранение
set_x_1:
 inc incx  ;вперед, значит incx=1;
set_delta_x:
 mov delta_x, ax ;delta_x = abs(x2-x1)

;определим длину проекции на ось ординат и шаг по оси Y
 mov ax, y2
 sub ax, y1  ;ax=y2-y1;

;определим шаг по Y (+1 если вперед, -1 если назад, 0 если не меняется)
 mov incy, 0  ;пусть incy=0
 test ax, ax  ;ax=delta_y
 jz set_delta_y ;не меняется
 jg set_y_1  ;вперед?
 dec incy  ;назад, значит incy=-1
 neg ax  ;найдем ax==abs(delta_y)
 jmp set_delta_y ;на сохранение
set_y_1:
 inc incy  ;вперед, значит incy=1;
set_delta_y:
 mov delta_y, ax ;delta_y=abs(y2-y1)
 
;определим большее из проекций как основное напрвление
 cmp ax, delta_x ;ax=delta_y
 jge from_y  ;y будет основным
 cmp delta_x, 0 ;проверим, чтобы не было delta_x=0 (для точки),
 jz to_Line_ret ; иначе будет деление на 0
;delta_x>delta_y && delta_x!=0
;основное направление - по оси X
 fild delta_y
 fidiv delta_x  ;st=k=(float)(delta_y/delta_x)

;for (int i=0;i<delta_x;i++)
 xor cx, cx  ;cx=i
 jmp cmp_i_x  ;на проверку i<delta_x 
x_loop:    ;тело цикла
 mov i, cx  ;запишем переменную цикла в память (для сопроцессора)
 fld st  ;st=st(1)=k
 fimul i  ;st=k*i
 fimul incy  ;st=incy*k*i
 call floor  ;округлим до целого в большую сторону
 fistp i  ;сохраним в переменной
 mov ax, i  ;относительный номер строки на экране
 add ax, y1  ;добавим до ординаты начальной точки
 mov dx, 320  ;получим индекс начала строки экрана в сегменте экрана
 imul dx  ; для этого умножим на длину в байтах одной стоки
 mov bx, ax  ;сохраним bx=y=(y1+floor(incy*k*i))*320
    ;посчитаем X
 mov ax, incx ;X меняется ровно на шаг приращения,
 imul cx  ; умноженному на индекс точки
 add ax, x1  ;добавим абциссу начальной точки ax=x=x1+incx*i

 add ax, bx  ;сложим с индексом начала строки
 mov di, ax  ;будем адресовать через di

 mov al, color ;цвет точки
 mov es:[di], al ;рисуем!

 inc cx  ;на следующую точку
cmp_i_x:
 cmp cx, delta_x ;дошли до конца?
 jl x_loop
to_Line_ret:
 jmp Line_ret ;на выход
 
from_y:    ;вдоль оси Y
 fild delta_x
 fidiv delta_y  ;st=k=(float)(delta_x/delta_y)

;for (int i=0;i<delta_y;i++)
 xor cx, cx  ;cx=i
 jmp cmp_i_y  ;на проверку i<delta_y 
y_loop:    ;тело цикла
 mov ax, incy ;Y меняется ровно на шаг приращения,
 imul cx  ; умноженному на индекс точки
 add ax, y1  ;добавим абциссу начальной точки ax=y=y1+incy*i
 mov dx, 320  ;получим индекс начала строки экрана в сегменте экрана
 imul dx  ; для этого умножим на длину в байтах одной стоки  
 mov bx, ax  ;сохраним bx=y=(y1+incy*i)*320
    ;посчитаем X
 mov i, cx  ;запишем переменную цикла в память (для сопроцессора)
 fld st  ;st=st(1)=k
 fimul i  ;st=k*i
 fimul incx  ;st=incx*k*i
 call floor  ;округлим до целого в большую сторону
 fistp i  ;сохраним в переменной
 mov ax, i  ;относительный номер строки на экране
 add ax, x1  ;ax=x=x1+floor(incx*k*i)

 add ax, bx  ;сложим с индексом начала строки
 mov di, ax  ;будем адресовать через di

 mov al, color ;цвет точки
 mov es:[di], al ;рисуем!

 inc cx  ;на следующую точку
cmp_i_y:
 cmp cx, delta_y ;дошли до конца?
 jl y_loop
Line_ret:
 fistp i  ;удалим из сопроцессора k
 ret
Line endp

;округление до целого в большую сторону
;округление по умолчанию, до ближайщего, не устраивает
floor proc
local CtrlWordOld:word, CtrlWordNew:word
 fstcw CtrlWordOld  ;сохраним управляющее слово
 fclex    ;сбросим исключения
 mov CtrlWordNew,0763h ;установим необходимое значение управляющего слова
 fldcw CtrlWordNew  ;загружаем управляющее слово
 frndint    ;округляем st до целого
 fclex    ;сбросим исключения
 fldcw CtrlWordOld  ;восстановим старое управляющее слово
 ret
floor endp

 .data
coef_x dw KOEF_X ;коэффициент масштабирования по X
coef_y dw KOEF_Y ;коэффициент масштабирования по Y
a dd -1.3
b dd -1.45
c2 dw 2
c10 dw 10

 END

Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 03.10.2011, 16:18
Рейтинг ответа:

НЕ одобряю 0 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка  |  восстановить логин/пароль

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!



В избранное