So I started learning assembly and am writing a simple OS with FASM. I have a blue screen with a gray top bar and a cursor but can't get text to appear on a line. On the top line I want it to say "FILE SYSTEM" and then on other lines I want other stuff. I'll put the code here:
mov ax, 9ch
mov ss, ax
mov sp, 4096d
mov ax, 7c0h
mov ds, ax
;----------------
;this sets blue to background
mov ah, 09h
mov cx, 1000h
mov al, 20h
mov bl, 17h
int 10h
;end of blue
;start of gray top
mov ah, 09h
mov cx, 80d
mov al, 20h
mov bl, 87h
int 10h
;end of gray
;top bar
;end of top bar
;define mouse
mov ah, 01h
mov cx, 07h
int 10h
mov bl, 5h
mov cl, 5h
_mouser:
mov ah, 02h
mov dl, bl
mov dh, cl
int 10h
mov ah, 00h
int 16h
cmp al, 77h
je _up
cmp al, 73h
je _down
cmp al, 61h
je _left
cmp al, 64h
je _right
cmp al, 20h
je _click
jmp _mouser
_click:
mov ah, 0eh
mov al, 0b2h
int 10h
jmp _mouser
_up:
cmp cl, 0h
je _mouser
sub cl, 1h
jmp _mouser
_down:
cmp cl, 24d
je _mouser
add cl, 1h
jmp _mouser
_left:
cmp bl, 0h
je _mouser
sub bl, 1h
jmp _mouser
_right:
cmp bl, 79d
je _mouser
add bl, 1h
jmp _mouser
;----------------
times 510-($-$$) db 0
dw 0xAA55
i have tried
mov ah, eoh
mov al, 'F'
int 10h
problem is that can only make a single character not a string.
The PC's ROM BIOS provides a set of video services, invoked via interrupt 10h, including some that print characters to the string. Comprehensive documentation for them can be found here.
It seems you have already discovered service 0Eh, which writes a single character to the screen at the current character position and advances the character position. This treats the screen as if it were a teletype (TTY), and makes it very easy to get output on the screen.
(At least, it looks like you were trying to invoke service 0Eh. Your code wasn't correct. You had mov ah, eoh
, which isn't correct. o
isn't a hexadecimal value, and even if that was a typo for 0, you have the nibbles reversed. It should be mov ah, 0Eh
.)
If you want to print a string (multiple characters), you essentially have two options:
You can iteratively invoke a service like 0Eh, writing a single character to the string each time. An example implementation of this would be:
mov ah, 0Eh ; service 0Eh: print char as TTY
.PrintNextChar:
mov al, BYTE PTR [si] ; get next character in string, pointed to by SI
inc si ; increment pointer
test al, al ; is character == 0 (end-of-string)?
je .Done
int 10h
jmp .PrintNextChar
.Done
This prints characters from the string pointed to by SI
until it reaches a 0 (NUL character), which signifies the end of the string (a standard C-style NUL-terminated string).
However, this print-one-character-at-a-time method is relatively slow. Instead, one usually prefers to…
Use service 1300h or 1301h to print an entire string at once. The difference is that service 1301h advances the cursor after printing the string, whereas service 1300h doesn't change the cursor. Otherwise, they are the same.
The parameters for these services are documented in the link above; reprinted here for convenience:
AX
== 1300h/1301hBL
== video attribute (in text mode, specifies foreground and background colors)BH
== video page (usually 0)CX
== length of stringDL
/DH
== column/row of starting position for stringES:BP
== address of beginning of string
Obviously this requires that you know the length of the string in advance, and pass it in as a parameter in the CX
register. The string is pointed to by ES:BP
.
In your case, to print "FILE SYSTEM", you would declare an array of characters in your DATA segment that contained this string, then do something like:
MyString DB "FILE SYSTEM"
mov ax, ds
mov es, ax ; set ES == DS
mov bp, MyString
mov cx, 11 ; length of string (number of chars)
mov bx, 07h ; foreground & background color (white on black)
xor dx, dx ; starting position (top-left)
mov ax, 1301h ; service 1301h: print string and update cursor
int 10h