Page 1 of 1

Non-functional PrintString? [Solved]

Posted: Fri Apr 03, 2009 5:07 am
by SamW
Hi all,

First off - an apology. I'm sorry to be yet another stuck newbie coming and asking for your time, but I've been working at this for awhile now and I don't appear to be going anywhere so I could really do with a second opinion.

I'm attempting to write a real mode bootstrap. I've made a few boot sectors before and got to the point of reading keyboard input but in those effects I must admit I had used copy and pasted code. Code that I understood but c&p'd not the less.

Currently my code sits as follows:

Code: Select all

[BITS 16]
ORG 0			;Setup at start of memory

MOV AH, 07h
INT 10h			;Clear Screen

MOV SI, WELCOME
MOV BL, 07h		;Colour set 7
MOV BH, 00h		;Page 0
CALL PRINTSTRING	;Print it!

JMP $

PRINTCHAR:			;AL=CHAR, BL=COLOUR, BH=PAGE#

MOV AH, 09h
MOV CX, 1h
INT 10h
RET

PRINTSTRING:			;SI=STRING, BL=COLOUR, BH=PAGE#

MOV AL, [SI]		;Move current character of string into AL
CMP AL, 0		;Is it 0?
JNZ .EXIT		;If so, exit
CALL PRINTCHAR		;Print current Char
INC SI			;Move the pointer one character forward in the string
JMP PRINTSTRING		;Repeat

.EXIT:
RET			;Leave procedure

WELCOME db 'Hello World', 0

TIMES 510-($-$$) db 0	;fill the rest with 0s
DW 0xAA55		;Bootsector stamp	
The output of this is a cleared screen and the cursor underscore, nothing else.

Editing the code to test the PRINTCHAR function results in a correctly printed character, giving the impression the fault is not with that but with the PRINTSTRING function.

Any ideas would be greatfully received, thanks
Sam

EDIT:

Forgot to mention it's nasm code, compiled with:

nasm BOOTSTRAP.asm -f bin -o boot.bin

Then virtualized with VirtualBox. Thanks.

Re: Non-functional PrintString?

Posted: Fri Apr 03, 2009 5:39 am
by djmauretto
Add this line at start of code:

Code: Select all

mov ax,7c0h
mov ds,ax
and remember to setup stack :wink:

Re: Non-functional PrintString?

Posted: Fri Apr 03, 2009 6:30 am
by SamW
Ok, still no luck, but thanks for the reply.

The code now stands at this;

Code: Select all

[BITS 16]
ORG 0			;Setup at start of memory

MOV ESP, 0x105000  	;Set the stack pointer

mov ax,7c0h		;Initialise DS register

mov ds,ax

MOV AH, 07h
INT 10h			;Clear Screen

MOV SI, WELCOME
MOV BL, 07h		;Colour set 7
MOV BH, 00h		;Page 0
CALL PRINTSTRING	;Print it!

JMP $



PRINTCHAR:			;AL=CHAR, BL=COLOUR, BH=PAGE#

MOV AH, 09h
MOV CX, 1h
INT 10h
RET


PRINTSTRING:			;SI=STRING, BL=COLOUR, BH=PAGE#


MOV AL, [SI]		;Move current character of string into AL
CMP AL, 0		;Is it 0?
JNZ .EXIT		;If so, exit
CALL PRINTCHAR		;Print current Char
INC SI			;Move the pointer one character forward in the string
JMP PRINTSTRING		;Repeat

.EXIT:
RET			;Leave procedure



WELCOME db 'Hello World', 0

TIMES 510-($-$$) db 0	;fill the rest with 0s
DW 0xAA55		;Bootsector stamp
Same symptoms as before. Any ideas?

Also, I looked though some of my old code and I realised that I'd been writing directly to the screen before - I don't think I've ever got AH=09h working :(

Thanks, Sam

Re: Non-functional PrintString?

Posted: Fri Apr 03, 2009 7:15 am
by djmauretto
Try This:

Code: Select all

[BITS 16]
ORG 0  


Start:

	CLI
	XOR	AX,AX
	MOV	SS,AX
	XOR	AX,7C0H
	MOV	DS,AX
	SHL	AX,4
	MOV	SP,AX
	STI

	MOV	AX,0003H
	INT	10H

	MOV	SI,WELCOME
	CALL	PRINTSTRING

