Page 1 of 1

Problem with bootloader

Posted: Tue May 13, 2008 1:57 am
by skapunky
Hi, firstly sorry for my english. i'm spanish

I have a problem with my simple boot loader. I want that it are charged display "skaos", but when y simulated with vmware, see very rare strings :S.

This is the code, is compiled in fasm:

Code: Select all

        org 0x7C00  ; Dirección donde se encuentran las bios.
        use16       ; Usamos modo de 16 bits.

INFO    db "SKAOS"

INI:    MOV AH,00H          ;Configuramos modo video
        MOV AL,03h
        int 10h
        XOR AX,AX           ; AX = 0
        MOV DS,AX           ; DS = AX = 0

        MOV SI,INFO         ; Apuntamos a INFO
        MOV CX,5            ; Metemos en CX valor del string a cargar
VER:    MOV AH,0x0E         ; CARGAMOS 1 CARÃ

Posted: Tue May 13, 2008 2:14 am
by AJ
Hi,

I see you use the segment override [ES:SI] but you don't seem to set the value of ES - it may be that it just contains a junk value initially. You also never seem to terminate your VER loop.

You may like to look at using the instruction LODSB and also NULL terminating your string.

Cheers,
Adam

Posted: Tue May 13, 2008 2:52 am
by skapunky
Hi, thanks for your response.

I use instruction LODSB, but in vmware, i see the first character any.This is the code with lodsb:

Code: Select all

org 0x7C00  ; Dirección donde se encuentran las bios.
	use16	    ; Usamos modo de 16 bits.



INI:	XOR AX,AX	  ; AX = 0
	MOV DS,AX	    ; DS = AX = 0
	MOV SI,INFO	    ; Apuntamos a INFO
	CALL VER

FIN:	JMP FIN 	    ; Salto sobre si mismo

VER:	LODSB		    ; CARGAMOS 1 CARÃ

Posted: Tue May 13, 2008 3:01 am
by AJ
Ok, not much time at the moment, but here's what I use if it's any help:

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	PutString - print a string on the screen		;
;	takes - si: pointer to 0-terminated str	;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PutString:
	mov 	ah,	0x0E	;	TeleType Function
	mov		bh,	0x00	;	Page 0
 	mov 	bl,	0x07	;	Grey on Black

	.nextchar:
	 	lodsb 
	 	or		al,	al
	 	jz		.str_end
	 	int		0x10 
 	jmp .nextchar

	.str_end:
ret
Cheers,
Adam

Posted: Tue May 13, 2008 3:20 am
by skapunky
Thanks, is perfect and the problem is solved, thanks thanks :D .

The code is:

Code: Select all

org 0x7C00  ; Dirección donde se encuentran las bios.
	use16	    ; Usamos modo de 16 bits.



INI:	XOR AX,AX	    ; AX = 0
	MOV DS,AX	    ; DS = AX = 0
	MOV SI,sk_INFO	    ; Apuntamos a INFO
VER:	MOV AH,0EH
	MOV BH,0	  ;pagina 0
	MOV BL,07H	  ;Color blanco sobre negro
NEXT:	lodsb
	OR AL,AL
	JZ FIN
	INT 10H
	JMP NEXT
FIN:

LOP:	JMP LOP 	    ; Salto sobre si mismo

sk_INFO    db 'Sistema operativo SkaOs',0


	times 510- ($-INI)  db 0
	dw 0xAA55
Thanks AJ :D

Posted: Tue May 13, 2008 9:29 am
by svdmeer
This is my print-function:

Code: Select all

; **********************
; *** Function Print ***
; **********************
;
;  Usage: The string must follow directly after the call
;         to the function "Print".
;
;  For example:
;               call Print ; Call printfunction
;               db 'Put your message here...',0
;               nop     ; Program execution continues..
;
Print:       cld             ; Directionflag=0, for lodsb
             pop si          ; ds:si -> string
             push bp         ; BP on stack, buggy bioses
             lodsb           ; Char from string in AL
NextChar:    mov bx,7        ; Color 7 (ordinary light gray)
             mov ah,0x0e     ; Function 0x0e: Teletype output
             int 0x10        ; Call video-BIOS with interrupt 10h
             lodsb           ; Char from string in AL
             or al,al        ; Value 0 ?
             jnz NextChar    ; If not, print this char
             pop bp          ; Restore BP
             push si         ; Put the right value of IP on the stack
             ret             ; Return from function
