2

I want to color some letters using this proc:

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

In my array (CharMas) I have got smth like: 'a','b','c'. But there is just a black blank instead of colored letters. What is wrong with my code?

P.S. it works perfect if I change index of arr to 0 or 1, e.g:

mov bp, offset CharMas[0]
coldembrace
  • 549
  • 8
  • 19

2 Answers2

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

You've chosen one of the more difficult BIOS functions to output your colored characters. Moreover you're not using the parameters correctly!

Luckily there's a very much more user friendly function that you can use.

 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
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
Fifoernik
  • 9,779
  • 1
  • 21
  • 27
  • Another great solution, I'll keep it in mind for future. Thanks! – coldembrace Jun 22 '17 at 15:49
  • I'm not really sure I agree that this is any more user-friendly. You still have to get the parameters right, but your solution requires a lot more code, not to mention the fact it is slower. All you really need to do is follow the documentation, no matter which function you're going to use. – Cody Gray - on strike Jun 23 '17 at 03:35
  • 1
    @CodyGray All tests I conducted in preparation for [today's Q/A about displaying characters](https://stackoverflow.com/questions/44747002/displaying-characters-with-dos-or-bios/44747003#44747003) show that the code presented by Fifoernik is neither longer nor slower. Don't forget that the OP is (ab)using the BIOS *WriteString* function 13h to output just **a single character**, thereby suffering a big BIOS overhead. – Sep Roland Jun 25 '17 at 14:57
  • Well, I believe that for a single character. But I was speaking more generally. Did your tests actually show that this loop (and with `LODSB` of all things) was equally as fast for printing a moderate-length string as the BIOS function designed to do that? I guess that's possible, if you have a particularly inefficient BIOS implementation… By the way, @Sep, thanks for putting together that Q&A. Looks like an *excellent* canonical dupe target for all of the "debug my text output" questions we get! – Cody Gray - on strike Jun 25 '17 at 15:10
  • @CodyGray If the BIOS *WriteString* function is used to output an entire string with just the one call, it can't be beaten provided the string involved reaches a certain length. The tipping point I found is at 4 characters. – Sep Roland Jun 25 '17 at 15:52
1

The "Write Character String" BIOS function requires a pointer to the output string in ES:BP. This is exactly what your "good" code does:

mov bp, offset CharMas[0]

However, your "bad" code

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

loads 1 byte from the string into bp. What you need to do it put the pointer to that byte into bp. You can do it like this:

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

Or actually you can use just one instruction to do this:

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

Here lea is the load effective address instruction.

anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • 3
    This BIOS video function 13h *also* requires that `AL` be set to specify a sub-function. See [the documentation](http://webpages.charter.net/danrollins/techhelp/0131.HTM). – Cody Gray - on strike Jun 23 '17 at 03:34