Поиск:

Ответ в темуСоздание новой темы Создание опроса
> ASM - с чего начать? 
:(
    Опции темы
Chingachguk
Дата 12.6.2003, 00:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1232
Регистрация: 25.3.2002
Где: Москва

Репутация: 11
Всего: 18



Цитата

.286
VectorKeyboard equ 09h
HotKey        equ 1208h ; alt+Scroll Lock, 0208h - left alt
Color          equ 45    ; Color Of Frame
text segment byte public
assume cs:text,ds:text
org  100h
begin:
; Go to ini part
  jmp  @@InitWatcher
@@NewInt09Handler:
  pusha
  push ds
  push es
  push cs
  pop  ds
  MOV  AX,40h
  MOV  ES,AX
  xor  bx,bx
  MOV  AX,ES:[0017h]
  and  ax,HotKey ; AND  AL,3
  cmp  ax,HotKey ; CMP  AL,3
  JNZ  @Exit
  XOR  TESTT,1
  JZ  @@RestoreScreen
  pusha
  push ds
  pop  es
  push 0b800h
  pop  ds
  xor  si,si
  mov  di,offset SavePage
  mov  cx,80*25
  cld
  rep  movsw
  push cs
  pop  ds
  popa
  MOV  BH,Color
  jmp  @@DisplayFrame
@@RestoreScreen:
  pusha
  push 0b800h
  pop  es
  mov  si,offset SavePage
  xor  di,di
  mov  cx,80*25
  cld
  rep  movsw
  popa
@@DisplayFrame:
  MOV  AX,1001h
  INT  10H
  call Sound
@EXIT:
  PUSHF
  CALL DWORD PTR OLD_9H
  pop  es
  POP  DS
  popa
  IRET
; Sound proc
Sound Proc near
  pusha
  mov  al,0B6H
  out  43h,al
  MOV  AX,0110dH
  OUT  42H,AL
  MOV  AL,AH
  OUT  42H,AL
  IN    AL,61H
  OR    AL,3
  OUT  61h,AL
  xor  CX,CX
@Wait: 
  loop  @Wait
  and  AL,11111100b
  OUT  61H,AL
  popa
  retn
Sound Endp
OLD_9H        dd ?
TESTT          db 0
SavePage      db 80*25*2 dup(?)
;
; Initialization part *********************************************************
;
@@InitWatcher:
  mov  dx,offset Start
  call @@Message
; Set keyboard handler
  mov  ax,(35H shl 8) + VectorKeyboard
  int  21h        ; Get old HookedVector to es:bx
  mov  word ptr OLD_9H,bx
  mov  word ptr OLD_9H+2,es
  mov  dx,offset @@NewInt09Handler
  mov  ah,25h
  int  21H        ; Set new Vector
; Terminate and stay resident
  mov  dx,offset @@InitWatcher
  int  27h
@@Message:
  mov  ah,09h
  int  21h
  retn
Start          db 'Start !',13,10,'$'
Text Ends
end begin



--------------------
I don't like the drugs (but the drugs like me). M.Manson.
PM MAIL ICQ   Вверх
Uchenik
Дата 25.6.2003, 02:12 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Chingochguk adv/51.gif ! Я прилежно исследовал первые 3 урока , сделал все домашние
задания и смиренно жду 4-й урок.















  Вверх
Chingachguk
Дата 25.6.2003, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1232
Регистрация: 25.3.2002
Где: Москва

Репутация: 11
Всего: 18



Хм. Я давно думал что-то написать в продолжение, вот только не решил, что именно. Смысл в том, что начальная теория, я считаю, изложена и далее должна идти практика. Практика позволит закрепить знания и улучшить технику. Вопрос в том, какая именно практика: порты ввода-вывода, работа с прерываниями, передача и получение параметров в/из ассемблерного кода из/в язык Паскаль (или Си) или вообще что-то типа написания кода загрузчика (MBR-сектор).

Вообщем, пишите Ваши пожелания - что именно Вы бы хотели узнать о Машине - и, возможно, мы сделаем это на языке ассемблера ;)


--------------------
I don't like the drugs (but the drugs like me). M.Manson.
PM MAIL ICQ   Вверх
vanya
Дата 10.7.2003, 07:39 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Помогите зарегистрированному Ламмеру с прогой Ассемблер!
  Вверх
