Toon posts:

[ASM] Switchen naar Protected mode

Pagina: 1
Acties:

Verwijderd

Topicstarter
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
jmp short _start

%define     Code        10011011b   ;Toegangsrechten Code segment
%define     Data        10010011b   ;Toegangsrechten Data segment

;Selectors
%define     Programma   0x08        ;Wijst naar het programma
%define     Opslag      0x10        ;Wijst naar de data opslag
%define     BeeldScherm 0x18        ;Wijst naar het beeldscherm

%macro Descriptor 5
    dw      %3      ;Limiet
    dw      %2      ;Basis Minst Significant
    db      %1      ;Basis Meest Significant
    db      %4      ;Toegangsrechten
    db      %5      ;Hoogste nibble granulitiet laagste nible Limiet
    db      0       ;Basis
%endmacro

;--------------------------------------
;Nog in Real MODE
;--------------------------------------
bits 16
_start:
    mov ax, 0xb800
    mov es, ax          ;ES wijst naar video geheugen
    mov al,'R'          ;Zet een R op het scherm in Real mode
    mov ah,10000111b    ;Geef R in het wit en knipperend weer
    mov word [es:0x2], ax   ;Zet R plus attribuut in video geheugen

    cli                 ;Zet Interrupts uit
    lgdt[gdtr]              ;laad Gdt
    mov eax, cr0
    or al,0x01              ;Zet PM bit
    mov cr0,eax
    jmp Programma:PM_start  ;HIER GAAT HET FOUT
;--------------------------------
;Protected MODE
;--------------------------------
bits 32
PM_start:
    mov ax,Opslag
    mov ds, ax
    mov es, ax
    mov ax, BeeldScherm
    mov gs, ax
    mov word[gs:0], 0x741   ;Zet in PM een witte A op het scherm
spin : jmp spin
PM_eind:

bits 16
gdtr:
    dw      gdt_eind-gdt-1  ;Limiet
    dd      gdt         ;Basis
gdt
    Descriptor      0,0,0,0,0 ; Null descriptor
    Descriptor      0, 0, 0x0ffff , Code, 0x0cf ;Programma code 08h
    Descriptor      0,0, 0x0ffff, Data, 0xcf    ;Data Opslag 10h
    Descriptor      0x0b, 0x8000, 0x4000, Data, 0x00 ; Scherm 18h
gdt_eind

Ben al een tijdje bezig met wat low-level programmeren en het leek me erg leuk zelf de protected mode eens in te gaan(ivm 4gb geheugen en multitasking). Heb dus assembler code van het net gehaald die ervoor zorgt dat het bestand PM.bin(bovenstaande code) van schijf in het geheugen geladen wordt bij booten.

Nu is het volgende een probleem. Ik heb het internet eens afgestruind en in een aantal assembler boeken gekeken en ze hebben het er allemaal over dat als de GDT eenmaal in orde is, het een kwestie is van PM bit zetten en een far jump uitvoeren om in de protected mode te komen.

Nu is bovenstaande code volgens mij dik in orde. Niks is echter minder waar, want als ik de code uitvoer is het enige wat de computer doet rebooten.

Nu wil ik jullie vragen wat doe ik fout.
offtopic:
Even voor de duidelijkheid, bovenstaande is dus geen php ;) , maar hij gaf hem op deze manier het mooist weer

  • igmar
  • Registratie: April 2000
  • Laatst online: 29-06 18:56

igmar

ISO20022

Verwijderd schreef op 16 October 2003 @ 13:20:

Nu is het volgende een probleem. Ik heb het internet eens afgestruind en in een aantal assembler boeken gekeken en ze hebben het er allemaal over dat als de GDT eenmaal in orde is, het een kwestie is van PM bit zetten en een far jump uitvoeren om in de protected mode te komen.
Met nadruk op 'in orde' GDT is een tabel met pages die je moet opzetten VOORDAT je PM ingaat.
Nu is bovenstaande code volgens mij dik in orde. Niks is echter minder waar, want als ik de code uitvoer is het enige wat de computer doet rebooten.
De reboot is waarschijnlijk te wijten aan dat je een page-fault krijgt die je niet afhandeld, en resulteerd in een dubbele pagefault, wat betekend dat de CPU een reboot uitvoert.

Bovenstaande info kun je het mooist terugvinden in de boeken van Tanenbaum. Die heb ik wel, helaas nog ingepakt in dozen. Dat boek is zowiezo een aanrader als je low-level OS-like stuff gaat doen.

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 16:11
* Xiphalon graaft in geheugen

2 opties:

1) De jump wordt stug door je assembler omgebakken naar een near-jump
2) Het adres waarnaar je toespringt is niet aligned of heeft geen code-uitvoerrechten

[ Voor 6% gewijzigd door Xiphalon op 16-10-2003 18:23 . Reden: short jump -> near jump ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

igmar schreef op 16 October 2003 @ 15:42:
[...]

Met nadruk op 'in orde' GDT is een tabel met pages die je moet opzetten VOORDAT je PM ingaat.
maar dat doet ie toch ook :?
De reboot is waarschijnlijk te wijten aan dat je een page-fault krijgt die je niet afhandeld, en resulteerd in een dubbele pagefault, wat betekend dat de CPU een reboot uitvoert.
nou ja een page fault zal het niet zijn, aangezien paging nog niet aan staat. Maar idd een general protection fault / access violation, waarschijnlijk door het springen naar een code segment die niet correct is of niet de juiste privilege level heeft, of omdat de offset waarnaartoe gesprongen wordt niet binnen het segment valt.

--Paradox--: ik ga je GDT eens inspecteren, ogenblik

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Het probleem is deels opgelost door de code in de bootstrap te plaatsen. Op deze manier kan ik een zinnetje in PM op het scherm zetten. Nadeel van alles moeten plaatsen in de bootstrap is dat ik maar 1 sectortje(512kb) de ruimte heb. En aangezien de hele IDT, voor het inschakelen van de interrupts, er nog bij moet. Is 512 kilobyte niet voldoende.

De bootstrap laadt de image PM.BIN trouwens naar het realadres 0050:0000. Zit ik hier misschien in een stuk geheugen waar de protected mode niet meer geactiveerd mag worden. :?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

aha
code:
1
    jmp Programma:PM_start    ;HIER GAAT HET FOUT


hint: wat is PM_start?
De routine bevindt zich op 0x0050:PM_start in realmode, maar dat heeft dus een absoluut adres van 0x0050 * 16 + PM_start in protected mode, en daarom gaat het waarschijnlijk fout

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
.oisyn schreef op 16 October 2003 @ 20:03:
aha
code:
1
    jmp Programma:PM_start    ;HIER GAAT HET FOUT


hint: wat is PM_start?
De routine bevindt zich op 0x0050:PM_start in realmode, maar dat heeft dus een absoluut adres van 0x0050 * 16 + PM_start in protected mode, en daarom gaat het waarschijnlijk fout
Programma is de selector die de eerste entry in de gdt vertegenwoordigt en die zou dus in het codesegment(CS) moeten komen staan.

PM_start staat op regel 41 en is eigenlijk alleen maar een label(geheugen plek) waarnaar toe gesprongen moet worden. EIP(instructie pointer) moet daar dus naar gaan wijzen. Zodat uiteindelijk het adres 0x08:PM_start respectievelijk in CS:EIP staat.

edit:
0x08h -> 0x08 in reactie op de hieronder geplaatste post. Klopt was dubbelop

[ Voor 7% gewijzigd door Verwijderd op 16-10-2003 21:17 ]


Verwijderd

je doet toch een %define Programma 0x08?
Dan staat er dus :

jmp 0x08:PM_start

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

uh ja ik weet waar ze voor staan, maar ik bedoel wat is de waarde van die identifiers als het zootje gecompiled is.

Want PM_start wijst denk ik gewoon naar de offset binnen segment 0x0050. Alleen die segment vervalt, omdat je naar protected mode gaat, en je krijgt een 4gb address space. Die 0x0050::PM_start heeft als absolute offset in je geheugen 0x50 * 16 + PM_start, oftewel, je zit er 0x50 * 16 = 0x500 naast

Maak dit er eens van:
GAS:
1
jmp Programma:(0x50 * 16 + PM_start)    ;HIER GAAT HET FOUT

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

oisyn : wat ik dus bedoelde dat die
code:
1
jmp 0x08:PM_start


misschien dit moet zijn?

code:
1
jmp 0x50:PM_start


edit : je gaat er in je bovenstaande post vanuit dat de jump al in protected mode uitgevoerd wordt, maar is protected mode niet pas aktief NA de jump?

[ Voor 36% gewijzigd door Verwijderd op 16-10-2003 21:20 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, je moet jumpen naar een protected mode code segment.
Ik mis echter wel de dword modifier op de jump, als ik zo eens terug kijk op mijn eigen pmode initializatie routine. Je assembler weet namelijk nog niets van de 32 bits modus, en assembleert dan ook een word offset, ipv een dword offset.

Je jump moet dus zijn:
code:
1
jmp dword Programma:(0x50 * 16 + PM_start)


(ik ga er even vanuit dat je nasm gebruikt, aan de definities van je macros e.d. te zien)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
.oisyn schreef op 16 October 2003 @ 21:42:
Nee, je moet jumpen naar een protected mode code segment.
Ik mis echter wel de dword modifier op de jump, als ik zo eens terug kijk op mijn eigen pmode initializatie routine. Je assembler weet namelijk nog niets van de 32 bits modus, en assembleert dan ook een word offset, ipv een dword offset.

Je jump moet dus zijn:
code:
1
jmp dword Programma:(0x50 * 16 + PM_start)


(ik ga er even vanuit dat je nasm gebruikt, aan de definities van je macros e.d. te zien)
Heb de jump uitgevoerd zoals je hem omschreven hebt maar het enige wat mijn computer blijft doen is triple faulten en rebooten.

Heb je in je eigen PM initializatie de PM in een appart bestand geinitializeerd (bijv KERNEL.BIN) of heb je dat in de bootstrap gedaan? Als je hem namelijk in een appart bestand hebt gedaan zou ik graag willen zien hoe je dat gedaan hebt.

  • _the_crow_
  • Registratie: September 2000
  • Laatst online: 30-03-2025

_the_crow_

Rare vogel

De jump na het switchen naar 32-bit PM moet volgens mij al 32-bit code zijn.
^ ^ Dit is dus onzin. Heb het even gecheckt in m'n eigen code. :)

[ Voor 42% gewijzigd door _the_crow_ op 17-10-2003 20:08 ]

Schrödingers cat: In this case there are three determinate states the cat could be in: these being Alive, Dead, and Bloody Furious.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

mijn asm code (ik gebruik even vb voor mooiere code tags ;))

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
%include "pmode.inc"

BITS 16

SECTION .pmodedata

gdttable:   dw gdt_size
            dd 00010000h + gdt

idttable:   dw idt_size
            dd 00010000h + idt

gdt:
make_segment_descriptor 0, 0, 0, 0          ; null descriptor

gdt_seg     EQU $ - gdt     ; descriptor that points to the (future) gdt table
make_segment_descriptor 0800h, 0ffffh, 0, SD_DATA_WRITABLE | SD_BITS_32 | SD_PRESENT

idt_seg     EQU $ - gdt     ; descriptor that points to the (future) interrupt table
make_segment_descriptor 0000h, 00800h, 0, SD_DATA_WRITABLE | SD_BITS_32 | SD_PRESENT

code32_seg  EQU $ - gdt     ; full 32 bits code segment for the kernel
make_segment_descriptor 0, 0fffffh, 0, SD_CODE_READABLE | SD_BITS_32 | SD_PAGE_GRANULAR | SD_PRESENT

data32_seg  EQU $ - gdt     ; full 32 bits data segment for the kernel
make_segment_descriptor 0, 0fffffh, 0, SD_DATA_WRITABLE | SD_BITS_32 | SD_PAGE_GRANULAR | SD_PRESENT

gdt_size    EQU $ - gdt


idt:
idt_size    EQU $ - idt


SECTION .pmode16

        global pmodestart
pmodestart:
    cli
    mov ax, cs
    mov ds, ax
    mov ss, ax
    xor sp, sp

    lgdt [gdttable]
    lidt [idttable]

    mov eax, cr0
    or al, 1
    mov cr0, eax

        ; TODO: load kernel file from disk with valid filesystem

    jmp dword code32_seg:main32


SECTION .pmode32
BITS 32

main32:
    mov eax, data32_seg
    mov ds, eax
    mov es, eax
    mov fs, eax
    mov gs, eax
    mov ss, eax
    mov esp, 00040000h



En de bijbehorende pmode.inc:

Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
; Protected mode include file

;------------------------------------------------------------------------------
; Normal GDT entry
;
;15   14   13   12   11   10   09   08   07   06   05   04    03   02   01   00
;[        Base address 31:24          ] [ G] [ D] [ 0] [AVL] [Sg. length 19:16]
;[P] [  DPL  ] [DT] [      Type       ] [        Base address 23:16           ]
;[                             Base address 15:00                             ]
;[                            Segment length 15:00                            ]
;
; G     : granularity (0 = byte granular, 1 = page granular (1 page = 4096 bytes))
; D     : operand size (0 = 16 bit, 1 = 32 bit)
; AVL   : available for use
; P     : present bit (0 = not present, 1 = present, valid)
; DPL   : descriptor privilege level
; DT    : descriptor type (0 = system, 1 = application)
;   system descriptors are entirely different and explained later on
; TYPE  : segment type
;       T  E  W  A
;
;       0  0  0  0      read-only data segment
;       0  0  0  1      accessed read-only data segment
;       0  0  1  0      writable data segment
;       0  0  1  1      accessed writable data segment
;       0  1  0  0      down-expanding read-only data segment
;       0  1  0  1      accessed down-expanding read-only data segment
;       0  1  1  0      down-expanding writable data segment
;       0  1  1  1      accessed down-expanding writable data segment
;
;       T  C  R  E
;
;       1  0  0  0      code segment
;       1  0  0  1      executed code segment
;       1  0  1  0      readable code segment
;       1  0  1  1      executed readable code segment
;       1  1  0  0      conforming code segment
;       1  1  0  1      executed conforming code segment
;       1  1  1  0      readable conforming code segment
;       1  1  1  1      executed readable conforming code segment
;
;   the accessed flag (A) or executed flag (E) is set by the cpu whenever
;   data/code is accessed/executed


%define     SD_PRESENT          00080h
%define     SD_VALID            SD_PRESENT

%define     SD_DATA             00010h
%define     SD_DATA_WRITABLE    00012h
%define     SD_CODE             00018h
%define     SD_CODE_READABLE    0001Ah
%define     SD_EXPAND_DOWN      00004h
%define     SD_CONFORMING       00004h
%define     SD_BITS_16          00000h
%define     SD_BITS_32          04000h
%define     SD_BYTE_GRANULAR    00000h
%define     SD_PAGE_GRANULAR    08000h
%define     SD_ACCESSED         00001h


; make_segment_descriptor macro
;
; usage : make_segment_descriptor base, length, privilege, flags
;
; base      : the base address
; length    : the length of this segment in granularity units
; privilege : the privilige level (0 - 3)
; flags     : one or more of the SD_xxx flags

%macro make_segment_descriptor 4        ; base, length, privilege, flags
    dw  (%2) & 0000FFFFh
    dw  (%1) & 0000FFFFh
    db  ((%1) & 00FF0000h) >> 16
    dw  ((%4) & 1101000010011111b) | (((%3) & 0011b) << 5) | (((%2) & 000F0000h) >> 8)
    db  ((%1) & 0FF000000h) >> 24
%endmacro


;------------------------------------------------------------------------------
;
; when the system flag is set, the descriptortype is one of the following
;
%define     SD_286_TSS              01h
%define     SD_LDT                  02h
%define     SD_286_BUSY_TSS         03h
%define     SD_286_CALL_GATE        04h
%define     SD_TASK_GATE            05h
%define     SD_286_INTERRUPT_GATE   06h
%define     SD_286_TRAP_GATE        07h
%define     SD_386_TSS              09h
%define     SD_386_BUSY_TSS         0Bh
%define     SD_386_GALL_GATE        0Ch
%define     SD_386_INTERRUPT_GATE   0Dh
%define     SD_386_TRAP_GATE        0Eh

; 386 Call gate descriptor
;
;15   14   13   12   11   10   09   08   07   06   05   04    03   02   01   00
;[                               Offset 31:16                                 ]
;[P] [  DPL  ]  [0    1    1    0    0    0    0    0] [     Dword count      ]
;[                                 Selector                                   ]
;[                               Offset 15:00                                 ]
;
; P     : present bit (0 = not present, 1 = present, valid)
; DPL   : descriptor privilege level
; dword count : the number of dwords that have to be copied to another stack

%macro make_callgate_descriptor 4       ; selector, offset, privilege, numdwords, flags
    dw (%2) & 0000FFFFh
    dw (%1) & 0000FFFFh
    dw ((%4) & 00011111b) | (((%5) & SD_PRESENT) << 8) | 0000110000000000b
    dw ((%2) >> 16) & 0000FFFFh
%endmacro



; 386 TSS Descriptor
;
;15   14   13   12   11   10   09   08   07   06   05   04    03   02   01   00
;[        Base address 31:24          ]  [G]  [0    0] [AVL] [Sg. length 19:16]
;[P] [  DPL  ]  [0    1    0]  [B]  [1]  [        Base address 23:16          ]
;[                             Base address 15:00                             ]
;[                            Segment length 15:00                            ]
;
; G     : granularity (0 = byte granular, 1 = page granular)
; AVL   : available
; P     : present bit (0 = not present, 1 = present, valid)
; DPL   : privilege level
; B     : busy

%define     SD_TSS_BUSY         0002h

%macro make_tss_descriptor 4            ; base, length, privilege, flags
    dw  (%2) & 0000FFFFh
    dw  (%1) & 0000FFFFh
    db  ((%1) & 00FF0000h) >> 16
    dw  ((%4) & 1001000010000010b) | (((%3) & 0011b) << 5) | (((%2) & 000F0000h) >> 8)
    db  ((%1) & 0FF000000h) >> 24
%endmacro


; 386 Task Gate Descriptor
;
;15   14   13   12   11   10   09   08   07   06   05   04   03   02   01   00
;[                                 Not Used                                  ]
;[P] [  DPL  ]  [0    0    1    0    1]  [              Not Used             ]
;[                                 Selector                                  ]
;[                                 Not Used                                  ]
;
; P     : present bit (0 = not present, 1 = present, valid)
; DPL   : privilege level
;

%macro make_taskgate_descriptor 3      ; selector, privelege, flags
    dw  0
    dw  (%1) & 0000FFFFh
    dw  (((%2) & 0011b) << 13) | ((%3) & SD_PRESENT) | 0000010100000000b
    dw  0
%endmacro


;-----------------------------------------------------------------------------
; IDT entry
; Interrupt gate or Trap Gate
;
;15   14   13   12   11   10   09   08   07   06   05   04   03   02   01   00
;[                               Offset 31:16                                ]
;[P] [  DPL  ]  [0    1    1    1]  [T]  [0    0    0    0    0    0    0   0]
;[                                 Selector                                  ]
;[                               Offset 00:15                                ]
;
; P     : present bit (0 = not present, 1 = present, valid)
; DPL   : privilege level
; T     : trap gate (0 = interrupt gate, 1 = trap gate)

%define     ID_PRESENT          8000h
%define     ID_VALID            ID_PRESENT

%define     ID_INTERRUPT_GATE   0000h
%define     ID_TRAP_GATE        0100h

%macro make_interrupt_descriptor 4      ; selector, offset, privelege, flags
    dw  (%2) & 0000FFFFh
    dw  (%1) & 0000FFFFh
    dw  (((%3) & 0011b) << 13) | ((%4) & (ID_PRESENT | ID_TRAP_GATE)) | 0000111000000000b
    dw  ((%2) & 0FFFF0000h) >> 16
%endmacro

[ Voor 6% gewijzigd door .oisyn op 16-10-2003 22:08 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

Kijkend naar mijn code is de main dus wel een real mode adres, en niet een protected mode adres...

Dit zou dus moeten werken, mits je GDT goed is geinitializeert:
Visual Basic:
1
jmp dword Programma:PM_start

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1