[comp.sys.apple2] HLLs vs. Assembly

jpenne@ee.ualberta.ca (Jerry Penner) (03/30/91)

In article <13156@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
>Gee, Todd don't get so defensive! (:-))

[ stuff about timing critical code and the plethora of Mac/PC SW nuked ]

>One thing really amazes me: people's insistence on writing Operating Systems
>in HLLs like C.  It is actually *easier* to write most of the OS in assembly
>than it is to write it in C.  It's just that modern day OS writers are
>incompetent assembly language programmers so they force C to do the job for
>them.

They might be incompetent assembly language programmers but there is a
bigger reason why OS writers do not want to use assembly language.
Portability.  It makes a lot more economic sense to write in a more
portable language than in assembly.  I think this is the most
important reason OS writers use C.  I agree that using assembly is
probably easier to write an OS in, because you don't have to fight the
HLLs tendencies to constrict you into doing something in a certain
way.  I disagree that most OS designers/writers are incompetent
assembly programmers.  They also probably have orders from mgmt to use C
or some other HLL (like Modula 2 or 3).

[ stuff about OS course deleted ]

-- 
-------------
    Jerry Penner	alberta!bode!jpenne	Edmonton, Alberta, Canada
		 -- Go ahead, make my nanosecond! --

gwyn@smoke.brl.mil (Doug Gwyn) (03/30/91)

In article <1991Mar30.080418.16299@ee.ualberta.ca> jpenne@ee.ualberta.ca (Jerry Penner) writes:
>Portability.  It makes a lot more economic sense to write in a more
>portable language than in assembly.  I think this is the most
>important reason OS writers use C.

I think that's an argument for UNIX, but not in general.  Texas
Instruments, for example, wrote at least some of their OSes in
an extended version of Pascal; Burroughs wrote theirs in ESPOL,
which resembled Extended Algol; and DEC wrote VAX/VMS mainly in
Bliss, which is very analogous to C although different in detail.
In all these cases (UNIX also), an important consideration was
that it is simply easier to do a good job using a structured
high-level language.  The fact that there was negligible impact
on performance was of course crucial.

>I agree that using assembly is probably easier to write an OS in,
>because you don't have to fight the HLLs tendencies to constrict
>you into doing something in a certain way.

C was specifically designed to allow a high degree of exploitation
of the system architecture from within a structured high-level
language.  There are a few things that normally HAVE to be done in
assembly language, such as the glue between trap vectors and the C
code that processes the interrupts, but these are relatively few
and easily isolated.

rhyde@gibson.ucr.edu (randy hyde) (04/02/91)

If I was a hardware manufacturer writing an OS for an Apple II gs, the last
thing I'd worry about is portability.  Performance of my hardware is a much
greater concern.  That's why Apple has written their OSes in assembly in the
past.  Hopefully they will not succumb to the HLL trait.
It's always amazing to me how much more money people are willing to spend on
faster CPUs (8088->80286->80386->80486) but they're unwilling to spend more
money on software to develop it in assembly rather than C.  I'm not talking
about one-of-a-kind programs here, I'm talking about high volume applications
like word processors, spreadsheets, and the like.  Guess the programmers never
really have to *use* the software they write.
OSes are the backbone of a machine.  Furthermore, they are *pure overhead*.
A high performance one will not speed up applications programs.  A low
performance
one, however, can cripple applications.  When I'm sitting at a machine running
applications I could care less how portable the OS is.  I want it to be fast!

gwyn@smoke.brl.mil (Doug Gwyn) (04/03/91)

In article <13202@ucrmath.ucr.edu> rhyde@gibson.ucr.edu (randy hyde) writes:
>OSes are the backbone of a machine.  Furthermore, they are *pure overhead*.

Not so -- operating systems almost always provide support services,
such as I/O management, for applications.  If the OS didn't do it,
the application would have to.  There is great value in having a
single consistent implementation of such services, even if task
scheduling were not needed.  Even MS-DOS systems have a "BIOS" that
is designed to provide basic I/O services, not overhead.

We have graphical performance monitors for a lot of our UNIX systems;
these show what percentage of processor time is spent in various "modes".
For example, "user" mode is pure processing without OS involvement,
while "system" time is spent in the kernel, either on behalf of
applications or in genuine overhead, and "idle" mode is time when the
processor is not needed for anything.  We find that a lightly-loaded
system spends typically less than 1% of its processing in the kernel
(due to always having a bunch of daemons handling network traffic,
etc., not to mention having to run at least the monitoring process,
it cannot be precisely 0%, which is the theoretical ideal).  With
numerous time-sharing tasks heavily competing for system resources,
we nevertheless often attain "user" mode utilization over 90%, and on
our multithreaded applications we have been able to attain around 99%
"user" mode processing when the application is crunching numbers and
not doing I/O concurrently.

Thus, system overhead, at least on our UNIX systems, is close to
negligible, even if one doesn't allow for the convenience of having
the I/O, IPC etc. services that the OS provides.  And the vast
majority of the code executed by the UNIX kernel is written in C.
Efficiency arguments about C versus assembler for the bulk of an OS
kernel are thus spurious.

kadickey@phoenix.Princeton.EDU (Kent Andrew Dickey) (04/03/91)

In article <15682@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
    [Lots deleted...]   
>With
>numerous time-sharing tasks heavily competing for system resources,
>we nevertheless often attain "user" mode utilization over 90%, and on
>our multithreaded applications we have been able to attain around 99%
>"user" mode processing when the application is crunching numbers and
>not doing I/O concurrently.
>
>Thus, system overhead, at least on our UNIX systems, is close to
>negligible, even if one doesn't allow for the convenience of having
>the I/O, IPC etc. services that the OS provides.  And the vast
>majority of the code executed by the UNIX kernel is written in C.
>Efficiency arguments about C versus assembler for the bulk of an OS
>kernel are thus spurious.

