Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm для начинающих > ASM - с чего начать?


Автор: Wowa 25.3.2002, 01:56
Посоветуйте что-нибудь.

Автор: Fantasist 25.3.2002, 07:32
Chingachguka! Chingachguka на сцену. Пусть дла начала свои уроки запостит.

Автор: Vit 25.3.2002, 11:15
Это точно, начинать надо с Chingachguka :)

Автор: neutrino 25.3.2002, 12:48
Est takaia bolshaia kniga Toma Svana (Tom Swan) nazivaetsia "programmirovanie v Turbo Assembler". Ochen podrobnoe opisanie. Kucha primerov i poniatno napisannaia.
Rekomenduiu. :)

Автор: Chingachguk 25.3.2002, 17:36
О ! Всем привет ! ;)))

Так что, можно продолжить ?! Оки !
Ниже пошел первый Урок.

Автор: Chingachguk 25.3.2002, 17:39
Урок 1. Немного порисуем.

Итак, начнем. Запустите tp7(или более младшие версии,
где можно писать asm end; - и компиллер не ругнется).
Tp7 Вы можете взять тут(~550Кил):
http://chat.ru/~vzubko/tp7.zip

Наберите следующий код:

begin
 {Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
 asm
 mov  ax,0013h
 int  10h
 end;
 asm
 mov  ax,0A000h
 mov  es,ax
 {Рисуем - раз}
 mov  byte ptr es:[320*10+10],12
 mov  byte ptr es:[320*10+11],12
 mov  byte ptr es:[320*10+12],12
 mov  byte ptr es:[320*11+10],12
 mov  byte ptr es:[320*11+11],12
 mov  byte ptr es:[320*11+12],12
 mov  byte ptr es:[320*12+10],12
 mov  byte ptr es:[320*12+11],12
 mov  byte ptr es:[320*12+12],12
 {Рисуем - два}
 mov  byte ptr es:[320*100+100],1
 mov  byte ptr es:[320*101+101],2
 mov  byte ptr es:[320*102+102],3
 mov  byte ptr es:[320*103+103],4
 mov  byte ptr es:[320*104+104],5
 mov  byte ptr es:[320*105+105],6
 end;
 {Ожидаем нажатия клавиши}
 asm
 mov  ah,0
 int  16h
 end;
 {Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
 asm
 mov  ax,0003h
 int  10h
 end;
end.

Ага. Теперь скомпиллируйте ЭТО и запустите на выполнение. Что Вы видите ?
(Должны увидеть квадратик и цепочку точек). Нажав клавишу, Вы должны закрыть
графическое окно и вернуться в среду.

НЕбольшое техническое отступление. Синтаксис асм-вставок в tp7.
Асм-вставка начианется псевдооператором "asm". Далее идут сами ассемблерные
команды(Вы должны видеть их зелеными). Завешает блок асм директива
"end;" - как, врочем, и другие логически завершенные блоки в Pascal.

Теперь посмотрим на команды. Их не так много и они довольно одинаковы.
Отбросим пока вот эти три блока, дав им поверхностное объяснение:

 asm
 mov  ax,0013h
 int  10h
 end;

Пока примите, как факт, что для вызова Операционной системы, BIOS или
других программ обычно используются вот такие вот записи(команды):

 mov ax,0013h - это пример ЗАДАНИЯ ПАРАМЕТРОВ, передаваемых другим
программам;
 int 10h - это ВЫЗОВ других программ Вашей машины - здесь это вызов BIOS.

 {Ожидаем нажатия клавиши}
 asm
 mov  ah,0
 int  16h
 end;

 mov ah,0 - это пример ЗАДАНИЯ ПАРАМЕТРОВ, передаваемых другим
программам;
 int 16h - это ВЫЗОВ других программ Вашей машины - здесь это вызов BIOS.

Итак, вернемся к тем командам, которые откомментарены как " {Рисуем - раз}"
и "{Рисуем - два}". Попытайтесь понять, чем они похожи, а чем отличаются...

... Вы должны были заметить, что вот эти команды:

 mov  byte ptr es:[320*10+10],12
 mov  byte ptr es:[320*10+11],12
 ...

в более общем виде можно записать как:

mov byte ptr es:[Что-то],Еще что-то.

Попробуйте самостоятельно поменять эти "Что-то" и "Еще что-то" у нескольких
команд. Посмотрите на результат. Создайте еще несколько подобных  команд.
Проявите фантазию в разумных пределах и насоздавайте еще разных
подобных команд.
Попытайтесь сделать самостоятельно какие-то обобщения по результатам.

А теперь небольшое задание. Исходный пример рисовал нам красный квадратик в
верхнем левом углу экрана. Попробуйте на основе полученного опыта ТОЛЬКО с
помощью команд типа:

mov byte ptr es:[Что-то],Еще что-то.

нарисовать синий прямоугольник, но уже в нижнем правом углу экрана.
Подсказка: обратите внимание вот на этот комментарий:

{Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}

Урок 1 закончен. Решение и некоторые объяснения будут даны в
уроке 2. Да пребудет с Вами Великая Сила !

Автор: Chingachguk 25.3.2002, 17:43
Урок 2. Основные понятия. Микропроцессор 8086. Решение примера Урока 1
на основе полученных знаний. Косвенная адресация: первый пример.

Итак, начнем этот урок с очень важной штуки. Введем основные определения,
которых будет немного, они будут просты... но это будут самые важные понятия
во всем этом деле !
Итак, чего вообще мы хотим ? Мы хотим научиться разговаривать с Машиной на ее
языке. Поэтому дадим понятие КОМПЬЮТЕРА(Машины), именно так, как она будет
выглядеть для Вас при программировании на ассемблере:

МАШИНА - нечто, состоящие из ПРОЦЕССОРА, ОПЕРАТИВНОЙ ПАМЯТИ и ПОРТОВ
ВВОДА-ВЫВОДА. ПРОЦЕССОР умеет выполнять ПРОГРАММЫ. Раскроем детальнее эти
понятия:

- ОПЕРАТИВНАЯ ПАМЯТЬ: набор ячеек, в котрые можно записывать числа и из которых
можно читать числа.
- ПОРТЫ ВВОДА-ВЫВОДА: набор ячеек, в котрые можно записывать числа и из которых
можно читать числа.
- ПРОЦЕССОР: функция, понимающая и реализующая числа, записанные
в ОПЕРАТИВНОЙ ПАМЯТИ как действия (КОМАНДЫ).
Выполнение команд назовем ПРОГРАММОЙ.

Итак, это важно !!! - нет никаких жестких дисков, джойстиков, мышей ... Есть только
ПРОЦЕССОР, ОПЕРАТИВНАЯ ПАМЯТЬ и ПОРТЫ ВВОДА-ВЫВОДА. Любое наше действие
будет направлено ТОЛЬКО на работу с этими тремя объектами.

Итак, мы определились: есть ОПЕРАТИВНАЯ ПАМЯТЬ, в ней храняться числа, ПРОЦЕССОР
обрабатывает эти числа и выполняет действия, заданные этими числами. Очевидно из
данных нами определений, что эти действия(КОМАНДЫ) в любом случае могут быть
направлены ТОЛЬКО на измение(чтение/запись) ОПЕРАТИВНОЙ ПАМЯТИ и
(или) ПОРТОВ ВВОДА-ВЫВОДА, либо на изменение состояния самого ПРОЦЕССОРА.

В общем виде КОМАНДУ можно представить в таком виде:

Что_Делать:<Как Делать>.

Как_Делать может быть пропущенно(<...>), ибо Что_Делать: ничего не делать
не требует дополнительных сведений. Да, есть такая команда - Ничего_Не_Делать.
Пример из жизни: команда "Лежать" также не требует дополнительных данных.

Таким образом, процессор читает ОПЕРАТИНВУЮ ПАМЯТЬ и трактует прочитанные
числа как команды. Поняв команду, он выполняет заданные в ней действия.
Команды, как уже было сказано, могут сводится к одному или нескольким
из следующих действий:

- Ничего не делать;
- Изменить что-то в ОПЕРАТИВНОЙ ПАМЯТИ;
- Изменить что-то ПОРТАХ;
- Изменить состояние процессора.

Что значит "Изменить что-то в оперативной памяти" ? Это означает изменить те числа,
которые в ней находятся: прочесть их или записать новое значение числа. То же самое
и с портами ввода-вывода.
Что означает "Изменить состояние процессора" ? Это означает повлиять на то, как он будет
трактовать(исполнять, выполнять) КОМАНДЫ.

Вернемся к второй части КОМНАДЫ - "Как Делать". Очевидно, что в ней должно содержаться
указание на область ОПЕРАТИВНОЙ ПАМЯТИ, если мы хотим ее читать/записывать, либо указание
на область ПОРТОВ, если мы хотим читать/записывать в них. Поэтому введем понятие
ЭФФЕКТИВНОГО АДРЕСА - указатель на конкретный элемент памяти, портов или процессора.

Теперь хватит теории, перейдем к  практике. Мы работали в Уроке 1 и будем работать в ближайшее
время с конкретным процессором - 8086 фирмы Intel, выпущенным еще в конце 70-х годов.
Процессор этот выполняет команды, записанные в опеределенного вида памяти, и может,
выполняя команды, изменять определенного вида порты ввода-вывода.
Память эта также есть набор ячеек, в которые можно записывать числа. Каждая ячейка
может хранить числа от 0 до 255. Порты также являются ячейками, в которые можно записывать
/из которых можно читать числа от 0 до 255.
Как храняться числа в этих ячейках ? Каждая из них состоит из 8 так называемых бит. Бит - это нечто,
могущее быть только в двух состояниях  - 0/1(Да/Нет,Триггер ... - как Вам нравиться).
Вспомним, что любое целое и неотрицательное число (0,1,2..10000...) можно разложить по степеням
двойки:

 25 = 16+8+1 = 1*2^4 + 1*2^3 + 0*2^2 + 0*2^1 + 1*2^0 = 1*16+1*8+0*4+0*2+1*1.

Итак, если мы будем трактовать 8 бит каждой такой ячейки, называемой байтом, как
коэффициенты при степени двойки, то получим возможность раскладывать числа
по 8-ми различным степеням:

2^7,2^6... 2^0.

Иначе говоря, каждое число в каждой ячейке оперативной памяти 8086 реализовано
определенным состоянием всех восьми бит этой ячейки:

Число:
         25  65  128  255
Бит0   1    1    0       1
Бит1   0    0    0       1
Бит2   0    0    0       1
Бит3   1    0    0       1
Бит4   1    0    0       1
Бит5   0    0    0       1
Бит6   0    1    0       1
Бит7   0    0    1       1.

Каждая такая ячейка называется байтом.

Итак, в 8086 записываются числа в оперативную память. Процессор может читать
эти числа, трактовать их как команды, понимать из команды, какую ячейку памяти ему
нужно изменять. Как же он это делает ? Очевидно, что ему надо знать
ЭФФЕКТИВНЫЙ АДРЕС команды, ЭФФЕКТИВНЫЙ АДРЕС ячейки, которую указано
поменять в ПАМЯТИ или ПОРТАХ. По большому счету, ЭФФЕКТИВНЫЙ АДРЕС - это номер
ячейки(номер байта) в памяти или портах. Нумерация от нуля. Например, байт(ячейка)
номер 20 содержит значение 22.
Как же процессор формирует этот ЭФФЕКТИВНЫЙ АДРЕС ? (Иными словами, где
хранится и как вычисляется номер байта) ?
Как ни странно, но он делает это весьма замысловатым образом: в процессоре имеются
так называемые РЕГИСТРЫ - это тоже ячейки "памяти" самого процессора,
но размером в СЛОВО(два байта). Можно сказать, что у Процессора есть своя небольшая
память, состоящая из набора слов. Если байт - это ячейка из восьми бит, то слово содержит
целых 16 бит, и в него можно записывать числа от 0 до 65535(посмотрите, как хранятся
числа в ячейках-байтах и поймите, какие числа можно хранить в ячейках из 16 бит). Имея
около десятка таких ячеек-слов, процессор использует некоторые из них для вычисления
ЭФФЕКТИВНОГО АДРЕСА. Вы можете подумать, что номер ячейки памяти, содержащую
текущую выполняемую команду, просто храниться в одном из РЕГИСТРОВ, а после
выполнения текущей команды в него заносится номер следующей команды:

Команда1    Байт1, Байт2,Байт3 команды 1. Номер ячейки  - 230 (Номер байта1).
Регистр_Текущей_Команды равен 230.

После выполнения команды1 процессор начнет выполнять команду2:

Команда2    Байт1, Байт2 команды 2. Номер ячейки  - 233 (Номер байта1).
Регистр_Текущей_Команды равен 233 ?

В какой-то мере у процессора 8086 это так, но в точности - не так !

Скажем вот что: процессор 8086 может работать с памятью размером
в один Мегабайт(примерно миллон ячеек по одному байту). Команды или
какие-то вспомогательные числа могут быть размещены в любой ячейке
с номером от 0 до ~1 миллиона. Т.е. номер текущей выполняемой команды
может быть в этом диапазоне. Процессор может использовать для хранения
этого номера один или несколько из своих регистров размером в слово. Вот
эти регистры, которые есть у него(все они размером в слово):

Сокращенное имя/Полное имя

IP - Instruction Pointer;
CS - Register of Code Segment;
SS - Register of Stack Segment;
SP - Stack Pointer;
ES - Register of Extra Segment;
DS - Register of Data Segment;
AX - Accumulator;
BX - Base Register;
CX - Counter
DX - Data Register;
SI - Source Register;
DI - Destination Register;
BP - Base Pointer;
FLAGS - Flags Register.

Итак, имеем этот набор регистров. Каждый размером в слово. Не обращайте
пока внимание на их названия. Прикинте, как процессор хранит номера ячеек памяти
в них.

Вы могли догадаться, что для хранения номера ячейки недостаточно любого
одного регистра из-за того, что размер памяти 8086 = 1 миллион > максимальное
число, которое можно хранит в одном слове - 65535. Два будет абсолютно достаточно,
ибо число ~один миллион легко раскладывается по степеням двойки вплоть до 20 степени,
а, значит, нам достаточно иметь всего 20 бит для его хранения ... А два регистра
обладают уже 32 битами. Например, можно придумать такую схему размещения
номера байта(ЭФФЕКТИВНОГО АДРЕСА) в двух регистрах:

1-ый регистр - 16 младших(первых) битов числа ЭФФЕКТИВНОГО АДРЕСА;
2-ой регистр - 4 старших(вторая часть) битов.

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

ЭФФЕКТИВНЫЙ АДРЕС = Регистр1 x 16 + Регистр 2(или непосредственное значение).

Возьмем команду из Урока 1:

 mov  byte ptr es:[320*10+10],12

Эта команда предназначена для того, чтобы записать в ячейку памяти номер
658570 числа 12. Смотрите, что в этой команде задано:

Что_Делать: Записать число в память.
Как Делать:
Число взять из самой команды - 12;
Адрес памяти вычислить, используя регистр es и непосредственное значение,
указанное в команде - 320*10+10;
Размер применика(числа в памяти для записи) - один байт.

Сейчас обратим внимание ТОЛЬКО на то, как 8086 ухитрился вычислить адрес
ячейки памяти из этой команды. Смотрите:

Регистр1 = Регистр ES(в команде так и задано)
Непосредственное значение для прибавки = 320*10+10 (тоже задано в команде)

ЭФФЕКТИВНЫЙ АДРЕС = ES x 16 + 320*10+10 = 658570.
Кто же задал значение регистра ES ??? Ясно дело, что мы ! Мы контролируем
весь процесс выполнения программы процессором ! А как мы это сделали ?
А вот как:

 mov  ax,0A000h
 mov  es,ax

Мы тут задали значение регистра ES - 0A000h = 40960.
Теперь Вы понимаете, что меняя "Что-то" в командах Урока1:

mov byte ptr es:[Что-то],Еще что-то

вы меняли Адрес Ячейки Памяти !

А вот решение задания:

 mov  byte ptr es:[320*160+110],9
 mov  byte ptr es:[320*160+111],9
 mov  byte ptr es:[320*160+112],9
 mov  byte ptr es:[320*161+110],9
 mov  byte ptr es:[320*161+111],9
 mov  byte ptr es:[320*161+112],9
 mov  byte ptr es:[320*162+110],9
 mov  byte ptr es:[320*162+111],9
 mov  byte ptr es:[320*162+112],9

- синий квадратик.

Сейчас у Вас должно возникнуть еще больше вопросов, нежели после
первого урока !!! Но и должно появиться смутное ощущение ПАМЯТИ,
которой Вы можете управлять такими вот командами.

А теперь - на закуску - Косвенная адресация !!!
Уже было сказано, как 8086 может вычислять адрес в памяти:

ЭФФЕКТИВНЫЙ АДРЕС = Регистр1 x 16 + Регистр 2(или непосредственное значение).

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

 mov  bx,320*180+100 {Заносим значение(число) 320*180+100 в регистр BX}
 mov  byte ptr es:[bx],2 {Изменим память, используя ДВА регистра для адресации}

В последней команде эффективный адрес будет вычислен так:

ЭФФЕКТИВНЫЙ АДРЕС = ES x 16 + BX.

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

{Рисуем - три !!!}
asm
 mov  bx,320*180+100 {Заносим значение(число) 320*180+100 в регистр BX}
 mov  byte ptr es:[bx],2 {Изменим память, используя ДВА регистра для адресации}
 mov  bx,320*180+101 {Заносим значение(число) 320*180+101 в регистр BX}
 mov  byte ptr es:[bx],2 {Изменим память, используя ДВА регистра для адресации}
 mov  bx,320*180+102 {Заносим значение(число) 320*180+102 в регистр BX}
 mov  byte ptr es:[bx],2 {Изменим память, используя ДВА регистра для адресации}
end;

Если Вы выполните этот код, то должны увидеть маленькую зеленую полоску
внизу и посередине экрана.

Задание: попробуйте сделать эту полоску потолще и подлиннее, но используя
именно такие команды - mov byte ptr es:[bx]. Попытайтесь вместо таких команд
использовать уже известные Вам - типа mov  byte ptr es:[320*180+100],2.

Урок 2 закончен.  Некотрые объяснения будут даны в
уроке 3, но вопросов должно быть немеряно !!!
Да пребудет с Вами Великая Сила !

Автор: AXEL3323 26.3.2002, 08:16
Привет!! Уроки - просто супер! Вот у меня вопрос :)
В пакете Tasm в отладчике td.exe для отладки существует много способов (пошаговые, бреакпоинтовский и т.д.), для краткости это F4,F7,F8, ну и F9. Так вот чтобы прервать выполнение программы надо нажать сочетание Ctrl+F2 ( Program Reset). НО в режиме отладки F9 программа не останавливается   :dg . Так надо??..Что-то я не пойму...
А отладчик версии 5.0 ( от 21.02.96), я его взял с нового диска  :D , хотя с тех пор он и не менялся....(ну я имею ввиду 16-разрядный из TASM'а)
Так как мне прервать выполнение программы?(из режима RUN) :notify

Автор: neutrino 26.3.2002, 12:12
Tut mnogo, kto hochet asm uchit. Mojet Chingachguku otdelnuiu formu sdelat? S temami ... Ia bi, naprimer, zahjodil. I primeri interesnie daet. Mojet knigu vipustit "Assembler Chingachguka". Vot eto tochno ne lamievo! :satisfied

Автор: Chingachguk 26.3.2002, 13:58
Цитата

AXEL3323 Дата сообщения: 26.3.2002,08:16
Привет!! Уроки - просто супер! Вот у меня вопрос  
В пакете Tasm в отладчике td.exe для отладки существует много способов (пошаговые, бреакпоинтовский и т.д.), для краткости это F4,F7,F8, ну и F9. Так вот чтобы прервать выполнение программы надо нажать сочетание Ctrl+F2 ( Program Reset). НО в режиме отладки F9 программа не останавливается    . Так надо??..Что-то я не пойму...
А отладчик версии 5.0 ( от 21.02.96), я его взял с нового диска   , хотя с тех пор он и не менялся....(ну я имею ввиду 16-разрядный из TASM'а)
Так как мне прервать выполнение программы?(из режима RUN)


Из режима RUN можно использовать CTRL_BREAK. Но !
Если, к примеру, в программе написать замкнутный цикл:

@@Label: jmp @@Label

То нажатие этих клавиш не всегда прервет программу внутри этого кода ;) Потому, что еще выполняются прерывания ...
Отладчик может остановить работу программы двумя способами: установить свой обработчик на клавиатуру(это и есть CTRL_BREAK), но бывает код, вырубающий прерывания/маскирующий прерывания от клавиатуры, а также установить брейкпойнты (это и есть F4...).
Видимо, ты пытаешься отладить программу, которая, к примеру, где-то виснет и ты хочешь, нажав CTRL_F2, ее скинуть, узнав где она зависла ? Рекомендую действовать методом приближения к "багу": устанавливаешь брейки и постепенно доходишь до неверного кода.

Цитата

neutrino Дата сообщения: 26.3.2002,12:12
Tut mnogo, kto hochet asm uchit. Mojet Chingachguku otdelnuiu formu sdelat? S temami ... Ia bi, naprimer, zahjodil. I primeri interesnie daet. Mojet knigu vipustit "Assembler Chingachguka". Vot eto tochno ne lamievo!  


Хе, да я в жизни ничего подобного не делал, у меня даже своей странички нету ;) Хотя, может быть, дойдут руки...
К тому же я счас помогаю развивать вот этот сайт http://hi-tech.nsys.by/ - он целиком по асму.

Автор: neutrino 26.3.2002, 15:07
Da, sait nichego, osobenno fanariki na solnechnih batareikah ponravilis. No dolgo gruzitsia.  :satisfied

Автор: Chingachguk 26.3.2002, 22:10
Урок 3. Продолжаем работать с памятью. Первый цикл. Изучение
двухкомпонетного адреса.

Упс, как говорит Б.Спирс, ай дид ит эгейн. Ну и мы тоже эгейн. В смысле, снова
поработаем с памятью.
Итак, память. Памяти у нас примерно миллион ячеек по 1 байту. Где-то находятся
байты нашей программы, которую процессор сейчас читает байт за байтом и выполняет,
где-то байты программ БИОС-а, где-то - ДОС-а. Ну а начиная с байта нумер 655360
находится так называемый видеобуфер. Можно сказать по-другому - с номера A0000h.
Это - шестнадцетеричная система исчисления. Эти числа равны: 655360=A0000h, просто они
записаны по-разному. Здесь мы не будем подробно разбирать эту систему, приведем только
пример преобразования числа A0000h в "нормальный" вид:

A0000h = A*16^4+0*16^3+0*16^2+0*16^1+0*16^0 = 10*16^4 = 655360.

h - просто обозначение такой системы исчисления;
A = 10, B = 11, C = 12, D = 13, E = 14, F = 15 - поскольку основанием является 16, то для записи
числа НЕ ХВАТАЕТ чисел "привычной" десятичной системы - 0,1,2,3..9.
Вы вполне можете обойтись виндовым или любым другим калькулятором для
такого рода преобразований.
Ага, так что же такое видеобуфер ? Он же - видеопамять, видеокарта, ... Для
нас нет никаких железок, джемперов, жестких дисков, повторяю !
Есть только память, порты и процессор. Видеобуфер для нас в данном
случае - просто КУСОК ПАМЯТИ. Начинается с байта номер A0000h. Почему же мы
выделяем этот кусок особо ? А вот почему: помните, у нас в Уроке 1 был такой код:

 {Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
 asm
 mov  ax,0013h
 int  10h
 end;

Всего две команды, а делают сколько ! После их выполнения БИОС сделает так, что
всякая запись чисел в этот видеобуфер приведет к изменениям на мониторе !
Как это происходит ? С нашей стороны "забора" мы пишем в ячейки этого куска памяти
числа. Они там и остаются, пока их не изменить. С другой стороны "забора" сидит
аппаратура, "железо", как ее еще называют, которая СОВЕРШЕННО НЕЗАВИСИМО от
выполнения наших программ начинает трактовать эти числа КАК ЦВЕТА ТОЧЕК монитора.
Это ее БИОС так заставил делать. Переключил в такой режим. Бывают и другие режимы
работы видеокарты-видеоаппаратуры - текстовые там, графические ... Мы в графическом.
Но это все нам неважно. Важно нам только то, как надо писать в эту память числа, чтобы
аппаратура эта нарисовала на их основе изображение на мониторе.
Более детально. Вспомним, что режим у нас - 320x200, 256 цветов. 320 точек по
горизонтали, 200 - по вертикали. Каждая точка может иметь 256 различных цветов.
1 байт памяти как раз может иметь 256 различных состояний. Число в байте номер
A0000h аппаратура трактует как цвет верхнего левого пикселя, число в следующем
байте - как цвет следующего(двигаясь направо) пикселя и так далее. На одну строчку
320 пикселей - значит, и в памяти 320 байт. 321 байт начиная с байта A0000h - это уже
самый левый пиксель второй стороки и так далее:

Номер пикселя по
горизонтали/вертикали - номер байта в памяти
       0             1                2              3
0  A0000h  A0000h+1 A0000h+2 A0000h+3 ...
1  A0000h+320...
2
...

Ага. Нетрудно сообразить, что для всех 320x200 точек монитора требуется
320x200 = 64000 байт памяти. Например, запись в байт с номером
A0000h+320x200-1 приведет к изменению цвета нижнего правого пикселя.
Проверим это. Нарисуем вертикальную горизонтальную линию на мониторе,
желтого цвета, по самой первой строке от левого до правого края монитора.
От уха до уха, так сказать. Для этого мы должны записать
число 14(желтый цвет) в байты с номерами
A0000h,A0000h+1... A0000h+319 - всего 320 последовательных байт.
Вспоминаем, как процессор может делать это:

 mov  ax,0A000h {Заносим в регистр AX число 0A000h}
 mov  es,ax {Копируем число из регистра AX в регистр ES, фактически - 0A000h}
 mov  byte ptr es:[0],14 {Записываем по адресу 0A000hx16+0 байт значением 14}
 mov  byte ptr es:[1],14 {Записываем по адресу 0A000hx16+1 байт значением 14}
 mov  byte ptr es:[2],14 {Записываем по адресу 0A000hx16+2 байт значением 14}
 ...

Не надоело ? Верно, надо делать цикл. Как и в других языках программирования,
в асме тоже есть циклы. Что же за цикл нам нужен ? Цикл из 320 повторений,
в цикле должен вертеться индекс, позволяющий нам записывать СМЕЩЕНИЕ
адреса в команде от 0 до 319. СМЕЩЕНИЕ - это та часть эффективного адреса,
который процессор вычисляет из команды и добавит его к СЕГМЕНТНОМУ
регистру, умноженному на 16:

 mov  byte ptr es:[1],14
 Эффективный адрес =             es * 16           +         1
                                        СЕГМЕНТНАЯ ЧАСТЬ    СМЕЩЕНИЕ.

В этой команде смещение указано явно. Жестко. Сколько бы раз мы не выполнили
эту команду, она запишет байт 14 в одну и ту же ячейку памяти. Если только не
менять значение сегментного регистра es. Почему бы нам не поменять его ?
А вот, например, почему: нетрудно заметить, что ЛЮБОЕ значение в сегментном
регистре es при смещении = 1 нам НИКОГДА не позволит писать в ячеку памяти
номер A0000h(подумайте, почему !;). Теперь вспомним, что в Уроке 2 мы проходили
так называемую КОСВЕННУЮ адресацию:

 mov bx,1
 mov byte ptr es:[bx],14 {Записываем по адресу 0A000hx16+bx байт значением 14}.

Процессор использовал для получения смещения регистр ! А регистры мы можем
менять ! Тогда начнем писать цикл:

 mov  ax,0A000h {Заносим в регистр AX число 0A000h}
 mov  es,ax {Копируем число из регистра AX в регистр ES, фактически - 0A000h}
 mov bx,0 {Смещение первой точки равно 0}
 mov byte ptr es:[bx],14
 ADD bx,1 {Добавить к регистру BX 1 !}

Вот, новая команда(ADD) ! До сих пор мы работали с одной командой засылки
значения - mov(от move, англ.). А команда "ADD" (addition, сложить) позволяет
добавлять к приемнику операции (здесь - регистр BX) значение источника - "1".
И регистр BX станет равен 1 !
Что же дальше ? Последуем классическому типу циклов:

repeat  
{Тело цикла}
Until {Условие=TRUE}

Очевидно, что телом цикла у нас выступает команда
закраски - mov byte ptr es:[bx],14. Командой add bx,1 мы изменили регистр BX
и можем анализировать его состояние (Условие=TRUE). Что же мы будем
анализировать ? Если мы хотим задать смещение от 0 до 319, то нам годятся
все значения bx в этом диапазоне, иначе цикл надо прерывать. Делаем это:

add bx,1 {inc(BX) или BX:=BX+1 или BX++}
CMP bx,319 {Сравнить BX и 319}
JBE МЕТКА_НАЧАЛА_ЦИКЛА - @repeat.

Опять, опять новые команды ! Не бойтесь, их вообще не так много, а выучить
их проще простого ! Я обязательно далее раскажу подробно о командах, а пока
лишь вкратце:

CMP bx,319 {COMPARE BX WITH 319}
JBE @repeat {JUMP IF BELOW OR EQUAL}

Вы видите расшифровку сокращений этих команд. CMP-это сравнение.
BX с 319. По результатам этого сравнения мы можем писать команды
переходов. А фактически - приказать процессору перейти на конкретную
команду, да еще и в зависимости от результата сравнения - JBE.
А вот как выглядит весь код:

begin
 {Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
 asm
 mov  ax,0013h
 int  10h
 end;
 asm
 {Кусок рисования}
 mov ax,0A000h
 mov es,ax
 mov bx,0
@Repeat:
 mov byte ptr es:[bx],14
 add bx,1
 cmp bx,319
 jbe @Repeat
 {Кусок рисования - Закончен}
 end;
 {Ожидаем нажатия клавиши}
 asm
 mov  ah,0
 int  16h
 end;
 {Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
 asm
 mov  ax,0003h
 int  10h
 end;
end.

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

Выполните этот код. Убедитесь в наличии желтой полосы вверху экрана.

Метка начала цикла у нас называется @Repeat. Почему вначале @ ?
Это особенность asm-вставок языка Паскаль. В настоящем ассемблере
Вы можете извращаться так, как вам хочется, хотя это ограничение не слишком
сильное. Вы могли назвать метку @MY_LABEL. Важно одно: Вы сравнили командой
CMP регистр BX с 319, и, если его значение МЕНЬШЕ(BELOW) или(OR)
равно(EQUAL) 319, то передаете управление на эту метку.

Примечание: Вам должно быть непонятно, ОТКУДА команда JBE знает про
результаты выполнения команды сравнения (CMP).

Усложним слегка пример. Хочу, чтобы мы нарисовали желтую полосу не по
первой сверху строке, а по строке номер 160 ! Думаю, Вам понятно, где
начинаются байты, отвечающие этой строке:

Номер пикселя по
горизонтали/вертикали - номер байта в памяти
           0                                     1                               2
160  A0000h+160*320  A0000h+160*320+1 A0000h+160*320+2...

А это означает, что начальное смещение в цикле надо задать просто
не с нуля, а с 160*320:

 {Кусок рисования}
 mov ax,0A000h
 mov es,ax
 mov bx,160*320 {Начальное смещение !}
@Repeat:
 mov byte ptr es:[bx],14
 add bx,1
 cmp bx,160*320+319 {Внимание ! Мы изменили и эту команду !}
 jbe @Repeat
 {Кусок рисования - Закончен}

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

Важный момент:

 cmp bx,160*320+319 {Внимание ! Мы изменили и эту команду !}

У нас регистр BX уже меняется не от нуля ! И закончим мы рисовать не тогда,
когда он станет 320, а когда 160*320+320 !

А теперь еще навороченне !!! Мы можем задавать эффективный адрес, варьируя
две компоненты: сегмент и смещение. Только что мы сместили полосу на экране,
меняя смещение. Это было естественно, поскольку мы занесли в регистр es такое
число, что процессор, умножая его на 16, как раз втыкался в начало видеобуфера:

es * 16 = 0A000h * 16 = 0A0000h !

И нам было наглядно задавть смещение от нуля(словно индексация в массиве).
Но мы попробуем устроить себе трабл и использовать другое (не 0A000h)
значение, заносимое в сегментный регистр es, чтобы нарисовать ту же желтую
линию в 160 строке. Нам надо задавть в командах такие вот адреса:

Номер пикселя по
горизонтали/вертикали - номер байта в памяти
           0                                     1                               2
160  A0000h+160*320  A0000h+160*320+1 A0000h+160*320+2...

A0000h бралось ранее из es. Смещения - 160*320+0,1,2.. - из bx.
А можно ли задать так значение es, чтобы смещение, к примеру,
начиналось с 0 ? Вот так:

          0       1     2
160  X+0h  X+1 X+2... - ?

Здесь X - это неизвестное. Оно должно быть получено процессором так:

X = es*16

А ячейки памяти должны иметь одинаковые адреса:

X+0h = A0000h+160*320.

Решая это несложное уравнение, найдем, что X = AC800h = 706560.
Значит, es = AC800h / 16 = AC80h ! И измененный код готов:

 {Кусок рисования}
 mov ax,0AC80h
 mov es,ax
 mov bx,0 {Начальное смещение ! - опять нуль !}
@Repeat:
 mov byte ptr es:[bx],14
 add bx,1
 cmp bx,319 {Внимание ! Мы изменили и эту команду ! - вернули !}
 jbe @Repeat
 {Кусок рисования - Закончен}

Заделаем этот пример понагляднее ! Сначала нарисуем желтую полосу
в строке 160 "обычным" способом - занося перед циклом в регистр es число
0A000h, а потом нарисуем поверх желтой полосы фиолетовую, но уже занося
в es значение 0AC80h ! Вот кодец:

 {Кусок рисования}
 mov ax,0A000h
 mov es,ax
 mov bx,160*320 {Начальное смещение !}
@RepeatYellow:
 mov byte ptr es:[bx],14
 add bx,1
 cmp bx,160*320+319
 jbe @RepeatYellow
 {Остановим программу известным нам способом}
 mov  ah,0
 int  16h
 {Рисуем, но уже другим способом !}
 mov ax,0AC80h
 mov es,ax
 mov bx,0 {Начальное смещение ! - опять нуль !}
@RepeatMagneta:
 mov byte ptr es:[bx],13 {Цвет не желтый !}
 add bx,1
 cmp bx,319
 jbe @RepeatMagneta
 {Кусок рисования - Закончен}

Проверьте этот код !

Ну вот. А теперь я хочу, чтобы Вы выполнили два небольших заданьица:

1) Заполнить ВЕСЬ экран каким-нибудь цветом. Желательно - красным.
2) Нарисовать горизонтальную полосу зеленого цвета в 64 строке экрана:
    - занеся в регистр es адрес начала видеобуфера;
    - занеся в регистр es такое значение, чтобы рисовалась та же полоса в
      64 строке экрана, Но вот смещение Вы бы задавали с нуля !

Не возбраняется, а приветствуется появление Ваших решений до выкладки
Урока 4, где они будут приведены ! Будет неплохо поглядеть на Ваш код
и сделать обсуждам !

Урок 3 закончен.
Да пребудет с Вами Великая Сила !

Автор: Melancholy 8.4.2002, 12:24
прога заполняет весь экран красным цветом.


begin
{Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
asm
mov  ax, 00013h
int  010h
end;
asm
{Кусок рисования}
mov  ax, 0A000h
mov  es, ax
xor  di, di {обнуляем регистр di}
mov  al, 004h
mov  cx, 64000 {счетчик = 64000  =  320 * 200}
rep  stosb {выполняем 64000 раз команду stosb}
         {stosb - помещает значение регистра al в ячейку памяти es:di}
{Кусок рисования - Закончен}
end;
{Ожидаем нажатия клавиши}
asm
mov  ah,0
int  16h
end;
{Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
asm
mov  ax,0003h
int  10h
end;
end.

а как тебе такой код?

Автор: Chingachguk 8.4.2002, 15:46
Цитата

Melancholy Дата сообщения: 08.4.2002,13:24
прога заполняет весь экран красным цветом.

{Кусок рисования}
mov  ax, 0A000h
mov  es, ax
xor  di, di {обнуляем регистр di}
mov  al, 004h
mov  cx, 64000 {счетчик = 64000  =  320 * 200}
rep  stosb {выполняем 64000 раз команду stosb}
{stosb - помещает значение регистра al в ячейку памяти es:di}
{Кусок рисования - Закончен}


Неплохо ! ж)
Видимо, ты знаешь ассемблер на каком-то уровне !
Всего одна ошибка: пропустил команду "cld" ;)
Но код почти на 100% работает !

Правда, в уроке подразумевалось более "незамысловатое" решение.

А как насчет второго задания ? :)

Автор: Melancholy 8.4.2002, 15:56
Вариант 1
begin
{Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
asm
mov  ax, 00013h
int  010h
end;
asm
{Кусок рисования}
mov  ax, 0A000h
mov  es, ax
mov  di, 320*64
mov  al, 004h
mov  cx, 320
cld {между прочим вероятность, что флажек CF установлен очень мола!!!}
rep  stosb {выполняем 64000 раз команду stosb}
{Кусок рисования - Закончен}
end;
{Ожидаем нажатия клавиши}
asm
mov  ah,0
int  16h
end;
{Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
asm
mov  ax,0003h
int  10h
end;
end.
Вариант 2
begin
{Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
asm
mov  ax, 00013h
int  010h
end;
asm
{Кусок рисования}
mov  ax, 0A000h + 20*64
mov  es, ax
xor  di, di
mov  al, 004h
mov  cx, 320
cld
rep  stosb {выполняем 64000 раз команду stosb}
{Кусок рисования - Закончен}
end;
{Ожидаем нажатия клавиши}
asm
mov  ah,0
int  16h
end;
{Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
asm
mov  ax,0003h
int  10h
end;
end.

P.S. Что ты имеешь введу "почти на 100% работает"?

Автор: Chingachguk 8.4.2002, 16:06
Ну что ж, все верно ! ;)

А под этими "почти 100%" я и имел в виду флажок направления.
Думаю, хоть вероятность и мала, но все-таки есть ;)


ЗЫ А еще кто-нибудь сможет решить ?

Автор: Alex101 28.5.2002, 21:34
Цитата(Chingachguk @ 08.4.2002, 17:06)
ЗЫ А еще кто-нибудь сможет решить ?

У меня есть старые наработки на асме - графические процедуры
для разных режимов...
Может кинуть сюда кое-что? Там и работа с портами...

Автор: Melancholy 29.5.2002, 00:41
Можешь кинуть и мне на мыло! ;)
мой мыл

Автор: Chingachguk 29.5.2002, 02:53
>Alex101  Написано: 28.5.2002,22:34    
>Цитата (Chingachguk @ 08.4.2002,17:06)
>>ЗЫ А еще кто-нибудь сможет решить ?
>У меня есть старые наработки на асме - графические процедуры
>для разных режимов...
>Может кинуть сюда кое-что? Там и работа с портами...

Вообще я пытался уроки написать ... До портов не дошло дело ;)
Графика тут постольку поскольку - я ж не демки рисовать ...

Так что кидай рядом, видимо ! Тему создавай ! Или мне на мыл тоже ;)
Может, и я в тему допишу ;) И народ !

