EDIT: sorry for the repeated edits, but I am trying to avoid sequential posts as new things come to mind.
bzt wrote:In that case a manually optimized assembly will perform better than any machine optimized code (basically because compilers can do only micro-optimizations, while human can do large scale algorithmic optimizations as well).
Permit me to blow your mind:
STALIN Scheme. It is widely regarded as the most aggressively optimizing compiler for any language, ever (the official motto is, "STALIN Brutally Optimizes"). Notably, it is a
global optimizer, something which is generally unheard of elsewhere; it can re-arrange steps, inline function calls, merge memory objects whose scopes don't overlap, and several other things that most compiler writers simply don't try to do, all applied to the entire program. While it can't replace an algorithm, in some cases it can perform successive transforms which end up with a significantly different method for accomplishing the same thing.
There is a follow up called
Stalingrad which implements a Scheme dialect called VLAD. The former was meant mainly as a proof of concept, and both are intended to be used as a 'ultra-optimal release' tool rather than general development - the idea is that once you had it working and debugged on a faster, but less aggressively optimizing, compiler, you would then use the Stalin (or Stalin∇) compiler to squeeze performance out of the released version.
In any case, the algorithm issue is a ludicrous argument in favor of assembly, as algorithms aren't language specific - if you are changing an algorithm, why change the language? Your basic argument is, as Love4Boobies points out, advocating a
Turing tarpit - while you can express any algorithm in assembly, it is it is generally
harder for even an experienced assembly programmer to implement one than it is for that same programmer to implement it in a HLL. The ability to express more complex abstractions than would be
feasible in assembly is indeed an advantage of HLLs - not be cause it isn't possible to write them in assembly, but because writing them in assembly would be unreasonably difficult compared to writing them in a more abstract notation.
Expressiveness is not the same as computation strength; some things are just easier to express in one language than in another, even though both are equally capable of expressing it. Expressiveness is in the interaction between the developer and the language, not just in the language's Turing Equivalence, and unlike Turing Equivalence, it is subjective - indeed, you can't really discuss expressiveness in general without considering the programmer using the language, though some aspects of it could be considered 'semi-objective' (while some exceptions such as Topmind or Spectate Swamp exist, few programmers would say that tables are more expressive than objects, or gotos more expressive than structured iteration statements and functional decomposition).
This
Alan Perlis quote may be apt here: "A language that doesn't affect the way you think about programming, is not worth knowing." While learning assembly does affect your ideas of how you can program - and usually for the better, as it gives a lot of insights into the actual workings of the systems - it is by no means the
only meaningful view of programming.
Understanding the relevance of this to
my 'Thelema Notes' thread is left as an exercise for the reader.
Love4Boobies wrote:As for platforms for which there are no compilers, I don't think that argument holds ground because the cost of writing a C compiler is extremely low. One can slap together a half-assed C89 compiler in no more than a couple of days (and if you use something like LLVM, it will be a whole less half-assed than one might expect for such a short period of time). Or, better yet, they can port an existing one. It's better to invest a little bit in effort in that than have to live with a large-scale assembly program for years. The "no tools" argument is artificial and would've made it in the 80s and maybe early 90s but not today.
Actually, even then it would have been nonsensical, as cross-compilers were an established technology in the mid-1960s. The last system of any significance which didn't have at least an in-house assembler and either a compiler or an interpreter for it before release was probably the PDP-1 - DEC was quite fast in adopting cross-development tools, as was IBM, and everyone else copied whatever one of those two companies did.
For example, it is my understanding that Gary Kildall had the first
PL/M compiler ready and had the generated code running on a simulator before the design of the 8008 was completed, and had to make changes to it to match the actual hardware once the masks were set. Later, when the 8080 was developed, he was already working on
CP/M - which, contrary to what most people assume, was originally mostly written in PL/M, though the 8086 and 68000 versions were first written in Pascal, then re-written in C - when the first chips were being made.
Or consider the product that put Microsoft on the map,
Altair Basic. It was written, in the span of a few weeks, on a timeshare account which Paul Allen had for his classwork at Harvard (I don't know the OS; it was on a PDP-10, so probably either TOPS-10 or Tenex, as I doubt Harvard would have used ITS or WAITS), and tested using an emulator Allan and Gates wrote (based on the one the wrote for the 8008 the previous year;
Traf-O-Data's hardware used the 8008 as a microcontroller, which was their big innovation at that point). At that time, they had never seen a working
Altair (in fact, the only prototype had
gone missing in transit when it was sent for the Popular Electronics photoshoot due to a strike at the shipping company - the one on the magazine cover was a mockup made for the shoot when they couldn't track down the actual machine - and they were still working on replacing it when Gates contacted Ed Roberts to offer the interpreter). When they went to demonstrate it at MITS' offices in Albuquerque on an Altair loaded with 4KiB of RAM (which the sole completed prototype with that much, which required multiple memory boards), they were able to load it from a paper tape made using that timeshare account, and it ran on the first go (with some minor issues regarding the tape reader at first). It was the first time
any non-trivial program had run on the system at all.
So, then why are there so many stories of early microcomputer software being written in assembly, or even machine code? There were a number of reasons. First, a lot of that was conflation between how you
programmed the systems and how you
used theme - especially for the Altair, which used a passive backplane and initially didn't ship with a BIOS ROM, so starting it required use of the toggle switches. Two, while there were usually cross-development tools, there generally weren't a lot of tools that ran natively, especially in the very early days when the systems often didn't have enough memory to run a 4KiB BASIC or PL/M compiler. Third, most of the first generation micros didn't bundle any of the tools, and something like Altair BASIC wasn't cheap - the original sale price was $200, which was considered so out of line even then that it spurred hobbyists to develop several inexpensive or free
Tiny BASIC as an alternative (and they also usually used less memory). Fourth, just because they existed didn't mean they were very good; compiler optimization was still a black art at the time, so a lot of the time a hand-optimized program
could run better (and the limited memory meant that they couldn't be very elaborate, so it wasn't as unreasonable a proposition to hand-code something). Finally, the 'real programmer' ethic was still lingering, so a lot of programmers did it that way because of sheer machismo.