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