Автор: PoluBOG 29.5.2002, 22:28
Ето круто, а как енту прогу в чистом асме оформить?

begin
{Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
asm
mov  ax, 00013h
int  010h
end;
asm
{Кусок рисования}
mov  ax, 0A000h
mov  es, ax
mov  di, 320*64
mov  al, 004h
mov  cx, 320
cld {между прочим вероятность, что флажек CF установлен очень мола!!!}
rep  stosb {выполняем 64000 раз команду stosb}
{Кусок рисования - Закончен}
end;
{Ожидаем нажатия клавиши}
asm
mov  ah,0
int  16h
end;
{Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
asm
mov  ax,0003h
int  10h
end;
end.
Вариант 2
begin
{Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
asm
mov  ax, 00013h
int  010h
end;
asm
{Кусок рисования}
mov  ax, 0A000h + 20*64
mov  es, ax
xor  di, di
mov  al, 004h
mov  cx, 320
cld
rep  stosb {выполняем 64000 раз команду stosb}
{Кусок рисования - Закончен}
end;
{Ожидаем нажатия клавиши}
asm
mov  ah,0
int  16h
end;
{Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
asm
mov  ax,0003h
int  10h
end;
end.

Автор: Заходяга 4.6.2002, 14:07
Цитата(neutrino @ 25.3.2002, 12:48)
Est takaia bolshaia kniga Toma Svana (Tom Swan) nazivaetsia "programmirovanie v Turbo Assembler". Ochen podrobnoe opisanie. Kucha primerov i poniatno napisannaia.
Rekomenduiu. :)

Искал я на поисковиках строку "Том Сван" - не находит.  ??? Может подскажешь где найти  :huh

Автор: end1 30.6.2002, 23:41
Chingachgukу пора писать книгу.Однозначно.

Автор: Baa 1.7.2002, 14:53
;-)
http://www.kalashnikoff.ru/

Автор: Edmond 15.8.2002, 21:33
Вы и
http://wasm.ru
Незабывайте...

P.S
Чинганчук. Ах, незнал, незнал!!!
Чтож ты так скромничаешь?

Автор: Baa 22.8.2002, 10:36
Wasm оно ток недавно...эт 2 сайта слили...а он давно статьи писал на дZене

Автор: Jon 6.11.2002, 09:09
напиши по подробнее для чего нужна команда int

Автор: Chingachguk 6.11.2002, 18:38
Как правило, в системе существуют одновременно кроме программы пользователя различные системные программы и обработчики прерывания.

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

Однако как правило программа запускается ОС и часто вызывает сервисы ОС. В свою очередь ОС вызывает программы БИОС(дос-семейства) или собственные обработчики (WinNT, Unix) или и те и другие (Win98) прерываний для доступа к устройствам (дискам, звуковой карте и проч.).

Как организовать вызовы таких обработчиков ? Ставим задачу: пусть выполняется программа пользователя и существуют аппаратные прерывания от таймера. При возникновении прерывания процессор (он не может выполнять одновременно несколько программ) должен "временно отложить" выполнение программы пользователя, выполнить некую "программу обработки события прерывания от таймера" и вернуться к выполнению основной программы; при этом он должен:

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

Начнем с конца. В процессоре 8086 для конкретизации места обработчиков прерываний в памяти в памяти начиная с адреса 0 расположена ТАБЛИЦА АДРЕСОВ обработчиков прерываний. Каждый адрес дальний (far), он состоит из сегмента обработчика и его смещения в этом сегменте. В таблице 256 элементов. Размер каждого адреса 4 байта: seg:offset. Заполняет эту таблицу адресами обработчиков кто угодно: bios - своими адресами, дос-другим, вирус - своими ;)

Аппаратно прерывания имеют свои номера: те процессор в момент прерывания знает лишь:

1) Произошло прерывание;
2) Номер прерывания.

