From: lasner@watsun.cc.columbia.edu (Charles Lasner)
Newsgroups: alt.folklore.computers,comp.unix.misc
Subject: Re: The need for an assembler (was: Favorite CPU)
Date: 5 Sep 92 12:28:50 GMT
Reply-To: lasner@watsun.cc.columbia.edu (Charles Lasner)
Organization: Columbia University

In article <9224903.16502@mulga.cs.mu.OZ.AU> fjh@mundil.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
>lasner@watsun.cc.columbia.edu (Charles Lasner) writes:
>
>>In article <9224507.14644@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
>>>lasner@watsun.cc.columbia.edu (Charles Lasner) writes:
>>>
>>>>In article <1992Aug28.222616.2251@merlin.dev.cdx.mot.com> lezz@merlin.dev.cdx.mot.com (Lezz Giles) writes:
>>>>>
>>>>>Once again, I don't want to say that assembler is a Bad Thing.  Also
>>>>>notice that I'm not saying anything about ease of programming, speed,
>>>>>or anything else.  I'm just saying that if you program in assembler for
>>>>>an 80386 then your program will run well on an 80386, sub-optimally on
>>>>>an 80486 and not at all on an 80286 (and forget about a 68030).  If you
>>>>
>>>>This is patently wrong.
>>>
>>>No, it's quite correct.
>>
>>Again, the statement stands.  There isn't enough functionality improvement
>>among the models to care about; you seem to have grabbed onto a notion and
>>won't let go of it.  There are a handful of situations, like N-bit rotates
>>which are helpful, but I could put a conditional on them if I really cared.
>>I would generally rather go with compatibility.  Nitpicking percentage
>>differences in efficiency will occur except in contrived conditions.
>
>OK, you are not disagreeing that the code will be sub-optimal, you are just
>arguing about whether the difference is worth caring about.
>So why then did you say that the original statement was "patently wrong"?

Simply because I don't equate sweeping statements about sub-optimality with
nit-picking.  Further, the kind of nitpicking in question is far less than
the issues of why to use assembler over hll for overall speed improvement.
Moreover, much of the "performance gap" can be achieved merely using macroes
that expand to work either way.  On these machines, there is little if any
difference between the best totally-handcoded assembly with conditionals to
create either of two alternatives, and code created by a macro to generally
handle the same conditions.  The rotate extension comes to mind: you can
create a macro to take a count and stick it in the CX register and to a 
CX-driven rotate, or you can use the 286-up extension instruction that takes
a count.  The macro can optimize out the case of 1 rotate to use the form
always available.  The only argument is whether the former CX register is
required to be saved, and if so, where/how and as to its being restored, etc.
In general, the proper code would just load over it, but perhaps there ought
to be a macro option or variant that saves/restores it as well since '286-up
style could demand CX be used for other purposes.

So, it's all a matter of how "fastidious" you want to be and whether you need
to deal with the problem on a totally mindless basis, a partial scrutiny basis
or just ignore it.  At best, most of these optimizations have no net effect
for the bulk of the applications.  The ability to even calibrate their effect
may be below the point of measurability, one factor in which is the instability
in the DMA refresh clock which takes forced DMA cycles for the memories' sake.
Thus, .02% improvement can't even be accurately measured when .1% timing
error potentially exists.

>
>You even say later:
>>The so-called sub-optimality is a nit below optimality.
>
>As far as I can see, you have admitted that it was true, but are arguing
>that the efficiency differences are not relevant. Hardly sounds like
>"patently wrong" to me.

Nits are nits.

