Page 1 of 1
Pointers in real mode
Posted: Wed Apr 16, 2008 7:43 pm
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?
Posted: Wed Apr 16, 2008 7:46 pm
by Brynet-Inc
.byte == 8 bits.
.word == 16 bits.
.long == 32 bits.
.quad == 64 bits.
Hope that helps.
Posted: Wed Apr 16, 2008 7:51 pm
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?
Posted: Thu Apr 17, 2008 1:24 am
by JamesM
You can't load a 32 bit value into a 16 bit register...
you'd have to use a two-register pair, like ax:dx.
Posted: Thu Apr 17, 2008 11:58 am
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.
Posted: Thu Apr 17, 2008 1:26 pm
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.
Posted: Thu Apr 17, 2008 6:40 pm
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?
Posted: Thu Apr 17, 2008 7:23 pm
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.
Posted: Thu Apr 17, 2008 8:37 pm
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.
Posted: Fri Apr 18, 2008 1:36 pm
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.