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

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


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

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

Чемпионы рейтинга экспертов в этой рассылке

Boriss
Статус: Академик
Рейтинг: 2308
∙ повысить рейтинг »
_Ayl_
Статус: Практикант
Рейтинг: 1823
∙ повысить рейтинг »
vladisslav
Статус: 6-й класс
Рейтинг: 1231
∙ повысить рейтинг »

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

Номер выпуска:1338
Дата выхода:17.05.2010, 17:30
Администратор рассылки:Лысков Игорь Витальевич, Модератор
Подписчиков / экспертов:276 / 61
Вопросов / ответов:1 / 1
IRC-канал по теме:#assembler

Вопрос № 178349: Здравствуйте уважаемые эксперты! Побывав в реанимации, озадачился вопросом рисования синусоиды методом ПОВ. Чёрно-белые мониторы с маленькой диагональю, в которых рисовалась и перерисовывалась синусоида, там переносились с места на место и вроде как,...



Вопрос № 178349:

Здравствуйте уважаемые эксперты! Побывав в реанимации, озадачился вопросом рисования синусоиды методом ПОВ. Чёрно-белые мониторы с маленькой диагональю, в которых рисовалась и перерисовывалась синусоида, там переносились с места на место и вроде как, кроме эл.сети никуда не подключались, из чего я сделал вывод (возможно ошибочный), что процессор и память находятся внутри монитора. А если это так, то для рисования синусоиды вряд ли используется int 21h DOS, наверное, с большей вероятностью ПОВ.

1. У меня при нажатии на F1, появляются синие линии, а вот как их убрать, не могу додуматься. Мне нужно, чтобы при последовательном нажатии F1 вертикальные синие линии то появлялись, то исчезали.
2. Как нарисовать недвигающуюся синусоиду в пять периодов (т.к. экран у меня после нажатия на F1 поделён вертикальными линиями на 10 вертикальных полос) амплитудой в 18 строк после нажатия клавиши, например, F2. Не могу найти символы, соответствующие вершинам амплитуд, есть тол ько вертикальные скобки ( ), тем более что вершины амплитуд при разных условиях будут иметь разное искривление, хотя линию можно заменить и точками.
3. При повторном нажатии на F2 синусоида начинает двигаться вдоль горизонтальной оси, сама скорость перемещения значения не имеет.
4. При следующем нажатии F2 движение синусоида останавливается, ещё при следующем – опять двигается и т.д..
Заранее спасибо.

Отправлен: 12.05.2010, 17:01
Вопрос задал: Adsorores, Посетитель
Всего ответов: 1
Страница вопроса »


Отвечает Лысков Игорь Витальевич, Модератор :
Здравствуйте, Adsorores.
Позвольте продемонстрировать решение Вашей задачи в графическом режиме:
Код:

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

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

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

MainLoop:
;рисуем вертикальные линии через каждые pi/2 0<=у<=199
call vert, 0, 199
;ось ординат (0,0)-(0,199) цвета 0ch
call line, 0, 0, 0, 199, 0ch
;ось абсцисс (0,100)-(319,100) цвета 0ch
call line, 0, 100, 319, 100, 0ch
;синусоида 0<=x<=319, y=sinus(x) цвета 0bh
call Graph, 0, 319, offset sinus, 0bh

wait_key: ;цикл проверки ожидания нажатия на клавишу
mov ah, 1
int 16h
jnz get_key ;что-то нажато, проверим что
cmp f_F2, 0 ;флаг движения по F2 = 0,
je wait_key ; на ожидание клавиши
;сдвинем синусоиду!
call DELAY ;пауза
call Graph, 0, 319, offset sinus, 0 ;вытрем старую (нарисуем цветом 0!)
fld fi ;изменим параметр в формуле sin(x+fi)
fadd c01 ;на 0.1
fstp fi ;благодаря изменению fi и получаем движение синусоиды
jmp MainLoop ;рисуем заново!
get_key:
mov ah, 0 ;проверяем на код клавиши
int 16h
cmp ah, 1 ;по Esc выходим
je Exit
cmp ah, 3bh ;F1
je key_F1
cmp ah, 3ch ;F2
jne wait_key ;все остальное игнорируем
xor f_F2, 1 ;по F2 меняем флаг движения
jmp wait_key
key_F1: ;по F1 меняем цвет вертикальных линий (синий/черный)
xor vcolor, 9
call Graph, 0, 319, offset sinus, 0 ;вытираем
jmp MainLoop ;и рисуем по-новому

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

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

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

;рисуем вертикальные линии x=(pi*n)/2, ystart<=y<=yend
vert proc ystart:word, yend:word
local xx:word, num:word
mov num, 1 ;номер линии
vert_loop:
fldpi ;Пи
fidiv c2 ;Пи/2
fimul coef ;масштабируем в экранные размеры
fimul num ;coef*num*Пи/2
fistp xx ;x
cmp xx, 319 ;дошли ли до края экрана
ja vert_ret
;рисуем линию цвета vcolor (синим или черным, т.е. невидимым, цветом)
call line, xx, ystart, xx, yend, vcolor
inc num ;на следующую линию
jmp vert_loop
vert_ret:
ret
vert endp

