Помощь - Поиск - Пользователи - Календарь
Полная версия: Tutorial.Temp
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ассемблер > Избранное
Страницы: 1, 2
AlaRic
Цитата
смотриhttp://forum.pascal.dax.ru/?board=links;action=display;num=1058013615;start=0#0

Вижу...все заканчиваем с флеймом!
Dark
Я очень извиняюсь !mol1.gif так как сначало практика, затем сессия, => Отлучение от Internet затем работа а затем поломка аппаратуры( конкретно модема) :'( но я щас из клуба, надеюсь здесь не сломается ;D ЛОВИТЕ. КОМЕНТИРУЙТЕ.
Dark
Се начнем повесть сию...   ;D

Итак, уважаемые, позвольте мне представить мой туториал №1.

Он посвящен основам программирования графики на паскалевском ассемблере,и предназначен для тех, кого достала тормознутость графики на пасе (а работать с графикой с его процедурами я бы не советовал...), кто хотел бы написать БЫСТРУЮ игру, да и для тех, кому вообще интересен asm.
 
Внимание: Более-менее непонятные термины будут объясняться в глоссарии(в конце туториала).

Данные эксперименты не совсем совместимы с библиотечкой Graph, поэтому крайне нежелательно ее подключать. Конкретнее, Graph не признает вручную(без использования процедуры InitGraph) включенный режим, и не будет с ним работать.

Данный документ писался для людей с разной степенью подготовки, и поэтому здесь могут разбираться слишком элементарные вещи.

Для использования примеров вам необходима карточка VGA(хе хе, сейчас это любой видеоадаптер), поддерживающая режим 320*200, TP версии 7.0, и желание разобраться.

Начну с благодарностей: спасибо моей маме, моим учителям, авторам интересной литературы, этому форуму, лично Gluck'у и Shadow. ПРЕОГРОМНОЕ спасибо!!!

В этой, первой,(и, надеюсь, не последней) части я расскажу о том, как врубить режим 320*200*256цв., и как с ним начать работать. Этот режим в литературе можно втретить под названием MCGA-режима. (Multi Color Grafic Adapter).

Он имеет номер 13 в шеснацатеричной системе счисления или 19 в десятичной. В дальнейшем  16-теричный вид будет отмечаться буквой h или символом $ (Например 13h=$13) а десятичный отмечатся не будет (19).

Несколько общих моментов:

Начиная со стандарта VGA, видеопамять реализована в виде адресного пространства, доступ к которой возможен при помощи одной команды, тогда как для стандартов EGA и CGA характерна сложная организация видеопамяти, где простая операция записи в нее или чтения из нее невозможна, для этого требуется около десятка команд и необходимо работать с портами.

Видеобуфер реализован в виде ЛИНЕЙНОГО пространства,т.е. видеокарточка не понимает что такое координаты (представте себе одномерный массив).

1. В режиме 13h задействуется один байт памяти на одну точку, т.е. 8 бит.

2. Раз на каждую ячейку памяти приходится одна точка, то формула для рисования точки по координатам х,у выглядит так:
P(x,y)= x+y*(MaxX+1) (В нашем случае MaxX будет 319 т.е. P(x,y)=x+y*320)

3. Раз используем 8-битный (однобайтный) режим, то мы можем работать с 256 цветами (в отличие от 16 цветов в пасе)!!!!!!!!!

4. Адрес видеопамяти, начиная с которого изображение в графических режимах выводится на монитор, равен 0A000:0000h. следующие 64000 (320*200) байт в данном режиме как раз и выводятся на экран.

5. Для закрытия графического режима 13h я буду использовать текстовый режим 3(80*25*16)
 
Ну так вот, для того, чтобы менять режимы будем использовать функцию BIOS установки режима:  

------------------------------------------------------------------------
Установка видеорежима(прерывание 10h):  
На входе:  
  ah=00h ; Установить режим  
  al=   ; Номер режима  

Используемые регистры: ax.
------------------------------------------------------------------------
 
В нашем случае:

------------------------------------------------------------------------

procedure Set13h;
begin  
asm  
  mov ah,00h  ; Установить режим  
  mov al,13h ; Номер режима 320*200*256цв  
  int 10h     ; Номер прерывания видеокарточки
end;  
end;  

------------------------------------------------------------------------

------------------------------------------------------------------------

procedure Close13h;  
begin  
asm  
   mov ah,00h  ; Установить режим  
   mov al,03h ; Текстовый режим 80х25х16цв  
   int 10h  ; Номер прерывания
