News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Question about memory accesses

Started by Oliver, January 08, 2010, 10:58:00 AM

Previous topic - Next topic

Oliver

Hi,

I am working on a BIOS porting for a AMD Geode LX processor.

In this project I have to access a register of a device which is at address 0xFF000000. But I am not sure how to access this register.

The BIOS itself lies in the address range 0xFFFC0000 to 0xFFFFFFFF.
The machine starts at address 0xFFFFFFF0, which the processor accesses by setting the code segment cs to 0xf000 and the program counter eip to 0xFFF0. In the debugger I see a additional register called cs.base, which is FFFF000. So it seems that this cs.base is somehow calculated from cs and I get the correct memory address by adding cs.base and eip.
For me it looks as if the cs.base is calculated from cs by multiplaying by 16 and then doing a sign extension to 32 bits.
So with the help of this cs.base this access to the BIOS range is possible. (Otherwise the machine wouldn't boot at all)

But in my example I need to access the address 0xFF000000. I was able to read this address by using the debugger and manually setting cs to 0 and cs.base to 0xFF000000. But how can I access this cs.base register using normal assembler code written in MASM? If my explanation above is corrected I would need to set cs to 0x0FF0.0000 to get the correct cs.base, but since cs is only 16 bits wide, this is not possible.

Or is there a way to set the processor into protectedl mode and directly address 0xFF000000 without using segmentation? I used code segment cs in the explanation above, but in my code I might use data segment ds, but the problem stays the same.

I hope someone can help me with my problem.


Thanks,


Oliver



dedndave

Hi Oliver - welcome to the forum   :U

the segment value is always on 16-byte boundries
(a change of one in the segment value is a change of 16 in calculated linear address)
with a segment value of 0F000h, you can access everything to the end of x86 memory

segment F000  16 bits
offset  F000 16 bits
address FF000 24 bit address - accesses 1 Mb linear address space

you would normally see it written as "F000:F000"
that is essentially the same address as "FF00:0000"
that address is normally part of the BIOS ROM

sometimes, you may see other values written in the form XXXX:YYYY
that may indicate XXXXYYYY
in the case of segmented addressing, it is XXXX0+YYYY

FORTRANS

Hi,

   The base is a part of the protected mode selector.  In
real mode, as on boot-up, your addresses are from 00000H
to FFFFFH, a 1 MB range.  The 20 bit address is formed as
pointed out by Dave.  To get a 32-bit address you need to
be in protected mode.  Even in real mode there is a selector
defined for each of the segment registers, but it is not accessible.

   Check the documentation about your chip's startup memory
addressing.  It may have a 32-bit address until some code is
executed and normal real mode addressing is enforced.

Regards,

Steve N.

Edit: One source says you do execute with a 32-bit address until
a far jump is executed.  So (if this is correct) you do start at
FFFFFFF0H.  But after a far jump you go into segmented mode.

SRN

Oliver

So why can the processor access the start adress 0xFFFFFFF0 which can not be written as a segmented address, if it starts in real mode? Or does the instruction fetch always happen in protected mode?
And why can I access the ds.base with the debugger? Does it automatically switch to protected mode to access this register ?

dedndave

the processor starts execution at address F000:FFF0
when you run the debug program, windows recognizes that it is a 16-bit program and runs it under ntvdm.dll
that creates a virtual machine real-mode world for your 16-bit code to run under

FORTRANS

Hi,

   I checked some Intel documentation I have, and found the
following paragraph in the 486 data sheet.  While a Geode is
not a 486, it may help.

   "The 486 microprocessor will start executing instructions at
location FFFFFFF0H after a RESET.  When the first InterSegment Jump
or Call is executed, address lines A20-A31 will drop LOW for for
CS-relative memory cycles, and the 486 microprocessor will only
execute instructions in the lower one Mbyte of physical memory.
This allows the system designer to use a ROM at the top of physical
memory to initialize the system and take care of RESETs."

   What the other segments are doing is not mentioned.  A table
shows them as zeroed out.  You might be able to use CS overrides
on memory access instructions.  Anyway, check something a bit
more informative than a data sheet to find out what is happening.

HTH,

Steve N.

Oliver

Quote from: dedndave on January 08, 2010, 03:03:57 PM
the processor starts execution at address F000:FFF0
when you run the debug program, windows recognizes that it is a 16-bit program and runs it under ntvdm.dll
that creates a virtual machine real-mode world for your 16-bit code to run under

My question was not why my PC can understand the 16 bit mode, it was why the Geode processor which works in 16 bit mode can still access a 32 bit address.

But FORTRANS gave the right idea. So I guess the address 0xFF000000 is not accessible at all in real mode. And the register cs.base seems to be a helpregister the processor uses at startup to expand the 16bit address to 32bits. So the only remaining question is whether I can access this register.

dedndave

hiya Steve
all of the BIOS code i have looked at begins with a far jump at F000:FFF0
there are only 16 bytes of code space available - lol
usually, that jump is followed by the vendor name and ID code, as well as a ROM checksum value
that jump sets the CS and IP registers, of course
the code at that target address usually begins by setting the other segment registers

FORTRANS

Hi Dave,

   One memory about a BIOS is that the hardware would
have the ROM code addressed in both places.  So that the
end of the 32-bit address space would have the same code
as the end of the 16-bit address space.  And you only have
16 bytes in any event, so some kind of jump seems to be
required.  And so, unless you are careful, you end up in real
mode with segmented addressing real quick.

   Doing an intrasegment jump presumably leaves the 32-bit
address open, but it seems the selectors are not in a very
good state, and so you would have to set them up as part of
the start-up code.  And you then need an intersegment jump
to activate them.  I imagine you might as well go into protected
mode at the same time if 4 Gig addressing is wanted.

   I have a lot of trivia saved up, but I am not an expert here.

Regards,

Steve N.

dedndave

that's ok Steve - i am no expert, either
i was pretty good with th 8086 - lol
of course, all that info was a waste of time   :P

Farabi

Im a bit confused about the memory segmentation too, I can access the Video RAM just like it was part of my RAM. I wonder how if I was having a 4 GB memory, how to access all of it when the register was sharing with the VRAM too.


To access the 0xFF000000 you will need to jump to protected mode and then set the base memory to 0xff000000. You should understand LGDT instruction, I've forgot the GDT table field. But If you had send the GDT to the processor, you will just need to switch using the segment register.


LGDT some_GDT
mov ds,The_GDT
mov eax,ds:[esi]
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

dedndave

the video ram is paged into a window of the x86 address space
typically, the A000 and B000 segments can be used
on the video card, there are I/O accessible registers that allow you to control which pages of video memory are enabled
unfortunately, all that I/O stuff requires ring 0 access under win 2000 and up
it was fun to program for win 95/98, because you could still do hardware I/O
one of these days, i will have to play with ring 0 and see how hard it is to code

sinsi

Intel docs, volume 3A, section 8.1.4
QuoteThe first instruction that is fetched and executed following a hardware reset is located at physical address FFFFFFF0H. This address is 16 bytes below the
processor's uppermost physical address. The EPROM containing the software-initialization code must be located at this address.

The address FFFFFFF0H is beyond the 1-MByte addressable range of the processor while in real-address mode. The processor is initialized to this starting address as
follows. The CS register has two parts: the visible segment selector part and the hidden base address part. In real-address mode, the base address is normally
formed by shifting the 16-bit segment selector value 4 bits to the left to produce a 20-bit base address. However, during a hardware reset, the segment selector in the
CS register is loaded with F000H and the base address is loaded with FFFF0000H. The starting address is thus formed by adding the base address to the value in the EIP
register (that is, FFFF0000 + FFF0H = FFFFFFF0H).

The first time the CS register is loaded with a new value after a hardware reset, the processor will follow the normal rule for address translation in real-address mode
(that is, [CS base address = CS segment selector * 16]). To insure that the base address in the CS register remains unchanged until the EPROM based software-
initialization code is completed, the code must not contain a far jump or far call or allow an interrupt to occur (which would cause the CS selector value to be changed).

To access your device at FF000000 you would need to be in protected mode. The easiest way to do that is base=0,limit=FFFFFFFF with interrupts disabled.
Program the device, then go back to real mode.
Light travels faster than sound, that's why some people seem bright until you hear them.

MichaelW

It's not actually necessary to be in protected mode at the time of the access, if you first enter protected mode temporarily to load the necessary base and limit into the descriptor cache for whatever segment register is being used for the access. The attachment contains an app that does this, and compares the 16 bytes at absolute address FFFF0 to the 16 bytes at absolute address FFFFFFF0. Note that the app will not work under Windows 2000, but it might under Windows 9x. Here are the results for my test system, running under MS-DOS 6.22:

EA5BE000F030342F31302F393800FCD3
0
1
EA5BE000F030342F31302F393800FCD3
2EFF26F5FF1BC000EA1DC000F000002B


The first 5 bytes are:

2EFF26F5FF JMP WORD PTR CS:[FFF5]

And the others appear to be data.
eschew obfuscation

dedndave

#14
EA5BE000F030342F31302F393800FCD3

EA5BE000F0 = JMP     F000:E05B

30342F31302F393800 = DB      '04/10/98',0

FCD3 = DW      0D3FCh  ;probably the ROM checksum compliment (so the total ROM checksum = 0)

the date serves as the revision number - the checksum is sometimes used that way, too
if you look at the lower addresses of the ROM, you will probably find who it was written by and/or the machine OEM

Michael, if i win the lottery, i am buying you a new machine - lol