Doug misses an important point here in what those numbers mean.  Unix uses
timer interrupts to determine when to switch from one process to the next
(so one doesn't monopolize the CPU time).  After a program has been running
for more than N clock ticks, that process is preempted and moved to the back
of the queue (all of this is basically right, but there are a lot more
subtleties to it all).

Those numbers that Doug is quoting are calculated simply--when a timer
interrupt occurs, the system merely figures out what state the machine was
in when the interrupt came (either system or user) and increments a counter.
However, there are times when interrupts are not enabled!  Thus, the
interrupt cannot occur at those times, and so the numbers calculated are not
exactly right.  In fact, during a context switch, these interrupts will not
occur, so those numbers do not include times the system is taking to switch
among processes (on most systems).  Those numbers are really only meaningful
in finding out whether the computer is spending a lot of time in the kernel
calls (like read(2), write(2), pipe(2), etc.) and not in simple OS overhead.
Granted, Doug's system may do the numbers absolutely correct (I don't know
what he's running), but I wouldn't bank a lot on the validity of the numbers
he's quoting.

Unix has an incredible amount of overhead.

Kent
kadickey@phoenix.Princeton.EDU

jerry@polygen.uucp (Jerry Shekhel) (04/03/91)

jpenne@ee.ualberta.ca (Jerry Penner) writes:
>
>I agree that using assembly is
>probably easier to write an OS in, because you don't have to fight the
>HLLs tendencies to constrict you into doing something in a certain
>way.
>

I doubt it.  Modern OS's with their multitasking and inter-process
communication capabilities are much more complex than most application
programs.  They have to manipulate process lists, maintain I/O request
queues, use statistical methods and even heuristics to re-prioritize tasks,
etc.  And I'm not even talking about things like graphical window management
and such.  Don't tell me all these things are easier to code in assembly
language than, say, C.

Sure, operating systems used to be simple; all they did was talk to the
hardware.  For these, assembly language was acceptable.  MS-DOS is such
a system.  But for modern OS's like UNIX, assembly language just gets in
the way, and doesn't provide significant performance advantages.

By the way, what tendencies do HLL's have that "constrict you into doing
something in a certain way"?

>
>    Jerry Penner	alberta!bode!jpenne	Edmonton, Alberta, Canada
>
--
+-------------------+----------------------+---------------------------------+
| JERRY J. SHEKHEL  | POLYGEN CORPORATION  | When I was young, I had to walk |
| Drummers do it... | Waltham, MA USA      | to school and back every day -- |
|    ... In rhythm! | (617) 890-2175       | 20 miles, uphill both ways.     |
+-------------------+----------------------+---------------------------------+
|           ...! [ princeton mit-eddie bu sunne ] !polygen!jerry             |
|                            jerry@polygen.com                               |
+----------------------------------------------------------------------------+

rhyde@koufax.ucr.edu (randy hyde) (04/04/91)

>>>
Thus, system overhead, at least on our UNIX systems, is close to negligible...
<<<

How did you come up with this?  Have you actually rewritten the kernel in
assembly and compared the difference?  Warm fuzzy feelings about it don't
count.

Now, perhaps, what you really mean to say is "Gee, we write all of our apps
in "C" and we write them in a sloppy fashion (i.e., slow).  They eat up so
much CPU time that the overhead of the O/S pales in comparison."

I could buy that.  However, it's not a good argument for writing OSes in
C.  Some of us *do* write very high performance software in assembly and don't
need boat anchors like UNIX slowing us down!

BTW, I recently rewrote a MINIX-based SCSI device driver in assembly
(the original
code was in C).  It actually took fewer lines of code (NS32532) and ran about
an order of magnitude faster.  While this is not an entire O/S, I suspect the
process manager would fare much better in assembly.  The memory manager
probably
would be better in assembly (warm fuzzy, I wouldn't bet anything on it).  The
file manager probably wouldn't gain much in assembly over C assuming the device
drivers were written in assembly.

JWANKERL@UTCVM.BITNET ("Josef W. Wankerl") (04/05/91)

On Wed, 3 Apr 91 15:59:44 GMT Jerry Shekhel said:
>I doubt it.  Modern OS's with their multitasking and inter-process
>communication capabilities are much more complex than most application
>programs.  They have to manipulate process lists, maintain I/O request
>queues, use statistical methods and even heuristics to re-prioritize tasks,
>etc.  And I'm not even talking about things like graphical window management
>and such.  Don't tell me all these things are easier to code in assembly
>language than, say, C.

ACK!!!!  "Easy" is a relative term.  I could probably code something
much faster in C, but I could do a much better job in assembly (on the
IIGS, other architectures may vary.)  Saying it's easier in C than
assembly - well - the concepts are all the same, I can implement a
linked list and queues and binary trees and all sorts of other nifty
constructs with assembly, and I have lots more flexibility with my
assembly constructs, too.  ...and sometimes the easy way out isn't
always the best way.

>--
>+-------------------+----------------------+---------------------------------+
>| JERRY J. SHEKHEL  | POLYGEN CORPORATION  | When I was young, I had to walk |
>| Drummers do it... | Waltham, MA USA      | to school and back every day -- |
>|    ... In rhythm! | (617) 890-2175       | 20 miles, uphill both ways.     |
>+-------------------+----------------------+---------------------------------+
>|           ...! [ princeton mit-eddie bu sunne ] !polygen!jerry             |
>|                            jerry@polygen.com                               |
>+----------------------------------------------------------------------------+

--
===> Josef W. Wankerl, Technical Editor for GS+ Magazine
  BITNET:  JWANKERL@UTCVM.BITNET       | America Online:  JWankerl
 ProLine:  jwankerl@pro-gsplus         |--------------------------------
Internet:  jwankerl@pro-gsplus.cts.com | "I am a Viking"  -Y. Malmsteen

gwyn@smoke.brl.mil (Doug Gwyn) (04/05/91)

In article <7830@idunno.Princeton.EDU> kadickey@phoenix.Princeton.EDU (Kent Andrew Dickey) writes:
>However, there are times when interrupts are not enabled!

Wrong.  The scheduler clock on our systems is serviced reliably.

>Unix has an incredible amount of overhead.

Also wrong in general, although perhaps true of some implementations
if you overload them to the point that they start pagging or swapping
unduly.

gwyn@smoke.brl.mil (Doug Gwyn) (04/05/91)

In article <13275@ucrmath.ucr.edu> rhyde@koufax.ucr.edu (randy hyde) writes:
>>Thus, system overhead, at least on our UNIX systems, is close to negligible...
>How did you come up with this?  Have you actually rewritten the kernel in
>assembly and compared the difference?

NO, but the opposite conversion occurred and was reported in the literature
which you apparently don't read.

>... don't need boat anchors like UNIX slowing us down!

I feel sorry for your students.

jcav@quads.uchicago.edu (john cavallino) (04/05/91)

One fact that hasn't yet been addressed in this discussion is the existence
of new processor architectures (RISC especially) of such complexity that you
REALLY DO NEED A COMPILER TO WRITE EFFICIENT SOFTWARE.  I'm talking about
things like multi-stage instruction pipelines which must be kept full to
achieve good performance.  What about branch prediction and
register/pipeline interlock, which might involve actually changing the
apparent order of instructions?  Do you really want to have to keep track
of stuff like that, when bunches of very smart people have already written
compilers that will do it for you?  Machine language isn't always the answer,
and I suspect that will become more true in the future.

-- 
John Cavallino                      |     EMail: jcav@midway.uchicago.edu
University of Chicago Hospitals     |    USMail: 5841 S. Maryland Ave, Box 145
Office of Facilities Management     |            Chicago, IL  60637
"Opinions, my boy. Just opinions"   | Telephone: 312-702-6900

rhyde@ucrmath.ucr.edu (randy hyde) (04/05/91)

>>>>
By the way, what tendencies do HLL's have that "constrict you into doing
something in a certain way"?
<<<<

All languages (included different assembly languages) have a "programming
paradigm".  The differences between some languages is subtle (e.g., there
are small, subtle, differences between languages like "C" and Pascal, there
are considerable differences between languages like "C", Snobol4, ICON, LISP,
Prolog, and SETL). Some languages are especially suited for certain apps.
For example, Snobol4 and ICON are really great at pattern matching, but fair
poorly in number crunching applications.  APL is great for linear algebra
and matrix arithmetic problems, but you never use it for database
manipulation, COBOL isn't good for anything (okay, I couldn't resist that
one!).  

Any application which requires bit pushing, assembly language wins hands
down (a good example is a SCSI device driver I have been converting from C
to 32532 assembly language).  The program will generally shorter by a factor
of two or more and about 10-100 times faster.  Furthermore, in the hands of
competent assembly and C programmers, the assembly language program will
be easier to read and understand.  This is not an absolute assessment, but
it has been true most of the time, in my experience.

Applications which push bytes around (e.g., text editors, graphic
display drivers, memory managers, etc.) are generally easier to write or
not much more difficult to write in assembly than in a language like C.
Not all such applications, but a good number of them.  Too many times I've
started writing such a program in C only to swear at myself well into the
project because so many components of the project would have been easier to
implement in assembly.  Why not write those components in assembly and call
them from C?  Alas, working in C forces you into a different programming
paradigm.  You have to think about the problem in a different fashion
("Constricting" is such a harsh term).  This paradigm permeates throughout
the code.  Writing a few procedures or functions in assembly will not let
you escape that paradigm.  Assembly language programmers *think* about
problems differently than C programmers.  This is the true reason good
assembly language programmers write much faster code than C programmers.
If you write "C" code using MOVs (or LDAs), you're code isn't going to
be much faster or much smaller than the output of the compiler.  Indeed,
optimizing compilers may beat the pants off of people acting as human
compilers.  I'm sure this is what the original poster was alluding to
when s/he made the above comment.

Of course, there are some applications where the choice of assembly language
is not appropriate.  Assuming a decent toolkit of library routines written
in assembly language, I could not justify writing user interface code in
assembly language.  C, Pascal, or something at a high level (like 4th Dimension
on the Macintosh) is more appropriate.  And there would be very little
performance benefit to sticking with asm.

>>>
I doubt it.  Modern OS's with their multitasking and inter-process
communication capabilities are much more complex than most application
programs.  They have to manipulate process lists, maintain I/O request
queues, use statistical methods and even heuristics to re-prioritize tasks,
etc.  And I'm not even talking about things like graphical window management
and such.  Don't tell me all these things are easier to code in assembly
language than, say, C.

Sure, operating systems used to be simple; all they did was talk to the
hardware.  For these, assembly language was acceptable.  MS-DOS is such
a system.  But for modern OS's like UNIX, assembly language just gets in
the way, and doesn't provide significant performance advantages.
<<<<<

An OS, though, is a byte pusher.  The process manager, communications
managers, device managers, and user interface toolkits would all benefit
from being written in assembly.  The file manager is questionable.