Далее по номеру прерывания он вычисляет адрес обработчика по ТАБЛИЦЕ АДРЕСОВ:

Номер прерывания x 4 = Адрес в памяти Адреса Обработчика;

Извлекая найденный адрес, Он передает на него управление и запоминает в стеке адрес той точки основной программы, которая выполнялась на момент прерывания, чтобы вернуться к ней впоследствии, а также регистр флагов:

Действия процессора по сохранению контекста прерванной программы:

push  Flags
push  segment
push  offset

jmp   dword ptr 0000:[Номер прерывания x 4]

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

iret

Которая пользуясь сохраненным контекстом прерванной программы на стеке (выше) вернет управление:

Действия процессора по возвращению управлению прерванной программе:

Flags <- Флаги со стека
Восстановить стек
jmp на сохраненный адрес в стеке.

Таким образом, в памяти находятся программы, выполняющиеся в момент того или иного прерывания.

А теперь ответ на вопрос. Их можно вызывать программно. Те не процессор переключает задачу на них, а сам программист специальной командой int:

int NN, NN - Номер прерывания, опкод 0xCD,0xNN (2 байта).

После выполнения этой команды ДЕЙСТВИЯ ПРОЦЕССОРА АБСОЛЮТНО ЭКВИВАЛЕНТЫ его реакции на аппартное прерывание.

Разумеется, вызвать код обработчика можно не только командой int, а и call far, jmp far, retf... и т.д. Просто так удобнее ;)

Таким образом появляется возможность вызывать сервисы ОС, БИОС и всякие другие через Таблицу Адресов прерываний. Это удобно прежде всего тем, что вызов можно осуществить лишь ЗНАЯ НОМЕР ПРЕРЫВАНИЯ (иногда говорят "номер вектора") в отличии от того случая, когда вызов осуществляется по заданному адресу. Так, например в ОСь Linux осуществляется всего лишь вызовом int 80h в отличии от других Unix, где, к примеру, системную программу можно вызвать через дальний call:

call 0000:0007 ; Вызов системы в одном из unix.

ДОС может быть вызван по нескольким прерываниям:

int 20h, int 21h, int 23h, int 24h, ... ,int 25h, int 26h...

БИОС:

int 10h, int 13h, int 15h, ...

А вот в winNT можно вызвать систему также, в отличии от win98:

int 2Eh ; Вызов WinNT и ее наследников из пользовательского кода.

Автор: Jon 7.11.2002, 01:54
Почему в уроке 3 вы написали что видеобуфер начинаеться с A0000h, а в программе надо записывать 0A000h?

Автор: Chingachguk 8.11.2002, 06:45
Потому, что в программе мы оперируем содержимым сегментного регистра для доступа к памяти:

mov  ax,0a000h
mov  es,ax

в то время как процессор вычисляет адрес ячейки памяти следующим образом:

Адрес = Сегментный регистр(es - тот, который используется) x 16 + смещение.

Собственно, об этом я и писал где-то тама ;)

Автор: Jon 9.11.2002, 01:06
Как  считать значение ячейки и вывести её значения на экран.Допустим 1beh  :sneaky2

Автор: Chingachguk 9.11.2002, 19:40
Вот подпрограмма, которая позволяет сформировать изображение строки по адресу ds:[di] числа в регистре ax в шестнадцатеричном представлении:

HexChar proc near
 pusha ; Внимание: команды процессора 286. В паскале нужен ключ {G+}
 mov  cx,4
 mov  bx,offset TabHex
@GetHex:
 rol  ax,4
 push ax
 and  al,0fh
 xlat
 mov  [di],al
 inc  di
 pop  ax
 loop @GetHex
 popa
 retn
TabHex  db '0123456789abcdef'
HexChar endp

А вот пример вызова этой процедуры: пусть мы хотим вывести содержимое регистра es:


 mov  ax,es
 mov  di,offset MyString+4
 call   HexChar

MyString db 'es: ????$'

После этого мы можем легко вывести ее на экран:

 mov  ah,09h
 mov  dx,offset MyString
 int    21h

Автор: Ramstar 7.12.2002, 18:35
Win95chih модифицируйте а потом в нет выложите и все дела и будет мир играть в войну :p

Автор: dr.ZmeY 13.12.2002, 08:24
Chingachguk, в чём различая вывода на экран в режиме записи 1 и 2, если можно, на примере поясни...

Автор: Chingachguk 17.12.2002, 23:44
Цитата

Snick_Y2K Дата сообщения: 13.12.2002,00:24
Chingachguk, в чём различая вывода на экран в режиме записи 1 и 2, если можно, на примере поясни...


Я не совсем понял, что ты имеешь в виду. Если ты про то, что

Цитата

{Кусок рисования}
mov ax,0AC80h
mov es,ax
mov bx,0 {Начальное смещение ! - опять нуль !}
@Repeat:
mov byte ptr es:[bx],14
add bx,1
cmp bx,319 {Внимание ! Мы изменили и эту команду ! - вернули !}
jbe @Repeat
{Кусок рисования - Закончен}


так тут (собственно, в уроке 3 про это и рассказывается) идет речь о том, в процессоре адрес ячейки памяти формируется из двух частей - регистров: сегментного и смещения:

Адрес = сегментный регистр * 16 + регистр смещения;

Причем смещение может быть задано в самой команде или же построено даже из комбинации нескольких регистров (максимум - 2-х) и смещения !

Таким образом, раз мы задаем адрес из двух частей, то мы можем играться обеими частями таким образом, то общий адрес будет одним и тем же !

Вот там-то и был пример этого: можем рисовать одно и то же (заносить в одну и ту же память числа) двумя способами(или большим числом):

1. Задав сегмент равным 0A000h:

Цитата

{Кусок рисования}
mov ax,0A000h
mov es,ax
mov bx,160*320 {Начальное смещение = 160*320, линия 160}
@Repeat:
mov byte ptr es:[bx],14
add bx,1
cmp bx,319+160*320
jbe @Repeat
{Кусок рисования - Закончен}


2. Так, как приведено выше, те в сегментный регистр заноситься другое число, но такое, что:

0A000h x 16 + 320*160 = 0AC80h x 16 + 0
    |                                  |
   es                                 es

Автор: dr.ZmeY 19.12.2002, 08:05
Вот пример установки режима записи 2:
Код
MOV DX,3CEH  ;указываем на регистр адреса
MOV AL,5  ;инедксируем регистр 5
OUT DX,AL  ;посылаем индекс
INC DX  ;указываем на регистр режима
MOV AL,2  ;выбираем режим записи 2
OUT DX,AL  ;устанавливаем режим


Код

;---рисуем красную точку в левом верхнем углу экрана
MOV AX,0A000H  ;адрес буфера
MOV ES,AX  ;
MOV BX,0  ;указываем на первый байт буфера
;---установка регистра маски битов
MOV DX,3CEH  ;указываем на адресный регистр
MOV AL,8  ;регистр маски битов
OUT DX,AL  ;адресуем регистр
INC DX  ;указываем на регистр данных
MOV AL,10000000B  ;маскируем все биты, кроме 7-го
OUT DX,AL  ;посылаем данные
;---рисуем красную точку
MOV AL,ES:[BX]  ;заполняем регистры задвижки
MOV AL,4  ;красный цвет
MOV ES:[BX],AL  ;рисуем точку


Режим записи 1:  
Код
;---копируем строку в следующую строку
MOV CX,80  ;число байтов в строке
MOV BX,0  ;начинаем с 1-го байта буфера
MOV AX,0A000H  ;адрес буфера
MOV ES,AX  ;
NEXT_BYTE: MOV AL,ES:[BX]  ;заполняем задвижку
MOV ES:[BX]+80,AL  ;выводим в следующую строку
INC BX  ;переходим к следующему байту
LOOP NEXT_BYTE  ;


с точкой всё выходит, но при попытке создать линию, в режиме записи 2 на экран выдается какая-то хрень, а точнее точки находящиеся на расстоянии, а в графическом режиме 0013h и того хуже...

Автор: NightGoblin 25.12.2002, 16:37
Цитата(Chingachguk @ 09.11.2002, 11:40)
Вот подпрограмма, которая позволяет сформировать изображение строки по адресу ds:[di] числа в регистре ax в шестнадцатеричном представлении:
...

Если немного оптимизировать:

HexChar proc near
 pusha ; Внимание: команды процессора 286. В паскале нужен ключ {G+}
 mov  cx,4
;;  mov  bx,offset TabHex
@GetHex:
 rol  ax,4
 push ax
 and  al,0fh
;;  xlat
;; Тут:
 cmp  al, 10
 sbb  al, 69h
 das
;; ---
 mov  [di],al
 inc  di
 pop  ax
 loop @GetHex
 popa
 retn
;; TabHex  db '0123456789abcdef'
HexChar endp

Автор: Chingachguk 26.12.2002, 19:23
to Snick_Y2K:

У меня где-то дома валялся код для работы с битовыми плоскостями, все никак не донесу ;) Но будет ! А в 13h режиме вроде тока палитру менять через порты можна ;) Точки делать нужно просто через mov(movs).

to NightGoblin:

Ага, это известная фича. А вот слабо оптимизнуть вот эта:

Цитата

; Форматирование десятичного числа
 mov  di,offset NumBuff
 xor  ax,ax
 mov  al,[si].Head
 call DecChar
...
DecChar proc near
 pusha
 mov  cx,5
 mov  bx,10000
@GetDec:
 xor  dx,dx
 div  bx
 add  al,'0'
 mov  [di],al
 inc  di
 push dx
 xor  dx,dx
 mov  ax,bx
 mov  bx,10
 div  bx
 mov  bx,ax
 pop  ax
 loop @GetDec
 popa
 retn
DecChar endp

Автор: NightGoblin 31.12.2002, 19:06
2 Chingachguk:

Честно говоря, реально оптимизировать, наверное, действительно слабо :) Но я тут порылся немножко, нашел одно место... Если где приемник с источником спутаю - мне пришлось с Intel'а на AT&T переводить и обратно, так как с nasm разбираться, а тем более ставить DOS, лень... :) В общем, так должно быть немножко быстрее... Да, заодно сделал на 32-битных регистрах, так что максимальное значение числа 4G вместо 64K :)

Код

DecChar32 proc near

pushad
xor ecx, ecx
mov cl, 10
mov ebx, 1000000000
GetDec32:
xor edx, edx
div ebx
add al, 30h
mov byte ptr [edi], al
inc edi
push edx
mov eax, ebx
mov edx, 429496730
mul edx
mov ebx, edx
pop eax
loop GetDec32
popad
ret

DecChar32 endp


:)

Автор: ARTi 7.1.2003, 10:20
Вопрос: как наиболее универсально инициализировать звуковуху? То есть, предполагается, что в системе стоит нечто совместимое с SB и работа идет с ним или же нет?
Ситуация такая: был (и сейчас есть) эмуль ZX Spectrum под DOS в защищенном режиме. Хочется перевести его под DPMI, а винда его как раз поддерживает. В dos'е тоже можно запустить cwsdpmi.exe - и вот вам dpmi под dos. Так вот, в досе ясное дело как работать с звуковухой, а вот в винде он не везде эмулируется или эмулируется, но через зад.
Есть ли универсальный способ работы со звуковухой и в досе, и в виндах?

P.S. Если кто хочет, выложу всякие процедурки для работы с экраном.

P.P.S. А причем, извиняюсь, этот ... паскаль? Он к асму вообще никакого отношения не имеет, разве что только всего лишь поддерживает...

Автор: XpyDi 7.1.2003, 21:11
Цитата
Есть ли универсальный способ работы со звуковухой и в досе, и в виндах?

смотря какие винды, хотя лучше попробовать впихнуть в этот эмуль свои нормальные процедуры для работы со звуковой картой.
Цитата
P.S. Если кто хочет, выложу всякие процедурки для работы с экраном.

Говорю только за себя. Мне лично не нужно.
Цитата
P.P.S. А причем, извиняюсь, этот ... паскаль? Он к асму вообще никакого отношения не имеет, разве что только всего лишь поддерживает...

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

Автор: ARTi 7.1.2003, 21:51
Цитата
смотря какие винды, хотя лучше попробовать впихнуть в этот эмуль свои нормальные процедуры для работы со звуковой картой

Желательно любые винды. Но в 98-х поддержки SB в DOS-окне у меня почему-то нет (звуковуха - Audigy), а вот в XP есть, но с горем пополам. То есть, кто-то определяет, а кто-то нет, более того, звук, если и есть, то очень прерывистый, до тех пор, пока не повысишь приоритет до real time, но тогда уже ничего нельзя делать - просто сидеть и смотреть в экран...

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

В смысле? Когда знаешь "волшебные" слова BEGIN и END ?

Автор: NightGoblin 8.1.2003, 09:05
Цитата(ARTi @ 07.1.2003, 13:51)
Желательно любые винды. Но в 98-х поддержки SB в DOS-окне у меня почему-то нет (звуковуха - Audigy), а вот в XP есть, но с горем пополам. То есть, кто-то определяет, а кто-то нет, более того, звук, если и есть, то очень прерывистый, до тех пор, пока не повысишь приоритет до real time, но тогда уже ничего нельзя делать - просто сидеть и смотреть в экран...

Как правило, делается это через DMA - тогда таких проблем не будет. Общий принцип такой - пишешь в память кусок файла (.wav например), потом даешь звуковухе команду считывать данные оттуда через DMA (прямой доступ к памяти). Когда она доходит до конца, вызывает прерывание, обработчик которого пишет в память следующий кусок и так далее. Если очень надо, могу замылить файлик, воспроизводящий один .wav под DOS - не свой, правда, но, надеюсь, пойдет :)

Автор: ARTi 9.1.2003, 04:00
NightGoblin
Спасибо, но я, в общем-то, в курсе :). Просто в моей проге до этого даже дело не доходит (автодетект никак не может определить irq), а в других всяких там игрушках под дос, где, я думаю, все делается как раз правильно, звук прерывистый и искаженный.
В принципе, я вот думаю - ну сделаю я этот автодетект, но у меня, видимо, будет такой же искаженный звук как и везде. А привязываться именно к винде не хотелось бы.

Автор: NightGoblin 12.1.2003, 19:07
[offtopic]

Кстати, я вот смотрю - книга Зубкова С. В. - хорошая, стало быть, штука, раз ее все примером приводят :) Я правда в ней опечаток нашел несколько штук (в кодах), но мне так тоже очень даже помогла в освоении этого нехитрого, но, вместе с тем, коварного языка ;-)

Автор: ARTi 21.1.2003, 08:03
Да, книга Зубкова - достаточно крутая, вот если б ее лет эдак 7-8 назад...
А то все так: документаций нет - добываешь инфу кропотливым трудом и намеренными страданиями ;), а потом - бац! - так необходимая когда-то дока тут как тут!

Автор: [auxx] 9.2.2003, 03:20
Мне очень помогла книга В.Ю. Пирогова. До нее я асм знал, а писать не умел.

Автор: Vco 22.2.2003, 23:40
Вот это супер прога smile.gif)
Код

asm
@a1:cli
jmp@a1
end;

Отключает свсе регистры компа...))
Хотя думаю это несложно. Сам я когда паскаль учисл (немного), интересовался асемблером т.к. на паскале изварённый метод работы с прерываниями, а асма удобнее...
правда сам почти нечего не знаю... sad.gif но не чего, зато дельфи учу hehe.gif

Автор: Chingachguk 23.2.2003, 00:09
Цитата

Отключает свсе регистры компа...))


Не регистры, а в win98 вводит в транс драйвер, вирутализирующий флаг прерываний VIF ;)
В NT++ это уже не работает. А в досе просто cli, @L:jmp @L достаточно.

Автор: Vco 23.2.2003, 05:53
мда сразу видно ассемблер знает =)
блин я разрываюсь...то дельфи, до ещё, что, та ассемблер=))

Автор: Mikel 24.2.2003, 19:09
А вложенные циклы как можно сделать? Например, линии через одну нарисовать.

Автор: Wowa 24.2.2003, 19:36
Народ, может быть будем задавать вопросы, типа:

Цитата
А вложенные циклы как можно сделать? Например, линии через одну нарисовать.


в отдельной теме? а здесь только будут уроки.

Автор: Chingachguk 24.2.2003, 19:58
Цитата

Народ, может быть будем задавать вопросы, типа:

QUOTE 
А вложенные циклы как можно сделать? Например, линии через одну нарисовать. 


