| 
	
		|  Autor | Tema: int 13h problema  (Leído 4,120 veces) |  
	| 
			| 
					
						| Khronos14 
								 
								
								 Desconectado 
								Mensajes: 443
								
								 
								A lie is a lie
								
								
								
								
								
								     | 
 
Hola, estoy escribiendo mi propio bootloader, que se carga desde una imagen FAT12 de disquete. Utilizo bochs para la virtualización. El problema que tengo, es que no se como trabajar con el buffer que devuelve la función int 13h cuando lees unos sectores del disquete. [bits 16][ORG 0] jmp short startnop   ; No Operation (1 byte) OEMLabel:                     db "KERNEL  "      ; 8 characters padded with spacesBytesPerSector:                 dw 512            ; Bytes per sectorSectorsPerCluster:                db 1            ; Sectors per clusterReservedSectors:                dw 1            ; Reserved Sectors (for sector 0)NumberOfFATs:                   db 2            ; Number of FAT´sMaxRootEntries:                dw 224            ; Number of Root Entries NumberOfSectors:                dw 2880            ; Number of sectorsDeviceDescriptor:                db 0xF0            ; Device Descriptor 0xF0 => 1.44 MB floppy imageSectorsPerFAT:                   dw 9            ; Sectors Per FATSectorsPerTrack:                dw 18            ; Sectors Per TrackSides:                         dw 2            ; Sides of diskHiddenSectors:                   dd 0            ; Number of Hidden SectorsLengthOfSectors:               dd 0            ; Length of sectorsDriveNo:                      db 0            ; Drive Number (0 or 1)Flags:                         db 0            ; Additional flagsSignature:                      db 0x14            ; Signature, some number of 1 byteVolumeID:                     dd 0xAABBCCDD      ; Volume IDVolumeLabel:                   db "DISCO TANIS "   ; 11 characters padded with spacesFileSystem:                   db "FAT12   "      ; 8 characters padded with spaces ;**********************************************************;; Entry Point; Reset the floppy disk.; Calculate the root directory CHS address and jump to ; read_root_directory.;**********************************************************;start:   jmp 07C0h:stage_1 stage_1:   mov ax, cs   mov ds, ax   mov es, ax    mov si, StringMsg   call print_string    xor ah, ah ; Ah = 0, reset function   mov dl, BYTE [DriveNo]   int 13h ; Reset Floppy Disk    xor ax, ax    add ax, WORD [SectorsPerFAT]   mul BYTE [NumberOfFATs]   add ax, WORD [ReservedSectors]   ; AX = (SectorsPerFAT * NumberOfFATs) + ReservedSectors    call lba2chs    jmp short read_root_directory read_root_directory:   ; We have already calculated the CH = Cilynder, CL = sector and   ; DH = Head.   mov ax, 1000h   mov es, ax   mov bx, 0    mov ah, 02h   ; Read mode   mov al, 0Fh ; Sectors to read (512 bytes each sector)   mov dl, BYTE [DriveNo]    int 13h ;Call the interruption!   jc .root_dir_read_error    mov si, [1000h]   mov dx, 512   call print_n         ... 
 Y la función print_n ;**********************************************************;; Print a string in screen; SI => String pointer; DX => Number of characters to print;**********************************************************;print_n:   push ax   push bx   push cx    mov ah, 0Eh    xor cx, cx    .loop:   mov al, [si]   int 10h   inc cx   cmp cx, dx   je short .end_loop    inc si   jmp short .loop    .end_loop:   pop ax   pop bx   pop cx   ret 
 El problema que tengo, está aquí: mov si, [1000h]mov dx, 512call print_n 
 Me debería escribir en pantalla en caracteres ASCII el contenido del Root Directory, pero en vez de eso, comienza a escribirme desde el sector 0, es decir, va escribiendo la propia memoria del programa... La función lba2chs, convierte direccionamiento LBA (Logical Block Address) a CHS (Cylinder Head Sector), y funciona bien. Espero que me podáis ayudar. Saludos.
 
 |  
						| 
								|  |  
								|  |  En línea | 
 
 |  |  |  | 
			| 
					
						| _Enko | 
 
