Reputation: 10701
I'm trying to write some ASM code that will write some text to the display using BIOS interrupts. This code will run from the boot sector.
I have
msgText DB "Hello" ;Text
msgCol DB 0x07,0x08,0x09,0x0A,0x0B ;Colours
msgXY DW 0x0E26 ;Col/Row
msgLen DB 0x05 ;Length
The message is just "Hello", each letter having a different colour. The position of the message on the screen is roughly in the middle, and it has a length of 5.
I want to write a function that will write any message/colour/xy/length to the screen, but for now, let's focus on this one.
print:
MOV AH,0x02 ;Tell BIOS we want to set the cursor position
MOV DX,[msgXY] ;Tell BIOS where the cursor should go
INT 0x10 ;Call BIOS video interrupt
XOR ECX,ECX ;Clear ECX
MOV CX,[msgLen] ;Set CX = msgLen
MOV AH,0x0E ;We want to print characters on the screen
_loop:
MOV EDX,msgText ;Move address of text to EDX
DEC ECX ;Temporarily decrement ECX
ADD EDX,ECX ;Add ECX to the address of msgText
INC ECX ;Increment ECX back to what it was
MOV AL,BYTE[EDX] ;Put the contents of the memory at EDX into AL
MOV EDX,msgCol ;Move address of text colour to EDX
DEC ECX ;Temporarily decrement ECX
ADD EDX,ECX ;Add ECX to the address of msgCol
INC ECX ;Increment ECX back to what it was
MOV BL,BYTE[EDX] ;Put the contents of the memory at EDX into BL
INT 0x10 ;Call BIOS video interrupt
LOOP _loop
RET
Now, I should be able to call this with CALL print
.
(yes, I know this prints "Hello" backwards, I'm not worried about that. I can just store it in memory as "olleH", I don't care - I've got much bigger problems)
First of all, the line where I set CX
to [msgLen]
causes problems. I've had to hardcode it to make CX
equal to 0x05
and I'm not sure why.
Secondly, presumably for the same reason, when I try to set the colour code I have the same problem as the text length. If I get rid of those lines and just hardcode MOV BL,0x0C
, then it works fine.
Oddly, however, the MOV DX,[msgXY]
part seems to work OK.
I can't give any exact problems, because I've been trying to fix this for hours by changing lots of thing, and little things I change here and there seem to have very unpredictable results. Furthermore, calling various BIOS interrupts seems to change some of the registers, which is very annoying. Also, when I push stuff down onto the stack and pop it back out later, it's different, so I've been avoiding PUSH
and POP
altogether.
By the way, I'm still in real mode x86 at this stage.
Surely what I'm doing can't be this hard. Maybe I just need a coffee. Or some help? :)
Upvotes: 1
Views: 2601
Reputation: 36
You Can Use This Code:
mov si,msg_text
call print_colored
print_colored:
.loop:
lodsb
cmp al,0
je .done
inc bl
mov ah,0x0E
Int 0x10
jmp .loop
.done:
ret
It makes your String colored but not for your choice.
Upvotes: 0
Reputation: 1452
Well, "first of all", you've defined msgLen
as db
. When you mov cx, [msgLen]
, you load two bytes. Whether this causes a problem depends on what (if anything) is after msgLen
. Either define msgLen
as dw
, or do mov cl, [msgLen]
(since you've got the upper bits cleared).
I don't see a similar problem with "Secondly" - you're moving a byte into an 8-bit register. Seems strange that you're using 32-bit registers in this section. "Should" work, but it bloats up your code a bit. [dx]
is not a valid 16-bit addressing mode, of course - you'd have to use bx
(which is being used for other purposes), si
, or di
. Since you are using 32-bit registers, lea edx, [edx + ecx - 1]
should do what you want without temporarily decrementing and incrementing ecx
. (but I don't think that'll help your problem)
It is expected that certain BIOS interrupts would alter registers. Whether it's weird or not depends on which interrupts are doing it. Mostly they don't. Not being able to pop
the same value you push
ed is weird. Either you've discovered a CPU bug or you're doing something wrong. Guess which is more likely. :) They're useful instructions, so it's a shame not to be able to use 'em. You don't show "act I" of your bootsector, where you initialize ds
and es
and set up a sensible stack - perhaps there's a problem there?
Have you looked at int 10h/13h? I think it'll do what you want ("rainbow" text). It's a weird interrupt, in that it expects the text address to be in es:bp
, but useful. Another approach is to poke character and color directly to "screen memory" at B800h:xxxx - one byte for character and one byte for color.
A bootsector isn't particularly easy to write. If you've got real dos available (or even Dosbox), it may help to "try out" your routines as part of a .com file (where DEBUG is available). A bootsector is a different environment from dos, so it won't solve all your problems, but may help to narrow it down.
Coffee may help, but mostly... Courage!
Best, Frank
Upvotes: 2