From: lasner@watsun.cc.columbia.edu (Charles Lasner)
Subject: Re: The need for an assembler (was: Favori
Reply-To: lasner@watsun.cc.columbia.edu (Charles Lasner)
Organization: Columbia University
Date: Fri, 14 Aug 1992 07:41:41 GMT

In article <1992Aug12.171241.14907@sctc.com> smith@sctc.com (Rick Smith) writes:
>
>>There is an issue being overlooked here: assembler programmers do *not*
>>"optimize" their code, they write it correctly the first time. It doesn't
>>take too much experience with an architecture to know what's good and what's
>>not.  It quickly becomes "second nature" to anticipate a goodly number of
>>conditions in the course of creating the code such that the final product is
>>what *ought* to run well on the architecture. 
>
>I have several problems with this statement.
>
>First, the generalization about "assembly language programmers" is
>overly broad. It is not consistent with my own experiences with
>assembly language programming and programmers. A new chunk of code
>might mostly work the first time, but it can always be made better. As
>a project grows, so does my understanding of it, so I find ways to
>redo various parts more effectively.  Overall, I've noticed that my
>code tends tends to grow in the early stages of implementation and
>then shrink in later stages as I optimize and just tighten things up
>in general. I've talked to lots of other competent programmers who've
>noticed a similar pattern in their own work. I see it in my HLL work
>as well. Perhaps this "optimization" is at a higher level than what
>the author is addressing, but I've done low level optimizations later,
>too.

I agree that this shouldn't be generalized, so let's change it to:
*good* assembly programmers do not optimize their code, they write it correctly
the first time.  Don't you know anything about learning curves?  It really
doesn't take all that extra skill to know when to use what after you are
beyond the "tinkering" stages of learning an architecture, or is it just that
you never heard of anyone who was "good enough".  I am not claiming I am
at the top of this category by any reckoning, but I think that a fair amount
of the code I have written over the last 24 years wouldn't ever be optimized
by me or anyone else at any point because it truly is the best way to deal
with the specifics at hand.

I will also freely admit that projects parameters will "drift" for various
reasons, and that the highly optimized code will be excised and wasted, 
although in actuality this is a "cookbook" problem where the recipe changes, 
not the master list of ingredients.  If I maintain a personal macro library
of the 100 most likely ways a certain fragment of code may have to be called
when applied to an application, it's not likely that there is going to be
a type 101.  There is always a point of diminishing returns.  Once the
list grows to its ultimate length, the code will indeed be written optimally
the first time.  And if changed in the course of the project, it will
be rewritten anew optimally this new occurrence of a "first time".  Contrary
to the notions of people questioning this, all architectures are capable of
being understood at a symbolic level that is not only at a one-one
correspondance level with the hardware, but sufficiently that there won't
be any "tricks" left to apply.  Moreover, the only "new" source of ideas or
algorithms today is generally overall mathematical methods for accomplishing
complex tasks.  The elements of these still break down into applying the
correct "recipe" for the major components.  This doesn't change the basic
method of writing the correct code for the job the first time.  Furthermore,
assembler programmers are virtually the only source of all of the "tricks"
added to compilers.  Compilers are therefore a useful source of an
assembly programmers bag of tricks taken from other assembler programmers'
work.  So, any assembler programmer worth his salt is "up" on just what
makes a particular architecture "tick" to that fine a degree.

Much has been made of a notion that essentially says "by the time you know
enough, the machine is obsolete and you have to start all over again".  Well,
there is some truth to the fact that you have to start over again, but I can't
say that the word "all" applies.  Most assembler programmers eventually get to
be quite adept at comparing architectures for good and bad fine points, etc.
Perhaps this is because all machines are all alike in many ways, differing
only in a sort-of "cookbook" way?  Of course it is!  So, maybe it's something
like "by the time you have been productively cranking out lotsa quite good
quality code someone will bring out a new machine and you'll have to study
yet another architecture to get up to speed on it."  Admittedly some will
take longer than others, and without a serious committment to the machine,
it would be a worthless investment of time.  But look at the "lifetime" of
machines in this business.  There really haven't been too many total turnovers
over the years.  How many decades are we going to have MAC and 68K-based unix
people essentially whining "we better not learn how to use 68000 family
assembler in any serious way, because any time now it's going to be so obsolete
that no one can ever make use of it anymore in any way".  DEC is saying that
the Alpha chip is going to take them well into the next century.  I guess that
means we shouldn't learn it either to any extent because DEC might retract
that statement any time now, right?

>
>Perhaps I misunderstood the author, but that first sentence almost
>sounds like it's saying "My code is always perfect the first time I
>write it." This is most often true when the software performs a
>trivial or mundane task. It is seldom true for software addressing
>harder problems.

No, I am saying that with reasonable experience, most of my code is, to
paraphrase StarTrek, "where I have gone many times before".  Harder problems
just means writing more code, not writing more difficult code.  High-level
organization of any problem in any language is a universal problem and is
perhaps what you are referring to.

This part is admittedly a personal response, and I don't claim to know if it
applies to anyone else, although I sincerely hope it does.  As I get "long in
the tooth" I find that my rate of output is slowing down (not a lot, but it's
noticeable, and I guess inevitable for all of us), but that the bug rate is
lower.  This partially offsets the slow-down, and thus productivity is better
than might be predicted.  Discipline is clearly at a peak, and I can better
"tune out" the outside world for longer times.  Further, the work itself
seems more satisfying than ever.  Part of this is related to a better
development environment (I started with just a computer and a 110 baud
teletype and nothing else :-( :-( :-( and have gravitated into more or less
the same direction as most of us, which is several orders of magnitude better.)

I am also commenting my code both better and more so.  The "worth" of the
comments is clearly much better than years ago.  When working on larger
projects it is invaluable; the size of some things written in recent years
is so large that no one can claim to remember details of the work done
even a few weeks earlier.  Try reading the code of a large project in any
language and see what you remember of the early part when you read it a
second time after reaching the end of the source code listing(s).

(Maybe all of this has to do with peaking of sex drive :-).)

>
>Another common example of trivially "correct" software is when the
>software is written by a single programmer for a very small customer
>community. The author can then simply assert the program is correct
>and that any flaws are in the customer's peception of what the program
>does.

I think I'll let the hll people have exclusive rights to the "it's not a
bug, it's a feature" statements.  Disciplined programmers don't do that; a
determined assembler programmer is *very* disciplined.

>
>As far as "second nature" and experience with the instruction set,
>this only helps with optimizing instruction sequences, and not with
>the overall organization and structure of a large program. Machines
>that support large programs have pretty similar instruction sets these
>days; the differences aren't going to constrain your top level program
>design in any important way. The address map garbage on the Intel
>chips might be a good counterexample, but there are lots of ways to
>structure a program to efficiently ignore such a constraint.

I totally agree; the overall organization of a program is all.  This is a
language-independent idea.

Instruction sets *are* that similar, that's why I take the position against the
obsolescence notions.

cjl