3

I am currently writing an OS from complete scratch(making my own bootloader etc), and I am attempting to adapt VESA mode. I have read documentation, it all makes sense..all but just a few things.

This is directly from the documentation(I have it implemented differently):

vbe_set_mode:
    mov [.width], ax
    mov [.height], bx
    mov [.bpp], cl
 
    sti
 
    push es                 ; some VESA BIOSes destroy ES, or so I read
    mov ax, 0x4F00              ; get VBE BIOS info
    mov di, vbe_info_block
    int 0x10
    pop es
 
    cmp ax, 0x4F                ; BIOS doesn't support VBE?
    jne .error
 
    mov ax, word[vbe_info_block.video_modes]
    mov [.offset], ax
    mov ax, word[vbe_info_block.video_modes+2]
    mov [.segment], ax
 
    mov ax, [.segment]
    mov fs, ax
    mov si, [.offset]
 
.find_mode:
    mov dx, [fs:si]
    add si, 2
    mov [.offset], si
    mov [.mode], dx
    mov ax, 0
    mov fs, ax
 
    cmp [.mode], 0xFFFF         ; end of list?
    je .error
 
    push es
    mov ax, 0x4F01              ; get VBE mode info
    mov cx, [.mode]
    mov di, mode_info_block
    int 0x10
    pop es
 
    cmp ax, 0x4F
    jne .error
 
    mov ax, [.width]
    cmp ax, [mode_info_block.width]
    jne .next_mode
 
    mov ax, [.height]
    cmp ax, [mode_info_block.height]
    jne .next_mode
 
    mov al, [.bpp]
    cmp al, [mode_info_block.bpp]
    jne .next_mode
 
    ; If we make it here, we've found the correct mode!
    mov ax, [.width]
    mov word[vbe_screen.width], ax
    mov ax, [.height]
    mov word[vbe_screen.height], ax
    mov eax, [mode_info_block.framebuffer]
    mov dword[vbe_screen.physical_buffer], eax
    mov ax, [mode_info_block.pitch]
    mov word[vbe_screen.bytes_per_line], ax
    mov eax, 0
    mov al, [.bpp]
    mov byte[vbe_screen.bpp], al
    shr eax, 3
    mov dword[vbe_screen.bytes_per_pixel], eax
 
    mov ax, [.width]
    shr ax, 3
    dec ax
    mov word[vbe_screen.x_cur_max], ax
 
    mov ax, [.height]
    shr ax, 4
    dec ax
    mov word[vbe_screen.y_cur_max], ax
 
    ; Set the mode
    push es
    mov ax, 0x4F02
    mov bx, [.mode]
    or bx, 0x4000           ; enable LFB
    mov di, 0           ; not sure if some BIOSes need this... anyway it doesn't hurt
    int 0x10
    pop es
 
    cmp ax, 0x4F
    jne .error
 
    clc
    ret
 
.next_mode:
    mov ax, [.segment]
    mov fs, ax
    mov si, [.offset]
    jmp .find_mode
 
.error:
    stc
    ret
 
.width              dw 0
.height             dw 0
.bpp                db 0
.segment            dw 0
.offset             dw 0
.mode               dw 0

What I am confused about is, why does it assign the segment to the video modes pointer plus 2? I get that the video mode pointer has an offset:segment, but I am just confused as to why we assign video mode pointer + 2 to the segment, and why we add si by two after we assign the offset and segment to the dx register.

phuclv
  • 37,963
  • 15
  • 156
  • 475

1 Answers1

1
mov ax, word[vbe_info_block.video_modes]
mov [.offset], ax
mov ax, word[vbe_info_block.video_modes+2]
mov [.segment], ax

why does it assign the segment to the video modes pointer plus 2? I get that the video mode pointer has an offset:segment, but I am just confused as to why we assign video mode pointer + 2 to the segment

A far pointer is stored in memory with a word-sized offset followed by a word-sized segment.
The offset is stored at vbe_info_block.video_modes, and the segment is stored in the following word which has an address that is 2 more, so at [vbe_info_block.video_modes + 2]

mov dx, [fs:si]
add si, 2
mov [.offset], si

and why we add si by two after we assign the offset and segment to the dx register.

We don't assign the offset and segment to the DX register!

The far pointer we retrieved (and put in FS:SI) points to a list of word-sized mode numbers. It's a mode number that we load in the DX register. And the add si, 2 mov [.offset], si is there so the loop can iterate over all the words in the list.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76