Manipulating process lists, I/O request queues, and reprioritzing tasks is
no big deal in assembly language.  I teach OS (CS 431) at Cal Poly Pomona.
I make my students write their code in 8086 assembly language.  These are
people who are totally incompetent in assembly language.  Yet they manage
to accomplish these tasks quarter after quarter.  Statistical methods
and heuristics are definitely beyond these students, but they're not beyond
me.  They are just fancy names for some really simple processes.  Certainly
not too complex for a reasonable assembly language programmer.  Keep in
mind, that re-prioritizing tasks occurs at the level of the short and
medium-term scheduler.  These processes have to be very fast!  Indeed,
even in UNIX the dispatcher (i.e., short-term CPU scheduler) is typically
written in assembly language.

As for the Graphical User Interface- No way is this easier to write in
assembly than in C.  But there is an obvious performance benefit to having
this written in assembly.  X-Window is a good example of what happens when
you try to write such code in C.  It's wonderful that X is portable, but
you need a H**L of a machine  run in reasonably well.  I'd hate to imagine
a PC (<386), Mac, or *egads* an Apple IIgs where the windowing software was
written in C.
*** RAndy Hyde

 

 

rhyde@ucrmath.ucr.edu (randy hyde) (04/05/91)

>>>>
One fact that hasn't yet been addressed in this discussion is the existence
of new processor architectures (RISC especially) of such complexity that you
REALLY DO NEED A COMPILER TO WRITE EFFICIENT SOFTWARE.  I'm talking about
things like multi-stage instruction pipelines which must be kept full to
achieve good performance.  What about branch prediction and
register/pipeline interlock, which might involve actually changing the
apparent order of instructions?  Do you really want to have to keep track
of stuff like that, when bunches of very smart people have already written
compilers that will do it for you?  Machine language isn't always the answer,
and I suspect that will become more true in the future.
<<<<

I let some people sucker me into believing this.  I swear I'm gonna teach
myself SPARC assembly before I make any cracks one way or another on this
topic.  However, please allow me to make one quick comment:  Why on earth
can't we write an *optimizing assembler* which rearranges instructions
to keep the queues full, and warns you if you're not using the registers
as efficiently as you possibly could?  This would address the statement
that one really needs a compiler to write efficient code on a RISC.

Remember, it isn't just the instruction mix which makes human-written
assembly language programs better than machine-written assembly language
programs, it's the intelligence of the auther and the way s/he thinks
about the solution to the problem.  

