smryan@garth.UUCP (Steven Ryan) (07/27/88)
>Given real world system sizes, budgets, deadlines, and MAINTENANCE >constraints as your "requirements," assembly language will "fit" only >the smallest, most toy-like, never-to-be-used-for-real prototypes. Leaping into the fray, I will place a vote for assembly. In a previous incarnation, I worked on a Fortran compiler written in a macro assembler. Today I'm working on a compiler written in Pascal. The assembly-written compiler was easier to maintain for two reasons: (1) using macros, the assembler was more extensible than pascal. (2) your manager won't let you write an assembly program without block comments, interface description, and comments on nearly ever line. In the case of assembly, nobody pretends the code is self documenting and so everybody is required to maintain the appropriate documentation. The pascal code is presumed self documenting which is load of cow doo-doo. Added to that, old code is commented out rather than deleted. [SCCS? We don't need no steenking SCCS.] As a newcomer to Unix, I'm disgusted by the lack of documentation, both embedded in the code and in the user manuals/interface description. [Interfaces? We don't need no steenking interfaces.] And I thought CDC was bad. I still don't know what all the VI/EX commands are--none the ATT manuals I have describe it fully. I can't use EMACS because nobody has botherred defining it or make the documentation available. Assembly is so difficult that nobody deludes himself about the difficulty. Unix won't go belly up because of ATT's pigging--it'll die when Kernighan, Ritchie, Thompson, et al retire and the next generation is completely unable to decipher the supposedly simple and easy operating system.
ken@gatech.edu (Ken Seefried iii) (07/27/88)
In article <1086@garth.UUCP> smryan@garth.UUCP (Steven Ryan) writes: >>Given real world system sizes, budgets, deadlines, and MAINTENANCE >>constraints as your "requirements," assembly language will "fit" only >>the smallest, most toy-like, never-to-be-used-for-real prototypes. > >Leaping into the fray, I will place a vote for assembly. In a previous >incarnation, I worked on a Fortran compiler written in a macro assembler. >Today I'm working on a compiler written in Pascal. The assembly-written >compiler was easier to maintain for two reasons: > >(1) using macros, the assembler was more extensible than pascal. Hard to believe, but i will conceded that it is possible. >(2) your manager won't let you write an assembly program without block > comments, interface description, and comments on nearly ever line. Funny, both my professors and employers don't let me write C or Modula-2 without them either. I dont see this being endemic to assembler. >In the case of assembly, nobody pretends the code is self documenting >and so everybody is required to maintain the appropriate documentation. > >The pascal code is presumed self documenting which is load of cow doo-doo. >Added to that, old code is commented out rather than deleted. [SCCS? We >don't need no steenking SCCS.] Sounds like a lack of programmer discapline to me. I have no illusions about the self documenting aspects of pascal; you're right, they don't exist. C is much worse. But it is the programmers fault any programme is not thouroghly documented, almost line by line. Also, any team that is working on a large software project and not using SCCS (or better, RCS), deserves the disaster that results. >As a newcomer to Unix, I'm disgusted by the lack of documentation, both >embedded in the code and in the user manuals/interface description. Join the club...;'} >Assembly is so difficult that nobody deludes himself about the difficulty. And C is a cakewalk? Fine, Ill tell you what...lets get together some time and program, say, a MIPS machine, you in asm, and me in C. I'll even tie one hand behind my backand program in FORTRAN. And we'll see how far each gets (the MIPS is a RISC machine. Even trivial operations require non-trivialamounts of asm code). Thats the problem with assembly in my perception. It makes EVERYTHING difficult, especially on some of the new architectures. At least with C or Pascal,some things are easy. >... [about unix] ...the supposedly simple and easy operating system. I've never heard this from anyone but marketing types... ken seefried iii ...!{akgua, allegra, amd, harpo, hplabs, ken@gatech.edu inhp4, masscomp, rlgvax, sb1, uf-cgrl, ccastks@gitvm1.bitnet unmvax, ut-ngp, ut-sally}!gatech!ken soon to be open: ...!gatech!spooge!ken (finally ;'})
gillies@p.cs.uiuc.edu (07/28/88)
I have a hard time believing people who claim that assembly is more modifiable than a high level language. Consider: (a) Changing an *int* declaration to a *long int* declaration. (b) Changing a *float* variable to a *double* variable. Changing an *int* to a *float*. (c) Extensively revising a struct {} data type to add and remove fields, then recompiling. (d) increasing the local storage of a subroutine from 5 words (smaller than the register set) to 50 words (probably larger than the register set). (e) Changing a subroutine interface specification (adding & removing arguments) & making sure all the calls are updated appropriately. With a high level language (C/Modula-II), these changes are instant and trivial. In assembly, even if you plan ahead to be "tricky" with macros, etc, the changes are nontrivial. Let's just say "It is possible to make changes to assembly language programs", but I don't want to hear about how easy it is. Don Gillies, Dept. of Computer Science, University of Illinois 1304 W. Springfield, Urbana, Ill 61801 ARPA: gillies@cs.uiuc.edu UUCP: {uunet,ihnp4,harvard}!uiucdcs!gillies
henry@utzoo.uucp (Henry Spencer) (07/29/88)
In article <1086@garth.UUCP> smryan@garth.UUCP (Steven Ryan) writes: >Assembly is so difficult that nobody deludes himself about the difficulty. Ho ho ho ha ha ha HO HO HO HA HA HA! If only it were so. :-( -- MSDOS is not dead, it just | Henry Spencer at U of Toronto Zoology smells that way. | uunet!mnetor!utzoo!henry henry@zoo.toronto.edu
chris@mimsy.UUCP (Chris Torek) (07/29/88)
In article <76700041@p.cs.uiuc.edu> gillies@p.cs.uiuc.edu writes: >I have a hard time believing people who claim that assembly is more >modifiable than a high level language. I think they mean that the assemblER (the thing that reads the program source and generates the program object) is more flexible/modifiable than a higher-level language compiler. This I find easy to believe. Before I had decent HLL compilers available to me (when I was programming on a TRS-80 model I with bits of homebrew hardware and software: now *that* is primitive :-) ) I did some fairly extensive Z80 assembly programming. The only way I could keep track of what I was doing was to stick to a particular discipline. Within that, I was at least as restricted as by a compiler. Given that (voluntary) set of restrictions, none of the following were particularly difficult: >(c) Extensively revising a struct {} data type to add and remove >fields, then recompiling. (Done by using various label conventions. It would have been nice had I had something to do this for me.) >(d) increasing the local storage of a subroutine from 5 words (smaller >than the register set) to 50 words (probably larger than the register >set). (Use the stack. Painful; stack-relative references are *hard* on a Z80. The typical trick is to use IX or IY; this is slow.) >(e) Changing a subroutine interface specification (adding & removing >arguments) & making sure all the calls are updated appropriately. (A matter of checking all the calls. Typically pointers were in HL and integers in BC, or [if small] in B, C, or A. If many arguments, some went on the stack, or in a `structure' with a descriptor in HL.) >With a high level language (C/Modula-II), these changes are instant >and trivial. Not all of them, perhaps, but the point is that the HLL helps me to do this: it makes it much easier, and that is why I use(d) it. (The TRS-80 has been off for years, now; it has a bad 4116 somewhere in the expansion interface, and I have not the inclination to hunt it down, nor do I have any idea where, or even whether, these 16K chips are still available.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
albaugh@dms.UUCP (Mike Albaugh) (07/29/88)
Piggy-backing on article <12729@mimsy.UUCP>, by chris@mimsy.UUCP (Chris Torek): This is my first attempt to post anything in news, so please bear with me. Apologies also to Chris Torek for doing it by replying to his message. It seemed an easy way to get into an on-going discussion. I have two comments and a question. First, in re: assembly. While I thoroughly concur that it should be used sparingly, I cannot condone an outright prohibition. I'd rather have to maintain an average C program than an average assembly program, but I'd rather wrestle a rabid weasel than attempt to modify the sort of C that all too often results when someone dogmatically refuses to 'descend' to assembly, and instead pulls every trick the last version of his compiler let him get away with. If you're so sure you know the right five assembly instructons, just use them. Don't write ten lines of totally opaque C that will break next release of the compiler (see below). Second, in re: hardware Blitters. I find it at least mildly amusing that in a group where I might expect to see some discusion of algorithms to run conventional (SISD) code on multiple processors and/or functional units, someone is seriously proposing that it is a BAD IDEA to take an explicit, programmer-given, clean partioning of the task and throw it away. Next I suppose I'll hear that "Real men don't use disk controllers, they bit-boff the read/write heads" :-) Last, the question. In the last two years I have increasingly run across cases where new releases of the compiler have introduced bugs in my code. I'm not talking about tighter type checking catching bogus constructs, I'm talking about pushing the wrong length of data if a parameter is an expression containing (0+fred) where fred is a short and the 0 resulted from folding some #define's. Or would you believe forgeting how to multiply or divide (this seems especially difficult for C compilers for the 68000). Anyway, what is the orthodox way to deal with the fact that your 50,000 lines of debugged, tested code become 50,000 lines of un-debugged, un-tested code every time a new release of the compiler comes out. I know about regression testing, but the last time it ONLY munged the multiply that was concerned with the average up-time of a machine, so I didn't hear about it until a machine in the field had been running continuously for over 32767 minutes. Any suggestions? | Mike Albaugh (weitek!dms!albaugh) voice: (408)434-1709 | Atari Games Corp (Arcade Games, no relation to the makers of the ST) | 675 Sycamore Dr. Milpitas, CA 95035
chris@mimsy.UUCP (Chris Torek) (07/30/88)
[I have redirected this to comp.misc, as perhaps I should have done earlier] In article <517@dms.UUCP> albaugh@dms.UUCP (Mike Albaugh) writes: > First, in re: assembly. While I thoroughly concur that it should >be used sparingly, I cannot condone an outright prohibition. Certainly---for instance, having /sys/vax/locore.s written in assembly, rather than in `asm' statements with intermixed C code, is clearly proper. Things such as #define VECTOR(x) (((void (**)())VEC_BASE)[x]) ... void my_keyintr(), (*old_keyintr)(); ipl_t ipl; ipl = iplraise(IPL_KEYINTR); old_keyintr = VECTOR(17); VECTOR(17) = my_keyintr; setipl(ipl); are somewhat `iffy', although I prefer the C code in this particular case. Stuff like f() { long *savedstack = &savedstack - 7; ... is, for me, on the other side of that line. >... Anyway, what is the orthodox way to deal with the fact that your >50,000 lines of debugged, tested code become 50,000 lines of >un-debugged, un-tested code every time a new release of the compiler >comes out. I know about regression testing, but the last time it ONLY >munged the multiply that was concerned with the average up-time of a >machine, so I didn't hear about it until a machine in the field had >been running continuously for over 32767 minutes. Any suggestions? I doubt you will find any infallible method. The obvious answer is a more strict regression test: add such multiplication to your test suite. Indeed, add anything that has ever triggered a compiler bug to your test sets. (This can quickly become unweildy :-) ) Knuth likes the `exercise every line of code' test: instrument the compiler, and arrange to have everything in it run at least once (including, of course, the error recovery code). This usually requires external hooks, and it helps immensely to have a compiler that does the instrumentation automatically. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
rick@pcrat.UUCP (Rick Richardson) (07/31/88)
In article <517@dms.UUCP> albaugh@dms.UUCP (Mike Albaugh) writes: >especially difficult for C compilers for the 68000). Anyway, what is the >orthodox way to deal with the fact that your 50,000 lines of debugged, tested >code become 50,000 lines of un-debugged, un-tested code every time a new >release of the compiler comes out.I know about regression testing, but the last >time it ONLY munged the multiply that was concerned with the average up-time >of a machine, so I didn't hear about it until a machine in the field had been >running continuously for over 32767 minutes. Any suggestions? Never, ever, switch tools on production quality software unless you have to. If you absolutely have to change tools, treat the software as you would the first time it is sent to system test -- take nothing for granted. -- Rick Richardson, PC Research, Inc. (201) 542-3734 (voice, nights) OR (201) 389-8963 (voice, days) uunet!pcrat!rick (UUCP) rick%pcrat.uucp@uunet.uu.net (INTERNET)
albaugh@dms.UUCP (Mike Albaugh) (08/02/88)
In article <12756@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek): >a more strict regression test: add such multiplication to your test >suite. Indeed, add anything that has ever triggered a compiler bug >to your test sets. (This can quickly become unweildy :-) ) No kidding? The point of capping "ONLY" was that this was the only 16x16 multiply in the whole set of 6 modules that was hit. In a friend's case, only one of 20 32x32 multiplies was bungled. These bugs seem very sensitive to context, moving from one to another expression in a routine when, for example: fred() { int a; short b; ...} is changed to: fred() { short b; int a; ...} WHETHER or NOT a and b are involved in the eventual "victim" multiply. Also, the 32x32 bug which got my friend was not one of the classic "corner" cases. Should I check all possible 32x32 multiplies across all possible permutations of variable declarations. Perhaps you were under the impression that I have the sources to the compiler. I wish that were the case, but I don't. From article <546@pcrat.UUCP>, by rick@pcrat.UUCP (Rick Richardson): > Never, ever, switch tools on production quality software unless you have > to. If you absolutely have to change tools, treat the software as you > would the first time it is sent to system test -- take nothing for granted. I am a lowly programmer :-). People like system administrators decide when to change releases of the compiler. They do so based on considerations like how much disk space they can spare to hold old versions and how many other people are screaming for the latest release to fix the OLD bugs that broke THEIR code. They also have to deal with vendors who refuse to even listen to bug-reports on any but the latest version. One of my responsibilities here is to maintain/extend a set of tools and utility subroutines for use in embedded systems. While we no longer manufacture the games for which they were originally written, there is enough commonality to warrant re-use of code (I thought this was an acceptable practice, using proven code rather than re-inventing the wheel :-) But the release of the compiler that compiled the original code (circa 1982) won't even run on the latest release of VMS (which is where I work). > would the first time it is sent to system test -- take nothing for granted. > ^^^^^^^^^^^^^^^^^^^^^^^^ If you mean that literally, there is no point in using even an assembler, let alone a compiler. And even if I coded in hex, the loader could always "get" me :-) I have had cases where the inclusion of an fprintf(stderr... was enough to get rid of the bug, but if the the fprintf was removed, #if'd or even if ( debugsw == 1) ..., the bug would re-appear. Is Heisenberg writing compilers these days :-) One of the things that worry me most about ADA is that so much of the code in many "mission critical" systems will be in the form of "packages" which, like my compiler, are "gauranteed" but not testable. So we'll know who to sue for the next shuttle explosion or WWIII :-) | Mike Albaugh (weitek!dms!albaugh) voice: (408)434-1709 | Atari Games Corp (Arcade Games, no relation to the makers of the ST) | 675 Sycamore Dr. Milpitas, CA 95035 | The opinions expressed are my own (My boss is on vacation)
hjm@cernvax.UUCP (hjm) (08/03/88)
In article <519@dms.UUCP> albaugh@dms.UUCP (Mike Albaugh) writes: > Is Heisenberg writing compilers these days :-) > Answer: probably! :-) Hubert Matthews
zs01+@andrew.cmu.edu (Zalman Stern) (08/15/88)
> *Excerpts from ext.nn.comp.arch: 27-Jul-88 Re: using assembler Ken Seefried* > *iii@gatech. (2803)* > And C is a cakewalk? Fine, Ill tell you what...lets get together some > time and program, say, a MIPS machine, you in asm, and me in C. > I'll even tie one hand behind my backand program in FORTRAN. And > we'll see how far each gets (the MIPS is a RISC machine. Even trivial > operations require non-trivialamounts of asm code). I am not sure which instructions you are refering to as requiring non-trivial amounts of code to synthesize. Are they things I am likely to use quite often? Here are some reasons why the MIPS R2000/R3000 should be quite reasonable for assembly language programming: Simplicity: 3 hours with "MIPS R2000 RISC Architecture" by Gerry Kane and I understood (or "groked" if you prefer) the R2000 and R2010 (floating point unit). There were none of those "What would I use that instruction for?" type questions going through my mind. Orthogonal register set: One register is pretty much as good as another. None of this "Where am I going to put the CX register so I can do a shift" crud you run into on the earlier Intel beasties. Abundance of registers: You get ten or twelve (depending on whether or not you count v0 and v1) unsaved registers to use as temporaries. (Actually, you can add in four to that for the argument passing registers a0-a3.) Arguments passed in registers: Many routines will not need to allocate a stack frame at all. This frees you from having to deal with the calling convention a lot of the time. Single cycle instructions: You don't have to have an instruction timing table handy to write efficient code. Almost every instruction takes one cycle. The only exceptions I know of are multiply/divide, loads/stores, and branches. (And of course floating point.) Intelligent assembler: The assembler removes the burden of scheduling delay slots from programmer. The assembler can also synthesize addressing modes for the programmer. Of course I don't write entire programs in assembly. (For many reasons, most of which can be summed up by saying "Assembly language is just the wrong level of abstraction.") I occasionally find it necessary to write a routine or two in assembly either because high level languages can't do what I need, or because I need extreme speed. Examples of where this has come up in practice are dynamic loading and DES encryption. We have a dynamic loading system which uses a "link snapping" mechanism. This means that when you call a routine that hasn't been loaded yet, you wind up in some trampoline code that loads the routine, fixes the original reference to the routine to point to the newly loaded code, and finally jumps to the new routine. Since there is no way to jump to a routine in C, this trampoline code must be written in assembly. In the DES case, assembly can win big because DES is essentially a bunch of bit manipulations on a small block of data (64 bytes if I remember correctly.) In assembly, the entire block of data can be loaded into the register file and manipulated. The lack of loads and stores during the manipulation makes the encryption run much faster. (I have yet to run into a C compiler that is tense enough to do this. Maybe someday, one will exist.) Most people have decided that the portability loss of assembly is not worth the speed gain for DES code. I have never actually programmed on the MIPS machine. I have however written assembly code for the IBM RT which has some of the same features. (Notably passing arguments in registers.) I have had a much easier time on the RT than on either the VAX, the 68000, or the 8086. (Granted the 68020 and the 80386 fix a few of my complaints with these processor families.) In short, a processor's machine language ought to be simple, regular, and damn fast. Sincerely, Zalman Stern Internet: zs01+@andrew.cmu.edu Usenet: I'm soooo confused... Information Technology Center, Carnegie Mellon, Pittsburgh, PA 15213-3890