Author Topic: enter protected mode but lgdr instruction not accepted  (Read 3728 times)

ggmasm32

  • Member
  • **
  • Posts: 51
enter protected mode but lgdr instruction not accepted
« 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.,

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave

ggmasm32

  • Member
  • **
  • Posts: 51
Re: enter protected mode but lgdr instruction not accepted
« Reply #2 on: November 02, 2015, 05:40:31 AM »
you used only two words to reply, but it solved my problem  :lol: :t :greensml:

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: enter protected mode but lgdr instruction not accepted
« Reply #3 on: November 02, 2015, 05:49:48 AM »
yah, i'm efficient that way   :lol:

ggmasm32

  • Member
  • **
  • Posts: 51
Re: enter protected mode but lgdr instruction not accepted
« Reply #4 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??

jj2007

  • Member
  • *****
  • Posts: 7552
  • Assembler is fun ;-)
    • MasmBasic
Re: enter protected mode but lgdr instruction not accepted
« Reply #5 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

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: enter protected mode but lgdr instruction not accepted
« Reply #6 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

ggmasm32

  • Member
  • **
  • Posts: 51
Re: enter protected mode but lgdr instruction not accepted
« Reply #7 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








dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: enter protected mode but lgdr instruction not accepted
« Reply #8 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]

ggmasm32

  • Member
  • **
  • Posts: 51
Re: enter protected mode but lgdr instruction not accepted
« Reply #9 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. !!

jj2007

  • Member
  • *****
  • Posts: 7552
  • Assembler is fun ;-)
    • MasmBasic
Re: enter protected mode but lgdr instruction not accepted
« Reply #10 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

ggmasm32

  • Member
  • **
  • Posts: 51
Re: enter protected mode but lgdr instruction not accepted
« Reply #11 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. :)

ACP

  • Regular Member
  • *
  • Posts: 10
Re: enter protected mode but lgdr instruction not accepted
« Reply #12 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?

ASM beyond Repair https://corexor.wordpress.com blog about assembly related stuff

ggmasm32

  • Member
  • **
  • Posts: 51
Re: enter protected mode but lgdr instruction not accepted
« Reply #13 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.

dedndave

  • Member
  • *****
  • Posts: 8734
  • Still using Abacus 2.0
    • DednDave
Re: enter protected mode but lgdr instruction not accepted
« Reply #14 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