As an aside (which I'm sure will start another flaming thread), I suspect that
RISC's days are numbered.  Most of the advantages of RISC are being implement-
ed into CISC, and what CICS will never be able to handle, LIWCs will blow
both RISC and CISC away on.  I suspect that VCISC computers, once someone
comes up with a better system bus structure (e.g., optical) will prove
that RISC is a dead end.
*** Randy Hyde

rhyde@ucrmath.ucr.edu (randy hyde) (04/05/91)

>>>>
NO, but the opposite conversion occurred and was reported in the literature
which you apparently don't read.

>... don't need boat anchors like UNIX slowing us down!

I feel sorry for your students.
<<<

Not only have I read that literatur (from the early '70's I might point out,
my how things have changed since then!), I assign it as reading.

Don't feel sorry for my students.  They come out of that class with a major
prejuidice against assembly removed.  By the time they're seniors they've
written a *lot* of C and Ada code, yet very little assembly.  They are
excited by the end of the quarter.  A good number of them exclaim happily that
"Gee, I really learned assembly language this quarter, it's nowhere near as
bad as I thought it was."  To bad *YOU* never had this experience.

One other comment about the literature you are obviously refering too:
keep in mind that the "C" which UNIX was originally re-written in was
an over-glorified assembler for the PDP-11.  C's syntax (e.g., ++i) was
designed to take advantage of the PDP-11's instruction set and hardware.
When you look at how C has grown (e.g., ANSI C and C++) and you look at
the various architectures it's running on (65c816, 8086, SPARC, R3000, etc.),
I believe you'll discover that compiling UNIX in C won't universally produce
the same results the original programmers found on the PDP-11.
*** Randy Hyde

gwyn@smoke.brl.mil (Doug Gwyn) (04/06/91)

In article <13345@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
>X-Window is a good example of what happens when you try to write such code
>in C.  It's wonderful that X is portable, but you need a H**L of a machine
>run in reasonably well.  I'd hate to imagine a PC (<386), Mac, or *egads*
>an Apple IIgs where the windowing software was written in C.

Again I have to challenge this, using real-world evidence.  The bitmap
graphics interface (including multitasked windows) I'm using while
typing this has nearly all of its firmware and applications written in
C, and it uses a processor and clock comparable with low-end Macintosh
models.  Its interactive performance far exceeds that of X11 terminals,
and also exceeds that of the Macintosh Finder and of Microsoft Windows
on a 33MHz IBM PC/AT clone.  If it had had to have been programmed in
assembler, I doubt very much that it would ever have been developed.

X11 indeed suffers from several problems, but none of them are due to
use of C.

gwyn@smoke.brl.mil (Doug Gwyn) (04/06/91)

In article <13348@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
>One other comment about the literature you are obviously refering too:
>keep in mind that the "C" which UNIX was originally re-written in was
>an over-glorified assembler for the PDP-11.  C's syntax (e.g., ++i) was
>designed to take advantage of the PDP-11's instruction set and hardware.

While C is a good match for the PDP-11, it is as equally good match for
the VAX and MC68000 instruction sets.  Most modern CPUs were designed,
unlike the afore-mentioned, with the idea that the majority of programs
for them would be coded in HLLs, and thus if their designers did a decent
job they should also be good matches for HLLs, certainly including C,
which is the most popular of all HLLs these days.

As I mentioned in private correspondence with you and also, as I recall,
some time ago in this newsgroup, the 65816 instruction set does not do a
very good job of supporting HLLs, so there are cases where assembly code
is preferred in Apple II applications (such as display animation loops).
But that does not support the argument that assembly coding should be
preferred in most cases.

jh4o+@andrew.cmu.edu (Jeffrey T. Hutzelman) (04/06/91)

gwyn@smoke.brl.mil (Doug Gwyn) writes:
> In article <13345@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
> >X-Window is a good example of what happens when you try to write such code
> >in C.  It's wonderful that X is portable, but you need a H**L of a machine
> >run in reasonably well.  I'd hate to imagine a PC (<386), Mac, or *egads*
> >an Apple IIgs where the windowing software was written in C.
> 
> Again I have to challenge this, using real-world evidence.  The bitmap
> graphics interface (including multitasked windows) I'm using while
> typing this has nearly all of its firmware and applications written in
> C, and it uses a processor and clock comparable with low-end Macintosh
> models.  Its interactive performance far exceeds that of X11 terminals,
> and also exceeds that of the Macintosh Finder and of Microsoft Windows
> on a 33MHz IBM PC/AT clone.  If it had had to have been programmed in
> assembler, I doubt very much that it would ever have been developed.
> 
> X11 indeed suffers from several problems, but none of them are due to
> use of C.

Me too.  The machine I'm sitting at (a DECstation 3100) uses a RISC
architecture that no one in his right mind would want to program in
assembly for.  The C compiler generates much more efficient code than
any human programmer I know, and I know plenty of decent human
programmers.
--------------------
Jeffrey Hutzelman			America Online: JeffreyH11
Internet: jh4o+@andrew.cmu.edu		BITNET: JHUTZ@DRYCAS
>> Apple // Forever!!! <<

rhyde@ucrmath.ucr.edu (randy hyde) (04/06/91)

>>>>
Me too.  The machine I'm sitting at (a DECstation 3100) uses a RISC
architecture that no one in his right mind would want to program in
assembly for.  The C compiler generates much more efficient code than
any human programmer I know, and I know plenty of decent human
programmers.
<<<<

The MIPS R2000 and R3000 archetectures are not that bad. Would decent
tools appear (e.g., an asm data flow analyzer) it would be perfectly
possible to program it any assembly language with no problem (other than
a steep learning curve).

Of course, as machines get faster and faster, the point really becomes one
of economics.  If C programs run between 1/2 and 1/10th the speed of
assembly language programs and you can buy a machine that is two to ten
times faster, you can easily opt for the faster machine and do all your work
in C.  My original post did not claim that *everyone* should write *all*
their applications in assembly.  I simply stated that I spend lots of extra
money on high-end machines so that they will execute their applications
*fast*, not so those application authors can write their programs in C
rather than assembly.

Some people around here think that I'm totally against the use of HLLs.
Nothing could be farther from the truth.  Indeed, I consider languages like
C and Pascal low(er) level languages.  HLLs encompass things like Prolog,
ICON, 4GLs, SETL, and the like.  Why don't we write applications in these
languages?  For many applications I can write a program in SETL ten times
faster than you can write it in C.  Why don't we write all (applicable)
software in SETL?  There are two reasons: SETL is dreadfully slow (although
I'll counter that by saying "buy a faster machine");  SETL isn't
appropriate for all applications.  However, you can make both of these
statements about *any* programming language *except* assembly.  For assembly,
only one of the statements might be true (dreadfully slow isn't the correct
answer).

pnakada@oracle.com (Paul Nakada) (04/06/91)

In article jh4o+@andrew.cmu.edu (Jeffrey T. Hutzelman) writes:
>gwyn@smoke.brl.mil (Doug Gwyn) writes:
>>In article <13345@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
>>>X-Window is a good example of what happens when you try to write such code
>>>in C.  It's wonderful that X is portable, but you need a H**L of a machine
>>>run in reasonably well.  I'd hate to imagine a PC (<386), Mac, or *egads*
>>>an Apple IIgs where the windowing software was written in C.
>>
>>Again I have to challenge this, using real-world evidence.  The bitmap
>>graphics interface (including multitasked windows) I'm using while
>>typing this has nearly all of its firmware and applications written in
>>C, and it uses a processor and clock comparable with low-end Macintosh
>>models.  Its interactive performance far exceeds that of X11 terminals,
>>and also exceeds that of the Macintosh Finder and of Microsoft Windows
>>on a 33MHz IBM PC/AT clone.  If it had had to have been programmed in
>>assembler, I doubt very much that it would ever have been developed.
>>
>>X11 indeed suffers from several problems, but none of them are due to
>>use of C.
>
>Me too.  The machine I'm sitting at (a DECstation 3100) uses a RISC
>architecture that no one in his right mind would want to program in
>assembly for.  The C compiler generates much more efficient code than
>any human programmer I know, and I know plenty of decent human
>programmers.
>--------------------

I think the important thing to realize is not that the compiler
generates more efficient code, but that these days, CPU's are
designed with compilers in mind.  Efficient, with respect to compiler
generated code, does not necessarily mean tight, small, and tricky
code, but it refers to code that takes the greatest advantages of
processor strengths and limits the effects of processor weaknesses.  
Granted, this is nothing that someone couldn't do directly in
assembly, but why do it, when the compiler will do it for you?  

-Paul Nakada
--

Paul Nakada  |  Oracle Corporation  |  pnakada@oracle.com

gwyn@smoke.brl.mil (Doug Gwyn) (04/07/91)

In article <13390@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
>ICON, 4GLs, SETL, and the like.  Why don't we write applications in these
>languages?

You omitted one of the most important reasons in the real world:
Most such languages are not sufficiently widely available.  That
is also true in spaces of any specific assembly language.  Few
programs that I write run on only the system they were intially
implemented for; most of them end up being heavily used on a
large number of quite different computer systems, ranging from
Apple IIs to Cray-2s.  SETL or iAPX366 assembler would have been
an utter waste of time.

jerry@polygen.uucp (Jerry Shekhel) (04/09/91)

In article <13345@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
>
>All languages (included different assembly languages) have a "programming
>paradigm".  The differences between some languages is subtle (e.g., there
>are small, subtle, differences between languages like "C" and Pascal, there
>are considerable differences between languages like "C", Snobol4, ICON, LISP,
>Prolog, and SETL). Some languages are especially suited for certain apps.
>

I see your point; I guess I was just thinking of C.  I still don't see how
anything could be easier to code in assembly language than in C.  Maybe that's
why they say that C is not a real high-level language.

>
>Any application which requires bit pushing, assembly language wins hands
>down (a good example is a SCSI device driver I have been converting from C
>to 32532 assembly language).  The program will generally shorter by a factor
>of two or more and about 10-100 times faster.  Furthermore, in the hands of
>competent assembly and C programmers, the assembly language program will
>be easier to read and understand.  This is not an absolute assessment, but
>it has been true most of the time, in my experience.
>

I must disagree with this, again, keeping C in mind.  Any decent compiler
will optimize register usage, and C expressions like "a <<= 5" or
"a &= ~0x1234" will normally compile down to a single instruction.  So I
really don't see your "bit-pushing" argument here, and certainly not the
performance increase factors you quote.  Of course, you may have been
thinking of FORTRAN or LISP...
--
+-------------------+----------------------+---------------------------------+
| JERRY J. SHEKHEL  | POLYGEN CORPORATION  | When I was young, I had to walk |
| Drummers do it... | Waltham, MA USA      | to school and back every day -- |
|    ... In rhythm! | (617) 890-2175       | 20 miles, uphill both ways.     |
+-------------------+----------------------+---------------------------------+
|           ...! [ princeton mit-eddie bu sunne ] !polygen!jerry             |
|                            jerry@polygen.com                               |
+----------------------------------------------------------------------------+

jerry@polygen.uucp (Jerry Shekhel) (04/09/91)

In article <13347@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
>
>As an aside (which I'm sure will start another flaming thread), I suspect that
>RISC's days are numbered.  Most of the advantages of RISC are being implement-
>ed into CISC, and what CICS will never be able to handle, LIWCs will blow
>both RISC and CISC away on.  I suspect that VCISC computers, once someone
>comes up with a better system bus structure (e.g., optical) will prove
>that RISC is a dead end.
>

I disagree with this, too.  The problem (or blessing) is that people don't
want to write in assembly language, and the hardware which executes all those
complex (CISC) machine instructions is a waste of on-chip real-estate.  Typical
C compilers only utilize a tiny fraction of the instructions available on
a CISC processor, so what's the point?  The upshot of RISC is that these chips
are smaller, they require less power, they are more easily scaled down,
and less hardware is necessary for decoding the instructions, all of these
factors leading to much greater performance.  The typical RISC microprocessor
contains under 100,000 transistor components.  Compare that to the 1 million+
in the 486!  The only disadvantage I see with RISC is that executable programs
compiled for RISC are approximately 30% larger than equivalent programs
compiled for CISC.

>
>*** Randy Hyde
>
--
+-------------------+----------------------+---------------------------------+
| JERRY J. SHEKHEL  | POLYGEN CORPORATION  | When I was young, I had to walk |
| Drummers do it... | Waltham, MA USA      | to school and back every day -- |
|    ... In rhythm! | (617) 890-2175       | 20 miles, uphill both ways.     |
+-------------------+----------------------+---------------------------------+
|           ...! [ princeton mit-eddie bu sunne ] !polygen!jerry             |
|                            jerry@polygen.com                               |
+----------------------------------------------------------------------------+

jerry@polygen.uucp (Jerry Shekhel) (04/10/91)

In article <13345@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
>
>As for the Graphical User Interface- No way is this easier to write in
>assembly than in C.  But there is an obvious performance benefit to having
>this written in assembly.  X-Window is a good example of what happens when
>you try to write such code in C.  It's wonderful that X is portable, but
>you need a H**L of a machine  run in reasonably well.
> 

If you think that X-Window's slowness is due to it having been written in C,
you are sadly mistaken.  The reason it's slow is that it has to convert each
call to a network packet, and send it over the network (or socket).  The
server on the other end, then receives the packet, converts it back to a
request, and finally does the requested processing.  When this whole process
has to be repeated for EVERY SINGLE call, no wonder it's slow.  The fact that
the software is written in C has zero performance implications here.
--
+-------------------+----------------------+---------------------------------+
| JERRY J. SHEKHEL  | POLYGEN CORPORATION  | When I was young, I had to walk |
| Drummers do it... | Waltham, MA USA      | to school and back every day -- |
|    ... In rhythm! | (617) 890-2175       | 20 miles, uphill both ways.     |
+-------------------+----------------------+---------------------------------+
|           ...! [ princeton mit-eddie bu sunne ] !polygen!jerry             |
|                            jerry@polygen.com                               |
+----------------------------------------------------------------------------+

rhyde@gibson.ucr.edu (randy hyde) (04/11/91)

Obviously, if you need portability, you would *never* consider using assembly
language.  Gee, even machines with the same processor (Mac, Amiga, ST) don't
allow you to easily port assembly language programs.  If you must
sacrifice your
software on the altar of portability, you will not be able to use assembly
language.  Those of us who *use* software, as opposed to *write* software could
really care less about portability.  If I own an IBM PC, I could really
care less
if Lotus 1-2-3 runs on a Mac, under UNIX, or on an Apple II gs, I only
care that
it runs on a PC.  Sure, there are some people out there who work on different
platforms and may need the cross-platform portability, but they are a
very small
minority.  The rest of us could care less (I work on several platforms
and I could
care less, for example).  I'd rather see each program optimized for the
particular
platform than turned into generic mush which runs on everything.

rhyde@gibson.ucr.edu (randy hyde) (04/11/91)

>> I disagree with this (bit pushing is easier in assembly than in C)

Okay, here's a challenge, code a CRC-16 algorithm in C.  I can promise you
that I can do it in few lines of assembly language (on *any* machine) and the
result will be easier to understand to anyone who has a basic understanding of
the instruction set.  If you want further proof, let me know and I will post
the two versions of the algorithm.  Of course, this is but one example, but I
can come up with a fair number of similar examples.

rhyde@gibson.ucr.edu (randy hyde) (04/11/91)

RE: CISC vs. RISC

Yeah, RISCs are smaller, so what?  Yes, todays RISC chips use 100K xstrs, CISCs
use millions.  So what?  You can buy a 486 chip for less money than most RISC
chips.  Where is the savings?  CISC manufacturers are not standing still, they
are using those extra transistors to eliminate microcode in the frequently
executed instructions (on a 386 or 486, for example, the LOOP instruction is
actually *slower* than the corresponding DEC CX, JNE instructions because the
DEC and JNE instructions are implemented via random logic and the LOOP
instruction is microcoded; in a future version of the 80x86 family we'll
probably see *all* of the instructions implemented in random logic.  It
just takes time to do this).

>>> All of these factors lead to increased performance.

Then why are CISC processors like the 80486 and 68040 comparing
favorably or even out-performing their RISC competitors at equivalent
clock speeds.  As for the "They can run at faster clock speeds
arguement",  CISC is only about a year behind in brute force clock
speeds, in terms of system throughput rates, high end CISC compares
favorably against high-end RISC today.

RISC has had the obvious benefit of making CISC producers stand up and
take notice.  They've stopped using microcode so much and they're
switching to the use of random logic for instruction decoding (*exactly*
the hardware equivalent of the assembly language vs. C arguement).

rhyde@ucrmath.ucr.edu (randy hyde) (04/11/91)

>>>
If you think that X-Window's slowness is due to it having been written in C,
you are sadly mistaken.  The reason it's slow is that it has to convert each
call to a network packet, and send it over the network (or socket).
<<<

First of all, mostly high level commands get sent over the network.  The
communications performance is bad, but not as bad as you imply.  On a system
which doesn't use a network (client and server are all on the same machine)
sockets surely slow you down.  Why?  That part of the operating system is
written in C! :-)

Seriously, though, scrolling and redrawing are server operations, even these
operations take a fast machine to work reasonably well.  On a SPARC this
works okay, on a Sun-3, well you can go take a coffee break.  I'd hate to see
it on an Apple IIgs, even with a TWGS.

whitewolf@gnh-starport.cts.com (Tae Song) (04/13/91)

|I disagree with this, too.  The problem (or blessing) is that people don't
|want to write in assembly language, and the hardware which executes all those
|complex (CISC) machine instructions is a waste of on-chip real-estate. 
|Typical C compilers only utilize a tiny fraction of the instructions available
|on a CISC processor, so what's the point?  The upshot of RISC is that these
|chips are smaller, they require less power, they are more easily scaled down,
|and less hardware is necessary for decoding the instructions, all of these
|factors leading to much greater performance.  The typical RISC microprocessor
|contains under 100,000 transistor components.  Compare that to the 1 million+
|in the 486!  The only disadvantage I see with RISC is that executable programs
|compiled for RISC are approximately 30% larger than equivalent programs
|compiled for CISC.

The reason the i486 has 1,000,000 transistors is because it has everything
built-in... 8K cache, MMU, FPU, as will as the CPU itself and logic to handle
the interactions within the chip.

RISC itself is now even becoming a misnomer, because some RISC chips have more
instruction that CISC chips, it's now Simple Instruction Set Chip (SISC)...
The point is becoming moot as well, both CISC and RISC are merging and the most
inportant think is to keep the instruction time to near 1 cycle or less.  The
'040 has an average cycle time of 1.3 and the instructions that do more
(complex instruct.) take longer and the simpler ones shorter.
 
whitewolf@gnh-starport!info-apple

bh1e+@andrew.cmu.edu (Brendan Gallagher Hoar) (04/13/91)

So I was reading Tae's message on RISC and CISC chips and just
remembered a slightly humorous little thing I found out yesterday.

Thursday I got my new toy in the mail, a Digitech GSP 21 Pro which is
a DSP, etc sound processor specifically designed to be used with
electric guitars.  Anyway, supposedly the company did a lot of
development on the thing using VLSI, etc.  They call the engine a HISC
processor. I'm thinking to myself, obviously, "What does the H stand
for???".  Well, yesterday while going thru the manual I came upon a
list of acronym definitions.  Whats DSP, whats VLSI, etc.

HISC	Happenin' Instruction Set Computer.

Ahem.  Only from guitar geeks...sheesh.

Brendan G. Hoar                      bh1e+@andrew.cmu.edu
Apartment 1                          Carnegie Mellon, Inc.
357 Melwood Ave.
Pittsburgh, PA 15213
(412) 621-8278

gwyn@smoke.brl.mil (Doug Gwyn) (04/16/91)

In article <13494@ucrmath.ucr.edu> rhyde@gibson.ucr.edu (randy hyde) writes:
>>> I disagree with this (bit pushing is easier in assembly than in C)
>Okay, here's a challenge, code a CRC-16 algorithm in C.  I can promise you
>that I can do it in few lines of assembly language (on *any* machine) and the
>result will be easier to understand to anyone who has a basic understanding of
>the instruction set.

Here is an extract from actual code (being executed for EVERY character
being sent to or from the terminal I'm typing this on), not written by me
(or it would have been more readable).  It is a fair comparison, because
it uses the same algorithm with the same interface constraints (e.g., must
be callable from C).

C version:

	typedef unsigned char	uchar;
	typedef unsigned short	ushort;

	#define	lobyte(X)	((X)&0xff)
	#define	hibyte(X)	(((X)>>8)&0xff)

	static ushort	crc16t_32[2][16]	=
	{
		0, 0140301, 0140601, 0500,
		0141401, 01700, 01200, 0141101,
		0143001, 03300, 003600, 0143501,
		02400, 0142701, 0142201, 02100,
		0, 0146001, 0154001, 012000,
		0170001, 036000, 024000, 0162001,
		0120001, 066000, 074000, 0132001,
		050000, 0116001, 0104001, 042000
	};

	int
	crc(buffer, nbytes)
		register uchar *buffer;
		int		nbytes;
	{
		register ushort	tcrc = 0;
		register int	temp;
		register int	i;

		if ( (i = nbytes) > 0 )
		do
		{
			temp = tcrc ^ *buffer++;
			tcrc = crc16t_32[0][temp & 017]
				 ^ crc16t_32[1][(temp>>4) & 017]
				 ^ (tcrc>>8);
		}
		while
			( --i > 0 );

		if ( lobyte(tcrc) != *buffer )
			i++;
		*buffer++ = lobyte(tcrc);

		if ( hibyte(tcrc) != *buffer )
			i++;
		*buffer++ = hibyte(tcrc);

		return i;
	}

MC68000 assembler version:

		data
	crc16t_3:
		word	0,0140301,0140601,0500
		word	0141401,01700,01200,0141101
		word	0143001,03300,003600,0143501
		word	02400,0142701,0142201,02100
		word	0,0146001,0154001,012000,0170001
		word	036000,024000,0162001,0120001
		word	066000,074000,0132001,050000
		word	0116001,0104001,042000
		text
		global	crc
	crc:
		link	%fp,&crcF
		movm.l	&crcM,crcS(%fp)
		mov.l	8(%fp),%a2
		mov.l	&0,%d2
		mov.w	12(%fp),%d4
		ble	crc%140
	crc%170:
		mov.b	(%a2)+,%d3
		eor.b	%d2,%d3
		mov.l	&15,%d0
		and.b	%d3,%d0
		add.l	%d0,%d0
		mov.l	&crc16t_3,%a1
		mov.w	0(%a1,%d0.l),%d0
		lsr.b	&3,%d3
		and.w	&30,%d3
		mov.l	&crc16t_3+32,%a0
		mov.w	0(%a0,%d3.w),%d1
		eor.w	%d0,%d1
		lsr.w	&8,%d2
		eor.w	%d1,%d2
		sub.w	&1,%d4
		bgt	crc%170
	crc%140:
		cmp.b	%d2,(%a2)
		beq	crc%180
		add.w	&1,%d4
	crc%180:
		mov.b	%d2,(%a2)+
		lsr.w	&8,%d2
		cmp.b	%d2,(%a2)
		beq	crc%190
		add.w	&1,%d4
	crc%190:
		mov.b	%d2,(%a2)+
		mov.w	%d4,%d0
		movm.l	crcS(%fp),&crcM
		unlk	%fp
		rts
		set	crcS,-16
		set	crcF,-22
		set	crcM,02034

Frankly, I don't think either version is very intuitive, but both
are intended to execute quickly.  I would have to wonder about anybody
who would claim that there is anything inherently more readable about
the MC68000 version.

And no fair rewriting it to use a different algorithm or to fit
different constraints!  I could certainly substantially improve the
readability of the C version too under those circumstances.

rhyde@maris.ucr.edu (randy hyde) (04/17/91)

Well, I will post my CRC algorithms a little later (I don't have them here at
school, you'll have to wait until I get home).  I will attack one premise of
yours (or, perhaps, support it).  You state the following:

"It is a fair comparison, because it uses the same algorithm with the same
interface constraints (e.g., must be callable from C)."

If these are the constraints you place on assembly language programming then
I must support *your* position 100%.  It would not be worthwhile writing
*anything* (well, just about anything) in assembly language.  I don't know if
you were the original poster (my memory fades fast on these rwar topics), some-
one around here stated that you should always stick to the abstract model of
computation that a language has to offer.  Anytime you attempt to force one
model of computation on a language not suited for it, the end result is in-`
efficiency.  If you are going to act as a "human compiler" for C, your assembly
language code is not going to be as good as someone who "thinks" in assembly
language.  I do not have time, right now, to analyze your algorithm.  As soon
as I figure it out I'll post another version of it.  We'll see if I can do
any better (perhaps, perhaps not).
*** Randy Hyde

davewh@microsoft.UUCP (04/17/91)

My two cents:

I found that even though I had plugged on an Apple // for years, my
BEST source of serious knowledge on how a computer works came from 2
classes at MIT: one in which we built a predesigned computer (very
simple little thing, 800KHz clock, 64k RAM. CPU was built out of
little parts); the other one a compiler class.

The first class gave me a very good understanding of how the hardware
works in computers: why this instruction takes n cycles and so on.
The other gave me a good idea on how the compiler translates my C
into assembler. I had had plenty of assembler experience before these
classes, but the real insight doesn't come from programming in
assembler or programming in some HLL - but rather in knowing how the
compiler translates one into the other. Once you know how a compiler
works, it's much easier to locate obscure bugs in some HLL code. One
also can employ many tricks and know to avoid certain things. ie:

struct foo * NewFoo(void)
{
	struct foo TheNewFoo;

	TheNewFoo.member1 = value1;
	TheNewFoo.member2 = value2;

	return &TheNewFoo;
}

Do you know why this will FAIL? Do you know the RIGHT way to do it?
Sure, it compiles. It'll even run. I wouldn't write any code like
this though because it's dangerous. The quick and obvious fix is to
take out the '*' and the '&'. I still wouldn't do it that way
though... Anyone know why?

People here are arguing that Assembler should be a required course,
while others say it should only be touched upon or ignored. I
disagree with everyone: first, take a simple HLL course (like C).
Then a compiler class (we didn't have to write a C compiler, but the
language we did invent gave us a good idea of the complexity of
compilers and how they generally work). Then a more esoteric
language, like LISP. By then, students will have generic algorithm
experience and have a good idea on how to construct a program. Next
they get experience in how the compiler does the translation (and
what it gets translated into). They learn the pitfalls of doing
things the wrong way in some HLL. They learn WHY they have to use
'scanf("%d",&intvar)'. Then they learn the language of choice for CS
majors. The one where the compiler is much more friendly than a C
compiler but the students still know the pitfalls (why the thing has
to freeze up every now and then and garbage collect, etc).

The "you build it" computer class teaches people how the OS interacts
with the program. How the hardware handles memory cacheing, virtual
memory, context switching. Students learn why the computer will crash
if too many processes are running. Just what 'load" is. They learn
and appreciate what sort of work is going on. Why they should access
a 2-d array of numbers in row major order and not column major order
(one way causes the virtual memory system to spend all it's time
swapping - I sped a program up by a factor of 10 by simply changing
the order of the loops!). They appreciate the work involved in using
floating point numbers over integers. I could go on and on...

Ok, what do you all think?

Dave Whitney	Microsoft Corp, Work Group Apps  dcw@goldilocks.lcs.mit.edu or
I wrote Z-Link and BinSCII - send me bug reports. {...}!uunet!microsoft!davewh
I only work here. All opinions herein aren't Bill's, they're mine.
"We're samplin' - Yeah we're doin' it. We take good music an' we ruin it."
   -- "Rap Isn't Music"

davewh@microsoft.UUCP (04/18/91)

Raymond Lang <uunet!rex.cs.tulane.edu!lang> asks me (and I answer):

: >struct foo * NewFoo(void)
: >{
: >       struct foo TheNewFoo;
: 
: >       TheNewFoo.member1 = value1;
: >       TheNewFoo.member2 = value2;
: 
: >       return &TheNewFoo;
: >}
: 
: >Do you know why this will FAIL? Do you know the RIGHT way to do it?
: 
: I'm new at this. What's the problem?

OK, C compilers are pretty simple and predicatable. In fact, Pascal
compilers are very similar. At any rate, they all "create" local
variables on the stack. When a procedure call is made, the calling
function pushes its parameters on the stack and then calls the
function. The function then pushes dummy stuff onto the stack to
allocate enough space for its local variables.

So, upon entry to NewFoo, the top of stack contains the return
address for the function call (no parameters). NewFoo then pushes
enough space onto the stack to hold one foo struct.

Members are now set. Look what's returned: the address of TheNewFoo,
a pointer to some location on the stack (more accurately, a pointer
to some memory currently being used by the stack - memory that will
be used again by the stack). The calling function gets this pointer
back and does what it pleases. What happens when another function is
called? Well, the stack is overwritten (more accurately, the memory
where the stack is is changed). But that pointer I have is supposed
to point to some valid data! The pointer is still OK, but the data
has been corrupted because the next function call has changed the
contents of the memory where the stack is (and where my struct is)!

OK, you say. Don't pass back a pointer. C can pass whole structs
around. So, I change my function to pass back a struct instead of a
pointer to a struct. Well, that'll work. No problem there. The only
reason I wouldn't do it that way is because what if the struct is
HUGE? Passing structs around is terribly inefficient. Lots and lots
of bytes have to copied. You also get into very hairy stuff if the
struct contains pointers. How do you "copy" the struct? Do you copy
the pointers only or do you allocate new memory and copy what the
pointers point to? It depends.

My solution is this:

struct foo * NewFoo(void)
{
       struct foo *TheNewFoo = malloc(sizeof(struct foo));

       TheNewFoo->member1 = value1;
       TheNewFoo->member2 = value2;

       return TheNewFoo;
}

Subtle difference here. In this case, I've called the memory manager
and asked it for some memory. Assuming the memory manager works
correctly (which, by the way, on Sun OS 4.1, it does not - it
allocates n-1 bytes for you; the last byte of the memory you ask for
isn't there!), this is a safe thing to do. No other function in the
computer will deliberately interfere with this chunk of memory. It's
*not* on the stack, it's in the heap - a seperate section of memory
that the runtime system manages. Should the stack grow so large that
it runs into the heap, the program will crash - the runtime system
will cause it to crash with a stack overflow error. (This assumes
that you're running on a system that can handle an "infinite" stack.
Mac's and IIgs's have a much smaller limit and you may overflow that
stack long before it runs into the heap.)

Since I've manually allocated new memory, I can pass that pointer
around with confidence. All I need to do is remember to ask the
memory manager to free up that memory when I'm done with it. On unix
systems (and other multitasking environments), you can get away with
not freeing the memory because usually, when a program exits, all of
the space it asked for is freed automatically. This may or may not be
the case with the Mac or IIgs (I don't know). Not freeing your memory
could cause a memory leak and eventually your machine would fill up
with garbage and you'd run out of memory.

LESSON: don't return local struct variables. Manually allocate new
memory and return a pointer to it.

: >                       Then they learn the language of choice for CS
: >majors. The one where the compiler is much more friendly than a C
: >compiler but the students still know the pitfalls (why the thing has
: >to freeze up every now and then and garbage collect, etc).
: 
: What language is that?

Most (not all) would agree, LISP. LISP handles a lot of this memory
management crap for you. Allocations in the heap are done behind your
back. On the downside, freeing is not automatic and there's no way to
do it manually. Therefore, the machine runs out of memory. BUT,
because the system knows that it's very likely that you haven't
REALLY run out of memory, it does what's called a garbage collect. It
examines its list of pointers to objects and the allocated memory. It
does some shuffling around and pushing back and forth and discovers
allocated memory that has absolutely no pointer pointing to it. OOPS.
Free it. After scanning like this, memory is compacted so new
allocations can be made easily.

Symbolics LISP machines may be set up to do quick and dirty garbage
collection while your program is running. This gives you a slight
reduction in performance while giving you more time before a
heavy-duty garbage collect needs to be done. The heavy duty garbage
collect stops the system completely while it shuffles. This can take
a couple of hours (I've seen a machine tied up for 4 hours just
garbage collecting). You can make the machine NOT EVER do garbage
collection, but that isn't wise. The machine just goes right down the
toilet. You get panic messages saying "There's only 180K left!"
"There's only 100k left!" "There's only 60k left!" "There's only 10k
left!" GRONK! Machine crashes.

LESSON: no lanuage is perfect for everything. It depends on what you
want to do and how much operating responsibility you want to take on
for yourself.

Dave Whitney	Microsoft Corp, Work Group Apps  dcw@goldilocks.lcs.mit.edu or
I wrote Z-Link and BinSCII - send me bug reports. {...}!uunet!microsoft!davewh
I only work here. All opinions herein aren't Bill's, they're mine.
"We're samplin' - Yeah we're doin' it. We take good music an' we ruin it."
   -- "Rap Isn't Music"

gwyn@smoke.brl.mil (Doug Gwyn) (04/21/91)

In article <9104181707.AA29942@beaver.cs.washington.edu> davewh@microsoft.UUCP writes:
>{
>	struct foo TheNewFoo;
>	return &TheNewFoo;
>}
>Do you know why this will FAIL?

Sure, but it is not necessary to understand code generation to avoid
that pitfall.  The relevant knowledge concerns the concept of the
lifetime of an instance of an automatic variable, which can be dealt
with on a purely abstract (HLL) level.  A more detailed understanding
of one possible method of implementation might help one better
appreciate why the language has such a restriction; however, if you
simply are careful to obey the language rules you will avoid such
problems.

I agree with the general sentiment that a well-rounded background in
practical aspects of computing can be helpful in making better use of
computers.  I haven't been arguing against exposure to machine
architecture or assembly language.  What I have been arguing against
is that assembly language should be the language of choice for any
significant fraction of computing application implementations.

jerry@polygen.uucp (Jerry Shekhel) (04/22/91)

In article <13516@ucrmath.ucr.edu> rhyde@ucrmath.ucr.edu (randy hyde) writes:
>
>...[About the X Window System]...
>
>Seriously, though, scrolling and redrawing are server operations, even these
>operations take a fast machine to work reasonably well.  On a SPARC this
>works okay, on a Sun-3, well you can go take a coffee break.  I'd hate to see
>it on an Apple IIgs, even with a TWGS.
>

I use a Sun-3, and the performance of the vanilla MIT X Window Server went
up by a factor of about 5 between Release 3 and Release 4.  The improvement
is unbelievable.  And yes, it's still written in C, so go figure.
--
+-------------------+----------------------+---------------------------------+
| JERRY J. SHEKHEL  | POLYGEN CORPORATION  | When I was young, I had to walk |
| Drummers do it... | Waltham, MA USA      | to school and back every day -- |
|    ... In rhythm! | (617) 890-2175       | 20 miles, uphill both ways.     |
+-------------------+----------------------+---------------------------------+
|           ...! [ princeton mit-eddie bu sunne ] !polygen!jerry             |
|                            jerry@polygen.com                               |
+----------------------------------------------------------------------------+

rhyde@musial.ucr.edu (randy hyde) (04/24/91)

>> It went up by a factor of 4-5...Still written in C...So go figure...

There's nothing to figure, better programming is better programming regardless
of the language.  If you've got a better algorithm, it's going to run faster
(assuming that's what's better about the algorithm).  As my CRC posts prove,
it's quite possible to have a C program run faster than an assembly program
if the C program uses a better algorithm.  Given the same algorithm, though,
the assembly code will always run faster still (generally by 50% to 1000%).
Would you like X to run 8-10 times faster rather than 4-5?  Write it in
assembly.
Personally, I feel X is too unstable to do this just yet (still too many new
versions in the works), buit ultimately, a X-terminal vendor may want to recode
X in assembly so (1) That vendor has a performance advantage over
competitors, or
(2) that vendor can use slower parts (i.e., cheaper) to acheive the same
performance as competitors for less money.

If you're happy with the performance as it is (I suspect you're not, you *did*
upgrade to the faster version, right?), stick with it.  But would you turn down
code which runs 2x faster?

curts@usenet.umr.edu (Curt Schroeder) (04/25/91)

In article <9104181707.AA29942@beaver.cs.washington.edu> davewh@microsoft.UUCP writes:
[lots of great stuff that I agree with deleted]
>Ok, what do you all think?
>
>Dave Whitney	Microsoft Corp, Work Group Apps  dcw@goldilocks.lcs.mit.edu or

I have been following this discussion for some time now.  Some of the comments
that have been made I agree with, some have made me angry.  Dave is the first
one I can truly say I agree with.  Why?  Because other than changing the order
of a few things around, he has essentially described the curiculum that I have
had!  I would like to note that the curiculum here drifted away from the low-
level stuff about one year behind me during my undergrad.  But, the curiculum 
is starting to swing back to a stronger low-level understanding of computing 
(I would like to think that I had something to do with this, because I have 
supported this approach all along, but I doubt one student's voice had that 
much to do with it ;) ).

The key to the whole discussion though is "Use the right tool for the job!"

Curt

Curt Schroeder | U of Missouri - Rolla | curts@ee.umr.edu       |
---------------------------------------| curts@cs.umr.edu       |
"Oops?  What do you mean, oops?  I     | s076895@umrvma.bitnet  |
 distinctly heard an oops!" - Opus     | -- Apple II Forever -- |

reanor@speedy.cs.pitt.edu (Jeffrey Getzin) (04/26/91)

In article <9104041653.AB15986@apple.com> JWANKERL@UTCVM.BITNET ("Josef W. Wankerl") writes:
>
>ACK!!!!  "Easy" is a relative term.  I could probably code something
>much faster in C, but I could do a much better job in assembly (on the
>IIGS, other architectures may vary.)  Saying it's easier in C than
>assembly - well - the concepts are all the same, I can implement a
>linked list and queues and binary trees and all sorts of other nifty
>constructs with assembly, and I have lots more flexibility with my
>assembly constructs, too.  ...and sometimes the easy way out isn't
>always the best way.
>
>--
>===> Josef W. Wankerl, Technical Editor for GS+ Magazine
>  BITNET:  JWANKERL@UTCVM.BITNET       | America Online:  JWankerl
> ProLine:  jwankerl@pro-gsplus         |--------------------------------
>Internet:  jwankerl@pro-gsplus.cts.com | "I am a Viking"  -Y. Malmsteen

I think you people have been arguing with only tiny computers (such as
the Apple II's) in mind.   On these machines, the limitation is in the
compiler and not in the language.

On a larger machine, I don't see how it's even REMOTELY possible to out-do
a compiled high-level language.   Compilers can do automatically what is
inconceivably hard, boring, or distasteful to a programmer.   For example,
I recently read an article, "Program Optimization for Instruction Caches"
(McFarling/Stanford University) in which compiled programs are optimized
to minimize the miss rate on an instruction cache by rearranging the basic
blocks.   I don't know about you net-ers, but I personally would not want
to do this to assembler language programs by hand.  Personally, I don't know
if even I COULD, and I feel that I am a more than an adequate programmer.

The same argument goes for such things as register allocation (minimize
memory access), redundant load/store elimination (again minimizing memory
access), constant propogation (reducing number of computations performed),
invariant code motion (reducing number of instructions executed), etc.   All
of these optimizations are very easy conceptually, but are simply beyond the
boredom-thresholds of most programmers.


--
					---
Jeffrey Getzin
saintdor@vms.cis.pitt.edu

rhyde@dimaggio.ucr.edu (randy hyde) (04/27/91)

> The key to the whole discussion though, is use the right tool for the job.

AMEN.
The problem is, most people don't know what the right tool is at some
particular time (on both sides of the argument, I might point out).

toddpw@nntp-server.caltech.edu (Todd P. Whitesel) (05/01/91)

I don't have a specific point to prove, just a comment:

reanor@speedy.cs.pitt.edu (Jeffrey Getzin) writes:

> All of these optimizations are very easy conceptually, but are simply
>beyond the boredom-thresholds of most programmers.

Maybe this is because they don't know how to write efficient code in
the first place. Good assembly prorammers often write pre-optimized
code where it counts, and usually the optimizations are impractical
for the compiler but garner that extra size/speed edge that justified
using assembly in the first place.

Todd Whitesel
toddpw @ tybalt.caltech.edu

rhyde@ucrmath.ucr.edu (randy hyde) (05/02/91)

re: I wouldn't want to write assembly code on a big machine.... register
    optimizations... cache hits... etc...

Actually, anyone with about a year's experience can handle most of this
with no problem.  I've written assembly code on 80386, 680x0, and 32532
machines (which IMHO, are big), and I'm learning SPARC right now.  It's
not that big a deal to do those things you're so frightened of.  I can
tell you what's worse-- writing a serial driver on the 6502 using the
game port on the Apple II.  I've written a couple of those in my time.
At one time I had all the instruction cycle timings for the 6502 instr.
set memorized (it's been a while since I can remember them, though!).
I consider this a greater feat than learning about cache hits and
delay slots, and stuff like that.

As for compilers doing better than people at code generation, I must
reiterate an earlier post-- 
(1) This applies only if you continue thinking in C while programming in
    assembly.  If you do not switch to the assembly language programming
    paradigm (which, admittedly, takes a couple of years to learn), you
    don't stand a chance against modern optimizing compilers (which most
    available today are *not*).

(2) The same data flow analysis tools which optimize compilers can be
    applied to assembly language.  You could write a tool to tell you
    that you could be using the register better, or that moving a few
    instrs. around will speed things up.  This needn't be limited to
    HLLs.  Admittedly, such tools do not exist yet, but I'm working on
    such items (alas, not for the 65816, DFA tools wouldn't be much
    help for optimization [though I have developed a DFA tools for
    helping show program correctness of assembly language programs
    on the GS]).

*** Randy Hyde

psonnek@pro-mansion.cts.com (Patrick Sonnek) (05/03/91)

In-Reply-To: message from reanor@speedy.cs.pitt.edu

>I think you people have been arguing with only tiny computers (such as
>the Apple II's) in mind.   On these machines, the limitation is in the
>compiler and not in the language.
>
>On a larger machine, I don't see how it's even REMOTELY possible to out-do
>a compiled high-level language.   Compilers can do automatically what is
>inconceivably hard, boring, or distasteful to a programmer.   For example,
>I recently read an article, "Program Optimization for Instruction Caches"
>(McFarling/Stanford University) in which compiled programs are optimized
>to minimize the miss rate on an instruction cache by rearranging the basic
>blocks.   I don't know about you net-ers, but I personally would not want
>to do this to assembler language programs by hand.  Personally, I don't know
>if even I COULD, and I feel that I am a more than an adequate programmer.
>
>The same argument goes for such things as register allocation (minimize
>memory access), redundant load/store elimination (again minimizing memory
>access), constant propogation (reducing number of computations performed),
>invariant code motion (reducing number of instructions executed), etc.   All
>of these optimizations are very easy conceptually, but are simply beyond the
>boredom-thresholds of most programmers.

Have you ever heard of macros?  Most good assemblers, even Apples Pro-Dos
Assembler tools supports macros.  Alot of assmblers for mainframes come with
a whole truck load of memory and register management macros. (As well as I/O,
program initialisation, system inqiry.)  Granted, the Apple does this entirely
with Calls to the MLI, but those are almost as easy to use as macros.  About
the Redundant load/stores, I've noticed many compilers do the exact opposite,
the resulting code is full of unnessesary loads/stores.  in assembler you
would code direct memory access, which is many times faster, providing that
what it is your accessing is within your immediate memory page.


----
ProLine:  psonnek@pro-mansion    Sysop Pro-mansion: 507/726-6181
Internet: psonnek@pro-mansion.cts.com  MCImail:     psonnek
UUCP:     crash!pro-mansion!psonnek  ARPA: crash!pro-mansion!psonnek@nosc.mil
BITNET:   psonnek%pro-mansion.cts.com@nosc.mil
               <<Real programmers don't program in HLL's.>>
               <<HLL's are for wimpy application coders!!>>

gwyn@smoke.brl.mil (Doug Gwyn) (05/04/91)

In article <8993@crash.cts.com> psonnek@pro-mansion.cts.com (Patrick Sonnek) writes:
>Have you ever heard of macros?

None of the resource allocation issues that reanor@speedy.cs.pitt.edu
mentioned can be solved by using macros.

msucats@att1.Mankato.MSUS.EDU (msucats) (05/04/91)

In article <8993@crash.cts.com> psonnek@pro-mansion.cts.com (Patrick Sonnek) writes:

>> [ HLLs are faster because they do optimizations that assembly
>>   programmers wouldn't do due to boredom ]

>    Have you ever heard of macros?  Most good assemblers, even Apples
> Pro-Dos Assembler tools supports macros.  Alot of assmblers for
> mainframes come with a whole truck load of memory and register
> management macros. (As well as I/O, program initialisation, system
> inqiry.)  Granted, the Apple does this entirely with Calls to the
> MLI, but those are almost as easy to use as macros.  About the

Once you start using macros, you're back in HLL hell.  Macros hide
their internal details from the programmer; this is their advantage.
However, this is also their disadvantage, since the programmer's
ignorance means that macros may do useless things, such as...

> Redundant load/stores, 

Bingo.

> I've noticed many compilers do the exact opposite, the resulting
> code is full of unnessesary loads/stores.  

Get A Real Compiler.  (I suppose that's hard on the 6502.  I wonder if
gcc could be retargetted...naw.)  Seriously, this means that you need
a better optimizer for your compiler, or your compiler needs to be
recoded from the bottom up.

> in assembler you would code direct memory access, which is many
> times faster, providing that what it is your accessing is within
> your immediate memory page.

Huh?  Immediate memory page?  Page Zero?

> ProLine:  psonnek@pro-mansion    Sysop Pro-mansion: 507/726-6181
  ^^^^^^^
The reason ProLine is a work of art is that it exists at all.  Of
course, such artistry is not necessary on 8086 machines of similar
price...where HLL's can get the job done just as quickly. :-)

> Internet: psonnek@pro-mansion.cts.com  MCImail:     psonnek
> UUCP:     crash!pro-mansion!psonnek  ARPA: crash!pro-mansion!psonnek@nosc.mil
> BITNET:   psonnek%pro-mansion.cts.com@nosc.mil
					^^^^^^^^
Doesn't look like a BITNET address to me. 

>  <<Real programmers don't program in HLL's.>>

Yes.  We program in C. ;-)

>  <<HLL's are for wimpy application coders!!>>

Could you parenthesize that?  Do you mean coders who write wimpy
applications, application coders who are wimpy, or coders who are
wimpy and write applications?  Or are you trying to imply that people
who write applications are wimpy coders?

Jay Carlson
msucats@att1.mankato.msus.edu

rhyde@ucrmath.ucr.edu (randy hyde) (05/06/91)

>>>>
Get A Real Compiler.  (I suppose that's hard on the 6502.  I wonder if
gcc could be retargetted...naw.)  Seriously, this means that you need
a better optimizer for your compiler, or your compiler needs to be
recoded from the bottom up.
<<<<

I don't know what GCC is like on 68Ks and Sparcs, but I do know it produces
redundant loads on the 32532 version.  I recently hand-compiled a GCC SCSI
driver for my PC532 using the grossest, simple-minded code I code (to avoid
possible timing problems).  My code was less than 1/4 the size and about
three times faster than the GCC variety.  Mainly because of those Da*n redundant
loads.  GCC does some neat optimizations, but it really drops the ball in
other areas.

BTW, for anyone who is gonna start flaming me, SCSI drivers are a perfect
example of code that really *should* be written in assembly.
*** Randy Hyde