Компиляция 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 программы - Assembler»

textual
tasm MyProg.asm
tlink /Tdc MyProg.obj

12   голосов, оценка 3.667 из 5


СОХРАНИТЬ ССЫЛКУ