Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm: Общие вопросы > Отрисовка символов


Автор: jaAlex 20.10.2006, 18:07
Помогите, пожалуйста, решить такую задачку: нужно в графическом режиме 320x200 256 цветов нарисовать буковку "К" так, что ее высота 100 (50 сверху, 50 снизу), толщина 25, и полукруглые очертания. Желательно с примером. Заранее спасибо всем откликнувшимся.
P.S. Я насколько знаю, делается это прорисовкой по пикселам. Дк каждую линию отдельно прорисовывать чтоли?

Автор: makwen 20.10.2006, 19:30
код для установки режима 320х200 256 цветов:
Код

mov ah,00h
mov al,013h ; 13h - код требуемого  режима
int 10h


используй функцию 0Ch прерывания INT 10h, которая рисует пиксель.
Пример:
Код

mov ah,0Ch
mov al,03h ; цвет пикселя
mov bh,0 ;номер страницы
mov dx,10 ; вертикальная координата
mov cx,20 ; горизонтальная координата
int 10h

Создавай циклы и прорисовуй свою букву "К"!  smile 
Удачи! 

Автор: jaAlex 20.10.2006, 19:51
А как циклы - то создавать? Вот, к примеру, в твоем втором коде как сделать так, чтобы dx увеличивалась с 50 до 75? И еще такой вопрос: как задать условие типа if...then? Ну, все в том же коде надо так: когда dx=75, то прибавить к cx 1 и чтобы dx опять стала равна 50. Ну и снова цикл пошел, разумеется. Как вот все это, подскажи пожалуйста.

Автор: makwen 20.10.2006, 20:00
мда... я думаю, что за один пост не смогу описать синтаксис языка Assembler. Так что бери любую книгу по асму, и читай, там все ясно написано! 
Например Питер Абель "Ассемблер. Язык и программирование для IBM PC"

Автор: anwe 20.10.2006, 21:21
Даю наводку. Заметь слово пишеться слитно, тот есть не даю на выпивку!  smile 
Для примера - код, выводящий вертикальную составляющую буквы "К"
Код

mov    ax,13h    ;перевод в нужный видеорежим
int    10h
mov    ah,0Ch
mov    dx,50
mov    cx,50
mov    al,100b
int    10h    ;то что писал makwen
mov    bx,49    ;здесь счетчик строк
mov    di,5    ;здесь счетчик колонок
;собственно цикл в цикле: внутренний выводит вертикальную линию
;внешний выводит таких линий 5 штук.
l2:
inc    dx
int    10h
dec    bx
jns    l2    ;это цикл для вывода вертикальной линии
mov    dx,49
inc    cx
mov    bx,50
dec    di
jns    l2
;цикл для выхода из программы по нажатию клавиши
l1:
mov    ah,06h
mov    dl,0FFh
int    21h    ;считать символ
jz    l1    ;если ZF=0 - клавиша нажата - выход
mov    ax,0003h
int    10h
ret

Остальное, таким же способом, додумывай сам.
Можно еще посоветовать, чтобы было легче расчитать букву, сделай сначала ее на бумаге и просчитай координаты граничных точек.
Лучше сначала прорисовать верхнюю линию буквы, потом нижнюю.
Там надо за раз менять и di и bx.

То есть не то хотел сказать. Хотел сказать, что надо отдельно прорисовывать верхнюю линию, потом нижнюю. Так не то, что надо, так просто удобней.

Автор: jaAlex 20.10.2006, 22:11
Код

program K;
begin
asm
  mov  ax,0013h
  int  10h
end;
asm
  mov  ax,0A000h
  mov  es,ax
  mov  bx,50
  mov  si,0
@@OutLines:
  mov  ax,320
  mul  bx
  add  ax,10
  mov  di,ax
  mov  cx,25
  @@OutLine:
      mov  byte ptr es:[di],15
      inc  di
      dec  cx
      cmp  cx,0
      jnz  @@OutLine
  add  bx,1
  inc  si
  cmp  si,100
  jb  @@OutLines
end;
asm
  mov  ax,0A000h
  mov  es,ax
  mov  bx,50
  mov  si,0
