Page 1 of 1

baby steps #2 - bios print

Posted: Sun May 19, 2002 12:39 pm
by crazybuddha
Quick review: (1) boot sector loaded by BIOS is 512 bytes (2) the code in the boot sector of the disk is loaded by the BIOS at 0000:7c00 (3) machine starts in real mode (4) be aware that the CPU is being interrupted unless you CLI
   
    **************
Many (but not all) BIOS interrupts expect DS to be filled with a real-mode segment value. This is why many BIOS interrupts won't work in protected mode. So if you want to use int 10h/ah=0eh to print to the screen, then you need to make sure that your seg:offset for the characters to print is correct.
   
It doesn't matter if you use 0000:7c00 or 07c0:0000, but if you use ORG, you need to be aware of what's happening.

;------------------------
   mov ax, 0x07c0
   mov ds, ax   
      
   mov si, msg
ch_loop:lodsb    
   or al,al ;zero=end of str
   jz hang   ;get out
   mov ah,$0e
   int $10
   jmp ch_loop

hang:
   jmp hang

msg   db 'Welcome to Macintosh', 13, 10, 0      

   times 512-($-$$) db 0
;------------------------


Here's the ORG version. Note that you still need to tell DS what to be

;------------------------

[ORG 0x7c00]

   xor ax, ax ;make it zero
   mov ds, ax   
   
   mov si, msg
ch_loop:lodsb    
   or al,al ;zero=end of str
   jz hang   ;get out
   mov ah,$0e
   int $10
   jmp ch_loop

hang:
   jmp hang

msg   db 'Welcome to Macintosh', 13, 10, 0      

   times 512-($-$$) db 0
;------------------------

New topic: Typically 'procedures' are separated from the code using CALL/RET like he following

;------------------------

[ORG 0x7c00]
   xor ax, ax ;make it zero
   mov ds, ax   
   
   mov si, msg
   call bios_print

hang:
   jmp hang



msg   db 'Welcome to Macintosh', 13, 10, 0      


bios_print:
   lodsb    
   or al,al ;zero=end of str
   jz done   ;get out
   mov ah,$0e
   int $10
   jmp bios_print
done:
   ret

   times 512-($-$$) db 0
;------------------------

For some inexplicable reason, loading SI *then* jumping to the procedure lways bugged me. Fortunately for psychos like me NASM's macros let you retend that you are passing a parameter (macro definition has to go before t's being called).

;------------------------
%macro BiosPrint 1
mov si, word %1
ch_loop:lodsb
   or al,al ;zero=end of str
   jz done   ;get out
   mov ah,$0e
   int $10
   jmp ch_loop
done:
%endmacro

[ORG 0x7c00]

   xor ax, ax ;make it zero
   mov ds, ax   
   
   BiosPrint msg

hang:
   jmp hang

msg   db 'Welcome to Macintosh', 13, 10, 0      

   times 512-($-$$) db 0
;------------------------

And in case your code is becoming long and unreadable, you can break it up into ifferent files, then include the files at the beginning of your main code. Like o:

;------------------------

   jmp main

   %include "othercode.inc"

main:
   ;... rest of your code here

;------------------------

Re:baby steps #2 - bios print

Posted: Sun May 19, 2002 8:34 pm
by ASHLEY4
Thanks crazybuddha,I for one found them interesting and look forward to the next installment ;D

\\\///
(@@)
ASHLEY4.

Re:baby steps #2 - bios print

Posted: Tue May 27, 2003 2:19 pm
by TriDix
I'm a newbie OS developer (and new to asm too ;D), but reading the nasm docu I believe it would be better to use macro-local lables, so you can use the macro more than once:

; Define macro with one Argument
%macro BiosPrint 1
; Set si to string address
mov si, word %1

%%ch_loop:

; Load byte-string from si (esi in 32 bit mode)
lodsb

; Check for null byte
or al, al
jz done

; Invoke bios-interrupt
mov ah, 0x0E
int 0x10

jmp %%ch_loop

%%done:

%endmacro

Have fun,

TriDix

Btw. Nice snippets crazybuddha!