Page 1 of 1

Strange problem with VirtualPC

Posted: Thu May 10, 2007 11:17 am
by M@ReK
Hi,

I'm writing small kernel and bootloader. The kernel works prefect with grub but I decided to make my own bootloader. First stage load second stage file to memory and execute it in real mode, than load kernel to low mem < 1MB switch to pmode anable a20 line and copy kernel to 0x00100000. I have tested it with bochs, vmware and it works ok but with virtual pc it is not :( (unrecovable processor error) I find it occurs when kernel_mian() is called. First instruction from the kernel (setting stack pointer is executed) When I load the kernel below 1MB it is working on virtual pc ; I have tested it also on real PC's and it works :shock:
here is the code

ps. sorry for my english

first stage just load a file from fat12 formatted floppy so I think it is no need to place it's code

here is stage2

Code: Select all


  BITS 16

  ORG 0x0500

  jmp start

  %include "fat12/bpb.inc"
  %include "fat12/fat12.inc"
  %include "console.inc"
  %include "a20.inc"

error:

  mov si, messageError
  call puts

  jmp $ 

start:

  mov cx, 0x19

clear:

  mov si, messageLFCR
  call puts
  ;loop clear

  mov dl, 0x16
  mov dh, 0x0A
  call gotoxy

  mov si, messageLoading
  call puts

  mov dl, 0x16
  mov dh, 0x0C
  call gotoxy

  call enableA20
  bt ax, 0x0001
  jc $

  call calculate


  mov ax, WORD [calculate_rootStart]
	mov cx, WORD [calculate_rootSize]
	mov bx, 0x7E00
	call read

	mov cx, WORD [bpbRootEntries]
	mov si, fileName
	mov di, 0x7E00

search:

  push cx

	mov cx, 0x000B

	push si
	push di

	rep cmpsb

	pop di
	pop si

  je found
  add di, 0x0020

	pop cx

	loop search
	jmp error

found:

  mov dx, WORD [di + 0x001A]
  mov WORD [cluster], dx

  mov ax, WORD [calculate_FATstart]
  mov cx, WORD [calculate_FATsize]
  mov bx, 0x7E00
  call read

  mov ax, WORD [cluster]
  mov bx, 0x0D00

  push bx

next:

  pop bx
  push ax
  call FATtoLBA
  xor cx, cx
  mov cl, BYTE [bpbSectorsPerCluster]
  call read

  pop ax
  push bx

  mov cx, ax
  mov dx, ax
  shr dx, 0x0001
  add cx, dx
  mov bx, 0x7E00
  add bx, cx
  mov dx, WORD [bx]
  test ax, 0x0001
  jnz odd

even:

  and dx, 0x0FFF
  jmp done

odd:

  shr dx, 0x0004

done:

  mov ax, dx
  cmp dx, 0x0FF0
  jb next

  pop bx
  
  cli

  lgdt [gdth]

  mov eax, cr0
  inc ax
  mov cr0, eax

  jmp DWORD 0x08:protected

  BITS 32

protected:

  mov ax, 0x10
  mov ds, ax
  mov es, ax
  mov fs, ax
  mov gs, ax
  mov ss, ax
  mov esp, 0xFFFF
    
  mov si, 0x0D00
  mov edi, [destination]
  mov cx, 8192
  rep movsb
  mov [destination], edi

  
  jmp 0x08:0x00100000

gdt:

gdt_null:    

  dw 0x0000                         
  dw 0x0000            
  db 0x00                
  db 0x00                                       
  db 0x00                                   
  db 0x00                              

gdt_code_32:

  dw 0xFFFF                  
  dw 0x0000                                  
  db 0x00                                
  db 0x9A                                    
  db 0xCF                            
  db 0x00                                   
  
gdt_data_32: 

  dw 0xFFFF                        
  dw 0x0000                         
  db 0x00                             
  db 0x92                                
  db 0xCF                       
  db 0x00                               
  
gdt_code_16: ; selektor: 0x18

  dw 0xFFFF                         
  dw 0x0000                         
  db 0x00                          
  db 0x9a                              
  db 0x00                            
  db 0x00                               

gdt_data_16:

  dw 0xFFFF                              
  dw 0x0000                                 
  db 0x00                                    
  db 0x92                                    
  db 0x00                          
  db 0x00                                        
  
gdth:

  dw gdth - gdt - 0x01
  dd gdt

  LBAtoCHS_sector     db 0x00
  LBAtoCHS_head       db 0x00
  LBAtoCHS_track      db 0x00

  calculate_rootSize  dw 0x0000
  calculate_rootStart dw 0x0000
  calculate_dataStart dw 0x0000
  calculate_FATsize   dw 0x0000
  calculate_FATstart  dw 0x0000

  cluster             dw 0x0000
  address             dw 0x0000
  counter             dw 0x0000
  fat                 db 0x0000
  progress            db 0x00
  destination         dd 0x00100000
  kernel              db 0x00

  messageLFCR       db 0x0D, 0x0A, 0x00
  messageBackground db 0xB1, 0x00
  messageProgress   db 0xDB, 0x00
  messageLoading    db 'Trawa uruchamianie systemu Thorn...', 0x00
  messageError      db 'ERROR: Brak pliku "/system/thorn" lub jest on uszkodzony!', 0x00
  fileName          db 'THORN      ', 0x00

  times 0x7FE - ($ - $$) db 0x00                                                             
  
and the kernel entry point

Code: Select all

BITS 32

SECTION .text

global start

start:

  mov esp, system_stack                

  extern kernel_main
  call   kernel_main                     
  
  cli
  hlt                                                                                               

SECTION .bss

  resb 8192                                

system_stack:                    

Regards

Posted: Thu May 10, 2007 12:48 pm
by mathematician
Why worry? If it works with a real PC that's all that counts.

Posted: Thu May 10, 2007 3:27 pm
by M@ReK
Update: I'he just tested it on two old pentium procesors (I and III) and it works fine but on amd machine the computer reboots :?

Posted: Thu May 10, 2007 3:47 pm
by pcmattman
Correct me if I'm wrong, but that's why it's called Intel syntax... NASM assembleds to the intel opcodes.

Edit: ahh, I was wrong :oops: . I had a feeling something didn't sound right about that statement. Now I can't delete this post :cry:

Posted: Thu May 10, 2007 3:59 pm
by Combuster
I guess somebody needs to insert cli/hlt pairs and see where things go awry. Such things are usually related to wrong assumptions. Are you checking CF after a read from disk, verifying wether A20 has really been enabled, and more of that sort of necessary safeguards?

@pcmattman: thats the biggest nonsense I heard in years. AMD processors run exactly the same code as intel processors. there is no difference in opcodes whatsoever. Intel syntax is simply named after the company that invented it, not the one that uses it :shock:

Posted: Thu May 10, 2007 4:25 pm
by Brynet-Inc
haha that was rather funny... pcmattman.. aren't you supposedly writing an Operating System? :lol:

Posted: Thu May 10, 2007 4:27 pm
by pcmattman
I spend too much time in the Intel manuals, not enough in the AMD manuals. And the fact that no one ever told me. I feel deprived.

Edit: there's an ant on my monitor. I think I might take out my stress on it.

Posted: Thu May 10, 2007 4:59 pm
by Alboin
pcmattman wrote:Edit: there's an ant on my monitor. I think I might take out my stress on it.
Ahh!!!!!!!!! Ant!!!!
I really don't like bugs....the other night I saw this black moth thing fly out from somewhere....pretty weird....I wonder what else is living around my desk......Maybe I should clean it.....

In other news, the lesser known 'AMD syntax':

Code: Select all

EAT 64 INTO $R1
TU 32 OUT $R1
DIG $R1 1
EAT $R1 INTO $R2
Which of course translates to the following opcodes:

Code: Select all

DE 32 AD 04 BE 12 EF EE AE CA 43 FE EA BA 01 BE

Posted: Fri May 11, 2007 12:42 am
by M@ReK
LLLOOOLLL I think I found something :D

this is the code which copies kernel to 0x00100000

Code: Select all

mov si, 0x0d00
mov edi, [destination]
mov cx, 8192
rep movsb
I've changed it to

Code: Select all

  mov bx, 0x0D00
  mov cx, 0x02000 
  mov edx, 0x00100000

copy:

  mov al, BYTE [bx]
  mov BYTE [edx], al
  inc bx
  inc edx
  loop copy
I haven't tested it on real machine yet but on vpc is ok :wink: but why movsb crashes ?

Posted: Fri May 11, 2007 1:28 am
by Combuster
rep movsb normally comes without operand size prefix, i.e. in 16 bit modes it moves from si to di instead from esi to edi. in the second snippet you force the use of the correct register so the data is actually transferred how it was intended to be

Posted: Sat May 12, 2007 11:24 pm
by Brendan
Hi,
Combuster wrote:rep movsb normally comes without operand size prefix, i.e. in 16 bit modes it moves from si to di instead from esi to edi. in the second snippet you force the use of the correct register so the data is actually transferred how it was intended to be
Close, but it's 32-bit protected mode code.... ;)

The reason it crashes is that ESI and ECX is being used, but "mov si,0x0D00" and "mov cx, 8192" doesn't clear the upper 16-bits. For example, if the BIOS or some other code leaves 0x12345678 in ESI and 0xABCDEF01 in ECX, then the "rep movsb" would end up copying 0xABCD2000 bytes from 0x12340D00.

I'd guess it worked on some machines because the BIOS left the upper 16-bits of ESI and ECX clear, and crashed on other machines because the BIOS didn't, although it's also possible that the CPU is doing the equivelent of "mov [es:edi],[esi]; dec esi; dec edi; loop" because the direction flag isn't clear.

In any case, I'd try somethng like:

Code: Select all

  mov esi, 0x0D00
  mov edi, [destination]
  mov ecx, 8192/4
  cld
  rep movsd
  mov [destination], edi
BTW doing "mov esp, 0xFFFF" is never a good idea (the stack should be aligned). I'd use "mov esp,0x10000" but "mov esp,0xFFFC" would work too.


Cheers,

Brendan

Posted: Sun May 13, 2007 1:35 am
by M@ReK
Thanks Brendan and all of you for the replays :) I'll correct the stack pointer position, and try movsd with extended registers.