No recuerdo bien el tema, pero igual, creo que deberias de poner el codigo completo...
 la funcion print_n se encuentra en el loader o esta dentro de lo que se lee del disquet es decir, el kernel?
 
 Si esta fuera del loader, primero tienes que hacer un JMP hacia la direccion de memoria donde se almacenó lo que se leyo del disquet. Y ahi tiene que haber un ORG para que los saltos relativos funcionen.
 
 en PRINT_N los pop estan mal.
 Se saca de la pila en el orden inverso al que se meten. En cambio vos lo haces con el mismo orden, alternando ax con cx.
 
 
 
 por cierto, si no te quieres quemar la cabeza momentaneamente con fat12/16 no lo tienes que hacer. No es obligatorio.
 Al menos que uses virtual box de oracle que no acepta un disquete sin formato.
 WMWare por ejemplo, acepta disquet sin formato e inclusive con tamaño de cualquier tipo. Por ejemplo disquet de 5megas (inexistente) te lo acepta.
 
 Lo que puedes hacer es por ejemplo, en tu codigo:
 
 
 org 0;
 lectura del disquete a partir de 512bytes en adelante... no se, lees 2kb, con eso sobra
 salto a la direccion de memoria a  donde leiste el kernel.
 rellenar este pedazo que ocupe 512bytes.
 
 ;kernel CODE
 org (direccion de memoria de a donde leiste los 2kb)
 ;la direccion en el disquete es el byte 513... pero no es donde leiste eso en la memoria
 ;por eso el org por ejemplo 1000h
 
 codigo del kernel
 
 rellenas para que ocupe todo 1.44M
 
 
 es decir, el codigo del kernel no se ejecuta desde el disuqet, sino desde la memoria a lo que lo pasaste.
 
 
 |  
						| 
								|  |  
								| « Última modificación: 21 Julio 2012, 17:05 pm por _Enko » |  En línea | 
 
 |  |  |  | 
			| 
					
						| Khronos14 
								 
								
								 Desconectado 
								Mensajes: 443
								
								 
								A lie is a lie
								
								
								
								
								
								     | 
 
Muchas gracias por responder _Enko, entonces ¿podría hacer algo así?: mov ax, 1000h   mov es, ax   mov bx, 0    mov ah, 02h   ; Read mode   mov al, 0Fh ; Sectors to read (512 bytes each sector)   mov dl, BYTE [DriveNo]    int 13h ;Call the interruption!   jc .root_dir_read_error    jmp 1000h:0000   xor bx, bx   mov si, bx [b]?[/b]   mov dx, 512   call print_n 
 Print_n se encuentra en el loader, puse los puntos suspensivos porque a continuación está la búsqueda en el Root Directory, la búsqueda en la File Allocation Table, etc.. Lo de los push, fue un pequeño error, gracias. Lo de la imagen FAT, ya lo se. Pero lo prefiero hacer así, porque así podría cargar mis propios programas una vez que el kernel esté más avanzado. Leer y buscar archivos en FAT12, ya lo tengo listo. Voy a probar a hacer lo que me dices y luego te comento. Gracias, saludos. |  
						| 
								|  |  
								|  |  En línea | 
 
 |  |  |  | 
			| 
					
						| _Enko | 
 
 jmp 1000h:0000xor bx, bx
 mov si, bx ?
 mov dx, 512
 call print_n
 
 Eso no... por lo menos no asi. Todo el codigo que se encuentra despues de JMP no se va ejecutar. algo asi seria parox, no lo tomes literal org 0....
 ....
 ;loader
 ...
 ...
 ;kernel jump
 jmp 1000h:0000
 db  512 - $ dup  0 ;rellenamos con 512 bytes.
 ;kernel
 org 1000h?
 ;to do
 
 
 |  
						| 
								|  |  
								|  |  En línea | 
 
 |  |  |  | 
			| 
					
						| Khronos14 
								 
								
								 Desconectado 
								Mensajes: 443
								
								 
								A lie is a lie
								
								
								
								
								
								     | 
 
