Writing to Video Memory

  • Follow


Hi,

I am trying to write a string to the video memory. I can get
individual characters to the screen without a problem, as shown in my
code:

-------------------------------------------------------------------------
START:
  MOV     AX, 0xB800		;Video memory
  MOV     ES, AX		;Move to a segment
  XOR     DI, DI		;Offset (B800:0000)

  MOV     AX, 'T'		;ASCII Character to print
  CALL    WRMEM			;Procedure to write it to memory and set colour
  MOV     AX, 'E'
  CALL    WRMEM
  MOV     AX, 'S'
  CALL    WRMEM
  MOV     AX, 'T'
  CALL    WRMEM

HANG:				;End of program
  JMP HANG

WRMEM:
  STOSB				;Write the byte to memory and INC DI (to the next offset)
  MOV     AX, 7			;Set colour - white on black
  STOSB				;write colour to memory and INC DI
  RET				;Return
----------------------------------------------------------------------------------


The problem is that it is a really stupid way to write a sentence to
the screen. I want to use this in a 'kernel' that is loaded by a boot
loader, which is why I am trying to write directly to video memory.
I have tried 'msg db "message"' and 'mov si, msg' and lodsb, but for
some reason I can't get it to work. Am I on the right track?

0
Reply spamtrap2 (1628) 2/7/2007 2:15:37 AM

On 6 Feb 2007 18:15:37 -0800, "Luke"  <spamtrap@crayne.org> wrote in
comp.lang.asm.x86:

> Hi,
> 
> I am trying to write a string to the video memory. I can get
> individual characters to the screen without a problem, as shown in my
> code:
> 
> -------------------------------------------------------------------------
> START:
>   MOV     AX, 0xB800		;Video memory
>   MOV     ES, AX		;Move to a segment
>   XOR     DI, DI		;Offset (B800:0000)
> 
>   MOV     AX, 'T'		;ASCII Character to print
>   CALL    WRMEM			;Procedure to write it to memory and set colour
>   MOV     AX, 'E'
>   CALL    WRMEM
>   MOV     AX, 'S'
>   CALL    WRMEM
>   MOV     AX, 'T'
>   CALL    WRMEM
> 
> HANG:				;End of program
>   JMP HANG
> 
> WRMEM:
>   STOSB				;Write the byte to memory and INC DI (to the next offset)
>   MOV     AX, 7			;Set colour - white on black
>   STOSB				;write colour to memory and INC DI
>   RET				;Return
> ----------------------------------------------------------------------------------
> 
> 
> The problem is that it is a really stupid way to write a sentence to
> the screen. I want to use this in a 'kernel' that is loaded by a boot
> loader, which is why I am trying to write directly to video memory.
> I have tried 'msg db "message"' and 'mov si, msg' and lodsb, but for
> some reason I can't get it to work. Am I on the right track?

It has been a very long time since I did this, and I'm doing it from
memory, so it might be not quite right, but:

msg:	db 'test
		db 0			; so you know when to stop

write_screen:
	mov	ax, 0b800h
	mov	es, ax
	xor	di, di
	mov	si, msg			; point to string
	mov	ah, 7			; attribute to use, could be from a variable
	cld

write_loop:
	lodsb				; get string character into al
	or	al, al			; check for 0, end of string
	jz	write_done
	stosw				; write character and attribute
	jmp	write_loop

write_done:
	; whatever you want to do next

-- 
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

0
Reply Jack 2/7/2007 6:23:24 AM


Luke wrote:
> Hi,
> 
> I am trying to write a string to the video memory. I can get
> individual characters to the screen without a problem, as shown in my
> code:

[snip]

> The problem is that it is a really stupid way to write a sentence to
> the screen. I want to use this in a 'kernel' that is loaded by a boot
> loader, which is why I am trying to write directly to video memory.
> I have tried 'msg db "message"' and 'mov si, msg' and lodsb, but for
> some reason I can't get it to work. Am I on the right track?

Yes, but it would also help if you showed us the code that didn't work. 
Does it set up DS?

Two unrelated issues are where you set up the direction flag and why you 
always load the entire AX register when you never use AH.