в отдельной теме? а здесь только будут уроки.


Не, я думаю - нормально. Ведь он задал вопрос по урокам...

Вот вложенные циклы: с декрементом счетчика (cx) и инкрементом (si) ...


Цитата

const
  StartX  = 50;
  StartY  = 50;
  LenLines = 70;
  LinesNum =  5;
  LinesCol = 35;
  StepY    =  7;
begin
  {Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
  asm
  mov  ax,0013h
  int  10h
  end;
  asm
  mov  ax,0A000h
  mov  es,ax
  {Рисуем линиии через одну при помощи вложенных циклов}
  mov  bx,StartY
  mov  si,0 {Счетчик числа линий}
@@OutLines:
  {Вычисляем координату начала очередной линии: 320*y+StartX}
  mov  ax,320
  mul  bx
  add  ax,StartX
  mov  di,ax
  mov  cx,LenLines
  {Вложенный цикл}
  @@OutLine:
      mov  byte ptr es:[di],LinesCol
      inc  di
      dec  cx
      cmp  cx,0
      jnz  @@OutLine
  {Переходим к следующей линии}
  add  bx,StepY
  inc  si
  cmp  si,LinesNum
  jb  @@OutLines
  end;
  {Ожидаем нажатия клавиши}
  asm
  mov  ah,0
  int  16h
  end;
  {Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
  asm
  mov  ax,0003h
  int  10h
  end;
end.

Автор: Mikel 26.2.2003, 03:27
Вот тоже написал smile.gif
Жду замечаний, комментариев.
И вопрос- а как можно было бы соединять линиями эти точки, если использовать ещё и паскаль- то понятно, а на чистом ассемблере?
Код
const
 col=10;
begin
asm
 mov  ax,0013h
 int  10h

 mov ax, 0000h
 int 33h
 mov ax, 0001h
 int 33h


 mov bx,0A000h
 mov es,bx

@@Cic:
 xor dx,dx
 xor cx,cx
 mov ax, 0003h
 int 33h

 shr cx,1

 mov ax,320
 mul dx
 add ax,cx
 mov bx,ax


 mov byte ptr es:[bx],col

 mov ax,bx
 sub bx,1
 mov byte ptr es:[bx],col

 mov bx,ax
 add bx,1
 mov byte ptr es:[bx],col


 mov bx,ax
 sub bx,320
 mov byte ptr es:[bx],col
 mov bx,ax
 sub bx,321
 mov byte ptr es:[bx],col
 mov bx,ax
 sub bx,319
 mov byte ptr es:[bx],col

 mov bx,ax
 add bx,320
 mov byte ptr es:[bx],col
 mov bx,ax
 add bx,321
 mov byte ptr es:[bx],col
 mov bx,ax
 add bx,319
 mov byte ptr es:[bx],col

 mov ah,01h
 int 16h
jz @@Cic

 mov  ax,0003h
 int  10h
end;
end.

Автор: Chingachguk 26.2.2003, 23:04
Вот так:

Цитата

const
  col=10;
  colline=14;
procedure line256(color:byte; x2,y2,x3,y3: word);
  begin
  asm
  push bp
  mov  si,x2
  mov  dx,y2
  mov  bx,x3
  mov  ax,y3
  push ax
  push dx
  mov  ax,dx
  mov  di,320
  mul  di
  add  ax,si
  mov  di,ax
  pop  dx
  pop  ax
  sub  bx,si
  sub  ax,dx
  mov  si,bx
  mov  bx,ax
  mov  cx,si
  mov  ax,bx
  cmp  cx,0
  jge  @1
  neg  cx
@1:
  cmp  ax,0
  jge  @2
  neg  ax
@2:
  cmp  cx,ax
  jae  @3
  xchg cx,ax
@3:
  cld
  mov  al,color
  mov  bp,cx
  test cx,cx
  jz @@Ex
@line:  push di
        push ax
        mov  ax,si
        imul cx
        idiv bp
        add  di,ax
        mov  ax,bx
        imul cx
        idiv bp
        mov  dx,320
        imul dx
        add  di,ax
        pop  ax
        stosb
        pop  di
        loop @line
@@ex:
  pop bp
  end;
  end;
var
  StartFlag: byte;
  CurrX:    word;
  CurrY:    word;
  LastX:    word;
  LastY:    word;
begin
asm
mov  ax,0013h
int  10h

mov ax, 0000h
int 33h
mov ax, 0001h
int 33h


mov bx,0A000h
mov es,bx
{Флаг: последней точки нет в начале}
mov  StartFlag,0
@@Cic:
xor  dx,dx
xor  cx,cx
mov  ax,0003h
int  33h

shr  cx,1
{Запоминаем координаты текущей точки}
mov  word ptr CurrX,cx
mov  word ptr CurrY,dx

mov  ax,320
mul  dx
add  ax,cx
mov  bx,ax

{mov  byte ptr es:[bx],col
mov  byte ptr es:[bx-1],col
mov  byte ptr es:[bx+1],col
mov  byte ptr es:[bx-320],col
mov  byte ptr es:[bx-321],col
mov  byte ptr es:[bx-319],col
mov  byte ptr es:[bx+320],col
mov  byte ptr es:[bx+321],col
mov  byte ptr es:[bx+319],col}

{Проверяем, первое ли вхождение}
cmp  byte ptr StartFlag,0
mov  byte ptr StartFlag,1
jz  @@NoDrawLastPoint
{Рисуем линию от текущей точки к предидущей }
{Оформляем стек вызова процедуры на языке Паскаль}
mov  ax,colline
push ax
push word ptr CurrX
push word ptr CurrY
push word ptr LastX
push word ptr LastY
call line256
@@NoDrawLastPoint:
{Запоминаем текущую точку}
mov  cx,word ptr CurrX
mov  dx,word ptr CurrY
mov  word ptr LastX,cx
mov  word ptr LastY,dx

mov  ah,01h
int  16h
jz  @@Cic

mov  ax,0003h
int  10h
end;
end.


Следует заметить, что код процедуры line256 я писал давно, когда только начал изучение ассемблера ;)

Автор: Dark 18.5.2003, 04:12
Спасибо, Chingachguk, очень круто, мне понравилось, да... странно, ноя тоже взялся за етот непростой труд - туториалы wink.gif Круто объясняешь, я по моему хуже...
:-((( мою версию покачто моно взять на
http://forum.pascal.dax.ru/?board=assm;action=display;num=1052781903

Спасибо, если дашь коментарий... можешь написать мне на [email protected]

Автор: Chingachguk 2.6.2003, 16:46
Извини, что не посмотрел сразу, Dark

Обязательно гляну и отпишу !

Автор: GriKo 8.6.2003, 14:35
Ну самое простое должно быть наверное вот так :

begin
{Устанавливаем графический режим монитора 13h, 320x200, 256 цветов}
asm
mov ax, 00013h
int 010h
end;
asm
{Кусок рисования}
mov ax, 0A000h
mov es, ax
mov bx,0
@rep:
mov byte ptr es:[bx],4
add bx,1
cmp bx,200*320-1
jbe @rep
end;
{Ожидаем нажатия клавиши}
asm
mov ah,0
int 16h
end;
{Устанавливаем текстовый режим монитора 03h, 80x25, 16 цветов текста и фона}
asm
mov ax,0003h
int 10h
end;
end.

Автор: GriKo 8.6.2003, 14:36
sorry, я немного подтормозил с ответом... =)

Автор: Chingachguk 10.6.2003, 08:48
Цитата

{Кусок рисования}
mov ax, 0A000h
mov es, ax
mov bx,0
@rep:
mov byte ptr es:[bx],4
add bx,1
cmp bx,200*320-1
jbe @rep
end;


Это ты закрашиваешь весь экран красным цветом ? Да, можно и так. А можно и так:

Цитата

mov  cx,320*200
xor  di,di ; di=0
mov  al,4 ; al=color
cld
rep  movsb


или даже так:

Цитата

mov  cx,320*200/2
xor  di,di ; di=0
mov  ax,4+256*4 ; al,ah=color
cld
rep  movsw


А вот сможешь ли ты нарисовать линию в этом графическом режиме ? Входные данные: (X1,Y1) и (X2,Y2) - точки.

Автор: Oleg Grafov 11.6.2003, 23:34
Киньте что-нибудь по написанию резидентов, а еще лучше, если кому не трудно, киньте код следующей проги smile.gif, очень надо:

Сохранение/восстановление экрана
При нажатии одной из клавиш видеопамять текущей страницы текстового экрана(вместе с атрибутами) сохраняется в памяти. При нажатии другой комбинации клавиш в текущую видеостраницу загружается ранее запомненная копия.

Помогите, просто нет времени писать самому sad.gif


Автор: Chingachguk 12.6.2003, 00:08
Цитата

.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

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















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

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

Автор: vanya 10.7.2003, 07:39
Помогите зарегистрированному Ламмеру с прогой Ассемблер!

Автор: Shuricksoft 11.7.2003, 13:16
Chingachguk, вот я бы хотел изучить работу с внешними устройствами - объяснишь заодно и порты, и прерывания =) А потом бы хотел загрузчик. Вот тебе пожелания - надеюсь, ты их осуществишь в ближайшем времени, за что я тебе заранее благодарен wink.gif

Автор: Chingachguk 11.7.2003, 15:33
О'кей ;)

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

Автор: Baa 13.7.2003, 01:14
Shuricksoft, на wasm.ru сейчас идет серия статей про загрузчики...

Автор: Shuricksoft 13.7.2003, 22:31
Baa, сенкс! Завтра гляну... Но всё равно Chingachguk forever :-)

Автор: Chingachguk 17.7.2003, 14:12
Урок 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 раз в секунду).

Автор: Shuricksoft as a guest 11.9.2003, 23:02
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
О, я даже чуть оптимизировал третье задание с утра =)
Как я понимаю, с регистрами работать намного быстрей и приятней, чем с переменными, поэтому...
Код

...
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
Хм... Первый вариант (теоретически) был верный (я насчет 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).

Автор: Shuricksoft as a guest 14.9.2003, 16:17
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
О, это тонкая ошибка ! Попробуй сам догадаться, в чем дело (верный код):

Цитата

  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 и т.п. на регистры.

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

Автор: Chingachguk 19.9.2003, 08:26
Цитата

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


Нет, дело не в этом ;) Смотри, я вернул почти все к тому варианту, который был у тебя:

Цитата

  { Цикл опроса клавиатуры ~ repeat until keypressed }
  repeat
    { Рисуем квадрат размером MyScreenBarSize с центром в MyScreenCenter }
    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
        jb  @@XCycle
        mov ax,MyScreenBarSize
        cmp IndY,ax
        jb  @@YCycle
    inc MyScreenBarSize
    end;

    { Если размер стал более чем MaxBarSize }
    if MyScreenBarSize>=MaxBarSize then MyScreenBarSize:=1;
    { Проверяем кейбоард }
  until keypressed;


Разница - в двух командах.

Цитата

По поводу оптимизации, пользуясь твоей подсказкой, вынес строки
mov ax,0A000h
mov es,ax
непосредственно перед началом циклов. Больше ничего сделать не смог.


Все абсолютно верно !

Автор: Shuricksoft as a guest 20.9.2003, 11:54
О, всё, я понял свою ошибку =)
Кстати, заодно, если тебе не сложно, приведи, пожалуйста, все известные тебе версии команды jmp с описанием (ну, jnz, jb, jbe - это понятно, а ещё какие?).
Это хорошо, что верно =) Продолжаем? wink.gif

Автор: Mura-vey 22.9.2003, 00:47
Chingachguk Я внимательно ознакомился с уроками, задания правда не делал, но обязательно попробую как будет время.

Теперь самый каверзный вопрос: Как связать паскаль и ассемблер ? Сколько не пытался не получалось. Надо что бы просто и доступно было.

Автор: Monty 22.9.2003, 01:29
Можно так
Код
..........
var
I, J: integer;
begin
 I := 22;
 asm
   mov J, I
   add J, 11
   xor I, I
 end;
//посмотри теперь на значение переменных, это только самое простое
...............
end;

smile.gif

Автор: Chingachguk 22.9.2003, 15:57
Цитата
Кстати, заодно, если тебе не сложно, приведи, пожалуйста, все известные тебе версии команды jmp с описанием (ну, jnz, jb, jbe - это понятно, а ещё какие?).


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

В общем и целом все команды сравнения основываются вот на чем: для сравнения чего бы то ни было процессор использует сложение (вычитание - это тоже сложение). Сложение двоичных счетчиков. На основании результата модифицируется так называемый регистр флагов - вспомогательный регистр процессора. Все команды сравнения используют этот регистр для анализа. Например, мы хотим проверять, вышли ли мы за пределы размерности байтовой переменной при сложении регистров AL и AH:

Цитата

mov  al,Value1
mov  ah,Value2

add  al,ah


Требуемая логика: так как в регистре al 8 бит, то максимум, который может быть в нем - это число 255 (без знака) (или 0xFF или $FF или 011111111b или...). При сложении 10 и 10 в al будет 20, при сложении 100 и 100 - 200, при сложении 254 и 1 будет 255, а вот если сложить 255 и 1, то будет 0. Напоминаю, процессор складывает регистры как двоичные счетчики (типа связанных в цепочку триггеров) без насыщения, те если все биты (триггеры) в состоянии 1, то следующий добавляющий импульс последовательно сбросит все биты в 0. Так вот, нам нужно знать, когда произошел такой вот переход (те сумма Value1+Value2 > 255):

Цитата

mov  al,Value1
mov  ah,Value2

add  al,ah
; IF (AL+AH>255) THEN ... ELSE ...


Как это сделать ? Есть такой факт, что процессор контролирует факт переноса (перехода через максимальное значение) устанавливая в определенное состояние определенный бит регистра флагов. Этот бит имеет название CF (Carry Flag). Таким образом, после сложения можно опереться на этот факт:

Цитата

mov  al,Value1
mov  ah,Value2

add  al,ah
jnc @@Then ; Jump if not carry
@@Else:
; ...
@@Then:
; ...


Команда jnc как раз проверяет, установлен ли флаг CF. Точнее говоря, она проверяет его состояние (я не помню, 0 или 1 является признаком переноса).

На таких вот изменениях регистра флагов и основаны все команды условных переходов. В регистре флагов несколко таких флажков.

Цитата
Продолжаем? 


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

Цитата
LAHF ; Load to AH register FLAGS


Попробуй вывести состояние регистра флагов. Если сможешь, понаблюдай за тем, как он меняется после различных команд сложения, вычитания... и т.п. Поиграйся с ним, короче ;)

Цитата
Теперь самый каверзный вопрос: Как связать паскаль и ассемблер ? Сколько не пытался не получалось. Надо что бы просто и доступно было


Гм, я как раз тут об этом все время говорю. Попробуй задать конкретный вопрос ;) Например: как мне сложить две пас-переменные с помощью ассемблера или как мне написать функцию на ассемблере, получающую указатель на массив WORD'ов и сортирующую его и т.п.

Автор: Mura-vey 23.9.2003, 17:16
Хорошо, тогда задачка такая. На паскале мы вводим одномерный массив А[1000] и сортируем его на ассемблере, а выводим снова в паскале.

Автор: Mura-vey 23.9.2003, 17:17
Разумеется прога сортирования написана отдельно! Полученый обж мы должны слинковать с прогой на паскале.

Автор: Shuricksoft as a guest 23.9.2003, 21:37
По поводу регистра флагов нашёл, что за перенос отвечает младший (самый правый =) ) бит. 0 - переноса нет, 1 - есть. Потом нашёл в отладчике, где отображается этот регистр =) Там нашёл ZF, принимающий значение 1, если результат сравнения "равно" и 0, если "не равно". Больше ничего толком не понял. Там есть ещё что-то интересное? =) Кстати, не уловил, где "больше-меньше" указывается? Или это проверяет сам компилятор вычитанием?

Автор: Chingachguk 27.9.2003, 16:02
Цитата
Хорошо, тогда задачка такая. На паскале мы вводим одномерный массив А[1000] и сортируем его на ассемблере, а выводим снова в паскале.


Сначала по поводу вызова асм-кода.

Этот код помещаем в файл sort_bub.asm и компиллируем:

Цитата

CODE SEGMENT BYTE PUBLIC
      ASSUME CS:CODE
      PUBLIC  Sort_Bubble
Sort_Bubble PROC NEAR
  push bp
  mov  bp,sp
  mov  cx,[bp+4] ; Len of massive
  dec  cx
  jz  @@SortBubbleDone
@@SortBubble:
  push cx
  mov  si,[bp+6] ; Address of massive
@@OneStep:
  mov  ax,[si]
  cmp  word ptr [si+2],ax
  jae  @@NextElemNoLow
  xchg [si+2],ax
  mov  [si],ax
@@NextElemNoLow:
  inc  si
  inc  si
  loop @@OneStep
  pop  cx
  loop @@SortBubble
@@SortBubbleDone:
  pop  bp
  RET  2*2
Sort_Bubble ENDP
CODE  ENDS


masm sort_bub

Должен получится файл sort_bub.obj

Теперь паскаль:

Цитата

const
  MyMasLen = 10;
var
  MyMas: array[1..MyMasLen] of word;
  i: word;
{$L sort_bub.obj}
procedure Sort_Bubble(MasOffset,MasLen: Word); external;
begin
  randomize;
  write('Mas before:');
  for i:=1 to MyMasLen do
    begin
      MyMas[i]:=random(10);
      write(' ',MyMas[i]);
    end;
  writeln;
  Sort_Bubble(ofs(MyMas),MyMasLen);
  write('Mas after :');
  for i:=1 to MyMasLen do write(' ',MyMas[i]);
  writeln;
  readln;
end.


Но я предпочитаю не размещать асм-код в отдельных файлах, а писать его в асм-вставках в теле паскалевских программ.

Автор: Chingachguk 27.9.2003, 16:23
Цитата
По поводу регистра флагов нашёл, что за перенос отвечает младший (самый правый =) ) бит. 0 - переноса нет, 1 - есть.


С помощью lahf ? Если так, то ты выполнил "задание" !

Цитата

Потом нашёл в отладчике, где отображается этот регистр =) Там нашёл ZF, принимающий значение 1, если результат сравнения "равно" и 0, если "не равно". Больше ничего толком не понял.


А пока особо ничего и не надо ;) Я же говорю - при решении конкретной задачи возникает необходимость чего-либо, тогда и узнаешь все досконально. В данном случае регистр флагов - это "самый нижний" уровень, доступный программисту. А не команды условных переходов. Ведь, изучая ассмеблер, стремишься добратся до "самого основания", пуркуа па ?

То, что ты обратил внимание на существование отладчика - хорошо !

Цитата

Там есть ещё что-то интересное? =) Кстати, не уловил, где "больше-меньше" указывается? Или это проверяет сам компилятор вычитанием?


Нет, компиллятор ничего не делает. Он просто втыкает команды, причем не всегда удачно.

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

Цитата

cmp ax,bx
jb @AXLowThanBX ; jump if below

cmp ax,bx
ja @AXGreatThanBX ; jump if above

cmp ax,bx
jbe @AXLowOrEqualThanBX ; jump if below or equal


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

А вот и задание (достаточно сложное !). Пусть есть команда сравнения AX и BX и условный переход после:

Цитата

cmp ax,bx
; <...>
jb @AXLowThanBX ; jump if below


Требуется: инвертирование результата сравнения после команды cmp ax,bx после команды cmp и перед командой jb (выделено <...>). Что имеется в виду ? Допустим, если ax=10, а bx=300, то результат будет "меньше". Необходимо сделать его "больше или равно", чтобы команда jb получила его (в регистре флагов - а где еще ?). Если же результат сравнения будет "больше или равно", то нужно сделать его "меньше".

Для выполнения задания требуется команда загрузки регистра флагов значением. Этой командой может быть sahf - загрузить регистр флагов из регистра ah или popf (из стека).

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