@@OutLines:
  mov  ax,319
  mul  bx
  add  ax,110
  mov  di,ax
  mov  cx,25
  @@OutLine:
      mov  byte ptr es:[di],15
      inc  di
      dec  cx
      cmp  cx,0
      jnz  @@OutLine
  add  bx,1
  inc  si
  cmp  si,50
  jb  @@OutLines
end;
asm
  mov  ax,0A000h
  mov  es,ax
  mov  bx,100
  mov  si,0
@@OutLines:
  mov  ax,321
  mul  bx
  add  ax,-88
  mov  di,ax
  mov  cx,25
  @@OutLine:
      mov  byte ptr es:[di],15
      inc  di
      dec  cx
      cmp  cx,0
      jnz  @@OutLine
  add  bx,1
  inc  si
  cmp  si,49
  jb  @@OutLines
end;
asm
  mov  ah,0
  int  16h
end;
asm
  mov  ax,0003h
  int  10h
end;
end.

Вот такая буковка получилась. Но что - то какая - то она некрасивая smile . В чем тут косяк, как бы ее получше здесь вот отрисовать? 
anwe, с твоим кодом не разобрался пока, только напортачил - TP повис, и все...

Автор: jaAlex 20.10.2006, 23:20
Код

program TEST;
begin
 asm
 mov ax,$13
 int 10h
end;
asm
 mov ax,$A000
 mov es,ax
 mov al,15
 mov cx,25
 mov bx,16020
 @1:
 mov [es:bx],al
 add bx,1
 loop @1
end;
asm
 xor ah,ah
 int 16h
end;
end.


Вот код программы, которая рисует линию. Я хочу, чтобы таких линий было 100, и чтобы они были друг под другом. Для чего делаю так:

Код

program TEST;
begin
 asm
 mov ax,$13 
 int 10h
end;
asm
 mov ax,$A000
 mov es,ax
 mov al,15
 mov cx,100
 @2:
 mov cx,25
 mov bx,16020
 @1:
 mov [es:bx],al
 add bx,1
 loop @1
 add bx,320
 loop @2
end;
asm
 xor ah,ah
 int 16h
end;
end.


Помоему, все правильно, но программа виснет, и не воспринимает нажатия никаких кнопок с клавиатуры. Цикл в цикле неправильно делаю, чтоли, а может еще чего.  Что тут не так? Почему виснет? Подскажите плз!!! Заранее спасибо всем откликнувшимся.

Автор: anwe 21.10.2006, 00:34
Цитата

anwe, с твоим кодом не разобрался пока, только напортачил - TP повис, и все... 

Не знаю, что там можно напортачить. Ну да ладно.
В твоем последнем коде 3 ошибки.
1. Не верно указан адрес ячейки памяти в видеопамяти. Не там стоит скобка. Вместо
Код

mov [es:bx],al

надо
Код

mov es:[bx],al


2. Не верный цикл в цикле.
Код

 mov cx,100
 @2:
 mov cx,25

Не верное использование регистра cx. Второй цикл начнется с нулевым его значением. Для этого нужно использовать либо стек, где хранить cx для внешнего цикла, либо другой регистр. Использование стека в цикле -  smile Поэтому используй другой регистр:
Код

 mov  di,100      ;счетчик внешнего цикла
 @2:
 mov cx,25
mov bx,16020
@1:
 mov es:[bx],al
 add bx,1
 loop @1
 add bx,320
dec  di
jnя  @2


3. Я тебе предложил функцию DOS, которую правильнее использовать для целей выхода по нажатию клавиши. Выбранная тобой функция BIOS имеет другие цели. Ну да ладно. Не это главное.
Главное то, что для выхода при нажатии надо же ведь проверять результат!!! Для твоей функции надо проверять содержимое ah:
Код

@3:
 mov ah,0
 int 16h
test  ah,ah
je  @3


И напоследок 2 примечания.
1) При выходе в DOS лучше перевести видеорежим в текстовый:
Код

mov  ax,03h
int  10h


2)У тебя не прорисует толстую линию, так как при каждом внешнем цикле bx получает значение 16020. Его надо вынести за пределы внешнего цикла.

Автор: jaAlex 21.10.2006, 01:17
Код

