Author Topic: Question about offsets and segments  (Read 14042 times)

Offline ben321

  • Full Member
  • **
  • Posts: 185
Question about offsets and segments
« on: November 21, 2015, 07:48:10 PM »
In 16bit addressing, the format looked like this SSSS:OOOO where the actual memory address was calculated like this 0xSSSS * 0x10 + 0xOOOO. However now in 32bit addressing it looks like this SSSS:OOOOOOOO. But I'm not sure how to calculate the actual memory address. I know that you still add the offset after multiplying the segment number by a constant, but I don't know the value of that constant. Is it still 16? Or now is it now 32 instead?

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Question about offsets and segments
« Reply #1 on: November 21, 2015, 08:24:37 PM »
Neither. :)

Here is some old, but still accurate AFAIK, information.
http://geezer.osdevbrasil.net/johnfine/segments.htm

In short, when we set bit 0 of cr0, we're in protected mode, and the rules change for how we calculate addresses. The segment registers now hold a "selector" which is an index into an array of "descriptors". These descriptors contain a "base" and a "limit"... plus some other things. Now the "base" is added to an offset to form an address. In practice, every OS we know uses a "base" of zero, with the exception of fs (which is used for "thread local storage"). So for practical purposes the offset is the entire address.

It gets more complicated than that, however. If bit 31 of cr0 (check me on this) is set, paging is enabled. The virtual address (as calculated above) serves as an index into page directories and page tables which map to physical memory, or if we're out of physical memory, into a swap file. Thus, we have a full 4G of virtual memory even if we have less physical RAM than that. This is mostly of interest to writers of OSen (which may include you?). Intel/AMD manuals are probably the best guide. The rest of us can just figure that the offset is the whole address.

64-bit code doesn't give us a choice - the "base" is zero except for fs - as I understand it.

Best,
Frank


Offline ben321

  • Full Member
  • **
  • Posts: 185
Re: Question about offsets and segments
« Reply #2 on: November 21, 2015, 09:16:08 PM »
Neither. :)

Here is some old, but still accurate AFAIK, information.
http://geezer.osdevbrasil.net/johnfine/segments.htm

In short, when we set bit 0 of cr0, we're in protected mode, and the rules change for how we calculate addresses. The segment registers now hold a "selector" which is an index into an array of "descriptors". These descriptors contain a "base" and a "limit"... plus some other things. Now the "base" is added to an offset to form an address. In practice, every OS we know uses a "base" of zero, with the exception of fs (which is used for "thread local storage"). So for practical purposes the offset is the entire address.

It gets more complicated than that, however. If bit 31 of cr0 (check me on this) is set, paging is enabled. The virtual address (as calculated above) serves as an index into page directories and page tables which map to physical memory, or if we're out of physical memory, into a swap file. Thus, we have a full 4G of virtual memory even if we have less physical RAM than that. This is mostly of interest to writers of OSen (which may include you?). Intel/AMD manuals are probably the best guide. The rest of us can just figure that the offset is the whole address.

64-bit code doesn't give us a choice - the "base" is zero except for fs - as I understand it.

Best,
Frank

Well that explains then why the program crashes whenever it tries to change the content of the ES register when running in Windows. The register isn't really the segment at all then, but rather an index to a table as you said.

But then explain this to me, when using OllyDbg, I see this info for the content of the segment registers:
ES 002B 32bit 0(FFFFFFFF)
CS 0023 32bit 0(FFFFFFFF)
SS 002B 32bit 0(FFFFFFFF)
DS 002B 32bit 0(FFFFFFFF)
FS 0053 32bit 7EFDD000(FFF)
GS 002B 32bit 0(FFFFFFFF)


What is the 002B, and 0023 represent (in the ES and CS registers in this example). Are these the table entries or what? And what is the 0(FFFFFFFF) at the end? This just makes it more confusing. Also, is it possible to set these base addresses in the table in question? If so, how?

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Question about offsets and segments
« Reply #3 on: November 21, 2015, 10:16:59 PM »
Ollydbg is above my pay-grade, but 23, 2B, and 53 look like the selectors. The 0s look like base and FFFFFFFF like limits - different for fs, as promised. I think to change the values (except possibly fs) you'd need to write your own OS.

Best,
Frank


Offline ben321

  • Full Member
  • **
  • Posts: 185
Re: Question about offsets and segments
« Reply #4 on: November 21, 2015, 11:26:29 PM »
Ollydbg is above my pay-grade, but 23, 2B, and 53 look like the selectors. The 0s look like base and FFFFFFFF like limits - different for fs, as promised. I think to change the values (except possibly fs) you'd need to write your own OS.

Best,
Frank

Is there an intel x86 instruction for setting the values in the segment table? Or where is this table stored? Somewhere in memory? If so, there should be a way to edit it.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Question about offsets and segments
« Reply #5 on: November 22, 2015, 12:49:07 AM »
Rather a naive view...

http://wiki.osdev.org/GDT_Tutorial

Best,
Frank