Автор: Shuricksoft as a guest 30.9.2003, 15:24
Да, с помощью lahf
Цитата
Нет, компиллятор ничего не делает. Он просто втыкает команды, причем не всегда удачно.

Ну, я имел в виду, что компилятор суёт команды вычитания, то есть, программа проверяет, засунутыми командами. Вычисляет разность, проверяет флаг переноса и дальше реагирует, как ей надо.
Предыдущая гипотеза подтверждается тем, что, как я обнаружил, за меньше-больше тоже отвечает флаг переноса... Если 1 - меньше, если 0 - больше. Ну, а за "равно", судя по всему, отвечает четвёртый слева бит.
Задание я понял. Идея тоже есть. Но не могу осуществить, пока не узнаю, как получить доступ к отдельно взятому биту регистра... Ломал голову довольно долго, да решил у тебя спросить =) Ну, никак не могу понять, как инвертировать в регистре один-единственный (ну, или, в нашем случае, два) бит...

Автор: Chingachguk 3.10.2003, 22:09
Цитата
Но не могу осуществить, пока не узнаю, как получить доступ к отдельно взятому биту регистра... Ломал голову довольно долго, да решил у тебя спросить =) Ну, никак не могу понять, как инвертировать в регистре один-единственный (ну, или, в нашем случае, два) бит...


Если ты писал на СИ (а ведь писал, не так ли ?), то должен был видеть вот такие операторы: "^","|","&","~". Это так называемые битовые операторы: xor, or, and, not...

Естественно, они есть и в ассемблере. Только работать с битами на нем гораздо легче ;) Набор команд больше и они гибче:

Цитата

xor  ax,22h ; ax ^ = 22h
or    bl,11h  ; bl| = 11h
and byte ptr es:[bx+di+22h],7 ; AND Память в es:[bx+di+22h] с 7
...
; И так далее


Легче потому, что в асме команд для битов больше и они гибче. Это и понятно - ассемблерный код должен уметь заставить процессор делать все, что тот умеет, а процессор работает также и с битами.

Например, в языках высокого уровня нет команды test. Обычно для проверки битов пишут что-то вроде:

Цитата

for (i=0;i<8;i++)
{
  if (value&(1<<i))
  {
    // Если i-ый бит установлен (не равен нулю)
  }
}


Но ведь можно написать:

Цитата

mov  cx,1
@@Cycle_i:
  test value,cx
  jz  @@BitNotSet
  ; Если i-ый бит установлен (не равен нулю)
@@BitNotSet:
  shl  cx,1 ; Сдвинуть бит налево (например, значение 4 перейдет в 8)
  cmp cx,100000000b ; Двоичная запись числа 256
  jb @@Cycle_i:


Вот так smile.gif

Автор: Shuricksoft as a guest 4.10.2003, 22:35
На Си я писал довольно мало. В основном, на Паскале. And, or, xor, not я видел, но не знал, что они делают :-/ Поэкспериментировав, пришёл к выводу, что xor ax,i инвертирует i-тый бит регистра ах; and ax,i устанавливает туда 0; or ax,i - устанавливает 1; not ax инвертирует все биты. Все это установил на основе экспериментов, так что если я что-то понял неправильно, поправь меня, плз =)
Таким образом, получается вот такой код там, где <...>
Код

lahf
xor ah,1
sahf

Этот код на "ура" меняет больше на меньше и наоборот. Несколько по-другому дело обстоит с "равно". В данном примере (приведённом тобой коде) такой фокус работает. Но если проверять через je или jne, то получается, что ни один бит (после неудачных попыток определить, какой нам нужен, проверял все подряд) при инвертировании не инвертирует результат :-/ Почему так?

Автор: Shuricksoft 4.10.2003, 22:43
Я вчера ночью перед сном разобрался с and, or и xor, так что предыдущую версию этого поста считать недействительной =)
Но просьба в силе: приведи, плз, паскалевский эквивалент value&(1<<i). Остальное понял, а вот что значит два знака << и почему это в скобках - неясно =)
А рабочий код, работающий с "равно", приведу чуть позже =)

Автор: Shuricksoft 5.10.2003, 21:26
Вот этот код, с виду, работает. Инвертирует значение флага равенства и флага "больше-меньше". Можно, конечно, проверять, надо ли нам инвертировать флаг равенстсва, но к изменению результата это не приведёт, а код увеличит, уменьшив быстродействие =)
Код

lahf
xor ah,01000001b
sahf

Автор: NightGoblin 7.10.2003, 02:43
Shuricksoft,
не знаю как в паскале, а операторы << и >> в си - это операторы логического сдвига, на асме это команды SHL/SHR соответственно: сдвигают битовое значение регистра влево/вправо, заполняя освободившиеся биты нулями... Плюс, есть SAR для чисел со знаком (арифметический сдвиг) - в этом случае биты, освобождающиеся после сдвига, заполняются не нулями, а старшим (знаковым) битом.

Еще в асме есть хорошие команды циклического сдвига (ROR/ROL/RCR/RCL), которых, к сожалению, на си нет.

Автор: Shuricksoft 7.10.2003, 14:18
NightGoblin, что самое весёлое, в Паскале slr/shr команды так и пишутся =) Эх, ещё раз убеждаюсь, что Паскаль явно удобней С. Но это уже отдельная история =)
А вот sar/ror/rol/rcr/rcl в Паскале тоже нет.

Автор: Chingachguk 13.10.2003, 10:14
Цитата

Но просьба в силе: приведи, плз, паскалевский эквивалент value&(1<<i). Остальное понял, а вот что значит два знака << и почему это в скобках - неясно =)


В Паскале в этом смысле все то же самое - ну, об этом уже написали. В этом конкретном примере же:

Цитата

if (value and (1 shl i)) <> 0 then

или даже такой вариант:

if ((value shr i) and 1) = 1



Цитата

Вот этот код, с виду, работает. Инвертирует значение флага равенства и флага "больше-меньше". Можно, конечно, проверять, надо ли нам инвертировать флаг равенстсва, но к изменению результата это не приведёт, а код увеличит, уменьшив быстродействие =)

CODE 

lahf
xor ah,01000001b
sahf


Я думаю, с этим пока достаточно ;) Главное было разобраться в общем, а в деталях в конкретной задаче ты разберешься сам !

Следующее занятие (урок), если я соберусь со временем, я планирую посвятить BOOT...

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

Цитата

Procedure DrawLine256(X1,Y1,X2,Y2: word; Color: Byte);
  begin
  asm
  mov  ax,0A000h
  mov  es,ax
  mov  ax,X1
  { ... }
  end;
  end;


Помни, что к переданным параметрам (здесь - по значению) в асм-вставке так и обращаются: mov bx,Y2 или mov al,Color. Также следует знать, что нельзя разрушать входные значения регистров SS,DS,BP,SP (если необходимо, можно сохранить и восстановть их на стеке или (для SS:SP) в ячейке памяти). Однако в данном случае можно определять локальные переменные и спокойно их использовать:

Цитата

Procedure DrawLine256(X1,Y1,X2,Y2: word; Color: Byte);
  var
    TempX: word;
  begin
  asm
  mov  ax,X2
  mov  TempX,ax
  { ... }
  end;
  end;


и т.п.

Это довольно сложная задача, но с простым условием: построить линию, начинающуюся в точке с координатами (X1,Y1) и заканчивающуюся в точке (X2,Y2).

Автор: Shuricksoft 14.10.2003, 11:55
Кажется, я знаю, как выполнить эту задачу... Только мне надо знать, как производить деление. Нашёл в электронном справочнике, что это делается командой div. Решил проверить на простом коде:
Код

...
var
b : byte;
...
asm
mov b,2
mov al,10
div b
...

ну, дальше - вывод на экран =) Так вот, после выполнения команды деления выскакивает ошибка деления на ноль! А вроде как делитель не равен нулю и разрядность частного не превышает разрядность регистра... В чём ошибка и как правильно производить деление?

Автор: Shuricksoft 14.10.2003, 13:53
Всё, понял сам =) Всего заменить al на ax =)

Автор: oleg1973 14.10.2003, 14:14
деление это не по модному ( я про div оператор) smile.gif
чтоб на 2 поделить нада вправо на 1 сдвинуть smile.gif
mov eax,10
shr eax,1

все в еах результат будет smile.gif

Автор: Shuricksoft 14.10.2003, 14:22
А с чего ты взял, что я буду на 2 делить? biggrin.gif Тем более, мы здесь пока под ДОС асм-ом балуемся, а ты с расширенными регистрами wink.gif

Автор: oleg1973 14.10.2003, 15:21
mov ax,10
shr ax,1

под дос вариант smile.gif
а на 2 как у тебя в примере smile.gif


Автор: Shuricksoft 14.10.2003, 15:56
Я понимаю, как это под ДОС выглядит =)
А, ну, значит, пример такой попался неудачный =) Там любое число может быть =)

Автор: Chingachguk 15.10.2003, 08:44
Цитата

mov ax,10
shr ax,1

под дос вариант


Вот и нет. Спокойно пишем:

Цитата

begin
  asm
  db 066h,0B8h,00Ah,000h,000h,000h {mov eax,10}
  db 066h,0D1h,0E8h {shr eax,1}
  end;
end.


Цитата

Кажется, я знаю, как выполнить эту задачу... Только мне надо знать, как производить деление.


Про деление уже писали, а вот есть и команды умножения: mul и imul (знаковая). Кстати, есть знаковое деление: idiv

Автор: Chingachguk 15.10.2003, 08:53
Цитата

mov ax,10
shr ax,1

под дос вариант


Вот и нет. Спокойно пишем:

Цитата

begin
  asm
  db 066h,0B8h,00Ah,000h,000h,000h {mov eax,10}
  db 066h,0D1h,0E8h {shr eax,1}
  end;
end.


Цитата

Кажется, я знаю, как выполнить эту задачу... Только мне надо знать, как производить деление.


Про деление уже писали, а вот есть и команды умножения: mul и imul (знаковая). Кстати, есть знаковое деление: idiv

Автор: oleg1973 15.10.2003, 13:47
Chingachguk smile.gif

Автор: NightGoblin 15.10.2003, 21:25
Chingachguk,
ну это уже машинный код пошел, а не асм =)))

Автор: Chingachguk 15.10.2003, 22:02
Байты я забил ибо Пас не "вкуривает" команды выше 286. Даже в obj.

На самом деле для "доса" я даже "такое" писал (это кусок патча):

Цитата

.586p
HookedVector   equ 1
VectorEMM      equ 67h
VectorSelf     equ 63h
MaxPackets     equ 10000    ; Packets in ring buffer
DebugPort      equ 177h
; Table 2914
Table2914 struc
  _CR3      dd ?
  _GDTRaddr dd ?
  _IDTRaddr dd ?
  _LDTR     dw ?
  _TR       dw ?
  _CS_EIP   dq ?
Table2914 ends
...
;
@@InsertingCode:
;;  jmp  @@SkipSubroutins
; Set Stack - like sf
  ;;mov  ss,dx
  ;;mov  esp,ebx
; Set Trap(s)
  mov  eax,cr4
  or   eax,01000b
  mov  cr4,eax
  mov  eax,(0110011001100110b shl 16)+(07FFh) ; 020703h ; 010000001100000010b
  push ebx
  xor  ebx,ebx
@@MoveBXPort:
  mov  bx,DebugPort ; ds:Port
  mov  dr7,eax
  mov  dr0,ebx
  add  ebx,2
...



... Жаль, не застал я времени дос-экстендеров ;(((

Автор: Serzh 17.10.2003, 01:56
Я вернулся!!!
Раньше я был Melancholy, но забыл пароль и теперь я Serzh!!!
че тута происходит?
;)

Автор: Gannibal 29.12.2003, 13:02
Ну если здес все професионалы так подскажите мне компилатор длыа C+АSМ кроме Борланд и Висуала...tnx

Автор: oleg1973 29.12.2003, 15:56
gcc, Lcc, watcom

Автор: foRaver 6.1.2004, 19:34
Вот тут книжечку откопал по АСМьу, даже очень классная, всем советую: http://www.fh-augsburg.de/~hhoegl/mnp/www/drpaulcarter/pcasm-book.pdf

Автор: SashOk_ 8.2.2004, 05:25
Все вышесказанное конечно хорошо и приятно, однако никто не подскажет ресурсы для asm32, посколбку программировать под DOS уже НЕ актуально. Не плохо было бы пару примерчиков представить с коментариями.

Автор: oleg1973 8.2.2004, 13:30
примерчик: (компилить в fasm)

format PE GUI 4.0 <----- тут говорим какой файл будем компилить
include '%fasminc%/win32a.inc' <----- тут всякие виндосовские значения
start:
invoke MessageBox,0,txt,txt,0 <--- API рисуем месаджбокс
invoke ExitProcess,0 <----API выходим из программы
txt:
db 'hello world!',0

include '%fasminc%/api.inc' <---- тут собственно описания импортируемых функций для таблицы импорта


Автор: SKN 20.3.2004, 19:18
Как мне защитить программу от трассировки по прерываниям и работы под контролем отладчика, с помощью переопределения какого-либо прерывания (например 25h)? adv/burnout.gif

Автор: oleg1973 21.3.2004, 01:36
ты уж отдельный топик сделай со своим вопросом

Автор: Chingachguk 21.3.2004, 01:45
Цитата
Как мне защитить программу от трассировки по прерываниям и работы под контролем отладчика, с помощью переопределения какого-либо прерывания (например 25h)? 


Что такое 25h ? Debug прерывания - это int 1 и int 3. Да и где ? В дос ? Тогда в некоторых случаях может помочь переустановка (или использование для саморасшифровки) этих прерываний. Или в win ? От какого отладчика ?

Автор: SKN 21.3.2004, 22:13
Что такое 25h ? Debug прерывания - это int 1 и int 3. Да и где ? В дос ? Тогда в некоторых случаях может помочь переустановка (или использование для саморасшифровки) этих прерываний. Или в win ? От какого отладчика ?

OS -=- Win NT
25h -=- номер прерывания, понимаю ответ тупой, но в этой ос не знаю как снять запрет на просмотр векторов прерывания, и отсюда пошли все коллизии, чем дальше в лес тем.....

отладчика -=- это я ругнулся на Дизасемблерный софт, SoftIce и так далее, понимаю...тоже не лучшая перспектива их так называть, фактически смысл ограничивается тем, чтобы я смог переопределить это прерывание в Win NT, далее как напутать я вроде придумал идейку

Автор: Chingachguk 22.3.2004, 16:44
Что значит - переопределить "это" прерывание ? Если не знаешь точно, какой номер прерывания, то, может, скажешь, что оно делает ?

Автор: skn 22.3.2004, 18:32
Что значит - переопределить "это" прерывание ? Если не знаешь точно, какой номер прерывания, то, может, скажешь, что оно делает ?

номер прерывания -=- 25h
что делает -=- устанавливает вектор прерывания

мне необходимо написать на 25h новый обработчик.

мне необходим код который
{
повесит новый обработчик notify.gif
//мой код
вернет все как было notify.gif
}

Автор: Chingachguk 23.3.2004, 09:17
А ! ж)))

Я понял Вас. Это вектор исключительно досовский. Точнее даже не вектор, а функция (ah=25h) вектора int 21h. Однако в win все сложнее - неудивительно, там столько драйверов.

Для некоторых int'ов в win есть службы, их устанавливающие, есть службы, позволяющие встроится в цепочку обработчиков прерывания. Для отладочного прерывания, возможно, существует свой отдельный сервис. Однако (я про 98, но не думаю, что в nt что-то другое) к таким сервисам могут обращатся исключительно драйвера или код, который прорвался в ring0 "нелегально". Да и вообще никто (это справедливо для дос тем более) не может помешать драйверу установить свой обработчик прерывания "вручную", минуя всякие там сервисы системы. Например, защита 1C руками правит idt (таблица векторов защищенного режима) из собственного драйвера (hasp95dl.vxd) и никто ей в этом не мешает.

Автор: Guest 23.3.2004, 20:36
прошу прощения я малость перепутал, речь не про функцию inlove.gif а про прерывание 25h( считывание информации напрямую с диска)...
необходим код на который win ругаться не будет notify.gif

Автор: oleg1973 24.3.2004, 21:50
оно по любому ругатся будет если попытатся из доса напрямую сектора на харде читать

Автор: Vira 2.6.2004, 06:59
Доброе утро...У меня вопрос:Где взять Help по прерываниям???

Автор: Akina 2.6.2004, 08:11
Цитата
Где взять Help по прерываниям???

http://www.pobox.com/~ralf/files.html

Автор: ZAVS 4.6.2004, 02:18
лучше возмите книгу Абеля и читайте smile.gif

Автор: vilfred 14.6.2004, 23:32
Цитата(SashOk_ @ 8.2.2004, 05:25)
Все вышесказанное конечно хорошо и приятно, однако никто не подскажет ресурсы для asm32, посколбку программировать под DOS уже НЕ актуально. Не плохо было бы пару примерчиков представить с коментариями.

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

Нам вот надо сейчас сделать некоторую обработку файлов формата FITS, была бы эти проги на асме, то в нашей обсерватории было бы все под досом, кроме файрвола линуксового разве что... идеи есть - а как это реализовать быстро - не ясно.

А уроки реально - просто рулезные. И написаны тоже так же. Мегареспект!

Автор: Гость_Andrew 21.6.2004, 14:46
Я конечно понимаю что уже дофига говорилось про таймер, но то все про интервалы минимум у которых 55 мс, а как сделать програмку чтоб она каждые 5 мс (или еще чаще) какую-нить цифирку на экран выводила? Если кто может помочь или пример привести не стесняйтесь, пишите smile.gif .Особенно обрадует если это будет как асмовская вставка в СИ.

Автор: Chingachguk 21.6.2004, 20:34
Под дос ?

1) Перепрограммирование таймера на другую частоту;
2) Интерфейс прерывания ~int 15h (bios) - вплоть до сотен мкс (!), но не всякая винда его держит.

Автор: Гость_Andrew 28.6.2004, 12:45
А можешь простенькую програмку привести, тока полностью на асме написанную

Автор: Chingachguk 28.6.2004, 18:45
Вот это может работать (задержка в мкс):

Код

PROCEDURE DLY(MSEC:WORD);
BEGIN
  ASM
   MOV  AX,MSEC
   MOV  DX,1000
   MUL  DX; DX:AX=microseconds
   MOV  CX,DX
   MOV  DX,AX
   MOV  AH,86H
   INT  15H; wait CX:DX microseconds
  END;
END;

Автор: Гость_Andrew 29.6.2004, 14:57
Так это просто как пауза получается? Но "microseconds" он не понимает, а если его как переменную обозвать то он на синтаксис ругается.

Автор: Chingachguk 29.6.2004, 21:01
Кто ругается ?! ;) Это вставка в языке Паскаль. Вот как это будет на СИ:

Код

void DLY(unsigned int MSEC)
{
 asm {
   MOV  AX,MSEC
   MOV  DX,1000
   MUL  DX // DX:AX=microseconds
   MOV  CX,DX
   MOV  DX,AX
   MOV  AH,0x86
   INT  0x15 // wait CX:DX microseconds
 }
}


У этого прерывания есть также асинхронный сервис: вызываешь его и указываешь в ~es:bx дальний (far) адрес точки программы, куда должно поступить управление спустя указанное тобой число мкс.

Автор: Jin X 29.6.2004, 22:02
Вот тут гляньте: http://filezzz.nm.ru/pub/asm/delay.htm
Если кого звук интересует: http://filezzz.nm.ru/pub/asm/sound.htm

Автор: Гость_Andrew 30.6.2004, 12:33
если в качестве msec ставить число, то на микросекунды оно не дотягивет, скорее это на милисекунды похоже, а если попробовать поставить меньше 65 то вообще пауза пропадает? Так что же делать?

Автор: Chingachguk 30.6.2004, 12:49
Эта функция требует в CX:DX микросекунды. Т.е. CX:DX = 100 - это 100 мкс. Мне надо было сделать милисекунды - я и умножил на 1000.