program TEST;
begin
asm
  mov  ax,0013h
  int  10h
end;
asm
  mov  ax,0A000h
  mov  es,ax
  mov  bx,50
  mov  si,0
@@OutLines:
  mov  ax,320
  mul  bx
  add  ax,10
  mov  di,ax
  mov  cx,25
  @@OutLine:
      mov  byte ptr es:[di],15
      inc  di
      dec  cx
      cmp  cx,0
      jnz  @@OutLine
  add  bx,1
  inc  si
  cmp  si,100
  jb  @@OutLines
end;
asm
  mov  ax,0A000h
  mov  es,ax
  mov  bx,50
  mov  si,0
@@OutLines:
  mov  ax,319
  mul  bx
  add  ax,110
  mov  di,ax
  mov  cx,25
  @@OutLine:
      mov  byte ptr es:[di],15
      inc  di
      dec  cx
      cmp  cx,0
      jnz  @@OutLine
  add  bx,1
  inc  si
  cmp  si,50
  jb  @@OutLines
end;
asm
  mov  ax,0A000h
  mov  es,ax
  mov  bx,100
  mov  si,0
@@OutLines:
  mov  ax,321
  mul  bx
  add  ax,-88
  mov  di,ax
  mov  cx,25
  @@OutLine:
      mov  byte ptr es:[di],15
      inc  di
      dec  cx
      cmp  cx,0
      jnz  @@OutLine
  add  bx,1
  inc  si
  cmp  si,49
  jb  @@OutLines
end;
asm
  mov  ah,0
  int  16h
end;
asm
  mov  ax,0003h
  int  10h
end;
end.


Вот такая буковка "К" у меня получилась. По - моему, нормально.
И вот у меня такой еще вопрос появился. Вот линия:

Код

asm
  mov  ax,0A000h
  mov  es,ax
  mov  bx,50
  mov  si,0
@@OutLines:
  mov  ax,319
  mul  bx
  add  ax,110
  mov  di,ax
  mov  cx,25
  @@OutLine:
      mov  byte ptr es:[di],15
      inc  di
      dec  cx
      cmp  cx,0
      jnz  @@OutLine
  add  bx,1
  inc  si
  cmp  si,100
  jb  @@OutLines
end;


А как сделать ее такой, чтобы ее угол наклона был меньше, т.е.  вот чтобы каждая следующяя линия сдвигалась налево не на 1 пиксель, а, скажем, на 0.5?

Автор: anwe 21.10.2006, 01:40
Цитата
Вот такая буковка "К" у меня получилась. По - моему, нормально.

Нормально.

Цитата
чтобы каждая следующяя линия сдвигалась налево не на 1 пиксель, а, скажем, на 0.5?
 Полпикселя - этот класс  smile Делай сдвиг влево на 1, а вверх - на 2 (3, 4...). (Посмотри на линию секундной стрелки часов, что внизу справа.) Только линия будет уже не линией - ступенькой. Если надо сгладить - повышай разрешение экрана.

Автор: jaAlex 21.10.2006, 05:48
Цитата(anwe @  21.10.2006,  01:40 Найти цитируемый пост)
 Если надо сгладить - повышай разрешение экрана.

А как можно повысить разрешение? 
И еще: как задать пропорцию? Я еще до этого думал, что пропорция какая - то должна быть, посчитал так, чтоб линию из угла экрана в угол наискосок пропорция 5/8 выходит. Но где ее задать - незнаю. И как задать тоже незнаю. Если не составит труда, подскажи пожалуйста.

Автор: anwe 21.10.2006, 11:45
Установи SVGA режим. Здесь техника такая.
Так как одного сегмента DOS для всего изображения в SVGA режиме недостаточно, необходимо перемещать окна (так называемые банки) видео памяти. Делает это функция BIOS $4F.
Вобщем давай так. Вот тебе пример, где прорисована линия на экране с разрешением 640х480. Выход из программы - по нажатию клавиши. Попробуй сам разобраться, у меня сейчас нет времени. Если что - позже.
Вот код:
Код