Shuricksoft
Дата 11.7.2003, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 27.3.2002
Где: Odessa, Ukraine

Репутация: нет
Всего: нет



Chingachguk, вот я бы хотел изучить работу с внешними устройствами - объяснишь заодно и порты, и прерывания =) А потом бы хотел загрузчик. Вот тебе пожелания - надеюсь, ты их осуществишь в ближайшем времени, за что я тебе заранее благодарен wink.gif
PM MAIL ICQ   Вверх
Chingachguk
Дата 11.7.2003, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1232
Регистрация: 25.3.2002
Где: Москва

Репутация: 11
Всего: 18



О'кей ;)

Приянто к сведению ;)


--------------------
I don't like the drugs (but the drugs like me). M.Manson.
PM MAIL ICQ   Вверх
Baa
Дата 13.7.2003, 01:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2639
Регистрация: 12.4.2002
Где: Москва

Репутация: нет
Всего: 12



Shuricksoft, на wasm.ru сейчас идет серия статей про загрузчики...


--------------------
"Duty is everything; the greatest of joys, the deepest of sorrows" Aribeth de Tylmarande
PM ICQ   Вверх
Shuricksoft
Дата 13.7.2003, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 27.3.2002
Где: Odessa, Ukraine

Репутация: нет
Всего: нет



Baa, сенкс! Завтра гляну... Но всё равно Chingachguk forever :-)
PM MAIL ICQ   Вверх
Chingachguk
Дата 17.7.2003, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1232
Регистрация: 25.3.2002
Где: Москва

Репутация: 11
Всего: 18



Урок 4: прерывания.

Итак, в этом уроке мы попробуем "почувствовать" прерывания. Что такое
прерывания ?

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

Проанализируем ситуацию с точки зрения посторения программного кода. Иногда это называют странными словами "построить блок-схему", но мы ограничимся обывательским методом описания:

Основная процедура поиска:

Цитата

program MushroomsSerach;
{...}
repeat
  Широта:=ШиротаМоегоГорода+random(10/СколькоПиваВзялиССобой);
  Долгота:=ДолготаМоегоГорода+random(10/СколькоПиваВзялиССобой);
  Лес:=ВыбратьЛесДляПоиска(Широта,Долгота);
  if Лес.Выбран = True then
    begin
      for Лес.Грибы:=1 to Лес.ВсегоГрибов do
        begin
          if СправочникСъедобныхГрибовНеЗабыли:=True then
            {...}
    end;
until ПокаНеСтемнело;


Процедура обработки события "укусил комар":

Цитата

Procedure OnStingByInsect(ТочкаУкусаX,ТочкаУкусаY: word);
  begin
    НанестиУдарПоТелу(ТочкаУкусаX+random(10),ТочкаУкусаY+random(10));
  end;


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

Как же нам связать их в одну целую программу ? Ведь в любой момент
выполнения основной программы может быть нужно выполнить подпрограмму обработки кусания и безболезненно вернуться к выполнению основной.

Здесь нам на помощь приходят так назывемые "прерывания". Смысл в том,
что будет использован некий диспетчер, который будет по необходимости
вызывать ту или иную подпрограмму.

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

Цитата

uses crt; { we use keypressed and readkey function form this module }
const
  MyRandVal: word = 1;
  MyScreenCenter: word = 0;
  MaxBarSize = 20;
  MyScreenBarSize: word = 1;
  MyScreenColor: byte = 14;
var
  SaveOldHandler: pointer;
  CurrCoordinate: word;
  CurrColor: byte;
  IndX,IndY: word;
begin
  asm
  { Устанавливаем графический режим монитора, 320x200, 256 цветов }
  mov  ax,0013h
  int  10h

  { Устанавливаем обработчик прерывания 1Ch - таймер }
  { Сначала сохраняем старый обработчик }
  { Обратились к DOS за адресом старого обработчика }
  mov  ax,351Ch
  int  21h
  { Адрес старого обработчика вернулся в es:bx }
  { Запомним его }
  mov  word ptr SaveOldHandler,bx
  mov  word ptr SaveOldHandler+2,es

  { Зададим наш обработчик прерывания 1Ch }
  push ds { Сохранить регистр ds }
  mov  dx,offset @@OurHandlerOf1ChVector
  mov  ax,cs
  mov  ds,ax
  { Обратились к DOS, чтобы он установил новый обработчик }
  mov  ax,251Ch
  int  21h
  pop  ds { Восстановить регистр ds }

  { Обойдем обработчик прерывания и попадем в цикл ожидания клавиш }
  jmp  @@WaitForAnyKey

  { Наш обработчик прерывания 1Ch }
