Assembler string output in RM does not work

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
jkrug
Posts: 7
Joined: Thu Sep 10, 2009 12:10 pm
Location: Karlsruhe (Germany)
Contact:

Assembler string output in RM does not work

Post by jkrug »

Hi,

because I don't have a very good command of assembler although I need it often for my OS I've decided to become acquintated with it. I've just written a mini-RM program that should simply print a string to the screen using BIOS interrupts. Assembling and starting in QEMU works well but the program behaves strange when I try to put a string to the screen (he puts out small delta signs in an endless loop. Following code:

Code: Select all

[BITS 16]	; generate 16bit real mode code
[ORG 0x700]	; start address of code is 0x700

; jump to start label (without segment prefix -> 0x0:)
jmp 0x00:start

start:
	cli		; clear interrupt flag

	; setup working stack
	mov ax,0x9000
	mov ss,ax	; set stack base address to 0x9000
	mov sp,0	; set stack pointer to 0

	sti			; set interrupt flag

	mov dx,msg
	push dx
	call printstr

	jmp short $

msg db 'Welcome to simpleOS!',10,0	; welcome message

; print string
printstr:
	pop dx
	mov si,dx
_loop:
	mov al,[si]
	mov ah,0x0E			; move attribute byte to 0x0E
	int 0x10

	mov al,[si]			; just in case the BIOS interrupt modifies the register

	inc si

	cmp al,0			; compare al and 0
	jne _done			; if they are equivalent, jump to the 'done' label

	jmp _loop
_done:
	ret

times 512-($-$$)-2 db 0		; $ stands for the current line offset
							; $$ stands for the offset into the section
dw 0xAA55
Can anybody tell me what's wrong with it? I guess it's something very simple I just don't get.

Thanks
jkrug
Fatal error: line XVI: system down
Hangin10
Member
Member
Posts: 162
Joined: Wed Feb 27, 2008 12:40 am

Re: Assembler string output in RM does not work

Post by Hangin10 »

When you're getting the function arguments, the first item on the stack is going to be the return address. Assuming a near call, you'll want the second word (SP+2). Or use the frame pointer, in which case the third word:

Code: Select all

push bp
mov bp, sp
mov dx, [bp+4]
and then at the end:

Code: Select all

leave
ret
User avatar
beyondsociety
Member
Member
Posts: 39
Joined: Tue Oct 17, 2006 10:35 pm
Location: Eagle, ID (USA)
Contact:

Re: Assembler string output in RM does not work

Post by beyondsociety »

I see a few problems with your code that may make it not work for you, suggestions, etc.
[ORG 0x700] ; start address of code is 0x700
Why are you starting out your code at location 0x700? Never seen that as a loading address, you will want 0x7c00 as the address if this is part of a bootsector and i assume it is considering you have
times 512-($-$$)-2 db 0 ; $ stands for the current line offset
; $$ stands for the offset into the section
dw 0xAA55
at the bottom of the assembly file, otherwise you would want to try loading at 0x100 and assembling it to a .com file

You really don't need the cli/sti in between setting up the stack, more or less a personal perference. As for your location for your realmode stack, cant remember if that is a good place to put it or not, been a while since I've written code for real mode. the other code looks all right to me, though havent tested it in a emulator.

Hope this helps.
"I think it may be time for some guru meditation"
"Barbarians don't do advanced wizardry"
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Assembler string output in RM does not work

Post by Combuster »

It is generally easier to use a register-calling-convention in asm-only code.

And your stack is in reserved memory
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
jkrug
Posts: 7
Joined: Thu Sep 10, 2009 12:10 pm
Location: Karlsruhe (Germany)
Contact:

Re: Assembler string output in RM does not work

Post by jkrug »

Okay, thank you for your help. I've come to the conclusion that I don't understand a basic concept for when I try to put out a single character like this:

Code: Select all

[BITS 16]	; generate 16bit real mode code
[ORG 0x7C0]	; start address of code is 0x700

; jump to start label (without segment prefix -> 0x0:)
jmp 0x00:start

start:
	; setup working stack
	mov ax,0x9000
	mov ss,ax	; set stack base address to 0x9000
	mov sp,0	; set stack pointer to 0

	sign db 'H'

	; print character to screen
	mov al,[sign]
	mov ah,0x0E
	int 0x10

	jmp $

times 512-($-$$)-2 db 0
dw 0xAA55
he puts a 'F' to the screen. (I should definitely spend a little bit more time in getting the assembler basics and not only work on C/C++ level :D ) What's wrong with this?

Cheers
jkrug

PS: If 0x9000 is protected memory, is there a better place for the stack?

//edit: I just looked up in a memory map and 0x9000 has been describben as freely usable memory there.
Last edited by jkrug on Tue Sep 29, 2009 9:16 am, edited 1 time in total.
Fatal error: line XVI: system down
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Assembler string output in RM does not work

Post by Combuster »

Looks like you copied everything and understood nothing.

Start with reading Real Mode addressing, then ask again.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
geppyfx
Member
Member
Posts: 87
Joined: Tue Apr 28, 2009 4:58 pm

Re: Assembler string output in RM does not work

Post by geppyfx »

