Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Рисует пол экрана, а хочется целый.  (Прочитано 19074 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Yop
Гость
« : 11-07-2004 07:30 » 

Народ, начинаю изучать графику на ассемблере. Пишу программу, которая
рисует градиент палитры по строкам.))) Никак не могу въехать в вопрос.
Это моя вторая программа, поэтому за тупизмы прошу не пинать.




00:   mov  ax,13h
03:   int  010
05:   mov  ax,0a000
08:   mov  es,ax
0A:   xor  ax,ax
0C:   adc  al,001
0E:   mov  ah,al
11:   cmp  al,0c8
13:   jl   0A
15:   cmp  bx,0fa00
19:   jg   1D          ;проверяю на 64000
1B:   xor  bx,bx  
1D:   mov  cx,00140    ; 1 цвет на 320 строк
20:   adc  bx,001      ; почему, если сюда тупо забить mov bx,0CCCCh ,
                         например, то нарисуется, какая надо точка,
                         а если прибавлять, то только пол экрана?
23:   mov  es:[bx],ax    
26:   loop 20
28:   jmps 0C
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 11-07-2004 08:53 » 

Цитата

0C: adc al,001


Цитата

20: adc bx,001


Цитата

а если прибавлять


Yop, судя по слову "прибавлять" ты не имеешь в виду "прибавлять с переносом"

тогда (на первый взгляд) тебе вроде нужно пользовать команду "add" а не "adc"...

если же твой алгоритм (кстати - ты бы привёл его, разбираться в чужой логике сложно по программе Ага ) использует именно сложение с переносом, то особо обращай на флаг переноса "с" ...

имхо
Записан

Yop
Гость
« Ответ #2 : 11-07-2004 13:44 » 

Там без разницы ADD или ADC, все равно до конца регистра не доходит.

Ладно подробнее:

00:   mov  ax,13h        ;
03:   int  010           ; Переходим в режим 320х240
05:   mov  ax,0a000
08:   mov  es,ax         ; Заносим в ES A000h . A000 - B000   -- буфер регенирации VGA
0A:   xor  ax,ax         ; AX - цвет, будем возвращаться сюда каждый раз, чтоб сбросить в ноль
0C:   adc  al,001        ; Прибавляем значение цвета, здесь будем раз в 320 пикселей, чтоб каждой строчке по цвету
0E:   mov  ah,al         ; AH вроде за цвет второго пикселя рядом отвечает, я до конца не знаю, но пускай цвет тот же будет
11:   cmp  al,0c8        ; Сравниваем цвет с 200(количество строк)
13:   jl   0A            ; Если больше, то футболимся по 0А сбрасывать значение
15:   cmp  bx,0fa00      ; А это BX с 64000(кол-во пикселей) пробовал ставить 32000 - без раздницы
19:   jg   1D            ; если больше сбрасываем в ноль, если нет перелетаем в 1D
1B:   xor  bx,bx  
1D:   mov  cx,00140    ; ставим счетчик CX в 320
20:   adc  bx,001      ; прибавляем BX - соответственно рисуется следующий пиксель
23:   mov  es:[bx],ax   ; отправляем в буфер по адресу es+bx значение цвета из AX
26:   loop 20           ; когда счетчик CX сбрасывается в 0 - строка нарисована, идем за новым цветом
28:   jmps 0C           ;идем:)))

Все это набивал в HIEW и в COM файл все работает(почти), но почему пол экрана?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 11-07-2004 15:50 » 

Цитата

03: int 010 ; Переходим в режим 320х240


- это всё равно, что:

int 0ah

а это - "Запись символа".

напиши
Цитата

03: int 010h ; Переходим в режим 320х240


____________________

а вот ещё попробуй то же, но в другом фантике Ага

Код:

mov ax,13h ;
int 010h ;

mov ax,0a000h ;
mov es,ax ;