@@OurHandlerOf1ChVector:
  { В эту точку программы мы попадаем примерно 18 раз в секунду }
  { Выберем случайное число }
  { Но для обращения к ячекам памяти необходимо настроить сегментные регистры }
  { Например, для обращения к переменной MyRandVal }
  { Все используемые регистры необходимо сохранять ! }
  push es { Сохранить регистр es }
  push ax { Сохранить регистр ax }
  push dx { Сохранить регистр dx }
  mov  ax,seg @Data { Так в языке Паскаль можно получить СЕГМЕНТНЫЙ адрес }
  mov  es,ax { области данных (var + const) }
  { Умножаем ячеку памяти MyRandVal на число 16807 }
  mov  ax,16807
  mul  word ptr es:MyRandVal
  { dx:ax = MyRandVal * 16807 }
  { Запоминаем значение (MyRandVal * 16807) mod 2^16 в ячейке MyRandVal }
  mov  word ptr es:MyRandVal,ax
  { Инициализируем новое значение центра на экране }
  mov  word ptr es:MyScreenCenter,ax
  { Инициализируем начальное значение размера квадрата на экране }
  mov  word ptr es:MyScreenBarSize,1
  { Инициализируем новое значение цвета на экране }
  mov  byte ptr es:MyScreenColor,al
  pop  dx { Восстановить регистр dx }
  pop  ax { Восстановить регистр ax }
  pop  es { Восстановить регистр es }
  iret
@@WaitForAnyKey:
  end;
  { Цикл опроса клавиатуры ~ repeat until keypressed }
  repeat
    { Рисуем квадрат размером MyScreenBarSize с центром в MyScreenCenter }
    CurrColor:=MyScreenColor;
    for IndY:=1 to MyScreenBarSize do
      begin
        for IndX:=1 to MyScreenBarSize do
          begin
            CurrCoordinate:=MyScreenCenter+IndY*320+IndX;
            asm
            { Заносим в регистр es адрес видеопамяти - 0A000h }
            mov  ax,0A000h
            mov  es,ax
            { Рисуем точку с координатой CurrCoordinate и цветом CurrColor }
            mov  bx,ds:CurrCoordinate
            mov  al,CurrColor
            mov  byte ptr es:[bx],al
            end;
          end;
      end;
    { Увеличиваем текущий размер квадрата }
    inc(MyScreenBarSize);
    { Если размер стал более чем MaxBarSize }
    if MyScreenBarSize>=MaxBarSize then MyScreenBarSize:=1;
    { Проверяем кейбоард }
  until keypressed;
  { Считываем клавишу ~ readkey }
  readkey;
  asm
  { Восстановим старый обработчик прерывания 1Ch }
  { Адрес старого обработчика хранили в ячейке SaveOldHandler }
  { Получим его в ds:dx, ds сохраняем }
  push ds { Сохранить регистр ds }
  lds  dx,ds:SaveOldHandler
  { Обратились к DOS, чтобы он восстановил старый обработчик }
  mov  ax,251Ch
  int  21h
  pop  ds { Восстановить регистр ds }

  { Устанавливаем текстовый режим монитора }
  mov  ax,0003h
  int  10h
  end;
end.


Задания:

1. В приведенном коде попробовать отключить принудительное изменение
цвета или координаты начала квадрата;

2. Попробовать переписать код, рисующий квадраты, на ассемблере;

3. (Самое сложное !) изменить частоту принудительной смены параметров
отрисовки с большей на меньшую (например, 1 раз в секунду).



--------------------
I don't like the drugs (but the drugs like me). M.Manson.
PM MAIL ICQ   Вверх
Shuricksoft as a guest
Дата 11.9.2003, 23:02 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Hi! =)
Наконец-то у меня появилось свободное время и я взялся за урок! =) Спишу доложить результаты =)
Сделал задания 1 и 3 без проблем, за второе пока не брался, завтра займусь.
1. Отключить принудительное изменение координаты начала можно, убрав строку
mov word ptr es:MyScreenCenter,ax
Для цвета - строка
mov byte ptr es:MyScreenColor,al
3. Привожу изменённый кусок кода:
Код

