first post here
First of all I would like to thank you guys for all documentation, tutorials and forum discussions of this site. It is a mine of gold and I am having a blast taking my first steps in the OS dev world.
I am trying to get a grasp on the concepts and techniques around memory while in protected mode.
I have been reading about DGT descriptor and entries, memory layout, meaning and purpose of each of the 8 bytes of every DGT entry, and how to switch to Protected mode.
I have been commenting and executing carefully using bosch a simple example I found that writes a string while in Real mode, using Int 0x10 and then switches to Protected mode, defines one code segment and one data segment (covering the whole 4 Gb each), and then switches to Protected mode and writes another string writing over the VGA RAM area.
Where I am getting lost is in this line:
jmp CODE_SEG:b32
CODE_SEG at that moment is equal to 0x08, which happens to be the GDT entry for the code section. My question/s are:
- I fail to understand why using 0x08:b32 to jump to b32.
What would be the difference of just jump to b32.
Is this what we consider a far jump?
If so, how b32 ended up in a different segment? Is there any relationship of this with the [bits 32] directive?
Any tip, advise, suggestion will be very welcome !! Thanks in advance !
Code: Select all
; TODO: WRITE VGA RAM IN REAL MODE!!!!!!!!!!! INVESTIGATE THE OFFSET OF THE MEMORY AND TRY RANDOM STUFF THERE
[bits 16]
[org 0x7c00]
xchg bx, bx ; magic breakpoint
jmp 0:kernel_start
gdt_start:
gdt_null:
dd 0x0 ; 0x00000000 double word, 32 bits, 4 bytes < GDT descriptor 2 + 4 bytes, size + offset
dd 0x0 ; 0x00000000 double word, 32 bits, 4 bytes ; can be used for a pointer to GDT itself
gdt_code: ;cs should point here, code segment
dw 0xffff ; 0xFFFF <- limit low 2 bytes word 0 - 63 (20 bits wide )
dw 0x0 ; 0x0000 <- base low 2 bytes word
db 0x0 ; 0x00 <- base middle 1 byte
db 10011010b ; 0x9A <- access 1 byte - 1 fix - ring:0 - exec:true -direction:down
db 11001111b ; 0xCF <- granularity 1 byte - high = flags, low = limit high, for 4 bits for 20 bits wide limit
db 0x0 ; 0x00 <- base high 1 byte 63 - 63
gdt_data: ;ds, ss, es , fs and gs should point to data descriptor. why??
dw 0xffff ; 0xFFFF 2 bytes word
dw 0x0 ; 0x0000 2 bytes word
db 0x0 ; 0x00 1 byte
db 10010010b ; 0x92
db 11001111b ; 0xCF
db 0x0 ; 0x00 1 byte
gdt_end:
gdt_descriptor: ; there it goes the GDT descriptor 2 bytes size (8 null + 8 per entry = 24 = 0x18)
dw gdt_end - gdt_start ; 0x18 (with calc, and debug) - Total GDT table size !!
dd gdt_start ; 0x7c07
CODE_SEG equ gdt_code - gdt_start ; offste from start of the GDT to point CODE section ;0x8
DATA_SEG equ gdt_data - gdt_start ; offset from start of the GDT to point DATA section ;0x10
print:
pusha
xchg bx, bx ; magic breakpoint
mov ah, 14
mov bh, 0
.loop:
lodsb
cmp al, 0
je .done
int 0x10
jmp .loop
.done:
popa
ret
uzenet16 db 'Windows 9 !!!', 0
uzenet32 db 'uzenet32', 0
kernel_start:
mov ax, 0
mov ss, ax
mov sp, 0xFFFC ; byte 65,532
mov ax, 0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov si, uzenet16
call print
cli
xchg bx, bx ; magic breakpoint
mov edx,0 ; Bringing to edx the values of the GDT calculations for analysis
mov edx, gdt_start ; 0x7c07
mov edx,0
mov edx, gdt_end ; 0x7c1f
mov edx,0
mov edx, CODE_SEG ;0x8
mov edx,0
mov edx, DATA_SEG ;0x10
mov edx,0
mov edx, gdt_descriptor ; 0x7c1f
mov edx,0
mov edx, gdt_data ; 0x7c1f
mov edx,0
mov edx, gdt_code ; 0x7c0f
xchg bx, bx ; magic breakpoint
lgdt[gdt_descriptor] ; 0x7c1f
xchg bx, bx ; magic breakpoint
mov eax, cr0
or eax, 0x1
mov cr0, eax
jmp CODE_SEG:b32
[bits 32]
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
print32:
pusha
mov edx, VIDEO_MEMORY
.loop:
mov al, [ebx]
mov ah, WHITE_ON_BLACK
cmp al, 0
je .done
mov [edx], ax
add ebx, 1
add edx, 2
jmp .loop
.done:
popa
ret
b32:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov ebp, 0x2000
mov esp, ebp
mov ebx, uzenet32
call print32
jmp $
[SECTION signature start=0x7dfe]
dw 0AA55h