@@:
	STI
	HLT
	JMP	@B

PRINTSTRING:

	LODSB     
	TEST	AL,AL      
	JZ 	.EXIT      
	CALL 	PRINTCHAR            
	JMP 	PRINTSTRING    
.EXIT
	RET  

PRINTCHAR:         

	MOV 	AH,0EH
	MOV	BX,7
	INT 	10H
	RET

	DB 0C4H,0C4H

WELCOME db 'Hello World', 0

TIMES 510-($-$$) db 0   
DW 0xAA55  

Re: Non-functional PrintString?

Posted: Fri Apr 03, 2009 7:29 am
by Zenith
Okay, here goes:

Code: Select all

[BITS 16]
ORG 0         ;Setup at start of memory
MOV ESP, 0x105000     ;Set the stack pointer
mov ax,7c0h      ;Initialise DS register
mov ds,ax
First, get rid of using ESP and addressing above 0x100000. Won't work in real mode because addressing in real mode doesn't recognize the value in ESP, just the value in SP.

Second, it is usually better in the long run to set all your segment selectors to 0, and change the ORG to 0x7c00. And without proper (and hopefully equal) values in DS, ES, and SS (in this case, the proper values for these would be 0), addressing using SI will not work safely.

Code: Select all

MOV AH, 07h
INT 10h ;Clear Screen
According to Ralph Brown's Interrupt List, that interrupt is to scroll down the window (and you haven't defined any of the other input values, either). Best solution to clearing the screen is to either reset the video mode with Int 10/AH=00h or zero out the video buffer in memory.

Code: Select all

MOV AH, 09h
MOV CX, 1h
INT 10h
Instead of using Int 10/AH=09h, you may wish to consider Int 10/AH=0Eh which is what most people use in real mode (or just write into video memory directly).

And the big kicker, in your printstring function:

Code: Select all

cmp al, 0
jnz .exit
That is telling the computer to jump when AL is NOT 0. Which means it never ever gets to call printchar :)

Using your code as a base, this is how I would implement it:

Code: Select all

[BITS 16]
ORG 0x7c00         ; Put all offsets at 0x7c00

xor ax, ax    ; Set AX to 0
mov ds, ax   ; Initialize segment selectors
mov es, ax   ; If you want, you can also initial fs and gs
mov ss, ax
mov sp, 0x7c00 ; Why don't we just place the stack at 0x7c00, so it works downward from that

mov al, 3     ; AH is already 0, change video mode to text mode 3 
int 10h       ; Reset video mode, clearing screen as well

mov si, welcome
call printstring  ;Print it!

jmp $

printstring:
mov ah, 0Eh   ; Set interrupt to teletype output
mov bx, 0Fh    ; Set foreground color to white, page to 0
.print:
lodsb             ; Move current character of string into AL, increment SI
or al, al         ; Is AL 0?
jz .exit           ;If so, exit
int 10h
jmp .print      ;Repeat
.exit:
ret

welcome db 'Hello World',0

TIMES 510-($-$$) db 0   ;fill the rest with 0s
DW 0xAA55      ;Bootsector stamp
Disclaimer: Haven't tested the above code.

You seem like you've done really well, implementing that yourself without much prior knowledge of assembly. Since you've shown some initiative in learning, I hope you do well. Do some more research, get more practice at assembly, and make sure to understand my explanations above.

Good luck! :)

Re: Non-functional PrintString?

Posted: Fri Apr 03, 2009 7:50 am
by SamW
Thanks alot for that response!

I have got time to try all that out now, but I understand the points you made and as soon as I finish work I'll go and try those out.

Your help is greatly appreciated :), will report back later.

Sam

Re: Non-functional PrintString?

Posted: Fri Apr 03, 2009 8:46 am
by Troy Martin
Real mode assembly bare bones is my tutorial that accomplishes a small kernel and shell in a boot sector, so you could build off of that if you want.

Re: Non-functional PrintString?

Posted: Fri Apr 03, 2009 8:49 am
by SamW
Thanks alot for all the replys, that works brilliantly :) (and I understand it too :) )

Now onto int 13h :)

Thanks again to everyone,

Sam