...
var
...
i : word;
...
begin
asm
mov i, 1
...
@@OurHandlerOf1ChVector:
 { В эту точку программы мы попадаем примерно 18 раз в секунду }
 { Выберем случайное число }
 { Но для обращения к ячекам памяти необходимо настроить сегментные регистры }
 { Например, для обращения к переменной MyRandVal }
 { Все используемые регистры необходимо сохранять ! }
 push es { Сохранить регистр es }
 push ax { Сохранить регистр ax }
 push dx { Сохранить регистр dx }
 cmp i,19 {За секунду происходит 18 прерываний (изначально i=1), проверяем, прошла ли секунда}
 jnz @@NeNado {Если да, переходим на соответствующую метку}
 mov  ax,seg @Data { Так в языке Паскаль можно получить СЕГМЕНТНЫЙ адрес }
 mov  es,ax { области данных (var + const) }
 { Умножаем ячеку памяти MyRandVal на число 16807 }
 mov  ax,16807
 mul  word ptr es:MyRandVal
 { dx:ax = MyRandVal * 16807 }
 { Запоминаем значение (MyRandVal * 16807) mod 2^16 в ячейке MyRandVal }
 mov  word ptr es:MyRandVal,ax
 { Инициализируем новое значение центра на экране }
 mov  word ptr es:MyScreenCenter,ax
 { Инициализируем начальное значение размера квадрата на экране }
 mov  word ptr es:MyScreenBarSize,1
 { Инициализируем новое значение цвета на экране }
 mov  byte ptr es:MyScreenColor,al
 mov i,0
@@NeNado: {Сюда мы попадаем сразу, если i <> 19}
 inc i {Увеличиваем i}
 pop  dx { Восстановить регистр dx }
 pop  ax { Восстановить регистр ax }
 pop  es { Восстановить регистр es }
 iret
@@WaitForAnyKey:
 end;
...

Теперь вопросы. Что означает новый оператор lds и как используется? Как используется оператор mul? Почему MyRandVal умножается именно на 16807? Пока что всё...
P. S. Теперь буду стараться значительно чаще заходить сюда и учить уроки ассемблера =)
  Вверх
Shuricksoft as a guest
Дата 12.9.2003, 10:56 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











О, я даже чуть оптимизировал третье задание с утра =)
Как я понимаю, с регистрами работать намного быстрей и приятней, чем с переменными, поэтому...
Код

...
begin
asm
mov cl, 1
...
@@OurHandlerOf1ChVector:
{ В эту точку программы мы попадаем примерно 18 раз в секунду }
{ Выберем случайное число }
{ Но для обращения к ячекам памяти необходимо настроить сегментные регистры }
{ Например, для обращения к переменной MyRandVal }
{ Все используемые регистры необходимо сохранять ! }
push es { Сохранить регистр es }
push ax { Сохранить регистр ax }
push dx { Сохранить регистр dx }
cmp cl,19 {За секунду происходит 18 прерываний (изначально cl=1), проверяем, прошла ли секунда}
jnz @@NeNado {Если да, переходим на соответствующую метку}
mov  ax,seg @Data { Так в языке Паскаль можно получить СЕГМЕНТНЫЙ адрес }
mov  es,ax { области данных (var + const) }
{ Умножаем ячеку памяти MyRandVal на число 16807 }
mov  ax,16807
mul  word ptr es:MyRandVal
{ dx:ax = MyRandVal * 16807 }
{ Запоминаем значение (MyRandVal * 16807) mod 2^16 в ячейке MyRandVal }
mov  word ptr es:MyRandVal,ax
{ Инициализируем новое значение центра на экране }
mov  word ptr es:MyScreenCenter,ax
{ Инициализируем начальное значение размера квадрата на экране }
mov  word ptr es:MyScreenBarSize,1
{ Инициализируем новое значение цвета на экране }
mov  byte ptr es:MyScreenColor,al
xor cl,cl
@@NeNado: {Сюда мы попадаем сразу, если cl <> 19}
inc cl {Увеличиваем i}
pop  dx { Восстановить регистр dx }
pop  ax { Восстановить регистр ax }
pop  es { Восстановить регистр es }
iret
@@WaitForAnyKey:
end;
...

Сейчас займусь вторым заданием =) А вопросы остаются прежними...
  Вверх
