s***@crayne.org
2005-11-01 01:29:35 UTC
Howdy!
I'm a relative newbie to GAS, but I've played a fair bit with MASM.
I'm using GAS in an O/S-less environment. Meaning the elf format is
handy for debug and loading, but we don't have an operating system
setting things up for us. We need to transition the processor from
realmode to protected mode.
As part of my transition from Real mode to Protected, I want to load
the GDT. I'd like to be able to locate the GDT anywhere within the
".data" segment. In MASM, I accomplished this by:
mov ds, 0x9000 ;better match the base addr of the seg where
gdt is.
mov esi, offset gdt_init ;grabs the offset relative to wherever gdt
lives
lgdt ds:[esi] ;builds address 90000.
The same thing does not appear to work within GAS - if I attempt to
grab the "offset", it seems to think I want a Linux based offset. So it
waits until link time, and supplies the symbol's address information
then, as an absolute Address rather than as a relative offset.
This Makes sense since Linux uses flat addressing mode. In most
programs, DS would be set to 0, with a limit of F_FFFF and you can grab
whatever, wherever. So you would logically put the offset 0x90000 into
ESI.
But we're still in real mode, trying to transition. So it doesn't make
sense if that address lives at 0x90000. Setting ESI to 0x90000 returns
way too big of a value so it gpf's since it exceeds the limit.
What I want, is to obtain the relative offset within the data segment
of a variable - and have the preprocessor stuff this into my mov into
esi instruction. I can manage my DS. I can do this by hand supplying
esi, but it seems like there is a more elegant solution. Suggestions?
thanks!
---------
.intel_syntax noprefix
.arch i686
.file "test.s"
.text
.code16 #code16 vs. code16gcc - all targets for call with gcc are
32bit.
.globl _start
_start:
mov ax,0x9000
mov ds,ax
.att_syntax
mov $_gdt_init, %esi #this places 0x90000 into ESI after Link
stage
#happens. Not what we want.
.intel_syntax noprefix
mov esi,0
addr32 lgdt ds:esi # setup the gdt...
mov eax,cr0
or eax, 0x01 ##turn on protected mode (0)
mov cr0,eax # turns the protected mode on
ljmp 0x8, 0 #go to the protected mode segment
.code32
.org 0x2000 #absolute offset 0x80000
protected_region:
mov eax, 5
mov ebx, 6
mov edx, 7
hlt
.data
#don't move the gdt. I couldn't get intersegment referencing to work,
so I need
#it to live at Address 0!
.align 16
_gdt_init:
.word gdt_finish - _gdt_init - 1 #this is the limit of the GDT
table.
.long 0x90000 #this is the location of the GDT
table.
.word 0
#code0 descriptor entry
code0_desc:
#overall base 0x80000
.long 0x0000FFFF #base addr 0000, limit FFFF
.long 0x00CF9908 #base 00, g=1 d=1, limit F, present
#dpl=0,1/type=accessed, base 08
gdt_finish:
---------------------
here's how I'm linking it:
OUTPUT_FORMAT("elf32-i386")
OUTPUT_ARCH(i386)
SECTIONS
{
. = SIZEOF_HEADERS;
.text 0x7e000 : { *.o( .text ) }
.data 0x90000 : { *.o( .data ) }
.bss : { *.o( .bss ) }
/DISCARD/ : { *(.note.GNU-stack .comment) }
}
I'm a relative newbie to GAS, but I've played a fair bit with MASM.
I'm using GAS in an O/S-less environment. Meaning the elf format is
handy for debug and loading, but we don't have an operating system
setting things up for us. We need to transition the processor from
realmode to protected mode.
As part of my transition from Real mode to Protected, I want to load
the GDT. I'd like to be able to locate the GDT anywhere within the
".data" segment. In MASM, I accomplished this by:
mov ds, 0x9000 ;better match the base addr of the seg where
gdt is.
mov esi, offset gdt_init ;grabs the offset relative to wherever gdt
lives
lgdt ds:[esi] ;builds address 90000.
The same thing does not appear to work within GAS - if I attempt to
grab the "offset", it seems to think I want a Linux based offset. So it
waits until link time, and supplies the symbol's address information
then, as an absolute Address rather than as a relative offset.
This Makes sense since Linux uses flat addressing mode. In most
programs, DS would be set to 0, with a limit of F_FFFF and you can grab
whatever, wherever. So you would logically put the offset 0x90000 into
ESI.
But we're still in real mode, trying to transition. So it doesn't make
sense if that address lives at 0x90000. Setting ESI to 0x90000 returns
way too big of a value so it gpf's since it exceeds the limit.
What I want, is to obtain the relative offset within the data segment
of a variable - and have the preprocessor stuff this into my mov into
esi instruction. I can manage my DS. I can do this by hand supplying
esi, but it seems like there is a more elegant solution. Suggestions?
thanks!
---------
.intel_syntax noprefix
.arch i686
.file "test.s"
.text
.code16 #code16 vs. code16gcc - all targets for call with gcc are
32bit.
.globl _start
_start:
mov ax,0x9000
mov ds,ax
.att_syntax
mov $_gdt_init, %esi #this places 0x90000 into ESI after Link
stage
#happens. Not what we want.
.intel_syntax noprefix
mov esi,0
addr32 lgdt ds:esi # setup the gdt...
mov eax,cr0
or eax, 0x01 ##turn on protected mode (0)
mov cr0,eax # turns the protected mode on
ljmp 0x8, 0 #go to the protected mode segment
.code32
.org 0x2000 #absolute offset 0x80000
protected_region:
mov eax, 5
mov ebx, 6
mov edx, 7
hlt
.data
#don't move the gdt. I couldn't get intersegment referencing to work,
so I need
#it to live at Address 0!
.align 16
_gdt_init:
.word gdt_finish - _gdt_init - 1 #this is the limit of the GDT
table.
.long 0x90000 #this is the location of the GDT
table.
.word 0
#code0 descriptor entry
code0_desc:
#overall base 0x80000
.long 0x0000FFFF #base addr 0000, limit FFFF
.long 0x00CF9908 #base 00, g=1 d=1, limit F, present
#dpl=0,1/type=accessed, base 08
gdt_finish:
---------------------
here's how I'm linking it:
OUTPUT_FORMAT("elf32-i386")
OUTPUT_ARCH(i386)
SECTIONS
{
. = SIZEOF_HEADERS;
.text 0x7e000 : { *.o( .text ) }
.data 0x90000 : { *.o( .data ) }
.bss : { *.o( .bss ) }
/DISCARD/ : { *(.note.GNU-stack .comment) }
}