>
>>>>I write for the 8086/8088 model as do most people.
>>>>It runs on 8088, 8086, 80186, 80188, 80286, 80386SX, 80386DX, 80486SX,
>>>>80486DX, 80486DX2, and about 20 non-Intel clones from AMD, NEC, ULSI, TI,
>>>>and a few other cpu clone maker's cpu's.
>>>
>>>Yes, but your code will be sub-optimal for all but the 8086/8088.
>>>And as Lezz Giles pointed out, you can forget about the 68030.
>>>(and of course, your code won't work for a Z/80 ;-)
>>
>>Gee whiz, mea culpa! my 80x86 code can't run on z 68030 or Z-80.  Well, your
>>C-generated MAC II binary won't run on my '486 :-).
>
>So just recompile it!
>Better yet, distribute your code in source form.
>Another alternative is to use interpreted languages (like perl),
>or to compile to a byte-code which is then interpreted.
>(An application that I have worked on used the latter method to
>achieve seamless, virtually effortless portability to over 700 different
>systems.)

I was one of those suggesting that if hll's should be invented, they should
be interpreters calling excellently-coded assembly routines, because that
way you could run code that you couldn't express in the hll, but could call
in a closed way, although the language wouldn't just abstract what's going on
in a relatively simple way as we have now, but could be virtually totally
insulated from it.  This is part of the argument of posters pointing out that
hll's discussed here aren't high-level enough.

>
>>>>I can choose to exclude the 8088
>>>>and 8086 with a simple assembler directive, which merely enables extensions
>>>>available in the '286 and up, or I can us the larger models and write for
>>>>protect-mode on either 286 and up or 386 and up as I choose.  There is
>>>>hardly any difference between 386 and 486 save speed and a few instructions
>>>>(very few) that were added to the '486.  There is virtually no software
>>>>significence to the 486 over the 386, and for all indications, as posted on
>>>>this newsgroup, the '586 won't change this either.
>>>
>>>It's not just a matter of "a simple assembler directive" - to take full
>>>advantage of a better chip may require rewriting much of your code.
>>>Assembly language programmers must choose between 8086, 80286, 80386,
>>>and i486 at the time of writing, whereas HLL programmers choose at
>>>compilation time. This can be a significant advantage.
>>>For HLLs, it *is* just a matter of a simple compiler option.
>>
>>Pure crap. That's not what the assembler directives do.
>
>Huh? I didn't say anything about what the assembler directives do,
>it was what they *don't* do that I was pointing out.
>I don't even understand what it is that you're disagreeing with here.
>
>>... All this proves is that upward compatibility works.  The
>>features gained don't dictate rewrites, rather just additional opportunity
>>for alternate implementations that won't apply in this class of problem.
>>... As long as my programs are shorter than that [16M], there isn't an
>>avenue of improvement available.)
>
>There *is* a possibly small but definitely non-zero performance increase
>to be had from using the instructions that are not available for the 8086.
>If you are writing in assembler, taking advantage of this would mean going
>through your entire source code and modifying many parts of your program -
>a tedious and hence error-prone task. On the other hand, if you are using
>a HLL, taking advantage of the additional instructions, larger or more
>numerous registers, etc. etc., offered by a new processor is just a matter
>of a simple compiler option.

Wrong, that presumes an awful lot.  In most cases, using the instructions 
for '286 mode means they run slower, and certain forms of address calculation
to load segment registers, etc. isn't available, thus certain forms of
known hand-optimization have to be avoided.  Mentally, this isn't really a
problem because the majority of assembler programmers don't use these 
techniques except for quirky "advanced" optimization if ever.

But the main issue is that your compiler example will merely cause the
generation of protect-mode code, which will likely run slower in the
environments where either (protect or real) is acceptable, such as OS/2.
If you choose enhanced '386 protect mode (which apparently is the only
mode that gcc can generate for) it will run even slower, although would
be allowed to have code greater than 16 Mbytes.  I doubt that for any
practical project, the "restriction" to "only" 16 Mbytes of program space
should be cause for alarm, so I'll restrict myself to only the two relevant
cases.  (Also, '286 protect mode is always supported where '386 protect mode
is normal.  Applications aren't recompiled lest they get slowed down, not
speeded up!)

cjl