Изменение цветас строк при нажатии PrintScreen в ассемблере tasm

Нужна помощь с кодом, строки просто не выводятся при запуске, не говоря уже о изменении цвета. Вот код:

.model small
.stack 100h

.data
    msg1 db 'This program is designed to display lines on the screen', 0
    msg2 db 'And their color changes when you press PrintScreen', 0
    msg3 db 'By changing their attribute in a cycle from 1 to 15', 0
    msg4 db 'Each press of Print Screen changes the attribute', 0
    attribute db 14
    msg1_len = $ - msg1
    msg2_len = $ - msg2
    msg3_len = $ - msg3
    msg4_len = $ - msg4
    OLD_CS dw ? ; адрес сегмента старого вектора 1Сh
    OLD_IP dw ? ; адрес смещения старого вектора 1Сh


.code

mCLS macro
    push ax ; Сохранение регистров, используемых в макросе, в стек
    push bx
    push cx
    push dx

    mov ah, 10h
    mov al, 3h
    int 10h ; Включение режима видеоадаптора с 16-ю цветами
    mov ax, 0600h ; ah = 06 - прокрутка вверх
            ; al = 00 - строки появляются снизу и заполняются нулями
    mov bh, 00011110b ; 0001 - синий (фон), 1110 - желтый (текст)
    mov cx, 0000b ; ah = 00 - строка верхнуго левого угла
            ; al = 00 - столбец верхнего левого угла

    mov dx, 184Fh ; dh = 18h - строка нижнего правого угла
        ; dl = 4Fh - столбец нижнего правого угла
    int 10h ; Очистка экрана и установка цветов фона и текста

    mov dx, 0 ; dh - строка, dl - столбец
    mov bh, 0 ; Номер видео-страницы
    mov ah, 02h ; 02h - функция установки позиции курсора
    int 10h ; Устанавливаем курсор на позицию (0, 0)

    pop dx ; Перенос сохранённых значений обратно в регистры
    pop cx
    pop bx
    pop ax

endm mCLS

ChangeAttribute macro attribute1
        cmp attribute, 15
            je resetattribute
        cmp attribute, 15 
            jne incremattribute

        resetattribute:
            mov attribute1, 1
        incremattribute:
            INC attribute1
 endm ChangeAttribute

 NEW_5 proc far 
        push ax     
        push bx
        push cx
        push dx
        push ds
        push es

        mov ax, @data
    mov ds, ax              ; Don't forget to initialize DS!
    mov es, ax              ; Segment needed for Int 10h/AH=13h

    ChangeAttribute attribute

    lea bp, msg1            ; ES:BP = Far pointer to string
    mov cx, msg1_len        ; CX = Length of string
    mov bl, attribute               ; green 
    call print

    lea bp, msg2            ; ES:BP = Far pointer to string
    mov cx, msg2_len        ; CX = Length of string
    mov bl, attribute               ; blue 
    call print

    lea bp, msg3            ; ES:BP = Far pointer to string
    mov cx, msg3_len        ; CX = Length of string
    mov bl, attribute                ; red 
    call print 
    
    lea bp, msg4            ; ES:BP = Far pointer to string
    mov cx, msg4_len        ; CX = Length of string
    mov bl, attribute                ; red 
    call print 

    back:
        pop es             
        pop ds
        pop dx
        pop cx  
        pop bx
        pop ax
        iret   
NEW_5  endp

print PROC                  ; Arguments:
                            ;   ES:BP   Pointer to string
                            ;   CX      Length of string
                            ;   BL      Attribute (color)

    push cx                 ; Save CX (needed for Int 10h/AH=13h below)
    mov ah, 03h             ; VIDEO - GET CURSOR POSITION AND SIZE
    xor bh, bh              ; Page 0
    int 10h                 ; Call Video-BIOS => DX is current cursor position
    pop cx                  ; Restore CX

    mov ah, 13h             ; VIDEO - WRITE STRING (AT and later,EGA)
    mov al, 1               ; Mode 1: move cursor
    xor bh, bh              ; Page 0
    int 10h                 ; Call Video-BIOS

    ret
print ENDP

   

start:
    mov ax, @data
    mov ds, ax
    mov ax, 0

    ;Очистить экран
    mov ah, 06h
    mov al, 0 ; Значение 0 очищает экран
    int 10h

    ;Вывести строки с атрибутом 14
    mov ah, 09h
    lea dx, msg1
    mov bh, 0 ; Страница
    mov bl, attribute
    int 21h

    lea dx, msg2
    mov ah, 09h
    int 21h

    lea dx, msg3
    mov ah, 09h
    int 21h

    lea dx, msg4
    mov ah, 09h
    int 21h

    ; Перехватить прерывание печати экрана (Int 5h)
    mov ah, 25h
    mov al, 00h
    mov dx, offset NEW_5    
    mov ax, seg NEW_5
    int 15h

    mCLS
    mov dx, OLD_IP
    mov ax, OLD_CS
    mov ds, ax
    mov ah, 25h
    mov al, 1Ch

    mov ax, 4c00h
    int 21h

end start
end

        

Ответы (1 шт):

Автор решения: PRODIGY

Для печати текста в цвете лучше использовать "прямой вывод в видеобуфер", который в TXT-режиме в/адаптера находится в сегменте 0xB800. Для каждого символа в этом буфере отводится по 2-байта: первый = код символа, второй = цвет его фона/текста. У меня нет тасма, поэтому пример привожу на фасме. Перехват прерывания INT-5h не будет работать на вирт.машинах и эмуляторах - нужен только чистый дос. Восстановление вектора(5) здесь упущено:

org  100h       ; *.com file
jmp  start

msg    db  'Hello World! 123456789'  ; строка для вывода,
len    =   $ - msg                   ; ..и её длина.

;//-----------
PrintString:              ; Процедура вывода строк в видео-буфер
       push  es 0xb800    ; сегмент в/буфера,
       pop   es           ; ..в регистре ES.
       xor   di,di        ; смещение в в/буфере = 0 (верхний/левый угол экрана)
       mov   si,msg       ; адрес строки
       mov   cx,len       ; её длина
@@:    lodsb              ; очередной символ из DS:SI
       stosw              ; записать как 2-байта в ES:DI (второй байт с цветом передаётся аргументом)
       loop  @b           ; повторить СХ-раз..
       pop   es           ; восстановить ES
       ret                ;
;//-----------

start: mov   ax,3         ; текстовый режим: 80х25/16 цветов
       int   10h          ;

       mov   ah,0111b     ; цвет символа/фона = серый на чёрном
       call  PrintString  ; зовём процедуру печати оригин строки!

       mov   ax,0x2505    ; перехват прерывания INT-5h
       mov   dx,newInt5   ; адрес нового обработчика
       int   21h          ;

       xor   ax,ax        ; ждать любую клавишу,
       int   16h          ; ..через сервис клавиатуры.
       ret                ; выход из com-программы.

newInt5:                  ; новый обработчик INT-5h "PrintScreen"
       mov   ah,0100b     ; меняем цвет символа = красный на чёрном фоне
       call  PrintString  ; печать!
       iret               ; interrupt return
→ Ссылка