end;  
end;  

------------------------------------------------------------------------
 
Хорошо, вот мы и попали в режим 320*200*256 - возможно, скажете вы, - но стандартные средства паскаля использовать не рекомендуют, так что же нам здесь делать?  
 
Ну... для начала давайте покрасим экран в какой-нибудь цвет:

Это очень просто: адрес нам известен - $A000:0000, следующие 64000 байт - наш экран, поэтому этим 64000 байт просто присваиваем номер нужного нам цвета...

------------------------------------------------------------------------

procedure clscr(col:byte);  
begin  
 asm
   mov ax,0A000h
   mov es,ax
   xor di,di  
   mov al,[col]  
   mov cx,64000  
@l1:
   mov byte ptr es:[di],al
   inc di
loop @l1
 end;  
end;  


Используемые регистры: ax,es,di,cx.
------------------------------------------------------------------------

Итак, введя этот код вы получите процедуру закраски экрана.  
А теперь, давайте я расскажу о ней поподробнее...  
 

   mov ax,0A000h  
   mov es,ax   {es=$A000}
   xor di,di   {di=0}

 
Тремя этими командами мы помещаем в связку регистров es:di адрес видеопамяти.
 

mov al,[col]  

 
Здесь я помещаю в al номер цвета закраски фона.  
 

mov cx,64000  
@l1:
   mov byte ptr es:[di],al
   inc di
loop @l1


Команда цикла loop повторяет команды,находящиеся между меткой(@l1) и самой командой. Количество повторов помещается в регистр CX.

Команда пересылки mov записывает байт из регистра al в ячейку памяти по адресу es:di

И, наконец, команда inc увеличивает di на 1, тем самым обеспечивая перемещение по пространству памяти.

Есть специальная команда, которая сразу выполняет за нас работу по пересылке байта из al в ячейку памяти es:[di] и инкрементации di - НА СЦЕНУ ПРИГЛАШАЕМ КОМАНДУ STOSB.
И ВОТ ОНА - ВОЛШЕБНАЯ!!!!!!!!! Таким образом мы можем заменить две команды


   mov byte ptr es:[di],al
   inc di


на одну


   stosb

     
   
т.е. смотрите -

   mov cx,64000  
@l1:
   stosb
loop @l1


Если посмотреть в умную книжку по ассемблеру, то можно увидеть что есть и другой цикл - rep, и с ним наша программа будет выглядеть еще элегантнее -

   mov cx,64000  
   rep stosb


