Проблема с массивом и цветным текстом

Я хочу раскрасить некоторые буквы, используя этот процесс:

markText proc
    mov ax,data
    mov ds,ax
    mov es,ax

    mov cx, M
    mov dx, 1
    push dx 
    mov Counter, 0
    mov si, 0
colorText:
    mov  ah,13h ;SERVICE TO DISPLAY STRING WITH COLOR. 
    push ax
    mov al,[CharMas+si]
    cbw
    mov bp, ax;STRING TO DISPLAY.
    inc si
    pop ax
    mov  bh,0 ;PAGE (ALWAYS ZERO).
    mov  bl,Color
    mov L, cx
    xor cx, cx
    mov  cx,1 ;STRING LENGTH.
    mov  dl,0 ;X (SCREEN COORDINATE). 
    mov  dh,b.ColorRepeat ;Y (SCREEN COORDINATE). 
    int  10h ;BIOS SCREEN SERVICES.
    mov cx, L 

    inc ColorRepeat
    loop ColorText

    mov AX,4C00h
    int 21h

markText endp

В моем массиве (CharMas) у меня есть что-то вроде: «a», «b», «c». Но там просто черный пробел вместо цветных букв. Что не так с моим кодом?

P.S. он отлично работает, если я изменяю индекс arr на 0 или 1, например:

mov bp, offset CharMas[0]

person coldembrace    schedule 22.06.2017    source источник
comment
в dseg: CharMas DB 50 dup(13) после заполнения: 'r', 'g', 'u', 'h', 'u', ' ', ' ', ' ', ' ', ' '   -  person coldembrace    schedule 22.06.2017
comment
Попробуйте включить в свой вопрос объявление CharMas и b и любую другую полезную вещь.   -  person Jose Manuel Abarca Rodríguez    schedule 22.06.2017


Ответы (2)


Для функции BIOS «Запись символьной строки» требуется указатель на выходную строку в ES:BP. Это именно то, что делает ваш "хороший" код:

mov bp, offset CharMas[0]

Однако ваш «плохой» код

mov al,[CharMas+si]
cbw
mov bp, ax

загружает 1 байт из строки в bp. Что вам нужно сделать, так это поместить указатель на этот байт в bp. Вы можете сделать это следующим образом:

mov bp, offset CharMas[0]; now bp is a pointer to the string
add bp, si; now bp is a pointer to a specific byte in the  string

Или на самом деле вы можете использовать только одну инструкцию для этого:

lea bp, CharMas[si]; now bp is a pointer to a specific byte in the  string

Здесь lea — это инструкция загрузить эффективный адрес.

person anatolyg    schedule 22.06.2017
comment
Эта видеофункция 13h BIOS также требует, чтобы AL был установлен для указания подфункции. См. документацию. - person Cody Gray; 23.06.2017

mov  ah,13h ;SERVICE TO DISPLAY STRING WITH COLOR. 

Вы выбрали одну из самых сложных функций BIOS для вывода цветных символов. Более того, вы неправильно используете параметры!

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

 mov si, OFFSET CharMas
 mov cx, 1
 mov bh, 0
 mov bl, color
Again:
 mov ah, 09h
 lodsb               ;Get next character from array
 int 10h             ;Outputs the colored character
 mov ax, 0E0Ah       ;0Ah=Linefeed
 int 10h             ;Advances the cursor to the next line
 cmp byte ptr [si], 0
 jne Again

CharMas  db  'a','b','c',0
person Fifoernik    schedule 22.06.2017
comment
Еще одно отличное решение, я буду иметь его в виду на будущее. Спасибо! - person coldembrace; 22.06.2017
comment
Я не совсем уверен, что согласен с тем, что это более удобно для пользователя. Вам все еще нужно правильно указать параметры, но ваше решение требует гораздо больше кода, не говоря уже о том, что оно медленнее. Все, что вам действительно нужно сделать, это следовать документации, независимо от того, какую функцию вы собираетесь использовать. - person Cody Gray; 23.06.2017
comment
@CodyGray Все тесты, которые я провел в рамках подготовки к сегодняшнему Q/A об отображении символов показывают, что код, представленный Fifoernik, не длиннее и не медленнее. Не забывайте, что OP (ab) использует функцию BIOS WriteString 13h для вывода только одного символа, что приводит к большим накладным расходам BIOS. - person Sep Roland; 25.06.2017
comment
Ну, я думаю, что для одного персонажа. Но я говорил в более общем плане. Действительно ли ваши тесты показали, что этот цикл (и с LODSB из всех вещей) был так же быстр для печати строки средней длины, как и функция BIOS, предназначенная для этого? Я думаю, это возможно, если у вас особенно неэффективная реализация BIOS… Кстати, @Sep, спасибо за подборку вопросов и ответов. Выглядит как отличная каноническая мишень для дублирования всех вопросов об отладке моего текстового вывода, которые мы получаем! - person Cody Gray; 25.06.2017
comment
@CodyGray Если функция BIOS WriteString используется для вывода всей строки всего одним вызовом, ее нельзя превзойти, если задействованная строка достигает определенной длины. Переломным моментом, который я нашел, является 4 символа. - person Sep Roland; 25.06.2017