Int 10h ;Вывод символа
add DL, 3 ;сложение
inc SI ;+1
dec DI ;вычитание -1
jnz met2 ;если не равно 0
;—————-Завершение программы—————
mov AX, 4C00h
int 21h
END Start
4.3 Ассемблированием и компоновкой получить исполняемый модуль программы GRAFIC и убедиться в его работоспособности
4.4 Разработать на основе отлаженной программы новую программу GRAFIK_m производящую вывод на экран графика функции, заданной в сегменте данных массивом значений FUNC. Число выводимых на график элементов массива следует выбрать исходя из условия: N = 15 + n, где n – последняя цифра номера зачетной книжки. (При этом значения функции следует программно пронормировать путем деления на некоторый масштабный коэффициент с тем, чтобы максимальное значение не выходило за диапазон допустимых значений координаты Y на экране). Кроме того, в новой программе следует:
а) перенести начало осей координат в центр экрана;
б) обеспечить, чтобы значению Х = 0 соответствовало значение центрального элемента массива;
в) сформировать стрелочки на концах осей координат и обозначить их символами X и Y;
г) задать другой цвет осей и графика.
TITLE GRAFIC
;Программа построения графика функции в текстовом режиме экрана
;Входные параметры:
.MODEL SMALL
.DATA
Func DW 450, -350, 0, 250, 375, 400, 420, 360, 250, 200, 150
DW 325, 300, 285, 200, 0, –200, -275, -250, -150, -100
DW -50, 0, 50, 100, 150, 200
.STACK 256 (?)
.CODE
Start:
mov AX, @DATA
mov DS, AX
mov SI,0
;—————-функция преобразования значений ——-
cicl:
mov AX,Func[si][0] ;заносим первое число в ax
mov bl,55 ;помещаем значение 55 в регистр bl
idiv bl ;знаковое деление на число
cbw ;преобразование байт в слово
mov Func[si][0],AX ;перемещение нового значения в массив
inc SI ;увеличение на 1
inc SI
cmp si,36 ;сравнение индекса с числом
JE mz ;ноли или равно то переход на метку mz
jmp cicl ;переход к метке cicl
;——————————————————-
LOOP cicl ;цикл cicl
mz:
;——— Задание режима экрана с очисткой ————-
mov AH, 0
mov AL, 3 ;Режим 80х25, 16 цветов.
int 10h
;——— Построение вертикальной оси координат ———
mov BH, 0 ;Используем страницу видеопамяти 0.
mov DL, 40 ;Координаты начальной точки Х=40
mov DH, 4 ; Y = 4
metka:
mov AH, 02h ;Выбираем функцию установки курсора.
int 10h ;Установка курсора.
mov CX, 1 ;Выводим по одному символу
mov AL, 179 ;символ вертикальной черточки
mov BL, 00000001b ;Атрибут: синий
mov AH, 09h ;Выбираем функцию вывода символа
int 10h ;Вывод символа
inc DH ;Переход к координате Y+1
cmp DH, 20 ;Сравнение с нижней позицией
jb metka ;Если ниже, повторить цикл вывода символа
;——-Построение горизонтальной оси координат ———
mov BH, 0
mov DL, 13 ;Координаты начальной позиции Х=13
mov DH, 12 ;Y=12
mov AH, 02h ;Выбираем функцию установки курсора.
int 10h ;Вывод символа
mov CX, 55 ;Длина цепочки символов
mov AL,45 ;Символ горизонтальной черточки
mov BL, 00000011b ;атрибут голубой
mov AH, 09h ;Выбираем функцию вывода символа
int 10h ;Вывод символа
;—————Вывод точек графика———————
lea SI, Func ;Загрузка адреса массива значений
mov DI, 16 ;Установка счетчика циклов 15+1
mov CX, 1 ;Вывод по одному символу.mov BH, 0 ;Используем страницу видеопамяти 0
mov DL, 13 ;Координаты первой точки X=13
metka1:
mov DH, 12 ;Y=12.
sub DH, [SI] ;Вычисление Y(i) в системе координат
mov AH, 02h
int 10h
mov AL, 7 ;Символ точки
mov BL, 00001110b ;атрибут `жёлтый
mov AH, 09h ;Выбираем функцию вывода символа
int 10h ;Вывод символа
add DL, 3 ;промежуток между точками
inc SI ;SI+1
dec DI ;DI-1
jnz metka1 ;если не равно 0
;—————Создание верхней стрелки—————-
mov BH, 0 ;Используем страницу видеопамяти 0
mov DL, 40 ;Координаты начальной точки Х=40
mov DH, 4 ; Y = 4
mov AH, 02h ;Выбираем функцию установки курсора
int 10h ;Установка курсора
mov CX, 1 ;Выводим по одному символу
mov AL, 24 ;символ стрелки вверх
mov BL, 00000001b
mov AH, 09h ;Выбираем функцию вывода
int 10h ;Вывод символа
;—————Создание правой стрелки—————
mov BH, 0 ;Используем страницу видеопамяти 0
mov DL, 68 ;Координаты начальной точки Х (13+55)
mov DH, 12 ; Y
mov AH, 02h ;Выбираем функцию установки курсора
int 10h ;Установка курсора
mov CX, 1 ;Выводим по одному символу
mov AL, 26 ;символ стрелки
mov BL,00000011b
mov AH, 09h ;Выбираем функцию вывода символа и атрибута
int 10h ;Вывод символа
;—————БУКВА X——————————
mov BH, 0 ;Используем страницу видеопамяти 0
mov DL, 68 ;Х
mov DH, 13 ;Y
mov AH, 02h ;Выбираем функцию установки курсора
int 10h ;Установка курсора
mov CX, 1 ;Выводим по одному символу
mov AL, 88 ;X в ASCII
mov BL, 00001111b ;цвет белый
mov AH, 09h
int 10h ;Вывод символа
;—————-БУКВА Y—————————-
mov BH, 0 ;Используем страницу видеопамяти 0
mov DL, 43 ;Х
mov DH, 4 ;Y
mov AH, 02h ;Выбираем функцию установки курсора
int 10h ;Установка курсора
mov CX, 1 ;Выводим по одному символу
mov AL, 89 ;Y в ASCII
mov BL, 00001111b
mov AH, 09h
int 10h ;Вывод символа
;—————-Завершение программы—————-
mov AX, 4C00h
int 21h
END Start
Вопросы:
6.1 Поясните принципы вывода текстовой и графической информации на экран.
Для вывода изображений на экран используются видеоадаптеры (видеокарты). Существуют два принципиально разных режима работы видеоадаптеров – текстовый и графический. В тестовом режиме изображение состоит из литер расширенного набора ASCII, а после формируется попиксельно.
6.2 Что такое видеопамять, видеоадаптер и какова их роль в формировании изображений на экране?
6.3 Что представляет собой система координат экрана в текстовом режиме? номер строки и стобца,множество точек расположенных по этим координатам
6.4 Назовите основные типы видеоадаптеров.
– MDA – монохромный адаптер, применяемый в первых PC. Режим – текстовый, 4 цвета.
– HGC – монохромный адаптер фирмы. Режим – текстовый, графический, 4 цвета.
– CGA – цветной графический адаптер. Режимы – текстовый (16 цветов), графический (4 цвета),
– EGA – расширенный графический адаптер. Режим – текстовый, графический, 16 цветов
– VGA – видео графический адаптер. Режим текстовый, графический, 16 цветов (256 цветов с разрешением 320х200)
– SVGA – режим текстовый, графический. Число цветов от 16 до 32 млн. 6.5 Назовите и поясните существующие способы вывода информации на экран.
– с использованием средств DOS (группа функций вводавывода из диапазона 01h…0Ch прерывания INT 21h). Поддерживается 6 Программирование на языке ASSEMBLER только текстовый монохромный режим вывода.
– с использованием средств BIOS с помощью прерывания INT 10h. Позволяет реализовать все возможности видеоадаптеров в текстовом и графическом режимах. Используется в реальном режиме работы МП;
– прямое программирование видеопамяти.
6.6 Что такое системные прерывания? Какие системные прерывания используются для вывода информации на экран дисплея?
Работа с видеоадаптером производится с помощью прерывания INT 10h.
6.7 Назовите основные графические операции, реализованные с помощью BIOS?
Алгоритм создания изображения на экране в текстовом режиме работы состоит из нескольких шагов, которые реализуются функциями BIOS:
– задание режима экрана;
– очистка экрана с заданием цвета фона и воспроизводимых символов;
– установка курсора в нужную позицию;
– вывод символа;
– вывод горизонтальной цепочки любых символов (в том числе и текстовой строки).
6.8 Назовите шаги алгоритма, позволяющего построить изображение в текстовом режиме.
В начале программы следует задать режим экрана. Для этого используется функция BIOS с номером 0.
Номер функции нужно занести в регистр AH, а в регистр AL следует занести номер режима видеоадаптера (см. таблицу 8.1). Текстовому цветному режиму с разрешением 80х25 символов, который предполагается использовать, соответствует номер 3. Таким образом, режим экрана задаётся следующей последовательностью команд:
MOV AH, 00h ;выбор функции задания режима экрана
MOV AL, 03h ;режим видеоадаптера 80х25, 16 цветов
INT 10h ;вызов функции BIOS
6.9 Чем отличаются между собой разные режимы экрана?
Для вывода изображений на экран используются видеоадаптеры (видеокарты), которые подключаются к системе через разъемы расширения и формируют сигналы, управляющие работой монитора. Существуют два принципиально разных режима работы видеоадаптеров – текстовый и графический. В тестовом режиме изображение состоит из литер расширенного набора ASCII, формируемых знакогенератором. При этом из квазиграфических символов, которые входят в набор ASCII, возможно построение примитивных рисунков. В графическом режиме изображение строится попиксельно, что позволяет формировать на экране сложные изображения и надписи разных размеров и конфигураций.
6.10 Какие операции необходимо произвести для вывода некоторого символа в определенном месте экрана?
В коде
6.11 Чем отличаются процедуры изображения на экране горизонтальной и вертикальной цепочки символов?
vertic PROC near
m:
mov AH, 02h ;установка позиции курсора
int 10h ;Установка курсора.
mov CX, 1 ;Выводим по одному символу
mov AL, 7 ;символ ТОЧКИ.
mov BL, 00001110b ;Атрибут: жёлтый по черному фону
mov AH, 09h ;Выбираем функцию вывода символа
int 10h ;Вывод символа.
inc DH ;Переход к координате Y+1.
cmp DH, 15
jb m
RET
vertic ENDP
gorizont PROC near
mov AH, 02h ;установка позиции курсора
int 10h ;Установка курсора.
mov CX, 40 ;Длина цепочки символов.
mov AL,7;Символ точки
mov BL, 00001110b ;Атрибут: жёлтый по черному фону
mov AH, 09h ;Выбираем функцию вывода символа
int 10h ;Вывод символа.
RET
gorizont ENDP
6.12 Как задается цвет экрана и цвет символов?
mov BL, 00000001b
6.13 Какую роль выполняет байт атрибутов символа?
Отдельные биты атрибута кодируют следующие признаки:
Бит 7 (L) при установке в 1 обеспечивает эффект мигания символа.
Бит 3 (I) при установке в 1 обеспечивает повышенную яркость символа.
Биты 6, 5, 4 и 2, 1, 0 определяют цвет фона и символов соответственно. При этом R – красный, G – зеленый, B – синий цвет. Значения 1 обеспечивают наличие соответствующей компоненты цвета, 0 – его отсутствие. Можно заметить, что комбинация 000 соответствует черному, а 111 – белому цвету, R+G дает желтый цвет, R+B – пурпурный, G+B – голубой. Примеры байтов – атрибутов: 00000000b (0h) – черный по черному – неотображаемый символ (для пароля)
assembly — Различия между: INT 10H, INT 16H, INT 21H
Может ли кто-нибудь объяснить мне различия между: INT 10H, INT 16H, INT 21H на языке ассемблера? Когда мы должны использовать любой из них и для чего?
Например: в этом простом коде для печати «Hello, World!» Почему мы использовали int 10h в четвертой строке? Почему мы использовали int 16h в предпоследней строке?
name "hi-world"
org 100h
mov ax, 3
int 10h
mov ax, 1003h
mov bx, 0
int 10h
mov ax, 0b800h
mov ds, ax
mov [02h], 'H'
mov [04h], 'e'
mov [06h], 'l'
mov [08h], 'l'
mov [0ah], 'o'
mov [0ch], ','
mov [0eh], 'W'
mov [10h], 'o'
mov [12h], 'r'
mov [14h], 'l'
mov [16h], 'd'
mov [18h], '!'
mov cx, 12 ; number of characters.
mov di, 03h ; start from byte after 'h'
c: mov [di], 11101100b
add di, 2 ; skip over next ascii code in vga memory.
loop c
; wait for any key press:
mov ah, 0
int 16h
ret
1
Mariah 12 Май 2015 в 12:54
3 ответа
Лучший ответ
Прежде всего INT
означает прерывание и не имеет ничего общего с типом данных int
.
Каждый INT
представляет семейство функций, где обычно AH
представляет номер функции.
Например :
INT 0x10 используется для управления экраном
- AH = 0x00 -> установить режим видео
- AX = 0x1003 -> Установить режим мигания
- AH = 0x13 -> написать строку
- AH = 0x03 -> получить позицию курсора
INT 0x13 предназначен для хранения (HDD и FDD)
- AH = 0x42 -> ЧТЕНИЕ ДИСКА
- AH = 0x43 -> ЗАПИСЬ НА ДИСК
- INT 0x16 предназначен для управления с клавиатуры и читает:
- AH = 0x00 -> GetKey
- AH = 0x03 -> Установить скорость печати и задержку.
Вы можете найти все эти функции здесь: Таблица переходов по прерыванию
Но это просто BIOS INT, который ОС может переписать при запуске. Например, Windows использует INT 0x21
для связи между пространством пользователя и пространством ядра; Использование на базе Linux INT 0x80
. См. Также таблицу системных вызовов Linux
В вашем коде:
- INT 0x10 с AH = 0x00 и AL = 3 (
mov ax, 3
) означает: установить режим видео в TextMode 80×25 символов и 16 цветов. - INT 0x10 с AX = 0x1003 означает: ПЕРЕКЛЮЧЕНИЕ ИНТЕНСИВНОСТИ / МИГАЮЩЕГО БИТА для включения интенсивности фона
12
Gabriel Ciubotaru 20 Май 2015 в 12:30
INT здесь означает ПРЕРЫВАНИЕ и имеет функциональный режим, такой как 00,01,02 и т. д., INT 10h
используется для инициализации графического и видео режима, а INT 16h
используется чтобы установить ход клавиатуры.
1
Michael Petch 16 Дек 2015 в 23:56
Что касается этой части вашего вопроса:
Когда мы должны использовать любой из них и для чего?
Наверное, никогда.
Эти прерывания BIOS в основном использовались приложениями MS-DOS, и сегодня они практически устарели. Они недоступны во время выполнения для приложений, работающих в любой современной операционной системе, поэтому вы, вероятно, никогда не будете их использовать. (Исключения могут быть в том случае, если вы разрабатываете определенные части программного обеспечения, которые запускаются очень рано в процессе загрузки, например, загрузчик, прошивку для аппаратного устройства, или если вы разрабатываете сам BIOS.)
5
duskwuff -inactive- 17 Дек 2015 в 00:23
Функция 2 прерывание int 10h
Входные параметры: в dh номер строки, в dl номер столбца, в bh номер видеостраницы (для нас всегда 0).
Подпрограмма устанавливает курсор в заданную позицию.
ПРИМЕР: Установить курсор в центр экрана.
mov dx, 0c28h ; 12-я строка (0сh), 40-й столбец (28h).
mov bh, 0
mov ah, 2
int 10h
Функция 3 прерывание int 10h
Входные параметры: в bh номер видеостраницы (для нас 0)
Прерывание возвращает текущие координаты и конфигурацию курсора: в dh возвращается строка, в dl – столбец, в ch – верхняя строка развертки, в cl – нижняя строка развертки.
ПРИМЕР: запомнить текущую позицию курсора в переменной cursor
mov ah, 3
mov bh, 0
int 10h
mov cursor, dx
Функция 6 прерывание int 10h
Входные параметры: сх – координаты левого верхнего угла прямоугольной области экрана (ch – строка, cl – столбец), dx – координаты правого нижнего угла (dh – строка, dl – столбец), al – на сколько строк прокручивать заданное окно (при al = 0 все заданное окно очищается), bh — атрибуты для заполнения освобождающихся строк.
Прокрутка заданной прямоугольной области экрана (окна) на заданное число строк вверх. Такая процедура называется «скроллинг».
ПРИМЕР: Очистить экран.
mov cx, 0 ; левый верхний угол экрана. Строка=0, столбец=0.
mov dx, 184fh ; правый нижний угол экрана. Строка=24 (18h), столбец=79 (4fh)
mov bh,7 ; белый по черному mov ax, 600h ; функция 6. Очистить весь экран. int 10h
Функция 9 прерывание int 10h
Входные параметры: bh — номер видеостраницы (у нас 0), bl — атрибуты символа, al — ASCII-код выводимого символа, сх — число повторений.
Выводит заданный символ в текущую позицию курсора. Курсор при этом не перемещается. В сх помещается число х ( х >=1 ). При выводе символ распространяется на х позиций вправо от курсора. То есть если х =1, то будет напечатан один символ, при х =2 — два символа (одинаковых) и. т. д. Если cx =0, ничего выводиться не будет!!! Коды 7, 8, 0ah и 0dh являются управляющими.
ПРИМЕР: Забить верхнюю строку экрана символом «*». Вывод произвести черным по белому.
mov ah, 2 ; устанавливаем курсор
mov bh, 0 ; видеостраница 0
mov dx, 0 ; левый верхний угол экрана (строка = столбец =0)
int 10h
mov ah, 9 ; вывод символа
mov bh, 0 ; видеостраница 0
mov bl, 70h ; черным по белому
mov al, ‘*’
mov cx, 80 ; заполняем всю строку
int 10h
Функция 0eh прерывания int 10h
Входные параметры: al — ASCII-код выводимого символа
Выводит символ в текущую позицию курсора, после чего курсор сдвигается на позицию вправо. Символ выводится с текущими атрибутами.
Очень часто в программах приходится программным образом организовывать задержку. Например, если у нас по экрану летает символ, без задержки он будет летать настолько быстро, что мы увидим только некое мерцание. Есть несколько способов организации такой задержки.
Способ 1. Пустой цикл.
mov cx, 0ffffh ; в cx максимально возможное число
zero_loop: loop zero_loop
Увы, для современных процессоров эта задержка окажется слишком мала, мы ее даже не заметим. Приходиться делать вложенный пустой цикл. Например, так:
mov bx, 400
m1: mov cx, 0ffffh
m2: loop m2
dec bx
jnz m1
Недостаток заключается в том, что здесь время задержки зависит от производительности процессора. То есть, для конкретного компьютера ее приходится подбирать, уменьшая или увеличивая наше число 400.
Способ 2.
mov ah, 86h
mov cx, 4
mov dx, 0
int 15h
Эта функция прерывания int 15h отрабатывает задержку, заданную (в микросекундах) в регистровой паре cx:dx. В приведенном выше примере задержка составит порядка 218 микросекунд, то есть примерно четверть секунды. Недостаток заключается в том, что некоторые операционные системы (в частности, Windows NT) эту задержку «не понимают» (программа выполняется, а задержки нет).
Способ 3. Работа с системными часами, расположенными в области переменных BIOS.
Функция 0 прерывания 1ah возвращает в cx:dx текущее число тиков таймера. Таймер тикает примерно 20 раз в секунду. Отсюда, если мы реализуем такой фрагмент:
mov ah, 0
int 1ah
mov bx, dx
add bx, 10
mwait:
mov ah, 0
int 1ah
cmp dx, bx
jb mwait ; если меньше, снова идем на mwait
то получим задержку на полсекунды.
В качестве примера работы с экраном и клавиатурой, приведем программу, демонстрирующую тривиальное передвижение на экране принятого с клавиатуры символа. Программа очищает экран, ждет нажатия любой символьной клавиши, после чего принятый символ пролетает по 12-й строке от левого края экрана к его центру, где и останавливается. Затем программа снова ждет нажатия символьной клавиши и все повторяется сначала. Выход из программы по ESC.
code segment
assume cs:code, ds:code
org 100h
start:
jmp begin
x db 0 ;координата курсора по Х, исходный столбец 0
simb db 0
begin:
; прячем курсор
mov ah, 1
mov ch, 20
mov cl, 0
int 10h
; чистим экран красным цветом, символ будет черным
mov cx, 0
mov dx, 184fh
mov bh, 40h
mov ax, 600h
int 10h
m1:
; ждем нажатия клавиши
mov ah, 0
int 16h
; отсекаем функциональные клавиши
cmp al, 0
je m1
; проверяем на ESC
cmp al, 1bh
je exit
; сохраняем принятый символ
mov simb, al
; выводим пробел в центр экрана (стираем старый символ)
mov ah, 2
mov dx, 0c28h
mov bh, 0
int 10h
mov ah, 0eh
mov al, ‘ ‘
int 10h
m2:
; устанавливаем курсор для вывода символа
mov ah, 2
mov bh, 0
mov dh, 12 ; символ летит по 12-й строке
mov dl, x
int 10h
; выводим символ в текущую позицию курсора
mov ah, 9
mov cx, 1
mov bl, 40h
mov bh, 0
mov al, simb
int 10h
; задержка
mov ah, 0
int 1ah
mov bx, dx
add bx, 2
m3:
mov ah, 0
int 1ah
cmp dx, bx
jb m3
; увеличиваем Х координату курсора на единицу
inc x
; проверка на выход за центр экрана (40-й столбец)
cmp x, 41
jne m4
mov x, 0 ; восстанавливаем исходное значение Х координаты курсора
jmp m1 ; пошли на ожидание нажатия клавиши
m4:
; стираем символ в текущей позиции (пробелом)
mov ah, 0eh
mov al, ‘ ‘
int 10h
jmp m2 ; пошли на вывод символа в следующей позиции
exit:
mov ah, 4ch
int 21h
code ends
end start
ЗАДАНИЯ К ЛАБОРАТОРНОЙ РАБОТЕ «Клавиатура и экран»
1. Программа очищает экран. В центре экрана печатается звездочка. С помощью клавиш-стрелок можно перемещать эту звездочку по всему экрану, не выходя, однако, за его пределы. В любой момент на экране находится только одна звездочка. Выход из программы по нажатию клавиши TAB.
2. Программа очищает экран. При нажатии любой символьной клавиши на экране появляется соответствующий символ, который в дальнейшем можно распространять по экрану с помощью клавиш-стрелок. В любой момент можно сменить символ, нажав другую символьную клавишу. Выход из программы по нажатию клавиши ESC.
3. Программа очищает экран и вырезает в центре экрана инверсное окно разумных размеров. Далее, при нажатии любой символьной клавиши её отображение должно появляться внутри этого окна. Таким образом, окно постепенно заполняется вводимыми с клавиатуры символами. Заполнение окна происходит в общепринятом порядке: слева –направо – сверху — вниз. Выход из программы по нажатию клавиши INS или при полном заполнении окна.
4. Программа очищает экран. Вводимый с клавиатуры символ появляется одновременно во всех четырех углах экрана и с разумной скоростью слетается по диагоналям в центр экрана, где и застывает. При следующем нажатии любой из символьных клавиш все повторяется. Выход из программы по нажатию клавиши F10.
5. По экрану (хаотично!) летают два шарика (нули), зеркально отражаясь от его границ. К границе шарики подлетают под углом 45 градусов. Нажатие клавиши SPACE останавливает движение шариков, а последующее нажатие любой другой клавиши снова его возобновляет. Выход из программы по нажатию клавиши ESC или при столкновении шариков.
6. Программа очищает экран и вырезает в его центре инверсное окно разумных размеров. Вводимый с клавиатуры символ полностью заполняет это окно. При вводе следующего символа всё повторяется. Выход из программы по нажатию F9.
7. Программа очищает экран и вырезает в его центре инверсное окно разумных размеров. Вводимый с клавиатуры символ должен, с разумной скоростью, двигаться вокруг этого окна (по его кромке). При вводе следующего символа всё повторяется. Выход из программы по нажатию F8.
8. После запуска программы по границам очищенного экрана бежит «змей», например из 8-ми звездочек или нулей. С помощью клавиш-стрелок направление движения «змея» можно менять на 90 градусов от текущего направления. При достижении границы экрана «змей» автоматически заворачивает на 90 градусов вправо, то есть переходит на первоначальную траекторию. Выход из программы по нажатию клавиши SPACE.
9. Программа очищает экран. При вводе символа последний полностью заполняет собой границы экрана. Следующий вводимый символ полностью заполняет собой внешние границы ещё «чистой» области экрана. И так далее. Выход из программы по нажатию клавиши DEL или при полном заполнении экрана.
10. Программа очищает экран и рисует вертикальную инверсную линию, проходящую через весь экран. Эта линия должна иметь 2-3 разрыва шириной 1-2 строки. Затем программа просит игрока задать номер строки. После того как номер введен, по соответствующей строке из-за левой границы экрана вылетает шарик (например, ноль) и летит по горизонтали через экран (с разумной скоростью). Если шарик попал в разрыв программа, хвалит игрока, если не попал — ругает. Программа предоставляет игроку пять попыток. Выход из программы по нажатию клавиши ESC или после пяти попыток.
11. Программа очищает экран. Внешние границы экрана заполняются звездочками. Начиная с левого верхнего угла по верхней кромке экрана выводится фамилия одного из членов бригады. Так как фамилия выводится в ту же строку что и звездочки, то в соответствующих позициях (и только в них) звездочки отсутствуют. При нажатии клавиши R вся эта картинка начинает с разумной скоростью сдвигаться по часовой стрелке. То есть фамилия вместе со звездочками вращается вокруг экрана, при этом в любой момент времени границы экрана должны быть полностью заполнены, а остальная часть экрана должна быть чистой. Клавиша S останавливает вращение, клавиша R— возобновляет, клавиша ESC— выход из программы.
12. Программа очищает экран и выводит на него набираемую на клавиатуре информацию, но не в общепринятом порядке (слева – направо – сверху – вниз), а сверху – вниз – слева — направо. То есть сначала заполняется крайний левый столбец, затем следующий слева столбец и так далее. Соответственно меняется направление работы управляющих клавиш: ENTER, BACKSPACE, TAB и клавиш-стрелок. Выход из программы по нажатию клавиши ESC.
Примечание: СКЭН и ASCII коды для различных клавиш можно найти в различных справочниках. Очень хороша для этих целей маленькая программа code.exe.
ГЛАВА 8 Экранные операции I — АССЕМБЛЕР ДЛЯ ПРОЦЕССОРА 8086 . — КОМПЬЮТЕРНАЯ МАГИЯ . — Каталог статей
ГЛАВА 8 Экранные операции I: Основные свойства
__________________________________________________________________________
Ц е л ь: Объяснить требования для вывода информации на экран, а также
для ввода данных с клавиатуры.
ВВЕДЕНИЕ
________________________________________________________________
В предыдущих главах мы имели дело с программами, в которых данные
oпределялись в операндах команд (непосредственные данные) или
инициализировались в конкретных полях программы. Число практических
применений таких программ в действительности мало. Большинcтво программ
требуют ввода данных с клавиатуры, диска или модема и обеспечивают вывод
данных в удобном формате на экран, принтер или диск. Данные,
предназначенные для вывода на экран и ввода с клавиатуры, имеют ASCII
формат.
Для выполнения ввода и вывода используется команда INT (прерывание).
Существуют различные требования для указания системе какое действие (ввод
или вывод) и на каком устройстве необходимо выполнить. Данная глава
раскрывает основные требования для вывода информации на экран и ввода
данных с клавиатуры.
Все необходимые экранные и клавиатурные операции можно выполнить
используя команду INT 10H, которая передает управление непосредственно в
BIOS. Для выполнения некоторых более сложных операций существует
прерывание более высокого уровня INT 21H, которое сначала передает
управление в DOS. Например, при вводе с клавиатуры может потребоваться
подсчет введенных символов, проверку на максимальное число символов и
проверку на символ Return. Преpывание DOS INT 21H выполняет многие из этих
дополнительных вычислений и затем автоматически передает управление в
BIOS.
Материал данной главы подходит как для монохромных (черно-белых, BW),
так и для цветных видеомониторов. В гл. 9 и 10 приведен материал для
управления более совершенными экранами и для использования цвета.
КОМАНДА ПРЕРЫВАНИЯ: INT
________________________________________________________________
Команда INT прерывает обработку программы, передает управление в DOS
или BIOS для определенного действия и затем возвращает управление в
прерванную программу для продолжения обработки. Наиболее часто прерывание
используется для выполнения операций ввода или вывода. Для выхода из
программы на обработку прерывания и для последующего возврата команда INT
выполняет следующие действия:
— уменьшает указатель стека на 2 и заносит в вершину стека
содержимое флагового регистра;
— очищает флаги TF и IF;
— уменьшает указатель стека на 2 и заносит содержимое регистра
CS в стек;
— уменьшает указатель стека на 2 и заносит в стек значение
командного указателя;
— обеспечивает выполнение необходимых действий;
— восстанавливает из стека значение регистра и возвращает
управление в прерванную программу на команду, следующую после INT.
Этот процесс выполняется полностью автоматически. Необходимо лишь
определить сегмент стека достаточно большим для записи в него значений
регистров.
В данной главе рассмотрим два типа прерываний: команду BIOS INT 10H и
команду DOS INT 21H для вывода на экран и ввода с клавиатуры. В
последующих примерах в зависимости от требований используются как INT 10H
так и INT 21H.
УСТАНОВКА КУРСОРА
________________________________________________________________
Экран можно представить в виде двумерного пространства с адресуемыми
позициями в любую из которых может быть установлен курсор. Обычный
видеомонитор, например, имеет 25 строк (нумеруемых от 0 до 24) и 80
столбцов (нумеруемых от 0 до 79). В следующей таблице приведены некоторые
примеры положений курсора на экране:
________________________________________________________
Дес. формат Шест. формат
______________ ______________
Положение строка столбец строка столбец
________________________________________________________
Верхний левый угол 00 00 00 00
Верхний правый угол 00 79 00 4F
Центр экрана 12 39/40 00 27/28
Нижний левый угол 24 00 18 00
Нижний правый угол 24 79 18 4F
________________________________________________________
Команда INT 10H включает в себя установку курсора в любую позицию и
очистку экрана. Ниже приведен пример установки курсора на 5-ую строку и
12-ый столбец:
MOV AH,02 ;Запрос на установку курсора
MOV BH,00 ;Экран 0
MOV DH,05 ;Строка 05
MOV DL,12 ;Столбец 12
INT 10H ;Передача управления в BIOS
Значение 02 в регистре AH указывает команде INT 10H на выполнение операции
установки курсора. Значение строки и столбца должны быть в регистре DX, а
номер экрана (или страницы) в регистре BH (обычно 0). Содержимое других
регистров несущественно. Для установки строки и столбца можно также
использовать одну команду MOV c непосредственным шест. значением:
MOV DX,050CH ;Строка 5, столбец 12
ОЧИСТКА ЭКРАНА
________________________________________________________________
Запросы и команды остаются на экране пока не будут смещены в
результате прокручивания («скроллинга») или переписаны на этом же месте
другими запросами или командами. Когда программа начинает cвое выполнение,
экран может быть очищен. Очищаемая область экрана может начинаться в любой
позиции и заканчиваться в любой другой позиции с большим номером.
Начальное значение строки и столбца заносится в регистр DX, значение 07 —
в регистр BH и 0600H в AX. В следующем примере выполняется очистка всего
экрана:
MOV AX,0600H ;AH 06 (прокрутка)
;AL 00 (весь экран)
MOV BH,07 ;Нормальный атрибут (черно/белый)
MOV CX,0000 ;Верхняя левая позиция
MOV DX,184FH ;Нижняя правая позиция
INT 10H ;Передача управления в BIOS
Значение 06 в регистре AH указывает команде INT 10H на выполнение
операции очистки экрана. Эта операция очищает экран пробелами; в следующей
главе скроллинг (прокрутка) будет рассмотрен подробнее. Если вы по ошибке
установили нижнюю правую позицию больше, чем шест. 184F, то очистка
перейдет вновь к началу экрана и вторично заполнит некоторые позиции
пробелами. Для монохромных экранов это не вызывает каких-либо
неприятностей, но для некоторых цветных мониторов могут возникнуть
серьезные ошибки.
ЭКРАННЫЕ И КЛАВИАТУРНЫЕ ОПЕРАЦИИ: БАЗОВАЯ ВЕРСИЯ DOS
________________________________________________________________
Обычно программы должны выдать на экран сообщение о завершении или об
обнаружении ошибки, отобразить запрос для ввода данных или для получения
указания пользователя. Рассмотрим сначала методы, применяемые в базовой
версии DOS, в последующих pазделах будут показаны расширенные методы,
введенные в DOS версии 2.0. Операции из базовой DOS работают во всех
версиях, хотя в руководстве по DOS рекомендуется применять расширенные
возможности для новых разработок. В базовой версии DOS команды вывода на
экран более сложны, но команды ввода с клавиатуры проще в использовании,
благодаря встроенным проверкам.
ВЫВОД НА ЭКРАН: БАЗОВАЯ ВЕРСИЯ DOS
________________________________________________________________
Вывод на экран в базовой версии DOS требует определения текстового
сообщения в области данных, установки в регистре AH значения 09 (вызов
функции DOS) и указания команды DOS INT 21H. В процессе выполнения
операции конец сообщения определяется по oграничителю ($), как это
показано ниже:
NAMPRMP DB ‘Имя покупателя?’,’$’
.
.
MOV AH,09 ;Запрос вывода на экран
LEA DX,NAMPRMP ;Загрузка адреса сообщ.
INT 21H ;Вызов DOS
Знак ограничителя «$» можно кодировать непосредственно после cимвольной
строки (как показано в примере), внутри строки: ‘Имя покупателя?$’, или в
следующем операторе DB ‘$’. Используя данную операцию, нельзя вывести на
экран символ доллара «$». Кроме того, если знак доллара будет
отсутствовать в конце строки, то на экран будут выводиться все последующие
символы, пока знак «$» не встретиться в памяти.
Команда LEA загружает адрес области NAMPRMP в регистр DX для передачи
в DOS адреса выводимой информации. Адрес поля NAMPRMP, загружаемый в DX по
команде LEA, является oтносительным, поэтому для вычисления абсолютного
адреса данных DOS складывает значения регистров DS и DX (DS:DX).
ПРОГРАММА: ВЫВОД НА ЭКРАН НАБОРА СИМВОЛОВ КОДА ASCII
________________________________________________________________
Большинство из 256 кодов ASCII имеют символьное представление, и
могут быть выведены на экран. Шест. коды 00 и FF не имеют символов и
выводятся на экран в виде пробелов, хотя символ пробела имеет в ASCII
шест. код 20.
На рис.8.1 показана COM-программа, которая выводит на экран полный
набор символов кода ASCII. Программа вызывает три процедуры; B10CLR,
C10SET и D10DISP. Процедура B10CLR очищает экран, а процедура C10SET
устанавливает курсор в положение 00,00. Процедура D10DISP выводит
содержимое поля CTR, которое в начале инициализировано значением 00 и
затем yвеличивается на 1 при каждом выводе на экран, пока не достигнет
шест. значения FF.
__________________________________________________________________________
page 60,132
TITLE ALLASC (COM) Вывод на экран ASCII-символов 00-FF
CODESC SEGMENT PARA ‘Code’
ASSUME CS:CODESG,DS:CODESG,SS:CODESG,ES:NOTHING
ORG 100H
BEGIN: JMP SHORT MAIN
CTR DB 00,’S’
; Основная процедура:
; ——————
MAIN PROC NEAR
CALL B10CDR ;Очистить экран
CALL C10SET ;Установить курсор
CALL D10DISP ;Вывести символ на экран
RET
MAIN ENDP
; Очистка экрана:
; —————
B10CLR PROC
MOV AX,0600H
MOV BH,07
MOV CX,0000 ;Левая верхняя позиция
MOV DX,184FH ;Правая нижняя позиция
INT 10H
RET
B10CLR ENDP
; Установка курсора в 00,00:
; ————————-
C10SET PROC
MOV AN,02
MOV BN,00
MOV DX,0000
INT 10H
RET
C10SET ENDP
; Вывод на экран ASCII символов:
; ——————————
D10DISP PROC
MOV CX,256 ;256 итераций
LEA DX,CTR ;Адрес счетчика
D20
MOV AH,09 ;Функция вывода символа
INT 21H
INC CTR ;Увеличить счетчик
LOOP D20 ;Уменьшить CX,
; цикл, если не ноль
RET ;Вернуться
D10DISP ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.8.1. Вывод на экран набора символов кода ASCII
Так как символ доллара не выводится на экран и кроме того коды от
шест.08 до шест.0D являются специальными управляющими cимволами, то это
приводит к перемещению курсора и другим управляющим воздействиям. Задание:
введите программу (рис.8.1), выполните ассемблирование, компоновку и
преобразование в COM-файл. Для запуска программы введите ее имя, например,
В:ASCII.COM.
Первая выведенная строка начинается с пробельного символа (шест.00),
двух «улыбающихся лиц» (шест.01 и 02) и трех карточных символов (шест.03,
04 и 05). Код 07 выдает звуковой сигнал. Код 06 должен отобразиться
карточным символом «пики», но управляющие символы от шест.08 до 0D сотрут
его. Код 0D является «возвратом каретки» и приводит к переходу на новую
(следующую)строку. Код шест.0E — представляется в виде музыкальной ноты.
Символы после шест.7F являются графическими.
Можно изменить программу для обхода управляющих символов. Ниже
приведен пример фрагмента программы, позволяющий обойти все символы между
шест.08 и 0D. Вы можете поэкспериментировать, oбходя только, скажем,
шест.08 (возврат на символ) и 0D (возврат каретки):
CMP CTR,08H ;Меньше чем 08?
JB D30 ; да — принять
CMP CTR,0DH ; Меньше/равно 0D?
JBE D40 ; да — обойти
D30:
MOV AH,40H ;Вывод символов < 08
… ; и > 0D
INT 21H
D40:
INC CTR
ВВОД ДАННЫХ С КЛАВИАТУРЫ: БАЗОВАЯ ВЕРСИЯ DOS
________________________________________________________________
Процедура ввода данных с клавиатуры проще, чем вывод на экран. Для
ввода, использующего базовую DOS, область ввода требует наличия cписка
параметров, содержащего поля, которые необходимы при выполнении команды
INT. Во-первых, должна быть определена максимальная длина вводимого
текста. Это необходимо для предупреждения пользователя звуковым сигналом,
если набран слишком длинный текст; символы, превышающие максимальную длину
не принимаются. Во-вторых, в списке параметров должно быть определенное
поле, куда команда возвращает действительную длину введенного текста в
байтах.
Ниже приведен пример, в котором определен список параметров для
области ввода. LABEL представляет собой директиву с атрибутом BYTE. Первый
байт содержит максимальную длину вводимых данных. Так как это однобайтовое
поле, то возможное максимальное значение его — шест.FF или 255. Второй
байт необходим DOS для занесения в него действительного числа введенных
символов. Третьим байтом начинается поле, которое будет содержать
введенные символы.
NAMEPAR LABEL BYTE ;Список параметров:
MAXLEN DB 20 ; Максимальная длина
ACTLEN DB ? ; Реальная длина
NAMEFLD DB 20 DUP (‘ ‘) ; Введенные символы
Так как в списке параметров директива LABEL не занимает места, то
NAMEPAR и MAXLEN указывают на один и тот же aдрес памяти. В трансляторе
MASM для определения списка параметров в виде структуры может
использоваться также директива STRUC. Однако, в связи с тем, что ссылки на
имена, определенные внутри, требуют специальной адресации, воздержимся
cейчас от рассмотрения данной темы до гл.24 «Директивы ассемблера».
Для запроса на ввод необходимо поместить в регистр AH номер функции —
10 (шест. 0AH), загрузить адрес списка параметров (NAMEPAR в нашем
примере) в регистр DX и выполнить INT 21H:
MOV AH,0AH ;Запрос функции ввода
LEA DX,NAMEPAR ;Загрузить адреса списка параметров
INT 21H ;Вызвать DOS
Команда INT ожидает пока пользователь не введет с клавиатуры текст,
проверяя при этом, чтобы число введенных cимволов не превышало
максимального значения, указанного в списке параметров (20 в нашем
примере). Для указания конца ввода пользователь нажимает клавишу Return.
Код этой клавиши (шест. 0D) также заносится в поле ввода (NAMEFLD в нашем
примере). Если, например, пользователь ввел имя BROWN (Return), то cписок
параметров будет содержать информацию:
дес.: |20| 5| В| R| O| W| N| #| | | | | …
шест.: |14|05|42|52|4F|57|4E|0D|20|20|20|20| …
Во второй байт списка параметров (ACTLEN в нашем примере) команда
заносит длину введенного имени — 05. Код Return находится по адресу
NAMEFLD +5. Символ # использован здесь для индикации конца данных, так как
шест. 0D не имеет отображаемого символа. Поскольку максимальная длина в 20
символов включает шест.0D, то действительная длина вводимого текста может
быть только 19 символов.
ПРОГРАММА: ВВОД И ВЫВОД ИМЕН
________________________________________________________________
EXE-программа, приведенная на рис. 8.2, запрашивает ввод имени, затем
отображает в середине экрана введенное имя и включает звуковой сигнал.
Программа продолжает запрашивать и отображать имена, пока пользователь не
нажмет Return в ответ на очередной запрос. Рассмотрим ситуацию, когда
пользователь ввел имя TED SMITH:
1. Разделим длину 09 на 2 получим 4, и
2. Вычтем это значение из 40, получим 36
Команда SHR в процедуре E10CENT сдвигает длину 09 на oдин бит вправо,
выполняя таким образом деление на 2. Значение бит 00001001 переходит в
00000100. Команда NEG меняет знак +4 На -4. Команда ADD прибавляет
значение 40, получая в регистре DL номер начального столбца — 36. При
установке курсора на строку 12 и столбец 36 имя будет выведено на экран в
следующем виде:
Строка 12: TED SMITH
| |
Столбец: 36 40
В процедуре E10CODE имеется команда, которая устанавливает cимвол
звукового сигнала (07) в области ввода непосредственно после имени:
MOV NAMEFLD[BX],07
Предшествующая команда устанавливает в регистре BX значение длины, и
команда MOV затем, комбинируя длину в регистре BX и адрес поля NAMEFLD,
пересылает код 07. Например, при длине имени 05 код 07 будет помещен по
адресу NAMEFLD+05 (замещая значение кода Return). Последняя команда в
процедуре E10CODE устанавливает ограничитель «$» после кода 07. Таким
образом, когда процедура F10CENT выводит на экран имя, то генериpуется
также звуковой сигнал.
__________________________________________________________________________
page 60,132
TITLE CTRNAME (EXE) Ввод имен и вывод в центр экрана
;———————————————————
STSCKSG SEGMENT PARA STACK ‘Stack’
DW 32 DUP(?)
STACKSG ENDS
;———————————————————
DATASG SEGMENT PARA ‘Data’
NAMEPAR LABEL BYTE ;Имя списка параметров:
MAXNLEN DB 20 ; макс. длина имени
NAMELEN DB ? ; число введенных символов
NAMEFLD DB 20 DUP(‘ ‘),’$’ ;имя и ограничитель для вывода на экран
PRIMPT DB ‘Name? ‘, ‘$’
DATASG ENDS
;———————————————————
CODESG SEGMENT PARA ‘Code»
BEGIN PROC FAR
ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASC
PUSH DS
SUB AX,AX
PUCH AX
MOV AX,DATASC
MOV DS,AX
MOV ES,AX
CALL Q10CLR ;Очистить экран
A20LOOP:
MOV DX,0000 ;Установить курсор в 00,00
CALL Q20CURS
CALL B10PRMP ;Выдать текст запроса
CALL D10INPT ;Ввести имя
CALL Q10CLR ;Очистить экран
CMP NAMELEN,00 ;Имя введено?
JE A30 ; нет — выйти
CALL E10CODE ;Установить звуковой сигнал
; и ограничитель ‘$’
CALL F10CENT ;Центрирование и вывод
JMP A20LOOP
A30:
RET ;Вернуться в DOS
BEGIN ENDP
; Вывод текста запроса:
; ———————
B10PRMP PROC NEAR
MUV AN,09 ;Функция вывода на экран
LEA DX,PROMPT
INT 21H
RET
B10PRMP ENDP
; Ввод имени с клавиатуры:
; ————————
D10INPT PROC NEAR
MOV AN,0AN ;Функция ввода
LEA DX,NAMEPAR
INT 21H
RET
D10INPT ENDP
; Установка сигнала и ограничителя ‘$’:
; ————————————
E10CODE PROC NEAR
MOV BN,00 ;Замена символа Return (0D)
MOV BL,NAMELEN ; на зв. сигнал (07)
MOV NAMEFLD[BX],07
MOV NAMEFLD[BX+1],’$’ ;Установить ограничитель
RET
E10CODE ENDP
; Центрирование и вывод имени на экран:
; ————————————
F10CENT PROC NEAR
MOV DL,NAMELEN ;Определение столбца:
SHR DL,1 ; разделить длину на 2,
NEG DL ; поменять знак,
ADD DL,40 ; прибавить 40
MOV DH,12 ;Центральная строка
CALL Q20CURS ;Установить курсор
MOV AN,09
LEA DX,NAMEFLD ;Вывести имя на экран
INT 21H
RET
F10CENT ENDP
; Очистить экран:
; —————
Q10CLR PROC NEAR
MOV AX,0600H ;Функция прокрутки экрана
MOV BH,30 ;Цвет (07 для ч/б)
MOV CX,0000 ;От 00,00
MOV DX,184FH ;До 24,79
INT 10H ;Вызов BIOS
RET
Q10CLR
; Установка курсора (строка/столбец):
; ———————————-
Q20CURS PROC NEAR ;DX уже установлен
MOV AH,02 ;Функция установки курсора
MOV BH,00 ;Страница #0
INT 10H ;Вызов BIOS
RET
Q20CURS ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.8.2. Ввод и отображение имен.
Ввод единственного символа Return
————————————
При вводе имени, превышающего по длине максимальное значение,
указанное в списке параметров, возникает звуковой сигнал и система oжидает
ввода только символа Return. Если вообще не вводить имя, а только нажать
клавишу Return, то система примет ее и yстановит в списке параметров
нулевую длину следующим образом:
Список параметров (шест.): |14|00|0D|…
Для обозначения конца вводимых имен пользователь может просто нажать
Return в ответ на очередной запрос на ввод имени. Прогpамма определяет
конец ввода по нулевой длине.
Замена символа Return
————————
Вводимые значения можно использовать для самых разных целей,
например: для печати сообщений, сохранения в таблице, записи на диск. При
этом, возможно, появится необходимость замены символа Return (шест.0D) в
области NAMEFLD на символ пробела (шест.20). Поле NAMELEN содержит
действительную длину или отноcительный адрес кода 0D. Если, например,
NAMELEN содержит длину 05, то адрес кода 0D равен NAMEFLD+5. Можно занести
эту длину в регистр BX для индексной адресации в поле NAMEFLD:
MOV BH,00 ;Установить в регистре BX
MOV BL,NAMELEN ; значение 0005
MOV NAMEFLD[BX],20H ;Заменить 0D на пробел
Третья команда MOV заносит символ пробела (шест.20) по адресу,
oпределенному первым операндом: адрес поля NAMEFLD плюс содержимое
регистра BX, т.е. NAMEFLD+5.
Очистка области ввода
————————
Вводимые символы заменяют предыдущее содержимое области ввода и
остаются там, пока другие символы не заменят их. Рассмотрим следующие три
успешных ввода имен:
Ввод NAMEPAR (шест.)
1. BROWN |14|05|42|52|4F|57|4E|0D|20|20|20| … |20|
2. HAMILTON |14|08|48|41|4D|49|4C|54|4F|4E|0D| … |20|
3. ADAMS |14|05|41|44|41|4D|53|0D|4F|4E|0D| … |20|
Имя HAMILTON заменяет более короткое имя BROWN. Но, так как имя ADAMS
короче имени HAMILTON, то оно заменяет только HAMIL. Код Return заменяет
символ T. Остальные буквы — ON oстаются после имени ADAMS. Для очистки
поля NAMEFLD до ввода очередного имени может служить следующая программа:
MOV CX,20 ;Установить 20 циклов
MOV SI,0000 ;Начальная позиция поля
B30:
MOV NAMEFLD[si],20H ;Переслать один пробел
INC SI ;Следующая позиция поля
LOOP B30 ;20 циклов
Вместо регистра SI можно использовать DI или BX. Более эффективный
способ очистки поля, предполагающий пересылку слова из двух пробелов,
требует только десять циклов. Однако, ввиду того что поле NAMEFLD
определено как DB (байтовое), необходимо изменить длину в команде
пересылки, посредством операнда WORD, a также воспользоваться операндом
PTR (указатель), как показано ниже:
MOV CX,10 ;Установить 10 циклов
LEA SI,NAMEFLD ;Начальный адрес
B30:
MOV WORD PTR[SI],2020H ;Переслать два пробела
INC SI ;Получить адрес
INC SI ; следующего слова
LOOP B30 ;10 циклов
Команда MOV по метке B30 обозначает пересылку слова из двух пробелов
по адресу, находящемуся в регистре SI. В последнем примеpе используется
команда LEA для инициализации регистра SI и несколько иной способ в
команде MOV по метке В30, так как нельзя закодировать, например, следующую
команду:
MOV WORD PTR[NAMEFLD],2020H ;Неправильно
Очистка входной области решает проблему ввода коротких имен, за
которыми следуют предыдущие данные. Еще более эффективный cпособ
предполагает очистку только тех байт, которые расположены после введенного
имени.
ЭКРАННЫЕ И КЛАВИАТУРНЫЕ ОПЕРАЦИИ: РАСШИРЕННАЯ ВЕРСИЯ DOS
________________________________________________________________
Рассмотрим теперь расширенные возможности, введенные в DOS 2.0
(реализованные в стиле операционной системы UNIX). Если вы используете
более младшую версию DOS, то не сможете выполнить примеры из данного
раздела. Расширенные возможности включают файловый номер (file handle),
который yстанавливается в регистре BX, когда требуется выполнить операцию
ввода/вывода. Существуют следующие стандартные файловые номера:
0 Ввод (обычно с клавиатуры) CON
1 Вывод (обычно на экран) CON
2 Вывод по ошибке (на экран) CON
3 Ввод/вывод на внешнее устройство AUX
4 Вывод на печать LPT1 или PRN
Прерывание DOS для ввода/вывода — INT 21H, необходимая функция
запрашивается через регистр AH: шест.3F — для ввода, шест.40 — для вывода.
В регистр CX заносится число байт для ввода/вывода, а в регистр DX — адрес
области ввода/вывода.
В результате успешного выполнения операции ввода/вывода очищается
флаг переноса (CF) и в регистр AX устанавливается действительное число
байт, участвующих в операции. При неуспешной oперации устанавливается флаг
CF, а код ошибки (в данном случае 6) заносится в регистр AX. Поскольку
регистр AX может содержать как длину данных, так и код ошибки, то
единственный способ определить наличие ошибки — проверить флаг CF, хотя
ошибки чтения с клавиатуры и вывода на экран — явления крайне редкие.
Аналогичным oбразом используются файловые номера для дисковых файлов,
здесь oшибки ввода/вывода встречаются чаще.
Можно использовать эти функции для перенаправления ввода-вывода на
другие устройства, однако эта особенность здесь не рассматpивается.
ВЫВОД НА ЭКРАН: РАСШИРЕННАЯ ВЕРСИЯ DOS
________________________________________________________________
Следующие команды иллюстрируют операцию вывода на экран в расширенной
версии DOS:
DISAREA DB 20 DUP(‘ ‘) ;Область данных
…
MOV AH,40H ;Запрос на вывод
MOV BX,01 ;Выводное устройство
MOV CX,20 ;Максимальное число байт
LEA DX,DISAREA ;Адрес области данных
INT 21H ;Вызов DOS
Команда LEA загружает в регистр DX адрес DISAREA для возможности DOS
локализовать информацию, предназначенную для вывода. В результате успешной
операции флаг переноса очищается (это можно проверить), а в регистре AX
устанавливается число выведенных символов. Ошибка в данной операции может
произойти, если yстановлен неправильный файловый номер. В этом случае
будет установлен флаг CF и код ошибки (в данном случае 6) в регистре AX.
Поскольку регистр AX может содержать или длину, или код ошибки, то
единственный способ определить состояние ошибки — проверить флаг CF.
Упражнение: Вывод на экран
—————————-
Воспользуемся отладчиком DEBUG для проверки внутренних эффектов
прерывания. Загрузите DEBUG и после вывода на экран приглашения введите A
100 для ввода ассемблерных команд (не машинных команд) по адpесу 100. Не
забудьте, что DEBUG предполагает, что все числа вводятся в
шестнадцатиричном формате:
100 MOV AH,40
102 MOV BX,01
105 MOV CX,хх (введите длину вашего имени)
108 MOV DX,10E
10B INT 21
10D RET
10E DB ‘Ваше имя’
Программа устанавливает в регистре AH запрос на вывод и устанавливает
шест. значение 10F в регистре DX — адрес DB, содержащей ваше имя в конце
программы.
Когда вы наберете все команды, нажмите еще раз Return. С помощью
команды U (U 100,10D) дисассемблируйте программу для проверки. Затем
используйте команды R и T для трассировки выполнения. При выполнении
команды INT 21H отладчик перейдет в BIOS, поэтому при достижении адреса
10B введите команду GO (G 10D) для перехода к команде RET. Ваше имя будет
выведено на экран. С помощью команды Q вернитесь в DOS.
ВВОД С КЛАВИАТУРЫ: РАСШИРЕННЫЙ DOS
________________________________________________________________
Ниже приведены команды, иллюстрирующие использование функции ввода с
клавиатуры в расширенной версии DOS:
INAREA DB 20 DUP (‘ ‘) ;Область ввода
MOV AH,3FH ;Запрос на ввод
MOV BX,00 ;Номер для клавиатуры
MOV CX,20 ;Максимум байт для ввода
LEA DX,INAREA ;Адрес области ввода
INT 21H ;Вызов DOS
Команда LEA загружает относительный адрес INAREA в регистр DX.
Команда INT ожидает, пока пользователь не введет cимволы с клавиатуры, но
не проверяет превышает ли число введенных символов максимальное значение в
регистре CX (20 в приведенном примере). Нажатие клавиши Return (код шест.
0D) указывает на завершение ввода. Например, после ввода текста «PC Users
Group» INAREA будет содержать:
PC Users Group, шест.0D, шест.0A
После введенного текста непосредственно следует символ возврата
каретки (шест.0D), который был введен, и символ конца строки (шест.0A),
который не был введен. В силу данной особенности максимальное число
символов и размер области ввода должны предусматpивать место для двух
символов. Если будет введено cимволов меньше максимального значения, то
область памяти за введенными символами сохранит прежнее значение.
В результате успешной операции будет очищен флаг CF (что можно
проверить) и в регистре AX будет установлено число байт, введенных с
клавиатуры. В предыдущем примере это число будет равно 14 плюс 2 для
перевода каретки и конца строки, т.е. 16. Соответствующим образом
программа может определить действительное число введенных символов. Хотя
данное свойство весьма тривиально для ответов типа YES или NO, оно может
быть полезно для ответов с пеpеменной длиной, таких, например, как имена.
Ошибка ввода может возникнуть, если определен неправильный номер
файла. В этом случае будет установлен флаг CF и в регистр AX будет помещен
код ошибки (6 в данном случае). Так как регистр AX может содержать или
длину введенных данных, или код ошибки, то единственный способ определения
наличия ошибки — проверка флага CF.
Если вводить текст, который превышает максимальную длину,
yстановленную в регистре CX, то будут приниматься все символы. Рассмотрим
ситуацию, когда регистр CX содержит 08,а пользователь введет символы «PC
Exchange». В результате первые восемь символов «PC Excha» попадут в
область ввода без кодов возврата каретки и конца строки. В регистре AX
будет установлена длина 08. Следующая команда INT будет принимать данные
не с клавиатуры, а из собственного буфера, поскольку там еще остались
предыдущие данные. Таким образом, в область ввода будут приняты символы
«ngе», символ перевода каретки и символ новой строки, в регистре AX будет
установлено значение 05. Обе операции ввода являются вполне нормальными и
флаг CF будет очищен.
Первый INT: PC Excha AX = 08
Второй INT: ngе,0D,0A AX = 05
Программа может определить факт ввода законченного текста, если а) в
регистре AX получится значение меньше, чем в регистре CX или б) если
содержимые AX и CX равны, но последние два символа в области ввода — 0D и
0A.
Встроенные в DOS проверки по функции 0AH для ввода с клавиатуры имеют
более мощные средства. Их выбор для использования в программах является
предпочтительным.
Упражнение: Ввод данных
————————-
Выполним упражнение в котором можно проследить операцию ввода c
клавиатуры с помощью отладчика DEBUG. Предполагаемая программа позволяет
вводить до 12 символов, включая символы конца каретки и конца строки.
Загрузите DEBUG и после вывода на экран приглашения введите A 100 для
ввода ассемблерных команд, начиная c адреса 100. Не забудьте, что DEBUG
предполагает, что все числа вводятся в шестнадцатиричном формате.
100 MOV AH,3F
102 MOV BX,00
105 MOV CX,0C
108 MOV DX,10F
10B INT 21
10D JMP 100
10F DB ‘ ‘
Программа устанавливает регистры AH и BX для запроса на ввод c
клавиатуры, заносит максимальную длину ввода в регистр CX и загружает в
регистр DX значение 10F — область DB в конце программы. В эту область
будут помещаться вводимые символы.
Когда вы наберете все команды, нажмите еще раз Return. С помощью
команды U 100,108 выполните дисассемблирование программы для проверки.
Затем используйте команды R и T для трассировки четырех команд MOV.
Остановившись по адресу 10B, введите G 10D для выполнения команды INT
(входить в BIOS не следует). Теперь отладчик позволит ввести данные,
завершаемые клавишей Return. Проверьте содержимое регистра AX, состояние
флага CF и используя команду D 10F, просмотрите введенные данные в памяти.
Для завершения работы введите команду Q.
ИСПОЛЬЗОВАНИЕ СИМВОЛОВ ВОЗВРАТА КАРЕТКИ,
КОНЦА СТРОКИ И ТАБУЛЯЦИИ ДЛЯ ВЫВОДА НА ЭКРАН
________________________________________________________________
Один из способов получения более эффективного выводе на экран —
использование управляющих символов возврата каретки, перевода строки и
табуляции:
Десятичные ASCII Шестнадцатиричные
CR 13 0DH
LF 10 0AH
TAB 09 09H
Эти символы при операциях ввода-вывода выполняют одинаковые действия
как в базовой, так и в расширенной версиях DOS. Например:
MESSAGE DB 09,’PC Users Group Annual Report’,13,10
MOV AH,40H ;Запрос на вывод
MOV BX,01 ;Номер файла
MOV CX,31 ;Длина текста
LEA DX,MESSAGE ;Адрес текста
INT 21H ;Вызов DOS
Использование директивы EQU для определения кодов делает программу
более понятной:
CR EQU 13 ;или EQU 0DH
LF EQU 10 ;или EQU 0AH
TAB EQU 09 ;или EQU 09H
MESSAGE DB TAB, ‘PC Users Group Annual’ DB ‘Report’, CR, LF
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
________________________________________________________________
— Команда INT 10Н передает управление в BIOS для ввода с клавиатуры
или вывода на экран. Команда INT 21H передает управление в DOS для
выполнения некоторых более сложных действий при операциях ввода-вывода.
— Будьте внимательны при использовании шестнадцатиричной нотации,
например INT 21 и INT 21H — это не одно и то же.
— Будьте внимательны при установке значений в регистры AХ, BX, CX и
DX для операций ввода-вывода.
— При использовании INT 21H в базовой версии DOS устанавливайте
символ-ограничитель ($) непосредственно в конце области вывода. Будьте
осторожны при очистке области — не удалите символ-ограничитель. Отсутствие
ограничителя может привести к непредвиденным эффектам на экране.
— Для ввода в базовой версии DOS тщательно определяйте список
параметров. Экранные функции INT 21H предполагают, что первый байт
содержит максимальную длину ввода, а второй байт заполняется системой
автоматически значением действительной длины введенных данных.
— Для вывода на экран под управлением расширенной версии DOS
устанавливайте в регистре AН значение 40Н, а в регистре BX — файловый
номер 01.
— Для ввода с клавиатуры под управлением расширенной версии DOS
устанавливайте в регистре АН значение функции 3FH, а в регистре BX —
файловый номер 00. Введенные в область ввода данные завершаются символами
возврат каретки и перевод строки. Данная операция не контролирует ввод,
превышающий по длине максимальное значение.
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
________________________________________________________________
8.1. Какие шестнадцатиричные значения строки и столбца соответствуют
нижнему правому углу экрана 25х40?
8.2. Напишите команды для установки курсора по координатам: строка
12, столбец 8.
8.3. Напишите команды для очистки экрана, начиная с 0-го столбца 12-й
строки до 79-го столбца 22-й строки.
8.4. Составьте необходимые элементы данных и команды для вывода
запроса ‘Введите дату (дд/мм/гг)’. За сообщением должен следовать звуковой
сигнал. Используйте для вывода: а) функцию базовой версии DOS, б) функцию
расширенной версии DOS и файловый номер.
8.5. Составьте необходимые элементы данных и команды для ввода с
клавиатуры в формате вопроса 8.4. Используйте для ввода: а) функцию
базовой версии DOS, б) функцию расширенной версии DOS и файловый номер.
8.6. Укажите стандартные файловые номера для ввода с клавиатуры,
обычного вывода на экран и вывода на принтер.
8.7. Введите в компьютер программу из рис.8.2 со следующими
изменениями, ассемблируйте ее, выполните компоновку и проверку работы: а)
вместо строки 12 середина строки 15; б) вместо очистки всего экрана
очистка только строк от 0 до 15.
8.8. Измените программу из рис.8.2 для использования ее в расширенной
версии DOS. Выполните ее ассемблирование, компоновку и проверку работы.
Прерывания в защищённом режиме. Глава 6. Установка IDT в программе.
Smart ASM: Прерывания в защищённом режиме. Глава 6. Установка IDT в программе.Прерывания в защищённом режиме:
Глава 6. Установка IDT в программе.
Как уже говорилось в разделе «защищённый режим», воспользоваться прерываниями BIOS и DOS программа, работающая в P-Mode, не может. Это связано с тем, что вектора от 00h до 1Fh заняты исключениями либо зарезервированы для них, следовательно, прерывания, отображённые на эти вектора, предоставляют доступ не к ресурсам BIOS-а, а к обработчикам прерывания. Например, команда INT 10h в режиме реальных адресов обеспечивает доступ к сервису управления видеоадаптером, а в защищённом режиме — к обработчику исключения плавающей точки x87 FPU.
Итак, для того, чтобы определить прерывания в защищённом режиме, нужно выполнить следующие действия:
1. | Перенаправить аппаратные прерывания (IRQ) |
2. | Создать дескрипторы для всех используемых векторов (исключений, аппаратных и программных прерываний). |
3. | Подготовить образ IDTR и загрузить его в регистр IDTR. |
4. | Разрешить прерывания |
Действие 1 были рассмотрены в предыдущей главе, действие 3 — см. в исходнике — оно совмещено с построением GDT; в этой главе будет обсуждаться только 2-е.
Некоторые процедуры, из-за своей громоздкости, здесь будут приведены не полностью — будет показан только принцип их построения. В конце главы вы сможете найти ссылку на архив (7Кб) с файлами исходника, библиотеки и самой программы.
Теперь для каждого примера будет своя библиотека, т.к. макросы, определяющие обработчики прерываний, можно будет менять и дополнять в пределах изучаемой темы и отдельная библиотека для каждого примера позволит избежать путаницы и лишней работы по редактированию макросов.
Создаём дескрипторы для всех используемых векторов прерываний.
Для всех исключений и прерываний создадим дескрипторы шлюзов прерываний и ловушек; шлюзы задач будут рассматриваться отдельно в разделе «Мультизадачность».
Шлюзы прерываний и ловушек содержат точку входа (сегмент:смещение) и права доступа обработчика. В следующем ниже примере функцию самих обработчиков будут выполнять заглушки, определённые соответствующими макросами; функциональная реализация обработчиков исключений и аппаратных прерываний будет описана в дальнейших главах.
Для установки дескрипторов прерываний давайте определим три следующих функции. Базовая функция set_IDT_descriptor устанавливает дескриптор с правами доступа в CX. Шлюзы прерывания и ловушки отличаются всего лишь одним битом в байте прав доступа (бит D в дескрипторе шлюза ловушки равен 0, т.к. стек, используемый обработчиком ловушек в нашем примере — 16-разрядный).
init_set_IDT_descriptor macro set_IDT_descriptor proc near ; Установка IDT-дескриптора. ; DS:BX = дескриптор в IDT ; DX = селектор сегмента кода обработчика ; EAX = смещение в сегменте кода ; CX = access_rights (права доступа) push eax push ecx push cx mov cx,dx shl ecx,16 mov cx,ax ; ECX = dw Селектор & dw offset_low mov [ bx ],ecx pop ax mov [ bx + 4 ],eax ; EAX = dw offset_hi & db access_rights & db 0 add bx,8 pop ecx pop eax ret endp endm
init_set_int_IDT_descriptor macro set_int_IDT_descriptor proc near ; Установка IDT-дескриптора прерывания. ; DS:BX = дескриптор в IDT ; DX = селектор сегмента кода обработчика ; EAX = смещение в сегменте кода push cx mov cx,8600h ; Права доступа шлюза прерывания call set_IDT_descriptor pop cx ret endp endm
init_set_trap_IDT_descriptor macro set_trap_IDT_descriptor proc near ; Установка IDT-дескриптора ловушки. ; DS:BX = дескриптор в IDT ; DX = селектор сегмента кода обработчика ; EAX = смещение в сегменте кода push cx mov cx,8700h ; Права доступа шлюза ловушки с D=0 call set_IDT_descriptor pop cx ret endp endm
Обработчики прерываний определены следующим образом (здесь приводится неполный макрос, полностью — см. в конце главы, в архиве):
init_handlers macro ; Обработчики исключений ex_00_entry_point: exeption_00_handler ex_01_entry_point: exeption_01_handler ... ex_1f_entry_point: exeption_1f_handler ; Обработчики аппаратных прерываний IRQ_0_entry_point: IRQ_0_handler IRQ_1_entry_point: IRQ_1_handler ... IRQ_f_entry_point: IRQ_f_handler ; Обработчики программных прерываний Int_30_entry_point: Int_30_handler Int_31_entry_point: Int_31_handler endm
Сами макросы exeption_xx_handler, IRQ_x_handler и Int_3x_handler определяются следующим образом:
и т.д.
exeption_00_handler macro ex_00_start: jmp ex_00_start endm
exeption_01_handler macro ex_01_start: jmp ex_01_start endm
IRQ_1_handler macro IRQ_1_start: jmp IRQ_1_start endm
IRQ_2_handler macro IRQ_2_start: jmp IRQ_2_start endm
и т.д.
Int_30_handler macro iret endm
Int_31_handler macro iret endm
Такое определение макросов позволяет легко менять обработчики — просто заменить соответствующий макрос, не меняя при этом исходника.
Теперь определение IDT. Оно производится функцией setup_IDT, имеющей вид:
init_setup_IDT macro setup_IDT proc near lea bx,IDT mov dx,Code_selector ; Обработчики все исключений и ; прерываний в данном примере ; находятся в одном сегменте кода. lea eax,ex_00_entry_point call set_int_IDT_descriptor lea eax,ex_01_entry_point call set_trap_IDT_descriptor ; Ловушка lea eax,ex_02_entry_point call set_int_IDT_descriptor lea eax,ex_03_entry_point call set_trap_IDT_descriptor ; Ловушка lea eax,ex_04_entry_point call set_trap_IDT_descriptor ; Ловушка lea eax,ex_05_entry_point call set_int_IDT_descriptor ... lea eax,ex_1f_entry_point call set_int_IDT_descriptor lea eax,IRQ_0_entry_point call set_int_IDT_descriptor lea eax,IRQ_1_entry_point call set_int_IDT_descriptor ... lea eax,IRQ_f_entry_point call set_int_IDT_descriptor lea eax,Int_30_entry_point call set_int_IDT_descriptor lea eax,Int_31_entry_point call set_int_IDT_descriptor ret endp endm
Вот и все основные функции, необходимые для правильной работы системы прерываний в защищённом режиме. Для того, чтобы установить или обновить обработчик прерывания или исключения, нужно всего лишь изменить соответствующий макрос вида …_handler, все остальные функции при компиляции правильно построят IDT и обеспечат корректную работу системы.
Обратите внимание, что все обработчики исключений и аппаратных прерываний представляют собой простое зацикливание — это и есть простейший пример реализации заглушек. Эти заглушки необходимы на начальной стадии построения операционной системы, когда вы ещё не решили, как будут обрабатываться исключения и прерывания, но работать они должны.
В главе 7 будут показаны примеры заглушек для исключений, которые будут выдавать информацию о самих исключениях.
В этом примере определена IDT из 32h (т.е. 50) дескрипторов. Для примера — этого вполне хватает, для других программ — может не хватить, но главное, чтобы вы знали о возможности увеличить/уменьшить IDT простой заменой значения макроса idt_descr_n.
Для программных прерываний в примере определено всего 2 дескриптора — просто чтобы было понятно, как их определять. На самом деле, операционная система защищённого режима не нуждается в программных прерываниях — её сервис удобней предоставлять в виде вызовов соответствующих процедур или задач, к тому же, в защищённом режиме прерывание обрабатывается довольно-таки долго, по сравнению с дальним вызовом.
Сам пример рабочей программы и библиотеки вы можете скачать здесь: pmode_4.lib, examp_4.asm и examp_4.com в архиве examp_4.zip (7230 байт).
Copyright © Александр Семенко. |
Python на Assembler (Tasm) — Codeforces
Сегодня напишем в текстовом режиме с использованием прерываний BIOS и DOS змейку на Assembler. Для этого нужно знать основы, уметь ассемблировать (Tasm) и компоновать (Tlink) код.
Для начала напишем основу — змейку, которая перемещается в одном направлении по игровому полю. Змейка будет состоять из символа «*», координаты каждого символа хранятся в памяти.
model small
.data ;Сегмент данных. Храним координаты тела змейки
snake dw 0000h
dw 0001h
dw 0002h
dw 0003h
dw 0004h
dw 7CCh dup('?')
.stack 100h
.code
;В начале сегмента кода будем размещать процедуры
delay proc
push cx
mov ah,0
int 1Ah
add dx,3
mov bx,dx
repeat:
int 1Ah
cmp dx,bx
jl repeat
pop cx
ret
delay endp
start:
mov ax,@data
mov ds,ax
mov es,ax
mov ax,0003h
int 10h ;Очищаем игровое поле
mov cx,5
mov ax,0A2Ah
int 10h ;Выводим змейку из 5 символов "*"
mov si,8 ;Индекс координаты символа головы
xor di,di ;Индекс координаты символа хвоста
mov cx,0001h ;Регистр cx используем для управления головой. При сложении от значения cx будет изменяться координата x или y
main: ;Основной цикл
call delay
xor bh,bh
mov ax,[snake+si] ;Берем координату головы из памяти
add ax,cx ;Изменяем координату x
inc si
inc si
mov [snake+si],ax ;Заносим в память новую координату головы змеи
mov dx,ax
mov ax,0200h
int 10h ;Вызываем прерывание. Перемещаем курсор
mov ah,02h
mov dl,002Ah
int 21h ;Прерывание выводит символ '*'
mov ax,0200h
mov dx,[snake+di]
int 10h
mov ax,0200h
mov dl,0020h
int 21h ;Выводим пробел, тем самым удаляя хвост
inc di
inc di
jmp main
end start
Добавим процедуру «key_press» обработки нажатия клавиши и присваивания значения регистру CX, отвечающему за направление головы.
Управление стрелками.
key_press
key_press proc
mov ax, 0100h
int 16h
jz en ;Без нажатия выходим
xor ah, ah
int 16h
cmp ah, 50h
jne up
cmp cx,0FF00h ;Сравниваем чтобы не пойти на себя
je en
mov cx,0100h
jmp en
up: cmp ah,48h
jne left
cmp cx,0100h
je en
mov cx,0FF00h
jmp en
left: cmp ah,4Bh
jne right
cmp cx,0001h
je en
mov cx,0FFFFh
jmp en
right: cmp cx,0FFFFh
je en
mov cx,0001h
en:
ret
key_press endp
Вызовем её сразу после вызова процедуры delay:
main:
call delay
call key_press
Накормим змейку, создаём процедуру «add_food». Эта процедура будет на игровом поле размещать еду, символы «$». В качестве случайных чисел будем брать время.
add_food
add_food proc
sc:
inc bl ;В регистре BL рандомное число
cmp bx,50h ;Проверяем границу числа
jng ex
shr bl,1 ;Если больше, делим на 2 логическим сдвигом
jmp sc
ex:
mov dl,bl ;Запись координаты
sc2:
cmp bx,19h
jng ex2
shr bl,2
jmp sc2
ex2:
mov dh,bl ;Запись координаты
mov ax,0200h
int 10h
mov ax,0800h
int 10h
cmp al,2Ah ;Проверяем пустое ли место
je sc
cmp al,40h
je sc ;Если нет повторяем
mov ax,0200h
mov dl,0024h
int 21h
ret
add_food endp
Вызовем 1 раз в начале.
mov bl,51h
call add_food
main:
Делаем проверку, съела змея еду или нет. Если съела, вызываем процедуру «add_food» и не удаляем хвост.
Проверку добавляем в код перед выводом символа головы:
mov ah,02h
int 10h ;Вызываем прерывание. Перемещаем курсор
mov ax,0800h
int 10h ;Читает символ
mov dh,al
mov ah,02h
mov dl,002Ah
int 21h ;Прерывание выводит символ '*'
cmp dh,24h
jne next
call add_food
jmp main
next:
Усложним игру. После того, как питон съест 5 символов, в хвосте будет появляться символ «@». Пишем счетчик и вывод символа:
shit
;В сегмент данных добавим строчку
.data
tick dw 0 ;Счетчик
--------------------------------------------------------------------
cmp dh,24h
jne next
push cx ;В стек регистр
mov cx,[tick]
inc cx
cmp cx,5
jne exl
xor cx,cx
mov ax,0200h
mov dx,[snake+di-2]
int 10h
mov ax,0200h
mov dl,0040h
int 21h
exl:mov [tick],cx
pop cx
call add_food
jmp main
next:
Какая игра без Game Over. Пишем процедуру проверки границы поля, а также врезание в себя и символ «@».
game_over
game_over proc
;Проверяем границы
cmp dl,50h
je exit
cmp dl,0
jl exit
cmp dh,0
jl exit
cmp dh,19h
je exit
;Проверяем символы
cmp al,2Ah
je exit
cmp al,40h
je exit
jmp good
exit:
mov ax,4c00h
int 21h
good:
ret
game_over endp
Вызываем её после считывания символа:
mov ax,0800h
int 10h ;Считываем символ
call game_over
mov dh,al
Немного магии добавляем после инкремента индексов.
magic
inc si
inc si
cmp si,7CAh
jne nex
xor si,si
nex:
---------------------------------------------------------------------
inc di
inc di
cmp di,7CCh
jne main
xor di,di
Ну вот и всё, также можно добавить меню с выбором уровня, паузу, заставку Game Over, счет очков.
По ссылке архив с исходным кодом, exe’шником и DosBox для тех, у кого не запустится.
Good Luck!!!
Вывод на экран в текстовом режиме средствами BIOS
Данная работа является продолжением лабораторной работы «Вывод на экран в текстовом режиме средствами MS-DOS». Как отмечалось ранее функции MS-DOS вывода на экран позволяют перенаправлять вывод в файл, но не позволяют вывести текст в любую позицию экрана и не позволяют изменить цвет текста.
BIOS
Для реализации данных возможностей программа должна использовать видеофункции BIOS. BIOS (Basic Input/Output System — базовая система ввода-вывода) — это набор программ, расположенных в постоянной памяти компьютера, которые выполняют его загрузку сразу после включения и обеспечивают доступ к некоторым устройствам, в частности к видеоадаптеру.
Все функции видеосервиса BIOS вызываются через прерывание 10h. Рассмотрим функции, которые могут быть полезны для вывода текстов на экран.
Выбор видеорежима. BIOS предоставляет возможность переключения экрана в различные текстовые и графические режимы. Режимы отличаются друг от друга разрешением (для графических) и количеством строк и столбцов (для текстовых), а также количеством возможных цветов.
АН = 00 — Установить видеорежим
Ввод: AL = номер режима в младших 7 битах
Вызов этой функции приводит к тому, что экран переводится в выбранный режим. Если старший бит AL установлен в 0, то экран не очищается. Номера текстовых режимов — 0, 1, 2, 3 и 7. Режимы отличаются между собой количеством строк и столбцов, а также количеством видеостраниц. Отметим, что данная функция позволяет переводить и в графические режимы. Но работу в графических режимах рассмотрим позднее. По умолчанию стоит 3-й текстовый режим.
Установить положение курсора
Ввод: АН = 02
ВН = номер страницы
DH = строка
DL = столбец
С помощью этой функции можно установить курсор в любую позицию экрана, и дальнейший вывод текста будет происходить из этой позиции. Отсчет номера строки и столбца ведется от верхнего левого угла экрана (символ в левой верхней позиции имеет координаты 0, 0). Номера страниц 0 – 3 (для режимов 2 и 3)и 0 – 7 (для режимов 1 и 2) соответствуют области памяти, содержимое которой в данный момент отображается на экране. Можно вывести текст в неактивную в настоящий момент страницу, а затем переключиться на нее, чтобы изображение изменилось мгновенно.
Считать положение и размер курсора
Ввод: АН = 03
ВН = номер страницы
Вывод: DH, DL = строка и столбец текущей позиции курсора
СН, CL = первая и последняя строки курсора
Возвращает текущее состояние курсора на выбранной странице (каждая страница использует собственный независимый курсор).
Вывод символов на экранКаждый символ на экране описывается двумя байтами — ASCII-кодом символа и байтом атрибута, указывающим цвет символа и фона, а также является ли символ мигающим.
Каждый бит атрибута символа имеет свое назначение:
Бит 7: символ мигает или фон яркого цвета в зависимости от настроек видеофункции.
Биты 6 – 4 задают цвет фона.
Бит 3: символ яркого цвета или фон мигает в зависимости от настроек видеофункции.
Биты 2 – 0 задают цвет символа.
Цвета кодируются следующим способом (первое значение для обычного цвета, второе — для яркого):
- 000b — черный (темно-серый),
- 001b — синий (светло-синий),
- 010b — зеленый (светло-зеленый),
- 011b — голубой (светло-голубой),
- 100b — красный (светло-красный),
- 101b — пурпурный (светло-пурпурный),
- 110b — коричневый (желтый),
- 111b — светло-серый (белый).
Обратите внимание на то, что цвета соответствуют шкале RGB.
Считать символ и атрибут символа в текущей позиции курсора
Ввод: АН = 08
ВН = номер страницы
Вывод: АН = атрибут символа
AL = ASCII-код символа.
Вывести символ с заданным атрибутом на экран
Ввод: АН = 09
ВН = номер страницы
AL = ASCII-код символа
BL = атрибут символа
СХ = число повторений символа.
С помощью этой функции можно вывести на экран любой символ, включая даже символы CR и LF, которые обычно интерпретируются как конец строки. В графических режимах СХ не должен превышать число позиций, оставшееся до правого края экрана.
Вывести символ с текущим атрибутом на экран, т.е. с атрибутом символа, находящегося ранее в этой позиции.
Ввод: АН = 0Ah
ВН = номер страницы
AL = ASCII-код символа
СХ = число повторений символа.
Вывести символ в режиме телетайпа
Ввод: АН = 0Eh
ВН = номер страницы
AL = ASCII-код символа
Вывести строку символов с заданными атрибутами
Ввод: АН = 13h
AL = режим вывода:
бит 0 — переместить курсор в конец строки после вывода
бит 1 — строка содержит не только символы, но также и атрибуты, так что каждый символ описывается двумя байтами: ASCII-код и атрибут
биты 2 – 7 зарезервированы
СХ = длина строки (только число символов)
BL = атрибут, если строка содержит только символы
DH,DL = строка и столбец, начиная с которых будет выводиться строки
ES:BP = адрес начала строки в памяти
Задания
Задание. 4.1. Создайте com-файл (или файлы), в котором должны использоваться все указанные функции.
Задание. 4.2. Нарисуйте «разноцветную рожицу» — глаза в виде ноликов, рот из тире и т.д.
Задание. 4.3. Используя функции BIOS выведите все 256 символов таблицы ASCII по 16 символов в каждой строке.
Для этого используйте следующий код, ориентированный на NASM:
org 100h ; Начало СОМ-файла start: mov ax,0003h int 10h ; Видеорежим 3 (очистка экрана ; и установка курсора в 0, 0) mov dx,0 ; DH и DL будут использоваться ; для хранения положения курсора. ; Начальное положение - 0,0 mov si,256 ; SI будет счетчиком цикла mov al,0 ; Первый символ - с кодом 00h mov ah,9 ; Номер видеофункции "вывод символа с атрибутом" mov cx,1 ; Выводится один символ за раз mov bl,00011111b ;атрибут символа - белый на синем cloop: int 10h ; Вывести символ на экран push ax ; Сохранить текущий символ и номер функции mov ah,2 ; Номер видеофункции 2 - ; изменить положение курсора inc dl ; Увеличить текущий столбец на 1 int 10h ; Переместить курсор mov ax,0920h ; АН = 09, AL = 20h (ASCII-код пробела) int 10h ; Вывести пробел mov ah,2 ; Номер видеофункции 2 inc dl ; Увеличить столбец на 1 int 10h ; Переместить курсор pop ax ; Восстановить номер функции в ah ; и текущий символ в al inc al ; Увеличить AL на 1 - следующий символ test al,0Fh ; Если AL не кратен 16, jnz continue_loop ; продолжить цикл, push ax ; иначе - сохранить номер функции ; и текущий символ mov ah,2 ; Номер видеофункции 2 inc dh ; Увеличить номер строки на 1 mov dl,0 ; Столбец = 0 int 10h ; Установить курсор на начало следующей строки pop ax ; Восстановить номер видеофункции ; и текущий символ continue_loop: dec si ; Уменьшить SI на 1, ; если он не стал нулем - продолжить jnz cloop ; CX используется внутри цикла, ; так что нельзя использовать команду LOOP ; для его организации ret ; Завершение СОМ-файла end start
Обратим внимание на то, что управляющие символы тоже выведены.
Задание. 4.4. Модифицируйте программу так, чтобы она выдавала русские буквы красным цветом, а цифры — зеленым.
При подготовке материала использована книга С.В.Зубкова «Assembler. Язык неограниченных возможностей».
Лабораторные задания по архитектуре ЭВМ
Связанные статьи
Сборка— что означают аргументы для Int 10h, AH 6h / 7h?
Взгляните на эту потрясающую психоделическую картину красного прямоугольного окна, нарисованного в старом текстовом режиме:
Каждый бело-синий квадрат представляет собой символьную ячейку. Ячейки встречные вверху справа и сверху вниз .
Цифры сверху, читаемые сверху вниз, дают расстояние ячейки от левого края 1 .
Цифры слева показывают расстояние ячейки от верхнего края.
Пара (расстояние слева, расстояние сверху) , уникальная для каждой ячейки 2 , называется парой координат или просто координатами (или даже координатами ).
Принято называть расстояние слева как X , расстояние от вершины как Y и все, что связано с шириной, как something-X и все, что связано с высотой, как something-Y .
Большой красный прямоугольник — это окно 3 .
Окна имеют два измерения и положение. Таким образом, окно может быть идентифицировано тройкой (координаты положения верхнего левого угла, размер-X, размер-Y) .
Например, красное окно можно описать как ((30, 8), 22, 7) , поскольку оно начинается с (30, 8) , его ширина 22 ячейки, а высота 7 ячеек.
Другой способ описать окно — это координаты левого верхнего угла и координаты правого нижнего угла.
В этом случае красное окно — это ((30, 8), (51, 14)) .
Служба int 10h / AH = 06h
может использоваться для перемещения содержимого внутри красного окна вверх.
Нам нужно указать ему, куда нужно переместить окно, и, поскольку оно использует вторую нотацию, мы это делаем.
CL
и CH
образуют пару, удерживающую верхние левые координаты, X в CL , Y в CH .
DL
и DH
образуют пару, удерживающую нижние правые координаты, X в DL , Y в DH .
Этот код правильно загружает регистры (эквивалент обеих версий)
; Простая версия; Обычная версия
mov cl, 30 mov cx, 081eh
mov ch, 8 mov dx, 0e34h
mov dl, 52
mov dh, 14
Остальные входные данные служебных программ тривиальны, но для BH
, который на данный момент мы установили в ноль.
Позвоните в службу поддержки:
mov ax, 0603h; Прокрутить на три строки вверх
xor bh, bh
mov cx, 081eh
mov dx, 0e34h
int 10h
Результат:
Мы видим, что содержимое внутри окна было прокручено вверх на три строки.
Ничего не трогали за окном.
Отметим также, что «сдвинутые» снизу линии — это черные линии.
Здесь вступает в игру ввод BH
, он содержит атрибут (комбинацию цвета и цвета фона), используемый для рисования этих линий.
Например, атрибут 0e0h указывает ярко-желтый 4 , давайте использовать его.
mov ax, 0603h; Прокрутить на три строки вверх
mov bh, 0e0h; Желтые линии
mov cx, 081eh
mov dx, 0e34h
int 10h
Наконец, значение AL
может быть равно нулю для прокрутки всего окна вверх, то есть количества строк, равного высоте окна.
Для службы int 10h / AH = 07h
логика такая же, но окно прокручивается на вниз на .
1 В ячейках.
2 Обратите внимание, что ячейки, используемые для отображения числа, также имеют координаты.
3 Потому что это на самом деле похоже на окно.
4 Так как в этом контексте установлен бит высокой интенсивности.
Запись на экран [Protas]
Больше вывода в текстовом режиме
Я собираюсь рассмотреть еще несколько способов вывода текста в текстовых режимах. Эта первая программа является примером того, как переместить курсор, чтобы отобразить строку текста там, где вы хотите, чтобы она переместилась.
. Модель крошечный .код org 100h Начало: mov dh, 12; курсор col mov dl, 32; строка курсора mov ah, 02h; переместите курсор в нужное место xor bh, bh; страница видео 0 int 10h; позвонить в службу биос mov dx, OFFSET Text; DS: DX указывает на сообщение mov ah, 9; функция 9 - отображаемая строка int 21h; все службы дос mov ax, 4C00h; выход в dos int 21h Текстовая БД "Это какой-то текст $" конец начало
В следующем примере показано, как писать на экран, используя файловую функцию 40h прерывания 21h.
. Модель маленькая .куча .код mov ax, @ data; настроить DS как сегмент для данных mov ds, топор mov ах, 40ч; функция 40h - записать файл mov bx, 1; handle = 1 (экран) mov cx, 17; длина строки mov dx, OFFSET Text; DS: DX указывает на строку int 21h; позвонить в службу DOS mov ax, 4C00h; завершить программу int 21h .данные Текстовая БД "Это какой-то текст" конец
Следующая программа показывает, как настроить и вызвать функцию 13h прерывания 10h — запись строки. Это дает возможность написать строку в любом месте экрана заданным цветом, но это сложно настроить.
. Модель маленькая .куча .код mov ax, @ data; настроить DS как сегмент для данных mov es, ax; поместите это в es mov bp, OFFSET Text; ES: BP указывает на сообщение мов ах, 13ч; функция 13 - записать строку mov al, 01h; attrib в bl, переместить курсор xor bh, bh; страница видео 0 mov bl, 5; атрибут - пурпурный mov cx, 17; длина строки mov dh, 5; строка для вставки строки mov dl, 5; столбец для размещения строки int 10h; позвонить в службу BIOS mov ax, 4C00h; вернуться в DOS int 21h .данные Текстовая БД "Это какой-то текст" конец
Следующая программа демонстрирует, как писать на экран с помощью rep stosw, чтобы записать запись в видеопамять.
. Модель маленькая .куча .код mov ax, 0B800h; сегмент видеобуфера mov es, ax; поместите это в es xor di, di; clear di, ES: DI указывает на видеопамять mov ah, 4; атрибут - красный mov al, "G"; персонаж, чтобы поставить там mov cx, 4000; количество раз, чтобы положить это туда cld; направление - вперед rep stosw; выходной символ в ES: [DI] mov ax, 4C00h; вернуться в DOS int 21h конец
Следующая программа демонстрирует, как записать строку в видеопамять.
; записать строку прямо в видеопамять .модель маленькая .куча .код mov ax, @ data mov ds, топор mov ax, 0B800h; сегмент видеобуфера mov es, ax; поместите это в es mov ah, 3; атрибут - голубой mov cx, 17; длина строки для печати mov si, OFFSET Text; DX: SI указывает на строку xor di, di Wr_Char: lodsb; поместите следующий символ в al mov es: [di], al; вывод символа в видеопамять inc di; перейти к следующему столбцу mov es: [ди], ах; атрибут вывода в видеопамять inc di loop Wr_Char; цикл, пока не будет сделано mov ax, 4C00h; вернуться в DOS int 21h .данные Текстовая БД "Это какой-то текст" конец
Читателю предоставляется в качестве упражнения изменить его так, чтобы в видеопамять производилась только одна запись.
Режим 13ч
Режим 13h доступен только на картах VGA, MCGA и выше. Причина, по которой я говорю об этой карте, заключается в том, что ее очень легко использовать для графики из-за того, как устроена память.
Сначала проверьте, что режим 13h возможен
Было бы вежливо сообщить пользователю, если его компьютер не поддерживает режим 13h, вместо того, чтобы просто вывести его из строя без предупреждения.Вот как это делается.
. Модель маленькая .куча .данные NoSupport db «Режим 13h не поддерживается на этом компьютере». db, "Вам нужно видео MCGA или VGA" db, "карта / монитор. $" Поддерживаемая база данных "На этом компьютере поддерживается режим 13h. $" .код mov ax, @ data; настроить DS для указания на сегмент данных mov ds, ax; использовать топор call Check_Mode_13h; проверьте, возможен ли режим 13h jc Error; если cf = 1 есть ошибка mov ah, 9; функция 9 - отображаемая строка mov dx, OFFSET Поддерживается; DS: DX указывает на сообщение int 21h; позвонить в службу DOS jmp To_DOS; выход в DOS Ошибка: mov ah, 9; функция 9 - отображаемая строка mov dx, OFFSET NoSupport; DS: DX указывает на сообщение int 21h; позвонить в службу DOS To_DOS: mov ax, 4C00h; выход в DOS int 21h Check_Mode_13h PROC; Возврат: CF = 1 Режим 13h невозможен mov ax, 1A00h; Запросить информацию о видео для VGA int 10h; Получить код комбинации дисплея cmp al, 1Ah; Присутствует ли VGA или MCGA? je Mode_13h_OK; поддерживается режим 13h stc; режим 13h не поддерживается CF = 1 Mode_13h_OK: Ret Check_Mode_13h ENDP конец
Просто используйте это, чтобы проверить, поддерживается ли режим 13h в начале вашей программы, чтобы убедиться, что вы можете перейти в этот режим.
Настройка видеорежима
Установить режим очень просто. Вот как это делается.
mov ax, 13h; установить режим 13ч int 10h; позвонить в службу BIOS
Как только мы находимся в режиме 13h и закончили то, что мы делаем, нам нужно установить его в видеорежим, в котором он был ранее.
Это делается в два этапа. Сначала нам нужно сохранить режим видео, а затем сбросить его в этот режим.
VideoMode db? . . mov ah, 0Fh; функция 0Fh - получить текущий режим int 10h; Вызов видеосервиса Bios mov VideoMode, al; сохранить текущий режим ; программный код здесь mov al, VideoMode; установить предыдущий режим видео xor ах, ах; очистить ах - установить режим int 10h; позвонить в службу биос mov ax, 4C00h; выход в dos int 21h; вызов функции dos
Теперь, когда мы можем перейти в режим 13h, давайте что-нибудь сделаем.Во-первых, давайте разместим на экране несколько пикселей.
Функция 0Ch: Запись графического пикселя
При этом на экране появляется цветная точка с указанными графическими координатами.
Вход
Выход
Ничего, кроме пикселей на экране.
Примечание. Эта функция выполняет исключающее ИЛИ (XOR) с новым значением цвета, и устанавливается текущий контекст пикселя бита 7 AL.
Эта программа демонстрирует, как строить пиксели.Он должен отобразить четыре красных пикселя в центре экрана.
; пример построения пикселей в режиме 13 с использованием сервисов BIOS - ; ИНТ 10ч .model крошечный .код org 100h Начало: mov ax, 13; режим = 13ч int 10h; позвонить в службу биос mov ah, 0Ch; функция 0Ch mov al, 4; цвет 4 - красный mov cx, 160; x позиция = 160 mov dx, 100; y позиция = 100 int 10h; позвонить в службу BIOS inc dx; нанести пиксель вниз int 10h; позвонить в службу BIOS inc cx; построить пиксель вправо int 10h; позвонить в службу BIOS dec dx; построить пиксель вверх int 10h; позвонить в службу BIOS хор топор, топор; функция 00h - получить ключ int 16h; позвонить в службу BIOS mov ax, 3; mode = 3 int 10h; позвонить в службу BIOS mov ax, 4C00h; выход в DOS int 21h конец начало
Некоторые оптимизации
Этот метод не слишком быстрый, и мы могли бы сделать его намного быстрее.Как? Путем записи прямо в видеопамять. Делается это довольно легко.
Сегмент VGA — 0A000h
. Чтобы определить, куда идет каждый пиксель, вы используете эту простую формулу для получения смещения.
Смещение = X + (Y * 320)
Все, что мы делаем, это помещаем число в это место, и теперь на экране появляется пиксель. Цифра какого цвета. Есть две инструкции, которые мы можем использовать для размещения пикселя на экране, во-первых, мы могли бы использовать stosb, чтобы поместить значение из AL в ES: DI, или мы можем использовать новую форму инструкции MOV, например:
движений: [di], цвет
Что мы должны использовать? Когда мы собираемся записывать пиксели на экран, нам нужно делать это как можно быстрее.
Инструкция | Pentium | 486 | 386 | 286 | 86 |
---|---|---|---|---|---|
STOSB | 3 | 5 | 4 | 3 | 11 |
MOV AL to SEG: OFF | 1 | 1 | 4 | 3 | 10 |
Если вы используете метод MOV, вам может потребоваться увеличить DI (что делает STOSB).
Если бы у нас была программа, которая использовала спрайты, которые нужно было постоянно рисовать, стирать, а затем перерисовывать, у вас будут проблемы с мерцанием. Чтобы избежать этого, вы можете использовать «двойной буфер». Это еще одна часть памяти, в которую вы записываете, а затем копируете всю информацию на экран.
Этот веб-сайт использует файлы cookie для анализа посещаемости. Используя веб-сайт, вы соглашаетесь с хранением файлов cookie на вашем компьютере.OKПодробнее Программаотображает символы ascii на экране с помощью прерывания BIOS (INT 10H) — Учебник по языку ассемблера
.МОДЕЛЬ МАЛАЯ .КОД ORG 100H НАЧИНАТЬ: JMP КОРОТКАЯ ГЛАВНАЯ CTR DB 00 COL DB 24 РЯД DB 04 РЕЖИМ БД? ОСНОВНОЙ ПРОЦЕССОР РЯДОМ ЗВОНИТЕ B10MODE ПОЗВОНИТЬ C10CLR A20: ВЫЗОВ D10SET ПОЗВОНИТЬ E10DISP CMP CTR, 0FFH JE A30 INC CTR ДОБАВИТЬ COL, 02 CMP COL, 56 JNE A20 INC ROW MOV COL, 24 JMP A20 A30: ЗВОНИТЕ F10READ ПОЗВОНИТЬ G10MODE MOV AX, 4C00H ИНТ 21H ГЛАВНЫЙ КОНЕЦ B10MODE PROC РЯДОМ MOV AH, 0FH ИНТ 10H РЕЖИМ ПЕРЕМЕЩЕНИЯ, AL MOV AH, 00H МОВ АЛ, 03 ИНТ 10H RET B10MODE ENDP C10CLR PROC РЯДОМ MOV AH, 08H ИНТ 10H MOV BH, AH MOV AX, 0600H MOV CX, 0000 MOV DX, 184FH ИНТ 10H MOV AX, 0610H MOV BH, 16H MOV CX, 0418H MOV DX, 1336H ИНТ 10H RET C10CLR ENDP D10SET PROC РЯДОМ MOV AH, 02H MOV BH, 00 MOV DH, ROW MOV DL, COL ИНТ 10H RET D10SET ENDP E10DISP PROC РЯДОМ MOV AH, 0AH MOV AL, CTR MOV BH, 00 MOV CX, 01 ИНТ 10H RET E10DISP ENDP F10 ПРОЧИТАТЬ ПРОЦЕСС РЯДОМ MOV AH, 10H ИНТ 16H RET F10READ ENDP G10MODE PROC РЯДОМ MOV AH, 00H MOV AL, РЕЖИМ ИНТ 10H RET G10MODE ENDP КОНЕЦ НАЧАТЬ ВЫХОД *********** ? ? ? ? ? ? •? ? ? ? ? ? ? ¤ ? ? ? ? ¶ §? ? ? ? ? ? ? ? ? ? ! \ "# $% & \ '() * +, -._ \ `а б в г д е ж з и к л м н о p q r s t u v w x y z {| } ~ ¦ Ü é â ä à ç ê ë è ï î ì Ä Å É æ Æ ô ö ò û ù ÿ Ö Ü £ \ ¥ P ƒ á í ó ú ñ Ñ ª º ¿¬ ¬ ½ ¼ ¡«» ¦ ¦ ¦ ¦ ¦ ¦ ¦ + + ¦ ¦ + + + + + + - - + - + ¦ ¦ + + - - ¦ - + - - - - + + + + + + + + ¦ _ ¦ ¦ ¯ a ß G p S s µ t F T O d 8 f e n = ± = = () ÷ ˜ ° • • v n ² ¦
Assembly (реализовать 32-битное сложение и вызвать вывод int 10h)
Определите двойной подтип:
А DD 21111112H
Б ДД 11111111Н
Вышеупомянутые A и B являются 32-битными, а ax и dx оба являются 16-битными, поэтому старшие 16 бит и младшие 16 бит должны добавляться отдельно.Сначала обрабатываются младшие 16 бит и используется сложение. Старшие 16 бит могут иметь перенос, поэтому используйте adc.
21 |
11 |
11 |
11 |
12 |
A + 1 — 11, A + 4 — 21
Что касается вывода, используя таблицу xlat, сначала создайте таблицу поиска (для вывода 0-F), а затем выводите в соответствии со смещением.
Код:
СЕГМЕНТ ДАННЫХ
; введите здесь код сегмента данных
hextab db '0123456789ABCDEF'
А DD 21111112H
Б ДД 11111111Н
и ДД?
ДАННЫЕ КОНЕЦ
Данные слова относятся к 16 битам, а данные двойного слова относятся к 32 битам.
СЕГМЕНТ СТЕКОВ
; введите здесь код сегмента стека
СТЕК ЗАКОНЧИЛСЯ
КОДЫ СЕГМЕНТ
ПРИНЯТЬ CS: CODES, DS: DATAS, SS: STACKS
НАЧАЛО:
MOV AX, DATAS
MOV DS, AX
; введите код фрагмента кода здесь
mov ax, word ptr A
mov bx, слово ptr B
добавить топор, bx
mov слово ptr ans, ax
mov ax, слово ptr A + 2
mov bx, слово ptr B + 2
Adc ax, bx; adc добавит флаг переноса, сгенерированный предыдущим добавлением
mov слово ptr ans + 2, ax
Lea BX, Hextab
mov ah, 0eh; AH = 0EH
Регистр AL хранит отображаемый символ, а BH - текущая отображаемая страница.Если он находится в графическом режиме, BH должен быть установлен на 0, если он находится в графическом режиме,
Вы также можете установить BL для обозначения цвета текста, а BL в текстовом режиме не имеет никакой функции.
mov dx, слово ptr ans + 2
mov cx, 404h
c1:
rol dx, cl
mov al, dl
и др., 0fh
Xlat; найдите таблицу, сделав AL ← ((BX) + (AL)
int 10h
дек ch
jnz c1
mov dx, word ptr ans
mov cx, 0404h
c2:
rol dx, cl
mov al, dl
и др., 0fh
xlat
int 10h
дек ch
jnz c2
MOV AH, 4CH
ИНТ 21H
КОДЫ КОНЕЦ
КОНЕЦ НАЧАЛА
Проба Netwide Assembler / [Nasm-users] с bios int 10h
Здравствуй, Я написал следующую программу, которая будет запускаться при загрузке моей системы. используя int 10h.Но сообщение не выводится. Может кто плз. помогите мне с этим ?? Зульфи. org 7C00h; запуск программы на 7C00H. Адрес сгенерирован при сбросе раздел .text раздел .text; почему дважды ???? вызов сверхданных; Вызов? Какого черта? Не волнуйтесь, мы открываем. ; обратный адрес отключен, чтобы получить начальный IP. ; Обратите внимание, что «звонок» длиннее, чем ; нет; "jmp short", поэтому нам не нужен nop. На 7C00H мы нужно сделать jmp там, где начинается наш фактический код db 'MyOS'; OEM id - дополнен пробелами до 8 байтов DW 200h; байт / сектор db 1; секторов на кластер dw 1; секторов до FAT db 2; количество жировых отложений dw 0E0h; максимальное количество записей rootdir dw 0B40h; всего секторов db 0Fh; дескриптор медиа dw 9; секторов на FAT dw 12h; секторов на дорожку dw 2; число голов раз 0Ah db 0 дб 29 ч db 0EFh дб 7 db 10h дб 24ч db 'LINUX BOOT FAT12'; угадай, где я ; спрятал это от ; ---------------------------- вывод сообщения на экран при запуске.Мы не можем использовать int 21h избыточные данные: xor di, di mov ds, di мов топор, 0B800h mov es, ax ; Вероятно, здесь тоже стоит создать нормальный стек. ; mov ах, 03ч ; xor bh, bh ; int 10h ; ---------------------------- mov cx, 15 mov bh, 0 mov bl, 0011_1011b mov bp, msg мов топор, 1301h mov dl, 10 mov dh, 7 int 10h черная дыра: jmp blackhole msg db "We be bootin2 '!", 0 умножить на 510 - ($ - $$) дБ 0 db 55h, 0AAh; ?????? Я знаю, время как дурак.Но что это ($ - $$) и 55h и 0AAh ; подпись загрузочного сектора - Просмотрите это сообщение в контексте: http://www.nabble.com/prob-with-bios-int-10h-tp24251227p24251227.html Отправлено из архива списка рассылки nasm-users на Nabble.com.
emu8086 / int10_13.asm на главном сервере · AhmadNaserTurnkeySolutions / emu8086 · GitHub
emu8086 / int10_13.asm на главном сервере · AhmadNaserTurnkeySolutions / emu8086 · GitHub Постоянная ссылка В настоящее время невозможно получить участников; это пример функции bios: int 10h / ah = 13h. | |
; обратитесь к краткому списку прерываний dos для получения дополнительной информации: | |
; c: \ emu8086 \ документация \ | |
наименование «int10h» | |
орг 100ч | |
; установить es (на всякий случай): | |
толчок cs | |
поп | |
mov bh, 0; страница. | |
lea bp, msg; компенсировать. | |
mov bl, 0f3h; атрибут по умолчанию. | |
mov cx, 12; номер символа. | |
mov дл, 2; col. | |
mov dh, 1; строка. | |
мова ах, 13ч; функция. | |
mov al, 1; подфункция. | |
внутр 10ч | |
; показать текущую позицию курсора: | |
mov al, ‘<' | |
mov ah, 0eh | |
внутр 10ч | |
mov bh, 0; страница. | |
lea bp, cmsg; смещение строки с атрибутами. | |
mov bl, 0f3h; атрибут по умолчанию (не используется, если al = 3). | |
mov cx, 12; номер символа. | |
mov дл, 2; col. | |
mov dh, 3; строка. | |
мова ах, 13ч; функция. | |
mov al, 3; подфункция. | |
внутр 10ч | |
; показать текущую позицию курсора: | |
mov al, ‘<' | |
mov ah, 0eh | |
внутр 10ч | |
; дождитесь нажатия любой клавиши…. | |
mov ах, 0 | |
внутр 16ч | |
ret; вернуть управление операционной системе. | |
msg db ‘привет, мир!’ | |
cmsg db ‘h’, 0cfh, ‘e’, 8bh, ‘l’, 0f0h, ‘l’, 5fh, ‘o’, 3ch, », 0e0h | |
db ‘w’, 0b3h, ‘o’, 2eh, ‘r’, 0cah, ‘l’, 1ah, ‘d’, 0ach, ‘!’, 2fh | |
Ассемблер / язык ассемблера
Ассемблер / язык ассемблераЧто действительно нужно всем, так это хорошее и подробное знакомство с ассемблером. который объясняет основы, прежде чем углубляться в техническую информацию. Один хороший онлайн-руководство такого рода, которое я нашел, находится здесь:
http: //udgftp.cencar.udg.mx/ingles/tutor/Assembler.htmlТакже проверьте сборку x86 Language Webring, который, как можно догадаться по названию, является веб-кольцом о языке ассемблера для чипов x86, который относится к серии Intel x86, 286, 386, 486 и т.д. Пентиумы также включены.
И проверить http://www.riverland.net.au/~mdunn для нескольких примеров изящных трюков с asm, например, как управлять динамиком и т. д. (Здесь я научился делать ТСР.)
Однако я должен включить некоторые собственные материалы.Итак, в моем собственном стиль простого перехода к примеру, а затем объяснения того, как все работает, вот несколько небольших программ на ассемблере для разных вещей.
Вывести шестнадцатеричное число в виде удобочитаемого текста
MOV AL, 050h; Измените это на то, что вам нравится, для тестирования. ; Преобразуйте значение в AL в двухзначное шестнадцатеричное число и выведите ; результат на экран. ; Сначала мы используем левый символ ASCII, но его преобразование уничтожает ; содержимое AX ... НАЖАТЬ ТОПОР; ... поэтому давайте сохраним AX, чтобы мы могли восстановить его позже. SHR AL, 4; AL теперь содержит старший полубайт исходного числа. ADD AL, 30h; если этот полубайт был от 0 до 9, он теперь преобразован в ASCII. CMP AL, 39h; Символ 9 или меньше? JLE PRINTFIRSTHEXCHAR; Если да, то он готов к печати. ADD AL, 7; в противном случае это A-F, и его нужно увеличить на 7. ; (Между цифрой 9 и заглавной буквой A в ; Таблица ASCII.) PRINTFIRSTHEXCHAR: MOV AH, 0Eh; Давайте использовать INT 10, E для вывода AL в виде текста ASCII на экран.MOV BH, 0; Номер страницы для текстовых режимов. ИНТ 10ч POP AX; Теперь давайте восстановим AX и проделаем все заново для маленького полубайта! AND AL, 0Fh; Обнулить верхний полубайт, оставив только нижний ... ; ... а в остальном то же, что и выше. ДОБАВИТЬ AL, 30ч CMP AL, 39ч JLE PRINTSECONDHEXCHAR ДОБАВИТЬ AL, 7 PRINTSECONDHEXCHAR: MOV AH, 0Eh MOV BH, 0 ИНТ 10ч MOV AX, 4C00h; Завершить программу ИНТ 21ч
Программа, которая включает курсор мыши
; Включает курсор мыши MOV AX, 01 ИНТ 33ч MOV AX, 4C00h ИНТ 21ч
Первая строка этой программы — просто комментарий.В ассемблере точка с запятой начинается с комментария, а затем комментарий продолжается до остальная часть этой строки.
Строка MOV AX, 01 помещает значение 01 (другими словами, просто 1) в AX, который является регистром ЦП. Регистры — это небольшое временное хранилище области вашего процессора, используемые для обработки данных.
Линия INT 33h вызывает программное прерывание номер 33, которое используется для функций мыши. (Программные прерывания — это мини-функции, встроенные в ваш компьютер.) INT 33 получает все свои инструкции от AX.Что бы мы ни указанный для AX скажет INT 33, что делать. В данном случае мы указали 1, что означает, что мы говорим INT 33 включить курсор мыши. Это именно то, что он будет делать сейчас.
Последние две строки здесь просто для программы прекращение. INT 21 получает свои инструкции от AH, и когда мы передаем 4C в это говорит ему выключить программу. (Это важно. Если мы не указали эти последние две строки из этой программы, курсор мыши будет включен, но программа перестала бы работать и заблокировала компьютер.)
К настоящему времени вы, несомненно, задаетесь вопросом: откуда я знаю, что INT 33 управляет мышь и что MOV AX, 01 скажет включить курсор? Конечно это Достаточно легко, если вы это знаете, но где вы можете найти эту информацию?
Ответ очень прост: внешние ссылки. Целые книги были записывается в INT и регистры, а также в MOV, которые их запускают. Получите книгу от ваша местная библиотека, которая все это объясняет. А еще лучше купить. Если хотите станьте серьезным программистом, вы будете постоянно к нему обращаться.
Если вы не хотите покупать книгу или просто лень идти в библиотеки, вы также можете легко найти полные списки INT в Интернете. В Фактически, отсюда вы можете скачать программу под названием HelpPC 2.10, которая это справочная программа, наполненная полезной информацией для программистов и продвинутые пользователи компьютеров.
Скачайте здесь
Вы также можете получить HelpPC от Simtel по следующей ссылке:
ftp://ftp.simtel.net/pub/simtelnet/msdos/info/helppc21.почтовый индекс
Теперь, когда у вас есть программа, рассказывающая все, что вам нужно знать, вы может быть интересно, как именно создавать программы на ассемблере. Маленькая программа перечисленное выше выглядит, возможно, достаточно интересно, но как его запустить? Только введите его в командной строке компьютера? Ответ: Нет. Вы должны использовать компилятор. Так же, как BASIC, C и Java, ассемблер все еще не чистый, сырой машинный код, поэтому вы должны использовать программу для его перевода, чтобы компьютер может запустить это.
Если вы используете MS-DOS или Windows 95, у вас уже есть программа, которая может инструкции по компиляции ассемблера: Debug.Поставляется с MS-DOS и Windows 95. В командной строке просто введите debug и нажмите ENTER. Ты получишь дефис для подсказки. (Отладка на удивление не интуитивно понятна, но компенсирует это с силой.) Теперь, если вы хотите создать программу, описанную выше, вы можете как хорошо назовите программу перед тем, как начать. Это можно сделать, просто набрав n имя_файла где «имя_файла» — это имя, которое вы хотите дать файлу. (Используйте .COM для расширения, так как это программа.) N — это Debug’s команда для указания имени файла.Большинство команд отладки — это одна характер, собственно. (Я сказал, что это было нелогично.) Теперь вы можете ввести A и нажмите ENTER. Это команда Debug для «сборки», и вы теперь можете начать вводить текст в программе, нажимая ENTER в конце каждой строки, конечно. (Игнорируйте первую строку при вводе, так как это просто все равно прокомментируйте.) Как только вы закончите, запишите номер в конце Подсказка. Это число показывает, сколько байтов вы уже ввели. (Минус 100. Обратите внимание, что он начинается со 100, поэтому фактическое количество байтов равно 100. меньше.) Для этой конкретной программы вы увидите, что она имеет длину 9 байт. Теперь нажмите ENTER, чтобы выйти из сборки и вернуться к подсказке с дефисом. Один небольшая особенность Debug заключается в том, что вы должны указать размер в байтах программ, которые вы напишите, прежде чем сохранять их. Итак, введите RCX (сокращение от Register CX). Это заставит Debug показать вам текущее значение регистра CX (это будет 0), а подсказка станет двоеточием, указывая на то, что вам нужно ввести новое значение для CX. Введите 9 и нажмите ENTER (так как мы пишем 9 байтов).Теперь просто введите w (для «записи»), чтобы сохранить программу. Все сделано. Теперь вы можете ввести q (для выхода), чтобы выйти из отладки.
Теперь программа находится в текущем каталоге. Если вы хотите увидеть свой курсор мыши, просто запустите программу (убедитесь, что у вас загружен драйвер мыши первый). Теперь вы должны увидеть его и сможете перемещать с помощью мыши.
Кстати, обратите внимание, что числа INT выше имеют букву H после них. Это потому что некоторые компиляторы ассемблера предполагают, что если вы просто используете простые числа, они должны быть преобразованы в их шестнадцатеричные значения.Отладка не работает, но A86, очень популярный компилятор, делает. По сути, он будет использовать INT 21, где предполагается использовать 33 (33 десятичное = 21 шестнадцатеричное) и 15, где предполагается используйте 21 (21 десятичное = 15 шестнадцатеричное). Установка H после проясняет любые проблемы что могло бы придумать это.
Да, и если вы хотите снова выключить курсор, вот программа, которая делает именно это:
MOV AX, 02 ИНТ 33ч MOV AX, 4C00h ИНТ 21ч
Как видите, эта программа практически идентична. Единственная разница в том, значение 2 в AX указывает INT 33 выключить курсор.
Приостановить компьютер, пока не будет нажата кнопка мыши
MOV AX, 5; 5 в AX сообщает INT 33, что нужно получить информацию о кнопках мыши. INT 33h; получить информацию о кнопке мыши CMP AX, 1b; сравнивает AX (состояние кнопки) с 1 JL 0100h; если ни одна кнопка не нажата, вернуться к началу ; AX будет равен нулю, пока ни одна кнопка не нажата. JL означает, что если первый ; операнд меньше второго, прыгайте! mov ax, 4C00h; завершить программу int 21h
Работа этой программы должна быть достаточно простой и очевидной.
«Привет, мир».
Следующая программа распечатывает тестовое сообщение канонической программы: «Привет мир.» Практически вся первая программа на BASIC или C — это программа, которая распечатывает это сообщение. Вот один из ассемблера, который делает это
MOV AX, SEG СООБЩЕНИЕ MOV DS, AX MOV DX, СМЕЩЕНИЕ СООБЩЕНИЯ ; Эти три строки делают DS: DX указателем на сегмент: смещение ;СООБЩЕНИЕ. Обратите внимание, что AX используется в качестве промежуточного звена для сегмента, ; потому что некоторые компиляторы ассемблера не позволяют немедленно выполнить MOV ; значения в сегментные регистры (например, DS) напрямую.Некоторые делают, некоторые нет. ; Чтобы избежать проблем, вместо MOV DS, SEG MESSAGE мы делаем ; это в AX, а затем в MOV DS, AX. mov ah, 0009; 9 в AH заставляет INT 21 печатать строку int 21h; ссылка в DS: DX. mov ax, 4C00h; завершить программу int 21h СООБЩЕНИЕ: DB 'Hello, world. $'
Эта программа также должна быть довольно очевидной. Он вводит некоторые новые концепции, но просто изучите это, и я уверен, что вы поймете, что все делает.
Создать текстовую «кнопку» мыши
А теперь еще одна программа для мыши.Вся эта программа полностью не требует пояснений. Это больше, чем те, что указаны выше, но это хорошо прокомментированы.
; Дает вам экранную кнопку, по которой можно щелкнуть мышью, и ; продолжается только тогда, когда вы это делаете! mov ah, 06h; это вызывает SCROLL SCREEN UP mov al, 00h; AL указывает, сколько строк ... 0 просто очищает экран mov ch, 00h mov cl, 00h mov dh, 24ч mov дл, 80ч int 10h ; Вышеупомянутые строки просто очищают экран. mov ah, 02h; Установить позицию курсора mov dh, 0Bh; строка mov dl, 22h; столбец int 10h; Собственно делает это.:) MOV AX, SEG СООБЩЕНИЕ MOV DS, AX MOV DX, СМЕЩЕНИЕ СООБЩЕНИЯ mov ah, 0009; 9 в AH заставляет INT 21 печатать строку int 21h; ссылка в DS: DX. ; Итак, мы напечатали КНОПКУ именно там, где хотели !!! mov ax, 0001 int 33h ; Итак, мышь включена. МЫШЬ: MOV AX, 5; 5 в AX сообщает INT 33, что нужно получить информацию о нажатии кнопки мыши INT 33h; получить информацию о кнопке мыши CMP AX, 1b; сравнивает AX (состояние кнопки) с 1 JNE MOUSLOOP; если не нажата ТОЛЬКО ЛЕВАЯ кнопка, вернитесь в MOUSLOOP ; (Для этого подойдет только левая кнопка... Не то.) MOV AX, 3 INT 33h; Теперь мы получаем информацию о ПОЛОЖЕНИИ через INT 33,3! ; CX теперь горизонтальное положение мыши. 0 - 639 ; DX теперь вертикальное положение мыши. 0–199 CMP CX, 270 JL MOUSLOOP; Если CX меньше 270 (левый край кнопки), вернуться CMP CX, 315 JG MOUSLOOP; Если CX больше 400 (правый край), вернуться CMP DX, 85 JL MOUSLOOP; Если DX меньше 85 (вверху), вернитесь CMP DX, 95 JG MOUSLOOP; Если DX больше 110 (внизу), вернитесь ; Приведенные выше значения размеров кнопок являются приблизительными, но ; должно быть достаточно хорошо.mov ax, 0002 int 33h ; Это просто скрывает курсор. В противном случае он останется включенным, когда программа ; закончился! :) mov ax, 4C00h; завершить программу int 21h СООБЩЕНИЕ: DB 'BUTTON $'
Проверить наличие драйвера мыши
Часто программе нужно просто проверить, не был ли установлен драйвер мыши. установлен или нет. (Обычно при запуске программы, требующей мыши, поэтому при необходимости программа может прервать работу с ошибкой «Нет драйвера мыши».) программа, которая отображает сообщение об ошибке, если драйвер мыши НЕТ, и тихо завершает работу, если драйвер был обнаружен.
MOV AX, 0000 ИНТ 33ч CMP AX, 0000 JNE Ender ; Здесь код, который будет выполняться, если драйвер мыши не установлен. МОВ АГ, 09 MOV DS, сообщение SEG MOV DX, сообщение OFFSET ИНТ 21ч Эндер: mov ax, 4C00h; завершить программу int 21h Сообщение БД "ОШИБКА: драйвер мыши не обнаружен. $"
Вернуть уровень ошибки в зависимости от наличия драйвера мыши
Простое дополнение к предыдущей программе, возвращающее уровень ошибки. в зависимости от наличия драйвера мыши: возвращает 0, если драйвер был обнаружен, или 1, если драйвер не обнаружен.(В DOS уровень ошибки 0 — это стандартный код для обозначения «ошибок нет»)
; Проверяет драйвер мыши, возвращает уровень ошибки 0, если ошибок нет, возвращает ; errorlevel 1, если ошибка (т.е. драйвер мыши не установлен) MOV AX, 0000 ИНТ 33ч CMP AX, 0000 JNE Itsok ; Здесь код, который будет выполняться, если драйвер мыши не установлен. MOV AL, 01; Возвращает уровень ошибки 1 (указывает на ошибку) JMP Ender Ничего страшного: MOV AL, 00; Вернуть уровень ошибки 0 (нет проблем) Эндер: MOV AX, 4C00h; завершить программу ИНТ 21ч
Создание графического курсора мыши
Определенно немного длиннее и сложнее, чем предыдущие программы, но, на мой взгляд, оно того стоит.
; Включите графический курсор мыши и сделайте его похожим на указывающую руку. mov ах, 00ч mov al, 13h int 10h ; Три вышеперечисленных строки переключаются на 256 VGA! MOV AX, 09h; Указывает INT 33 установить курсор мыши MOV BX, 0Ah; горизонтальная горячая точка (от -16 до 16) MOV CX, 00h; вертикальная горячая точка (от -16 до 16) MOV ES, SEG Curlook MOV DX, СМЕЩЕНИЕ Curlook ; ES: DX = указатель на экран и маски курсора (16-байтовое растровое изображение) INT 33h; УСТАНОВИТЬ КУРСОР МЫШИ !!! MOV AX, 01h INT 33h; Включи! mov ax, 4C00h; завершить программу int 21h ; ПРИМЕЧАНИЕ. Каждое следующее слово определяет одну строку.; В одном ряду 16 пикселей. ; В каждой строке по 2 байта. ; 1 слово - это 2 байта или 16 бит. Каждый бит набора слов ; этот пиксель должен быть включен или выключен. ; (Размер курсора - 16 на 16 пикселей.) ; (Символы «xB» указывают на двоичное число.) ; Маска экрана: ; Если бит равен 1, то будет отображаться фон под этим пикселем. ; Если бит равен 0, то фон под этим пикселем будет скрыт ; курсором, когда он находится над этой областью. ; Второй байт в каждой строке - это 8 крайних левых пикселей. Первый байт ; - крайние правые 8 пикселей.(Не спрашивайте меня, почему они поменялись местами ;как это.) ; (В общем, эти биты должны быть прямо противоположны их ; аналоги курсора. Таким образом, курсор закрывает то, что находится под ним, ; и ничего вокруг курсора не закрывается.) Curlook DB 11111111xB, 11111001xB ДБ 11111111xB, 11110000xB ДБ 11111111xB, 11110000xB ДБ 11111111xB, 11110000xB ДБ 11111111xB, 11110000xB ДБ 11111111xB, 11110000xB ДБ 00000111xB, 11000000xB ДБ 00000011xB, 10000000xB ДБ 00000011xB, 10000000xB ДБ 00000111xB, 11000000xB ДБ 00000111xB, 11000000xB ДБ 00001111xB, 11100000xB ДБ 00011111xB, 11110000xB ДБ 00011111xB, 11111000xB ДБ 00011111xB, 11111000xB ДБ 00011111xB, 11111000xB ; Уф! :) Вот только маска экрана... А вот и маска курсора! ; (Если бит равен 1, это означает, что пиксель для курсора будет включен. ; Если бит равен 0, это означает, что пиксель для курсора будет выключен.) ; Второй байт в каждой строке - это 8 крайних левых пикселей. Первый байт ; - крайние правые 8 пикселей. (Не спрашивайте меня, почему они поменялись местами ;как это.) ДБ 00000000xB, 00000110xB ДБ 00000000xB, 00001111xB ДБ 00000000xB, 00001111xB ДБ 00000000xB, 00001111xB ДБ 00000000xB, 00001111xB ДБ 00000000xB, 00001111xB ДБ 11111000xB, 00111111xB ДБ 11111100xB, 01111111xB ДБ 11111100xB, 01111111xB ДБ 11111000xB, 00111111xB ДБ 11111000xB, 00111111xB ДБ 11110000xB, 00011111xB ДБ 11100000xB, 00001111xB ДБ 11100000xB, 00000111xB ДБ 11100000xB, 00000111xB ДБ 11100000xB, 00000111xB
Красный пиксель, который следует за движением мыши
Вот небольшая приятная программа, которая показывает, как сделать графику, которая реагировать на движение мыши.В этом случае «графика» — это только одиночный пикселя, но суть здесь в том, чтобы показать, как улавливать движение мыши, а не как рисовать красивую графику.
Причина, по которой это важно, состоит в том, что, хотя мы видели выше, как используйте INT 33,9 для создания нашего собственного графического курсора мыши, INT 33,9 не поддерживает изготовления цветных курсоров мыши; это может сделать только черно-белая мышь курсоры. Если вы хотите сделать курсор мыши цветным, прерывания нет функция для этого в стандартном Microsoft-совместимом драйвере мыши для DOS, это означает, что вместо использования простого вызова прерывания подключаемого модуля для создания вашего курсор мыши, вы должны проверить местоположение мыши с помощью INT 33,3 (который возвращает местоположение указателя мыши на экране), а затем нарисуйте свой собственный курсор мыши там.
Реализация рабочего курсора мыши с этим в основном означала бы создание курсор мыши в спрайт, который перемещается по экрану, но оставляет графика на экране, как она была после того, как она покидает эту часть экрана. Существует множество руководств о том, как создавать спрайт-графику, поэтому я пропустил эту информацию здесь, чтобы сосредоточиться на том, как фиксировать движение мыши и соответственно измените положение пикселя на экране. Это привело к удивительно медитативный опыт, учитывая, насколько простой код является.Программа также проверяет каждый цикл на предмет нажатия клавиши Q для выхода.
mov ах, 00ч mov al, 13h int 10h ; Три вышеперечисленных строки переключаются в режим 13h, который является 256-цветным VGA. MAINLOOP: ; Давайте проверим, нажал ли пользователь Q для выхода. IN AL, 60h; чтение из порта ввода клавиатуры в AL CMP AL, 10h; клавиша "Q" имеет скан-код 10h JE QUITTER; Если AL равно 10h, пользователь нажал Q, поэтому перейдите к процедуре выхода mov ax, 3; Получить позицию мыши (а также статус кнопки, который здесь не используется) int 33h ; Теперь CX и DX содержат позиции X и Y мыши: ; CX = положение по горизонтали (X) 0 - 639 ; DX = вертикальное (Y) положение 0 - 199 ; Во-первых, исправим CX, так как он на самом деле вдвое шире, чем нам нужно.; (Наш режим видео 320x200, но CX имеет разрешение 640 пикселей.) ; Загрузим CX в AX (так как нам нужно использовать AX для деления), ; затем разделите AX на 2 и переместите AX обратно в CX. MOV AX, CX MOV BX, 2 ; Здесь я хотел бы просто использовать DIV BX, чтобы разделить AX на 2. ; (Мы также могли бы использовать DIV BL для 8-битного деления, но это разрушит ; все вверх, если пользователь перемещает мышь слишком далеко вправо, так как наш ; экран имеет ширину 320 пикселей, но 8-битный регистр достигает только 256.) ; Однако есть еще одна небольшая деталь, на которую мы должны обратить внимание, ; а именно регистр DX, который, вероятно, вызовет сбой этой программы с ; ошибка переполнения при разделении, если мы не обращаем на нее внимания.; Инструкция DIV BX делит 32-битное значение в DX: AX на BX. ; Если значение DX отличное от 0 или 1, вероятно, вызовет разделение ; переполнение, потому что результаты не помещаются в 16-битный регистр AX, который ; приведет к сбою программы. ; В любом случае, мы хотим разделить только то, что находится в AX, а не в DX, ; поэтому давайте установим DX в 0. ; Однако DX по-прежнему содержит наше важное значение Y для положения мыши, поэтому ; мы сохраняем DX, сначала нажав PUSH, а затем POP, когда закончим с ним. PUSH DX MOV DX, 0 DIV BX; НАКОНЕЦ! POP DX MOV CX, AX ; CX делится на 2 ; Теперь давайте умножим DX на 320, так как каждая строка имеет длину 320 пикселей, поэтому ; размер ячейки памяти необходимо увеличить на 320 для каждой вертикальной строки.MOV AX, 320 MUL DX ; AX теперь содержит DX, умноженное на 320. Расположение по вертикали в видеопамяти ; правильно, поэтому давайте добавим горизонтальное значение, все еще содержащееся в CX ... ДОБАВИТЬ AX, CX ; ... и сохраните окончательное значение местоположения экрана в BX. MOV BX, AX MOV DS, 0A000h; сегмент видео с отображением в память VGA MOV AL, 40; десятичный 40 красный! MOV [BX], AL; Записывает красный пиксель в текущее местоположение экрана, сохраненное в BX. JMP MAINLOOP ЧЕТВЕРТ: mov ax, 4c00h; завершить программу int 21h
Используйте LODSB для загрузки данных из буфера памяти в аккумулятор
Эта программа содержит 200-байтовую последовательность цветов пикселей.Когда программа При запуске этот 200-байтовый блок данных загружается в память. Затем программа загружает данные из этого буфера по одному байту через LODSB, затем помещает байт значение на экране, чтобы создать пиксель этого цвета.mov ах, 0 mov al, 13h int 10h ; Вышеупомянутые 3 строки устанавливают видеорежим 13h MOV BX, 0; Начать с пикселя 0 MOV CX, 200; Количество раз, чтобы пройти цикл MOV SI, OFFSET MyBuffer; LODSB загружает байт из DS: SI в AL LOOPER: НАЖАТЬ CS POP DS; Устанавливает DS в качестве текущего сегмента программы CLD; Очистить флаг направления, чтобы SI увеличивался на LODSB LODSB; Загрузить байт из DS: SI в AL и увеличить SI MOV DS, 0A000h; сегмент видео с отображением в память VGA MOV [BX], AL; Вывести данные на экран в виде пикселя INC BX; перейти к следующему пикселю DEC CX CMP CX, 0 JNE LOOPER mov ax, 4C00h; завершить программу int 21h MyBuffer DB 40 DUP (40, 49, 33, 44, 37) ; Создает 40 копий этой 5-байтовой последовательности (что соответствует цветам ; красный, зеленый, синий, желтый, пурпурный) на 200 байт в памяти
Показать файл необработанного изображения
Как расширение вышеуказанной программы, эта программа читает файл необработанного изображения (один в котором каждый пиксель представляет собой отдельный байт файла) и выводит его на экран.Эта программа предполагает изображение размером 320×200 пикселей и, таким образом, использует данные размером 64000 байт. буфер, но если вы используете другой размер изображения, вы можете настроить размер этого буфера легко. Не забудьте указать имя файла в последней строке (здесь установлено «IMAGE.RAW»).
mov ах, 0 mov al, 13h int 10h ; Вышеупомянутые 3 строки устанавливают видеорежим 13h MOV AH, 3Dh; открыть файл с помощью дескриптора MOV AL, 0; только чтение MOV DS, SEG Имя файла MOV DX, OFFSET Имя файла ИНТ 21ч ; AX теперь дескриптор файла MOV BX, AX; дескриптор файла MOV AH, 03Fh; Прочитать из файла с помощью дескриптора MOV CX, 64000; количество байтов для чтения MOV DS, SEG MyBuffer MOV DX, СМЕЩЕНИЕ MyBuffer ИНТ 21ч ; MyBuffer теперь должен содержать 64000 байтов файла изображения MOV CX, 64000; Количество байтов для обработки MOV BX, 0; Начать с пикселя 0 MOV SI, СМЕЩЕНИЕ MyBuffer LOOPER: НАЖАТЬ CS POP DS; Устанавливает DS в качестве текущего сегмента программы CLD; Очистить флаг направления, чтобы SI увеличивался на LODSB LODSB; Загрузить байт из DS: SI в AL и увеличить SI MOV DS, 0A000h; сегмент видео с отображением в память VGA MOV [BX], AL; Вывести данные на экран в виде пикселя INC BX; перейти к следующему пикселю DEC CX CMP CX, 0 JNE LOOPER mov ax, 4C00h; завершить программу int 21h MyBuffer DB 64000 DUP (?) Имя файла DB 'IMAGE.RAW ', 0
Сброс дат файлов
Было весело, но теперь давайте отойдем от мыши. Вот утилита для сбросить даты файлов на 1 января 1980 г. в 12:00:00 (что является самым ранним дата, поддерживаемая DOS в файлах). Очень удобно, когда хочется забыть о когда что-то случилось.
; Следующие 5 строк просто сбрасывают флаг переноса (CF), что важно, ; поскольку очистка флага переноса заставляет INT 21,3D возвращать дескриптор файла ; вместо кода ошибки. PUSHF; передать в стек 16-битный флаговый регистр POP AX; AX теперь содержит содержимое регистра флагов AND AX, 0FFFEh; устанавливает крайний правый бит (флаг переноса) в 0 НАЖАТЬ ТОПОР POPF MOV AH, 3Dh; открыть файл с помощью дескриптора MOV AL, 1; только запись MOV DS, SEG имя файла MOV DX, OFFSET имя файла ИНТ 21ч ; AX теперь должен содержать дескриптор файла.MOV BX, AX; передать дескриптор файла в BX, где он принадлежит MOV AH, 57h; установить дату / время файла с помощью дескриптора MOV AL, 1; установить (не читать) дату и время MOV CX, 0; 12: 00: 00 AM MOV DX, 21h; 1 января 1980 г. (0000000000100001) ИНТ 21ч MOV AH, 3Eh; закрыть файл с помощью дескриптора ; BX уже содержит соответствующий дескриптор файла из предыдущей операции, ; поэтому нам не нужно его переустанавливать. ИНТ 21ч mov ax, 4C00h; завершить программу int 21h ; Отредактируйте строку ниже, чтобы отразить фактическое имя файла ; файл, дату которого вы хотите сбросить.имя файла DB 'newfile.txt', 00
Корпус TSR
Вот оболочка TSR. Он предоставляет основу для того, что вам нужно для создания программа, которая остается резидентной в памяти (теперь вам просто нужно поместить функцию что резидентная программа должна выполняться в указанной точке):
; КАК СДЕЛАТЬ TSR: ; ШАГ 1. Получить вектор прерывания INT 8. CLI; отключить аппаратные прерывания MOV AL, 8h; указывает INT 8 MOV AH, 35h; получить вектор прерывания ИНТ 21ч ; ШАГ 2. Заставьте INT C8 вести себя как INT 8.; (INT C8 все равно ничем не используется.) MOV DX, BX НАЖАТЬ ES POP DS ; указанные выше три строки устанавливают для DS: DX значение ES: BX. MOV AL, 0C8h MOV AH, 25h; установить вектор INT C8 (заставляет INT C8 вести себя как INT 8) ИНТ 21ч ; ШАГ 3. Установите вектор INT 8 в вашу собственную функцию прерывания. MOV DX, СМЕЩЕНИЕ TSRINT НАЖМИТЕ CS; нажмите сегмент кода ... POP DS; ... сделать DS равным сегменту этой подпрограммы МОВ АЛ, 8 MOV AH, 25h; установите INT 8 как ваша новая функция прерывания ИНТ 21ч ; ШАГ 4. Сделайте INT 21,31, и все готово. MOV AL, 0; код выхода (для командных файлов) MOV DX, 0FFh; сколько памяти зарезервировано для этого TSR MOV AH, 31h; превратить его в TSR сейчас ИНТ 21ч ЦРИНТ: ; ЭТО ФАКТИЧЕСКИЙ КОД САМОСТОЯТЕЛЬНОГО ПРЕРЫВАНИЯ: CLI; отключить прерывания PUSHA; сохранить текущий статус регистров на будущее ; ВАША ПРОГРАММА ПРЕРЫВАНИЯ ЗДЕСЬ! Здесь код фактического прерывания ; функция (процесс, который TSR должен повторять, пока находится в ; memory) должен уйти.; Напоминание: PUSHA используется выше для сохранения регистров, чтобы их можно было легко ; позже восстановили их прежнее состояние с помощью POPA. Однако PUSHA и POPA ; влияют только на (E) AX, (E) CX, (E) DX, (E) BX, (E) SP, (E) BP, (E) SI и (E) DI. Они ; НЕ влияют на какие-либо сегментные регистры (CS, DS, SS или ES), что означает, что ; если ваша процедура использует эти регистры, вам также необходимо сохранить их ; PUSH их перед этой подпрограммой прерывания и POPing после ее завершения. POPA; восстановить старый статус реестра (чтобы все было как раньше) INT 0C8h ; сделайте также старый INT 8, иначе то, что должно быть INT 8, никогда не будет выполнено НАЖАТЬ ТОПОР МОВ АЛ, 20ч OUT 20h, AL; отправляет сигнал End-Of-Interrupt на контроллер 8259 int. POP AX STI; повторно разрешить прерывания (противоположно CLI) IRET; возврат прерывания (означает, что прерывание закончилось)
Поддержание «постоянного пикселя» на экране
Хотя приведенная выше оболочка TSR является хорошей отправной точкой, на самом деле это не так. Делать что-нибудь.Программа ниже, вероятно, одна из самых забавных маленьких программы на ассемблере, которые я сделал, потому что это TSR, который что-то делает это постоянно видно: он переключается в графический режим 13h, затем ставит один желтый пиксель на экране. Что, пожалуй, еще интереснее загружая эту программу, а затем экспериментируя с другими программами, которые используют разные видеорежимы; в некоторых режимах видео из-за этого TSR несколько пикселей в горизонтальная строка будет повреждена (так как некоторые графические режимы не используют простое преобразование памяти из одного пикселя в один байт, которое используется в режиме 13h).
; TSR, который действительно что-то делает! Эта небольшая программа будет использовать свой ; Функциональность TSR для создания раздражающего пикселя на экране, который БУДЕТ ; НЕ уходите, сколько бы вы ни пытались прокрутить его или закрыть его ;далеко. (Что ж, переключение в режим видео без графики прояснит это.) mov ах, 00ч mov al, 13h int 10h ; Вышеупомянутые 3 строки переводят вас в режим видео 13 ; ШАГ 1. Получить вектор прерывания INT 8. CLI; отключить аппаратные прерывания MOV AL, 8h; указывает INT 8 MOV AH, 35h; получить вектор прерывания ИНТ 21ч ;ШАГ 2.Сделайте так, чтобы INT C8 вел себя как INT 8. MOV DX, BX НАЖАТЬ ES POP DS ; указанные выше три строки устанавливают для DS: DX значение ES: BX. MOV AL, 0C8h MOV AH, 25h; установить вектор INT C8 (заставляет INT C8 вести себя как INT 8) ИНТ 21ч ; ШАГ 3. Установите вектор INT 8 в вашу собственную функцию прерывания. MOV DX, СМЕЩЕНИЕ TSRINT НАЖМИТЕ CS; нажмите сегмент кода ... POP DS; ... сделать DS равным сегменту этой подпрограммы МОВ АЛ, 8 MOV AH, 25h; установите INT 8 как ваша новая функция прерывания ИНТ 21ч ; ШАГ 4. Сделайте INT 21,31, и все готово. MOV AL, 0; код выхода (для командных файлов) MOV DX, 0FFh; сколько памяти зарезервировано для этого TSR MOV AH, 31h; превратить его в TSR сейчас ИНТ 21ч ЦРИНТ: CLI; отключить прерывания PUSHA; сохранить текущий статус регистров на будущее PUSH DS; сохраните и DS, так как мы его используем ; ПОРЯДОК ПОКАЗАНИЯ ПИКСЕЛЕЙ СЛЕДУЕТ! MOV DS, 0A000h MOV BX, 35100; расположение пикселя на экране.Настроить по вкусу. MOV AX, 44h; 44h желтый MOV [BX], AX POP DS; поп DS ... POPA; ... и все остальное, так что все как было раньше. INT 0C8h; сделайте также старый INT 8 НАЖАТЬ ТОПОР МОВ АЛ, 20ч OUT 20h, AL; отправить сигнал End-Of-Interrupt на контроллер 8259 int POP AX STI; повторно разрешить прерывания IRET; возврат прерывания (означает, что прерывание закончилось)
Укажите текущий видеорежим
Эта программа выводит один байт, который указывает текущее видео. режим. Это может быть полезно, поскольку на самом деле я не знаю другого способа выяснить, в каком видеорежиме вы сейчас находитесь; вы также можете создать TSR который делает что-то подобное по команде, чтобы выяснить, в каком видеорежиме конкретная программа используется, поскольку она работает
; Показать текущий режим видео.Эта программа выводит один символ, который ; - это расширенный символ ASCII, соответствующий видеорежиму. В ; шестнадцатеричное значение символа - текущий видеорежим. МОВ ДС, 40ч МОВ СИ, 49ч ; DS: SI теперь указывает на 40:49, где находится текущее видео ;Режим MOV DL, [SI]; DL = символ для вывода МОВ АХ, 2 INT 21h; вывести символ mov ax, 4C00h; завершить программу int 21h
Распечатать дату BIOS
Стандартный компьютер BIOS хранит дату выпуска в виде 8-байтовой строки в памяти. расположение FFFF: 5.Эта программа печатает эту строку.
; Печать из ПЗУ, начиная с FFFF: 5 для 8 символов ; (Здесь отображается дата ROM BIOS) MOV DS, 0FFFFh МОВ СИ, 5 MOV CX, 8 mainloop: MOV DL, [SI]; DL = символ для вывода МОВ АХ, 2 INT 21h; вывести символ INC SI; переместить SI на следующий байт LOOPNZ mainloop; это повторяется 8 раз, потому что CX был установлен на 8 mov ax, 4C00h; завершить программу int 21h
Нарисовать пиксель в графическом режиме
По умолчанию приглашения DOS являются только текстовыми, что означает, что вы не можете рисовать графику на экран с ними.Однако вы можете изменить свой графический режим с помощью INT. 10,0. Эта программа начинается с переключения в знаменитый режим 13 (320×200 256-цветной VGA, очень популярный видеорежим для любительских игр DOS), а затем рисует один пиксель, чтобы продемонстрировать графические возможности этого режим.
; Рисует один желтый пиксель в верхнем левом углу. ; Записывает непосредственно в видеопамять, которая начинается с A000: 0 mov ах, 00ч mov al, 13h int 10h ; Вышеупомянутые три строки просто переключаются на 256-цветной VGA 320x200. mov ds, 40960 ; a000h = 40960 десятичное мов топор, 44ч ; 44h - желтый! ;) mov bx, 0000 mov [bx], топор ; По умолчанию используется DS: [something], и поскольку здесь указано bx, оно перемещается ; AX в DS: BX !!! mov ax, 4C00h; завершить программу int 21h
Нарисовать линию в графическом режиме
; В дальнейшем рисует желтую линию в верхнем левом углу.; Хороший пример того, как эффективно использовать INC, CMP, ; и условный переход для повторяющихся задач. mov ах, 00ч mov al, 13h int 10h ; Вышеупомянутые три строки просто переключаются на 256-цветной VGA 320x200. mov ds, 40960 ; a000h = 40960 десятичное мов топор, 44ч ; 44h - желтый! ;) mov bx, 0000 НАЧАЛО: mov [bx], топор inc bx cmp bx, 20 JL START ; Это ждет, пока BX не достигнет 20, а затем завершится! mov ax, 4C00h; завершить программу int 21h
Нарисовать по одному пикселю каждого цвета, доступного в режиме видео 13
; печатает подряд все 256 цветов в порядке от 1 до FF, ; в верхней части экрана.mov ах, 00ч mov al, 13h int 10h ; Вышеупомянутые три строки просто переключаются на 256-цветной VGA 320x200. mov ds, 40960 ; a000h = 40960 десятичное mov bx, 0000 mov ax, 00h; Начните с цвета номер 0, поскольку 0 также является допустимым цветом. MAINLOOP: mov [bx], топор inc bx вкл топор cmp ax, 0FFh JNG MAINLOOP mov ax, 4C00h; завершить программу int 21h
Нарисуйте пять рядов пикселей каждого цвета, доступного в режиме видео 13
; Печать всех возможных 256 цветов подряд 5 раз (таким образом получается 5 строк). ; ; Один пиксель трудно различить, поэтому я подумал, что это будет полезно ; чтобы цветные полосы были больше 1 пикселя.; Однако VGA с разрешением 320x200 имеет только 320 пикселей по горизонтали, поэтому нет ; возможность увеличить на 256 цветов по горизонтали и при этом сохранить их все ; в один ряд. Таким образом, я выбрал вертикальный вариант. mov ах, 00ч mov al, 13h int 10h ; Вышеупомянутые три строки просто переключаются на 256-цветной VGA 320x200. mov ds, 40960 ; a000h = 40960 десятичное mov bx, 0000 mov ax, 00h; Начните с цвета номер 0, поскольку 0 также является допустимым цветом. MAINLOOP: mov [bx], топор добавить bx, 320 ; Выше мы используем десятичное значение горизонтального разрешения для спуска на строку mov [bx], топор добавить bx, 320 mov [bx], топор добавить bx, 320 mov [bx], топор добавить bx, 320 mov [bx], топор sub bx, 1280; А теперь вычтите 4 раза горизонтальное разрешение, чтобы подняться на 4 строки inc bx вкл топор cmp ax, 0FFh JNG MAINLOOP mov ax, 4C00h; завершить программу int 21h
Включить «блокировку» всей клавиатуры.
Эта программа включает Caps Lock, Num Lock и Scroll Lock.
; Переместите F0h на 40:17 МОВ ДС, 40ч MOV BX, 17ч MOV AX, 0F0h MOV [BX], AX mov ax, 4C00h; завершить программу int 21h
Отключить «блокировку» всей клавиатуры.
; Перенести 80h на 40:17 МОВ ДС, 40ч MOV BX, 17ч MOV AX, 80ч MOV [BX], AX mov ax, 4C00h; завершить программу int 21h
Ожидание определенного скан-кода клавиатуры
; Продолжайте сканировать порт ввода клавиатуры (порт 60h). Это следит за ; какие бы клавиши ни были нажаты. Если ключ является ключом A (который имеет сканирование ; код 1Eh), программа завершается.Это демонстрирует, как напрямую просматривать ; какие клавиши нажимаются. петлитель: IN AL, 60h; получить последний скан-код CMP AL, 1Eh; это? JE эндер Петлитель JMP конец: MOV AX, 4C00h; завершить программу ИНТ 21ч
Показать содержимое буфера клавиатуры кольцевой очереди
Очевидно, ячейка памяти 40: 1E должна содержать «кольцевую очередь. буфер клавиатуры «. Я так и не понял, как это работает и что форматировать содержимое этого местоположения, которое предполагается принять, но это интересно запустить эту программу и посмотреть несколько исторических нажатий клавиш вверх.
; 40: 1E - расположение 32-байтового буфера клавиатуры кольцевой очереди MOV DS, 0040h MOV SI, 001Eh MOV BH, 0001h MOV AH, 0Eh MOV CX, 32ч MainLoop: MOV AL, [SI] ИНТ 10ч INC SI LOOP MainLoop mov ax, 4C00h; завершить программу int 21h
Показать параметры командной строки
В какой-то момент вы можете захотеть создать программу, которая будет использовать параметры командной строки. Эта программа позволяет вам экспериментировать с параметрами, так как он просто распечатывает параметры, которые вы даете ему во время выполнения.
; Показать параметры командной строки, заданные программе MOV AH, 03h INT 10h; Это вернет: строка курсора: DH, столбец курсора: DL МОВ СИ, 80ч CMP B [SI], 00ч. Дж. Э. Эндер ; Три вышеперечисленных строки быстро проверяют, заданы ли * какие-либо * параметры. ; Если нет, выполняется резкий выход. ; (Количество байтов в параметрах хранится в 80h) MOV SI, 82h; Начиная с 82h, параметры командной строки MOV CX, 1h; для INT 10, ради A MainLoop: MOV AH, 0Ah; Указывает INT 10 напечатать символ MOV AL, [SI]; Загружает символ в AL CMP AL, 0Dh; Если символ - возврат каретки, конец Дж. Э. Эндер; (Потому что это конец параметров) INT 10h; печатает символ в AL INC SI; перейти к следующему символу INC DL MOV AH, 02h ИНТ 10ч ; Три вышеперечисленных строки перемещают столбец на один вправо JMP MainLoop; продолжайте, пока не дойдет до возврата каретки Эндер: mov al, 0 ; Забавно, но это вызывает проблемы для INT 21,4C, если у AL есть ; отвратительное значение, поэтому мы сбрасываем его непосредственно перед завершением.mov ax, 4C00h; завершить программу int 21h
Включите внутренний динамик ПК
; Включает внутренний динамик. MOV AL, 0B6h ВЫХОД 43ч, AL ; Большинство источников говорят, что вы должны отправить шестнадцатеричный B6 на порт 43 перед ; включение динамика. Хотя кажется, что он работает нормально, даже если вы этого не сделаете, ; вы могли бы также. IN AL, 61h; Устанавливает AL на текущее значение порта 61 ИЛИ AL, 11b; Устанавливает последние два байта AL в 1 ВЫХОД 61ч, AL ; Получается 61 именно так, как было, но с двухбайтовой заменой! ; Это включит динамик! MOV AX, 4C00h; завершить программу ИНТ 21ч
Выключить внутренний динамик ПК
; Выключает внутренний динамик.IN AL, 61h; Устанавливает AL на текущее значение порта 61 XOR AL, 11b; Устанавливает последние два байта AL в 0 ВЫХОД 61ч, AL ; Получается 61 именно так, как было, но с двухбайтовой заменой! ; Это отключит динамик! MOV AX, 4C00h; завершить программу ИНТ 21ч
Изменение высоты звука внутреннего динамика ПК
; Изменяет тембр динамика компьютера. (Должно быть ; уже был включен раньше.) МОВ АХ, 11 MOV AL, 01011101xB ВЫХОД 42ч, AL MOV AL, AH ВЫХОД 42ч, AL mov ax, 4C00h; завершить программу int 21h
Превратите первого пилота в списке боевых кораблей 2000 во 2-го лейтенанта
Отличное дополнениеGunship 2000, Islands And Ice, позволяет использовать только его редактор миссии после того, как вы достигли звания не ниже 2-го лейтенанта (2LT).Это, честно говоря, возмутительно, поскольку вы должны уметь собственные миссии в любое время. Эта программа — простой способ справиться с этим проблема. Он редактирует файл реестра Gunship 2000, ROSTER.DAT, так что первый Пилот в составе 2-го лейтенанта. Если вы хотите сменить пилота кроме первого в списке, вы можете просто отредактировать количество байтов который программа продвигает в файле. В настоящее время он установлен на 54ч.
; Установите для байта 54h файла значение 5. Это сделает вас 2-м лейтенантом (2LT), ; что, в свою очередь, позволит вам использовать конструктор миссий.MOV AH, 3Dh; открыть файл с помощью дескриптора MOV AL, 01; только запись MOV DS, SEG FILENAME MOV DX, СМЕЩЕНИЕ ИМЕНИ ФАЙЛА ИНТ 21ч ; AX теперь дескриптор файла MOV BX, AX; перемещает AX (дескриптор файла) в BX MOV AH, 42h; переместить указатель файла МОВ АЛ, 0 MOV CX, 0; старшее слово количества байтов для перемещения MOV DX, 54h; младшее слово количества байтов для перемещения ; Переместите 54 байта, так как именно там находится нужный нам байт ИНТ 21ч ; BX по-прежнему остается дескриптором файла MOV AH, 40h; записать в файл с помощью дескриптора MOV CX, 1; количество байтов для записи MOV DS, SEG БУФЕР MOV DX, СМЕЩЕНИЕ БУФЕРА ИНТ 21ч mov ax, 4C00h; завершить программу int 21h ИМЯ ФАЙЛА db 'ROSTER.ДАТ ', 00 ; 00 в конце означает завершение имени файла символом 00, ; превращая его в строку ASCIIZ. БУФЕР db 5 ; BUFFER - это то, что на самом деле будет записано в файл.
Ну вот и все. Если у вас есть какие-либо советы или комментарии, пожалуйста Напиши мне. Спасибо.
Вернуться на главную
.