Компиляция com программы - Assembler
Формулировка задачи:
Нашла задачу, рисует линии, как я поняла от точки до точки. С помощью tasm и tlink делаю exe файл, запускается, курсор видно, но линии не рисуются. Прочитала что нужно делать не exe, а COM, но так и не поняла как его делать...
В общем, кто звстречался с проблемой, помогитее
Листинг программы
- ; mousedr.asm
- ;Рисует на экране прямые линии, оканчивающиеся в позициях, которые указываются мышью.
- STACK 256
- .model tiny
- .code
- org 100h ; COM-файл.
- .186 ; Для команжы shr cx, 3.
- start:
- mov ax, 12h
- int 10h ; Видеорежим 640*480.
- mov ax, 0 ; Инициализировать мышь.
- int 33h
- mov ax, 1 ; Показать курсор мыши.
- int 33h
- mov ax, 000Ch ; Установить обработчик событий мыши.
- mov cx, 0002h ; Событие - нажатие левой кнопки.
- mov dx, offset handler ; ES:DX - адрес обработчика.
- int 33h
- mov ah, 0 ; Ожидание нажатия любой клавиши.
- int 16h
- mov ax, 000Ch
- mov cx, 0000h ; Удалить обработчик событий мыши.
- int 33h
- mov ax, 3 ; Текстоый режим.
- int 10h
- ret ; Конец программы.
- ; Обработчик событий мыши: при первом нажатии выводит точку на экран,
- ; при каждом дальнейшем вызове проводит прямую линию от предыдущей
- ; точки к текущей.
- handler:
- push 0A000h
- pop es ; ES - начало видеопамяти.
- push cs
- pop ds ; DS - сегмент кода и данных этой программы.
- push cx ; CX (X-координата) и DX(Y-координата)
- push dx ; потребуются в конце.
- mov ax, 2 ; Спрятать курсор мыши перед выводом на экран.
- int 33h
- cmp word ptr previous_X, -1 ; Если это первый вызов,
- je first_point ; только вывести точку.
- call line_bresenham ; Иначе - провести прямую.
- exit_handler:
- pop dx ; Восстановить CX и DX
- pop cx
- mov previous_X, cx ; и запомнить их как предыдущие
- mov previous_Y, dx ; координаты.
- mov ax, 1 ; Показать курсор мыши.
- int 33h
- retf ; Выход из обработчика - команда RETF.
- first_point:
- call putpixellb ; Вывод одной точки (при первом вызове).
- jmp short exit_handler
- ; Процедура рисования прямой линии с использованием алгоритма Брезенхама.
- ; Вывод CX, DX - X, Y начальной точки.
- ; previous_X, previous_Y - X, Y начальной точки.
- line_bresenham:
- mov ax, cx
- sub ax, previous_X ; AX = длина проекции прямой на ось X.
- jns dx_pos ; Если AX отрицательный -
- neg ax ; сменить его знак, причем
- mov word ptr X_increment, 1 ; координата X при выводе
- jmp short dx_neg ; прямой будет расти.
- dx_pos: mov word ptr X_increment, -1 ; Иначе - уменьшаться.
- dx_neg: mov bx, dx
- sub bx, previous_Y ; BX = длина проекции прямой на ось Y.
- jns dy_pos ; Если BX отрицательный -
- neg bx ; сменить его знак, причем
- mov word ptr Y_increment, 1 ; координата Y при выводе
- jmp short dy_neg ; прямой будет расти.
- dy_pos: mov word ptr Y_increment, -1 ; иначе - уменьшаться.
- dy_neg:
- shl ax, 1 ; Удвоить значения проекций,
- shl bx, 1 ; чтобы избежать работы с полуцелыми числами.
- call putpixellb ; Вывести первую точку (прямая рисуется от
- ; CX, DX к previous_X, previous_Y).
- cmp ax, bx ; Если проекция на ось X больше, чем на Y,
- jna dx_le_dy
- mov di, ax ; DI будет указывать, в какую сторону мы
- shr di, 1 ; отклонились от идеальной прямой.
- neg di ; Оптимальное начальное значение DI:
- add di, bx ; DI = 2 * dy - dx
- cycle:
- cmp cx, word ptr previous_X ; Основной цикл выполняется,
- je exit_bres ; пока X не станет равное previous_X.
- cmp di, 0 ; Если DI > 0,
- jl fractlt0
- add dx, word ptr Y_increment ; перейти к следующему Y
- sub di, ax ; и уменьшить DI на 2 * dx.
- fractlt0:
- add cx, word ptr X_increment ; Следующий X (на каждом шаге).
- add di, bx ; Увеличить на DI на 2 * dy.
- call putpixellb ; Вывести точку. ;!!!!!
- jmp short cycle ; Продолжить цикл.
- dx_le_dy: ; Если проекция на ось Y больше, чем на X.
- mov di, bx
- shr di, 1
- neg di ; Оптимальное начальное значение DI:
- add di, ax ; DI = 2 * dx - dy.
- cycle2:
- cmp dx, word ptr previous_Y ; Основной цикл выполняется,
- je exit_bres ; пока Y не станет равным previous_Y.
- cmp di, 0 ; Если DI > 0,
- jl fractlt02
- add cx, word ptr X_increment ; перейти к следующему X
- sub di, bx ; и уменьшить DI на 2 * dy,
- fractlt02:
- add dx, word ptr Y_increment ; Следующий Y (на каждом шаге).
- add di, ax ; Увеличить DI на 2 * dy,
- call putpixellb ; вывести точку,
- jmp short cycle2 ; продолжить цикл.
- exit_bres:
- ret ; Конец процедуры.
- ; Процедура вывода точки на экран в режиме, использующем один бит для
- ; хранения одного пикселя.
- ; DX = строка, CX = столбец.
- ; Все регистры сохраняются.
- putpixellb:
- pusha ; Сохранить регистры.
- xor bx, bx
- mov ax, dx ; AX = номер строки.
- imul ax, ax, 80 ; AX = номер строки x число байтов в строке.
- push cx
- shr cx, 3 ; CX = номер байта в строке.
- add ax, cx ; AX = номер байта в видеопамяти.
- mov di, ax ; Поместить его в SI и DI для команд
- mov si, di ; строковой обработки.
- pop cx ; CX снова содержит номер столбца.
- mov bx, 0080h
- and cx, 07h ; Последние три бита CX =
- ; остаток от деления на 8 = номер бита в байте
- ; считая справа налево.
- shr bx, cl ; Теперь в BL установлен в 1 нужный бит.
- lods es: byte ptr some_label ; AL = байт из видеопамяти.
- ;or ax, bx ; Установить выводимый бит в 1,
- ; Чтобы стереть пиксел с экрана, эту команду OR можно заменить на
- not bx
- and ax, bx
- ; или лучше инициализировать BX не числом 0080h, а числом FF7Fh и использовать
- ; только and
- stosb ; И вернуть байт на место.
- popa ; Восстановить регистры.
- ret ; Конец.
- previous_X dw -1 ; Предыдущая X-координата.
- previous_Y dw -1 ; Предыдущая Y-координата.
- Y_increment dw -1 ; Направление изменения Y.
- X_increment dw -1 ; Направление изменения X.
- some_label: ; Метка, используемая для переопределения
- ; сегмента-источника для lods с DS на ES.
- end start
Решение задачи: «Компиляция com программы»
textual
Листинг программы
- tasm MyProg.asm
- tlink /Tdc MyProg.obj
Объяснение кода листинга программы
tasm
: это команда компилятора Assembler, поддерживаемого Borland Turbo Assembler (TASM).MyProg.asm
: это имя исходного файла Assembler, который будет скомпилирован.tlink
: это команда линковщика для создания исполняемого файла./Tdc
: это флаг командной строки, указывающий линковщику использовать определенный формат исполняемого файла.MyProg.obj
: это имя объектного файла, который будет использоваться в процессе линковки.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д