Bjarni
-- 

                        INFORMATION WANTS TO BE FREE

0
Reply Bjarni 2/7/2007 6:41:10 AM

On 7 helmi, 04:15, "Luke"  <spamt...@crayne.org> wrote:
> Hi,
>
> I am trying to write a string to the video memory. I can get
> individual characters to the screen without a problem, as shown in my
> code:
>
> -------------------------------------------------------------------------
> START:
>   MOV     AX, 0xB800            ;Video memory
>   MOV     ES, AX                ;Move to a segment
>   XOR     DI, DI                ;Offset (B800:0000)
>
>   MOV     AX, 'T'               ;ASCII Character to print
>   CALL    WRMEM                 ;Procedure to write it to memory and set colour
>   MOV     AX, 'E'
>   CALL    WRMEM
>   MOV     AX, 'S'
>   CALL    WRMEM
>   MOV     AX, 'T'
>   CALL    WRMEM
>
> HANG:                           ;End of program
>   JMP HANG
>
> WRMEM:
>   STOSB                         ;Write the byte to memory and INC DI (to the next offset)
>   MOV     AX, 7                 ;Set colour - white on black
>   STOSB                         ;write colour to memory and INC DI
>   RET                           ;Return
> ----------------------------------------------------------------------------------
>
> The problem is that it is a really stupid way to write a sentence to
> the screen. I want to use this in a 'kernel' that is loaded by a boot
> loader, which is why I am trying to write directly to video memory.
> I have tried 'msg db "message"' and 'mov si, msg' and lodsb, but for
> some reason I can't get it to work. Am I on the right track?

What about this:

START:
    MOV     AX, 0xB800
    MOV     ES, AX
    XOR     DI, DI

    CALL    WRMEM
HANG:
    JMP HANG

WRMEM:
    mov    si, offset msg
    mov    cx, 4       ; len of msg
    mov    ah, 07h   ; color attr

write:
    lodsb               ; get char from msg and inc si
    stosw              ; write char and attr
    loop    write     ; while there's text
    ret

msg    db    'test'

0
Reply KJH 2/7/2007 6:52:17 AM

Luke wrote:
> Hi,
> 
> I am trying to write a string to the video memory. I can get
> individual characters to the screen without a problem, as shown in my
> code:
> 
> -------------------------------------------------------------------------
> START:
>   MOV     AX, 0xB800		;Video memory
>   MOV     ES, AX		;Move to a segment
>   XOR     DI, DI		;Offset (B800:0000)
> 
>   MOV     AX, 'T'		;ASCII Character to print
>   CALL    WRMEM			;Procedure to write it to memory and set colour
>   MOV     AX, 'E'
>   CALL    WRMEM
>   MOV     AX, 'S'
>   CALL    WRMEM
>   MOV     AX, 'T'
>   CALL    WRMEM
> 
> HANG:				;End of program
>   JMP HANG
> 
> WRMEM:
>   STOSB				;Write the byte to memory and INC DI (to the next offset)
>   MOV     AX, 7			;Set colour - white on black
>   STOSB				;write colour to memory and INC DI
>   RET				;Return
> ----------------------------------------------------------------------------------
> 
> 
> The problem is that it is a really stupid way to write a sentence to
> the screen. I want to use this in a 'kernel' that is loaded by a boot
> loader, which is why I am trying to write directly to video memory.
> I have tried 'msg db "message"' and 'mov si, msg' and lodsb, but for
> some reason I can't get it to work. Am I on the right track?

Yes. You've set es to "screen memory". What about ds? If it's a dos .com 
file, ds will be set to the proper value to find "msg" when dos loads 
it. From boot, this may not be true, unless you've made it so. That's a 
likely cause of the problem. If this is in the bootsector, 0000:7Cxxh or 
07C0h:00xxh should be right (the former if assembled at "org 7C00h"). If 
this is something you've loaded from your bootsector, presumably you 
know where you loaded it...

Best,
Frank

0
Reply Frank 2/7/2007 7:50:31 AM

"Luke"  <spamtrap@crayne.org> writes:

> Hi,
>
> I am trying to write a string to the video memory. I can get
> individual characters to the screen without a problem, as shown in my
> code:
>
> -------------------------------------------------------------------------
> START:
>   MOV     AX, 0xB800		;Video memory
>   MOV     ES, AX		;Move to a segment
>   XOR     DI, DI		;Offset (B800:0000)
>
>   MOV     AX, 'T'		;ASCII Character to print
>   CALL    WRMEM			;Procedure to write it to memory and set colour
>   MOV     AX, 'E'
>   CALL    WRMEM
>   MOV     AX, 'S'
>   CALL    WRMEM
>   MOV     AX, 'T'
>   CALL    WRMEM
>
> HANG:				;End of program
>   JMP HANG
>
> WRMEM:
>   STOSB				;Write the byte to memory and INC DI (to the next offset)
>   MOV     AX, 7			;Set colour - white on black
>   STOSB				;write colour to memory and INC DI
>   RET				;Return
> ----------------------------------------------------------------------------------
>
>
> The problem is that it is a really stupid way to write a sentence to
> the screen. I want to use this in a 'kernel' that is loaded by a boot
> loader, which is why I am trying to write directly to video memory.
> I have tried 'msg db "message"' and 'mov si, msg' and lodsb, but for
> some reason I can't get it to work. Am I on the right track?

Yes, but if you want to copy a memory block to the video RAM like
that, you should either write a function that will copy the string to
a buffer containing each character and its color: 'm',7,'e',7,'s',7,...
or write the string like that in the first place.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

COMPONENT EQUIVALENCY NOTICE: The subatomic particles (electrons,
protons, etc.) comprising this product are exactly the same in every
measurable respect as those used in the products of other
manufacturers, and no claim to the contrary may legitimately be
expressed or implied.

0
Reply Pascal 2/7/2007 10:33:39 AM

On 6 Feb 2007 18:15:37 -0800, "Luke"  <spamtrap@crayne.org> wrote:

>Hi,
>
>I am trying to write a string to the video memory. I can get
>individual characters to the screen without a problem, as shown in my
>code:
>
>-------------------------------------------------------------------------
>START:
>  MOV     AX, 0xB800		;Video memory
>  MOV     ES, AX		;Move to a segment
>  XOR     DI, DI		;Offset (B800:0000)
>
>  MOV     AX, 'T'		;ASCII Character to print
>  CALL    WRMEM			;Procedure to write it to memory and set colour
>  MOV     AX, 'E'
>  CALL    WRMEM
>  MOV     AX, 'S'
>  CALL    WRMEM
>  MOV     AX, 'T'
>  CALL    WRMEM
>
>HANG:				;End of program
>  JMP HANG
>
>WRMEM:
>  STOSB				;Write the byte to memory and INC DI (to the next offset)
>  MOV     AX, 7			;Set colour - white on black
>  STOSB				;write colour to memory and INC DI
>  RET				;Return
>----------------------------------------------------------------------------------
>
>
>The problem is that it is a really stupid way to write a sentence to
>the screen. I want to use this in a 'kernel' that is loaded by a boot
>loader, which is why I am trying to write directly to video memory.
>I have tried 'msg db "message"' and 'mov si, msg' and lodsb, but for
>some reason I can't get it to work. Am I on the right track?
>

I think what you are looking for here is LODSB.  
You first set DS:SI to point to the string you want to
write, just as you now set ES:DI to the destination.
Then your main loop would be:

WRITE_STRING:
    LODSB
    TEST AL,AL
    JZ DONE
    CALL WRMEM
    JMP WRITE_STRING

DONE:

But this can be improved upon, since only AL
is needed to write the character.  So set AH = 7
before the loop, and replace the call to
WRMEM with STOSW.

Note that the test for AL = 0 is an implementation
of the standard method of null-terminated strings.
Alternatively, if you set the length of the string in CX
you could use a conventional LOOP here.

Hope this helps!


Bob Masta
 
            D A Q A R T A
Data AcQuisition And Real-Time Analysis
           www.daqarta.com
Scope, Spectrum, Spectrogram, Signal Generator
    Science with your sound card!

0
Reply NoSpam 2/7/2007 1:36:59 PM

"Luke" <spamtrap@crayne.org> wrote in message 
news:1170814537.308062.165550@h3g2000cwc.googlegroups.com...
> Hi,
>
> I am trying to write a string to the video memory. I can get
> individual characters to the screen without a problem, as shown in my
> code:
>
> -------------------------------------------------------------------------
> START:
>  MOV     AX, 0xB800 ;Video memory
>  MOV     ES, AX ;Move to a segment
>  XOR     DI, DI ;Offset (B800:0000)
>
>  MOV     AX, 'T' ;ASCII Character to print
>  CALL    WRMEM ;Procedure to write it to memory and set colour
>  MOV     AX, 'E'
>  CALL    WRMEM
>  MOV     AX, 'S'
>  CALL    WRMEM
>  MOV     AX, 'T'
>  CALL    WRMEM
>
> HANG: ;End of program
>  JMP HANG
>
> WRMEM:
>  STOSB ;Write the byte to memory and INC DI (to the next offset)
>  MOV     AX, 7 ;Set colour - white on black
>  STOSB ;write colour to memory and INC DI
>  RET ;Return
> ----------------------------------------------------------------------------------
>
>
> The problem is that it is a really stupid way to write a sentence to
> the screen. I want to use this in a 'kernel' that is loaded by a boot
> loader, which is why I am trying to write directly to video memory.
> I have tried 'msg db "message"' and 'mov si, msg' and lodsb, but for
> some reason I can't get it to work. Am I on the right track?

If you can't get it to work you're on the wrong track.
But: the things you tried sound about right. Why didn't it work? You must've 
done something else wrong. Perhaps your DS seg was in some random state (as 
in ES:DI, the correct pair is DS:SI).

By the by. A subroutine to write a single character is not a really stupid 
way, it's just that you usually also should have a subroutine that wraps a 
complete string write :o)

[Jongware] 

0
Reply Jongware 2/7/2007 2:57:00 PM

Thanks for your code, it looks good, but I am having a problem with
the 'mov si, offset msg' line
when I run 'nasm videomem.asm -o loader.bin', it gives the error
'videomem.asm:11: error: comma or end of line expected'.
I have tried removing the 'offset' from the line, and the error goes
away, but then when running the program, it prints random characters
on the screen. Presumably this is because it doesn't have the correct
DS:SI location and is printing random junk from memory.
This is probably really simple, but I don't have enough experience
behind me... any ideas?


Thanks

0
Reply Luke 2/7/2007 11:36:59 PM

In article <1170814537.308062.165550@h3g2000cwc.googlegroups.com>, 
spamtrap@crayne.org says...
> Hi,
> 
> I am trying to write a string to the video memory. I can get
> individual characters to the screen without a problem, as shown in my
> code:

..data
current_x db 0
current_y db 0
current_attr db 7

..data?
columns db ?

putstring proc uses es di
; call with ds:si = address of ASCIIZ string to print out.
; uses:     di, cx, dx
    ; The following section takes a pair of coordinates and figures
    ; out their address.

    mov cx,0b000h       ; First get the video buffer segment.
    mov ah, 0fh
    int 10h
    mov columns,ah
    cmp al, 7
    jz @f
    mov cx, 0b800h
@@:
    mov es,cx

    mov al,current_y
    mov dl,ah
    mul dl
    mov di,ax
    mov al,current_x
    cbw
    add di,ax
    shl di, 1

    ; This next bit actually writes the string to the screen.
    mov ah,current_attr
    lodsb
@@:
    stosw
    lodsb
    test  al,al
    jnz @b

    ; This converts the final address back to a pair of coordinates
    ; and stores them so the next string will immediately follow this
    ; one if the current position isn't repositioned beforehand.
    mov dl, columns
    div dl
    mov current_y, al
    mov current_x, ah
done:
    ret
putstring endp

Note that this code is quite old -- at least in theory, simpler 
sequences would probably be faster on a modern processor. OTOH, the 
speed will usually be limited by the bandwidth to video memory in any 
case, so it may be best to just keep it small.

-- 
    Later,
    Jerry.

The universe is a figment of its own imagination.

0
Reply Jerry 2/8/2007 1:06:22 AM