interesting piece of code you got here
sign db 'H' gets treated as code. But by lucky coincidence it corresponds to dec ax instruction

mov al,[sign] uses DS register which you did not setup, but since you did set CS register you can overwrite DS: mov al, [CS:sign]

Code: Select all

[BITS 16]	; generate 16bit real mode code
[ORG 0x7C00]	; 0x7C00

; jump to start label (without segment prefix -> 0x0:)
jmp 0x00:start

start:
	; setup working stack
	mov ax,0x9000
	mov ss,ax	; set stack base address to 0x9000
	mov sp,0	; set stack pointer to 0
	xor ax, ax
	mov ds, ax
	jmp next_code

	sign db 'H'

next_code:
	; print character to screen
	mov al,[sign]
	mov ah,0x0E
	int 0x10

	jmp $

times 512-($-$$)-2 db 0
dw 0xAA55
and I can't tell anything about int10 function becaouse i don't remember that stuff
jkrug
Posts: 7
Joined: Thu Sep 10, 2009 12:10 pm
Location: Karlsruhe (Germany)
Contact:

Re: Assembler string output in RM does not work

Post by jkrug »

@Combuster: The code is not copied although I do not really understand it. I know how it works in theory but I just can't put it into practice.

@geppyfx: It works now when I've applied your tips. I just got a bit confused about all this leaving-different-parts-out-to-see-if-it-works-then stuff so I forgot to set the ds register again :D. Thank you for your help!

Cheers
jkrug

PS: int 0x10 is working, I tried before by moving the constant ascii code for 'a' into al and it worked.

PPS: I got now what I originally wanted: putting out a string to the screen with this code:

Code: Select all

[BITS 16]	; produce 16bit real mode code
[ORG 0x7C00]	; organize code on 0x7C0 where it gets loaded by the BIOS

jmp 0x00:start	; jump to 'start' label (with sr prefix 0x00: -> cs = 0)

start:
	; setup a working stack at address 0x9000 (should be free for own use)
	mov ax,0x9000
	mov ss,ax	; set stack base address to 0x9000
	mov sp,0	; set stack pointer to 0

	; setup working environment
	xor ax,ax	; get zero into AX
	mov ds,ax	; set DS to zero
	mov es,ax	; set ES to zero

	; jump to actual start function
	jmp _start

	; reserve some memory for the welcome string to output
	msg db 'Hello',0

_start:
	mov ax,msg		; move sign address to ax
	push ax			; push address to stack
	call screen_write

	jmp $			; jump into endless loop

; this function writes a string to the screen
screen_write:
	pop ax			; pop return address from stack
	pop ax			; pop string base address from stack
	mov si,ax		; move base address to SI

_char_loop:
	lodsb			; load character currently being located at the address
					; stored in SI to AL

	cmp al,0		; compare AL and 0: 0 is subtracted from AL and if zero
					; comes out, the zero flag is set
	je _end			; if they are equivalent (-> zero flag is set), jump to end
	
	mov ah,0x0E		; move attribute byte to AH
	int 0x10		; raise BIOS interrupt
	jmp _char_loop

_end:
	ret
	

times 512-($-$$)-2 db 0		; $ stands for the current line offset
; $$ stands for the offset into the section
dw 0xAA55
Fatal error: line XVI: system down
User avatar
Andr3w
Member
Member
Posts: 76
Joined: Tue Jun 09, 2009 4:09 am
Location: Somewhere

Re: Assembler string output in RM does not work

Post by Andr3w »

Code: Select all

_start:
	mov ax,msg		; move sign address to ax
	push ax			; push address to stack
	call screen_write

	jmp $			; jump into endless loop

I think you don't really need an infinite loop at this time. If you wanna stop execution, I'd recommend you to halt the processor using

Code: Select all

        cli                  ; disable interrupts
        hlt                 ; halt - will continue execution after an exception or IRQ
                            ; (we disabled interrupts, so this will stop the processor)
Or, if you don't wanna halt the system, I'd recommend you to use this to stop fan from working everytime:

Code: Select all

INFINITE_LOOP:
        hlt                 ; halt - will continue execution after an exception or IRQ
        jmp INFINITE_LOOP      ; jump to INFINITE_LOOP and wait for another exception or IRQ
Correct me if I'm wrong! :)

-- Andrew
Hangin10
Member
Member
Posts: 162
Joined: Wed Feb 27, 2008 12:40 am

Re: Assembler string output in RM does not work

Post by Hangin10 »

Instead of pointing something out, I'm just going to suggest you try printing two strings (call your print string function twice).
jkrug
Posts: 7
Joined: Thu Sep 10, 2009 12:10 pm
Location: Karlsruhe (Germany)
Contact:

Re: Assembler string output in RM does not work

Post by jkrug »

Hangin10 wrote:Instead of pointing something out, I'm just going to suggest you try printing two strings (call your print string function twice).
Oh yes, I forgot that I have to push the return address again. Is running now, thanks for the hint. It is astonishing how much more I learn about assembler when I try to write a simple program like this than I've learned by reading a whole tutorial.

@qandrew: Makes sense, I've replaced the jmp $ now with

Code: Select all

cli
hlt
Cheers
jkrug
Fatal error: line XVI: system down
Post Reply