[SOLVED]p mode Jump weird behaviour

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
ND4
Posts: 4
Joined: Sat Dec 25, 2010 4:50 am

[SOLVED]p mode Jump weird behaviour

Post by ND4 »

Hello!

I made a protected mode boot loader that loads my kernel , and I want to make an absolute jump to another part in it, but for some reason it can not jump over more than 498 bytes

Code: Select all

org  1050000  ; decimal

jmp 8:a1
   times 500 -($-$$) db 0      
a1:
in Bochs it gives me this error:

interrupt () : gate descriptor is not valid sys reg

..and resets.



- I loaded the sectors at 10000 decimal and it gives the same error

- i made an IDT thinking it will fix the problem and now it doesn't give any errors but it doesn't jump either:

Code: Select all

org  10000

 lidt [idt]


 jmp 8:fidt


idt_A:

  dw isr0 , 8 , 1000111000000000b , 0
  dw isr1  , 8 , 1000111000000000b , 0
  dw isr2  , 8 , 1000111000000000b ,0
  dw isr3  , 8 , 1000111000000000b , 0
  dw isr4  , 8 , 1000111000000000b , 0
  dw isr5  , 8 , 1000111000000000b , 0
  dw isr6  , 8 , 1000111000000000b , 0
  dw isr7  , 8 , 1000111000000000b , 0
  dw isr8  , 8 , 1000111000000000b , 0
  dw isr9  , 8 , 1000111000000000b , 0
  dw isr10  , 8 , 1000111000000000b , 0
  dw isr11 , 8 , 1000111000000000b , 0
  dw isr12  , 8 , 1000111000000000b , 0
  dw isr13  , 8 , 1000111000000000b , 0
  dw isr14  , 8 , 1000111000000000b , 0
  dw isr15  , 8 , 1000111000000000b , 0
  dw isr16  , 8 , 1000111000000000b , 0
  dw isr17  , 8 , 1000111000000000b , 0
  dw isr18  , 8 , 1000111000000000b , 0
  dw isr19  , 8 , 1000111000000000b , 0
  dw isr20 , 8 , 1000111000000000b , 0
  dw isr21 , 8 , 1000111000000000b , 0
  dw isr22  , 8 , 1000111000000000b , 0
  dw isr23  , 8 , 1000111000000000b , 0
  dw isr24  , 8 , 1000111000000000b , 0
  dw isr25  , 8 , 1000111000000000b , 0
  dw isr26  , 8 , 1000111000000000b , 0
  dw isr27  , 8 , 1000111000000000b , 0
  dw isr28  , 8 , 1000111000000000b , 0
  dw isr29  , 8 , 1000111000000000b , 0
  dw isr30  , 8 , 1000111000000000b , 0
  dw isr31 , 8 , 1000111000000000b , 0

  dw irq0  , 8 , 1000111000000000b , 0
  dw irq1  , 8 , 1000111000000000b , 0
  dw irq2  , 8 , 1000111000000000b , 0
  dw irq3  , 8 , 1000111000000000b , 0
  dw irq4  , 8 , 1000111000000000b , 0
  dw irq5  , 8 , 1000111000000000b ,0
  dw irq6  , 8 , 1000111000000000b , 0
  dw irq7  , 8 , 1000111000000000b , 0

idt_B:


idt:
dw  idt_B - idt_A - 1
dd  idt_A            


...



jmp 8:a1
   times 800 -($-$$) db 0       ; 498
a1:

 mov byte[0xB8004], "3"
 mov byte[0xB8005], 00011011b   


hlt
- I also tried to jump with

Code: Select all

push cs
push a1
retf 
... and it doesn't work


My GDT is an avrage gdt , nothing fancy

Code: Select all

        cli

        lgdt  [gdt]

        mov eax,17
        mov cr0,eax

        jmp   8:Mode32


gdt_A:
 NullDescriptor:
    dq 0
 CodeDescriptor:    ; CodeDescriptor = 8
    dw 0FFFFh
    dw 0
    db 0
    db 10011010b
    db 11001111b
    db 0
 DataDescriptor:    ; DataDescriptor = 16
    dw 0FFFFh
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
gdt_B:

gdt:
   dw gdt_B - gdt_A - 1
   dd gdt_A  

Why can't I jump anywhere I want?
Last edited by ND4 on Tue Dec 28, 2010 12:23 am, edited 1 time in total.
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: p mode Jump weird behaviour

Post by Chandra »

Your code is kinda messed up. I dont see the stack being setup.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: p mode Jump weird behaviour

Post by bewing »

Hmmm. "al" is a bit of a reserved keyword, since it is the name of a register. I'm not sure it's a good idea to try to use it for a label.
ecco
Posts: 19
Joined: Mon Nov 29, 2010 1:21 am
Location: Anchorage, AK

Re: p mode Jump weird behaviour

Post by ecco »

Hmmm I wouldn't recommend using decimal values for ORG it can be confusing to read and most people expect to deal hex when it comes to memory addresses. I suspect things are not being placed where you expect therefore only short jumps will work. I would also try using JMP $ for testing, HLT will only stop for one interrupt I believe.
ND4
Posts: 4
Joined: Sat Dec 25, 2010 4:50 am

Re: p mode Jump weird behaviour

Post by ND4 »

Thanks for replies
- the label is not al it's a1 (a one)
- I replaced HLT with JMP $ - and it's the same
- I triple verified the memory locations in decimal and everything ends up where I expected and within usable memory areas, but I tried with hex values too

Code: Select all

org 7C00h

; video mode 80x25:
 mov     ah, 00h
 mov     al, 03h
 int     10h

; hide blinking
 mov ch, 32
 mov ah, 1
 int 10h

 ;  initialise registers
 mov  ax , 0
 mov  ds , ax
 mov  es , ax
 mov  fs , ax
 mov  gs , ax
 mov  ss , ax
 mov  sp , 2710h  ; 10 000 dec
 mov  bp , 2710h  

 xor  eax , eax
 xor  ebx , ebx
 xor  ecx , ecx
 xor  edx , edx
 xor  edi , edi
 xor  esi , esi

; -------------------------- enter 32 bit mode ----------------------------

        cli

        lgdt  [gdt]

        mov eax,17
        mov cr0,eax

        jmp   8:Mode32

; --------------------------------------  GDT  --------------------------------------------

gdt_A:
 NullDescriptor:
    dq 0
 CodeDescriptor:    ; CodeDescriptor = 8
    dw 0FFFFh
    dw 0
    db 0
    db 10011010b
    db 11001111b
    db 0
 DataDescriptor:    ; DataDescriptor = 16
    dw 0FFFFh
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
gdt_B:

gdt:
   dw gdt_B - gdt_A - 1
   dd gdt_A

; --------------------------------------  GDT  --------------------------------------------
use32
Mode32:

 mov  ax , 16  ; DataDescriptor
 mov  ds , ax
 mov  es , ax
 mov  fs , ax
 mov  gs , ax
 mov  ss , ax
 mov  esp , 9FAB0h  ; 654 000   dec
 mov  ebp , 9FAB0h  ; 654 000   dec

 xor  eax , eax
 xor  ebx , ebx
 xor  ecx , ecx
 xor  edx , edx
 xor  edi , edi
 xor  esi , esi

; -------------------------------------------------------------------------------------------



; print a character
 mov byte[0xB8000], "1"
 mov byte[0xB8001], 00011011b


; load sectors
  call loadM


; jump to loaded code
 jmp 8h:2710h  ; 10 000 dec



loadM:

; load sectors

mov     dx,0x1F1
mov     al,0h
out     dx,al

; sector count
mov     dx,1f2h
mov     al,10           ; number of sectors to read
out     dx,al


; sector location
mov     dx,1f3h
mov     al,1
out     dx,al

mov     dx,1f4h
mov     al,0
out     dx,al

mov     dx,1f5h
mov     al,0
out     dx,al

mov     dx,1f6h
mov     al,01000000b
out     dx,al


; read/write command
mov     dx,1f7h
mov     al,20h          ;20h - read    30h - write
out     dx,al


WhaitRead:
  in      al,dx
  test    al,8
jz WhaitRead


mov     cx,256
mov     edi, 2710h   ; location in RAM
mov     dx,1f0h
rep     insw

ret


; fill with zeroes the rest
times 510-($-$$) db 0
dw 0xAA55
; -------------------------------------------------------------------------------------------
; ---------------------------------- Kernel -----------------------------------
; -------------------------------------------------------------------------------------------

org 2710h


 lidt [idt]


 jmp 8:JumpOverIDT
; --------------------------------------  IDT --------------------------------------------
idt_A:
  ; Offset Low | Code Selector | Flags | Offset High
  dw isr0 , 8 , 1000111000000000b , 0
  dw isr1  , 8 , 1000111000000000b , 0
  dw isr2  , 8 , 1000111000000000b ,0
  dw isr3  , 8 , 1000111000000000b , 0
  dw isr4  , 8 , 1000111000000000b , 0
  dw isr5  , 8 , 1000111000000000b , 0
  dw isr6  , 8 , 1000111000000000b , 0
  dw isr7  , 8 , 1000111000000000b , 0
  dw isr8  , 8 , 1000111000000000b , 0
  dw isr9  , 8 , 1000111000000000b , 0
  dw isr10  , 8 , 1000111000000000b , 0
  dw isr11 , 8 , 1000111000000000b , 0
  dw isr12  , 8 , 1000111000000000b , 0
  dw isr13  , 8 , 1000111000000000b , 0
  dw isr14  , 8 , 1000111000000000b , 0
  dw isr15  , 8 , 1000111000000000b , 0
  dw isr16  , 8 , 1000111000000000b , 0
  dw isr17  , 8 , 1000111000000000b , 0
  dw isr18  , 8 , 1000111000000000b , 0
  dw isr19  , 8 , 1000111000000000b , 0
  dw isr20 , 8 , 1000111000000000b , 0
  dw isr21 , 8 , 1000111000000000b , 0
  dw isr22  , 8 , 1000111000000000b , 0
  dw isr23  , 8 , 1000111000000000b , 0
  dw isr24  , 8 , 1000111000000000b , 0
  dw isr25  , 8 , 1000111000000000b , 0
  dw isr26  , 8 , 1000111000000000b , 0
  dw isr27  , 8 , 1000111000000000b , 0
  dw isr28  , 8 , 1000111000000000b , 0
  dw isr29  , 8 , 1000111000000000b , 0
  dw isr30  , 8 , 1000111000000000b , 0
  dw isr31 , 8 , 1000111000000000b , 0

  dw irq0  , 8 , 1000111000000000b , 0
  dw irq1  , 8 , 1000111000000000b , 0
  dw irq2  , 8 , 1000111000000000b , 0
  dw irq3  , 8 , 1000111000000000b , 0
  dw irq4  , 8 , 1000111000000000b , 0
  dw irq5  , 8 , 1000111000000000b ,0
  dw irq6  , 8 , 1000111000000000b , 0
  dw irq7  , 8 , 1000111000000000b , 0

idt_B:


idt:
dw  idt_B - idt_A - 1
dd  idt_A


isr0:    ; iret
isr1:
isr2:
isr3:
isr4:
isr5:
isr6:
isr7:
isr8:
isr9:
isr10:
isr11:
isr12:
isr13:
isr14:
isr15:
isr16:
isr17:
isr18:
isr19:
isr20:
isr21:
isr22:
isr23:
isr24:
isr25:
isr26:
isr27:
isr28:
isr29:
isr30:
isr31:


irq0:   ; iret
irq1:
irq2:
irq3:
irq4:
irq5:
irq6:
irq7:

; -----------------------------------------------------------------------------------
JumpOverIDT:



jmp 8:JumpOverSomeCode
   times 800 -($-$$) db 0       ; 498
JumpOverSomeCode:

 mov byte[0xB8002], "2"
 mov byte[0xB8003], 00011011b


jmp $

User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: p mode Jump weird behaviour

Post by Brendan »

Hi,

I tried this code from a USB flash disk and it crashed. I tried to boot it from an external (USB) hard drive, and that crashed. Then I tried to boot it from a CD-ROM (using "El-Torito" hard disk emulation) and it crashed. I Installed it on the first hard drive of 2 different test computers (with different SCSI controllers) and it crashed. Then I tried on another different computer (with a SATA drive that uses AHCI) and it crashed. I found a computer that has some old ATA drives and I configured GRUB to chainload it from the second drive and it crashed. Then I created a partition on the first hard drive (on the system with ATA drives) so I don't need to trash GRUB, and installed it in that partition and told GRUB to chainload it and it crashed. The drive was large though (e.g. 500 GiB) and the partition was near the end of the drive, and I was thinking that maybe there's a subtle bug in your code that supports 48-bit LBA, so I created another new partition (near the start of the disk) and tried again. It crashed again.

There were no error messages displayed by your code at any step on any of these systems. No error message saying that it failed to load the sectors, and no error message saying that the kernel was loaded correctly but failed a CRC check or something. Because there was no errors, I assume that the kernel was loaded correctly in all of the cases above, and that it crashes for some other reason...


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
ND4
Posts: 4
Joined: Sat Dec 25, 2010 4:50 am

Re: p mode Jump weird behaviour

Post by ND4 »

[quote="Brendan"][/quote]

Thank you for verifying!
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: p mode Jump weird behaviour

Post by DavidCooper »

ND4 wrote:; print a character
mov byte[0xB8000], "1"
mov byte[0xB8001], 00011011b
I assume it prints that out, so your GDT must work.
; load sectors
call loadM


; jump to loaded code
jmp 8h:2710h ; 10 000 dec
This bit here, however, suggests that the last bit will never run the final bit of the code that prints 2 to the screen because it jumps instead into the code you've just loaded at 10000, so do you have anything in that code to print to the screen?

Here's something that may be an issue:-
; sector count
mov dx,1f2h
mov al,10 ; number of sectors to read
out dx,al
It looks as if you're trying to load in ten sectors (I've never communicated with hard disk controllers in this way so I could be wrong), but...
mov cx,256
mov edi, 2710h ; location in RAM
mov dx,1f0h
rep insw
...it then looks as if this bit only loads a single sector before the count runs out.

You shouldn't need the IDT at this stage at all, but it probably isn't doing any harm - just making it harder for me to see what's going on as I'm not into assembler.
jmp 8:JumpOverSomeCode
times 800 -($-$$) db 0 ; 498
JumpOverSomeCode:

mov byte[0xB8002], "2"
mov byte[0xB8003], 00011011b
And that's the bit that doesn't look as if it can ever run.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
jasorod
Posts: 2
Joined: Sun Dec 26, 2010 11:15 pm

Re: p mode Jump weird behaviour

Post by jasorod »

Hi,

I'm not that familiar with MASM (which by the assembler directives is what I believe you're using), so I re-assembled your code as a flat binary in NASM,with some slight adjustments to the labeling due to the fact that NASM throws an error with multiple ORG directives unlike MASM.

It seems that the main issue is that the hard-drive loading subroutine is not getting all the data from the disk into memory. Using QEMU, when I inspected the memory location at 0x2710, it was not the right length ... there were simply zero's past the second-to-last long jump where you wanted to jump over "some code", causing the instruction pointer to run wild through memory. You can see in my adjusted code below, that I've reduced the number of zeroed bytes to jump over, and that seemed to be just enough to get everything into memory so that there were no issues when running in QEMU.

Other than the hard-drive loading subroutine, your GDT and IDT looked good (for what they were), and the jump to 32-bit protected mode seemed to work fine as well once all the code was loaded into memory and wasn't truncated.

I ran the code with:
nasm -f bin [binary_filename]
qemu -hda [binary_filename]

Code: Select all

ORG 2710h

start_bs_code:

; video mode 80x25:
mov     ah, 00h
mov     al, 03h
int     10h

; hide blinking
mov ch, 32
mov ah, 1
int 10h

;  initialise registers
mov  ax , 0
mov  ds , ax
mov  es , ax
mov  fs , ax
mov  gs , ax
mov  ss , ax
mov  sp , 2710h  ; 10 000 dec
mov  bp , 2710h

xor  eax , eax
xor  ebx , ebx
xor  ecx , ecx
xor  edx , edx
xor  edi , edi
xor  esi , esi

; -------------------------- enter 32 bit mode ----------------------------

        cli

        lgdt  [GDT_DESCRIPTOR_PTR]

        mov eax, cr0
        or eax, 0x1
        mov cr0,eax
		
        jmp   0x8:MODE32_OFFSET

; --------------------------------------  GDT  --------------------------------------------

gdt_A:
NullDescriptor:
    dq 0
CodeDescriptor:    ; CodeDescriptor = 8
    dw 0FFFFh
    dw 0
    db 0
    db 10011010b
    db 11001111b
    db 0
DataDescriptor:    ; DataDescriptor = 16
    dw 0FFFFh
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
gdt_B:

GDT_OFFSET_START equ (0x7C00 + (gdt_A - 0x2710))
GDT_DESCRIPTOR_PTR equ (0x7C00 + (gdt - 0x2710))

gdt:
   dw gdt_B - gdt_A
   dd GDT_OFFSET_START

; --------------------------------------  GDT  --------------------------------------------
BITS 32
MODE32_OFFSET equ (0x7C00 + (Mode32 - 0x2710))
Mode32:

mov  ax , 16  ; DataDescriptor
mov  ds , ax
mov  es , ax
mov  fs , ax
mov  gs , ax
mov  ss , ax
mov  esp , 9FAB0h  ; 654 000   dec
mov  ebp , 9FAB0h  ; 654 000   dec

xor  eax , eax
xor  ebx , ebx
xor  ecx , ecx
xor  edx , edx
xor  edi , edi
xor  esi , esi

; -------------------------------------------------------------------------------------------



; print a character
mov byte[0xB8000], "1"
mov byte[0xB8001], 00011011b

; load sectors
call loadM

; jump to loaded code
jmp 8h:2710h  ; 10 000 dec


loadM:

; load sectors

mov     dx,0x1F1
mov     al,0h
out     dx,al

; sector count
mov     dx,1f2h
mov     al,10           ; number of sectors to read
out     dx,al


; sector location
mov     dx,1f3h
mov     al,1
out     dx,al

mov     dx,1f4h
mov     al,0
out     dx,al

mov     dx,1f5h
mov     al,0
out     dx,al

mov     dx,1f6h
mov     al,01000000b
out     dx,al


; read/write command
mov     dx,1f7h
mov     al,20h          ;20h - read    30h - write
out     dx,al


WhaitRead:
  in      al,dx
  test    al,8
jz WhaitRead


mov     cx,256
mov     edi, 2710h   ; location in RAM
mov     dx,1f0h
rep     insw

ret

end_bs_code:

; fill with zeroes the rest
times (510 - (end_bs_code - start_bs_code)) db 0
dw 0xAA55
; -------------------------------------------------------------------------------------------
; ---------------------------------- Kernel -----------------------------------
; -------------------------------------------------------------------------------------------
kernel_start:

lidt [IDT_PTR_OFFSET]

jmp 8:JUMP_OVER_IDT_OFFSET
; --------------------------------------  IDT --------------------------------------------
idt_A:
  ; Offset Low | Code Selector | Flags | Offset High
  dw isr0 , 8 , 1000111000000000b , 0
  dw isr1  , 8 , 1000111000000000b , 0
  dw isr2  , 8 , 1000111000000000b ,0
  dw isr3  , 8 , 1000111000000000b , 0
  dw isr4  , 8 , 1000111000000000b , 0
  dw isr5  , 8 , 1000111000000000b , 0
  dw isr6  , 8 , 1000111000000000b , 0
  dw isr7  , 8 , 1000111000000000b , 0
  dw isr8  , 8 , 1000111000000000b , 0
  dw isr9  , 8 , 1000111000000000b , 0
  dw isr10  , 8 , 1000111000000000b , 0
  dw isr11 , 8 , 1000111000000000b , 0
  dw isr12  , 8 , 1000111000000000b , 0
  dw isr13  , 8 , 1000111000000000b , 0
  dw isr14  , 8 , 1000111000000000b , 0
  dw isr15  , 8 , 1000111000000000b , 0
  dw isr16  , 8 , 1000111000000000b , 0
  dw isr17  , 8 , 1000111000000000b , 0
  dw isr18  , 8 , 1000111000000000b , 0
  dw isr19  , 8 , 1000111000000000b , 0
  dw isr20 , 8 , 1000111000000000b , 0
  dw isr21 , 8 , 1000111000000000b , 0
  dw isr22  , 8 , 1000111000000000b , 0
  dw isr23  , 8 , 1000111000000000b , 0
  dw isr24  , 8 , 1000111000000000b , 0
  dw isr25  , 8 , 1000111000000000b , 0
  dw isr26  , 8 , 1000111000000000b , 0
  dw isr27  , 8 , 1000111000000000b , 0
  dw isr28  , 8 , 1000111000000000b , 0
  dw isr29  , 8 , 1000111000000000b , 0
  dw isr30  , 8 , 1000111000000000b , 0
  dw isr31 , 8 , 1000111000000000b , 0

  dw irq0  , 8 , 1000111000000000b , 0
  dw irq1  , 8 , 1000111000000000b , 0
  dw irq2  , 8 , 1000111000000000b , 0
  dw irq3  , 8 , 1000111000000000b , 0
  dw irq4  , 8 , 1000111000000000b , 0
  dw irq5  , 8 , 1000111000000000b ,0
  dw irq6  , 8 , 1000111000000000b , 0
  dw irq7  , 8 , 1000111000000000b , 0

idt_B:

IDT_OFFSET equ (0x2710 + (idt_A - kernel_start))
IDT_PTR_OFFSET equ (0x2710 + (idt - kernel_start))

idt:
dw  idt_B - idt_A
dd  IDT_OFFSET

isr0:    ; iret
isr1:
isr2:
isr3:
isr4:
isr5:
isr6:
isr7:
isr8:
isr9:
isr10:
isr11:
isr12:
isr13:
isr14:
isr15:
isr16:
isr17:
isr18:
isr19:
isr20:
isr21:
isr22:
isr23:
isr24:
isr25:
isr26:
isr27:
isr28:
isr29:
isr30:
isr31:


irq0:   ; iret
irq1:
irq2:
irq3:
irq4:
irq5:
irq6:
irq7:

; -----------------------------------------------------------------------------------
JUMP_OVER_IDT_OFFSET equ (0x2710 + (JumpOverIDT - kernel_start))
JumpOverIDT:

JUMP_OVER_SOME_CODE_OFFSET equ (0x2710 + (JumpOverSomeCode - kernel_start))
jmp 8:JUMP_OVER_SOME_CODE_OFFSET
   times 146 db 0       ; 498
JumpOverSomeCode:

mov byte[0xB8002], "2"
mov byte[0xB8003], 00011011b


jmp $
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: p mode Jump weird behaviour

Post by DavidCooper »

Ah, I didn't spot the "org 2710h" bit, so the bit displaying 2 to the screen's in the code loaded by the earlier part, and only one sector of it's being loaded because cx has been set to 256 instead of 2560.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
ND4
Posts: 4
Joined: Sat Dec 25, 2010 4:50 am

Re: p mode Jump weird behaviour

Post by ND4 »

Thank you!

yes that was the problem.

I thought that the value in cx was supposed to be the count for each sector at a time , and only be changed when having HDD's with 1024 byte sectors.
Post Reply