Author Topic: Printing a null-terminating string  (Read 27155 times)

Offline KittenFace

  • Jr. Member
  • *
  • Posts: 4
Printing a null-terminating string
« on: January 09, 2011, 05:13:32 PM »
Hello, there.

I am trying to print out a null-terminating string, and have been through several examples but cant figure it out!

The code I have so far, which will run but no print out anything to the screen, is as follows

Code: [Select]
mov bx , HELLO_MSG
call print_string
jmp $

HELLO_MSG :
db 'Hello , World !', 0


print_string:
push bx
.1:
cmp byte [bx], 0
je .exit
mov al, [bx]
mov ah, 0x0e
int 0x10
inc bx
jmp .1
.exit: pop bx
ret

times 510 -($-$$) db 0
dw 0 xaa55

I am a complete beginner at assembler, and will be quite honest and say that pointers confuse me a bit

thanks in advance for pointing out the obvious problem i've made! :p

Offline the_mart

  • Jr. Member
  • *
  • Posts: 14
  • Country: gb
Re: Printing a null-terminating string
« Reply #1 on: January 09, 2011, 07:43:38 PM »
I guess you’re trying to write a boot sector there, and print using the BIOS. The boot sector is loaded by the BIOS at “0000:7C00”, so if the code you pasted is complete, you haven’t loaded the correct segment:offset for your string.

You could fix by putting “ORG 0x7C00” at the top of your code, and zeroing out DS.

Offline KittenFace

  • Jr. Member
  • *
  • Posts: 4
Re: Printing a null-terminating string
« Reply #2 on: January 09, 2011, 07:54:24 PM »
i currently have [org 0x7c00] at the top of my program, but didn't include it as i thought that the problems were caused in my print_string function

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Printing a null-terminating string
« Reply #3 on: January 10, 2011, 07:12:13 PM »
In addition to what "the_mart" mentions, there's a subtler problem which might trouble you, though probably not. Bios int 10h/0Eh might print to the "video page" in bh (you want zero). My video bios apparently doesn't care what's in bh or bl, but bh is "supposed" to be the video page, and bl might control the color (I've heard of this, but never seen it). I do "mov bx, 7" for that interrupt, "just to be sure". If this is a problem, you'll need to use a different register to point to your string. If you used si (di is about the only other possibility), you could use "lodsb", a one-byte instruction which does:

Code: [Select]
mov al, [si] ; note that this is implicitly [ds:si], ds still needs to be right!
inc si

Strictly speaking, it could decrement si instead, if the "direction flag" were set. This isn't likely in a bootsector, but to be sure... "cld". The "direction flag" is "up" if it's clear, and "down" if it's set - affects the "string instructions". If "lodsb" seems confusing, just use si exactly like you've done with bx.

That probably isn't your problem anyway (but might be, on "some" machine). Far more common is what "the_mart" describes - a failure to get your "org" and your "ds" synchonized. If you write "org 0", or no "org" at all (Nasm defaults to "org 0" in "-f bin mode), you can still get a perfectly good bootsector out of it... if you put 7C0h in ds. More common (it seems) is to write "org 7C00h" and put zero in ds (and perhaps other segment registers). Either combination, 0000:7C00 or 07C0:0000 address the same memory location - other combinations would, too, but don't make much sense. (this "segmented addressing" is a little weird, until you get used to it!).

If one of those ideas doesn't fix it, let us know!

Best,
Frank


Offline KittenFace

  • Jr. Member
  • *
  • Posts: 4
Re: Printing a null-terminating string
« Reply #4 on: January 10, 2011, 08:26:55 PM »
[org 0x7c00]  has been replaced with [org 7C00h], and
Code: [Select]
mov si,bx included and all mentions to bx replaced with si. now 'S ' (space included) is printed out

Offline the_mart

  • Jr. Member
  • *
  • Posts: 14
  • Country: gb
Re: Printing a null-terminating string
« Reply #5 on: January 10, 2011, 08:53:26 PM »
Did you zero DS before trying to load the address of your string?

Code: [Select]
xor ax,ax
mov ds,ax

How are you testing testing this? I tested it using VirtualBox 4.0 by copying the boot sector into a floppy disk image, and booting from it. It worked as expected.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Printing a null-terminating string
« Reply #6 on: January 10, 2011, 08:59:38 PM »
That's strange. 0x7c00 and 7C00h are the same thing, so that won't make any difference. You've got something like this now...

Code: [Select]
org 0x7c00 ; or 7C00h... or $7C00

xor ax, ax
mov ds, ax

mov si , HELLO_MSG
call print_string
jmp $

HELLO_MSG :
db 'Hello , World !', 0


print_string:
push si
.1:
cmp byte [si], 0
je .exit
mov al, [si]
mov ah, 0x0e

mov bx, 7 ; does this help?

int 0x10
inc si
jmp .1
.exit: pop si
ret

times 510 -($-$$) db 0
dw 0xaa55

Right?

And it's printing 'S '? (I hate to ask how you know the space is included!) :)

I dunno... haven't tried that, but it looks okay to me...

Best,
Frank


Offline KittenFace

  • Jr. Member
  • *
  • Posts: 4
Re: Printing a null-terminating string
« Reply #7 on: January 11, 2011, 10:32:58 AM »
Im using qemu for windows to test it, at the moment.

The entire program actually has an %include to another file which has the print_string method. This is part of a homework assignment, and %include has always been explained to me as inserting the contents of the other file at the point of the %include statement.

because of this i assumed that having the print_string function in the same program would be the same as having the print_string in another file, which was included. I have tested both ways, and the correct output is seen in the 'all-in-one' program, whereas the strings are replaced with 'S' in the 2-part program.

So i am now lead to think that i haven't handled %include properly

What i have so far is:
Code: [Select]
[org 0x7C00]

xor ax, ax
mov ds, ax

mov si , HELLO_MSG
call print_string
mov si , GOODBYE_MSG
call print_string
jmp $

; Data
HELLO_MSG :
db 'Hello , World !', 0
GOODBYE_MSG :
db 'Goodbye !', 0

%include "print_string.asm"

times 510 -($-$$) db 0
dw 0xaa55

and

Code: [Select]
org 0x7c00 ;

xor ax, ax
mov ds, ax

print_string:
push si

label:
cmp byte [si], 0
je exit
mov al, [si]
mov ah, 0x0e

mov bx, 7

int 0x10
inc si
jmp label

exit:
pop si
ret

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Printing a null-terminating string
« Reply #8 on: January 11, 2011, 11:30:29 AM »
Well, "%include"ing the file should work. You only want one "org" per file (including the "%include"d file). Nasm seems not to object if they're both the same. I'd delete the "%include"d "org" anyway, just to see if it makes a difference. The:

Code: [Select]
xor ax, ax
mov ds, ax

in the "%include"d file is never executed - just sits there between your data and the "print_string:" label. Not a problem - you've already done it in the .asm file. I'd start "print_string.asm" right at the "print_string:" label, but I don't see why it should be a problem - you've used "%include" correctly, I think. (it is essentially a "cut-and-paste" operation, as you assume)

I'll put this on a "real floppy" and try it, if I get to it. "Puzzles" like this are what make me not "trust" emulators! :)

Best,
Frank