Автор: scriptcoder 30.6.2004, 17:04
Лично мне понравились туториалы Iczelion'а

Автор: Гость_Andrew 1.7.2004, 11:26
Но если это число в микросекундах ставить меньше чем 65000 микросекунд, то он выдает постоянный сигнал (вообще нет никакой паузы.)

Автор: Chingachguk 1.7.2004, 11:40
Приведи код.

Автор: Гость_Andrew 2.7.2004, 11:56
КОД

#include<iostream.h>
#include<dos.h>
#include<conio.h>
void main()
{ int d=0,a=0,c=0;
unsigned int msec=1000;
outportb(0x378,0);
do
{
do
{

asm {
mov ax,msec
mov dx,1000
mul dx;// dx:ax microseconds
mov cx,dx
mov ah,0x86
int 0x15;// wait cx:dx microseconds
}
a=a^1;
outportb(0x378,a);
}
while(!kbhit());
c = getch();
if (c == 72) msec=msec+1;
if ((c == 80)&(msec>1)) msec=msec-1;
}
while(c!=27);
outportb(0x378,0);
}

Вот. "Лампочка" что к LPT подключена, мигает пока "msec" больше 65, а как тока меньше сделаешь, так сразу просто гореть начинает

Автор: Chingachguk 2.7.2004, 13:04
Может, так и должно быть ? Трудно увидеть частоту моргания > 1000/65 ?

Да и у лампочки должна быть инерция. Вообще-то этот сервис подглючивает, то ли из-за win, то-ли на новых компах.

Попробуй команду rdtsc. Она выдает 64-ти четырехбитный счетчик тактов процессора в регистрах edx:eax. Когда проц исполняет команды, он тратит на них такты (частота CPU). Но если ты хочешь универсального кода (на любых компах), то тебе придется калибровать эту процедуру. Допустим, ты измеряешь число тактов за секунду и тогда 0,1 сек - это 1/10 от этого цикла:

Код

void main( void )
{
 unsigned long CStart_l, CStart_h, CStop_l, CStop_h;
 long t;

 // Get start system clock
 asm {
 db 0x0F, 0x31 // RDTSC
 lea  si,CStart_l
 db  0x66, 0x36, 0x89, 0x04 // mov  ss:[si],eax
 lea  si,CStart_h
 db  0x66, 0x36, 0x89, 0x14 // mov  ss:[si],edx
 }

//  t=time();

 // Get stop system clock
 asm {
 db 0x0F, 0x31 // RDTSC
 lea  si,CStop_l
 db  0x66, 0x36, 0x89, 0x04 // mov  ss:[si],eax
 lea  si,CStop_h
 db  0x66, 0x36, 0x89, 0x14 // mov  ss:[si],edx
 }

 printf("Start=%ld:%ld Stop=%ld:%ld\n",CStart_h,CStart_l,CStop_h,CStop_l);

Автор: oleg1973 2.7.2004, 16:05
я так весь ваш трейд о милисекундах не читалsmile.gif
ну так у нас есть же таймер который вырабатвает int 8 вроде
ну дык его надо перепрограмировать на нужый отрезок и все smile.gif

Автор: Akina 2.7.2004, 16:45
Код
SET_TIMER   MACRO   COUNT
                       PUSH    AX
                       MOV     AL,00110110B
                       OUT     43H,AL
       IFIDN   <COUNT>,<>
                       XOR     AL,AL
                       OUT     40H,AL
                       XOR     AL,AL
                       OUT     40H,AL
       ELSE
               IFDIF   <COUNT>,<AX>
                       MOV     AX,COUNT
               ENDIF
                       OUT     40H,AL
                       MOV     AL,AH
                       OUT     40H,AL
       ENDIF
                       POP     AX
               ENDM

Автор: Chingachguk 2.7.2004, 19:56
Цитата
ну дык его надо перепрограмировать на нужый отрезок и все


Да грил я про это... Видимо, в данном случае не требуется что-то большее, чем Super_Delay(unsigned micsec).

Вы бы уж тогда и хэндлер новый привели ;)

Akina

Интересно, что скажет винда на попытку переставить частоту выше, чем ее собственная ? ;)

Автор: Ivan Ryzhakov 4.7.2004, 14:26
Посмотрел ваши уроки. Очень интересно, а об особенностях порграммирования ассемблером в юникс-системах не могли бы что-нибудь написать?

Автор: antonmasteR 4.7.2004, 19:49
а где можно найти описание по всем функциям под дос ???

Автор: Guest 4.7.2004, 19:59
и где можна найти описание по буферам. т. есть где буфер монитора, клавиатуры...

Автор: Chingachguk 5.7.2004, 00:11
Ivan Ryzhakov

К сожалению, я крайне мало кодировал под *nix, да и то на C. Так что считать себя достойным писать про эту платформу, разумеется, не могу.

Рекомендую следуюущие источники:

- статья на wasm.ru должна быть специально про *nix.
- Зубков С.В. , "Программирование на языке ассемблера".

В целом из той литературы, которую я читал по этому вопросу, авторы сходятся на мнении, что под nix писать лучше на си, только оптимизацию отдельных относительно платформеннонезависимых подпрограмм вроде video-вывода (Зубков) имеет смысл писать на асм. С другой стороны (я опять тут не практик) кто-то как-то пишет эксплойты под nix, а это означает достаточно глубокое знание этой платформы. Но вот про эксплойты под nix я литературы не видел, даже у того же Касперски.

antonmasteR

Ральф Браун, Interrupt List, прерывания int 21h и вспомогательные типа int 23h, 24h, 25h ... etc. Некоторые пишут про TechHelp, но я не юзал.

Guest

Это очень общий вопрос. Что именно тебя интересует ? Простые примеры работы с Video или Keyboard ты легко найдешь в книгах по ассемблеру. У того же Зубкова есть примеры с текстовым буфером VGA (B8000h), графикой (обычно рассматривают режим 320x200, 256 цветов - про это пишет Зубков). Разумеется, там же можно прочесть про клавиатуру. Источник доступен в электронном виде. Ссылку я уже давал в этом разделе или яндекс.



Автор: oleg1973 5.7.2004, 09:24
в целом под *никсы даже легче чем под виндос писать smile.gif
очень дос напоминаетsmile.gif

Автор: Jin X 6.7.2004, 22:23
Народ!!! Вы бы хоть ссылки, которые я привёл почитали exclamation.gif
Ничего перепрограммировать не надо, иначе будут тормоза и прочие проблемы. Кому это надо? Значение счётчика (> 1 МГц) можно читать, ничего не перепрограммируя.

Автор: antonmasteR 27.7.2004, 22:41
Цитата(Chingachguk @ 5.7.2004, 00:11)
Источник доступен в электронном виде. Ссылку я уже давал в этом разделе или яндекс.

не могу найти bored.gif
может кинеш линк или на мыло
[email protected]

Автор: kusa 4.8.2004, 11:57
А что такое byte ptr <registr> кто-нибудь может объяснить?

Автор: Akina 4.8.2004, 12:42
Цитата
что такое byte ptr <registr>

это указатель на байт, адрес коего в указанном регистре.

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

Автор: Jin X 4.8.2004, 18:44
Akina, не правда.
Код
mov byte ptr bx,1
аналогично
Код
mov bx,1

А вот:
Код
mov byte ptr [bx],1
это запись в память по адресу bx.

Автор: kusa 10.8.2004, 09:54
Спасибо за пояснения, народ! Правда, с этим я уде потихоньку разобралась

Автор: Guest 20.10.2004, 19:37
Chingachguk!
А будут ещё уроки?

Автор: Chingachguk 20.10.2004, 19:54
Даже и не знаю... Были мысли про написание загрузчика (тот, что в дискете зовется BOOT а на винте - mbr) и про анализ защиты...

Автор: Guest 24.10.2004, 14:32
А про алгоритмизацию? Про boot я где-то на www.xakep.ru, а про исследования защиты вообще в Сети полно статей. Только почему то эти статьи о взломе, а не исследовании… Написание алгоритмов – вот это интересно.
Так, пока книгу Кнута читаю.

Автор: dragon-gor 13.1.2005, 20:37
Привет всем. Только что я зарегистрировался и поэтому у меня вопрос, будим говорить с опазданием.
В самом начале есть ссылочка - http://chat.ru/~vzubko/tp7.zip, что-то у меня закачки html файла ничего не качает. В чём дело? smile

Автор: oleg1973 14.1.2005, 12:12
да просто устарела ссылочка вот и все
видимо нет там больше сайта и нет файла
а что за файл? может найдем?

Автор: ida 14.1.2005, 15:09
Можно еще покурить рассылку "Низкоуровневое программирование для дзенствующих", по-моему на subscribe.ru. Когда-то там в каждом выпуске были уроки с примерами кода.

Автор: Chingachguk 14.1.2005, 18:17
Ссылки больше нет, извините ;(

Положу на newmail.ru чуть позже.

Автор: dragon-gor 14.1.2005, 21:16
Oleg1973, у меня аськи нет (не люблю я ее). Может попробывать поиск по названию файла?
Если найдёшь пиши на [email protected]
А насчёт "Низкоуровневое программирование для дзенствующих" есть offline на Wasm.ru
Много полезного. smile
Добавлено @ 21:22
tp7.zipo это что, Borland Turbo Paskal ? smile

Автор: oleg1973 14.1.2005, 22:09
dragon-gor
а нафига тебе турбо паскаль?

Автор: Chingachguk 15.1.2005, 02:28
Да, это турбо паскаль для дос, версия 7.0 или 7.1., безо всяких лишних tpu, только голый компиллер и редактор, был ~600 килобайт. Нужен только как удобное (по моему мнению) средство изучать ассемблер на вставках asm ... end;

Автор: dragon-gor 15.1.2005, 22:52
просто по поиску файла нашёл один паскаль. Думал вдруг в вебе найду

Автор: smoc 18.1.2005, 15:31
smile [size=6][/size]
[color=green][/color]
А нельзя ли начать с простого . Вывод бегущей строки на экран. или самое простое. Ато почитаеш книги так там такие заумные советы :
X=y*C=C или чтото в этом роде. Кошмар!!!!! А мне надо попроще,
как первокласнику.

Автор: oleg1973 18.1.2005, 20:45
вывод бегушей строки на экран в графическом режиме требует минимальных знаний о графических режимах, о формате пикселей, фонтов, и некоторых команд асма smile

Автор: dragon-gor 15.3.2005, 18:09
Цитата(dragon @ 13.1.2005, 20:37)
В самом начале есть ссылочка - http://chat.ru/~vzubko/tp7.zip,
Так где же её взять???

Так где же её взять???smile smile smile

Автор: Chingachguk 16.3.2005, 10:28
Чуть позже опять положу. Это обычный паскаль 7.0 для DOS.

Автор: Payne 11.4.2005, 08:35
Chingachguk: я недавно зарегистрировался, попал в этот топик - чуть не офигел! Первые три урока все было настолько понятно, просто до ужаса! Разобрался во всем. Вот четвертый - не понял. Точнее, многое не понял. Да и еще вопрос: почему уроков больше нет? Идет обсуждение всякой лабуды, словно нельзя для этого отдельную тему создать :-(. А тема-то все-таки называется "Асм - с чего начать?". Хотелось бы уроков.

Автор: Chingachguk 11.4.2005, 09:27
Цитата
Вот четвертый - не понял.


Насколько я помню, там была речь про прерывания. У меня не было цели добиться полного понимания того, что это такое и как с ним работать. Поскольку настоящее понимание возможно только с опытом. Там была мысль дать почуствовать - каково это, когда код выполняется нелинейно. Ну просто попробовать ;)

Цитата
Да и еще вопрос: почему уроков больше нет?


Я задавал этот вопрос, но никто особо не пожелал или не высказал ничего конкретного - чего бы ему хотелось.

Собственно, далее по моему мнению должна идти практика. Берем задачку и решаем ее. Возможно, полностью не понимая того, что происходит. Но на принципах, изложенных в уроках 1-3.

Автор: Payne 13.4.2005, 08:16
Цитата
Поскольку настоящее понимание возможно только с опытом

Да, что правда, то правда.
Цитата
никто особо не пожелал или не высказал ничего конкретного - чего бы ему хотелось

Вот где-то после третьего урока все начали присылать коды с решениями заданий. Но эти коды были основаны не на тех циклах, которые юзались в уроке. Там фигурировала команда cld. Я так понял, что она увеличивает (уменьшает) значение счетчика (при организации циклов). Расскажи вкратце об этой команде, плз.

Автор: Chingachguk 13.4.2005, 12:08
Команда cld не влияет на счетчики циклов (обычно это регистры или ячейки памяти), команда влияет на флаг направления DF (direct flag) в регистре флагов процессора.

DF влияет на выполнение так называемых строковых команд movsb, cmpsb, scasb (movsw, cmpsw,...).

Что такое строковые команды ? Это нечто вроде макрокоманды, но на уровне процессора, сделано для удобства программирования.

Возьмем задачу пересылки блока данных (байт) из одной области памяти в другую:

Код

mov si,offset SourceMemory ; Адрес начала источника - смещение
mov ds, seg SourceMemory ; Адрес начала источника - сегмент
mov di,offset DestMemory ; Адрес начала приемника - смещение
mov es, seg DestMemory ; Адрес начала приемника - сегмент
mov cx,SizeofBlock ; Размер пересылаемой области

; Мы пересылаем из адреса ds:si в адрес es:di cx байт

@@MoveBlock:

mov  al,ds:[si] ; Получить пересылаемый байт в AL
mov  es:[di],al ; Записать его в приемник
inc  si ; Указать на следующий байт в источнике
inc  di ; Указать на следующий байт в применике

loop @@MoveBlock ; Перейти к следующему байту или закончить ~ while (--cx);


С помощью строковых команд, в этом случае - movsb, мы можем упростить решение следующим образом:

Код

mov si,offset SourceMemory ; Адрес начала источника - смещение
mov ds, seg SourceMemory ; Адрес начала источника - сегмент
mov di,offset DestMemory ; Адрес начала приемника - смещение
mov es, seg DestMemory ; Адрес начала приемника - сегмент
mov cx,SizeofBlock ; Размер пересылаемой области

; Мы пересылаем из адреса ds:si в адрес es:di cx байт
cld ; Указываем процессору, что после mosvb надо увеличивать si и di,
; а не уменьшать

@@MoveBlock:

movsb ; передать из ds:[si] байт в es:[di] и увеличить si и di на 1.

loop @@MoveBlock ; Перейти к следующему байту или закончить ~ while (--cx);


Таким образом, одна команда movsb делает абсолютно то же, что делают 4 команды выше.

Однако в результате выполнения movsb регистры si & di получили приращение, однако это произошло потому, что флаг направления DF был сброшен командой cld !

Если бы мы установили этот флаг командой std, то после выполнения movsb процессор бы уменьшил si & di на 1. Это может быть удобно в том случае, если копируются перкрывающиеся блоки данных. Если делать копирование вперед и с начала блока, то часть данных будет потеряна. Однако мы могли бы переписать копирование следующим образом:

Код

mov cx,SizeofBlock ; Размер пересылаемой области
mov ax,cx
dec  ax
mov si,offset SourceMemory ; Адрес начала источника - смещение
add si,ax ; Адрес последнего байта в источнике
mov ds, seg SourceMemory ; Адрес начала источника - сегмент
mov di,offset DestMemory ; Адрес начала приемника - смещение
add di,ax ; Адрес последнего байта в приемнике
mov es, seg DestMemory ; Адрес начала приемника - сегмент

; Мы пересылаем из адреса ds:si в адрес es:di cx байт
std ; Указываем процессору, что после mosvb надо уменьшать si и di

@@MoveBlock:

movsb ; передать из ds:[si] байт в es:[di] и уменьшить si и di на 1.

loop @@MoveBlock ; Перейти к следующему байту или закончить ~ while (--cx);


Еще мы бы могли вообще обойтись без циклов и использовать префикс REP (повторять следующую команду CX раз):

Код

mov cx,SizeofBlock ; Размер пересылаемой области
mov ax,cx
dec  ax
mov si,offset SourceMemory ; Адрес начала источника - смещение
add si,ax ; Адрес последнего байта в источнике
mov ds, seg SourceMemory ; Адрес начала источника - сегмент
mov di,offset DestMemory ; Адрес начала приемника - смещение
add di,ax ; Адрес последнего байта в приемнике
mov es, seg DestMemory ; Адрес начала приемника - сегмент

; Мы пересылаем из адреса ds:si в адрес es:di cx байт
std ; Указываем процессору, что после mosvb надо уменьшать si и di

rep mosvb ; !


Автор: Payne 14.4.2005, 11:44
Можно ли получить информацию о кодах сканирования клавиатуры, которые помещаются в регистр AH после нажатия клавиши во время прерывания
Код

mov ah,00
int 16h

Автор: Chingachguk 14.4.2005, 12:22
Информация ниже взята из книги Зубкова С.В.

Цитата
.4.2. Средства BIOS
Так же как и для вывода на экран, BIOS предоставляет больше возможностей по сравнению с DOS для считывания данных и управления клавиатурой. Например, функциями DOS нельзя определить нажатие комбинаций клавиш типа Ctrl-Alt-Enter или нажатие двух клавиш Shift одновременно, DOS не может определить момент отпускания нажатой клавиши, и наконец, в DOS нет аналога функции С ungetch(), помещающей символ в буфер клавиатуры, как если бы его ввел пользователь. Все это можно осуществить, используя различные функции прерывания 16h и операции с байтами состояния клавиатуры.



INT 16h, АН = 0, 10h, 20h — Чтение символа с ожиданием

Ввод: АН = 00h (83/84-key), 10h (101/102-key), 20h (122-key)
Вывод: AL = ASCII-код символа, 0 или префикс скан-кода
АН = скан-код нажатой клавиши или расширенный ASCII-код


Каждой клавише на клавиатуре соответствует так называемый скан-код (см. приложение 1), соответствующий только этой клавише. Этот код посылается клавиатурой при каждом нажатии и отпускании клавиши и обрабатывается BIOS (обработчиком прерывания INT 9). Прерывание 16h дает возможность получить код нажатия, не перехватывая этот обработчик. Если нажатой клавише соответствует ASCII-символ, то в АН возвращается код этого символа, а в AL — скан-код клавиши. Если нажатой клавише соответствует расширенный ASCII-код, в AL возвращается префикс скан-кода (например, Е0 для серых клавиш) или 0, если префикса нет, а в АН — расширенный ASCII-код. Функция 00Н обрабатывает только комбинации, использующие клавиши 84-клавишной клавиатуры, l0h обрабатывает все 101 – 105-клавишные комбинации, 20h — 122-клавишные. Тип клавиатуры можно определить с помощью функции 09h прерывания 16h, если она поддерживается BIOS (поддерживается ли эта функция, можно узнать с помощью функции C0h прерывания 15h).



INT 16h, АН = 1, 11h, 21h — Проверка символа

Ввод: АН = 01h (83/84-key), 11h (101/102-key), 21h (122-key)
Вывод: ZF = 1, если буфер пуст
ZF = 0, если в буфере присутствует символ, в этом случае
AL = ASCII-код символа, 0 или префикс скан-кода
АН = скан-код нажатой клавиши или расширенный ASCII-код


Символ остается в буфере клавиатуры, хотя некоторые BIOS удаляют символ из буфера при обработке функции 01h, если он соответствует расширенному ASCII-коду, отсутствующему на 84-клавишных клавиатурах.



INT 16h, АН = 05h — Поместить символ в буфер клавиатуры

Ввод: АН = 05h
СН = скан-код
CL = ASCII-код
Вывод: AL = 00, если операция выполнена успешно
AL = 01h, если буфер клавиатуры переполнен
АН модифицируется многими BIOS


Обычно можно поместить 0 вместо скан-кода в СН, если функция, которая будет выполнять чтение из буфера, будет использовать именно ASCII-код. Например, следующая программа при запуске из DOS вызывает команду DIR (но при запуске из некоторых оболочек, например FAR, этого не произойдет).

; ungetch.asm
; заносит в буфер клавиатуры команду DIR так, чтобы она
; выполнилась сразу после завершения программы
;
        .model    tiny
        .code
        org        100h          ; СОМ-файл
start:
        mov        cl,'d'        ; CL = ASCII-код буквы "d"
        call      ungetch
        mov        cl,'i'        ; ASCII-код буквы "i"
        call      ungetch
        mov        cl,'r'        ; ASCII-код буквы "r"
        call      ungetch
        mov        cl,0Dh        ; перевод строки
ungetch:
        mov        ah,5          ; AH = номер функции
        mov        ch,0          ; CH = 0 (скан-код неважен)
        int        16h            ; поместить символ в буфер
        ret                      ; завершить программу

        end        start

INT 16h, AH = 02h, 12h, 22h — Считать состояние клавиатуры

Ввод: АН = 02h (83/84-key), 12h (101/102-key), 22h (122-key)
Вывод: AL = байт состояния клавиатуры 1
АН = байт состояния клавиатуры 2 (только для функций 12h и 22h)


Байт состояния клавиатуры 1 (этот байт всегда расположен в памяти по адресу 0000h:0417h или 0040h:0017h):

Бит 7: Ins включена

Бит 6: CapsLock включена

Бит 5: NumLock включена

Бит 4: ScrollLock включена

Бит 3: Alt нажата (любая Alt для функции 02h, часто только левая Alt для 12h/22h)

Бит 2: Ctrl нажата (любая Ctrl)

Бит 1: Левая Shift нажата

Бит 0: Правая Shift нажата

Байт состояния клавиатуры 2 (этот байт всегда расположен в памяти по адресу 0000h:0418h или 0040h:0018h):

Бит 7: SysRq нажата

Бит 6: CapsLock нажата

Бит 5: NumLock нажата

Бит 4: ScrollLock нажата

Бит 3: Правая Alt нажата

Бит 2: Правая Ctrl нажата

Бит 1: Левая Alt нажата

Бит 0: Левая Ctrl нажата

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

; nolock.asm
; самая короткая программа для выключения NumLock, CapsLock и ScrollLock
; запускать без параметров
        .model    tiny
        .code
        org        100h        ; СОМ-файл. АХ при запуске СОМ-файла без параметров
                              ; в командой строке всегда равен 0
start:
        mov        ds,ax                  ; так что теперь DS = 0
        mov        byte ptr ds:0417h,al  ; байт состояния клавиатуры 1=0
        ret                              ; выход из программы
        end        start

Разумеется, в реальных программах, которые будет запускать кто-то, кроме автора, так делать нельзя, и первой командой дожна быть xor ах,ах.

Помимо этих двух байт BIOS хранит в своей области данных и весь клавиатурный буфер, к которому также можно обращаться напрямую. Буфер занимает 16 слов с 0h:041Eh no 0h:043Dh включительно, причем по адресу 0h:041Ah лежит адрес (ближний) начала буфера, то есть адрес, по которому располагается следующий введенный символ, а по адресу 0h:041Ch лежит адрес конца буфера, так что если эти два адреса равны, буфер пуст. Буфер действует как кольцо: если начало буфера — 043Ch, а конец — 0420h, то в буфере находятся три символа по адресам 043Ch, 041Eh и 0420h. Каждый символ хранится в виде слова — того же самого, которое возвращает функция 10h прерывания INT 16h. В некоторых случаях (если) буфер размещается по другим адресам, тогда адрес его начала хранится в области данных BIOS по адресу 0480h, а конца — по адресу 0482h. Прямой доступ к буферу клавиатуры лишь немногим быстрее, чем вызов соответствующих функций BIOS, и для приложений, требующих максимальной скорости, таких как игры или демо-программы, используют управление клавиатурой на уровне портов ввода-вывода.


Автор: CnApTaK 10.7.2005, 13:58
w32 инсталятор http://reborn.rimako.lv/tp70.exe

Автор: Гость_Начинающий 31.10.2005, 10:12
(о первом уроке) А если мне надобно обращатся не к конкретному адресу?Как его загнать в переменную? Напр
Код

...
       mov  ax,0A000h
        mov  es,ax
  xor bx,bx
  xor dx,dx
  mov ax,offset [320*100+100]
  mov  byte ptr es:ax,12
...

упорно не хочет ставить точку.Где ошибка?

Автор: oleg1973 31.10.2005, 11:05
mov ax,320*100+100

Автор: Гость_Начинающий 1.11.2005, 10:27
Без разницы.

Автор: Lonley 1.11.2005, 15:38
Код

IDEAL
MODEL TINY
CODESEG
ORG 100h
_start:
  mov ax,013h
  int 10h

  mov  ax,0A000h    
  mov  es,ax    
  xor  bx,bx    
  xor  dx,dx    
  mov  di,320*100+100    ; ax не используется для адресации памяти
  mov  es:[di],12        
  ; тут можно использовать si или di или bx но не ax
  
  xor ax,ax
  int 16h
  ret
  
end _start

Автор: kdaemonv 15.12.2005, 09:02
Chingachguk, подскажи.
Вот этот код я набираю в debug (система WinXP SP1):

Код

XOR     AX,AX
MOV     DS,AX
MOV     [0417],AL
RET


Это аналог "самой короткой программы для выключения NumLock, CapsLock и ScrollLock" приведенной выше.
После выполнения этого кода результата никакого - как горел NumLock так и горит.
Это винда мне мешает изменять этот кусок памяти??? И если да, как она это делает и как мне с этим бороться???

Автор: Chingachguk 16.12.2005, 10:17
Да, может быть что и винда. Попробуй загрузицца с дискеты в досе.

Нижеприведенный код точно работает в 98:

Код

.286
text segment byte public
    assume cs:text,ds:text
    org 100h
begin:  mov  bl,1+4+16+64
@Cyc:   mov  ah,2
        call @Wait
        mov  al,0edh
        out  60h,al
        mov  ah,1
        call @Wait
        mov  al,bl
        and  al,7
        out  60h,al
        mov  ah,2
        call @Wait
        rol  bl,1
        xor  dx,dx
@Delay: call @Wait
        dec  dx
        jnz  @Delay
        mov  ah,1
    int  16h
        jz   @Cyc
@GoDos: xor  ah,ah
        int  16h
        mov  ax,4c00h
        int  21h
@Wait:  xor  cx,cx
@Test:  in   al,64h
        test al,ah
        loopnz @Test
        jnz  @Error
        retn
@Error: pop  ax
        mov  ah,09
        mov  dx,offset ErrMess
        int  21h
        jmp  @GoDos
ErrMess db 'Error !','$'
text ends
    end begin

Автор: Гость_Merlin 8.1.2006, 14:15
Народ помогите умоляю!!!!!!! Срочно нужна прога на чистом ассемблере (без паскаля) рисующая на экране небольшой круг и перемещающая его через некоторое время в рандомное положение. Пожалуйста кто может с комментариями. Вам же это раз плюнуть. Горю на допуске к экзамену!!!
Или если есть что-то подобное шлите на [email protected]. Буду бесконечно благодарен

Автор: cardinal 8.1.2006, 15:32
Гость_Merlin, эта тему создана не для этого! Создай отдельную тему (в разделе "центр помощи" или "работа", если готов платить)!

Автор: ctranik 4.3.2006, 17:43
neutrino, привет

А где можго скачать эту книгу "Programmirovanie v Turbo Assembler"

И кстати перевод на русский имеется ?

Автор: peter789 19.3.2006, 18:57
поиск файла по маске smile

Автор: oleg1973 19.3.2006, 20:38
peter789,
os какая?

Автор: darthnick 12.6.2006, 13:01
привет, я только начал асм изучать и возник вопрос.. к примеру:
somevar dw 0
; ...
mov ax,23
mov [somevar],ax
;...

почему в последней строчки испл. [] ? ведь компилируется без них нормально и непрямая адресация не испл. 
З.Ы. сорри если не по теме smile 

Автор: Chingachguk 13.6.2006, 10:24
В данном случае все равно, как писать. Лично мне больше нравится mov word ptr SomeVar[...],ax например - mov word ptr SomeVar[bx+di],ax и т.п. 

Автор: daniel 20.6.2006, 18:22
Огромное спасибо за уроки! smile
    Расскажите пожалуйста побольше о циклах! 

Автор: setty 20.6.2006, 19:53
в книгах же все расписано хорошо
есть несколько видов loop ов
можно циклы устраивать последовательностью cmp/test и  jne/je
 

Автор: Chingachguk 24.6.2006, 00:10
daniel

Спасибо ;)