Jerry Coffin wrote:
> In article <1170814537.308062.165550@h3g2000cwc.googlegroups.com>, 
> spamtrap@crayne.org says...
> 
>>Hi,
>>
>>I am trying to write a string to the video memory. I can get
>>individual characters to the screen without a problem, as shown in my
>>code:
> 
> 
> .data
> current_x db 0
> current_y db 0
> current_attr db 7
> 
> .data?
> columns db ?
> 
> putstring proc uses es di
> ; call with ds:si = address of ASCIIZ string to print out.
> ; uses:     di, cx, dx
>     ; The following section takes a pair of coordinates and figures
>     ; out their address.
> 
>     mov cx,0b000h       ; First get the video buffer segment.
>     mov ah, 0fh
>     int 10h
>     mov columns,ah
>     cmp al, 7
>     jz @f
>     mov cx, 0b800h
> @@:
>     mov es,cx
> 
>     mov al,current_y
>     mov dl,ah
>     mul dl
>     mov di,ax
>     mov al,current_x
>     cbw

Would this work properly in 132-column modes?

>     add di,ax
>     shl di, 1
> 
>     ; This next bit actually writes the string to the screen.
>     mov ah,current_attr
>     lodsb
> @@:
>     stosw
>     lodsb
>     test  al,al
>     jnz @b
> 
>     ; This converts the final address back to a pair of coordinates
>     ; and stores them so the next string will immediately follow this
>     ; one if the current position isn't repositioned beforehand.
>     mov dl, columns
>     div dl

What are we dividing here? Don't we need a "mov ax, di"/"shr ax, 1" 
before this?

>     mov current_y, al
>     mov current_x, ah
> done:
>     ret
> putstring endp
> 
> Note that this code is quite old

Yeah, we don't see much mode 7 these days! :)

Oh, and don't feed it a null string!

Best,
Frank

0
Reply Frank 2/8/2007 5:27:00 AM

Luke wrote:
> Thanks for your code, it looks good, but I am having a problem with
> the 'mov si, offset msg' line

That's Masm/Tasm syntax - "true Intel syntax". Just remove "offset" for 
Nasm.

> when I run 'nasm videomem.asm -o loader.bin', it gives the error
> 'videomem.asm:11: error: comma or end of line expected'.
> I have tried removing the 'offset' from the line, and the error goes
> away, but then when running the program, it prints random characters
> on the screen. Presumably this is because it doesn't have the correct
> DS:SI location and is printing random junk from memory.

Seems likely.

> This is probably really simple, but I don't have enough experience
> behind me... any ideas?

Get some experience behind you? :)

The name "loader.bin" suggests "where we're at". Presumably, you loaded 
this from a bootsector, presumably using int 13h, and jumped to it. AS I 
recall, this writes to es:bx. Probably, bx was 0 and es had, say, 
"LOADER_SEG" in it... Then you did a far jump... "jmp LOADER_SEG:0", or 
maybe a far ret(?).

