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
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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 файл все работает(почти), но почему пол экрана?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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
|
|
« Ответ #4 : 12-07-2004 07:39 » |
|
Yop, там где сложение с флагом переносом не нужно специально, следует использовать сложение без флага переноса!
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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 результат тот же, почти.(почти в смысле маленький косячок с первым пикселем видоизменился)
Я же говорю у меня все работает, но только на пол экрана.
Ту что-то не то именно с адресацией, но я никак не пойму что.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 12-07-2004 18:36 » |
|
Yop, люди, базара нэт, но где я опечатался ? это именно JNC а не INC если выполнить то на метку будет сделан переход, если reg>=number соответственно, если то на метку будет сделан переход, если reg<number это у меня привычка после кр580 осталась :oops: ... но оно работает :arrow: да, люди, но опечатки в программах - это баг - а к ним надо серьёзно. А генерация не того прерывания - это баг ещё тот... :arrow: щас на бумаге распишу алгоритм - пороюсь, мож найду чего... :arrow: кстати - если прочитаешь энто раньше, чем я снова запостю, удостоверься, что разрешение включается именно то, которое надо
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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 » |
|
Спасибо Алексей, твоя версия заработала, только я не понял почему...
Буду учить, что учится.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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
Кому не лень набить, зацените.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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
должен вроде чёрно-белый "снег" получиться да нет чего-то черный экран
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #16 : 14-07-2004 16:51 » |
|
да нет чего-то черный экран
тады упс... значит восьмой бит ch постоянно равен 0... тогда поможет вот что: adc ch,dh
rol al,1 ;добавлено mov al,ch cbw mov es{[bx(,ah
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #17 : 14-07-2004 18:37 » |
|
Антон123, приветствую на единственном межпланетном форуме спасибо за подсказку - попробую ЗЫ. Антон, хочу проверить одно смутное сомнение: тебе строка CString zbsusu="НЗД515" случаем не знакома?
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #18 : 14-07-2004 21:24 » |
|
Yop, напиши алгоритм русским языком на бумаге, а потом переведи его в код - сразу станет проше и яснее. Кстати, вместо adc reg,1 , в твоем случае, вообще нужно ставить inc reg. Всего то нужно два цикла и один mov внутри.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Антон123
Гость
|
|
« Ответ #19 : 15-07-2004 09:06 » |
|
Алексей, тебе строка CString zbsusu="НЗД515" случаем не знакома?
нет, не понял. В чем прикол? :?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #20 : 16-07-2004 04:12 » |
|
Антон123, забей , просто один мой знакомый мог под таким ником сюда придти - он бы узнал но всё равно - добро пожаловать
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #21 : 16-07-2004 04:12 » |
|
Антон123, забей , просто один мой знакомый мог под таким ником сюда придти - он бы узнал но всё равно - добро пожаловать
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #22 : 16-07-2004 04:13 » |
|
Антон123, забей , просто один мой знакомый мог под таким ником сюда придти - он бы узнал но всё равно - добро пожаловать
|
|
|
Записан
|
|
|
|
|