flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Directly from realmode to longmode

Goto page Previous  1, 2
Author
Thread Post new topic Reply to topic
sinsi



Joined: 10 Aug 2007
Posts: 693
Location: Adelaide
sinsi
A simple CLI should do it. A mode change, for example, shouldn't take too long.
The code is there in the video BIOS - all you do is copy it to your memory, then it gets treated as 16-bit PM code. You supply the descriptors for code and data and away we go.

Anyway, that's how I read the vesa spec.
Post 05 Jun 2008, 13:41
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17270
Location: In your JS exploiting you and your system
revolution
Do you mean 16bit RM mode? I think the normal BIOS is expecting RM mode. This would mean that you have no control over the interrupt flag once you relinquish execution to an RM task. The RM task may enable interrupts, or change some hardware configuration that requires you to remap all your virtual pages on the PM side. It could be very tricky. One way around it is to go to 32bit PM mode and run a v8086 task inside that to catch any unwanted activity with the interrupt flag and things. That could also be tricky.
Post 05 Jun 2008, 13:49
View user's profile Send private message Visit poster's website Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3170
Location: Denmark
f0dder
revolution: I think sinsi is talking about the VESA "protected mode interface", which is 16bit PM code that you call by copying the code and calling it's entry-point, not by issuing an INT.

Personally, I'd probably go the emulation way and emulate the 16bit rm INTs, it's a decent amount of work, but it feels "safer". It's what 64bit windows does, as vid found out.
Post 05 Jun 2008, 14:41
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17270
Location: In your JS exploiting you and your system
revolution
f0dder wrote:
revolution: I think sinsi is talking about the VESA "protected mode interface", which is 16bit PM code that you call by copying the code and calling it's entry-point, not by issuing an INT.
Okay, thanks for the clarification.
f0dder wrote:
Personally, I'd probably go the emulation way and emulate the 16bit rm INTs, it's a decent amount of work, but it feels "safer". It's what 64bit windows does, as vid found out.
Yes, this is the safest way to go about it. Switching 64bit<-->16bit modes is rather troublesome and an easy way to get unexpected problems if future CPUs implement the mechanism differently and break such code.
Post 05 Jun 2008, 15:10
View user's profile Send private message Visit poster's website Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 693
Location: Adelaide
sinsi
f0dder wrote:
It's what 64bit windows does, as vid found out.

Can you give me a link to that? I just cannot search this forum with *any* degree of success... Crying or Very sad
Post 06 Jun 2008, 07:23
View user's profile Send private message Reply with quote
MazeGen



Joined: 06 Oct 2003
Posts: 975
Location: Czechoslovakia
MazeGen
Post 06 Jun 2008, 09:47
View user's profile Send private message Visit poster's website Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 693
Location: Adelaide
sinsi
Cheers mate!
Post 06 Jun 2008, 09:55
View user's profile Send private message Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville
sinsi wrote:
I'm just starting to play with 64-bit and long mode and was wondering if there's any problem with going straight to long mode without the protected mode part. The code in the attachment works in qemu and a real computer booting from a floppy.


Um, sorry, but how do you see attachments???

_________________
FAMOS - the first memory operating system
Post 19 Jul 2008, 05:12
View user's profile Send private message Visit poster's website Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville
Hey, thats weird....

After I wrote that last post, I refreshed the page and then there was a paperclip next to sinsi's first post, and sure enough - an attachment!

I swear it wasn't there before ..... honest!

I wonder why???
Post 19 Jul 2008, 05:17
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Perhaps you wasn't logged in when you saw the first page of this thread?
Post 19 Jul 2008, 05:38
View user's profile Send private message Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville
LocoDelAssembly wrote:
Perhaps you wasn't logged in when you saw the first page of this thread?


I've only been on this board a week so I guess I'm still getting used to it.

The other weird thing is I had logged on, but by the time I went to post a message it said I was logged off again... Anyway thanks Smile

_________________
FAMOS - the first memory operating system
Post 20 Jul 2008, 00:14
View user's profile Send private message Visit poster's website Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville
I noticed sinsi uses org 7C00h in the bootloader.

Beware that not all BIOS's do a Far jmp to 0000:7C00h (setting CS=0, IP=7C00h) when they pass control to the bootloader.

Early in my FAMOS development days (5 years ago now!) I discovered some BIOS's do a Far jmp to 07C0h:0000 which of course is still the same linear address 00007C00h.

But if the code offsets aren't what the cpu expects unexpected things can happen (e.g. all embedded data references such as text strings won't be found and won't be displayed correctly.

So its a good idea to force CS:IP to be what you want it to be as soon as possible in the bootloader, using your own Far jmp.
Because a Far jmp is 5 bytes, the first instruction could be:

jmp 0000:7C05h ;which jmps straight to the next address at 00007C05h and enforces CS=0

If CS=7C0h and IP=0 on entry from the BIOS this will fix it.

In FAMOS I often use org 0100h because there are many DOS utilities I can use to pre-test my code as a flat binary COM
file before migrating it to FAMOS.
So my first bootloader instruction would be:

jmp 07B0h:0105h ;which still gets to linear address 00007C05h


Actually I have a boot header as well so the first instructions are the standard 2-byte Near jmp + nop.
The Near jmp jumps over the 59-byte header (at offset +003Eh) so my code is:

org 0100h

jmp start
nop
header:
spt dw 0200h etc. (59 bytes)


start: jmp 07B0h:0143h ;offset 13Eh here
next: ... ;offset 143h here

Hope this might help somebody

_________________
FAMOS - the first memory operating system
Post 20 Jul 2008, 00:19
View user's profile Send private message Visit poster's website Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville
I now have a machine with an Athlon64 X2 CPU so I have been playing...

I can get to Long Mode using variations of sinsi's code at the start of this thread, but only by writing it to the bootsector of a floppy disk and then booting it.

The SAME code written to a bootable physical CD using floppy emulation does NOT work - it causes the machine to endlessly reboot itself.

The same code executed from 7B0H:0100H in FAMOS also reboots the machine.

In FAMOS the page tables are all built successfully, PAE is enabled OK, Long Mode is enabled, but the reboot occurs when the instruction MOV CRO,EAX is executed when attempting to enable paging...


Code:
 MOV     EAX,CR4
     OR      EAX,20H
     MOV     CR4,EAX         ;enable PAE

     MOV     EAX,PGTABLE
 MOV     CR3,EAX
     MOV     ECX,0C0000080H  ;EFER.MSR
   RDMSR
       OR      EAX,100H
    WRMSR                   ;enable long mode

       MOV     EAX,CR0
     OR      EAX,80000001H
       MOV     CR0,EAX         ;enable paging   CRASHES here    



WTF???

Can anybody help?

_________________
FAMOS - the first memory operating system
Post 16 Nov 2008, 04:06
View user's profile Send private message Visit poster's website Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 693
Location: Adelaide
sinsi
How do you know it crashes on that instruction? via bochs debugger?


That instruction triple faults if a butterfly farts I swear...
Post 16 Nov 2008, 04:34
View user's profile Send private message Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville
sinsi wrote:
How do you know it crashes on that instruction? via bochs debugger?

No, via my own native FAMOS debugger. I've never used an emulator - I figure its best to use the real thing... Its definitely that instruction that crashes.

_________________
FAMOS - the first memory operating system
Post 16 Nov 2008, 05:54
View user's profile Send private message Visit poster's website Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 693
Location: Adelaide
sinsi
I've noticed that with nero you can specify a load segment for a bootable cd and it seems to default to 0x1000 (apparently with el-torito you can load your code at any segment)...

Can you post some code?
Post 16 Nov 2008, 06:25
View user's profile Send private message Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville
I thought I would start my FAMOS 64-bit experiments with a program which:
(a) sets up Long Mode and displays my name on a text screen
(b) waits for an interrupt from the keyboard
(c) returns to FAMOS (if possible!)

sinsi, because FAMOS runs in real mode (albeit Flat Real), the code you posted in this thread seemed like an ideal starting point...

It will be great if I can do this, because then I can do 64-bit stuff on an "as required" basis before implementing a geniune 64-bit OS...

My program "GO64" in FAMOS should just enter Long Mode, and display "Neville" on the screen in pretty colours. I realise returning to flat real FAMOS again could be difficult without rebooting, but its frustrating that I can't even get to Long Mode in the first place...

The 512-byte bootsector version of the original code displays "Neville" just fine when booted from a floppy, but not from a CD.

Here's the "GO64" code. It relocates itself to 0:7C00H before execution because I thought that might help it to work, but now I don't think that is the problem:

Code:
;trial 64bit UNP for FAMOS (NB: no FPCA yet!)

        ORG     0100h         

        MOV     SI,300H        
        MOV     EDI,7C00H
        MOV     CX,1FEH         ;254 bytes of code max!
FILL:   MOV     AL,[CS:SI]
        MOV     [EDI],AL
        INC     SI
        INC     EDI
        LOOP    FILL

 TIMES  200 DB 90H
        JMP     07B0H:0100H
 TIMES  284 DB 0                ;padding to offset 300H
;this MUST be offset 300H...

        NOP
        cli
;        sub ax,ax
;        mov ss,ax
;        mov sp,7c00h            ;FAMOS UNP stack at 9000H:FFFEH
        MOV     AX,3
        INT     10H             ;set text video mode

        mov ax,7000h            ;70000h ok for pagetables
        mov es,ax
        sub di,di
        mov cx,4096
        sub eax,eax
        rep stosd
        mov dword [es:0000h],71000h + 111b ; first PDP table
        mov dword [es:1000h],72000h + 111b ; first page directory
        mov dword [es:2000h],73000h + 111b ; first page table
        mov di,3000h                       ; address of first page table
        mov eax,0 + 111b
        mov cx,256                         ; number of pages to map (1 MB)
 .next: stosd
        add di,4
        add eax,1000h
        loop .next                         ; create page table @ 73000 -

        mov eax,cr4
        or eax,1 shl 5
        mov cr4,eax                        ; enable physical-address extensions

        mov eax,70000h
        mov cr3,eax                        ; load page-map level-4 base
        mov ecx,0C0000080h                 ; EFER MSR
        nop
        rdmsr
        nop
        or eax,1 shl 8                     ; enable long mode
        wrmsr

        mov eax,cr0
 TIMES 4 DB 90H
;        MOV     [CR0COPY],EAX              ;can we access linear mem here??
        NOP
        or eax,(1 shl 31) + 1
        mov cr0,eax                        ; enable paging + pmode
                                           ; reboots here.... Sad
        NOP
;        lgdt [cs:GDTR] - 200H              ;HAND-CODE THIS...
;        lgdt [cs:GDTR]                     ;HAND-CODE THIS... GDTR=398 -> 198h
;        db 2eh, 0fh, 1, 16h, 98h, 1
        lgdt [cs:198H]                     ;assembles correctly with ABSOLUTE ptr
        NOP
        jmp 8:long_start - 200H

align 8                          
GDTR:                                   ; Global Descriptors Table Register
  dw 2*8-1                              ; limit of GDT (size minus one)
  dq GDT - 200H                         ; linear address of GDT

align 8                       
GDT rw 4                                ; null desciptor
    dw 0FFFFh,0,9A00h,0AFh              ; 64-bit code desciptor


        USE64

long_start:
        NOP
        mov     al,10001b               ; begin PIC 1 initialization
        out     20h,al
        mov     al,10001b               ; begin PIC 2 initialization
        out     0A0h,al
        mov     al,80h                  ; IRQ 0-7: interrupts 80h-87h
        out     21h,al
        mov     al,88h                  ; IRQ 8-15: interrupts 88h-8Fh
        out     0A1h,al
        mov     al,100b                 ; slave connected to IRQ2
        out     21h,al
        mov     al,2
        out     0A1h,al
        mov     al,1                    ; Intel environment, manual EOI
        out     21h,al
        out     0A1h,al
        in      al,21h
        mov     al,11111100b            ; enable only clock and keyboard IRQ
        out     21h,al
        in      al,0A1h
        mov     al,11111111b
        out     0A1h,al

        xor     edi,edi                 ; create IDT (at linear address 0)
        mov     ecx,21
  make_exception_gates:                 ; make gates for exception handlers
        mov     esi,exception_gate - 200H
        movsq
        movsq
        loop    make_exception_gates
        mov     ecx,256-21
  make_interrupt_gates:                 ; make gates for the other interrupts
        mov     esi,interrupt_gate - 200H
        movsq
        movsq
        loop    make_interrupt_gates
        NOP
        mov     word [80h*16],clock - 200H     ; set IRQ 0 handler
        mov     word [81h*16],keyboard - 200H  ; set IRQ 1 handler
        NOP
;        lidt    [IDTR] - 200H           ; load IDT register
;        lidt    [IDTR]                  ;HAND-CODE THIS...
;        lidt    [23FH]                  ;HAND-CODE THIS... 43F -> 23FH NO!
        lidt    [43FH]                  ;assembles using RELATIVE ptr so dont - 200 !!
        NOP
        sti                             ; now we may enable the interrupts

  main_loop:

        mov     rax,03760265014E0720h   ;'_Nev'
        mov     [0B8000h],rax
        mov     rax,0765066C056C0469h   ;'ille'
        mov     [0B8008h],rax
        NOP
        jmp     $


IDTR:                                   ; Interrupt Descriptor Table Register
  dw 256*16-1                           ; limit of IDT (size minus one)
  dq 0                                  ; linear address of IDT

exception_gate:
  dw exception and 0FFFFh,8
  dw 8E00h,exception shr 16 - 20H       ;200/16
  dd 0,0

interrupt_gate:
  dw interrupt and 0FFFFh,8
  dw 8F00h,interrupt shr 16 - 20H       ;200/16
  dd 0,0

exception:                              ; exception handler
        in      al,61h                  ; turn on the speaker
        or      al,3
        out     61h,al
        jmp     exception               ; repeat it until reboot

interrupt:                              ; handler for all other interrupts
        iretq

clock:
        inc     byte [0B8000h+2*80]     ; make the ticks appear
        push    rax
        mov     al,20h
        out     20h,al
        pop     rax
        iretq

keyboard:
        push    rax
        in      al,60h
        cmp     al,1                    ; check for Esc key
        je      reboot
        mov     [0B8000h+2*(80+1)],al   ; show the scan key
        in      al,61h                  ; give finishing information
        out     61h,al                  ; to keyboard...
        mov     al,20h
        out     20h,al                  ; ...and interrupt controller
        pop     rax
        iretq

reboot:
;attempt to return to FAMOS...

        USE16

        MOV     EAX,CR0
        NOP
        AND     EAX,7FFFFFFFH           ;reset PG
        MOV     CR0,EAX                 ;disable paging

        MOV     ECX,0C0000080H          ;EFER.LME
        NOP
        RDMSR
        BTR     EAX,8
        NOP
        WRMSR                           ;disable long mode

        MOV     EAX,CR0
        AND     EAX,0FFFFFFFEH          ;reset PE
        NOP
        MOV     CR0,EAX                 ;disable PM
        NOP
        DB      0EAH, 0, 1, 0D0H, 7     ;return to FAMOS? Don't assume ints are working!

CR0COPY: DD 0    

_________________
FAMOS - the first memory operating system
Post 16 Nov 2008, 20:59
View user's profile Send private message Visit poster's website Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville
I found a few bugs in the previous code, including an incorrect GDT pointer
after relocating the code to 00007C00H.

I've now abandoned the idea of relocating the code because it shouldn't be necessary anyway...

I fixed the bugs I found but the MOV CR0,EAX instruction still reboots. Grrr...

Latest version of the code:

Code:
;trial 64bit UNP for FAMOS
        ORG     0100h

        NOP
        cli

;        sub ax,ax
;        mov ss,ax
;        mov sp,7c00h            ;FAMOS stack at 9000:FFFEH

        MOV     AX,3
        INT     10H             ;set text video mode

        cli
;save IVT here & restore before attempting return to FAMOS??

        mov ax,7000h    ;70000h ok
        mov es,ax
        sub di,di
        mov cx,4096
        sub eax,eax
        rep stosd
        mov dword [es:0000h],71000h + 111b ; first PDP table
        mov dword [es:1000h],72000h + 111b ; first page directory
        mov dword [es:2000h],73000h + 111b ; first page table
        mov di,3000h              ; address of first page table
        mov eax,0 + 111b
        mov cx,256                ; number of pages to map (1 MB)
 .next: stosd
        add di,4
        add eax,1000h
        loop .next                ; create page table @ 73000 -

        MOV     EAX,GDT
        ADD     EAX,1FF00H        ;CS=1FF0H
        MOV     [CS:LINADDR],EAX

        mov eax,cr4
        or eax,1 shl 5
        mov cr4,eax                 ; enable physical-address extensions

        mov eax,70000h
        mov cr3,eax                 ; load page-map level-4 base
        mov ecx,0C0000080h          ; EFER MSR
        nop
        rdmsr
        nop
        or eax,1 shl 8             ; enable long mode
        wrmsr

;        lgdt [cs:GDTR]            ; LGDT first?? (still reboots...)
 TIMES 6 DB 90H
        NOP

        mov eax,cr0
        NOP
        or eax,(1 shl 31) + 1
        mov cr0,eax                 ; enable paging + pmode
                                    ; still reboots here.... Sad
        NOP
        lgdt [CS:GDTR]
        NOP

        jmp 8:long_start

align 8
GDTR:                                   ; Global Descriptors Table Register
  dw 2*8-1                              ; limit of GDT (size minus one)
LINADDR:                                ; lin addr of GDT
  dq 0
align 8
GDT rw 4                                ; null desciptor
    dw 0FFFFh,0,9A00h,0AFh              ; 64-bit code desciptor


        USE64

long_start:
        NOP
        MOV     AX,CS
        MOV     DS,AX

        mov     al,10001b               ; begin PIC 1 initialization
        out     20h,al
        mov     al,10001b               ; begin PIC 2 initialization
        out     0A0h,al
        mov     al,80h                  ; IRQ 0-7: interrupts 80h-87h
        out     21h,al
        mov     al,88h                  ; IRQ 8-15: interrupts 88h-8Fh
        out     0A1h,al
        mov     al,100b                 ; slave connected to IRQ2
        out     21h,al
        mov     al,2
        out     0A1h,al
        mov     al,1                    ; Intel environment, manual EOI
        out     21h,al
        out     0A1h,al
        in      al,21h
        mov     al,11111100b            ; enable only clock and keyboard 

IRQ
        out     21h,al
        in      al,0A1h
        mov     al,11111111b
        out     0A1h,al

        xor     edi,edi                 ; create IDT (at linear address 0)
        mov     ecx,21
  make_exception_gates:                 ; make gates for exception handlers
        mov     esi,exception_gate
        movsq
        movsq
        loop    make_exception_gates
        mov     ecx,256-21
  make_interrupt_gates:                 ; make gates for the other 

interrupts
        mov     esi,interrupt_gate
        movsq
        movsq
        loop    make_interrupt_gates
        NOP
        mov     word [80h*16],clock
        mov     word [81h*16],keyboard

        NOP
        lidt    [IDTR]
        NOP
        sti                             ; now we may enable the interrupts

  main_loop:

        mov     rax,03760265014E0720h   ;'_Nev'
        mov     [0B8000h],rax
        mov     rax,0765066C056C0469h   ;'ille'
        mov     [0B8008h],rax
        NOP
        jmp     $


IDTR:                                   ; Interrupt Descriptor Table 

Register
  dw 256*16-1                           ; limit of IDT (size minus one)
  dq 0                                  ; linear address of IDT

exception_gate:
  dw exception and 0FFFFh,8
  dw 8E00h,exception shr 16
  dd 0,0

interrupt_gate:
  dw interrupt and 0FFFFh,8
  dw 8F00h,interrupt shr 16
  dd 0,0

exception:                              ; exception handler
        in      al,61h                  ; turn on the speaker
        or      al,3
        out     61h,al
        jmp     exception               ; repeat it until reboot

interrupt:                              ; handler for all other interrupts
        iretq

clock:
        inc     byte [0B8000h+2*80]     ; make the ticks appear
        push    rax
        mov     al,20h
        out     20h,al
        pop     rax
        iretq

keyboard:
        push    rax
        in      al,60h
        cmp     al,1                    ; check for Esc key
        je      GO2FAMOS
        mov     [0B8000h+2*(80+1)],al   ; show the scan key
        in      al,61h                  ; give finishing information
        out     61h,al                  ; to keyboard...
        mov     al,20h
        out     20h,al                  ; ...and interrupt controller
        pop     rax
        iretq

GO2FAMOS:
;attempt to return to FAMOS...

        USE16

        MOV     EAX,CR0
        NOP
        AND     EAX,7FFFFFFFH           ;reset PG
        MOV     CR0,EAX                 ;disable paging

        MOV     ECX,0C0000080H          ;EFER.LME
        NOP
        RDMSR
        BTR     EAX,8
        NOP
        WRMSR                           ;disable long mode

        MOV     EAX,CR0
        AND     EAX,0FFFFFFFEH          ;reset PE
        NOP
        MOV     CR0,EAX                 ;disable PM
        NOP
        DB      0EAH, 0, 1, 0D0H, 7     ;don't assume ints are working!    

_________________
FAMOS - the first memory operating system
Post 19 Nov 2008, 22:38
View user's profile Send private message Visit poster's website Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville
The problem I've been having with activating Long Mode (crashing on the MOV CR0,EAX instruction below) only occurs when the real mode code segment is non-zero at the time the instruction is executed. If CS=0, it works fine.
Can anybody explain why this should be?
Code:
  MOV     EAX,CR0         
    OR      EAX,80000001H   ;enable paging & pmode
        MOV       CR0,EAX         ;activate Long Mode (crashes if CS ne 0)

        JMP     0008:LONG_MODE      ;works only if Real-Mode CS was 0 ...    

_________________
FAMOS - the first memory operating system
Post 04 Dec 2008, 08:48
View user's profile Send private message Visit poster's website Reply with quote
StarKnightD



Joined: 04 Jul 2007
Posts: 38
StarKnightD
Quote:
The problem I've been having with activating Long Mode (crashing on the MOV CR0,EAX instruction below) only occurs when the real mode code segment is non-zero at the time the instruction is executed. If CS=0, it works fine.
Can anybody explain why this should be?


it's because CS doesn't represent an address when running in protected mode (both 32 and 64 bit forms) -- which is what it does in real mode -- rather it's symbolic of the current state of the code-segment. if memory serves me right, there are only 3 states the CS can be in, each of which are represented by the first 3 powers of 2.
Post 11 Feb 2009, 16:27
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar.

Powered by rwasa.