Page 1 of 1

addresing on real-mode

Posted: Mon Dec 06, 2010 6:11 am
by Pes88
Hello,
I am writing a little loader that it must load a my module. The problem is the addresing with segmentation on real-mode , because I don't understand how a part of my module is loaded to memory...

I must load 20 sectors on this position of memmory :

Code: Select all

.set $SEG_DEST,0x0800
...
movw $SEG_DEST, %ax	# in es il segmento di destinazione
movw %ax, %es
xorw %bx,%bx 
...
int $0x13                           # this load the sector to es:bx 
For each sector I must insert the offset of 512 byte , therefore I add to register bx 512 , but this solution it don't work! Why?

Code: Select all

addw $512, %bx 
The solution correct is :

Code: Select all

	movw %es, %ax		# 
	movw %ax, %es		#  each new switch is given by the previous  plus 512 / 16        ( 32) 
	addw $0x20, %ax		# add 32 to %ax  
	movw %ax, %es		#  
Why?
I don't understand why on this solution ( that work correctly ) it increases the segment register instead of increase the offset register bx?

Re: addresing on real-mode

Posted: Mon Dec 06, 2010 8:26 am
by thepowersgang
Ok, firstly, How is it failing when you increment BX?

(also, are you sure the destination is denoted by ES:BX?)

Re: addresing on real-mode

Posted: Mon Dec 06, 2010 8:45 am
by Combuster
Increasing bx by 0x200 before each read does work if done correctly - it's been in my bootloader's code for several years and is tested on all emulators and all real hardware I had at the time. The only pitfall is that you can only load 64k after which bx will overflow and you start overwriting the start of the data.

Do you correctly preserve registers? Did you check the values before each int call to make sure they match what you expect them to be? You know that registers may be modified by a bios call?

Re: addresing on real-mode

Posted: Mon Dec 06, 2010 10:31 am
by Pes88
(also, are you sure the destination is denoted by ES:BX?)
Yes, I use the interrupt int $0x13 for load the sectors from the floppy!

AH = 02h
AL = number of sectors to read (must be nonzero)
CH = low eight bits of cylinder number
CL = sector number 1-63 (bits 0-5)
high two bits of cylinder (bits 6-7, hard disk only)
DH = head number
DL = drive number (bit 7 set for hard disk)
ES:BX -> data buffer


Do you correctly preserve registers? Did you check the values before each int call to make sure they match what you expect them to be? You know that registers may be modified by a bios call?
Yes, yes, yes! :) :D :D The problem is this instruction : addw $512, %bx .

Now, I have understand this solution :

Code: Select all

   movw %es, %ax      # 
   movw %ax, %es      #  each new switch is given by the previous  plus 512 / 16        ( 32) 
   addw $0x20, %ax      # add 32 to %ax  
   movw %ax, %es      #  
When the processor is on the real mode state, the memory is great 1MB and it is partition on 64K segments ! Right?
Then each segment is large 16 byte , therefore to have an offset of 512 can add 32 to the register es!!

Yet it should be right also my solution!

Code complete :

Code: Select all

.code16		# Necessario per eseguire il codice in modo reale

.set SEG_BOOT, 0x07c0
.set INIT_STACK, 0x0400

.set SEG_DEST, 0x0800
.set DIM_MODULO, 20		# settori del modulo

	.text

	movw $SEG_BOOT, %ax	# caricamento di valori noti nei registri 
	movw %ax, %ds		#  selettore
	movw %ax, %es

	cli			# interruzioni disabilitate nel cambiamento
				#  di pila
	movw %ax, %ss
	movw $INIT_STACK, %sp	# pila iniziale a 0x07c0:0400, cioe'
				#  512 byte dopo la fine del settore
				#  di avviamento in memoria

	sti

	movw $mess, %si		# indirizzo del primo carattere del messaggio
				#  in si

				# impostazione parametri int 0x10:
	movb $0x0e, %ah		# servizio stampa carattere
	movb $0, %bh		# numero di pagina

nuovo_car:
	lodsb			# carica il carattere in al
	cmpb $0, %al		# verifica se e' l' ultimo
	je fine_str
	int $0x10		# lo stampa
	jmp nuovo_car

fine_str:
	call carica		# carica il modulo da floppy
	call spegni		# spegne il motore del floppy

	ljmp $SEG_DEST, $0	# salto al modulo appena caricato

#
# Caricamento del modulo
# (non si salvano i registri)

da_leggere: .word DIM_MODULO

carica:
	xorw %ax, %ax		# reset del controllore del floppy
	xorw %dx, %dx
	int $0x13

	movw $SEG_DEST, %ax	# in es il segmento di destinazione
	movw %ax, %es
	movw $0x0002, %cx	# la lettura inizia dal secondo settore
				#  del primo cilindro (i settori sono
				#  contati da uno, cilindri e testine da
				#  zero)
	movw $0x0000, %dx	# prima testina del drive zero (primo floppy) dh=0 testina zero 

nuovo_sett:
	movw $0x0201, %ax	# lettura di un settore  numero di settori da leggere 
	xorw %bx, %bx		# azzeramento offset		mette il settore su %es:%bx quindi bx è l'offeset 
    
	int $0x13

	# jc errore_di_lettura	# cf=1 indica un errore in lettura

	decw da_leggere		# decremento del contatore
	cmpw $0, da_leggere
	je fine_car

	#movw %es, %ax		# incremento del selettore in es:
	#addw $0x20, %ax		#  ogni lettura si avanza di 512 byte, il  perchè?????
	#movw %ax, %es		#  nuovo selettore e' dato dal precedente
				#  piu' 512/16 = 32
	addw $0x0200, %bx    
                                        
  

	incb %cl		# incremento il settore
	cmpb $18, %cl		# se arrivo al 18-esimo devo cambiare testina	ogni traccia e data 18 settori 
	jbe nuovo_sett

	xorb $1, %dh		# cambio di testina			# metto la testina uno 
	movb $1, %cl		# riprende a leggere dal primo settore
	jnz nuovo_sett		# xor e' l' ultima istruzione a modificare
				#  eflag, se la testina e' tornata 0
				#  e' necessario cambiare anche cilindro
				#  (non salta)

	incb %ch		# incremento del cilindro
	jmp nuovo_sett

fine_car:
	ret

#
# Spegnimento del motore del floppy tramite il controllore
#

spegni:
	movw $0x3f2, %dx
	movb $0, %al
	outb %al, %dx
	ret

mess:	.asciz "Caricamento in corso"

	.org 510
sign:	.byte	0x55		# signature per un settore di avviamento valido
	.byte	0xaa

this address 0x0800:0x0200 identify the same cell of memory of this address 0x0820:0000! Right?

Re: addresing on real-mode

Posted: Mon Dec 06, 2010 11:12 am
by Combuster
I wrote:Do you correctly preserve registers?
Your answer.... going for a thousand credits .... MEEP. Sorry, the answer was no:

Code: Select all

bx = 0;
read_sector();
bx += 512;
bx = 0;
read_sector();
bx += 512;
bx = 0;
(...)

Re: addresing on real-mode

Posted: Mon Dec 06, 2010 11:27 am
by Pes88
thanks!!! Now , it works all!

Sorry, for my fast and wrong reply! :oops: :oops: :oops: :oops: :oops: