[comp.lang.misc] Languages and learning

nevin1@ihlpf.ATT.COM (00704A-Liber) (01/22/88)

[followups to comp.lang.misc]


In article <11348@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes:
>In article <4186@eagle.ukc.ac.uk> "H.A.Shaw" <has@eagle.ukc.ac.UK> writes:
>>I wholeheartedly agree, and hope I write better C
>>programs now for three years of BASIC/PASCAL/FORTRAN/FORTH first.
>>They did teach [C] to third year Computer Scientists sometimes.
>
>This is much too late.  Computer education should proceed from a
>hardware overview to machine language to assembler language to low-
>level compiled languages on up to high-level compiled languages.
>Teaching BASIC/Pascal/FORTRAN/Forth/etc first is like teaching algebra
>before arithmetic.

I don't know if this is the best way to learn computer programming.  Without
any previous experience, I think it would be extremely difficult to impossible
to debug a machine language program (although I do, I know that not everybody
in the world grasps logic easily).  In the beginning, it is very rewarding to
get a program to do something without too much effort; in assembler, even
printing out your name requires a non-trivial amount of work.  Most people
would probably just give up on computers.

>BASIC is a bad joke.  The bad habits that it imparts on students are
>particularly hard to unlearn (first impressions are lasting
>impressions).  It oversimplifies the hardware-software interface to
>the point where it seems, to the student, to be performing magic.  C
>on the other hand, is more transparent.  It allows the student to see
>the gears turning.

Non-structured BASIC (recently, I have seen some versions with Pascal-like
constructs in them) do bring on some very bad habits, I'll admit.  But most
HLLs oversimplify the hardware-software interface.  In my job, I very rarely
have to deal with hardware directly; I usually use standard system calls so
that to my program, all the hardware looks the same (this is one of the
purposes of an operating system).  I don't know what the best language to start
with is, but I don't think the bottom-up approach (i.e., starting with machine
language) has enough benefits to outweigh the problems.  Maybe starting with
Lisp (a language which can be described very simply) and teaching theory is the
way to go (I think this is MIT's approach); I really don't know.  None of the
current languages seem very good for an introduction (sorry, Mr. Kernighan and
Mr. Ritchie :-)).
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

karthur@codas.att.com (Kurt_R_Arthur) (01/23/88)

In article <3473@ihlpf.ATT.COM> nevin1@ihlpf.ATT.COM (00704A-Liber) writes:

> way to go (I think this is MIT's approach); I really don't know.  None of the
> current languages seem very good for an introduction (sorry, Mr. Kernighan and
> Mr. Ritchie :-)).

I'm running the risk of another holy war here, but REXX (IBM's system command
interpreter language for VM/CMS, now a part of SAA & due to be ported through
out IBM's architectures) seems to be a very good 'first language' because it
has access to the full range of OS commands, permits very good structured
programming techniques a la C (in fact, I've done prototyping for C using
Personal REXX with good results), is 'wordy' enough to be comprehensible to a
novice and has a tremendous trace function, allowing several different methods
of looking at the parsing of the statements.  REXX is also interpreted rather
than compiled, allowing immediate viewing of results.

I know that REXX doesn't do a whole lot of good for UNIX/VAX aficionados, but
if it does get a following because of its SAA standing, maybe someone'll do a 
port.


Just doing my part to start another war....

Kurt Arthur
Software Services of Florida, Inc.

nevin1@ihlpf.ATT.COM (00704A-Liber) (01/23/88)

In article <11348@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes:
>In article <4186@eagle.ukc.ac.uk> "H.A.Shaw" <has@eagle.ukc.ac.UK> writes:
>>I wholeheartedly agree, and hope I write better C
>>programs now for three years of BASIC/PASCAL/FORTRAN/FORTH first.
>>They did teach [C] to third year Computer Scientists sometimes.
>
>This is much too late.  Computer education should proceed from a
>hardware overview to machine language to assembler language to low-
>level compiled languages on up to high-level compiled languages.
>Teaching BASIC/Pascal/FORTRAN/Forth/etc first is like teaching algebra
>before arithmetic.

Yes, but arithmetic is usually first taught without logic and the axioms of
arithmetic.  If you started your mathematics career with only the Successor
function and the few other rules you need to define arithmetic, I don't think
you would have gotten very far.  Analagously,
try teaching someone how to write a exponentiation routine with a
Turing machine (or another simplistic model of a computer).  (Just wondering:
if I wanted to drive a car would you make me build all the parts for the car
and then build the car first? :-))

Unless you have a
higher level concept of what things like lists, queues, and stacks are,
programming in assembler is extremely tough.  There are no data structures in
assembler, and this makes it tough to do any kind of non-trivial programming.
HLLs are much better at learning the fundamentals of data structures and
thinking abstractly.

>BASIC is a bad joke.  The bad habits that it imparts on students are
>particularly hard to unlearn (first impressions are lasting
>impressions).  It oversimplifies the hardware-software interface to
>the point where it seems, to the student, to be performing magic.  C
>on the other hand, is more transparent.  It allows the student to see
>the gears turning.

Unfortunately, the many of the bad habits one picks up in BASIC one also picks
up in assembler.  One of the major habits is un-structured programming.  That
is why people have a hard time going from BASIC to Pascal (for instance); the
same problem would happen going from assembler to Pascal.

Also, many of the manipulations that can be done in assembler should not
usually be done in a HLL.  About 7 years ago, I disassembled the BASIC ROMs on
my TRS-80 Model I.  I noticed a curious piece of code (which I will pseudocode
here):

0998	LOAD	(C), 0
1000	LOAD	(AB), 0112
1003	LOAD	(AB), 0212
1006	LOAD	(AB), 0312
1009	real stuff

which pseudoassembles to:
0998	12
0999	00
1000	24
1001	12
1002	01
1003	24
1004	12
1005	01
1006	24
1007	12
1008	03
1009	real stuff

And I also found statements
JMP	0998
JMP	1001
JMP	1004
JMP	1007

They were taking advantage of the fact the the 12 in 12xx in the operand field
was also the operator for LOAD (C)!  They were jumping in to the middle of
instructions (hmm... maybe this should be an argument against BASIC.  After
all, this is for an implementation of BASIC :-))

Also, machine language allows self-modifying code, which is a no-no by today's
standards.  Although some modern architectures do not allow you to do this
because of pipelining and other reasons, this is not a problem with the machine
language itself but a fault of the designing hardware for speed purposes.


Machine language is NOT the place to start learning about computers or to
program them.  HLLs have too many advantages over machine languages.  But you
are right, BASIC is not a good place to start.  What is, I don't know.  Maybe
someone out in netland does.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

mason@tmsoft.UUCP (Dave Mason) (01/23/88)

In article <3473@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
>In article <11348@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes:
>>In article <4186@eagle.ukc.ac.uk> "H.A.Shaw" <has@eagle.ukc.ac.UK> writes:
>>>I wholeheartedly agree, and hope I write better C
>>>programs now for three years of BASIC/PASCAL/FORTRAN/FORTH first.
>>>They did teach [C] to third year Computer Scientists sometimes.
It's not clear to me that BASIC & FORTH (or even FORTRAN) are any
improvement over C.  None of them allow software engineering style,
top-down program design.  (Of course this is a generalization, with
the right FORTH environment, or a modern structured BASIC, this could be
less true).  It took me YEARS to unlearn the junk programming
practices that I developed using Basic & Fortran IV.

>>This is much too late.  Computer education should proceed from a
>>hardware overview to machine language to assembler language to low-
>>level compiled languages on up to high-level compiled languages.
>I don't know if this is the best way to learn computer programming.  Without
>any previous experience, I think it would be extremely difficult to impossible
>to debug a machine language program (although I do, I know that not everybody
>in the world grasps logic easily).
We (Ryerson) used to teach S/370 assembler as the first programming
language.  This had a very high failure rate, but those who made it
through that first year had a very good understanding of data flows,
etc. in the machine.  Unfortunately their programming style stank (for
the most part) (by 4th year when I saw them).  They had little idea of
how to structure a problem.  We then taught PL/1 for 2 or 3 years,
which wasn't so great either...program structure improved, but PL/1 is
such a big, ugly language.  Then we started using PASCAL, and
supplementing it with an intro Computer Organizatin course.  This is
the best combination so far, but I'm lobbying to change to LOGO
(non-graphic) supplemented with the Organization course.

>>BASIC is a bad joke.  The bad habits that it imparts on students are
>>particularly hard to unlearn (first impressions are lasting
>>impressions).
YES!  I'd rather they'd never seen a computer before my 1st year course.
>>  It oversimplifies the hardware-software interface to
>>the point where it seems, to the student, to be performing magic.  C
>>on the other hand, is more transparent.  It allows the student to see
>>the gears turning.
But there's so d**m much detail to keep track of (all 12 levels of
precedence and 40+ operators).  I think it obscures the logic too
much.  First year students find PASCAL syntax confusing, I see no
reason to increase the problem by switching to C!

> I don't know what the best language to start
>with is, but I don't think the bottom-up approach (i.e., starting with machine
>language) has enough benefits to outweigh the problems.  Maybe starting with
>Lisp (a language which can be described very simply) and teaching theory is the
>way to go (I think this is MIT's approach); I really don't know.
I basically agree. Brian Harvey (LOGO book authour) suggests that they
should learn a Lisp dialect (Scheme, LOGO, Common?) and an assembler
like C, and then pick up any remaining languages when and as necessary
for a particular problem.

ok@quintus.UUCP (Richard A. O'Keefe) (01/23/88)

In article <1616@codas.att.com>, karthur@codas.att.com (Kurt_R_Arthur) writes:
> I'm running the risk of another holy war here, but REXX (IBM's system command
> interpreter language for VM/CMS, now a part of SAA & due to be ported through
> out IBM's architectures) seems to be a very good 'first language' because it
> has access to the full range of OS commands, permits very good structured
> programming techniques a la C (in fact, I've done prototyping for C using
> Personal REXX with good results), is 'wordy' enough to be comprehensible to a
> novice and has a tremendous trace function, allowing several different methods
> of looking at the parsing of the statements.  REXX is also interpreted rather
> than compiled, allowing immediate viewing of results.

I think the Bourne shell is pretty bad as a programming language,
and the C shell is worse, but REXX out-bads the lot.  I do not understand
why "has access to the full range of OS commands" is thought to be a
virtue of a FIRST language.  If it comes to that, so has C, ever heard of
system()?  This is the only property of REXX which is not also a property
of Lisp, and Lisp is a much cleaner language.

In order to understand REXX, you have to understand quite a lot of rather
subtle things, and most importantly, you have to be happy with a language
that shifts under your feet.  (According to the SAA manual, some of the
control structures, such as SELECT, are *not* available in OS/2...)

"Interpreted rather than compiled" is quite independent of "allowing
immediate viewing of results".  For example, Pop-2 is a compiled interactive
langauge.  Type in
	define f(a,b);
	    [% a+b, a-b %]
	enddefine;
and this is *compiled*.  Then type
	pr(f(42, 27));
and	[69 15]
comes out at once.

The Centrum voor Wiskunde in Informatike [spelling?] in Amsterdam has
been working on a first language (called "Beta") for several years.
Does anyone know what they have come up with?

Everyone seems to recommend as a first language a language he happens
to like.  I'd be happy teaching programming with Lisp or Pop2.  But
that tells you more about me than about Lisp or teaching programming!
Does anyone have any EVIDENCE about what makes a better first language?
The kind of thing I'd like to see is a task analysis for programming,
an analysis of several programming languages in terms of how easy they
make it to explain the various subtasks, and some sort of experimental
evidence that the analysis was right.

All things considered, the University of Toronto's "Turing" language
looks like being a reasonable first language.  Is there anyone reading
this who has used Turing?  Comments on it?

cik@l.cc.purdue.edu (Herman Rubin) (01/24/88)

In article <3487@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704A-Liber) writes:
> In article <11348@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes:
> >In article <4186@eagle.ukc.ac.uk> "H.A.Shaw" <has@eagle.ukc.ac.UK> writes:

> >This is much too late.  Computer education should proceed from a
> >hardware overview to machine language to assembler language to low-
> >level compiled languages on up to high-level compiled languages.
> >Teaching BASIC/Pascal/FORTRAN/Forth/etc first is like teaching algebra
> >before arithmetic.

I would definitely teach algebraic _notation_ before arithmetic.  The
use of symbols for quantities is a great invention, comparable to the
invention of pronouns.  However, I would not teach any subject without
teaching the concepts first.  Unfortunately, I do not know of any subject
taught in this manner.  (It is very difficult for someone who has had a
statistical methods course to be able to grasp the assumptions involved
in a statistical situation.)  

> Yes, but arithmetic is usually first taught without logic and the axioms of
> arithmetic.  If you started your mathematics career with only the Successor
> function and the few other rules you need to define arithmetic, I don't think
> you would have gotten very far. 

Unfortunately, you are right; the arithmetic teachers cannot understand them.
What are you criticizing?  One should start with the notion of successor, i.e.,
the idea of _counting_.  Then addition is _continuing the count_ and multipli-
cation is repeated addition.  After this is done, a child can understand that
using addition and multiplication tables speed the process, not that they are
new processes.  If arithmetic were taught this way, using symbolic notation,
we would have people who understand it  Do not confuse requiring that all
statements are proved (completeness) with requiring that all statements are
correct (rigor).  Also, starting with successor does not prevent the later
use of the cardinal approach, or extending to rational numbers, negative
numbers, real numbers, complex numbers, etc.

> Analagously,
> try teaching someone how to write a exponentiation routine with a
> Turing machine (or another simplistic model of a computer).

That a Turing machine can do everything a computer can do does not make it
necessarily the only simple model of a computer, any more than the understand-
ing of arithmetic starting from counting precludes the use of place notation
and addition and multiplication tables.

> Unless you have a
> higher level concept of what things like lists, queues, and stacks are,
> programming in assembler is extremely tough.  There are no data structures in
> assembler, and this makes it tough to do any kind of non-trivial programming.
> HLLs are much better at learning the fundamentals of data structures and
> thinking abstractly.

I do not consider lists, queues, and stacks as any more abstract than overflow,
GOTO, and the hardware organization of items.  Data structures should be added
to the assembler; the HLL syntax, including weak typing, should be added.  
Macros of the form 
	X = Y + Z
and
	Q,R = M / N
should be added.  Start with what the hardware can do and proceed accordingly.

> One of the major habits is un-structured programming.  

I can give you examples where GOTOs are the simple thing to do, and the
"structured" alternatives are much more complex.  Structured programming
can block thinking of the efficient way to do things.
 
> Also, machine language allows self-modifying code, which is a no-no by today's
> standards.  

That you can cut yourself by using a knife does not mean knives should not be
used.  If self-modifying code is the thing to do, do it!

> Machine language is NOT the place to start learning about computers or to
> program them.  HLLs have too many advantages over machine languages.  

From the discussions I have seen, starting with machine languages _may_ be
more difficult.  However, I believe that for each person who has problems
starting with even the bad machines languages, dozens who start with the
HLLs will never be able to understand how to program anything that their
HLL does not support.
-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

skh@hpclskh.HP.COM (01/26/88)

>>In article <11348@brl-adm.ARPA> dsill@NSWC-OAS.arpa (Dave Sill) writes:
>>In article <4186@eagle.ukc.ac.uk> "H.A.Shaw" <has@eagle.ukc.ac.UK> writes:
>>>I wholeheartedly agree, and hope I write better C
>>>programs now for three years of BASIC/PASCAL/FORTRAN/FORTH first.
>>>They did teach [C] to third year Computer Scientists sometimes.
>>
>>This is much too late.  Computer education should proceed from a
>>hardware overview to machine language to assembler language to low-
>>level compiled languages on up to high-level compiled languages.
>>Teaching BASIC/Pascal/FORTRAN/Forth/etc first is like teaching algebra
>>before arithmetic.
>
>Unless you have a
>higher level concept of what things like lists, queues, and stacks are,
>programming in assembler is extremely tough.  There are no data structures in
>assembler, and this makes it tough to do any kind of non-trivial programming.
>HLLs are much better at learning the fundamentals of data structures and
>thinking abstractly.

You are completely correct, as far as I am concerned.  The whole process
of software engineering (the fancy name for programming) really takes place
at a *MUCH* higher level than the machine.  To write a really large product
(which is NOT done in any class) requires machine knowledge only after you get
down to the gritty details of how the product works.  And it is designing the
PRODUCT, not the implementation, where so many people fail.  A thorough
knowledge of programming constructs and data structures allows one to 
concentrate on the task, knowing that one can program the thing without
worrying about too much detail (i.e. the basis of top-down programming).

>
>>BASIC is a bad joke.  The bad habits that it imparts on students are
>>particularly hard to unlearn (first impressions are lasting
>>impressions).  It oversimplifies the hardware-software interface to
>>the point where it seems, to the student, to be performing magic.  
>
>Unfortunately, the many of the bad habits one picks up in BASIC one also picks
>up in assembler.  One of the major habits is un-structured programming.  That
>is why people have a hard time going from BASIC to Pascal (for instance); the
>same problem would happen going from assembler to Pascal.

How to start an argument...defend BASIC. (No flames if you can help it)
First, I will admit to being on a team which implemented a BASIC interpreter
and compiler.  Second, this is no "ordinary" BASIC...it is an operating
system unto itself, built on top of a larger system (i.e. it's not for PC's).
Third, like many others, I learned BASIC first and had to unlearn the bad
stuff.
BUT...there are now several powerful, structured BASIC languages in existance.
Some of these have interpreters, some have record structures and pointers.
I think it is a shame that these languages exist only on larger machines.
They would make very good first languages.  WHY? (you ask laughingly :-)
Think how easy BASIC was to use when you learned it...there were lots of silly
details you could ignore (like declaring everything under the sun).  Why should
you care about that? It's just an artifact of computer languages to a beginner.
(But not to a compiler, and not to those of us who have learned more :-)
If the BASIC has structured statements, GOTO is not needed, and need not be
taught (just as most instructors fail to mention that PASCAL has a GOTO).
And if an interpreter is available, the beginner can REALLY see how a program
works! (NOTE: By interpreter, I *DO NOT* mean one in which you can trace and
change variables.  I *DO* mean one which allows program changes on the fly,
plus all the tracing.  The less power the interpreter has, the more difficult
and useless it becomes.  My own opinion is that interpreters are great for
development, but have a compiler to get the speed.)
In my own experience, people who have not programmed before can grasp the 
simple concepts that BASIC can present.  and they can see the results.  I have
found that LISP, and compile-only languages, take longer to learn, and force
the student to concentrate not on the problem to be solved, but the syntax and
semantics of the language.

If one intends to teach a LANGUAGE course, concentrate on the language.  If
one intends to teach a BEGINNING programming course, find an easy language.
BASIC qualifies...though if I were teaching, it would have to be structured.

"'nuff said"
						skh

pds@quintus.UUCP (Peter Schachte) (01/27/88)

In article <3473@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704A-Liber) writes:
> Maybe starting with
> Lisp (a language which can be described very simply) and teaching theory is the
> way to go (I think this is MIT's approach); I really don't know.  None of the
> current languages seem very good for an introduction (sorry, Mr. Kernighan and
> Mr. Ritchie :-)).

Syracuse University's introductory programming course for CS majors
uses Lisp (at least it did when I was there).  I found this to be a
good approach.  I think it's pretty important that an introductory
course use an interpreted language, so users don't have to start out by
learning too much extraneous stuff, like running compilers.  And being
able to type in a fragment and execute it is helpful in getting started
quickly.  Once budding programmers have learned to be precise in
expressing themselves, and to think through what a program means, THEN
make them learn about things like syntax, and where semicolons go, etc.

And you shouldn't be sorry to K&R.  C wasn't meant to be a teaching
language, Pascal was.  And I think Pascal IS a better language for
teaching.  (Please, no flames about the UTILITY of Pascal relative to
C, just TEACHABILITY (learnability).)  C is more practical for
real-world programming.  So teach Lisp first, then Pascal, then C. THEN
teach assembly language.  THEN hardware.  The fewer details you make
students master, the better they'll do.  So start with simple concepts,
like functions, and build up to pointer manipulation and such.
-- 
-Peter Schachte
pds@quintus.uucp
...!sun!quintus!pds

kers@otter.hple.hp.com (Christopher Dollin) (01/28/88)

Peter Schachte says:

> I think it's pretty important that an introductory
> course use an interpreted language, so users don't have to start out by
> learning too much extraneous stuff, like running compilers.

repeat 1e4 times
    'Compiled languages NEED NOT be non-incremental\n'.pr
endrepeat;

The assumtion in Peter's note seemed to be that it was the fact that the Lisp
was INTERPRETED which was important for teaching purposes. In fact 
interpretation has little to do with it - it's the ability to build programs
incrementally. An incremental compiler will do the trick

Proof by existance - Poplog. All of Pop11, Prolog, Common Lisp, and ML run
COMPILED in this environment, not interpreted, but you can develop programs
incrementally, redefine procedures, etc.

Oh, I suppose you don't get as much fancy single-stepping with compiled code.
Don't seem to miss it ... 





Regards,
Kers                                    | "Why Lisp if you can talk Poperly?"

hydrovax@nmtsun.nmt.edu (M. Warner Losh) (01/29/88)

Christopher Dollin writes:
> Peter Schachte says:
> 
> > I think it's pretty important that an introductory
> > course use an interpreted language, so users don't have to start out by
> > learning too much extraneous stuff, like running compilers.
> 
But they still have to learn how to use the bloody interpreters.  Then they
forget what they learned when they go to a compiled language.  If you are
worried about a user not being able to handle the typical two to three
step process to compile, then write a shell script (As I did on VMS for
some old DEC-20 users).  It seems to me that an interpreter need these
same steps
	1. Start the interpreter	Compile your source.
	2. load your program		Link program (may be part of 1).
	3. Run your program		Run your program.

Looks like the same number of steps to me.  What you do loose in a compiled
environment is the ability to type a simple sequence of instructions (lines
of code if you will) into the computer.  This isn't entirely true, you could
place the small number of lines in a file called test1 or something like that
and compile it to see what happens.

> Oh, I suppose you don't get as much fancy single-stepping with compiled code.
> Don't seem to miss it ... 
> 
OH?  The debugger on VAX/VMS seems to handle source code single stepping in
a screen mode quite well.  As does dbx and dbxtool in Berkley Unix.  I know
that in the VMS debugger that you can evaluate expressions, set break points,
set watch points (tell me when variable X is changed), etc.  Since you have
to learn how to use a debugger ANYWAY, I would rather learn one that I can
use with compiled (upper level) languages, then learn one at the start of
my college career and another part way through.


-- 
bitnet:	lush@nmt.csnet			M. Warner Losh
csnet:	warner%hydrovax@nmtsun
uucp:	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!warner%hydrovax
	...{cmcl2, ihnp4}!lanl!unmvax!nmtsun!hydrovax
Warning:  Hydrovax is both a machine, and an account, so be careful.

nevin1@ihlpf.ATT.COM (00704a-Liber) (01/30/88)

In article <666@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
>Nevin Liber said:
>> Analagously,
>> try teaching someone how to write a exponentiation routine with a
>> Turing machine (or another simplistic model of a computer).
>
>That a Turing machine can do everything a computer can do does not make it
>necessarily the only simple model of a computer, any more than the understand-

Where in that statement did I say that a Turing machine was the ONLY simplistic
model of a computer??  As previously stated, I was making an analogy and not
defining abstract models of computers.  As a matter of fact, I implied that
there ARE other models for computers.

>> Unless you have a
>> higher level concept of what things like lists, queues, and stacks are,
>> programming in assembler is extremely tough.  There are no data structures in
>> assembler, and this makes it tough to do any kind of non-trivial programming.
>> HLLs are much better at learning the fundamentals of data structures and
>> thinking abstractly.
>
>I do not consider lists, queues, and stacks as any more abstract than overflow,
>GOTO, and the hardware organization of items.  Data structures should be added
>to the assembler; the HLL syntax, including weak typing, should be added.  
>Macros of the form 
>	X = Y + Z
>and
>	Q,R = M / N
>should be added.  Start with what the hardware can do and proceed accordingly.

In order to add things like data structures and weak typing, you have to either
build a more complicated architecture for a CPU and consequently add many more
instructions to the machine language (what do the RISC folks think about that?)
or restrict the assembly language so that it cannot be programmed to do
everything possible on that machine.  The latter should not be called assembly
language.

Typing is almost meaningless in assembly.  What is the difference to the
machine between a 4-byte float and a 4-byte int?  Nothing.  It is what we, the
users of the machine think of those 4-byte values.

Also, adding things like infix macros detract from the notion of what is really
going on in the hardware (which is the reason this whole subject was brought up
in the first place).  There are languages around that satisfy your criterion (I
think B, the predecessor to C, is one of them, but I'm not sure); if you think
one of those languages would be good as a first language, then state your case.
But please don't try to muck up assembly language; it is fine as it is for what
people usually program in it for.

>> One of the major habits is un-structured programming.  
>
>I can give you examples where GOTOs are the simple thing to do, and the
>"structured" alternatives are much more complex.  Structured programming
>can block thinking of the efficient way to do things.

Please post some examples of problems (not solutions that are already
implemented using GOTOs) where structured alternatives are 'much more' complex.
IF many of these problems exist, I would like to discuss how we can 'fix' the
structured languages to handle them more easily.

>> Also, machine language allows self-modifying code, which is a no-no by today's
>> standards.  
>
>used.  If self-modifying code is the thing to do, do it!

This is one of the differences between hacking and programming :-)!

Many operating systems will not allow you to modify code of a running system
(for example: SVR3 Unix).  Self-modifying, as well as non-reentrant code cannot
be shared; ie, if sh were not reentrant then every time you fork a new process
you would have to make a new copy of the entire executable for sh; our UNIX
machines would run out of memory (real and virtual) VERY quickly.

>> Machine language is NOT the place to start learning about computers or to
>> program them.  HLLs have too many advantages over machine languages.  
>
>From the discussions I have seen, starting with machine languages _may_ be
>more difficult.  However, I believe that for each person who has problems
>starting with even the bad machines languages, dozens who start with the
>HLLs will never be able to understand how to program anything that their
>HLL does not support.

This would be true IF these people only learn one language.  I did not propose
that they never learn assembler, just that it should not be the FIRST one they
are taught.  Programmers should learn assembly language sometime; but only after
they have developed some good programming techniques.  It is much harder to
'unteach' somebody than it is to teach somebody.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

cik@l.cc.purdue.edu (Herman Rubin) (02/01/88)

In article <3555@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704a-Liber) writes:
> In article <666@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
> >Nevin Liber said:
......
> >Macros of the form 
> >	X = Y + Z
> >and
> >	Q,R = M / N
> >should be added.  Start with what the hardware can do and proceed accordingly.
> 
> In order to add things like data structures and weak typing, you have to either
> build a more complicated architecture for a CPU and consequently add many more
> instructions to the machine language (what do the RISC folks think about that?)
> or restrict the assembly language so that it cannot be programmed to do
> everything possible on that machine.  The latter should not be called assembly
> language.

I am in no way advocating restricting the assembly language on any machine.  
There is nothing in my postings to indicate that I favor RISC; I have stated
that computer hardware should be versatile, and I consider the present CISC
machines as RISCy.

Most assembly languages are prenex, that is, the instruction comes first.  This
is what makes assembly difficult to read and write.  The assembler language,
COMPASS, on the CDC6x00 and the related CYBERs, is slightly prenex in that
the class of the instruction (integer, floating, "double", Boolean, increment,
etc.) is prenex, and the rest is mainly infix, although "," separators are
sometimes used.  I have used this language extensively.  The assembly
language on the CRAYs, CAL, uses very little of the prenex form, but 
requires that the class of the operator be included.  It is also rather
artificial in many places.  

> Typing is almost meaningless in assembly.  What is the difference to the
> machine between a 4-byte float and a 4-byte int?  Nothing.  It is what we, the
> users of the machine think of those 4-byte values.

Here is the place that the advocates of the present clumsy assemblers fail to
see the possibilities.  A given location, either register or memory, is a
collection of bits.  How the collection will be used is, indeed, up to the
programmer.  Now in HLLs we _declare_ the "type" assigned to that location.
Some languages, unfortunately, require that the type be inviolable; this is
generally called strong typing.  Some languages provide inadequate means of
allowing the programmer to change the type of something in memory; it is
extremely difficult for the user to change the type of something in registers.

What I am proposing is that an argument, either operand or result,  recognizable
by machine operations be typable by the user.  Then if the types of the
arguments are compatible with a version of the operator, that version is
used.  Thus on the VAX there are numerous move and convert instruction;
most of them would become

	X = Y

In some there can be a modification of the instruction, such as complementing
or negating, or restrictions can be put on sign extension, etc.  This would be
done by modifying the "=".  Only if we wish to perform a version of the move
which is not appropriate for the types of X and Y would the type symbols be
affixed to the "=" or its augmentation.  This would then become an explicit
unoverloading of the operation, while permitting normal overloading.  Notice
that typing would, in general, be required of all arguments.  Looking at the
VAX instructions with this in mind, I found 16 types, some of which may be
represented by disconnected pieces of storage (register or memory).

Clearly the programmer must be able to change the type of an entity at will.
This is not the cast operation in C; it is rather a _use_ operation.  The
meaning is either that the old type is no longer in use, which can with
difficulty be implemented in the present HLLs, or else it can be a statement
to the system, "I know you do not understand what I am doing, but remember
that you are supposed to do what I tell you."
 
> Also, adding things like infix macros detract from the notion of what is really
> going on in the hardware (which is the reason this whole subject was brought up
> in the first place).  There are languages around that satisfy your criterion (I
> think B, the predecessor to C, is one of them, but I'm not sure); if you think
> one of those languages would be good as a first language, then state your case.

> But please don't try to muck up assembly language; it is fine as it is for what
> people usually program in it for.

I am not "mucking it up," unless you are committed to operation-space-
comma separated argument list.  I have already pointed out that there are
assemblers not in this form.  If you append the type symbols to the operation
symbols, this is essentially the CAL syntax.  I see no reason why someone
programming with the full set of machine instructions need be perturbed by
infix notation, already used by some assemblers, and overloaded operators.
I would object to not allowing the programmer to include the type symbols,
as this would run into the weaknesses of strongly typed languages.

I admit it would be difficult for a _disassembler_ to have any of the
flexibility I would like--it might even be desirable for a disassembler
to _always_ specify the types.

> >> One of the major habits is un-structured programming.  
> >
> >I can give you examples where GOTOs are the simple thing to do, and the
> >"structured" alternatives are much more complex.  Structured programming
> >can block thinking of the efficient way to do things.
> 
> Please post some examples of problems (not solutions that are already
> implemented using GOTOs) where structured alternatives are 'much more' complex.

Of course, we can always replace a GOTO by "if TRUE then ..."  Notice the word
_efficient_ in my previous posting.  Suppose (and this is an actual case) we
have an algorithm which has an integer state, and there are stacks, which we
can guarantee do not become empty within the procedure if the integer state is
small enough.  Now we can do things by the usual case statements, but it will
drastically slow down the algorithm.  Until the integer state is reduced to 1,
processing occurs; should we put surplus material back on the appropriate
stack(s), store the new value of the integer, and go through the case procedure
at each stage, or should we use GOTOs, not even store the value of the integer
unless it is large (a rare occurrence), and keep our surplus material at hand
by going to an intermediate stage of the code for the new integer?  If you tell
me to get around this by using a better algorithm, I now inform you that the
algorithm uses on the average 4.4 _bits_ of information before proceding to
the store stage, and this includes getting the original integer state.  This
is not optimal, but it cannot be improved much by any practical coding scheme.

I know of no hardware which does not internally use GOTOs.  There are hardware 
implementations of conditional transfers on some machines which will make a
simple test in the transfer instruction, but in nanocode this is: make the
test; then transfer if the test succeeds (fails).  In other words, the machine
must have an internal GOTO.  If we want to understand the machine, we must,
therefore, have GOTO.

> IF many of these problems exist, I would like to discuss how we can 'fix' the
> structured languages to handle them more easily.
> 
> >> Also, machine language allows self-modifying code, which is a no-no by today's
> >> standards.  
> >
> >used.  If self-modifying code is the thing to do, do it!
> 
> This is one of the differences between hacking and programming :-)!
> 
> Many operating systems will not allow you to modify code of a running system
> (for example: SVR3 Unix).  Self-modifying, as well as non-reentrant code cannot
> be shared; ie, if sh were not reentrant then every time you fork a new process
> you would have to make a new copy of the entire executable for sh; our UNIX
> machines would run out of memory (real and virtual) VERY quickly.

There are obviously situations in which code cannot be self-modifying.  There 
are conditions in which certain loops or stack structures cannot be used if
certain parts of the machine state are being shared.  That does not mean that
self-modifying code should never be used.

> >> Machine language is NOT the place to start learning about computers or to
> >> program them.  HLLs have too many advantages over machine languages.  
> >
> >From the discussions I have seen, starting with machine languages _may_ be
> >more difficult.  However, I believe that for each person who has problems
> >starting with even the bad machines languages, dozens who start with the
> >HLLs will never be able to understand how to program anything that their
> >HLL does not support.
> 
> This would be true IF these people only learn one language.  I did not propose
> that they never learn assembler, just that it should not be the FIRST one they
> are taught.  Programmers should learn assembly language sometime; but only after
> they have developed some good programming techniques.  It is much harder to
> 'unteach' somebody than it is to teach somebody.

This is exactly why teaching HLL first is bad.  The student gets the impression
that the machine behaves like the HLL.  Only a badly designed machine has an
if...then...else structure.  Machines have operations of varying complexity;
the student who gets the impression that the structure of the machine looks
like the HLL certainly has a lot to unlearn!

-- 
Herman Rubin, Dept. of Statistics, Purdue Univ., West Lafayette IN47907
Phone: (317)494-6054
hrubin@l.cc.purdue.edu (ARPA or UUCP) or hrubin@purccvm.bitnet

nevin1@ihlpf.ATT.COM (00704a-Liber) (02/02/88)

In article <670@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
.
.Most assembly languages are prenex, that is, the instruction comes first.  This
.is what makes assembly difficult to read and write.  The assembler language,
.COMPASS, on the CDC6x00 and the related CYBERs, is slightly prenex in that
.the class of the instruction (integer, floating, "double", Boolean, increment,
.etc.) is prenex, and the rest is mainly infix, although "," separators are
.sometimes used.  I have used this language extensively.  The assembly
.language on the CRAYs, CAL, uses very little of the prenex form, but 
.requires that the class of the operator be included.  It is also rather
.artificial in many places.  

(CYBER--isn't that the machine that used 56 bit words? :-))

Looking at a variety of assembly languages (68k, Z80, PDP11), it looks like
most of the operators where infix would be applicable would become augmented
assignment operators, which I find a lot harder to read than prenex form.  If
augmented operators are not used, then the LHS of the assignment must be
repeated exactly as the first item of the RHS of the expression: ex: PDP-11

ADD	(R0), (R0)+	;add what R0 points to to itself and inc R0
non-augmented:	(R0) = (R0) + (R0)+	;and remember, the inc is done after
					;assignment; also, this 'addition' is
					;not commutative.
augmented:	(R0) += (R0)+		;harder to read than original

.Here is the place that the advocates of the present clumsy assemblers fail to
.see the possibilities.  A given location, either register or memory, is a
.collection of bits.  How the collection will be used is, indeed, up to the
.programmer.  Now in HLLs we _declare_ the "type" assigned to that location.
.Some languages, unfortunately, require that the type be inviolable; this is
.generally called strong typing.  Some languages provide inadequate means of
.allowing the programmer to change the type of something in memory; it is
.extremely difficult for the user to change the type of something in registers.
.
.What I am proposing is that an argument, either operand or result,  recognizable
.by machine operations be typable by the user.  Then if the types of the
.arguments are compatible with a version of the operator, that version is
.used.  Thus on the VAX there are numerous move and convert instruction;
.most of them would become
.
.	X = Y
.
.In some there can be a modification of the instruction, such as complementing
.or negating, or restrictions can be put on sign extension, etc.  This would be
.done by modifying the "=".  Only if we wish to perform a version of the move
.which is not appropriate for the types of X and Y would the type symbols be
.affixed to the "=" or its augmentation.  This would then become an explicit
.unoverloading of the operation, while permitting normal overloading.  Notice
.that typing would, in general, be required of all arguments.  Looking at the
.VAX instructions with this in mind, I found 16 types, some of which may be
.represented by disconnected pieces of storage (register or memory).
.
.Clearly the programmer must be able to change the type of an entity at will.
.This is not the cast operation in C; it is rather a _use_ operation.  The
.meaning is either that the old type is no longer in use, which can with
.difficulty be implemented in the present HLLs, or else it can be a statement
.to the system, "I know you do not understand what I am doing, but remember
.that you are supposed to do what I tell you."

First off, changing all the MOV statements to 'X = Y' do have reprocussions:
the language would have to be 'compiled', not 'assembled', since I no longer
know what statements are actually being executed.  If I need to do
time-sensitive operations, your language is out because I need to get to the
hardware instructions (but assembler is supposed to represent 1:1 the hardware
instructions).  Your 'do what I tell you' statement means to me:  now I want to
program in assembler and not this pseudo slightly higher level language.  To do
any real assembler work, you HAVE to turn on your 'do what I tell you' switch.

On register machines most operations are done in registers.  In order to
implement your suggestion, registers would have to be typed (although the type
can be changed).  The typing restrictions cannot always be enforced, due to
branching and/or jumping to calculated locations or even jumping into the
operand of an instruction (this is frowned upon but possible).

.I am not "mucking it up," unless you are committed to operation-space-
.comma separated argument list.  I have already pointed out that there are
.assemblers not in this form.  If you append the type symbols to the operation
.symbols, this is essentially the CAL syntax.  I see no reason why someone
.programming with the full set of machine instructions need be perturbed by
.infix notation, already used by some assemblers, and overloaded operators.
.I would object to not allowing the programmer to include the type symbols,
.as this would run into the weaknesses of strongly typed languages.

It is easier to me to use ADDB, ADDW, and ADDL to mean the byte, word, and long
adds, respectively, than to augment the already augmented assignment operators.
I find it much easier to read and easier to find bugs (especially when you have
code that jumps around all over the place).  If the architecture lends itself
to infix operators, then use them.  But do not claim that they are better than
prenex operators for all assembly languages.

.I admit it would be difficult for a _disassembler_ to have any of the
.flexibility I would like--it might even be desirable for a disassembler
.to _always_ specify the types.

This is because you want an uncompiler, not a disassembler.  You have defined a
language which is a level above assembler.  This is like trying to convert from
assembler to Pascal; a very difficult task, at best.

.> >> One of the major habits is un-structured programming.  
.> >
.> >I can give you examples where GOTOs are the simple thing to do, and the
.> >"structured" alternatives are much more complex.  Structured programming
.> >can block thinking of the efficient way to do things.
.> 
.> Please post some examples of problems (not solutions that are already
.> implemented using GOTOs) where structured alternatives are 'much more' complex.
.
.Of course, we can always replace a GOTO by "if TRUE then ..."  Notice the word
._efficient_ in my previous posting.  Suppose (and this is an actual case) we

I noted the word.  What do you mean by 'efficient'?  (I have deleted your
example since I have not had time to look at it.  I will comment on it later.)

.I know of no hardware which does not internally use GOTOs.  There are hardware 
.implementations of conditional transfers on some machines which will make a
.simple test in the transfer instruction, but in nanocode this is: make the
.test; then transfer if the test succeeds (fails).  In other words, the machine
.must have an internal GOTO.  If we want to understand the machine, we must,
.therefore, have GOTO.

Yes, but do you really need to know that in your first programming language
(the original topic of this discussion)?  It is very hard to learn structured
programming after using GOTO, since attacking a problem via a structured method
usually requires a different way of looking at it.  And GOTO can be understood
by looking at a block diagram of how a WHILE loop works.  Need you actually be
able to use a GOTO statement in order to understand how it works?  I would
rather see someone go from a structured environment to using branching than the
other way around.

A side comment:  The structure that Pascal imposes is far too rigid.  C
statements like 'break', 'continue', and 'return' are necessary; otherwise, far
too much time is spent trying to make algorithms 'fall off the end'.

.This is exactly why teaching HLL first is bad.  The student gets the impression
.that the machine behaves like the HLL.  Only a badly designed machine has an
.if...then...else structure.  Machines have operations of varying complexity;
.the student who gets the impression that the structure of the machine looks
.like the HLL certainly has a lot to unlearn!

With the possible exception of programming on a PC, most of the 'controlling of
the hardware' is done via macros and system calls.  What's the difference
whether I make the calls from assembler or C; I am still faced with the same
restrictions.  I don't get the 'feel' of the machine since all I am doing is
telling some other routine to go do the hardware stuff for me.

Your if-then-else statement:  By your statement most machines are badly
designed since most contain conditional branching statements; ie, IF certain
flags are set/reset THEN branch somewhere ELSE go on to the next statement.

Even if it can be concluded that learning assembler first is better (a
conclusion I do not believe in), your language (what you think assembler should
be) also detracts from how the machine really work; ie, machine memory
locations don't really have type, etc.


I do not believe that, when first learning how to program, that many people
believe that their machine acts just like their HLL program.  They consider
'write()' statements in Pascal, for instance, to be 'black boxes' that put
their output on the screen.  There is no need to initially know what is in that
black box in order to use it.  When the programming concepts, such as
structure, are already laid down, then it is time to learn to program in
assembler; the benefits far outway the drawbacks.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

lee@uhccux.UUCP (Greg Lee) (02/08/88)

In article <3579@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704a-Liber,N.J.) writes:
>In article <670@l.cc.purdue.edu> cik@l.cc.purdue.edu (Herman Rubin) writes:
>.
>.Most assembly languages are prenex, that is, the instruction comes first. This
>.is what makes assembly difficult to read and write.  The assembler language,
>....
>.programmer.  Now in HLLs we _declare_ the "type" assigned to that location.
>...
>First off, changing all the MOV statements to 'X = Y' do have reprocussions:
>the language would have to be 'compiled', not 'assembled', since I no longer
>know what statements are actually being executed.  If I need to do
>time-sensitive operations, your language is out because I need to get to the
>hardware instructions (but assembler is supposed to represent 1:1 the hardware
>instructions).
>...

A way to gain some of the readability of HLL's without giving up
the transparent semantics of assembly language is to use a preprocessing
translator with the properties:

	(1) legal assembly statements will be passed through
	    unaffected to the assembler, so that one can still
	    write in real assembly language, or partially in real
	    assembly language, when clarity demands this, and
	(2) the text transformations performed by the preprocessor
	    are sufficiently elementary that one can perform them
	    mentally if need be, to understand the import of a
	    piece of code.

I have such a tool for my Amiga, and I find it very helpful.  Here's
an example:

	define  snail  D1.B
	define  clips  D2.B
	byte    memvar
	byte    verf

	clips  =  memvar
	snail  =  clips
	snail  ?  verf
	!= {
		memvar += snail
	}

In the output file, the proprocessor produces:

 move.b .0001Q,D2
 move.b D2,D1
 cmp.b .0002Q,D1
 beq .0001
 add.b D1,.0001Q
.0001
.8001
   ...
 section webroom,bss
   ...
.0001Q DS.B 1
.0002Q DS.B 1
   ...
 end


Greg, lee@uhccux.uhcc.hawaii.edu

ray@micomvax.UUCP (Ray Dunn) (02/08/88)

In article <3487@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
 > ....  About 7 years ago, I disassembled the BASIC ROMs on my TRS-80 Model I
 > I noticed a curious piece of code (which I will pseudocode here):
 >
 > 0998	LOAD	(C), 0
 > 1000	LOAD	(AB), 0112
 > 1003	LOAD	(AB), 0212
 > 1006	LOAD	(AB), 0312
 > 1009	real stuff
 > ....
 > They were taking advantage of the fact the the 12 in 12xx in the operand
 > field was also the operator for LOAD (C)!  They were jumping in to the
 > middle of instructions ...

Without examining it too closely, it seems to me that it is MUCH more likely
that you are disassembling on the wrong boundaries than the code is jumping
into the middle of instructions!!  Interpreting binary dumps can be VERY
misleading!

Ray Dunn.  philabs!micomvax!ray

lee@uhccux.UUCP (Greg Lee) (02/17/88)

From article <903@micomvax.UUCP>, by ray@micomvax.UUCP (Ray Dunn):
> ...
> Without examining it too closely, it seems to me that it is MUCH more likely
> that you are disassembling on the wrong boundaries than the code is jumping
> into the middle of instructions!!  Interpreting binary dumps can be VERY
> misleading!
Oh, I don't think so.  This is a standard trick in 6502 programming.
The Basic interpreter on my Synertek SYM-1, Microsoft derived, I think,
is full of this.
	Greg, lee@uhccux.uhcc.hawaii.edu

nevin1@ihlpf.ATT.COM (00704a-Liber) (02/20/88)

In article <903@micomvax.UUCP> ray@micomvax.UUCP (Ray Dunn) writes:
>In article <3487@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704A-Liber,N.) writes:
>>
>> ....  About 7 years ago, I disassembled the BASIC ROMs on my TRS-80 Model I
>> I noticed a curious piece of code (which I will pseudocode here):
>> 0998	LOAD	(C), 0
>> 1000	LOAD	(AB), 0112
>> 1003	LOAD	(AB), 0212
>> 1006	LOAD	(AB), 0312
>> 1009	real stuff
>> ....
>> They were taking advantage of the fact the the 12 in 12xx in the operand
>> field was also the operator for LOAD (C)!  They were jumping in to the
>> middle of instructions ...
>
> Without examining it too closely, it seems to me that it is MUCH more likely
> that you are disassembling on the wrong boundaries than the code is jumping
> into the middle of instructions!!  Interpreting binary dumps can be VERY
> misleading!

I was NOT dissembling on the wrong boundaries!!  Let me explain the
circumstances which lead to this discovery and the reasons I think that they
coded it this way.  (Besides, what are the odds of finding what looks like
useful code if you disassemble on the wrong boundary??)  Please excuse any
Z80 notational problems in this; it's been about 5 years since I last
programmed in Z80 assembler. :-)


I was writing some assembler functions to be called from BASIC (via the usr()
function call, I think), and I needed to produce error messages in case the
input was bad, overflow occurred, etc.  I wanted these errors to be trapped
like all the other errors that a BASIC program could produce (ie, if
the user of this function had an "ON ERROR GOTO" statement in his program, the
program should jump there if an error occurred and the correct value should be
in ERR).  In order to do this correctly, I disassembled the code that traps
errors (I was simply going to JMP to it, but I had to know what needed to be
put in each register).

Just before the standard entry point to this routine, there were three
statements which loaded the BC register with three different values.
(BTW, Looking throught the routine, I noticed that it didn't use the
value loaded into BC.)  Wondering
why this seemingly useless code was here, I looked for all the references to
those locations and found out that all the references JMPed into the middle of
the LOAD BC instructions.  Disassembling from the place that was JMPed to, I
found that the instruction was LOAD E, which was what all the other routines
did before JMPing to the standard entry point for this routine!


Now to explain the reasons why I feel that it was done this way.  Suppose you
were using the E register and you wanted to check for an error condition.  If
it occurred, you would have to branch away, load E with the correct error
value, and JMP to the error handling routine.  This takes seven bytes (2 for
the branch, 2 for the load E, and 3 for the JMP).  If you JMP into the middle
of the the load BC instruction, you only need 6 bytes (3 for the JMP, 2 for the
load E, and 1 for the load BC opcode--this was needed so that others JMPing
into this routine before your entry point would ignore the LOAD E instruction).

They had to fit all of BASIC in a 12K ROM, and every trick in the book had to
be used to conserve memory (if I remember correctly, on the original release
they did it with 8 bytes to spare).  They had to be excellent assembly language
programmers to find tricks like this!  I take my hat off to these coders (as
well as the original Apple ROM writers); they did some of the most impressive
assembly work that I have ever seen!
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				"The secret compartment of my ring I fill
 /  / _ , __o  ____		 with an Underdog super-energy pill."
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

dhesi@bsu-cs.UUCP (Rahul Dhesi) (02/20/88)

In article <3755@ihlpf.ATT.COM> nevin1@ihlpf.UUCP (00704a-Liber,N.J.) writes:
[admiring the authors of the TRS-80 12K ROM]
>They had to fit all of BASIC in a 12K ROM, and every trick in the book had to
>be used to conserve memory (if I remember correctly, on the original release
>they did it with 8 bytes to spare).  They had to be excellent assembly language
>programmers to find tricks like this!  I take my hat off to these coders (as
>well as the original Apple ROM writers); they did some of the most impressive
>assembly work that I have ever seen!

No, not every trick.

The Z80 has duplicate sets of registers, the alternates being accessed
by one-machine-cycle instructions.  Yet not once did the 12K ROM use
the alternate set.

You would also see sequences similar to

     PUSH  HL                   ;save HL
     LD    HL,(ADDRESS)         ;load HL from memory
     LD    DE,HL                ;transfer to DE
     POP   HL                   ;restore HL

when a simple

     LD    DE,(ADDRESS)         ;load DE from memory

would have sufficed.  And so far as I could tell from disassembled
listings, the BASIC interpreter part of the ROM (as opposed to the 2K
that did the I/O) seldom or never used the index registers, which
I consider to be a very powerful feature of the processor.

Much of the power of the Z80 was wasted in the TRS-80 ROM.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee,uunet}!bsu-cs!dhesi