Chingachguk
Дата 12.9.2003, 15:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1232
Регистрация: 25.3.2002
Где: Москва

Репутация: 11
Всего: 18



Хм... Первый вариант (теоретически) был верный (я насчет 1 раз в секунду). Во втором случае никто не гарантирует сохранение регистра CX на пути от приложения (основной код, рисующий прямоугольники) через обработчик прерывания BIOS к нашему обработчику прерывания и обратно. Кроме того, "не хорошо" менять в обработчике прерывания регистры "как угодно", если только это не предусмотрено специально (например, для передачи параметров и т.п.) Поясню на примере, почему это может быть неверно. Допустим, в машине работает только два куска кода:

; Прерывание
MyHandler:
; ...

; Основной код
MainCode:
; ...

Прерывание получает управление асинхронно, т.е. случайно во времени относительно выполнения MainCode - например, 20 раз в секунду.
Если теперь написать:

; Прерывание
MyHandler:
cmp cl,18
jb @@Skip
; ...
@@Skip:
inc cl

; Основной код
MainCode:
mov cl,0
@@MainCycle:
; We dont use CX here !
jmp @@MainCycle

То вроде все OK - и только прерывание меняет регистр внутри себя. На самом деле первым получает управление BIOS и картинка усложняется:

Приложение -> (прерывание)BIOS-код -> Твое прерывание->
Обратно в BIOS->Обратно в Приложение.

Например:

; Прерывание
MyHandler:
cmp cl,18
jb @@Skip
; ...
@@Skip:
inc cl

; BIOS
StartBIosInt8Handler:
; ...
; А вдруг BIOS тут использует CX ?
call MyHandler
; А вдруг BIOS тут использует CX ?
iret

; Основной код
MainCode:
mov cl,0
@@MainCycle:
; We dont use CX here !
jmp @@MainCycle

Но это не главное. Ведь вряд ли в реальном коде, который использует прерывания, можно обойтись без использования CX. Например, обработчик от таймера переодически опрашивает устройство, а основной код - это интерфес с кнопками. Поэтому гораздо проще сосредоточить внимание на небольшом коде обработчика нежели везде следить за тем, чтобы не юзать CX. А если ты используешь стандартные библиотеки Паскаля (СИ, etc ?).

Ну а первый вариант, как я говорил, верный.

Цитата

Теперь вопросы. Что означает новый оператор lds и как используется?


lds - это более краткий способ написать пару команд:

mov SEG_REGISTER,memory+2
mov USAL_REGISTER,memory

Например, такой случай: в памяти, доступной через es:[bx+20] лежат два слова: смещение и сегментный адрес, которые надо занести в регистры ds:dx:

mov dx,word ptr es:[bx+20]
mov ds,word ptr es:[bx+20+2]

С помощью lds это сделать проще:

lds dx,dword ptr es:[bx+20].

Существуют также команды les (es), lss (ss). Однако работа с сегментными регистрами уже остается только дос-приложениям или коду уровня ядра. Win32-код очень редко использует их. LDS является сокращением от ~"load pointer using DS".

Цитата

Как используется оператор mul? Почему MyRandVal умножается именно на 16807?


Оператор mul - это команда целочисленного умножения. Всегда умножается регистр AX или AL (в 32 битном коде - eax) на другой регистр или память:

mov ax,10
mov bx,10
mul bx ; В результате в паре dx:ax содержится unsigned long 100

mov al,10
mov bl,10
mul bl ; В результате в ax содержится unsigned short 100

MyVar db 10
; ...
mov al,10
mul byte ptr MyVar ; В результате в ax содержится unsigned short 100

Существуют также команды знакового умножения imul.

Почему умножение на 16807 ? Это довольно-таки от балды взятое число из генератора псевдослучайных чисел. Общий вид конгруэнтного генератора:

static unsigned long RandVal;

void RandSeed(void)
{
RandVal=time(NULL);
}

unsigned long Rand(void)
{
RandVal=RandVal*A+B;
return(RandVal);
}

Таким образом, следующее число генератора на i-м шаге равно:

RandVal[i+1]=(RandVal[i]*A+B) mod 2^32 (зависит от размерности ulong).

В моем случае я не делал чего-то особо сложного, а выбрал:

A=16807;
B=0;
Размерность - 2^16 (Word).