var
buf    db    100h dup(?)
;-----------------------------------
mov    ax,4F01h
mov    cx,111h
mov    di,offset buf
int    10h
mov    ax,4F02h
mov    bx,111h
int    10h
push    word ptr [buf+08h]
pop    es
mov    dx,4
xor    bx,bx
call    dword ptr [buf+0Ch]
mov    di,44416
mov    ax,0FFFFh
mov    cx,100h
@2:
mov    es:[di],ax
inc    di
loop    @2
@1:
mov    ah,06h
mov    dl,0FFh
int    21h
jz    @1
mov    ax,0003h
int    10h

Автор: jaAlex 21.10.2006, 22:04
Код

program TEST;
var
buf    db    100h dup(?)
begin
{ Здесь устанавливаем графический режим 640х480}
asm
mov    ax,4F01h
mov    cx,111h
mov    di,offset buf
int    10h
mov    ax,4F02h
mov    bx,111h
int    10h
push    word ptr [buf+08h]
pop    es
mov    dx,4
xor    bx,bx
call    dword ptr [buf+0Ch]
end;
{Здесь отрисовываем линию}
asm
mov    di,44416
mov    ax,0FFFFh
mov    cx,100h
@2:
mov    es:[di],ax
inc    di
loop    @2
@1:
mov    ah,06h
mov    dl,0FFh
int    21h
jz    @1
end;
{Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
asm
mov    ax,0003h
int    10h
end;
end.


Вроде разобрался. Но вот это у меня TP никак воспринимать нехочет, ругается сильно:

Код

var
buf    db    100h dup(?)


Я что только уж не делал, никак не хочет. Как тут вот поступить надо? В коде вроде бы разобрался, но получается разрешение, по - моему, не 640х480, а 640х400, ведь разрешение стандартного графического режима 320х200, а мы его увеличиваем с угла. Вот с разрешением еще пока не разобрался.

Автор: anwe 21.10.2006, 22:15
Переменную надо объявлять так:
Код

var
buf:array [0..100] of byte;


Цитата
 по - моему, не 640х480, а 640х400 


Не, здесь тупое умножение на коэффициент не правильно. А как же быть, по-твоему, с другими разрешениями, к примеру 800х600?

Автор: jaAlex 22.10.2006, 23:43
Тут сразу уйма вопросов возникла по поводу этого графического режима. Но не буду тебя грузить, и так достал уже наверно...
Но все же, ответь пожалуйста еще на парочку вопросов. Вот наклонная линия:

Код

program TEST;
begin
 asm
 mov ax,$13
 int 10h
end;
asm
 mov ax,$A000
 mov es,ax
 mov al,15
 mov di,50
 mov bx,16820
 @2:
 mov cx,25
 @1:
 mov [es:bx],al
 add bx,1
 loop @1
 add bx,616
 dec di
 jnz @2
end;
asm
 xor ah,ah
 int 16h
end;
end.


Но почему - то она как зебра. Точнее даже я примерно предполагаю почему она такая, но сделать ее не в полосочку никак не получается. Помоги пожалуйста исправить мои ошибки и нарисовать ее нормально, не в полосочку. Заранее большое спасибо.

P.S. Угол наклона именно такой вот должен быть, это я буковку "А" нарисовать пытаюсь.

Автор: anwe 23.10.2006, 23:59
Цитата
Но не буду тебя грузить, и так достал уже наверно...
Нет, иначе я бы здесь не сидел.
Но есть "но". Такую ошибку, а скорее недочет ты бы и сам нашел. Это же элементарно. Пробуй! Программирование - наука экспериментальная.

У тебя разрешение 320х200, что значит 320 точек в  строке, а строк 200. Нас сейчас интересует количество точек в строке. Ты добавляешь 616 и перескакиваешь через строку: 320*2=660 плюс наклон и минус длина линии. А ты сделай тоже, но в следующей строке: 320-25 (длина линии) + 1 (смещение для наклона).

Но тогда, возможно, изменится наклон. Проверь. Скорее всего да. Сейчас, просто поздно  smile 
Если так, тогда оставляй все как есть, но прорисовывай две линии. То есть прямо в цикле делай так:
Код

...
 mov es:[bx],al
 mov es:[bx+320],al
 add bx,1
...
 понатно, что 320 - это переход на следующую линию строго под первой.
Тогда у тебя, как бы утолщится каждая линия и они дожны слиться воедино. И наклон не должен изменится.
Вот тебе два варианта.

Автор: jaAlex 31.10.2006, 01:23
anwe, большое спасибо за помощь. В итоге я почитал тут умные книжки и сделал все заливкой, с закругленными краями. Ну, в общем, красиво.

Автор: anwe 31.10.2006, 14:17
А полюбоваться можно? прикрепи, если не сложно, результат.

Автор: jaAlex 3.11.2006, 01:36
Цитата(anwe @  31.10.2006,  14:17 Найти цитируемый пост)
А полюбоваться можно? прикрепи, если не сложно, результат.


Вот только сделаю еще парочку фишек с книжки и выложу. Ну, в общем, скоро будет.

Автор: jaAlex 14.11.2006, 11:32
Код

Program KAA;
Var Chessfill: word;

Procedure figure ( K1,K2, H, kl1, kh1, kl2, kh2, al1, ah1, al2, ah2: word);assembler;
asm
  mov ax,0A000h
  mov es, ax
  cld
  mov di, K1
  mov si, K2
  mov ax, di
  mov bx, 320
  xor dx, dx
  div bx
  mov Chessfill, ax
  xor dx, dx
  xor bx, bx
  mov al, 13
  mov cx, H
@l: push cx
  push di
  mov ax, cx
  add ax,di
  add ax, Chessfill
  mov cx, si
  sub cx, di
  jnc @nc
  neg cx
  std
@nc:  shr ax, 1
  sbb ax,ax
  not ah
  and ax, $0A0A
@l2:  stosb
  xchg ah, al
loop @l2
  rep stosb
  pop di
  add dx, kl1
  adc di, kh1
  add bx, kl2
  adc si, kh2
  mov cx, al1
  add kl1, cx
  mov cx, ah1
  adc kh1, cx
  mov cx, al2
  add kl2, cx
  mov cx, ah2
  adc kh2, cx
  pop cx
  loop @l
end;

begin
asm
  mov ax, 13h
  int 10h
end;

figure(10*320+20,10*320+40,100,0,320,0,320,0,0,0,0);
figure(50*320+40,50*320+60,60,42768,320,0,321,65536-595,65536-1,65536-1192,65536-1);
figure(10*320+55,10*320+75,40,42768,319,0,320,65536-795,65536-1,65536-1192,65536-1);
figure(60*320+120,60*320+130,80,42768,319,0,320,0,0,0,0);
Figure(60*320+153,60*320+163,80,0,320,65536-42768,320,0,0,0,0);
figure(40*320+130,40*320+150,20,32768,319,0,321,65536-121,65536-1,65536-2126,65536-1);
figure(95*320+130,95*320+153,20,65536-1986,319,0,320,0,0,0,0);
figure(100*320+225,100*320+235,80,42768,319,0,320,0,0,0,0);
figure(100*320+255,100*320+265,80,0,320,65536-42768,320,0,0,0,0);
figure(80*320+235,80*320+252,20,32768,319,0,321,65536-121,65536-1,65536-2126,65536-1);
figure(130*320+235,130*320+255,20,65536-1986,319,0,320,0,0,0,0);

asm
  xor ah,ah
  int 16h
  mov ax, 3
  int 10h
end;

end.


Долго не отвечал, занят был... В общем, вот что у меня получилось. Шахматная однобайтовая заливка. А написаны мои инициалы. По - моему, нормально получилось.

Автор: anwe 14.11.2006, 18:57
Ну ты и приколист!  smile 
Только у букв "А" сверху не хватает по одной линии справа. Присмотрись.

Автор: jaAlex 16.11.2006, 23:20
anwe, дк на скорую руку делал... Еще хотел спросить, как сделать заливку этих буковок таким же способом, но 4 - байтовой заливкой???

Автор: anwe 20.11.2006, 01:24
При 4-байтовой байт 0 содержит значение синего цвета, 1 - зеленого, 2 - красного, 3 - резервный. И еще при разрешении 320х200 это номер функции... забыл  smile , блин, или 10E или 10F, кажется.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)