Циклы... ранее я писал ориентируясь на то, что изучающий будет использовать вставки на языке Паскаль для DOS. Времена меняются... возможно, будет лучше использовать вставки на языке Делфи или СИ (VC6). Пусть это будет язык Делфи. Здесь программа - WIN32 приложение, никаких сегментов больше нет (почти нет, но бывают иногда). Все указатели на любые данные или параметры в большинстве случаев - 32 битные значения. Используются 32-х разрядные регистры: EAX (ранее был AX/AL), EBX, ECX, EDX, ESI, EDI, EBP. Регистры EBX, ESI, EDI лучше сохранять.

Предполагаем простую задачу: программа принимает указатель на массив байт и размер самого массива и ищет в нем заданный байт. Если находит, то возвращает номер байта (нумерация от 1), иначе возвращает 0:

Цитата

function Get_BytePosition(Mas: array of byte; MasSize: integer; ByteToScan: byte): integer;
  begin
  { Начинаем писать на ассемблере }
  { Делфи уже сделало пролог процедуры и можно }
  { обращатся к параметрам через их имена }
  asm
    push ebx
    mov  ebx,Mas { Получаем  адрес массива }
    mov  ecx,1 { Номер проверяемого байта }
    mov  al,byte ptr ByteToScan
    xor  edx,edx { Номер найденного байта - по умолчанию 0 }
@@FindByte:
    { Проверка конца массива }
    cmp  ecx,MasSize
    ja   @@FindByteDone
    { Проверяем очередной байт }
    cmp  byte ptr [ebx],al
    jnz  @@NextByte
    { Если байт найден, сохраняем его номер в edx и break }
    mov  edx,ecx
    jmp  @@FindByteDone
@@NextByte:
    { Переходим к следующему байту и увеличиваем номер текущего байта }
    inc  ebx
    inc  ecx
    jmp  @@FindByte

@@FindByteDone:
    pop  ebx
    mov  @Result,edx { Возвращаем результат }
  end;
  end;


Надо сказать, что код выше я не проверял ;) Главное - попробовать самому его использовать, может быть даже модифицировать.

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

- Написать программу под DOS, com-файл с максимально коротким размером;

- Получить время от DOS следующим образом:

Цитата

INT 21 - DOS 1+ - GET SYSTEM TIME
    AH = 2Ch
Return: CH = hour
    CL = minute
    DH = second
    DL = 1/100 seconds
Note:    on most systems, the resolution of the system clock is about 5/100sec,
   so returned times generally do not increment by 1
    on some systems, DL may always return 00h


- После этого вывести текущее время на экран в формате: HH:MM:SS. Например, если время сейчас 23 часа 24 минуты 25 секунд, то на экране будет 23:24:25

Ниже мой пример. Попробуй разобрать его и понять как он работает. Там есть несколько циклов.

Код

.286
text segment byte public
    assume cs:text,ds:text    
    org 100h
begin:
      mov  ah,2Ch
      int  21h
      mov  al,ch
      mov  bl,11011011b
@DecChar:
      aam
@CharNext:
      xchg al,ah
      add  al,'0'
      int  29h
      mov  al,':'-'0'
      shl  bl,1
      jnz  @Next
      ret
@Next:
      jc   @CharNext
      mov  al,cl
      mov  cl,dh
      jmp  short @DecChar
Text Ends
    end begin


Добавлено @ 00:20 
Мда, int 29h - это вывод байта на консоль (экран):

Цитата

INT 29 C - DOS 2+ - FAST CONSOLE OUTPUT
    AL = character to display
Return: nothing
    BX may be destroyed by some versions of DOS 3.3
 

Автор: nerezus 5.11.2006, 22:55
А ссылочку на справочни по коммандам можно? Учебники не нужны =(

Автор: Роман 6.11.2006, 04:21
Да, не помешал бы справочник по asm-командам, особенно электронный и оперативный! Чтобы можно было найти описание конкретной команды, а также быстро подобрать команду из определенной категории.

Автор: Damarus 7.11.2006, 08:42
Цитата(Роман @  6.11.2006,  04:21 Найти цитируемый пост)
Да, не помешал бы справочник по asm-командам, особенно электронный и оперативный! Чтобы можно было найти описание конкретной команды, а также быстро подобрать команду из определенной категории.

http://www.intel.com/design/pentium4/manuals/index_new.htm

Автор: Snik 20.11.2006, 11:47
Привет! 
Очень хорошо подан матерьял, а можно гдето в подобном стиле изложения поучиться для чистого assembler(a) , а точнее Turbo Assembler  Version 4.1  Copyright © 1988, 1996 Borland International

Автор: Роман 20.11.2006, 14:06
Intel® 64 and IA-32 Architectures Software Developer's Manuals - вещь конечно хорошая, но хочется чего-нибудь на русском языке! 

Автор: Роман 21.11.2006, 13:13
Вот нашел интересную ссылку по теме: http://vas-unn.narod.ru/
Вот еще: http://212.176.41.3:777/archive/66/38978/asm-abc.zip (25КБ)

Но нужно искать дальше!

Автор: mr666 15.2.2007, 15:26
Я вот только начал вникать в ассемблер. Читаю калашникова, возник вопрос,  
mov es: [di],ax
Не пойму что за [], толи они напрямую пишут по адресу, что тоневъеду никак.

Автор: Shaggie 15.2.2007, 15:37
mr666, все правильно. Значение, содержащееся в регистре ax, пишется не в сам регистр di, а по адресу, содержащемуся в нем.

Если в ax лежит 005E, а в di лежит 27B3, то значение регистра di не изменится, а значение ячейки памяти по адресу es:27B3 станет равным 005Е

Автор: mr666 15.2.2007, 16:06
Shaggie,
там вроде es (сигментный регистр) а что значит [di] di это вроде указатель. Запутался я. 

Автор: Shaggie 15.2.2007, 16:18
mr666, ой, прошу простить, это я виноват - запутал. Щас поправлю.

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

Когда регистр берется в квадратные скобки [], то этим мы указываем процессору писать (или читать) информацию не в сам регистр, а по адресу памяти, которое содержится в этом регистре.

Код

mov di,2cdeh
; загружаем в регистр di адрес, куда писать информацию
; в регистре di содержится число 2cde
; в сегменте памяти по адресу es:2cde находится... неважно

mov [di],5
; загружаем в ячейку памяти, на которую указывает di, число 5
; в регистре di содержится число 2cde
; в сегменте памяти по адресу es:2cde находится число 05

Автор: MAKCim 15.2.2007, 20:57
Цитата(mr666 @  15.2.2007,  15:26 Найти цитируемый пост)
mov es: [di],ax
Не пойму что за [], толи они напрямую пишут по адресу, что тоневъеду никак. 

в реальном режиме эквивалентно
записи слова из регистра AX по абсолютному адресу 'слово в ES << 4 + слово в DI'

Автор: Metixa 10.3.2007, 16:25
Добрый день!!! Я не давно начал асм. помогите понять  почему в случии:
Код

.data?
bigArray dword 1000 dup(?)


нет
а так:
Код

.data
bigArray dword 1000 dup(?)


получаем большой исполняемый модуль?

Автор: W4FhLF 10.3.2007, 16:55
Metixa, потому что в первом случае инициализация массива идёт в секции неициниализированных данных, т.е. этих данных не будет в исполняемом exe, они будут выделены загрузчиком в момент запуска программы. А вот во втором случае ты говоришь компилятору записать в исполняемый exe массив состоящий из 1000 байт. 

Автор: Metixa 14.3.2007, 12:12
Прошу обьясните:
1. почему установливается флаг CF когда происходит напр. 1-2, когда все решаетсья в диапазоне до 255, и приомник регистр al?
2. мой масм по моему не видит разницу между sbyte и byte,  sword и word, и т.д. почему..? 
благодарью...!!! 

Автор: Metixa 16.3.2007, 02:12
--------------------------------------------------------------------------------

вот как я думаю:

когда происходит 1-2 машина работает так:
0000 0001

0000 0010

т.е. 0000 0010 инвертируется и прибавляется 1, значит

0000 0001
+
1111 1110
---------------
1111 1111 а где нам понпдобилься добовочная 1? только когда прибавляли 1 инвертированного 1111 1101 в младшем регистре, ????
Но сейчас я лучше запутался:
постарался представить что происходит бинарно кагда 3-1 (когда CF=0) но у меня почему то понадобился вирт. 1.. вот так:

0000 0011 -- 3 

0000 0001 --1 
=

0000 0011 --3
+
1111 1111 "-1"
-----------------------
1 0000 0010 --2
поможете?
а что касается типу sbyte, в книжке прочитал, что когда обьявляем со знаком т.е. sbyte (signbyte) тогда диапазон -128 - +127 , но если запишу:

.data
x1 sbyte 130
.code
mov al, x1

почему не выдается ошибка???? al же 8 регистровый что тратится на 256 число с -128 до +127, жду ответа и очень благодарью!!!!!!!!!!

Автор: MAKCim 16.3.2007, 09:20
Цитата(Metixa @  16.3.2007,  02:12 Найти цитируемый пост)
почему не выдается ошибка???? al же 8 регистровый что тратится на 256 число с -128 до +127, жду ответа и очень благодарью!!!!!!!!!!

у процессора нет никаких типов данных
sbyte, имхо, просто надстройка для проверки транслятором диапозонов
почему не работает - хз   smile 
насчет перевода
-x = neg(x) + 1
например -1 = neg(00000001) + 1 = 11111110 + 1 = 11111111
3 + (-1) = 
00000011
+
11111111
=
00000010

Автор: Metixa 16.3.2007, 09:44
Цитата(MAKCim @ 16.3.2007,  09:20)
Цитата(Metixa @  16.3.2007,  02:12 Найти цитируемый пост)
почему не выдается ошибка???? al же 8 регистровый что тратится на 256 число с -128 до +127, жду ответа и очень благодарью!!!!!!!!!!

у процессора нет никаких типов данных
sbyte, имхо, просто надстройка для проверки транслятором диапозонов
почему не работает - хз   smile 
насчет перевода
-x = neg(x) + 1
например -1 = neg(00000001) + 1 = 11111110 + 1 = 11111111
3 + (-1) = 
00000011
+
11111111
=
00000010

00000011
+
11111111
=
00000010

а где старшая 1?

мне интересно старшая 1, которая не видно у вас, почему не установит CF=1?

Автор: AET 21.6.2007, 13:22
Shaggie
Shaggie, народ помпгите кто может объеснит пошагово эту программу

Автор: try_to_get 13.7.2007, 16:48
http://ruasm.ru/index.php с нуля!

Автор: ne0n 18.8.2007, 23:18
Цитата(AET @  21.6.2007,  13:22 Найти цитируемый пост)
Shaggie, народ помпгите кто может объеснит пошагово эту программу 


Фигасе smile  так этож не программа а IDAвсий листинг!!! врятли кто возьмется в нем капаться...

Автор: StrikerX 5.9.2007, 00:39
Я асм немного знаю, по изучению в универе, но это как на уровне обезьяны с гранатой=)
Поэтому хочелось бы узнать кое-что по этим пунктам:

1. Какую бумажную литературу почитать по асму(с самого начала для полного ознакомления)?

2. Какие есть специализирующиеся сайты по этому языку?

3. Каким компилятором пользоваться? (тасм консольный однако не оченьsmile).

Автор: cardinal 5.9.2007, 01:09
Пожалуйста, один топик - один вопрос.