--------------------
I don't like the drugs (but the drugs like me). M.Manson.
PM MAIL ICQ   Вверх
Shuricksoft as a guest
Дата 14.9.2003, 16:17 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Chingachguk, я тоже засомневался по поводу CX, но проверил - работает =) А потом подумал: ведь основной код данной программы не использует этот регистр. БИОС его использовать также не может. Почему? А потому что, когда мы юзаем CX в основном коде, БИОС точно так же получает управление, но ничего страшного не происходит, следовательно CX БИОСу не нужен. При использовании стандартных библиотек Паскаля или С могут быть ошибки - тут я с тобой полностью согласен. Но в нашем случае это не принципиально =)
По поводу ответов на мои вопросы всё понятно, спасибо.
Теперь переделка кода рисования на ассемблер:
Код

...
 { Цикл опроса клавиатуры ~ repeat until keypressed }
 repeat
asm
mov al,MyScreenColor
mov CurrColor,al
mov IndY,0
@@YCycle:
inc IndY
mov IndX,0
@@XCycle:
inc IndX
mov ax,MyScreenCenter
mov CurrCoordinate,ax
mov ax,IndY
push cx
mov cx,320
mul cx
pop cx
add CurrCoordinate,ax
mov ax,IndX
add CurrCoordinate,ax
mov ax,0A000h
mov es,ax
mov bx,ds:CurrCoordinate
mov al,CurrColor
mov byte ptr es:[bx],al
mov ax,MyScreenBarSize
cmp IndX,ax
jnz @@XCycle
mov ax,MyScreenBarSize
cmp IndY,ax
jnz @@YCycle
inc MyScreenBarSize
end;
   { Если размер стал более чем MaxBarSize }
   if MyScreenBarSize>=MaxBarSize then MyScreenBarSize:=1;
   { Проверяем кейбоард }
 until keypressed;
...

Но! Квадраты рисуются очень медленно, а на первых порах ещё и цвет фона меняется. В чём ошибка? И ещё: как записать if MyScreenBarSize>=MaxBarSize then MyScreenBarSize:=1; на ассемблере? А для организации repeat until keypressed надо ставить свой обработчик на прерывание клавы? И нельзя ли значения переменным присваивать напрямую, а не через регистры?
  Вверх
Chingachguk
Дата 16.9.2003, 14:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1232
Регистрация: 25.3.2002
Где: Москва

Репутация: 11
Всего: 18



О, это тонкая ошибка ! Попробуй сам догадаться, в чем дело (верный код):

Цитата

  repeat
    { Рисуем квадрат размером MyScreenBarSize с центром в MyScreenCenter }
    asm
    mov al,MyScreenColor
    mov CurrColor,al
    mov IndY,1
@@YCycle:
        mov IndX,1
@@XCycle:
        mov ax,MyScreenCenter
        mov CurrCoordinate,ax
        mov ax,IndY
        push cx
        mov cx,320
        mul cx
        pop cx
        add CurrCoordinate,ax
        mov ax,IndX
        add CurrCoordinate,ax
        mov ax,0A000h
        mov es,ax
        mov bx,ds:CurrCoordinate
        mov al,CurrColor
        mov byte ptr es:[bx],al
        inc IndX
        mov ax,MyScreenBarSize
        cmp IndX,ax
        jbe @@XCycle
        inc IndY
        mov ax,MyScreenBarSize
        cmp IndY,ax
        jbe @@YCycle
    inc MyScreenBarSize
    end;


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


--------------------
I don't like the drugs (but the drugs like me). M.Manson.
PM MAIL ICQ   Вверх
Shuricksoft as a guest
Дата 18.9.2003, 21:58 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











По-моему, единственная разница при выполнении новой версии кода - это то, что при окончании цкла значение IndX или У = MyScreenBarSize + 1 (у меня - просто MyScreenBarSize). Цикл же выполняется для одинаковых значений в обоих случаях. Но ведь Паскалевское for IndX := 1 to MyScreenBarSize в конце тоже выдаст MyScreenBarSizr (без 1). Я что-то совсем запутался :-/
По поводу оптимизации, пользуясь твоей подсказкой, вынес строки
mov ax,0A000h
mov es,ax
непосредственно перед началом циклов. Больше ничего сделать не смог.

  Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Asm для начинающих"
MAKCim
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой КОД.
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, MAKCim.

 
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Asm для начинающих | Следующая тема »


 




[ Время генерации скрипта: 0.1432 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.