The MASM Forum

Miscellaneous => 16 bit DOS Programming => Topic started by: DuckRaw on July 07, 2021, 06:30:14 PM

Title: how to entering PM
Post by: DuckRaw on July 07, 2021, 06:30:14 PM
Hi All, help me please, my code isn't working:

.386p

;ml.exe /c masm.obj masm.asm
;link16.exe masm.obj,masm.img
 
code segment
org 7C00h
assume cs:code
start:   
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
;mov sp, start

    in      al, 92h
    or      al, 2
    out     92h, al
; Вычисляем линейный адрес начала массива дескрипторов
mov     eax, 0
mov     ax, cs
shl     eax, 4
mov     eax, offset GDT + 1
; Записываем его в структуру
mov ebx, offset gdt_descriptor + 2
mov     word ptr gdt_descriptor + 2, ax

    ;xor     ax, ax
    ;mov     ax, cs
    ;shl     ax, 4
    ;mov     ax, word ptr GDT + 1 ;адрес GDT
    ;mov     word ptr GDTR + 2, ax
    ;lgdt    fword ptr [GDTR]

; Загружаем GDTR.
; fword ptr – указатель на шестибайтную структуру
lgdt    fword ptr [gdt_descriptor]

    cli              ; запретить прерывания
    in      al, 70h  ; индексный порт CMOS
    or      al, 80h  ; установка бита 7 в нем запрещает NMI
    out     70h, al

    mov     eax, cr0 ; прочитать регистр CR0
    or      al, 1    ; установить бит PE,
    mov     cr0, eax ; с этого момента мы в защищенном режиме

jmp $

GDT label   byte
gdt_start:

gdt_null:                               ; null descriptor
        dd 0
        dd 0

gdt_code:                               ; code segment descriptor
        dw 20h                       ; segment limit (bits 0 - 15)
        dw 0                          ; base address (bits 0 - 15)
        db 0                          ; base address (bits 16 - 23)
        db 10011010b                    ; type flags;
        db 11001111b                    ; other flags
        db 0                          ; base address (bits 24 - 31)

gdt_data:                               ; data segment descriptor
        dw 50h                       ; segment limit (bits 0 -15)
        dw 0                          ; base address (bits 0 - 15)
        db 0                          ; base address (bits 16 -23)
        db 10010010b                    ; type flags
        db 11001111b                    ; other flags
        db 0                         ; base address (bits 24 - 31)

gdt_end:

gdt_descriptor:                         ; gdt descriptor
        dw gdt_end - gdt_start - 1      ; declare size of gdt descriptor
        dd gdt_start                    ; declare address of gdt

codeend:
db 510-(codeend-start) dup (0)
db 055h,0AAh
code ends
end start

this code working from real mode without dos.
What wrong?
Help please
Title: Re: how to entering PM
Post by: LiaoMi on July 08, 2021, 01:08:31 AM
Quote from: DuckRaw on July 07, 2021, 06:30:14 PM
Hi All, help me please, my code isn't working:

.386p

;ml.exe /c masm.obj masm.asm
;link16.exe masm.obj,masm.img
 
code segment
org 7C00h
assume cs:code
start:   
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
;mov sp, start

    in      al, 92h
    or      al, 2
    out     92h, al
; Вычисляем линейный адрес начала массива дескрипторов
mov     eax, 0
mov     ax, cs
shl     eax, 4
mov     eax, offset GDT + 1
; Записываем его в структуру
mov ebx, offset gdt_descriptor + 2
mov     word ptr gdt_descriptor + 2, ax

    ;xor     ax, ax
    ;mov     ax, cs
    ;shl     ax, 4
    ;mov     ax, word ptr GDT + 1 ;адрес GDT
    ;mov     word ptr GDTR + 2, ax
    ;lgdt    fword ptr [GDTR]

; Загружаем GDTR.
; fword ptr – указатель на шестибайтную структуру
lgdt    fword ptr [gdt_descriptor]

    cli              ; запретить прерывания
    in      al, 70h  ; индексный порт CMOS
    or      al, 80h  ; установка бита 7 в нем запрещает NMI
    out     70h, al

    mov     eax, cr0 ; прочитать регистр CR0
    or      al, 1    ; установить бит PE,
    mov     cr0, eax ; с этого момента мы в защищенном режиме

jmp $

GDT label   byte
gdt_start:

gdt_null:                               ; null descriptor
        dd 0
        dd 0

gdt_code:                               ; code segment descriptor
        dw 20h                       ; segment limit (bits 0 - 15)
        dw 0                          ; base address (bits 0 - 15)
        db 0                          ; base address (bits 16 - 23)
        db 10011010b                    ; type flags;
        db 11001111b                    ; other flags
        db 0                          ; base address (bits 24 - 31)

gdt_data:                               ; data segment descriptor
        dw 50h                       ; segment limit (bits 0 -15)
        dw 0                          ; base address (bits 0 - 15)
        db 0                          ; base address (bits 16 -23)
        db 10010010b                    ; type flags
        db 11001111b                    ; other flags
        db 0                         ; base address (bits 24 - 31)

gdt_end:

gdt_descriptor:                         ; gdt descriptor
        dw gdt_end - gdt_start - 1      ; declare size of gdt descriptor
        dd gdt_start                    ; declare address of gdt

codeend:
db 510-(codeend-start) dup (0)
db 055h,0AAh
code ends
end start

this code working from real mode without dos.
What wrong?
Help please

Hi DuckRaw  :biggrin:,

what specifically doesn't work? Take a look here - http://masm32.com/board/index.php?topic=4775.0

.686p
https://github.com/microsoft/Ironclad/raw/main/ironclad-apps/src/Checked/BootLoader/SingLdrPc/blentry16.asm

As of MSVC 2005 in both the 32-bit ml.exe and 64-bit cross-tools ml64.exe, the followingworks just fine when using LGDT... key is to use "FWORD PTR" as operand size modifier and when doing this in 32-bit code, also include ".686P" assembler pseudo-op to enable privileged instructions. Results in same opcode, i.e. 0F 01, being emitted in both 64-bit mode and compatibility/legacy mode. Also, please make sure that section 9.8 of Intel 64 and IA-3 2 Architectures Software Developer's Manual Volume 3A: System Programming Guide and related sections are well understood, as there are implications in order in which steps must be done when altering protected mode operation.

LGDT macro mem:req
local x,y

x:
prefetchnt1 mem
y:
org x
byte 0fh
byte 01h
org y

endm


Title: Re: how to entering PM
Post by: DuckRaw on July 08, 2021, 05:54:19 AM
Thank you for your help, I think I figured it out:

.286p

;masm 6.14
;ml.exe /c masm.obj masm.asm
;link.exe masm.obj,masm.img
 
code segment
org 7C00h
start:   

        in      al, 92h
        or      al, 2
        out     92h, al

mov ax, 0
mov ax, offset GDT
mov word ptr gdt_descriptor + 2, ax
mov di, offset gdt_descriptor

lgdt fword ptr gdt_descriptor

        cli                 
        in      al, 70h
        or      al, 80h
        out     70h, al

mov ax, 1
lmsw ax

db 0eah ; дальний переход (jump far)
dw PMode ;  jmp far Code_selector:PMode
dw 08h
PMode:

nop
nop
nop
nop
nop
nop
...

code_size dw $ - start

GDT label   byte
gdt_start:

gdt_null:                                 ; null descriptor
        dq 0h
gdt_code:                               ; code segment descriptor
dw 0FFFFh
dw 0
db 0
db 10011010b
db 11001111b
db 0
gdt_data:                               ; data segment descriptor
dw 0FFFFh
dw 0
db 0
db 10010010b
db 11001111b
db 0
gdt_end:

gdt_descriptor:                                          ; gdt descriptor
        dw gdt_end - gdt_start - 1 ; declare size of gdt descriptor
dd 0

codeend:
db 510-(codeend-start) dup (0)
db 055h,0AAh
code ends
end start

Thank you!