Re: Using tasm
From: Beth (BethStone21_at_hotmail.NOSPICEDHAM.com)
Date: 03/14/04
- Next message: Ben Measures: "Re: LOL"
- Previous message: Frank Kotler: "Re: "[" , "]" and nasm"
- In reply to: PlasmaDragon: "Re: Using tasm"
- Next in thread: R.Wieser: "Re: Using tasm"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Sun, 14 Mar 2004 13:46:32 +0000 (UTC)
PlasmaDragon wrote:
> I couldn't find tlink, but I could find something called ilink32 in
> the same directory. I thought "close enough" and tried to use it to
> link the obj file, but then I got a message saying "Fatal:
unsupported
> 16-bit segment(s) in module x.asm". So I think the problem is that
> tasm32 is making 16-bit code. How do I force it to make 32-bit
code?
> Thanks in advance.
Ah, "ILINK" is Borland's "incremental linker"...Borland improved their
linker to be able to work "incrementally" and called this
"ILINK32"...this is what they tend to throw into their HLL packages
like C++ Builder and so forth...as the "32" in the name suggests (like
it does with "TLINK" and "TLINK32" ;), this is a 32-bit linker
designed for 32-bit Windows code...I personally have never seen a
"ILINK" (non-"32" version ;) so I don't know if Borland ever made
one..."ILINK" is the "improved" version of "TLINK" so maybe, at this
point, Borland have simply decided on a "DOS is dead!" policy and
can't be bothered to support 16-bit code anymore with this "ILINK"
stuff...
Anyway, I spot a "misconception" in what you've written so allow me to
try to clarify; TASM32 has produced _THE CODE YOU ASKED IT TO
PRODUCE_...this code happens to be 16-bit code that _you_ have fed
into TASM32...hence, when you ask "How do I force it to make 32-bit
code?", the unhelpful answer is: "write 32-bit Windows code rather
than 16-bit DOS code instead!"...of course, you want to assemble this
particular example so that's NOT a particularly helpful remark...but
it is the truth of the matter...
You're NOT using HLLs anymore! That is to say, the output that the
assembler produces _IS EXACTLY WHAT YOU WRITE_...all an assembler does
is convert those "mnemonics" (e.g. "MOV", "ADD", "INC", "EAX", "[ ESP
+ 8 ]", etc. :) into _machine code_ (often mislabelled as "binary" but
we won't go into that pedantic "the number system is irrelevent"
theoretical nonsense here and calling it "binary" is okay because,
yeah, it does come out and get stored as BInary digiTS - bits - in
practice ;)...
Hence, the code you're passing to TASM32 is _16-bit_ code...the
instructions operate under the presumption that they are running with
_DOS_...that is, in the CPU's 16-bit "real mode" (which has a
_completely different_ addressing scheme to the CPU's 32-bit
"protected mode"...hence, _why_ "16-bit" and "32-bit" are
_INCOMPATIBLE_ in this - and other - instances...Intel made a terrible
design mistake with their 16-bit chips and, to fix it, they introduced
two "modes" for the CPU...one with the "real mode" addressing scheme -
which is a nightmare and a total mess - and the "protected mode"
addressing scheme, which is elegant, beautiful and simple..basically,
the design Intel should have _gone with in the first place_!!
Unfortunately, the "addressing" used in both "modes" is completely
incompatible (well, not without major limitations and
restrictions...plus a few impossibilities...so, in fact, your CPU has
_three_ "modes" with a third "V86" mode used to provide the "half and
half" in-between mode to help "compatibility" between the two...this
is what Windows uses for its "DOS box" to allow 16-bit DOS programs to
run under 32-bit Windows because it would otherwise be totally
incompatible due to the "addressing scheme" problems :)...so, you have
to treat them differently...
Okay, this might sound confusing...so, let's take a different angle
and put it all into context...jump into my Delorean, we'll speed up to
88mph and travel back into the past...the 1970s, to be exact...
There we find Intel engineers putting together the first 8086 chip
designs and meet the "terrible mistake" of computing history that,
yup, goes so far as being mostly responsible for Microsoft "owning"
the universe...it works like this: When you want to refer to something
in memory, you need a way to tell one piece of memory apart from all
the other pieces...that is, I have, say, 64KB of RAM installed
(remember, it's the '70s in this example, so 64KB was actually a _lot_
of RAM to have ;)...and I want to get _one_ particular value - just a
single byte - out of that memory...well, how do I tell one byte from
another so that I can instruct the CPU to pull out the right byte, out
of all 65,536 bytes available in my 64KB RAM?
The answer is by using an "address"...which is not a particularly
complex idea...just like you number each house in a street so that you
can send a letter to a particular house by specifying the house number
on the envelope, we can also simply treat RAM as one really long
"street" and each byte is like a house and we give it a "house
number"...the easiest scheme - which is what is used - is simply to
number the first byte as zero, the next one as one, the next one as
two, etc....then every byte in memory has its own "house number" and
we can refer to any particular byte by its "address", just like you
can do the same with _house_ "addresses" on the front of envelopes...
All good so far until we consider that the 8086 was a 16-bit
machine...its registers - which held these "addresses" - were only
16-bits in size...our problem is that if we're numbering each byte in
memory from zero upwards, then the biggest number we can hold in
16-bits is 2^16 (that's "two to the power sixteen"..."^" is used
because ASCII doesn't support the usual maths notation of small
superscript "indexes" next to numbers :)...and that is 65,536
different addresses...or, oh dear, only 64KB of memory that 16-bits is
able to "address"...
What are we going to do when we install more than 64KB of RAM? And
this was the challenge facing those Intel engineers...now, clearly, if
16-bits isn't big enough then just use more than 16-bits...that's the
simple solution...but _how_ do we do this exactly? And this is where
Intel made their really bad design mistake that has haunted everything
ever since...now, one obvious idea is to say "let's use _two_ 16-bit
registers and put them side-by-side to get one long 32-bit number and
use this as the address"...this was the approach rival Motorola
thought of and it's good up to 4GB of addresses (2^32 = 4GB :)...
But, for reasons unknown to any rational mind, Intel's engineers
thought something like: "oh, 4GBs of RAM is far too big! 640KB is more
than enough for anyone! There's no sense making things that
big!"...so, they invented one of the most absurd addressing schemes
you'll ever see...the idea was to have two 16-bit registers - this is
good - but rather than simply "put them side-by-side" and have a long
32-bit address (good up to 4GB of RAM), they crippled the entire thing
with some strange "addition" idea...
The "upper" 16-bit register was called the "segment" and the "lower"
16-bit register was called the "offset"...but rather than treat these
two as one long 32-bit address (and then just _ignore_ all those
higher addresses that are far beyond the amount of RAM you've
installed...the sensible Motorola approach, which, eventually, Intel
realised was the more sensible approach and is how the CPU finally
operates with "protected mode" on the modern x86 chips :), the
"address" is composed as follows:
Address = (segment * 16) + offset
....which is a total mad scheme and is the "nightmare" which Intel
unleashed on the world...note that a particular byte in memory can be
referenced _in more than one way_(!!)...the segment:offset of
0040:0000h, for example, is the same as 0000:0400h or 0030:0100h and
hundreds of other different addresses which actually refers to exactly
the same byte in memory (note, "addresses" are traditionally always
written in _hexadecimal_ which is what the little "h" after the
address reminds us :)...also, because of the "overlap" they
introduced, the scheme has a much lower "upper limit" of only just
over a 1MB of RAM...
Clearly, Intel's engineers were thinking something like: "oh, this
chip won't last more than a few years or so...so, we don't need to
make it 'future compatible'...1MB of RAM is far distant from being
'normal' in the 1970s here and by the time 1MB of RAM becomes normal,
then this unimportant 8086 chip will be long dead and everyone will be
using better Intel chips" when they came up with this madness...
Unfortunately, that was as terrible a "misprediction" as: "There will
only be a need for 5 or 6 computers world-wide" and "640KB is enough
for anyone!" (Bill Gates there ;)...it's now coming up towards its
_thirtieth birthday_ and the x86 architecture still looks completely
untouchable...yes, in all that time, there's been a constant
prediction about how something else - with a _better_ design...say,
64-bits or whatever - will take over and consign the x86 to the
rubbish...but, hey, even today, when there's talk of 64-bits, AMD
suggest "oh, just make the registers 64-bits big and carry on!"...and
though Intel want to finally break away, it's probably a _safer_
prediction to go with "yes, they'll carry on flogging the dead horse
for another decade or so - at least - rather than for the undead
zombie to be finally allowed to rest in peace!"...even if Intel do get
their way and AMD's "let's just resurrect the zombie one more time!"
approach eventually loses, it still took _30 YEARS_(!!) for it to
happen...hardly the "fast pace of progress" that the media constantly
likes to dupe the Great Unwashed into believing...no, trust me, things
have dragged along at snail's pace thanks to Intel and Microsoft...it
_should_ have gone far, far faster than this...because we never got to
see the things we were _cheated_ out of, it's easy to fall for this
idea that everything's going "fast" and we've got the "best"
technology on our desktops...sorry to be the one to reveal the lie but
that's the truth of the matter: A 30 year old "scam" of accidents,
bluffs and mistakes (as I mention in another thread around here, the
'386 brought all the "32-bit protected mode" stuff that Windows 95
sold itself on in _1985_...it took Microsoft a _decade_ to get their
software to only _begin_ to use the hardware facilities of that
chip...and, even then, Win95 was full of 16-bit code so, really, only
with _XP_ - around 17 years after it was made possible by the hardware
manufacturers did Microsoft finally get their software up to
scratch...yes, _almost two decades_ too late...if you've seen people
moan about Microsoft and never quite understood why, then realise that
this _absurd_ situation is, in fact, _only the tip of the iceberg_ of
what Microsoft have done...and this in itself - being nearly two
decades too late - should be enough to explain the upset but that
isn't the full story either...their "de-commoditisation" policy is
another thing that can single-handedly condemn Microsoft that when
people portray Sir Bill as a devil, you can kind of sympathise with
that particular perspective on the matter...you do have to think to
youself as to whether this was actually _delibrate_ or not, when
things are literally held back _decades_ and made so "backward"...the
_ONLY_ saving grace has been those great hardware manufacturers who,
indeed, made Windows 95 a possibility in 1985, even if Microsoft
couldn't actually be bothered to code it for another decade or
two...those guys have speeded up the machines to absurd levels that
the _raw CPU clock speed_ on PCs is basically the _only_ reason that
things get better - rather than, yes, _worse_ because software _is_
being written in an increasingly _worse_ way all the time - and that
you can actually, you know, _do something useful_ with your PC...you
know, there's more computing power in your desktop than a network of
supercomputers of a few decades back, used to do some pretty
hair-raising number-crunching things even then...they got to the Moon
with 32KB of RAM! If you could really _see_ what your hardware is
capable of, then it would not be a cream pie you'd offer to be thrown
into Sir Bill's face...a more fitting substance would be to throw the
_bullcrap_ he's been throwing at us back into his face!!! ;)...
Nevertheless, this is what happened and DOS - running in this 16-bit
"real mode" - uses this horrible "addressing scheme"...Intel "fixed"
this - while also introducing things like an on-chip MMU (Memory
manager unit :) and "protections" - with their '386 "32-bit protected
mode", which is what Windows and Linux and so forth now use...but DOS
pre-dates this and uses the older, horrible scheme...
Hence, that's kind of what this whole "16-bit" and "32-bit" thing
boils down to...the actual instructions in 16-bit and 32-bit are, in
fact, _compatible_ (you can use 32-bit instructions in "16-bit" real
mode and 16-bit stuff in "32-bit" protected mode :)...BUT what is
completely different is the _operating environment_..."16-bit code"
for things like DOS use the older, horrible addressing scheme and this
is _NOTHING_ alike the way things work under 32-bit "layered
architecture" Windows and Linux...
Because of this incompatibility, you have to treat "16-bit" and
"32-bit" differently...as Rudy noted and I posted to update, Borland,
in fact, only finally combined an assembler able to generate both
16-bit and 32-bit code - stuffed into "TASM32" rather separate 16-bit
"TASM" and 32-bit "TASM32" - fairly recently (relatively
speaking)...but the actual linker still remains separate and, worse,
Borland made "TLINK32" into "ILINK32" to "improve" it by using
"incremental linking" ("incremental" just means "relative",
basically...it deals only with the _changes_ since the last time
rather than beginning again from scratch every single
time..."incremental" stuff works "relative" to the last linking, the
non-incremental stuff just links from scratch in an "absolute" way
every time :)...and I think this also signals that they simply can't
be bothered supporting 16-bit DOS code anymore with their "ILINK32"
linker...not a completely surprising prospect because Borland have
also given up on developing TASM itself as a separate product because,
well, there's just no money in assembly language for them to get rich
off catering to ("supply and demand", yeah? ;)...
And that code example you want to assemble is inherently designed to
run under DOS in the 16-bit "real mode" addressing scheme and makes
use specifically of DOS OS services (so you kind of need DOS to be
running in order to provide those services the program is expecting to
be available ;)...in short, you've got _DOS_ code there...but
"ILINK32" is a _Windows_ linker...and, due to Intel's previous
insanity in the '70s, this stuff is _thoroughly incompatible_,
unfortunately...
Now, in this case, I'm presuming it makes more sense for you, though,
to try to find an old 16-bit "TLINK" linker somewhere, so that you can
get your 16-bit code linked to a 16-bit DOS EXE rather than it is to
re-write the code in 32-bits (trust me, things work so completely
differently under something like Linux or Windows that many DOS
programs _don't even make any logical sense_ under these OSes, let
alone for things to be at all easy to "port"...it's best to look at
these two things - due to the vast incompatibilities - as being almost
like "two completely different machines"...a "DOS PC" and a "Windows
PC" or whatever...Windows' "DOS emulation" is NO TRIVIAL PROGRAM, in
fact...smoothing over the differences and incompatibilities means that
the "DOS box" emulation stuff is, in fact, really an _entire OS in
itself_, so to speak...part real-mode, part V86 mode, part protected
mode...lots of shuffling back and forth between "modes", translating,
redirecting and so on...actually, in some respects, the "DOS box"
alone is _more complicated_ than Windows itself is...Windows is just
"big" (and badly designed and coded) and that's why it's
"complicated"...the "DOS box" thing, though, really is a nightmare to
understand, let alone code...so, seeing DOS code running happily under
Windows might give the impression that everything's "compatible"...but
it isn't at all, really...Microsoft did an awful lot of work and sweat
gallons getting that to work to enable "smooth transition" from DOS to
Windows...after all, it was _crucial_ to Microsoft's "world
domination" plans that everyone was happy to "switch" with a "seamless
transition"...that's, I reckon, the only reason Microsoft took on such
an insanity and worked so hard on it, that this part is actually one
of the more impressive bits of Microsoft coding for Windows..."dosemu"
on Linux - trying to do much the same thing - has certainly had a lot
of work on it and isn't up to the "DOS box"...of course, Microsoft
have the advantage seeing as they also wrote DOS but you get the
picture...because this bit was important to Microsoft riches, they
_actually_ put in an honest day's work on the "DOS box" to make sure
it would work really well for that initial "DOS -> Windows" transition
that they needed from their customers ;)...
Anyway, you need 16-bit "TLINK" for this...or, alternatively, there
are some other linkers capable of doing the job out there too, if they
are able to deal with 16-bit so-called "OMF" format object files
(note: MS's MASM and LINK used to use OMF a while back but now use
COFF format, meaning that these aren't appropriate)...
Beth :)
- Next message: Ben Measures: "Re: LOL"
- Previous message: Frank Kotler: "Re: "[" , "]" and nasm"
- In reply to: PlasmaDragon: "Re: Using tasm"
- Next in thread: R.Wieser: "Re: Using tasm"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]