Bueno, después de una dura semana programando he conseguido terminar el Stage_1 de mi bootloader. No fue una tarea fácil, pero valió la pena, además aprendí muchísimo. El Bootloader busca en una imagen FAT12 el archivo STAGE_2.BIN y lo carga en memoria. Podeis crear una imagen FAT12 con herramientas como esta:https://sourceforge.net/projects/fat12maker/ También desarrollada por mi, totalmente escrita en C. ; Developed by Khronos [bits 16] ; Real mode [ORG 0] ; Origin address jmp short start ; 2 bytesnop ; No Operation (1 byte) OEMLabel:							db "KERNEL  "		; 8 characters padded with spacesBytesPerSector:  					dw 512				; Bytes per sectorSectorsPerCluster: 					db 1				; Sectors per clusterReservedSectors: 					dw 1				; Reserved Sectors (for sector 0)NumberOfFATs: 						db 2				; Number of FAT´sMaxRootEntries: 					dw 224				; Number of Root Entries NumberOfSectors: 					dw 2880				; Number of sectorsDeviceDescriptor: 					db 0xF0				; Device Descriptor 0xF0 => 1.44 MB floppy imageSectorsPerFAT: 						dw 9				; Sectors Per FATSectorsPerTrack: 					dw 18				; Sectors Per TrackSides: 								dw 2				; Sides of diskHiddenSectors: 						dd 0				; Number of Hidden SectorsLengthOfSectors:					dd 0				; Length of sectorsDriveNo: 							db 0				; Drive Number (0 or 1)Flags: 								db 0				; Additional flagsSignature: 							db 0x14				; Signature, some number of 1 byteVolumeID:							dd 0xAABBCCDD		; Volume IDVolumeLabel: 						db "DISCO TANIS "	; 11 characters padded with spacesFileSystem: 						db "FAT12   "		; 8 characters padded with spaces  start:	jmp 07C0h:stage_1 ; CS = 07C0h ;*******************************************************************;* STAGE 1;*******************************************************************stage_1:	mov ax, cs	mov es, ax ; ES = 07C0h	mov ds, ax ; DS = 07C0h 	mov si, BootMsg	call print_string ; Print Boot Message 	xor ah, ah ; Ah = 0, reset function	xor dl, dl ; DL = 0, Drive number 0	int 13h ; Reset Floppy Disk 	jnc short read_root_directory ; If no errors, jump read_root_directory 	jmp reboot ; else, reboot!  ; Root Directory starts at LBA 19 with; 15 sectors of sizeread_root_directory:	mov ax, 1000h    mov es, ax ; ES = 1000h 	;Vamos a leer el sector número 1	mov ax, 19 ; 19 = Root Directory	call lba2chs ; LBA to CHS 	mov ah, 02h ; Read function	mov al, 0Fh ; Sectors to read	xor bx, bx ; ES:BX = 1000h:0000	xor dl, dl ; DL = 0, Drive 0 	int 13h ;Read! 	jnc short find_file ; If no errors, jump find_file 	jmp reboot ; else, reboot! find_file:	mov ax, 1000h	mov ds, ax ; DS = 1000h 	mov bx, 4640 ; bx = (0Fh * 512) + 32	mov cx, -32	.loop:		mov dl, 1 ; DL = FALSE 		sub bx, 32 ; BX - 32		or bx, bx		jz .endloop ; If BX = 0 then, jump .endloop 		add cx, 32 ; CX += 32		mov si, cx 		lodsb ; mov al, [SI]; inc si		cmp al, 'S'		jne short .loop 		lodsb		cmp al, 'T'		jne short .loop 		lodsb		cmp al, 'A'		jne short .loop 		lodsb		cmp al, 'G'		jne short .loop 		lodsb		cmp al, 'E'		jne short .loop 		lodsb		cmp al, '_'		jne short .loop 		lodsb		cmp al, '2'		jne short .loop 		lodsb		cmp al, ' '		jne short .loop 		lodsb		cmp al, 'B'		jne short .loop 		lodsb		cmp al, 'I'		jne short .loop 		lodsb		cmp al, 'N'		jne short .loop 		xor dl, dl ; DL = TRUE		add si, 0Fh ; SI current Pos + 15		mov cx, [si] ; Get the Starting Cluster 	.endloop: 	or dl, dl	jz short read_fat ; If DL = TRUE then, jump read_fat 	jmp reboot ; else, reboot! read_fat:	; We will overwrite the Root Directory with the FAT	mov ax, 1000h	mov es, ax ; ES = 1000h 	mov ax, 1 ; LBA = 1	push cx ; We save the Starting Cluster 	call lba2chs 	mov ah, 02h ; Function 02h: Read	mov al, 9 ; Sectors to read = SectorsPerFAT	xor dl, dl ; Drive = 0	xor bx, bx ; 1000h:0000 	int 13h 	jnc short read_data ; if no errors, then jump read_data 	jmp reboot ; else, reboot! read_data:	; FAT cluster 0 = media descriptor = 0F0h	; FAT cluster 1 = file cluster = 0FFh	; Cluster start = ((cluster number) - 2) * SectorsPerCluster + (start of user)	;               = (cluster number) + 31 	pop cx ; Restore the Starting Cluster 	xor bx, bx ; BX = 0	push bx ; Push! 	mov bx, 3000h	mov es, bx ; ES:BX = 3000h:0000	; Segment where we will load the stage_2	.loop:		mov si, 0000h ; SI Pointer to 1000h:0000 		mov ax, cx ; AX = CX		mov bx, 2 ; BX = 2		div bl ; AH = AX MOD BL 		or ah, ah		jz short .par ; If remainder = 0 then, jump .par		.impar:	; d = (n - 1 / 2) * 3 + 1			mov ax, cx ; AX = CX			dec ax			shr ax, 1			mov bx, 3 ; BX = 3			mul bx ; AX * 3			inc ax 			add si, ax ; SI + AX			mov dx, [si] ; We get the 16 bits of FAT, but we only need 12 bits 			shr dx, 4 ; DX >> 4			jmp short .next 		.par: ; d = (n / 2) * 3			mov ax, cx ; AX = CX			shr ax, 1			mov bx, 3 ; BX = 3			mul bx ; AX * 3		 			add si, ax ; SI + AX			mov dx, [si] ; We get the 16 bits of FAT, but we only need 12 bits 			and dx, 0x0FFF ; DX AND 0FFFh		.next: 			mov ax, 31 ; AX = 31			add ax, cx ; AX = AX + CX (Starting or next cluster) 			pop bx ; Restore BX 			push dx ; Save next cluster			call lba2chs			mov ah, 02h ; Read function			mov al, 1 ; 1 sector to read			xor dl, dl ; Drive = 0 			int 13h	 			pop dx ; Restore next cluster	 			cmp dx, 0x0FF8 ; Compare Next Cluster with 0x0FF8			jae short execute ; if dx >= 0x0FFF8 then, jump execute 			add bx, 512 ; BX = BX + 512			push bx ; Save BX 			mov cx, dx			jmp short .loop execute:	jmp 3000h:0000   ;**********************************************************;; Print a string in screen; SI => String pointer with NULL terminator;**********************************************************;print_string:	pusha	mov ah, 0Eh 	.loop:	mov al, [si]	or al, al	jz short .end_loop	int 10h	inc si	jmp short .loop 	.end_loop: 	mov al, 13	int 10h	mov al, 10	int 10h 	popa	ret ;**********************************************************;; Convert LBA address to CHS address; AX => LBA address;; CH <= Cilynder; DH <= Head; CL <= Sector;**********************************************************;lba2chs:	push bx ; Push bx	mov bx, ax ; Copy LBA in BX 	;AX has the LBA value	mov dl, 18 ; BL = Sectors Per Track	div dl	xchg ax, bx	;BL = Temp = LBA / (Sectors Per Track)	;BH = LBA % (Sectors Per Track)	mov cl, bh	inc cl ; CL = Sector = [LBA % (Sectors Per Track)] + 1 	xor ax, ax ; AX = 0	mov al, bl ; AL = Temp = LBA / (Sectors Per Track)	mov dx, 2 	div dl	;AL = LBA / (Number of Heads)	;AH = LBA % (Number of Heads)	mov dh, ah ; Head	mov ch, al ; Cylinder 	pop bx	ret  ;**********************************************************;; Print a error message, then wait for a keypress and reboot;**********************************************************;reboot:	mov ax, 07C0h	mov ds, ax ; DS = 07C0h 	mov si, Error	call print_string 	mov si, Reboot	call print_string 	mov ax, 0	int 16h				; Wait for keystroke	mov ax, 0	int 19h				; Reboot the system  ;**********************************************************;; Variables;**********************************************************;BootMsg:								db "Loading...", 0 Error:									db "Missing or corrupt STAGE_2.BIN!", 0Reboot:									db "Press any key to reboot...", 0  ;**********************************************************;; EOF;**********************************************************; times 510-($-$$) db 0 ; Fill with zero´sdw 0xAA55 ; Bootloader signature 
 Y aquí esta el stage_2.asm ;*******************************************************************;* STAGE 2;******************************************************************* [bits 16][ORG 0] stage2:	mov ax, 3000h		mov ds, ax	mov es, ax				mov fs, ax				mov gs, ax 	mov si, HelloString	call print_string2	jmp test  print_string2:	pusha	mov ah, 0Eh 	.loop:	mov al, [si]	or al, al	jz short .end_loop	int 10h	inc si	jmp short .loop 	.end_loop: 	mov al, 13	int 10h	mov al, 10	int 10h 	popa	ret times 512 db 'A'times 512 db 'B' test:	mov si, TestString	call print_string2	jmp $ times 512 db 'C'times 2048 db 'D' HelloString:							db "Hello from Stage_2!", 0TestString:								db "This is a test", 0 
 Para crear la imagen: fat12maker -b Stage_1.bin -i Stage_2.bin About.txt .... -o Kernel.img Ahora voy a trabajar en el Kernel, tengo que activar el modo largo y empezar a programar en C. Si encontráis errores o tenéis alguna sugerencia, postearlo aquí. Saludos y gracias. |  
						| 
								|  |  
								| « Última modificación: 25 Julio 2012, 16:38 pm por Khronos14 » |  En línea | 
 
 |  |  |  |  |  
 
	
 
   |