Instead of pointing SI to the string when calling the function, I have the string directly after the function call in the code. The print-function increases the return-address, so execution of the code continues after the string.

POP SI in the beginning and PUSH SI are doing all the work for geting the address of the string and let de code continue. That are 2 bytes of code. MOV SI,<addr> is 3 bytes of code, so you save one byte. But if you are calling this function twice, you safe another 3 bytes, total 4 bytes. Three times, you save 7 bytes, and so on. I assume you'll call the print-function multiple times, otherwise it isn't efficient to use it as a function.

In a bootsector I take every change to save bytes, because a bootsector is VERY small to read the (beginning of) a file from a FAT12-file system, with support for both legacy int 13h functions and the int 13h extensions.

skapunky wrote:Thanks, is perfect and the problem is solved, thanks thanks :D .

The code is:

Code: Select all

org 0x7C00  ; Dirección donde se encuentran las bios.
	use16	    ; Usamos modo de 16 bits.



INI:	XOR AX,AX	    ; AX = 0
	MOV DS,AX	    ; DS = AX = 0
	MOV SI,sk_INFO	    ; Apuntamos a INFO
VER:	MOV AH,0EH
	MOV BH,0	  ;pagina 0
	MOV BL,07H	  ;Color blanco sobre negro
NEXT:	lodsb
	OR AL,AL
	JZ FIN
	INT 10H
	JMP NEXT
FIN:

LOP:	JMP LOP 	    ; Salto sobre si mismo

sk_INFO    db 'Sistema operativo SkaOs',0


	times 510- ($-INI)  db 0
	dw 0xAA55
Thanks AJ :D
I see you are not using a function call (I think you'll need a function when you like to display both a message and disk-errors).

You can improve your code this way:

Code: Select all

org 0x7C00  ; Dirección donde se encuentran las bios. 
use16       ; Usamos modo de 16 bits. 


INI:    XOR AX,AX       ; AX = 0 
        MOV DS,AX       ; DS = AX = 0 
        MOV SI,sk_INFO  ; Apuntamos a INFO 
        cld             ; just be sure.. 
        lodsb           ; read 1st character 
next:   MOV AH,0EH 
        MOV BX,07H      ; MOV BH,0 and MOV BL,07 in one instruction 
        INT 10H
        lodsb 
        OR AL,AL 
        jnz next 

LOP:    JMP LOP         ; Salto sobre si mismo 

sk_INFO db 'Sistema operativo SkaOs',0 

times 510- ($-INI)  db 0 
        dw 0xAA55
Using an extra LODSB, you can do it without that jump, and BL and BH can be initialized with one MOV BX,.. instruction. I add CLD just to be sure the direction flag is right (LODSB depends on it).

In my version I push BP on stack. 2 valuable bytes, but Ralph Browns interrupt list says some buggy bioses can destroy BP when scrolling the screen (maybe it can occur with those older BIOSes with a lage bunch of PCI-hardware strings so your first string will let the screen scroll). I use BP very often in the bootsector for addressing variabeles in memory with less code.

Posted: Thu May 15, 2008 1:45 am
by jal
svdmeer wrote:You can improve your code this way:
Using an extra LODSB, you can do it without that jump, and BL and BH can be initialized with one MOV BX,.. instruction. I add CLD just to be sure the direction flag is right (LODSB depends on it).
Of course, some more size improvement is possible. For one thing, if we use bx instead of ax to initialize ds, we can save one byte because we only need a mov bh instead of bx. Also, if you do not care for an extra blank to be printed at the end of the string, you can print the terminating zero, then compare. As for initializing ah and bx/bh, I'd do that outside the loop for speed optimization (int 10h shouldn't destroy any registers, except the mentioned bp bug on some old BIOSes). Doing a CLD should not be necessary I think in this case, but I'm not entirely sure all BIOSes leave it reset. So then the code becomes:

Code: Select all

        xor bx,bx
        mov ds,bx
        mov si,sk_info
        mov ah,0eh
        mov bh,7
        cld
next:   lodsb
        int 10h
        or al,al
        jnz next

lop:    jmp lop

sk_info db 'Sistema operativo SkaOs',0

JAL