The MASM Forum

Miscellaneous => 16 bit DOS Programming => Topic started by: ewok on July 21, 2014, 04:56:24 AM

Title: bootloader
Post by: ewok on July 21, 2014, 04:56:24 AM
Hello,
i've took a NASM code example and fixed it for MASM32, here it is:
code segment use16
assume cs:code
org 7c00h

start:
; Main program
main: ; Label for the start of the main program

mov ax,0000h ; Setup the Data Segment register
; Location of data is DS:Offset
mov ds,ax ; This can not be loaded directly it has to be in two steps.
; 'mov ds, 0000h' will NOT work due to limitations on the CPU

mov si,offset HelloWorld ; Load the string into position for the procedure.
call PutStr ; Call/start the procedure

jmp $ ; Never ending loop

; Procedures
PutStr: ; Procedure label/start
; Set up the registers for the interrupt call
mov ah,0Eh ; The function to display a chacter (teletype)
mov bh,00h ; Page number
mov bl,07h ; Normal text attribute

nextchar: ; Internal label (needed to loop round for the next character)
lodsb ; I think of this as LOaD String Block
; (Not sure if thats the real meaning though)
; Loads [SI] into AL and increases SI by one
; Check for end of string '0'
or al,al ; Sets the zero flag if al = 0
; (OR outputs 0's where there is a zero bit in the register)
jz return ; If the zero flag has been set go to the end of the procedure.
; Zero flag gets set when an instruction returns 0 as the answer.
int 10h ; Run the BIOS video interrupt
jmp nextchar ; Loop back round to the top
return: ; Label at the end to jump to when complete
ret ; Return to main program

; Data
HelloWorld db 'Hello World',13,10,0

db 510-($-start) dup(0)  ; Fill the rest of the sector with zero's
dw 0AA55h ; Add the boot loader signature to the end

code ends
end start

Did someone know how can i 'center' the hello world on the screen ?

Regards
Title: Re: bootloader
Post by: Vortex on July 21, 2014, 05:14:52 AM
The fastest solution is to add leading space characters to your string.
Title: Re: bootloader
Post by: KeepingRealBusy on July 21, 2014, 05:18:15 AM
ewok

Because SI is a pointer register. You need to load it with a pointer to the string:


mov si,OFFSET HelloWorld


If "HellowWorld" was a parameter to a function call, then you would need:


mov si,ADDRESS HelloWorld


To center the data you need to get the width of the screen less the length of the string, divide by 2, then print a string of blank characters before printing the message. Cheat, create a string of blanks (without the null terminator) immediately in front of the desired string, then pass the offset of the string less the half centering size.

Dave.
Title: Re: bootloader
Post by: dedndave on July 21, 2014, 05:39:55 AM
the function you want is INT 10h, AH=2
;AH=2, BH = Page Number, DH = Row, DL = Column
    mov     bh,0
    mov     dx,23h
    mov     ah,2
    int     10h


it should be smaller than 35 spaces   :P

you can calculate, as Dave suggested.....
;AH=2, BH = Page Number, DH = Row, DL = Column
    mov     bh,0
    mov     dx,(80-sizeof HelloWorld-3)/2   ;-3 to ignore CR/LF/null
    mov     ah,2
    int     10h
Title: Re: bootloader
Post by: Gunther on July 21, 2014, 08:37:30 AM
And welcome to the forum, ewok.

Gunther
Title: Re: bootloader
Post by: ewok on July 21, 2014, 10:59:07 AM
Thanks for the heads-up guys, and thanks Gunther :)
@dedndave, when i put you code looks like i'm having difficulty (that compile fine but when i boot, i've no text printed, at least seem AH=2 is the problem)
If dl is for column what are dx for ? he have the same role as dl ?
Also, there is a standard resolution for the height on dh ? (like 80?)

Regards
Title: Re: bootloader
Post by: dedndave on July 21, 2014, 12:26:55 PM
function AH=2 sets the cursor position - it does not display any text
so - you want to set the position, then display the text

DL, DH, DX, EDX are all different ways to access the same register
EDX is a 32-bit register
DX is the lower 16 bits (word) of that same register
the High and Low bytes of DX may be accessed via DH and DL
EAX, EBX, and ECX are similar

so - we set the column in DL, and the row in DH to 0 - both by setting DX
normally, there are 80x25 char cells - unless it's set up to boot in 40x25 mode
as i recall, the original PC's and XT's had a DIP switch setting for startup mode
that way, if the user had a TV connected to the CGA composite output, it was legible

(http://www.c-jump.com/CIS77/asm_images/gp_registers.jpg)
Title: Re: bootloader
Post by: dedndave on July 21, 2014, 12:35:09 PM
this loop is a bit questionable
the reason i say that is - some BIOS may not preserve the contents of AX and BX across the call

PutStr: ; Procedure label/start
; Set up the registers for the interrupt call
mov ah,0Eh ; The function to display a chacter (teletype)
mov bh,00h ; Page number
mov bl,07h ; Normal text attribute

nextchar: ; Internal label (needed to loop round for the next character)
lodsb ; I think of this as LOaD String Block
; (Not sure if thats the real meaning though)
; Loads [SI] into AL and increases SI by one
; Check for end of string '0'
or al,al ; Sets the zero flag if al = 0
; (OR outputs 0's where there is a zero bit in the register)
jz return ; If the zero flag has been set go to the end of the procedure.
; Zero flag gets set when an instruction returns 0 as the answer.
int 10h ; Run the BIOS video interrupt
jmp nextchar


a better loop might be...

ShowChar:
    mov     bx,7
    mov     ah,0Eh
    int     10h

PutStr:
    lodsb
    or      al,al
    jnz     ShowChar

notice that loop entry is still PutStr   :t