;Функция вычисления y по x
Sinus proc x:word
local y:word ;переменная для получения значения из сопроцессора
fild x ;экранный x
fidiv coef ;убираем масштабирование
fadd fi ;x+fi
fsin ;sin(x+fi)
;промасштабируем для вывода на экран
;умножим на coef=20 и получим величины [-20,+20]
;отнимем от 100 и получ им экранные 80-120, "перевернутые" (0 сверху)
fimul coef
fistp y ;сохраним в y
mov ax, 100
sub ax, y ;ax = 100 - y
ret
Sinus endp

;рисует график, последовательно соединяя точки отрезками
;параметры:
;xmin - левая экранная координата графика
;xmax - правая экранная координата графика
;pFun - адрес функции, вычисляющей экранную координату по вертикали
;col - цвет линий
Graph proc xmin:word, xmax:word, pFun:word, col:word
Graph_loop: ;цикл рисования отрезков
mov ax, pFun ;адрес функции
call ax, xmin ;считаем y первой точки
mov cx, ax ;сохраним в cx

mov ax, xmin ;найдем x соседней справа точки
inc ax
mov si, ax ;сохраним в sі
cmp ax, xmax ;проверим, дошли и до правого края
ja Graph_ret

mov ax, pFun ;адрес функции
call ax, si ;ax = y второй точки

test cx, cx ;проверим, чтобы не выходить за 0 (за пределы экрана)
jge Gr_ax
xor cx, cx ;отрицательные 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
;рисуем линию (xmin, cx)-(si,ax) цветом col
call line, xmin, cx, si, ax, col
Graph_next:
mov xmin, si ;готовим xmin для следующего шага
jmp Graph_loop
Graph_ret:
ret
Graph endp

;рисуем линию (x1,y1)-(x2,y2) цветом color
Line proc uses di bx, 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 Line_ret ; иначе будет деление на 0
;delta_x>delta_y && delta_x!=0
;основное направление - по оси X
fild delta_y
fidiv delta_x ;st=k=(float)(delt a_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
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

;пауза ~40мс. Под Windows весьма условно, скорее всего будет больше
time equ 4 ;число интервалов по 10мс
DELAY: pusha ;сохраним все регистры
mov ah,2dh ;сбросим &q uot;локальное" системное время (под nt+ все равно не поменяет)
xor cx,cx
xor dx,dx
int 21h

dl2: mov ah,2ch
int 21h ;читаем время
;считаем сотни мс
mov al,100
mul dh ;секунды умножаем на 100 -> ax = количество интервалов по 10мс
xor dh,dh ;dx - число сотых
xchg ax,dx ;поменяем местами
mov cl,10
div cl ;ax = количество интервалов по 10мс из сотых
add ax,dx ;складываем с количеством из секунд
cmp ax,time ;сравним с ожидаемым интервалом
jl dl2 ;ждем, если меньше
popa ;восстановим все регистры
ret

.data
f_F2 dw 0 ;флаг движения по F2
vcolor dw 0 ;цвет вертикальных линий, меняется по F1
coef dw 20 ;коэффициент масштабирования
fi dd 0 ;угол сдвига в функции sin(x+fi)
c01 dd 0.1 ;шаг для изменения угла сдвига
c2 dw 2 ;константа для деления в сопроцессоре на 2
END

-----
Удачи!

Ответ отправил: Лысков Игорь Витальевич, Модератор
Ответ отправлен: 13.05.2010, 01:58
Номер ответа: 261355
Украина, Кировоград
Тел.: +380957525051
ICQ # 234137952
Mail.ru-агент: igorlyskov@mail.ru
Абонент Skype: igorlyskov

Оценка ответа: 5

Вам помог ответ? Пожалуйста, поблагодарите эксперта за это!
Как сказать этому эксперту "спасибо"?
  • Отправить SMS #thank 261355 на номер 1151 (Россия) | Еще номера »
  • Отправить WebMoney:

  • Оценить выпуск »
    Нам очень важно Ваше мнение об этом выпуске рассылки!

    Задать вопрос экспертам этой рассылки »

    Скажите "спасибо" эксперту, который помог Вам!

    Отправьте СМС-сообщение с тестом #thank НОМЕР_ОТВЕТА
    на короткий номер 1151 (Россия)

    Номер ответа и конкретный текст СМС указан внизу каждого ответа.

    Полный список номеров »

    * Стоимость одного СМС-сообщения от 7.15 руб. и зависит от оператора сотовой связи. (полный список тарифов)
    ** При ошибочном вводе номера ответа или текста #thank услуга считается оказанной, денежные средства не возвращаются.
    *** Сумма выплаты эксперту-автору ответа расчитывается из суммы перечислений на портал от биллинговой компании.


    © 2001-2010, Портал RFpro.ru, Россия
    Авторское право: ООО "Мастер-Эксперт Про"
    Автор: Калашников О.А. | Программирование: Гладенюк А.Г.
    Хостинг: Компания "Московский хостер"
    Версия системы: 2010.6.14 от 03.03.2010

    В избранное