Понять что такое асм и с чем его едят можно довольно таки просто при помощи Microsoft VS C++ например 6-ой версии и возможных в нем inline вставок...
Цитата(StrikerX @  4.9.2007,  23:39 Найти цитируемый пост)
Какие есть специализирующиеся сайты по этому языку?

асм может очень сильно отличаться от контроллера к контроллеру. Не по сути, по синтаксису и названию комманд. Определитесь для начала с процессором.
Цитата(StrikerX @  4.9.2007,  23:39 Найти цитируемый пост)
Какую бумажную литературу почитать по асму(с самого начала для полного ознакомления)?

Я в свое время прочитал
http://www.williamspublishing.com/Books/5-8459-0332-7.html
Кстати с этим издательством ведется сотрудничество с нашем форумом и Вы можете написать статью про эту книгу и получите таким образом один экземпляр бесплатно. Подробности здесь:
http://forum.vingrad.ru/forum/topic-145075.html
http://forum.vingrad.ru/forum/topic-114346/unread-1/hl/williams/index.html
Цитата(StrikerX @  4.9.2007,  23:39 Найти цитируемый пост)
Какие есть специализирующиеся сайты по этому языку?

Их завались, но для начала хватить книги (см. выше) и http://firststeps.ru/

Автор: StrikerX 5.9.2007, 01:13
cardinal, Ну допустим x86, программирование пока под вин.

Автор: cardinal 5.9.2007, 01:15
Цитата(cardinal @  5.9.2007,  00:09 Найти цитируемый пост)
при помощи Microsoft VS C++ например 6-ой версии и возможных в нем inline вставок...

Про прерывания для начала забудь...

Автор: StrikerX 5.9.2007, 01:17
Нифига не понял, как забыть? 

Автор: cardinal 5.9.2007, 01:36
Пока забудь, так как они у тебя не будут работать.
Цитата

If you planning to do Win32 Windows programming using Assembler you need to tell more about the application. There are two types of Win32 application: console (black DOS-type window with text scrolled up) and GUI (normal application with windows, panels, dialogs, etc.) Both types use the specific APIs to do the job, like to read user pressed keys or to get the mouse input. No interrupts allowed here.

http://www.programmersheaven.com/mb/x86_asm/341024/341101/ReadMessage.aspx?S=B20000
Запрещены они короче.

И для начала узнай что такое прерывание и пойми нужно ли оно тебе и зачем вообще int 21h...

Автор: MAKCim 5.9.2007, 10:05
Цитата(cardinal @  5.9.2007,  01:36 Найти цитируемый пост)
Запрещены они короче.

они не запрещены
просто не будет ожидаемого эффекта
никто не запрещает писать
Код

int 0x15

другое дело, какой будет эффект  smile 

Автор: StrikerX 7.9.2007, 01:06
Цитата(cardinal @ 5.9.2007,  01:09)
Я в свое время прочитал
http://www.williamspublishing.com/Books/5-8459-0332-7.html

Такой вопрос, там есть 3 и 4 издание, 4е пойдет?

PS. Кстати, там описываются действия о числах с плавующей точкоЙ?

Автор: cardinal 7.9.2007, 02:21
Цитата(StrikerX @  7.9.2007,  00:06 Найти цитируемый пост)
PS. Кстати, там описываются действия о числах с плавующей точкоЙ?

Вроде нет. Вопрос зачем? Пример назови.
Цитата(StrikerX @  7.9.2007,  00:06 Найти цитируемый пост)
Такой вопрос, там есть 3 и 4 издание, 4е пойдет?

У меня третье, наверно четвертое не хуже. smile 

Автор: Evergreen 7.9.2007, 02:36
StrikerX, вот это ещё посмотри http://kalashnikoff.ru/Assembler/ С тем программированием про прерывания можно будет снова вспомнить. Можно скачать всё одним архивом, на той же странице есть ссылка на программы. То что там представлено есть в виде книги. Там же собственно и ссылка на спецов есть. 
 smile Но здесь ведь тоже можно спросить.

Автор: Aleksey2007 17.9.2007, 22:18
Все языки супер но Asm прикольный

Автор: Denem 8.2.2008, 11:21
Привет! я Хочу попытаться изучить Ассемблер. это мой первый язык программирования, и не могли бы подсказать Какие инструменты лучше выбрать. Желательно чем глубже тем лучше..... smile [email protected]

Автор: Pango 16.2.2008, 23:10
http://depositfiles.com/files/3560529Издание посвящено вопросам программирования на языке ассемблера для процессоров Intel Pentium.  Рассмотрен широкий круг вопросов, начиная с основ программирования на ассемблере и заканчивая применением самых современных технологий обработки данных, таких как MMS, SSE и SSE2.  Материал книги раскрывает методику оптимизации программного кода для всех поколений процессоров Intel Pentium, включая Intel Pentium 4.  Теоретический материал подкреплен многочисленными примерами программного кода.  Для широкого круга читателей, от студентов до опытных разработчиков программного обеспечения.

Автор: Pavlikoff 12.4.2008, 15:27
Chingachguk вопрос к тебе,как к знающему человеку,имеется код
fcom   qword ptr [edi-15BF31F9h]
push   ebx
seto    byte ptr [eax]
xchg    eax,ecx
mov    ch,20h: '   '

Так вот,не пойму что означает этот код? Подскажи пожалуйста!

ЗЫ: понял только последнее-регистру ch присваивается значение 20h

Автор: cardinal 12.4.2008, 16:12
Модератор: Pavlikoff, в этой теме достаточно материала, с которого можно начать изучение асм'а! Эта тема не для вопросов подобного рода!

Автор: Pavlikoff 12.4.2008, 18:26
cardinal, Спасибо! Надеялся на помощь!

Автор: cardinal 12.4.2008, 21:56
Цитата(Pavlikoff @  12.4.2008,  17:26 Найти цитируемый пост)
Надеялся на помощь! 

Понимаешь в данном случае тебе хорошая книжка и поиск по форуму лучшая помощь, а не разбор каких-то строк кода...

Автор: Chingachguk 21.4.2008, 09:55
Pavlikoff

Это скорее всего либо obfuscated-код или вообще данные ты смотришь как код ;-)

Автор: ecl1pse 27.4.2008, 15:14
fcom   qword ptr [edi-15BF31F9h] - не знаю
push   ebx - кидаем в стек содержимое регистра ebx
seto    byte ptr [eax] - пока не знаю смысл операнда seto, но думаю, что тут производиться какое-то действие с 1 байтом, который находиться по адресу (которые лежит в регистре eax), ну или что-то подобное
xchg    eax,ecx -  произведен взаимный обмен данными между двумя регистрами - eax и ecx 
mov    ch,20h 

Автор: Lycifer 14.5.2008, 11:26
Chingachguk такой вопрос как править hex(я понимаю точ это не совсем asm, хотелось бы узнать соответствие команд или ссылку получить)

Автор: ЛЕФ 15.6.2008, 16:35
Лучше всего начинать изучать асм сразу по нескольким книгам, тогда некоторые вопросы которые не понятны в первой книге будут раскрыты во второй и т.д. Из авторов могу посоветовать Зубкова,пирогова,Юрова,Калашникова ну и конечно же Питера Абеля, патом если знаеш другой какойнить язык программирования, полезно делать следующее - пишеш простенькую прогу, дизассемблируеш ее и пытаешся понять как она работает и вообще как можно больше нужно работать с отладчиком и не бояться эксперементировать. И тогда все непременно будет!=)

Добавлено через 3 минуты и 14 секунд
Цитата(Lycifer @ 14.5.2008,  11:26)
Chingachguk такой вопрос как править hex(я понимаю точ это не совсем asm, хотелось бы узнать соответствие команд или ссылку получить)

Hex можно править в каком нить Hviewe, например, а таблицу 16ричных кодов и асм значений можно при желании найти в инете и памойму чтото падобное было в пакете Масм32... но не помню точно па этому врать не буду.... Первое что приходит на ум 90h = команде Nop

Автор: asha92 7.11.2008, 10:28
Добрый день уважаемые профессионалы и начинающие.
Вот решил познакомиться с ассемблером по книге Олега Калашникова, и у меня возник такой вопрос. Автор даёт примеры под 8086-80186 процессоры, а у меня к примеру sempron 2800+. Программы его работают просто под мой проц могут быть другие команды или регистров данных может быть больше, т.е если я захочу писать прогу под свой проц мне ведь по идее нужно знать как он устроен, как быть? Извиняюсь если глупый вопрос я пока мало что знаю.

Автор: Mikl_ 7.11.2008, 11:00
asha92, я к сожалению не знаю что это за процессор sempron 2800+. Но если заглянуть в Wiki "процессоры AMD Mobile Sempron выпускались как и все прочие процессоры AMD на базе 32-разрядной архитектуры K7" AMD так же как и Intel поддерживают совместимость задач снизу до верху -- т.е. то что написано для 8086-80186 будет работать и на твоем процессоре. Просто по традиции ассемблер изучают от простого к сложному. Понятно, что DOS не актуален, но программировать под WinXP не очень сложно smile 

Автор: cardinal 7.11.2008, 11:14
Цитата(asha92 @  7.11.2008,  09:28 Найти цитируемый пост)
Вот решил познакомиться с ассемблером

Познакомься лучше с ассемблером на маленьком микроконтроллере (см. ATMEL). Так и эффект будет более понятен (и увидеть его можно будет, см. "программирование контроллеров") и вообще тема эта более актуальная (даже 80386 насколько я знаю больше не выпускают, не то что 80186).

Автор: asha92 7.11.2008, 11:33
Mikl_
Понятно, где то мне попадалась команда введя которую в командную строку(windows xp) можно было посмотреть информацию по регистрам, а так же там была инфа по памяти, может кто в курсе. 

Автор: rangrover 16.7.2009, 22:12
Всем привет,написал текст в TurboPascal,как говорил Chingachguk.Но при выполнении программы вылетает ошибка
"16bit MS-DOS Subsystem:TurboPascal This system does not support fullscreen mode.Choose 'Close' to terminate the application".
В чем может быть проблема?

Автор: Goodwin98 16.7.2009, 23:19
Ставьте обратно WinXP, пока дяди из M$ не поймут, что от доса отказываться пока не стоит. Или запускайте программу через какую-нибудь виртуальную машину.

Автор: rangrover 16.7.2009, 23:25
Ок,большое спасибо.

Автор: ДобренькийПапаша 16.8.2009, 09:18
Так, я в асме ничё пока не понимаю, но у меня есть вопросы...

Каково современное состояние дел? Что подвластно асму сейчас, а что нет? Какие среды разработки существуют? Написаны ли какие-либо библиотеки программного кода для асма (типа ATL, STL для C++, или скажем отдельно для работы над GUI)? И всё-таки, с ЧЕГО начать изучение асма, мне нужен список литературы (я, прошу прощения у Чингачгука, никогда не доверял статьям в инете, я их анализирую, только если сам имею опыт программирования на данном языке, а пока не имею, хочу НОРМАЛЬНУЮ литературу от WROX press, APRESS, или что-то в этом роде smile )

Заранее спасибо, с уважением ко всем асмщикам smile 

Автор: GoldFinch 16.8.2009, 12:06
ДобренькийПапаша, для начала неплохо бы почитать чтонить про устройство процессора и компьютера вообще, тогда вопросы
"Что подвластно асму сейчас, а что нет?" отпадут
ну и вообще , начинать надо именно с этого, а не с изучения "абстрактного ЯП asm"

Автор: ДобренькийПапаша 17.8.2009, 06:36
Цитата(GoldFinch @ 16.8.2009,  12:06)
ДобренькийПапаша, для начала неплохо бы почитать чтонить про устройство процессора и компьютера вообще

Например с Таненбаума... это я в курсе. В свете остальных вопросов на которые вы ответы не дали, первый вопрос не теряет актуальность даже в свете прочтения Таненбаума... так что я жду нормальный ответ.

Автор: GoldFinch 17.8.2009, 10:10
ДобренькийПапаша, я рад что вы в курсе что есть книги Таненбаума (я их не читал)
однако там либо нет того что надо, либо вы читали не то.


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

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

на практике, ЯВУ как язык более высокого уровня позволяет в ряде случаев писать более компактный исходный код, за счет встроенных возможностей ЯВУ. Например если в каком-то ЯВУ есть оператор "написать_программу_с_окошком" то например файл с одним этим оператором уже будет программой, которая выводит окошко, при этом за этим оператором будут скрыты тысячи строк кода.

Какие среды разработки существуют?
- под х86 есть 2 компилятора masm и fasm, 
масм более старый, под него больше заголовочных файлов, однако масм не поддерживается майкрософтом как отдельный компилятор, а сторонняя сборка "masm32" (masm32.com) тоже не развивается в плане синтаксиса
фасм (flatassembler.net) более новый компилятор, опенсорсный, активно развивается, во многом совместим с масмом.
- из ИДЕ используют msvs, RadASM, обычно хватает простого редактора с подсветкой (в фасме есть встроенный)

Написаны ли какие-либо библиотеки программного кода для асма (типа ATL, STL для C++, или скажем отдельно для работы над GUI)?
- ATL и STL  - библиотеки шаблонов, причем сам C++ кроссплатформенный, сравнение малость некорректно.
асм не кроссплатформенный, т.к. зависит от конкретного семейства процессоров (х86-32, х64)
стандартных библиотек для асма нет. т.к. асм - не язык как таковой, со своим стандартом, асмов много
в masm32 есть библиотека masm32.lib схожая с stdlib в С, есть библиотеки для отладки и т.п.
в фасме есть стандартная библиотека макросов, и есть пользовательские библиотеки

при этом надо помнить что объектные модули (.obj) написанные на асме можно слинковать с объектниками на других ЯП, и из асма можно вызывать код написанный на любом другом ЯП.
GUI на асме пишут либо в простых случаях, тогда обходятся winapi\com, либо в случаях когда стандартных подходов нет
написание GUI на асме прироста производительности не дает, разве что уменьшает размер файла, впрочем того же можно добиться и на С(С++)

- с ЧЕГО начать изучение асма
0) с выбора асма, например х86, например под винду
1) с изучения принципа работы процессора (регистры, память, стек и т.п., состояния, флаги, режимы адресации памяти, организация памяти)
2) с изучения ОС, 
поверхностно - если не надо работать с ОС, все равно надо знать организацию памяти в ОС, может надо знать про потоки и исключения, углубленно - если заниматься системным программированием

- список литературы
про процессор можно почитать что-нибудь наподобие "справочника по процессору 386", или по более современному
про ОС (винде) надо читать Рихтера, windows via c\c++

Автор: nlp 22.8.2009, 13:25
К мегапосту GoldFinch'а добавлю лишь, что новичку необходим редактор - простой в обращении, но с мощными возможностями подсветки синтаксиса ассемблера (чтоб ошибок было минимум, и так наделает кучу без опечаток).
Лучшей подсветки чем в http://ogarvv.narod.ru я не встречал нигде.

Автор: cardinal 22.8.2009, 13:28
nlp, ники на форумах принято выделять жирным...

Автор: Kipter 7.5.2010, 05:43
Цитата(GoldFinch @  17.8.2009,  10:10 Найти цитируемый пост)
асм - это минимальный уровень на котором можно писать программы вообще. 
любая программа, будучи скомпилированной состоит из инструкций асма.

Цитата(GoldFinch @  17.8.2009,  10:10 Найти цитируемый пост)
поэтому функциональные языки компилятся в императивный асм код


Но-но-но! аккуратнее с таким заявлением то =) 
Безусловно конечно некоторые компилеры мб и генерят сперва асм код а потом его компилят в машинный. 
Но программа будучи скомпилированной не состоит из инструкций асма =) Асм создает тот же слой абстракции, и скрывает за мнемониками команд процессора - порой целый набор вариантов машинных команд =)

вот в аттаче - пример инструкции MOV, из книги тайн =)
для каждого типа операндов у инструкции mov свой машинный код =)
причем эта таблица не полная и в какой то степени сжатая =)
чтобы получить машинный код инструкции нужно либо к опкоду прибавлять некоторые значения (например номер регистра)
либо после опкода установить управляющие биты например ModR/M и SIB, не зря же в х86 переменная длинна инструкций =)))

Автор: Abyx 7.5.2010, 13:11
Цитата(Kipter @  7.5.2010,  05:43 Найти цитируемый пост)
Безусловно конечно некоторые компилеры мб и генерят сперва асм код а потом его компилят в машинный. 
Но программа будучи скомпилированной не состоит из инструкций асма =) Асм создает тот же слой абстракции, и скрывает за мнемониками команд процессора - порой целый набор вариантов машинных команд =)

Ты ошибаешься.
Асм не создает никаких абстракций, и нет разделения понятий "инструкций асма" и "инструкций проца".

Есть взаимно однозначное соответствие между байтами инструкции и ее текстовым представлением.
Например 
"100: jmp near 105" соответствует E9 00 00 00 00
"100: jmp short 105" соответствует EB 03

Но это если писать инструкцию полностью.
Большинство компиляторов асма, для удобства программиста позволяют опускать спецификаторы размеров операндов, и сами выбирают наиболее удачный вариант. Более того, некоторые компиляторы заменяют одни инструкции другими, например mov на lea.

Но всегда можно написать полное название инструкции, чтобы компилятор скомпилировал нужную инструкцию.
Наиболее наглядно это видно в тех ассемблерах где важна возможность указать конкретный размер инструкции - например в ассемблерах встроенных в OllyDbg, HIEW и т.п.

Автор: Simpleton 23.12.2010, 11:09
Абсолютный новичок в асм но не нра.

Автор: fuckingniger 14.3.2011, 23:40
а есть интерпретатор,  который работает с 64 битной виндой ??? 

Автор: fuckingniger 15.3.2011, 00:07
я пока мало чего понимаю в этом всём.Какую среду выбрать среду разработки для процессора 8086 ???

Автор: Marlik 29.11.2012, 17:53
Привет всем, народ на дворе почти 2013 год, кто использует какие проги для написания, под какие процы и архитектуры, где почитать и что, самое свежее. У меня Windows 7 64 bit. Хочется с чего-то начать а как стартануть не знаю. Спасибо.

Автор: xcislav 14.1.2013, 23:36
А я не могу создать на форуме тему(

Добавлено через 2 минуты и 35 секунд
00000000  BB0000            mov bx,0x0
00000003  31C0              xor ax,ax
00000005  CD16              int 0x16
00000007  B400              mov ah,0x0
00000009  2C30              sub al,0x30
0000000B  91                xchg ax,cx
0000000C  6800B8            push word 0xb800
0000000F  1F                pop ds
00000010  31C0              xor ax,ax
00000012  CD16              int 0x16
00000014  8807              mov [bx],al
00000016  2E88063200        mov [cs:0x32],al
0000001B  43                inc bx
0000001C  43                inc bx
0000001D  E2F1              loop 0x10


Вот программа печатаю - выводит посимвольно в видеобуфер (цикл столько сколько раз первый запрос указан). Но программа не работает. А должна писать после тела программы сразу байты и исполнять их после завершения цикла ввода.

Автор: bernice 20.4.2013, 23:46
Цитата(neutrino @ 26.3.2002,  15:07)
Da, sait nichego, osobenno fanariki na solnechnih batareikah ponravilis. No dolgo gruzitsia.  :satisfied

все что нравится-долго грузится))

Автор: Белоснежка 23.5.2013, 01:14
Привет всем! 

У меня вопрос. Может глупый.

Нам сказали поставить готовую операционку на виртуальную машину. Операционка: Убунту, с насм и гцц. 
Ну и дали задачку, записать в регистр еах число, потом выдать это число наоборот в регистре еbх. Я для переворачивания использовала команду bswap.
Я правильно понимаю, что если я скомпилирую этот код другим ассемблером, то он не будет работать? Но смена самой операционки ведь никак не повлияет на работу кода (если всё-таки скомпилируется), или? 

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