AST's message on the new compiler didn't make it to the West Coast -
no, not Oban - either. A repost is probably indicated.
Ok. Here it is for the third time.
Andy Tanenbaum (a...@cs.vu.nl)
--------------------------------------------------------------------------
The new MINIX compilers are finally available. Sorry for the small :-)
delay. It is my intention to go over to the ANSI C compiler for MINIX 2.0.
In fact, I have been running nothing else but the ANSI compiler for over
a year, and it seems pretty solid. The compiler runs on 8088, 286, and 386
machines. It also runs on MINIX 1.5, and probably on most previous versions.
Most of version 1.6.18 is already ANSI-fied. Nevertheless, as much as possible,
I will keep the 2.0 code such that it can be compiled with the old compiler,
so you don't have to switch to the new ANSI compiler if you can't afford it.
In addition, we also have compilers for Pascal and Modula 2. Since most
of the compiler is identical for all ACK generated compilers, it was easy
to throw in additional front ends without taking up much extra disk space,
so we have put together a package with ANSI C, Pascal, and Modula 2 for MINIX.
(For information on ACK, see my paper in Commun. of the ACM, Sept. 1983.)
The distribution is binary only, except for the ANSI C library, whose
full source is provided.
The three compilers provided are:
- ANSI C, conforming to ANS X3.159-1989
- Modula-2, conforming to
"Report on The Programming Language Modula-2", in "Programming in
Modula-2, 3rd ed." by Niklaus Wirth, Springer-verlag, 1983
- Pascal confrming to level 1 of BSI standard BS 6192: 1982 (ISO 7185),
with a few small exceptions
Also, a Modula-2 makefile generator and some utilities for handling
relocatable object files are included (aal, nm, size, strip, etc).
Complete libraries for ANSI C, Pascal, and Modula 2 are provided.
This package is available in 4 different versions:
- 5.25" DS/DD floppies for 8088/286/386 (4 360K floppies);
- 5.25" DS/HD floppies for 8088/286/386 (1 1.2M floppy);
- 3.5" DS/DD floppies for 8088/286/386 (2 720K floppies);
- 3.5" DS/DD floppies for Commodore Amiga or Atari ST (2 720K floppies).
Many problems with the old Minix C compiler have been resolved:
- All versions have separate as and ld programs. Asld is gone.
- Floating point is now supported
- Library is greatly improved and is ANSI conformant
- A program aal is provided to manage libraries (ranlib-like)
The package is available from two companies:
Transmediair Products & Support B.V. Unipress Software
Melkweg 3 2025 Lincoln Highway
3721 RG Bilthoven Edison, NJ 08817
The Netherlands U.S.A.
Tel: +31 30 281820 Tel: +1 908 287 2100
FAX: +31 30 292294 FAX: +1 908 287 4929
Email: m...@unipress.com
Transmediair charges US $200,- for the 4 floppy PC version, US $150,-
for the other versions. Unipress charges US $199,- for all versions.
Andy Tanenbaum (a...@cs.vu.nl)
UUCP: {hplabs!hp-sdd ucsd nosc}!crash!pnet01!hall
ARPA: crash!pnet01!ha...@nosc.mil
INET: ha...@pnet01.cts.com
> The new MINIX compilers are finally available. Sorry for the small :-)
>delay. It is my intention to go over to the ANSI C compiler for MINIX 2.0.
>In fact, I have been running nothing else but the ANSI compiler for over
>a year, and it seems pretty solid. The compiler runs on 8088, 286, and 386
>machines. It also runs on MINIX 1.5, and probably on most previous versions.
Andy,
I know you have already replied to part of this in private,
e-mail, but the rest of this seems more appropriate for the
whole community.
Andy, has already confirmed to me that these mew compilers
still have a 64K+64K limit on the PC version, not the other
versions.
My question is this - does anyone know of the current/future
availibility of a compiler for 286 minix systems which does
not have the 64K limit. Since minix can use protected mode on
a 286 system, it seems rather strange that 286 systems are still
stuck with this "old" limit. [ No, I'm not competant enough
to write such a compiler :-( ] Thanks in advance for any info.
I'll summarize any e-mail.
--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Stuart Millington = "A mind is a terrible thing,
uad...@dircon.UUCP = remember that."
...!uknet!dircon!uad1146 = David Bryan, Bon Jovi
For the 286,the problem is NOT the compiler. It is the operating
system itself. The OS does not understand segmented memories.
For the 68000, there is no such limit. Thus fixing the compiler
does not help. For DOS, there is no problem because DOS does not
keep track of memory at all.
Andy Tanenbaum (a...@cs.vu.nl)
[ ... about large memory model compiler for minix ... ]
>For the 286,the problem is NOT the compiler. It is the operating
>system itself. The OS does not understand segmented memories.
>For the 68000, there is no such limit. Thus fixing the compiler
>does not help.
The OS already keeps track of 2 segments (well, 3, but the third is
always zero-size). Generalizing this to an arbitrary number of
segments shouldn't be too hard. Writing a new compiler seems more of a
problem to me (But I have written neither an OS nor a compiler yet, so
what do I know :-)
--
| _ | Peter J. Holzer | Think of it |
| |_|_) | Technical University Vienna | as evolution |
| | | | Dept. for Real-Time Systems | in action! |
| __/ | h...@vmars.tuwien.ac.at | Tony Rand |
I talked with Toni at Unipress Software on Monday, March 16 to try and get the
details on the compiler straight. They said that they had not seen AST's note,
so I forwarded her a copy. Also they have been trying to get a hold of you
Andy (ARE YOU LISTENING). Please give them a call.
--
"It's astounding.
Time is fleeting. ** YOU THINK I SAID WHAT??? **
Maddness takes its toll ..."
Dale Dey,ded...@otis.ca.boeing.com,BCS,Box 24346,M/S 6M-97,Seattle,(206) 234-3611
> The compiler runs on 8088, 286, and 386
> machines. It also runs on MINIX 1.5, and probably on most previous versions.
If I read right, this is the small difference between "runs on ..." and
"supports ...", or am I wrong? ACK does not even generate 80186 code, only
plain 8088. BTW: runs on 8088, 286 and 386 ... you forgot 80186 and 80486.
It sounds much better :)
> Most of version 1.6.18 is already ANSI-fied. Nevertheless, as much as possible,
> I will keep the 2.0 code such that it can be compiled with the old compiler,
> so you don't have to switch to the new ANSI compiler if you can't afford it.
So if a student gets MINIX to experiment with, the first test he has to
pass, is fighting with an old compiler and its bugs. No prototypes, no
ANSI typechecking, no useful warnings. MINIX is a wonderful system to
experiment with, but why ANSIfy everything and shipping it with this old
compiler? Sorry, it does not make sense for me.
> - ANSI C, conforming to ANS X3.159-1989
> - Modula-2, conforming to
> "Report on The Programming Language Modula-2", in "Programming in
> Modula-2, 3rd ed." by Niklaus Wirth, Springer-verlag, 1983
> - Pascal confrming to level 1 of BSI standard BS 6192: 1982 (ISO 7185),
> with a few small exceptions
Well, that's an offer. I think the price is ok for what you get. On
the other side, what is MINIX intended to be? I thought an experimental
system, without all these features of real UNIX, or Linux to be precise.
No virtual consoles, but a student should be able to develop programs?
Two weeks after I got MINIX 1.3 a few years ago, I had a vt100 to kill
jobs. This combination doesn't make sense to me as well: Programming
languages conforming to standards, but an programming environment
without any features. I haven't seen combined offers of MINIX+serial
tty yet, and waiting 30 seconds for update to sync and rebooting to kill
a program running an infinite loop in rawmode isn't the best solution.
> Also, a Modula-2 makefile generator and some utilities for handling
> relocatable object files are included (aal, nm, size, strip, etc).
> Complete libraries for ANSI C, Pascal, and Modula 2 are provided.
Are there at least sources for the utilities?
> - Floating point is now supported
In software, I guess. Or is there FPU support?
> - Library is greatly improved and is ANSI conformant
Greatly improved earlier PD code which is now copyrighted? Or a completely
new library?
> Transmediair charges US $200,- for the 4 floppy PC version, US $150,-
> for the other versions.
So, if I would like to use MINIX on a 286 machine, I will have to buy it
(I forgot the exact price, something about $150 to $200 I think) plus at
least $150. Makes at least $300 for me. $300 -- and no compiler sources.
If I would be that student, I would buy a new mainboard and ftp Linux.
GNU C 1.40 comes of course with sources, and there is even GNU C 2.0 with
GC++ support (again with sources).
Sorry, I don't want to offend you, but I think that no free compiler
binary means the end of MINIX for most people, and I don't like that.
The offer for these three compilers is ok, but what if I want to hack in
the ANSIfied kernel *with ANSI support* and if I don't need Pascal or M2
at all? MINIX *is* copyrighted, and there is no official permission to
make copies for it to other people. No one will give it to me for free
at the university here, so I *have* to buy it, or to break laws.
In fact, now I am convinced that I have to leave MINIX and change to
Linux when the next release comes out. I think in a few months, I will
sell my MINIX 1.3 package with all my upgrades and software, and perhaps
buy a small used second harddisk as swapping and /tmp device for the
money. Until then, I will swap to a file. Period.
Michael
The intention is that the source code will remain compilable with the old
compiler, so it is not necessary to get the new one. People running Bruce's
32 bit version can use GCC. If all this means the end of MINIX, so be it.
Andy Tanenbaum (a...@cs.vu.nl)
Another interesting though, wasn't this the same person who was
complaining about people trying to force backwards programming style on him
during the BSD monolithic OpSys flamewar a little bit ago?? Nothing more
backwards than that asld thing with 8char identifiers and no ranlib.
Also, 386 & mx386 are not officially supported, or has Andy
conveniently forgotton about that. It's just in the 'experimental'
stage, and isn't part of the 'official' distribution. You can't use
gcc without about 4Meg on mem, so even with mx386, Andy's suggestion
of using gcc is bad at best.
> My question is this - does anyone know of the current/future
> availibility of a compiler for 286 minix systems which does
> not have the 64K limit. Since minix can use protected mode on
> a 286 system, it seems rather strange that 286 systems are still
> stuck with this "old" limit. [ No, I'm not competant enough
> to write such a compiler :-( ] Thanks in advance for any info.
> I'll summarize any e-mail.
Well, my reaction will be In Public :-)
1. The 64+64K limit is not only the fault of the compiler. In MM
and the kernel a process gets only _one_ CS and _one_ DS
descriptor allocated. This means that, with the hardware
limit of a segment being <= 64K, that a process can at
mosthave two such segments allocated.....
The solution is simple: change MM and Kenrel so, that more
segments can be allocated to a single process (say: 16*CS
and 16*DS), and change the compiler to create binary images
that have been divided over various code and data segments.
Of course, this means that the compiler has to generate
far calls and far jumps when jumping from one code segment
to another (i.e. CALL segment:_somefunc instead of CALL _somefunc)
but.....
2. Programs running in large (actually: huge) model are much
slower than "small model" programs, because almost no extra
pointer arithmetic (ptr = (seg << 16) | ((off & 0xFFF0 << 12) || off & 0xF)))
is needed for every object reference.
I once thought off doing this by doing the MM and kernel stuff described
above, and then cross-compile large-model programs under MS-DOS using
TurboC. I still think it would work, provided one can come up with a
decent a.out format to convert the .EXE to....
Fred.
[stuff deleted]
> 1. The 64+64K limit is not only the fault of the compiler. In MM
> and the kernel a process gets only _one_ CS and _one_ DS
> descriptor allocated. This means that, with the hardware
> limit of a segment being <= 64K, that a process can at
> mosthave two such segments allocated.....
> The solution is simple: change MM and Kenrel so, that more
> segments can be allocated to a single process (say: 16*CS
> and 16*DS), and change the compiler to create binary images
> that have been divided over various code and data segments.
> Of course, this means that the compiler has to generate
> far calls and far jumps when jumping from one code segment
> to another (i.e. CALL segment:_somefunc instead of CALL _somefunc)
> but.....
>
[more stuff deleted]
I have actually been giving this a bit of thought myself, but I don't think
that what you are suggesting will work. Because you need to run in prot. mode
on the 286 to get the potential 16 meg, Turbo C (or any other DOS compiler)
will not work quite the way you might like. Instead of the segment register
being a physical address base, it is an index into a descriptor table. If you
wanted to do as you are suggesting, you would need a table with every (ie. 64k)
worth of descriptors. As far as I can see, the only sane way to allow Minix to
use more than 64 + 64 on a 286 is to set up an extra set of "standard"
descriptors (much like your 16*CS + 16*DS) and have a C compiler that could use
them... The compiler is the hard bit.... At the moment, the compiler and OS in
general is set up to use the CS for code and the DS for data and it would be
_very_ difficult to write a compiler to do otherwise.
Just my $0.02
Pat -- have a day!
[stuff deleted]
them... The compiler is the hard bit.... At the moment, the compiler and OS in
general is set up to use the CS for code and the DS for data and it would be
_very_ difficult to write a compiler to do otherwise.
As far I can see it isn't harder to make compiler which
generates code which doesn't have 64kb+64kb limit. Just use
32bit pointers and far calls instead 16bit pointers and near
calls. The biggest problem would optimizing those references.
A simple optimatization could be following:
1. each object file contains 2 subsegments
(text,data+bss) and both have maximum size 64kb
2. all global functions in module sets DS to modules
own datasegment and uses far returns. Static
functions can use near return, and they don't need
change DS because they are only called by module's
global functions which has already changed DS.
3. All global variables are referenced with 32bit
pointers and static variables with 16 pointers.
Rest of job can leave to linker which resolves all global
references and optimally local references too if small modules
are compined to make one 64kb module (that can cause far calls
even inside one 64kb segment)
When program is executed it it's virtual memory is following
0kb 64kb 128kb 192kb
|text1|unused |text2 | unused |data1| unused |data2| unused
256kb 320kb 384kb 448kb
| empty | empty | stack |
Even though there is unused virtual memory between different
segment it doesn't need to mean that actual memory has such
holes as every segment can be anywhere in physical memory.
The number of segments are limited only by size of LDT (and
GDT if it is used; shared libraries could be there).
When process receive stack fault exception (interrupt 12) the
stack would grow by making stack segment bigger if it weren't
already 64kb or allocating a empty segment between data and
stack segements.
a.out would ofcourse have information about number of segments and
their size.
That kind system shouldn't be too difficult to make but
efficiency is another story.
Any comments?
Petri
--
-----------------------------------------------------------------------
Petri Virkkula | email : Petri.V...@hut.fi
J{mer{ntaival 11 H 168 | pvir...@niksula.hut.fi
02150 Espoo | pvir...@vipunen.hut.fi
FINLAND | Phone : +358 0 455 1277
-----------------------------------------------------------------------
I think you may have missed the point of what my original posting was about.
How exactly do you use 32 bit pointers on a 286????
Ok, You can use only 30 bit pointers or 29 bit pointers; 29
bit pointers when process can only access memory in local
descriptor table.
To access a given memory
location on a 286 (in protected mode of course), you need to specify a 16 bit
descriptor and a 16 bit offset, correct?
No! You need specify 16 bit offset and 16 bit selector which is
just a 13 bit index to local or global descriptor table which
determines where the actual memory resides in 24 bit address
space. That 16 bit selector contains also bit indicating
whether we are indexing local or global descriptor table and
2 bit info about requested privilege level.
If process is restricted to access memory with local
descriptor table size of its virtual memory is 0.5 gigabytes.
Ok, the problem is the fact that you
would need enough descriptors set up to allow access to the entire 24 bit
address space. In my books, that'd make 256 selectors, a small problem to
But you don't have to give to process access to 16Mb of memory.
You can alwayslimit size of local descriptor table to any
number between 1 and 8192, in Minix it is limited to 2.
(Maximum size of descriptor table= 64kb, size of one
descriptor=8 bytes, 64kb/8b = 8192)
begin with, and then you'd need to worry about address comparisons etc. The
only _sane_ way to deal with it would be to convert the address to a "flat"
24 bit address when you wanted to increment/decrement/compare/whatever it,
Programs protected mode have only 30 bit virtual addresses, it
can't access the physical addresses, the prossessor itself
make the conversion using local and global descriptor tables.
So increment/decrement/compare/whatever is safe as long you
don't cross the limit specified in descriptor table.
And We can always limit the size of descriptor table to
eg. to 16 entries which would make 112*<number of process>
bigger; with 32 processes it means 3.5kB, and maximum size for
process would be 16*64kb=1Mb.
and then convert it back into the selector:offset pair afterward. Apart from
duplicating exactly what the processor itself does, this would be a real
performance killer....
You are right, the we would loose some performance, loading
new new segment registers with mov would take 17-19 clock
cycles (in real mode it takes 2-5 clock cycles)
If I've made any glaring errors, please point them out.
The addressing of memory is totally different in real and
protected mode; a good book to read is Intel's
"iAPX286 Programmermer's Reference Manual Including the
iAPX286 Numeric Supplement", ISBN 08359-3054-8,
especially chapter 6: Memory management and virtual
addressing.
Pat -- have a day!
Would someone please explain to me how exactly you use 32 bit pointers on an
80286???? Yes, you could sort of fudge it by making the compiler generate code
to set up a selector every time it needed to access some memory, but this would
be so slow it wouldn't be funny! Really!
Even using a so called "far call" is not really very easy, requiring a selector
to be set up for the code segment being jumped to... I think some people might
be forgetting that the 286 specifies addresses in SELECTOR:OFFSET pairs, rather
that SEGMENT:OFFSET physical addresses. As I stated in a previous posting, the
only way to do "break" the 64k limit on a 286 is to set up 256 selectors,
allowing access to the full 24 bit addressing range. Then, to convert a 24 bit
"flat" address to a SELECTOR:OFFSET pair would mean stuffing the low 16 bits
directly into the OFFSET and the upper 8 into the SELECTOR.
You haven't understood how 286 address the memory in
protected mode. ALL addresses are virtual. A process
can't access a exact location in physical memory unless
it is in privilege level 0 (in Minix kernel is the only
one in that level). And a process DON't have to worry about
where in physical memory a variable is. And there is no need
to make any conversion from selector:offset pair to physical
memory address, the processor makes that for you (usually
you can't do that conversion!).
The processor maps a virtual address to physical address using
logal or global descriptor table. Those tables are build from
eight byte descriptors, the maximum size is 64kb meaning
that there are max 8192 entries in both tables.
The layout of a descriptor is following:
15 8 7 0
---------------------------
+7 | intel reserved | +6
---------------------------
+5 | access byte | base23-16 | +4
---------------------------
+3 | base15-0 | +2
---------------------------
+1 | limit15-0 | +0
---------------------------
base23-16 = bits 23-16 of base address
base15-0 = bits 15-0 of base address
limit15-0 = bits 15-0 of limit
The layout of a selector is following:
15 0
---------------------------
| index |TI|RPL|
---------------------------
index = 13 bits
TI(Table Indicator) = 1 bit
RPL(Requested Privilege Level) = 2 bits
In other words selector is contents of segment register.
When processor sees address 0x12345678 (= (DS contains
0x1234 and process executes instruction mov [0x5678], ax)
it converts that address to physical address following way:
index=582 (decimal)
TI=1
RPL=0
Because TI is 1 it look for 581th entry in local descriptor
table (if it had been 0 it would have used global descriptor
table). Suppose that that entry in table contains
limit=0x6000, base=0x004500. That would mean that contents of
ax would be stored into address base+offset=0x9b78 (0x004500+5678)
in physical memory (it would have checked if the segment is
present (eg. not swapped to disk), if the segment is read-only,
and so on based the access byte in descriptor table).
As one can from above see, a process can access 2*8192*64kb of
virtual memory (means a gigabyte).
If process is is in privilege lvel 0 (in minix kernel is in
that level) it can change contents of descriptor table.
When it needs to access eg. address 0xffffff (16MB -1), it just
sets a descriptor that have eg. base=0xff0000 and loads to
segment register the index of that descriptor and uses offset
0xffff. if it in turn access memory in address 0x000000 in
physical memory, it just changes the base to 0x000000 and uses
offset 0x0000. So there is no need to have 256 descriptors
to access full 16Mb physical memory, you need only one for
that.
If someone has their own wonder way or magic method that allows access to the
full 286 addressing space in protected mode, by all means, let me know what it
is! I'm desparate!
I hope that cleared something (sorry my poor english). As this
don't anymore belong to comp.os.minix send email me if there
is something that you didn't understand. And I recommend again
to buy/borrow Intels book about iAPX286 processor.
Pat -- have a day!
There is a slight confusion in terminology here. I was thinking (incorrectly)
that the offset by itself would be considered the pointer, but I now realise
that the SELECTOR:OFFSET pair make a pointer on the 286.
> To access a given memory location on a 286 (in protected mode of course), you
> need to specify a 16 bit descriptor and a 16 bit offset, correct?
>
>> No! You need specify 16 bit offset and 16 bit selector which is
>> just a 13 bit index to local or global descriptor table which
>> determines where the actual memory resides in 24 bit address
>> space. That 16 bit selector contains also bit indicating
[stuff about protection bits deleted]
Another problem with terminology. I used the word "descriptor" where I should
have used "selector". Physical addresses are calculated by using the selector
as an index into a descriptor table, which gives the descriptor, a 24 bit base
(plus other stuff) that has the offset added to it to form the physical address.
> Ok, the problem is the fact that you would need enough descriptors set up to
> allow access to the entire 24 bit address space. In my books, that'd make
> 256 selectors, a small problem to
>
>> But you don't have to give to process access to 16Mb of memory.
>> You can alwayslimit size of local descriptor table to any
>> number between 1 and 8192, in Minix it is limited to 2.
>> (Maximum size of descriptor table= 64kb, size of one
>> descriptor=8 bytes, 64kb/8b = 8192)
Ok, point taken. But what about when you _need_ to access physical memory? I
have a problem with this in trying to port mini-X to 286 Minix at the moment.
I think the only solution to this is to have a global descriptor pointing to
the start of the screen RAM or for any other areas of physical memory required.
> begin with, and then you'd need to worry about address comparisons etc. The
> only _sane_ way to deal with it would be to convert the address to a "flat"
> 24 bit address when you wanted to increment/decrement/compare/whatever it,
>
>> Programs protected mode have only 30 bit virtual addresses, it
>> can't access the physical addresses, the prossessor itself
>> make the conversion using local and global descriptor tables.
>> So increment/decrement/compare/whatever is safe as long you
>> don't cross the limit specified in descriptor table.
I do understand that the processor uses the selector specified to calculate the
physical address required by way of the descriptor tables. The problem is being
able to access any arbitrary physical address upon demand, such as video RAM or
any other memory mapped I/O devices, which requires a set of selectors for (on
an IBM compatible) at least the first 1 meg of memory.
Because the maximum size of a segment remains 64k, it is necessary to resort to
quite a deal of acrobatics to manipulate objects that fall outside this limit.
For example, if a block of dynamic memory larger than 64k is required (from
malloc() or whatever), it is impossible to return a pointer to the new block,
as it in effect needs more than one pointer. This is where my thoughts of the
conversion to flat addresses came in, if the malloc() function is written to
return a "flat" 24 bit physical address, and we have a standard method of
converting this to and from the SELECTOR:OFFSET form, it becomes possible to
handle chunks bigger than 64k. Unfortunately, this introduces a big performance
problem...
[stuff about performance deleted]
I have come to realise that my original posting did not adequately explain my
thoughts. Two major points that I did not describe well were the assumption
that access to arbitrary physical memory locations would be required, and that
it is blocks of memory _larger_ than 64k that I am interested in. The first of
these points prevented me from thinking about the virtual memory system on the
286 the way Intel had obviously intended.
I still believe that the only sensible way to access blocks of memory larger
than 64k on the 286 is to convert addresses into a 24 bit "flat" form whenever
pointer arithmetic is needed.