EmbeddedRelated.com
Forums
The 2026 Embedded Online Conference

x86 real mode

Started by Don Y October 17, 2014
Hi,

What are the most conservative, *practical* expectations I can
make living in x86 real mode:  TEXT of 64K and DATA of (disjoint)
64K?  BSS in it's own segment?  Or, shared with DATA?

And, how seemlessly will the compiler let me *implicitly* move
those segments around as well as between them?  (e.g., practical
limitations on code/data sizes).  "PC" handled 640K so should
I expect that to be the size of my playground?

[Presumably, any "object" is constrained to fit within a single
segment]

I imagine this will all be accomplished in the linkage editor
(not visible to the source code).

[What a screwed up architecture!]

Thx,
--don
On 10/17/2014 04:23 PM, Don Y wrote:
> Hi, > > What are the most conservative, *practical* expectations I can > make living in x86 real mode: TEXT of 64K and DATA of (disjoint) > 64K? BSS in it's own segment? Or, shared with DATA? > > And, how seemlessly will the compiler let me *implicitly* move > those segments around as well as between them? (e.g., practical > limitations on code/data sizes). "PC" handled 640K so should > I expect that to be the size of my playground?
It would depend on what tools you use. I remember working with Borland tools, and they'd offer a choice of several different memory models.
On 10/17/2014 7:31 AM, Arlet Ottens wrote:
> On 10/17/2014 04:23 PM, Don Y wrote: >> Hi, >> >> What are the most conservative, *practical* expectations I can >> make living in x86 real mode: TEXT of 64K and DATA of (disjoint) >> 64K? BSS in it's own segment? Or, shared with DATA? >> >> And, how seemlessly will the compiler let me *implicitly* move >> those segments around as well as between them? (e.g., practical >> limitations on code/data sizes). "PC" handled 640K so should >> I expect that to be the size of my playground? > > It would depend on what tools you use. I remember working with Borland tools, > and they'd offer a choice of several different memory models.
So, the "most conservative" would be to assume a tiny-ish model -- 64K TOTAL address space? (with everything residing therein) [I don't really care what it is, just need to know the constraints before I settle on a design. E.g., I surely wouldn't use int's if values would fit in char's and every byte of data "cost" me a byte of code!!]
On 17/10/14 16:23, Don Y wrote:
> Hi, > > What are the most conservative, *practical* expectations I can > make living in x86 real mode: TEXT of 64K and DATA of (disjoint) > 64K? BSS in it's own segment? Or, shared with DATA?
It should, I think be possible to have DS, CS and SS each pointing to a different 64 KB segment. But .bss and .data would both be part of the data segment. Access to other segments (including pointers to stack data, if SS is not the same as DS) is via "far pointers".
> > And, how seemlessly will the compiler let me *implicitly* move > those segments around as well as between them? (e.g., practical > limitations on code/data sizes). "PC" handled 640K so should > I expect that to be the size of my playground? >
I believe in real mode you can get 1 MB of address space total. I am not sure if things like video cards get mapped into that space at all, or are only accessible with I/O instructions.
> [Presumably, any "object" is constrained to fit within a single > segment]
It doesn't have to be - but it is going to be a little complex to access objects that span 64K segments.
> > I imagine this will all be accomplished in the linkage editor > (not visible to the source code). > > [What a screwed up architecture!] >
Yes, x86 was screwed up the day it arrived on the market. But the real question, which you knew someone was bound to ask, is /why/ are you using real mode on the x86? The chips boot in real mode, but you would normally jump to protected mode after a few instructions to set it up (unless you really are using an 8086 processor). I believe I read somewhere that in modern x86 chips, the cache can be configured to work as ram (basically, you have a write-back cache but disable writing back to external memory), so that if you are working with x86 code this small, you don't need any external memory. You might find more useful information on the www.coreboot.org or www.freedos.org websites.
On 10/17/2014 04:45 PM, Don Y wrote:

>>> What are the most conservative, *practical* expectations I can >>> make living in x86 real mode: TEXT of 64K and DATA of (disjoint) >>> 64K? BSS in it's own segment? Or, shared with DATA? >>> >>> And, how seemlessly will the compiler let me *implicitly* move >>> those segments around as well as between them? (e.g., practical >>> limitations on code/data sizes). "PC" handled 640K so should >>> I expect that to be the size of my playground? >> >> It would depend on what tools you use. I remember working with Borland >> tools, >> and they'd offer a choice of several different memory models. > > So, the "most conservative" would be to assume a tiny-ish model -- 64K > TOTAL address space? (with everything residing therein)
Here's an overview of the memory models: http://en.wikipedia.org/wiki/Intel_Memory_Model The smallest one is the Tiny model, but I don't know if it makes sense to use that as a design constraint, since it's a trivial matter to change to another memory model if your tools support it.
> [I don't really care what it is, just need to know the constraints > before I settle on a design. E.g., I surely wouldn't use int's > if values would fit in char's and every byte of data "cost" me > a byte of code!!]
I would start by looking for a toolchain, and see what it supports.
On Fri, 17 Oct 2014 07:23:40 -0700, Don Y <this@is.not.me.com> wrote:

>Hi, > >What are the most conservative, *practical* expectations I can >make living in x86 real mode: TEXT of 64K and DATA of (disjoint) >64K? BSS in it's own segment? Or, shared with DATA? > >And, how seemlessly will the compiler let me *implicitly* move >those segments around as well as between them? (e.g., practical >limitations on code/data sizes). "PC" handled 640K so should >I expect that to be the size of my playground? > >[Presumably, any "object" is constrained to fit within a single >segment] > >I imagine this will all be accomplished in the linkage editor >(not visible to the source code). > >[What a screwed up architecture!]
Typically compilers would offer several memory models you could use. One code (text) and one data segment was "small" model. You also had large (code and data could both be more than one segment, but no object could be bigger than a segment), and medium (one data, multiple code) was very common. Rarely did you see compact (one code, multiple data). The pointer sizes obviously varied between the models, and the larger pointers had performance impacts. There would be some limitations even with the large data models (beyond the single-object size limit). Invariably your stack could still not exceed 64KB, and some compilers insisted on putting some data (and usually the stack as well) in one "primary" data segment (usually called DGROUP), and it was occasionally possible to run out of space there if you had masses of initialized storage (you could usually tell the compiler to put initialized items elsewhere). Usually the compiler would include libraries compiled for each model, so all would work pretty much as expected. Typically you'd select the memory model with a command line switch. Some folks also supported "huge" model, which was like large, except objects bigger than 64K were supported (the generated code was often painful, but it worked). Tiny existed as well, which was the old single segment (".com") model, although that was more a mangling of small model in most cases. In most cases you could explicitly deal with larger pointers in code, for example by declaring a pointer as "far". Although that would usually have library issues that you'd have to manually deal with (for example, a program compiled medium model would have nominal small data pointers, and while you could allocate additional "far" data, and access it via far pointers, you couldn't pass those addresses to a "normal" library function like strcpy(), which, in medium mode, would be expecting only small pointers). But most serious compilers, and pretty much all C compilers, support(ed) large model just fine, and you basically see no oddities accessing the entire 640KB (or more, in 16-bit protected mode), although there is a performance hit. Nor were there usually any oddities with the other memory models (other than sometimes having different size code and data pointers). You did see some stuff if you built a mixed model application, where, as I mentioned, you'd have explicit "far"s in you code. If you *don't* do mixed model, it's just another platform.
On 10/17/2014 7:53 AM, Arlet Ottens wrote:
> On 10/17/2014 04:45 PM, Don Y wrote: > >>>> What are the most conservative, *practical* expectations I can >>>> make living in x86 real mode: TEXT of 64K and DATA of (disjoint) >>>> 64K? BSS in it's own segment? Or, shared with DATA? >>>> >>>> And, how seemlessly will the compiler let me *implicitly* move >>>> those segments around as well as between them? (e.g., practical >>>> limitations on code/data sizes). "PC" handled 640K so should >>>> I expect that to be the size of my playground? >>> >>> It would depend on what tools you use. I remember working with Borland >>> tools, >>> and they'd offer a choice of several different memory models. >> >> So, the "most conservative" would be to assume a tiny-ish model -- 64K >> TOTAL address space? (with everything residing therein) > > Here's an overview of the memory models: > http://en.wikipedia.org/wiki/Intel_Memory_Model > > The smallest one is the Tiny model, but I don't know if it makes sense to use > that as a design constraint, since it's a trivial matter to change to another > memory model if your tools support it.
Not a question of toolchain but, rather, what the *environment* already "expects" (provides). Hence the "*practical*" qualifier in my original post. Thanks! I can do a LOT in 64K. Just need to know that "going in" instead of "after the fact"...
>> [I don't really care what it is, just need to know the constraints >> before I settle on a design. E.g., I surely wouldn't use int's >> if values would fit in char's and every byte of data "cost" me >> a byte of code!!] > > I would start by looking for a toolchain, and see what it supports. >
On 17.10.14 18:28, Don Y wrote:

> Not a question of toolchain but, rather, what the *environment* > already "expects" (provides). Hence the "*practical*" qualifier in > my original post. > > Thanks! I can do a LOT in 64K. Just need to know that "going in" > instead of "after the fact"... > >>> [I don't really care what it is, just need to know the constraints >>> before I settle on a design. E.g., I surely wouldn't use int's >>> if values would fit in char's and every byte of data "cost" me >>> a byte of code!!] >> >> I would start by looking for a toolchain, and see what it supports.
One question is whether your target processor is 8086/88/186/188 or something bigger. The former wrap addresses at 1 MiB, so the old PC/AT trick to address 65520 bytes above 1048576 works only on the bigger processors. Some older 8086 code (including base PC BIOS) used small model segmenting for ROM just below 1 MiB and RAM at 0. This is the cause why there is a thing called A20 gate in PC/AT and derivatives. -- Tauno Voipio
On 10/17/2014 05:28 PM, Don Y wrote:

>> Here's an overview of the memory models: >> http://en.wikipedia.org/wiki/Intel_Memory_Model >> >> The smallest one is the Tiny model, but I don't know if it makes sense >> to use >> that as a design constraint, since it's a trivial matter to change to >> another >> memory model if your tools support it. > > Not a question of toolchain but, rather, what the *environment* > already "expects" (provides). Hence the "*practical*" qualifier in > my original post.
The environment is provided by the toolchain startup code, so it is a question of toolchain.
On 2014-10-17, Don Y <this@is.not.me.com> wrote:

> What are the most conservative, *practical* expectations I can > make living in x86 real mode: TEXT of 64K and DATA of (disjoint) > 64K? BSS in it's own segment? Or, shared with DATA?
It depends on the compiler and on the memory model you selected when invoking the compiler. Real-mode compilers usually had at least 4 memory models, sometimes more. It was a _long_ time ago I think the last time I used the Microsoft DOS C compiler there were 5: tiny small medium large huge I think tiny meant everything was in the same 64K segment (all segment registers were equal and never changed). That may have only been used for .com files rather than .exe files. All pointers were 16 bits. IIRC, small meant there was a single 64K text segment, and a single 64K data segment. All pointers were 16 bits. In medium, I think each function (or file?) had it's own text segment, but there was still a single 64K data segment (pointer to function was 32 bits, pointer to data was 16 bits). Or was that large. In huge every function (or file?) had its own text segment and its own data segment. All pointers were 32 bit. Or something like that. And then there was paging/overlay support you could add into the mix.
> [What a screwed up architecture!]
Yup. -- Grant Edwards grant.b.edwards Yow! Jesus is my POSTMASTER at GENERAL ... gmail.com
The 2026 Embedded Online Conference