Pointers in real mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
johnl87
Posts: 4
Joined: Tue Apr 08, 2008 1:23 pm

Pointers in real mode

Post by johnl87 »

When something is declared as a double word (dd) in intel syntax, how would that translate to att syntax?

For example, the video mode pointer in the vbeinfoblock struct

Code: Select all

     VbeInfoBlock struc
     VbeSignature        db   'VESA'    ; VBE Signature
     VbeVersion          dw   0200h     ; VBE Version
     OemStringPtr        dd   ?         ; Pointer to OEM String
     Capabilities        db   4 dup (?) ; Capabilities of graphics cont.
     VideoModePtr        dd   ?         ; Pointer to Video Mode List
...
It's declared as a double word so in att syntax would it be:

Code: Select all


VESA_Info:
    .ascii "VBE2"
    .word 0x300
    .word 0 //oem string ptr
    .word 0
    .byte 0, 0, 0, 0 //capabilities of graphics cont.
    .word 0 //pointer to video mode list
    .word 0
    ...
Is that correct?

After calling 0x4f00, since this is in the bootstrap code, the address returned would be 0x0 : 0xaddress so when dereferencing the pointer, I would just have to worry about the second part right?

Code: Select all

    movw $VESA_Info + 13, %ax
    movw (%ax), %ax
and then loop through all the modes that are returned, calling function 0x4f01 until I find what I'm looking for, (linear framebuffer, 1280x1024, 32bit depth)

Would that be correct?
User avatar
Brynet-Inc
Member
Member
Posts: 2426
Joined: Tue Oct 17, 2006 9:29 pm
Libera.chat IRC: brynet
Location: Canada
Contact:

Post by Brynet-Inc »

.byte == 8 bits.
.word == 16 bits.
.long == 32 bits.
.quad == 64 bits.

Hope that helps.
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.
johnl87
Posts: 4
Joined: Tue Apr 08, 2008 1:23 pm

Post by johnl87 »

Right, so should I declare a .long and use it exactly like I would in 32 bit mode? Would loading it into a 16bit register (%ax or whatever) work?
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

You can't load a 32 bit value into a 16 bit register... :roll:

you'd have to use a two-register pair, like ax:dx.
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

johnl87 wrote:Right, so should I declare a .long and use it exactly like I would in 32 bit mode? Would loading it into a 16bit register (%ax or whatever) work?
If you're in real mode, I would use 2 words, since when accessing a far pointer, you must use a segment register and general purpose register pair...

es:ax, ds:ax, etc.

If you're using pmode, you must convert the far pointer to a linear address. And lastly if you're using unreal mode (flat real mode) you would want to convert to a linear address as well, then use 0x00 in your segment register and access it using the linear address and a 32-bit register. A bit more information on your development environment will help us point you in the correct direction.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

If you load from that location into a 16 bit register, it will work, of course -- but you will only get the bottom 16 bits of the value.

You are also free to use 32 bit registers in 16 bit mode. The assembler just has to add one byte to the opcode to tell the CPU that the opcode is for a 32 bit instruction.
johnl87
Posts: 4
Joined: Tue Apr 08, 2008 1:23 pm

Post by johnl87 »

Well, as far as my situation goes, I have a bootstrap program, which loads the code from a floppy disk, switches to protected mode and jumps to an isr restore routine. The bootstrap code isn't linked with the os code. Since I'm only working on one type of machine, I guess I can just bypass the vesa modeinfo quering and just call 0x4f02 to set a mode. Do I have to call 0x4f01 on the mode to get the pointer to the frame buffer?
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

bewing wrote:If you load from that location into a 16 bit register, it will work, of course -- but you will only get the bottom 16 bits of the value.

You are also free to use 32 bit registers in 16 bit mode. The assembler just has to add one byte to the opcode to tell the CPU that the opcode is for a 32 bit instruction.
Please be careful telling people unfamiliar with assembly that they can use 32-bit registers for memory access, this is only viable in unreal mode, internally the CPU checks whatever the limit is in the selector cache, if you are in real mode, it's 65k (16-bits), and will clip a 32-bit value against this if that's how the limit is setup (same as just using a 16-bit register, except you used an extra byte infront telling it to use a 32-bit register)! Also, if you read the 32-bit value returned by the bios function for vesa, it is a segment/register pair, which would have to be converted to a linear address, so attempting to use it directly will not work even in unreal mode. Just because it's "using" a 32-bit register, which can hold a 32-bit value, doesn't mean you can read a 32-bit address if the segment cache limit is still at 64k.


johnl87: I would keep the query in there, and switch the modes, get the frame buffer pointer, and convert it to a linear address so you know where it's located in pmode. You can easily access the information in your vesa structure as well, either in pmode after converting the pointer to linear, or from real mode by using a segment register pair. I only know intel syntax (not a big fan of ATT syntax), but here is a short description on how to access the data of the Video Mode Ptr if returned as a dword (.long).

Code: Select all

;Inputs, eax = far pointer returned by bios
;Outputs, es = segment, bx = offset
;This can be simplified, but for readability, here is the function
PointerToSegOff:
  mov ebx, eax
  shr ebx, 16
  mov es, bx
  mov bx, ax
  ret

;Lets assume we already filled our structure in at this point:
mov eax, VideoModePtr
call PointerToSegOff  ;Converts us to a seg:offset [es:bx]
;es:bx is now a pointer to VideoModePtr data... so, we can now read it..
mov al, [es:bx]        ;byte from offset + 0
mov ah, [es:bx+1]   ;byte from offset + 1
mov ecx, [es:bx+4] ;dword at offset + 4
I don't recall what the format of the pointer is, but you would simply check whatever values you needed reading them as shown above.
johnl87
Posts: 4
Joined: Tue Apr 08, 2008 1:23 pm

Post by johnl87 »

Ready4Dis:
Thanks, that's what I was wondering about. Since the struct had a 32 bit field, I was wondering how it would be used when thrown into a bios interrupt in 16bit mode. I guess keeping it two separate words makes it easier to get the segment/offset instead of doing the bit shifting and stuff.
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

johnl87 wrote:Ready4Dis:
Thanks, that's what I was wondering about. Since the struct had a 32 bit field, I was wondering how it would be used when thrown into a bios interrupt in 16bit mode. I guess keeping it two separate words makes it easier to get the segment/offset instead of doing the bit shifting and stuff.
Just make sure you read the segment and offset into the correct variables ;). That little endian thing can get people sometimes.
Post Reply