When we get to executing "loader.bin", cs has got the "right" segment in 
it (or we wouldn't be there). "push cs"/"pop ds" ought to take care of 
ds. Now, "mov si, msg"... Nasm, of course, replaces "msg" with a number 
- calculated by "origin" plus "file offset".

I've been known to write similar code - using the same name - which, in 
the bootsector, loaded "loader.bin" to LOADER_SEG:100h and made ds = 
LOADER_SEG, put an "int 19h" at LOADER_SEG:0, pushed a 0 on the stack, 
before the "jmp LOADER_SEG:100h"... The starting conditions for 
"loader.bin" were similar to a dos .com file, so I could test code under 
dos without having to boot to test it. Didn't help that much, IIRC. If 
you've encountered code like that, "loader.bin" wants to be assembled at 
"org 100h" (and will exit... well, restart... with a "ret").

Otherwise, I would expect probably "org 0" (although Nasm defaults to 
it, I'd specify it "for clarity"). All sorts of other arrangements are 
possible, of course. If we need to see the code, we'll probably need to 
see the code that loads it, too...

To help you work out how ds, "org", and offset relate, consider these 
dos .com files (untested and prone to typos).

org 100h

mov dx, msg ; "offset msg" for Masm/Tasm
mov ah, 9
int 21h
ret
msg db "Hello, World$"

Works (I hope). But suppose we forgot "org 100h", or didn't want it for 
some reason. Garbage characters! But we could do:

mov dx, msg + 100h
mov ah, 9
int 21h
ret
msg db "Hello, World$"

Or we could fix up ds so our data *was* at "org 0" with respect to ds:

mov ax, ds
add ax, 10h
mov ds, ax
mov dx, msg ; "offset msg" for Masm/Tasm
mov ah, 9
int 21h
ret
msg db "Hello, World$"

Diddle with those things in your code and I think you'll get it working. 
You really are on the right track.

Best,
Frank

0
Reply Frank 2/8/2007 9:22:33 AM

I am using a sample bootsector I got from the web for the moment. I
will be using my own eventually. I have included the relevant part of
the source below.
I am guessing that I need to use ORG 50h, as that's where the kernel
is being loaded?
Long story short, I tried org 50h and org 100h, and it displays a few
garbage characters at seemingly random places on the screen. Should I
be using ORG something else, or is something else the problem?
I have included the source for loader.bin below the boot sector



bootsector (partial)
-------------------------------
; read image file into memory (0050:0000)
     mov     si, msgCRLF
     call    DisplayMessage
     mov     ax, 0x0050
     mov     es, ax                              ; destination for
image
     mov     bx, 0x0000                          ; destination for
image
     push    bx
LOAD_IMAGE:
     mov     ax, WORD [cluster]                  ; cluster to read
     pop     bx                                  ; buffer to read into
     call    ClusterLBA                          ; convert cluster to
LBA
     xor     cx, cx
     mov     cl, BYTE [SectorsPerCluster]        ; sectors to read
     call    ReadSectors
     push    bx
; compute next cluster
     mov     ax, WORD [cluster]                  ; identify current
cluster
     mov     cx, ax                              ; copy current
cluster
     mov     dx, ax                              ; copy current
cluster
     shr     dx, 0x0001                          ; divide by two
     add     cx, dx                              ; sum for (3/2)
     mov     bx, 0x0200                          ; location of FAT in
memory
     add     bx, cx                              ; index into FAT
     mov     dx, WORD [bx]                       ; read two bytes from
FAT
     test    ax, 0x0001
     jnz     .ODD_CLUSTER
..EVEN_CLUSTER:
     and     dx, 0000111111111111b               ; take low twelve
bits
    jmp     .DONE
..ODD_CLUSTER:
     shr     dx, 0x0004                          ; take high twelve
bits
..DONE:
     mov     WORD [cluster], dx                  ; store new cluster
     cmp     dx, 0x0FF0                          ; test for end of
file
     jb      LOAD_IMAGE
DONE:
     mov     si, msgCRLF
     call    DisplayMessage
     push    WORD 0x0050
     push    WORD 0x0000
     retf
FAILURE:
     mov     si, msgFailure
     call    DisplayMessage
     mov     ah, 0x00
     int     0x16                                ; await keypress
     int     0x19                                ; warm boot computer




loader.bin
----------------------------------------------
org 50h

msg:    db 'test'
                db 0                    ; so you know when to stop

write_screen:
        mov     ax, 0b800h
        mov     es, ax
        xor     di, di
        mov     si, msg                 ; point to string
        mov     ah, 7                   ; attribute to use, could be
from a variable
        cld

write_loop:
        lodsb                           ; get string character into al
        or      al, al                  ; check for 0, end of string
        jz      write_done
        stosw                           ; write character and
attribute
        jmp     write_loop

write_done:


------------------------------------------------
PS. If I eventually get out of real mode and into protected mode (when
I understand how it works - I'll look into that later), does the org
100h or similar still apply?

Thanks...

0
Reply Luke 2/9/2007 12:32:42 AM

Luke wrote:
> I am using a sample bootsector I got from the web for the moment. I
> will be using my own eventually. I have included the relevant part of
> the source below.
> I am guessing that I need to use ORG 50h, as that's where the kernel
> is being loaded?

No, segment 50h, offset 0.

> Long story short, I tried org 50h and org 100h, and it displays a few
> garbage characters at seemingly random places on the screen. Should I
> be using ORG something else, or is something else the problem?

Wrong ds, too. In the bootsector, ds was probably 0 or 7C0h (or it 
wouldn't have worked). You don't change it when you jump (retf_ to 
"loader.bin", so it's still there.

....
>      mov     ax, 0x0050
>      mov     es, ax                              ; destination for
> image
>      mov     bx, 0x0000                          ; destination for
> image

....
>      push    WORD 0x0050
>      push    WORD 0x0000
>      retf

....
> loader.bin
> ----------------------------------------------
> org 50h

Should be "org 0".

> msg:    db 'test'
>                 db 0                    ; so you know when to stop

This gets executed!!! Move it to the end of your code (or jump over it).

push cs
pop ds

Now ds = cs = 50h... es was already 50h from the bootsector. (but you 
change it, shortly) I don't think it's any part of your problem, but 50h 
is kinda low. You might encounter "extended bios data area" in segment 
50h. I'd be tempted to load at 60h:0 - that's where dos loads, I think...

> write_screen:
>         mov     ax, 0b800h
>         mov     es, ax
>         xor     di, di
>         mov     si, msg                 ; point to string
>         mov     ah, 7                   ; attribute to use, could be
> from a variable
>         cld
> 
> write_loop:
>         lodsb                           ; get string character into al
>         or      al, al                  ; check for 0, end of string
>         jz      write_done
>         stosw                           ; write character and
> attribute
>         jmp     write_loop
> 
> write_done:

I think that should fix it...

> ------------------------------------------------
> PS. If I eventually get out of real mode and into protected mode (when
> I understand how it works - I'll look into that later), does the org
> 100h or similar still apply?

Yes. Segment registers are used differently, but they still need to be 
set to a "valid" value, and they are still a part of *every* address. 
The "base" of the segment is added to the "offset" to form the complete 
address. In real mode, the "base" is 16 times the value in the segreg. 
In protected mode, the "base" is specified in the descriptor. The 
"usual" pmode scheme is "flat memory model" - the "base" of all 
descriptors is 0. So the offset is the whole address. The origin "org" 
still has to match the address where the code was loaded. Typical "org" 
values would be much larger than 100h, but it still applies.

Paging complicates the issue considerably!

Best,
Frank

0
Reply Frank 2/9/2007 2:58:38 AM

Thanks for that, it is working fine now. Now i'm starting to get some
experience behind me :-)
I have included the source below if anyone is interested...


-------------------------------------------------------
;writes a string to video memory
;used in real mode


  ORG 0

  PUSH CS			;CS = the location in memory where this program is loaded
  POP DS			;Move the value of CS into DS

Print:
  MOV     AX, 0xB800		;Start location of video memory
  MOV     ES, AX		;Move video memory location to ES
  XOR     DI, DI		;Clear Destination Index
  MOV     SI, msg		;Move our message into memory
  MOV     AH, 7			;Set colour attribute (7 = white on black)
  CLD				;Clear directional flag. DI increments with each write
(instead of decrements)

Print_Loop:
  LODSB				;Loads the first byte of msg
  OR      AL, AL		;checks for the 0 character
  JZ      Hang			;If we're up to the 0 character, we are at the end of
the line
  STOSW				;Store the character in ES:DI (video memory)
  JMP     Print_Loop		;Loop to the next character

Hang:
  JMP     Hang			;End of program


msg:    db 'test'		;Message definition
                db 0		;0 character specifying the end of the string

0
Reply Luke 2/9/2007 5:26:45 AM

MOV  CX, msglen
REPZ MOVSD

msg:    db 't',7,'e',7,'s',7,'t',7   ;ascii, colour attribute
; db ........
fillbytes = ($-msg)-(($-msg)/4)*4)
%if fillbytes >0
times fillbytes DB 0
%endif
msglen = ($-msg)/4

Dirk

0
Reply Dirk 2/10/2007 6:12:10 AM

15 Replies
237 Views

(page loaded in 0.263 seconds)

Similiar Articles:


















7/29/2012 4:52:09 PM


Reply: