Bound Range Exceeded Exception on jmp [solved]
Bound Range Exceeded Exception on jmp [solved]
So, I'm back to trying to get "shutting down" to work in my kernel. I'm using the guide here->http://www.osdever.net/tutorials/pm.php in order to switch back to real mode to call the APM functions. The second step says to do a far jump to a 16 bit code segment. I have created a 16bit code segment in my GDT at offset 0x18 and I have loaded the 16bit shutdown code so that the code starts at 0x2000. When I try to jump to the code, however, I get this weird "Bound Range Exceeded" exception. I have read the Intel manuals and, as far as I can tell, this exception can only be thrown by a BOUNDS instruction. I have never used the BOUNDS instruction so I guess it is being inserted by NASM. If anyone could shed some light on this it would be greatly appreciated.
Last edited by Stevo14 on Tue May 06, 2008 12:28 am, edited 1 time in total.
Does this help, its fasm code written for DexOS by smiddy:
Code: Select all
PowerDown:
call DisableAllIRQs
mov al,11h
out 020h,al
out 0A0h,al
mov al,08h
out 021h,al
mov al,070h
out 0A1h,al
mov al,4
out 021h,al
mov al,2
out 0A1h,al
mov al,1
out 021h,al
out 0A1h,al
jmp 28h:RealModePowerDown
use16
PowerManagmentVersion dw 0
NoPowerManagment db 'No power management functionality',10,13,0
ErrorMessage db 'Power management error',10,13,0
WrongVersion db 'Need APM version 1.1 or better',10,13,0
RealModePowerDown:
mov ax,30h
mov ds,ax
mov ss,ax
nop
mov bx,[RealModeCS]
push bx
lea bx,[DoPowerDownRealMode]
push bx
mov eax,cr0
and al,0xFE
mov cr0,eax
retf
DoPowerDownRealMode:
mov ax,cs ; Save CS to AX
mov ds,ax ; Put DS to CS
mov ax,[StackSegment] ; Save original stack segment to AX
mov ss,ax ; Replace original stack segment
mov ax,[StackPointer] ; Save the stack pointer to AX
movzx esp,ax ; and Replace original stack pointer (force 16 bit)
nop ; Take a CPU clock tick
mov es,ax ; Update ES with AX
mov fs,ax ; Update FS with AX
mov gs,ax ; Update GS with AX
;;;;;;;;;;;;;;;;;;;;;;;
;; Load real mode IDTR
;;;;;;;;;;;;;;;;;;;;;;;
lidt [RIDTR] ; Load original IVT from 0000:0000
push cs ; Put CS on stack
pop ds ; Put CS from stack to DS
push ds ; Save DS to the stack
pop es ; Update ES with DS from stack
mov al,0 ; Re-enable realmode IVT by turning on all IRQs
out 0A1h,al ; Updates lower 7 IRQs
out 021h,al ; Updates upper 8 IRQs
sti ; Re-enable interrupts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Now to do the real mode interrupt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov ax,5300h ; See if APM available
mov bx,0 ; device = BIOS
int 15h
mov si,NoPowerManagment
jc .Error
cmp ax,101h ; See if version 1.1 or greater
mov dx,WrongVersion
jc .Error
mov [PowerManagmentVersion],ax
mov ax,5301h ; Do a real mode connection
mov bx,0 ; device = BIOS
int 15h
jnc .NoConnectionError
cmp ah,2 ; Pass if already connected
mov si,ErrorMessage ; else error
jnz .Error
.NoConnectionError:
mov ax,530eh ; Enable latest version of APM
mov bx,0 ; device = BIOS
mov cx,[PowerManagmentVersion] ; version
int 15h
mov si,ErrorMessage
jc .Error
mov ax,530dh ; Now engage and enable CPU management
mov bx,1 ; device = all
mov cx,1 ; enable
int 15h
mov si,ErrorMessage
jc .Error
mov ax,530fh
mov bx,1 ; device = ALL
mov cx,1 ; enable
int 15h
mov si,ErrorMessage
jc .Error
mov ax,5307h ; Do the power down
mov bx,1 ; device = ALL
mov cx,3 ; mode = OFF
int 15h ; shutdown CPU
mov si,ErrorMessage
.Error:
call PrintString
jmp CheckCodeSegment ; Change this to the DOS check for EXIT or REBOOT
; ret
Use32 ; No expected return
- Combuster
- 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: Bound Range Exceeded Exception on jmp
You too, young padawan, must learn not to blame the compiler.Stevo14 wrote:I have never used the BOUNDS instruction so I guess it is being inserted by NASM.
You're probably executing somewhere in the data area. Have you at least tried using bochs' debugger?
Re: Bound Range Exceeded Exception on jmp
Yea, sorry. That was just my first instinct. I will continue to learn.Combuster wrote:You too, young padawan, must learn not to blame the compiler.Stevo14 wrote:I have never used the BOUNDS instruction so I guess it is being inserted by NASM.
No, I have not. I had endless problems trying to compile a version with debugging enabled, so I just stuck with the default package.Combuster wrote: You're probably executing somewhere in the data area. Have you at least tried using bochs' debugger?
@Dex: If I'm following the code correctly, it doesn't use a jmp command to set the code segment but rather pushes the code segment and address onto the stack and then simulates a return. Is there any specific reason for this?
Re: Bound Range Exceeded Exception on jmp
Its just one of the instructions that change the CS register like:Stevo14 wrote:
@Dex: If I'm following the code correctly, it doesn't use a jmp command to set the code segment but rather pushes the code segment and address onto the stack and then simulates a return. Is there any specific reason for this?
jmp (far)
retf
iret
I have written many demos, one that demos go to and from real mode to pmode, for vesa mode switching, it may help you, with your problem.
http://www.dex4u.com/demos/VesaDemo.zip
Re: Bound Range Exceeded Exception on jmp
I feel like a total idiot.... I forgot to tell Bochs to load the shutdown code as a module so I was, in fact, trying to jump into some random garbage instead of my code...
Here are the relevant portions of code:
and the declarations at the end of the code:
EDIT: More specifically, it seems things go wrong when the processor tries to return from an interrupt. A good example is using int 10 to print a character. The character is printed fine but after it is printed it starts running off into unknown memory.
Thanks for that link. After realizing my stupid mistake I used your demo to help me get into real mode. Now I'm back to where I was last time, getting interrupts to work. I have loaded the Ivt using the lidt instruction (like in the demo) but whenever I invoke an interrupt (int 0x10 for example) it seems to jump off into some random piece of memory.Dex wrote: I have written many demos, one that demos go to and from real mode to pmode, for vesa mode switching, it may help you, with your problem.
http://www.dex4u.com/demos/VesaDemo.zip
Here are the relevant portions of code:
Code: Select all
;***********************************************************;
;************* Protected Mode **************;
;***********************************************************;
use32
exit_pmode:
cli ;make sure interrupts are disabled
;clear all registers
xor eax,eax
xor ebx,ebx
xor ecx,ecx
xor edx,edx
xor esp,esp
xor ebp,ebp
xor esi,esi
xor edi,edi
;point the processor to the real mode gdt
lgdt [gdtr]
;load the real mode data segments
mov ax,0x10
mov ds,ax
mov ss,ax
mov es,ax
mov fs,ax
mov gs,ax
nop
;load the real mode code segment
jmp 0x08:exit_pmode2
exit_pmode2:
;disable protection (go into real mode)
mov eax,cr0
and al,0xFE
mov cr0,eax
;***********************************************************;
;************* Start Real Mode **************;
;***********************************************************;
use16
init_real_mode:
;realmode segments
mov ax,0x00
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ax,rm_stack_bottom
mov ss,ax
;point the processor to the real mode interrupt table
lidt [idtr]
;load the realmode stack
mov ax,rm_stack_top
mov sp,ax
mov ax,0x0000
mov bp,ax
sti ;re enable interrupts
Code: Select all
rm_stack_bottom:
resb 0x1000
rm_stack_top:
idtr:
dw 0xFFFF ;idt limit
dd 0x00000000 ;idt base
gdtr:
dw gdt_end - gdt - 1 ; GDT limit
dd gdt ; (GDT base gets set above)
gdt: ; Address for the gdt
dw 0 ; limit 15:0 (0h) Null Segment
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
real_code_1: ; (20h) Real mode code segment
dw 0xFFFF
dw 0
db 0
db 10011010b
db 0
db 0
real_data_1: ; (28h) Real mode data segment
dw 0xFFFF
dw 0
db 0
db 10010010b
db 0
db 0
gdt_end: ; Used to calculate the size of the GDT
Here things to watch:
1. do you remap pic on entering pmode ?, as these may need setting back.
2. In the demo and my OS, i set addressing identical in realmode and protected mode, by setting the base of the code and data descriptors to DS * 16.
If not you have to do this each time you switch to realmode from pmode and use pointers etc.
3. Is the realmode stack below 1MB ?.
Are you sure this is right
8h does not seem right, also you first go from pmode to 16bit pmode, than realmode
Here some well commented code that may help, nasm this time
1. do you remap pic on entering pmode ?, as these may need setting back.
2. In the demo and my OS, i set addressing identical in realmode and protected mode, by setting the base of the code and data descriptors to DS * 16.
If not you have to do this each time you switch to realmode from pmode and use pointers etc.
3. Is the realmode stack below 1MB ?.
Are you sure this is right
Code: Select all
jmp 0x08:exit_pmode2
Here some well commented code that may help, nasm this time
- Attachments
-
- PM1.ASM
- (24.8 KiB) Downloaded 84 times
Yes, I do but I didn't think about remapping it back. This seems like a likely culprit. I will look into it.Dex wrote:Here things to watch:
1. do you remap pic on entering pmode ?, as these may need setting back.
I'm not exactly sure what you mean by this. In my OS the segments for pmode have a base of 0x00 and a limit of 4GB. I change this though by loading the 16bit pmode gdt.Dex wrote: 2. In the demo and my OS, i set addressing identical in realmode and protected mode, by setting the base of the code and data descriptors to DS * 16.
If not you have to do this each time you switch to realmode from pmode and use pointers etc.
Yes. It actually comes right after the code at about 0x2000. It has a size of 0x1000 (and it grows downward).Dex wrote: 3. Is the realmode stack below 1MB ?.
0x08 is the offset in the new gdt to the 16bit code selector.Dex wrote: Are you sure this is right8h does not seem right, also you first go from pmode to 16bit pmode, than realmodeCode: Select all
jmp 0x08:exit_pmode2
Thanks again. Well commented sample code is much appreciated.Dex wrote: Here some well commented code that may help, nasm this time
Hey, It works now! My mistake was rather simple. I wasn't properly setting the real mode code segment. All I did was add
and it worked! I can post the full code if someone wants it. It has also been committed to the goglecode repository if someone wants to get it that way.
Many thanks to all who helped me.
Code: Select all
;realmode code segment
jmp 0x00:rmode
Many thanks to all who helped me.