Я немного извиняюсь :-[, но это все что я сделал в первом туториале, но надеюсь что это еще не все, и я перейду в такой режим работы над туториалами, когда я смогу давать больше материала и по качеству гораздо лучше ;D; несомненно есть много людей, которые намного лучше меня во всем этом разбираются, но и у меня все впереди... Я НЕ ВОЛШЕБНИК, Я ТОЛЬКО УЧУСЬ!!!
:-[Извините если слишком всего много или наоборот мало. :-[
До новых встреч.

Заключительный Пример:  

uses crt;  
 
procedure clscr(col:byte);  
begin  
 asm  
   mov ax,0a000h
   mov es,ax
   xor di,di  
   mov cx,64000  
   mov al,col  
@l1:
   mov byte ptr es:[di],al
   inc di
loop @l1
 end;  
end;  

procedure clscr1(col:byte);  
begin  
 asm  
   mov ax,0a000h
   mov es,ax
   xor di,di  
   mov cx,64000  
   mov al,col  
@l1:
   stosb
loop @l1
 end;  
end;  
 
procedure initgr;  
begin  
asm  
 mov ax,0013h  
 int 10h  
end;  
end;  
 
procedure closegr;  
begin  
asm  
 mov ax,0003h  
 int 10h  
end;  
end;  
 
begin  
randomize;  
initgr;  
repeat
 clscr(random(255));
until keypressed;
readkey;  
repeat
 clscr1(random(255));  
until keypressed;
readkey;  
closegr;  
end.  


Happy codding!!!!!!!!!!!!!

Анекдот напоследок: Стоят два хакера и ругаются на ассемблере... ;D

Глоссарий.

1.Команда mov устроена таким образом, что она может пересылать данные из регистров или памяти в регистр или память, но у нее следующие исключения и возможности:

  Запись вида mov ax,bx обозначает пересылку значения из регистра bx в регистр ax
  Запись вида mov ax,[bx] обозначает пересылку значения из ячейки памяти по адресу
  ds:[bx] в регистр ax

  Иногда необходима пересылка с указанием типа, т.к. в некоторых случаях компилятор может непонять, что имеется в виду: пересылка слова или байта : mov ax,[bx]
     для этого используют специальный оператор указания типа ptr:

     mov ax,byte ptr [bx]   - пересылка байта
     mov ax,word ptr [bx]   - пересылка слова


А. Нельзя передавать значение одного сегментного регистра в другой:

mov es,ds


Б. Нельзя с ее помощью записать в сегментный регистр значение из памяти или константу:

mov es,0A000h
или
mov es,[seg].


В. Нельзя передавать значение из одной области памяти в другую:

mov es,ds
[/color=Blue]

Г. В качестве первого оператора не может выступать сегментный регистр cs:
[color=Blue]
mov cs,ax.


В случаях А,Б и В нужно использовать промежуточный объект - регистр или стек:

mov ax,[seg]   или   push [seg]         push ds
mov es,ax            pop es      ;      pop  es

2. Стек - область памяти, специально выделенная для временного хранения работы программы. По принципу доступа он реализован в виде LIFO - последний пришел - первый ушел (Last in First Out).Команды для работы с ним:

push [что] - сохранить в стеке
pop [куда] - восстановить из стека


Пример:

push ax
pop bx


Помните: вытаскивайте в обратном порядке сохранения в стек:

push ax
push bx
push cx
 ...
pop cx
pop bx
pop ax


Возможно сразу сохранение всех регистров:
pusha - сохраняет ax,cx,dx,bx,sp,bp,si,di
popa - востанавливает di,si,bp,sp,bx,dx,cx,ax

3.
 В ПК термином "адрес" обозначают разные вещи. Часто под адресом понимается
16-битовое смещение (offset) - адрес ячейки,отсчитанный от начала сегмента
(области) памяти,  которому принадлежит эта ячейка. В этом случае под адрес
отводится слово памяти.
 В другом случае под "адресом" понимается 20-битовый абсолютный адрес
некоторой ячейки памяти. В силу ряда причин в ПК такой адрес зада-
ется не как 20-битовое число, а как пара "сегмент:смещение", где "сег-
мент" (segment) - это первые 16 битов начального адреса сегмента памяти,
которому принадлежит ячейка,  а "смещение" - 16-битовый адрес этой
ячейки,  отсчитанный  от  начала  данного  сегмента  памяти  (величина
16*сегмент+смещение  дает абсолютный адрес ячейки).  Такая пара записы-
вается в виде двойного слова: в первом слове размещается смещение,
а во втором - сегмент.

(Язык макроассемблера для IBM. Составитель В.Н.Пильщиков (МГУ, ВМК) 1992г ) -

Электронная версия, кому надо - дам...

Всего хорошего...
Dark
Извиняюсь за огрехи с цветом - время заканчивается...

На тему ассемблер по темам - я так и собирался, взялся за графику т.к. именно через нее начал изучать ассемблер...

И еще раз простите за такую тягомотину со временем... Спасибо Alesha_GA за информацию...

Я уже стараюсь со вторым туториалом... когда выйдет - уже боюсь предсказывать... ;D
___ALex___
абсолютно верно как-то Gluck тебе сказал - если тему какую-то затрагиваешь - то объясняй её популярно или вообще не затрагивай вот к примеру говоришь что mov cs, 7 нельзя, так а как можно?!
___ALex___
и пора уже второй было выкладывать, первый уже все видели
а корректировать можно бесконечно
Dark
На тему именно cs:

Г. В качестве первого оператора не может выступать сегментный регистр cs:
mov cs,ax

Это значит, что этого не может быть никогда, т.к. CS:IP - текущий адрес выполняемой команды, т.о. изменяя CS или IP мы получаем процедуру прыжка на другую команду, а зачем это надо, если есть стандартные...?!!!

На тему второго туториала: УЖЕ ПРОХОДИТ СТАДИЮ ОТЛОВА БЛОХ, т.е. почти завершен.
___ALex___
"CS:IP - текущий адрес выполняемой команды"
это на самом деле НЕ так
Shadow
Цитата
"CS:IP - текущий адрес выполняемой команды"
это на самом деле НЕ так

т.е. как это везде написано что ето так да открой любой дебуг наконец
___ALex___
не ТЕКУЩЕЙ, а СЛЕДУЮЩЕЙ команды
поэтому, к примеру, в команде jmp смещение и отсчитывается от следущей за jmp командой до метки
Shadow
:D
-=-=-=
следующей слудующей
=-=-=-=-
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.