clr_color{ xor ax,ax ;  
nextcol{ inc al ;

mov ah,al ; AH - ?

cmp al,200 ;  
jc clr_color ;  

cmp bx,64000 ;
jnc load_RC_320
xor bx,bx

load_RC_320{
mov cx,320 ;
next_pix{ inc bx ;
mov es{[bx(,ax ;з AX
loop next_pix ;  
jmps nextcol ;

___________________________
я пока попробую разобраться на пальцах - запустить мне сию радость негде Жаль
если всё ещё не работает - ругайся ещё, попробую дальше разобраться. Улыбаюсь
Хотя ты уже сам наверняка разберёшься

___________________
ГРОМ, а с форматированием - прямо бедааа...
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 12-07-2004 07:39 » 

Yop, там где сложение с флагом переносом не нужно специально, следует использовать сложение без флага переноса!
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 12-07-2004 09:25 » 

кстати,Yop,  я чего-то сразу не обратил внимания на твою фразу
Цитата

Там без разницы ADD или ADC, все равно до конца регистра не доходит.

сложение с переносом - это не связано напрямую с переполнением регистров (косвенно только), это значит , что к результату , полученному в результате сложения операндов, прибавляется содержимое флага переноса СF (причём то, которое было ДО операции сложения). А изменить флаг переноса может, к примеру, та же cmp и adc ( Ага ). Ди и что творят с этим флагом в прерывании - тоже одному Биллу известно Улыбаюсь
Так что насчёт "add" RXL и я тебя не зря предупреждаем...

 :arrow:
а что касаемо пол-экрана - это вполне может быть как раз из-за пропущенного "h" - разрешение не переключилось, а количество пикселей на чёрном экране или градиенте не посчитаешь...
Записан

Yop
Гость
« Ответ #6 : 12-07-2004 12:27 » 

Ну опечатался, опечатался я. Забыл h дописать.Ты Алексей тоже опечатался, предлагаешь мне jnс вместо inс. Все мы люди))))


        Пробовал я inc результат тот же, почти.(почти в смысле маленький косячок с первым пикселем видоизменился)

Я же говорю у меня все работает, но только на пол экрана.

Ту что-то не то именно с адресацией, но я никак не пойму что.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 12-07-2004 18:36 » 

Yop, люди, базара нэт, но где я опечатался ? Ага это именно JNC а не INC

если выполнить
Код:

cmp  reg,number
jnc    label

то на метку будет сделан переход, если reg>=number

соответственно, если
Код:

cmp  reg,number
jc     label

то на метку будет сделан переход, если reg<number

это у меня привычка после кр580 осталась  :oops: ... но оно работает
 
:arrow:
да, люди, но опечатки в программах - это баг Ага - а к ним надо серьёзно. А генерация не того прерывания - это баг ещё тот...

 :arrow:
щас на бумаге распишу алгоритм - пороюсь, мож найду чего...

 :arrow:
кстати - если прочитаешь энто раньше, чем я снова запостю, удостоверься, что разрешение включается именно то, которое надо
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 12-07-2004 20:02 » 

выяснил я вот что

 :arrow:
видеопамять размещена в области A0000...BFFFF.
Мы загружаем в es число A000 а не A0000 потому, что при формировании адреса es:bx сегментный регистр будет аппаратно сдвинут влево на 4 бита, следовательно:
физический адрес == ((es<<4) + bx);

 :arrow:
режим 13h видеосервиса 10h это:
VGA 320x200, 256 цветов



 :arrow:
Yop, попробуй такую прогу
(она из предположения, что каждый пиксел кодируется одним байтом видеопамяти и байты расположены друг за другом - все 64000 байт для режима 320x200. Если пикселы в видеопамяти кодируются иначе - прога не заработает)

Код:

      mov      ax,13h
      int      10h
      mov      ax,0a000h
      mov      es,ax

      mov      al,0
begin_row{
      mov      cx,320

put_pix{
      mov      es{[bx(,al
      inc      bx
      loop      put_pix

next_row{
      inc      al
      cmp      bx,64000
      jnz      begin_row

screen_filled{
      ;экран уже должен быть заполнен градиентом
      ...
Записан

Yop
Гость
« Ответ #9 : 13-07-2004 10:09 » 

Спасибо Алексей, твоя версия заработала, только я не понял почему...

  Буду учить, что учится.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 13-07-2004 13:05 » 

Цитата

только я не понял почему


хочешь подскажу, почему? Улыбаюсь

(только не воспринимай как нравоучения и капание на мозг - это просто советы, я сам прошёл через эти грабли, и , по сути, я сейчас перечислю мои собственные ошибки в "процессе обучения", если так мона выразиться Ага )

 :arrow:
я в твоей версии не заметил выхода - она зациклена Ага Может он и есть, но я не заметил   Вот такой я вот .
в ассемблерной программе в таких случаях разбираться что же именно нарушило работу программы - это геморрой, порой даже невозможно.

твоя прога не зависала случаем? Если нет - тогда она каким-то счастьем всё-таки выходила из "спагетти"

 :arrow: до ассемблера ты ничего не писал на С++ Ага

 :arrow: ты писал программу сразу - в мнемонике, не нарисовав алгоритма на БУМАГЕ, да?

 :arrow:
о программе в самом первом посте - структурно нечитабельна и , кроме того , незаремарена (!)
Вместо меток используешь адреса - (интересно - ты сам их высчитывал или компилятору какому сперва подсунул Ага и сколько времени и нервов на это ушло ?)

серьёзные ЛОГИЧЕСКИЕ ошибки (по крайней мере - возможные источники ошибок) -
Код:

03{      int         010              ; нет "h"
05{      mov      ax,0a000      ; нет "h"
...
0C{      adc      al,001           ; adc вместо add
...
0E{      mov      ah,al            ;
...
13{      jl          0A                ; нет "h"
15{      cmp      bx,0fa00       ; нет "h"
19{      jg         1D                ; нет "h"
...
1D{      mov      cx,00140      ; нет "h" )вот и половина экрана:
20{      adc      bx,001           ; adc вместо add
23{      mov      es{[bx(,ax     ; запись не байта а слова
...
28{      jmps      0C               ; нет "h"



1) 0a000, 0fa00, 0A, 1D, 0C - так как эти лексемы начинаются с цифр, компилятор, встретив в них символы шестнадцатеричного числа, призадумался и приподняв левую бровь посчитал их хексами. А вот число 00140 он радостно оставил десятичным - отсюда и половина экрана - 140 строк заместо 320.
Хексы, которые больше 9, лучше всегда начинать с цифры (или ставить ноль перед числом, если начинается с буквы) и оканчивать "h".
2) про adc уже говорилось
3) а вот тут:

mov es:[bx],ax

ты записываешь al по адресу es:[bx] , а ah по адресу es:[bx+1] . Прога не упала потому, что ты выводил только 140 строк - интересно, что будет, если записать байт в 64001 - байт видеопамяти? (адрес С0000). Также первый пиксел 141-й строки был закрашен, верно? Кроме того - каждый закрашенный пиксел был закрашен дважды (кроме самого первого и последнего - который единственный в 141-й строке).

 :arrow:
Цитата

Буду учить, что учится.

нет, надо так :
Буду учить Ага

___________________________
если в чём я оказался неправ - опровергай, мне просто интересно проверить, что я угадал, а что нет Улыбаюсь
и ещё раз - Yop, без обид, ага? Улыбаюсь Это просто советы (даже не советы - это и мои ошибки Улыбаюсь ) . Я вовсе не ставлю целью показаться заумным и очень опытным - это совершенно не так, я почти чайник Улыбаюсь (но заварка хорошая - блин, скромный я ещё Улыбаюсь) ). Просто без этих простых правил - тебе будет трудно искать баги
Записан

Yop
Гость
« Ответ #11 : 13-07-2004 17:01 » 

Какие обиды могут быть за прекрасную науку Улыбаюсь

А вообще я только учусь, и набиваю весь ассемблер в HIEW 6.11.
Мне так пока проще понимать процессорную суть Я шокирован!

А HIEW все цифры воспринимает как HEX, потому уже и привык.


Цитата
твоя прога не зависала случаем?


Виснет, но очень редко, так что почти нет.

Цитата
до ассемблера ты ничего не писал на С++ Ага

Наверно только пытался думать...

Цитата
ты писал программу сразу - в мнемонике, не нарисовав алгоритма на БУМАГЕ, да?

Нет на бумаге, но во второй раз в жизни. Кожется во второй...

 

Цитата
...
1D:      mov      cx,00140      ; нет "h" (вот и половина экрана)...


Нет у меня рисует ровно пол экрана(значение менял, линейкой замерял)

Цитата
...Также первый пиксел 141-й строки был закрашен, верно?

Верно,но еще и потому, что BX не принимает значения 0 в качестве смещения ES
Поэтому первый пиксель каждой строчки имеет цвет предыдущей строки, а самый первый пиксель черный.

Цитата

нет, надо так :
Буду учить Ага

Еще в 1c на работе уже не только НДС и кнопочки забивать приходится, и выделенку в этом месяце ставим, linux+squid в первый раз:)))

Учение - свет монитора.

 
Кстати моя предыдущая программа (генерирует аналоговые помехи Улыбаюсь)) работет очень хорошо:

Код:

mov  ax,013h
int  010h
mov  ax 0A000h
mov  es,ax

adc  bx,1   ; а если сюда
adc  dx,1   ; и сюда забить вместо adc - add,
                   то вообще Матрица получится{::
 
adc  ch,dh

mov  es{[bx(,ch
jmps 00000000A    ; на строчку {  adc  bx,1

Кому не лень набить, зацените.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 14-07-2004 04:31 » 

Цитата

но еще и потому, что BX не принимает значения 0 в качестве смещения ES
Поэтому первый пиксель каждой строчки имеет цвет предыдущей строки, а самый первый пиксель черный


это из-за

Цитата

1B: xor bx,bx
1D: mov cx,00140 ; ставим счетчик CX в 320
20: adc bx,001 ; прибавляем BX - соответственно рисуется следующий пиксель


то есть обнулив bx ты тут же увеличиваешь его на единицу, и следовательно ВСЁ выводимые пикселы сдвинулись вправо на 1. Края строк, "зашедшие" за "край" растра экрана, "вылезли" слева.
Если алгоритм требует такой последовательности команд(хотя всегда можно извернуться, если представить программу ниткой с узлами - узлы можно передвигать, а нитка потянется за узлами, и топология сохраниться), то инициализировать bx надо не нулём, а "-1" (0ffff). Тогда будет нормально.

а насчёт первого пиксела в 141-й строке - если ты сделаешь bx=-1 в начале, то у тебя пикселы слева бы не вылезли, но первый пиксел в 141-й строке был бы всё равно окрашен в цвет 140-й строки - это из-за

mov es:[bx],ax

вместо
mov es:[bx],al

Первые пикселы всех строк, кроме первой, тоже окрашиваются в цвет предыдущих строк, но они (при переходе на следующую строку) тут же окрашиваются в нужный цвет

Цитата

Кому не лень набить, зацените


ну - забить мне её некуда, а то я б заценил... Хотя - кто знает, подскажите как сделать ассеблерную вставку в VC++ ?

 
Цитата

Кстати моя предыдущая программа (генерирует аналоговые помехи )) работет очень хорошо:


просто она хорошо глючит - именно так, как надо Улыбаюсь

шутю Улыбаюсь

а если серьёзно - не контролируешь выход bx за число 63999 - и пишешь в неотображаемую при данном разрешении видеопамять (хорошо, что всё заканчивается на 65535 - а если бы разрешение было включено по максимуму, и сегмент был бы побольше, чем 64К ?)

сделай перед выводом в озу ch такое

Код:

        mov        ax,013h
        int        010h
        mov        ax 0A000h
        mov        es,ax
tohell{
        adc        bx,1
        adc        dx,1

        adc        ch,dh

        mov        al,ch                ;*
        cbw                                ;*
        mov        es{[bx(,ah        ;*

        jmps        tohell


должен вроде чёрно-белый "снег" получиться Улыбаюсь
Записан

Антон123
Гость
« Ответ #13 : 14-07-2004 13:00 » 

Алексей,
Цитата

Хотя - кто знает, подскажите как сделать ассеблерную вставку в VC++ ?


asm
{
}
Записан
Антон123
Гость
« Ответ #14 : 14-07-2004 13:05 » 

точнее

__asm
{
    ; your code
}
Записан
Yop
Гость
« Ответ #15 : 14-07-2004 14:10 » 

Цитата

а насчёт первого пиксела в 141-й строке - если ты сделаешь bx=-1 в начале, то у тебя пикселы слева бы не вылезли, но первый пиксел в 141-й строке был бы всё равно окрашен в цвет 140-й строки - это из-за


mov es:[bx],ax

вместо
mov es:[bx],al


Тв прав, только в 100-й строке при ax , будет 2 пикселя
                                                 при al - один
 

Цитата

сделай перед выводом в озу ch такое

Код:

        mov        ax,013h
        int        010h
        mov        ax 0A000h
        mov        es,ax
tohell{
        adc        bx,1
        adc        dx,1

        adc        ch,dh

        mov        al,ch                ;*
        cbw                                ;*
        mov        es{[bx(,ah        ;*

        jmps        tohell


должен вроде чёрно-белый "снег" получиться Улыбаюсь


да нет чего-то черный экран
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 14-07-2004 16:51 » 

Цитата

да нет чего-то черный экран


тады упс...
значит восьмой бит ch постоянно равен 0...

тогда поможет вот что:

Код:

        adc        ch,dh

        rol        al,1                ;добавлено
        mov        al,ch
        cbw
        mov        es{[bx(,ah
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #17 : 14-07-2004 18:37 » 

Антон123, приветствую на единственном межпланетном форуме Улыбаюсь

спасибо за подсказку - попробую

ЗЫ. Антон, хочу проверить одно смутное сомнение: тебе строка CString zbsusu="НЗД515" случаем не знакома?
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 14-07-2004 21:24 » 

Yop, напиши алгоритм русским языком на бумаге, а потом переведи его в код - сразу станет проше и яснее.
Кстати, вместо adc reg,1 , в твоем случае, вообще нужно ставить inc reg.
Всего то нужно два цикла и один mov внутри.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Антон123
Гость
« Ответ #19 : 15-07-2004 09:06 » 

Алексей,

Цитата

тебе строка CString zbsusu="НЗД515" случаем не знакома?


нет, не понял. В чем прикол?  :?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #20 : 16-07-2004 04:12 » 

Антон123, забей Улыбаюсь ,
 просто один мой знакомый мог под таким ником сюда придти - он бы узнал

но всё равно - добро пожаловать
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 16-07-2004 04:12 » 

Антон123, забей Улыбаюсь ,
 просто один мой знакомый мог под таким ником сюда придти - он бы узнал

но всё равно - добро пожаловать
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #22 : 16-07-2004 04:13 » 

Антон123, забей Улыбаюсь ,
 просто один мой знакомый мог под таким ником сюда придти - он бы узнал

но всё равно - добро пожаловать
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines