The MASM Forum

Miscellaneous => 16 bit DOS Programming => Topic started by: ggmasm32 on November 01, 2015, 09:01:17 PM

Title: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 01, 2015, 09:01:17 PM
hello all,
i am using the masm32 compiler along with its linker and wrote 16-bit asm code to enter CPU into protected mode. I did before several years ago and entered p-mode successful but this time it is brush-up thing. Now the following line in my asm returns error code:

lgdt [gdtPtr]

with gdtPtr is the pointer to GDT structure. Rechecked everything but when during compilation this line causes error:
A2085: instruction or register is not accepted in current CPU mode.
I tried many things like putting .586p but still no avail. I can not figure out why it is throwing this error, I have never seen it in the past.
has any has their ears rining bell or something??

Once compiler it has to run from DOS environment (not from Windows box virtual DOS) , the real DOS.
However during compilation it should not matter.

Thanks.,
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: dedndave on November 01, 2015, 10:48:58 PM
use .686p

http://masm32.com/board/index.php?topic=4029.msg42766#msg42766 (http://masm32.com/board/index.php?topic=4029.msg42766#msg42766)
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 02, 2015, 05:40:31 AM
you used only two words to reply, but it solved my problem  :lol: :t :greensml:
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: dedndave on November 02, 2015, 05:49:48 AM
yah, i'm efficient that way   :lol:
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 02, 2015, 02:15:50 PM
BUMMER! :( it turns out i build wrong file with does not have the lgdt instruction. Back to sad reality I build the file and even with .686p, it is stll not building. Any other ideas??
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: jj2007 on November 02, 2015, 02:27:25 PM
One minute for Google, five minutes to test:

Code: [Select]
include \masm32\include\masm32rt.inc
.686p

GDT STRUCT
  limitStorage dw ?
  baseStorage dd ?
GDT ENDS

.code
mygdt GDT <?>
start:
  inkey "it assembles"
  exit

  lgdt mygdt

end start
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: dedndave on November 02, 2015, 03:09:58 PM
the first 2 lines of Jochen's code tell you what's happening   :biggrin:

the masm32rt.inc file sets the processor to .486
so, the .686p line has to go after the include

this builds, but raises a priviledged instruction exception, as one might expect

Code: [Select]
;###############################################################################################

        INCLUDE    \Masm32\Include\Masm32rt.inc
        .686p

;###############################################################################################

        .DATA?

tablex FWORD ?

;###############################################################################################

        .CODE

;***********************************************************************************************

main    PROC

    lgdt    tablex

    inkey
    exit

main    ENDP

;###############################################################################################

        END     main
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 02, 2015, 03:50:51 PM
still not working.
I did
.486
.686p

I am using the more elaborate old way of declaring the segments. I am wondering if that is the cause:


.486
.686p

include macros.inc

sta segment para stack use16 'stack'
    db 100h dup(0)
sta ends

data segment para public 'data'
    str0    db 'test string in asmfile.asm$'
    str1    db 'str1$'
    acpiPtr db 'RSD PTR$'
    bdaPtr  db  0f8h, 03h, '$'

;    dw          gdt_end - gdt - 1   ;last byte in table
;    dd gdt                 ;start of table

    gdtPtrSize  db 0,0
    gdtPtrAddr  db 0,0,0,0

;   0:15    - limit 0:15
;   15:31   - base  0:15

;   0:7     - base 16:23
;   8:15    - access byte
;   16:19   - limit 16:19
;   20:23   - flags
;   24:31   - base 24:31

;   entry0 - not used
;   entry1 -    dw ffff - limit 0:15
;               db 0    -

;   base    0:31 = 00000000h
;   limit   0:19 = ffffffh
;   access byte  = 10010010b?
;   flags        = 1100b?

;   gdt start
;   entry 0 (always unused)

    gdt         dd 0,0          ; entry 0 is always unused

;   entry 1

    flatdesc    dw 0ffffh       ; limit 0:15
                db 0, 0         ; base 0:15
                db 0            ; base 16:23
                db 10010010b    ; access byte

                ; 1 - present (yes)
                ; 00 - privilige 00
                ; 1?
                ; 0 - data selector
                ; 0 - can only executed from ring set in priv level.
                ; 1 - readable code segment
                ; 0 - accessed bit. cpu sets this bit when accessed.

                db 11001111b    ; limit 16:19 flag

                ; 1 - granularity bit - 1 limit is in 4KiB blocks
                ; 1 - Sz - 32-bit protected mode
                ; 00 - ??

                db 0            ; base 24:31
    gdtEnd      dw 0
data ends

code segment para public use16 'code'
assume cs:code, ds:data,ss:sta

M_EXTERNDEF

main    proc    far
    mov     ax, DATA
    mov     ds, ax

...

switchPmode:
    ; must run from DOS not WINDOWS!!!
    ;
    ; create PTR TO GDT
    ; create GDT and fill up.
    ; load GDT
    ; disable all INT-s
    ; switch to pmode
    ; fetch data
    ; enable all INT-s back
    ; display fetched data.

;   Check if already in protected mode

    mov eax, cr0
    test    al, 01h
    jz      pmodeTestDone
    M_PRINTF  "\nSystem is already in protected mode"
    jmp     exit

pmodeTestDone:
    M_PRINTF  "\nSwitching to protecte mode"

;   disable interrupts

    cli

;   DS=0

    sub     ax, ax
    mov     ds, ax

    lgdt    [gdtPtr]
    mov     eax, cr0
    or      al, 01h
    mov     cr0, eax
    jmp     $+2

;   DS = set segment descriptor entry 1 in GDT

    mov     bx, 08h
    mov     ds, bx

;   grab memory from ext.memory

;   ...

;   exit protected mode

    mov     eax, cr0
    and     eax, 0fffffffeh
    mov     cr0, eax

;   enable back interrupts

    sti

exit:
    mov     ax, 4c00h
    int     21h

    main    endp
;   input
;   DS:BP   - pointer to string ($) terminated.


code    ends
    end     main







Title: Re: enter protected mode but lgdr instruction not accepted
Post by: dedndave on November 02, 2015, 05:26:50 PM
i don't think lgdt supports direct addressing - i believe it has to be immediate
... or register indirect

if you don't declare the table as type FWORD, use FWORD PTR

immediate
Code: [Select]
    lgdt fword ptr tablex
register indirect - in this case, you must use FWORD PTR
Code: [Select]
    mov     ebx,offset tablex
    lgdt fword ptr [ebx]
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 02, 2015, 07:11:07 PM
ok thanks a lot. have to put that stupid .386 in another inc file to work it all. Got hint from another  google page " where it says .386 .286 etc.," must be placed in include file before the file that contains lgdt instruction. Anyways moving on. !!
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: jj2007 on November 02, 2015, 07:49:59 PM
I am using the more elaborate old way of declaring the segments. I am wondering if that is the cause:

You are not obliged to do it the modern way, assembler is a tolerant language 8)
However, it looks clearer IMHO when using a structure:

GDT STRUCT
  limitStorage   dw ?
  baseStorage   dd ?
GDT ENDS

.data?
mygdt   GDT <?>
.code
.686p
lgdt mygdt


Assembles fine as 16-bit code. Anyway, keep trying :t
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 03, 2015, 06:49:37 AM
yeah just for "historical" reasons, I need to do it the old fashioned way :)
it is just how i did it when I was doing asm dev job. since then i moved on and did something else. :)
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ACP on November 10, 2015, 09:09:29 AM
Even more historical would be accessing part of CR0 register with SMSW and LMSW instructions. The old 286 style.  ;) Obviously on 386+ direct access to CR0 is preferred method.

Out of curiosity: why are you using .486 and .686p keyword one after another? I haven't used MASM for years so maybe there is a good reason for it?

Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 10, 2015, 10:42:10 AM
I aint going back to 286 :). That belongs to generation before I reached adolescence.
For the 486 ad 686p i am just there to keep what works. May be I will clean up afterward.
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: dedndave on November 10, 2015, 11:42:56 AM
.686p is enough - you can delete the .486
each time you name a new processor, the old setting is tossed out, with the exception of .87, .287, etc
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ACP on November 10, 2015, 06:33:16 PM
.686p is enough - you can delete the .486
each time you name a new processor, the old setting is tossed out, with the exception of .87, .287, etc

That was my assumption but I wasn't sure. As for 286 protected mode related instruction there is one reason to still use them on 386+: SMSW is not privilege instruction hence it can be used to detect if DOS is running in real or protected/v86 mode without causing an exception. I guess there are very few people who remember protected mode programming on 286. It was so brain damaged. Probably finding a code example for 286 PM would be a challenge by itself today. 
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: dedndave on November 10, 2015, 10:33:29 PM
it wasn't that long ago - lol
you would set up the boot vector, then cause a triple-fault (something like that) to get back to real mode
very slow
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 13, 2015, 05:14:07 PM
meant to put it here:

my next step would be going to pmode with interrupts enabled. That translates to creating IDT from scratch. I presume this is going to be monumental task to translate every vector into IDT (at least that I think will be needed).

I have attempted few times in the past and given up with lack of resource, material. I looked into linux kernel source code that seemed to do this briefly.
Once I get over this, this would be a tremendous boost to my main pet project: minix kernel design.

I am so unsure about whether I can successfully create IDT and go in and out of pmode without hanging the system, I am even considering if someone can implement this for me for some moderate amount of bounty :).
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: FORTRANS on November 14, 2015, 09:24:12 AM
Hi,

   You could look in the source code for LILO and GRUB
and see if there is anything that helps.

Regards,

Steve N.
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: sinsi on November 14, 2015, 01:18:32 PM
The usual way for a simple IDT is
 - int 00 through 1F are for CPU exceptions etc
 - int 20 through 2F (really, any two blocks of 8 ) are re-mapped IRQs
 - unused ints all point to the same gate which is just an iret
You can then use an int for your own code, just replace the default gate with a custom one (like linux's int 80)

The FASM board OS Construction (http://board.flatassembler.net/forum.php?f=11) has lots and lots of examples.
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 14, 2015, 06:34:53 PM
thanks i do remember long time ago, if i repeated print out the vector through 0x00-3xff address, some of the mere constantly changing.  I could not explain it at that time. Then the logical question arises: if particular IVT is changing a value to different then how do i know which one to use when translating. How do I know whether it is correct one. etc.,
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: dedndave on November 15, 2015, 11:41:33 AM
i suggest you read info that is posted on osdev.org

http://forum.osdev.org/ (http://forum.osdev.org/)

beware - they are not very friendly over there
they assume you are an expert
before asking any questions, read everything in the world (i guess they have)

but - a good place to browse and get code snippets
Title: Re: enter protected mode but lgdr instruction not accepted
Post by: ggmasm32 on November 15, 2015, 03:36:15 PM
ok i will thanks., i know people who know too much get cranky at times. I sometimes do it too.