On Sat, Jun 28, 2014 at 8:35 PM, Zbigniew <zbigniew2...@gmail.com> wrote:
> It was always a bit strange to me, that I had - well, I still have ;) > - a few quite useful Pascal compilers for such little machine, like > Commodore 64, and just one C compiler (Power C), which is cumbersome > and hard to work with. C compiler - for the language being "closer to > machine" than Pascal or BASIC - theoretically should be less > resource-hungry (just like Forth compilers). There are fundamental language differences to take into account. Niklaus Wirth created Pascal as a teaching tool, for teaching algorithm design. It was originally intended to be "compiled" on paper, with the teacher grading the quality of the student's assignment. In ISO standard Pascal, the last I knew, things like I/O were undefined, because a program wouldn't *do* I/O. When compiler writers began creating compilers to generate executables from Pascal code, they had to roll their own in areas like I/O, because it wasn't defined in the language. Pascal spread widely be4cause it was relatively easy to learn to write, but became inherently non-portable because of differences in implementations. The C language was created by Dennis Ritchie at Bell Labs, largely concurrently with the development of Unix by Ken Thompson and Brian Kernighan. C was intended to solve a specific problem. Up till C came about, systems software, like operating systems, was written in the flavor of Assembler supported on the target machine. The DEC minicomputers used to host the development of C and Unix, for example, used Macro-11, DEC's flavor of Assembler. (DEC also had a specialized language called BLISS intended for systems software.) The problem with Assembler was that while it provided the greatest possible efficiency, it was hard to write and harder to maintain. The developer had to think with the machine's point of view, which was very different from the problem to be solved. Ritchie was creating a language intended to have the control constructs available in higher level languages, but efficient enough that you didn't *have* to write in Assembler to get adequate performance. Another goal was that it be portable, and relatively easy to bring up on a different machine. He wanted a language to make it easier and faster to write operating systems. Unix was intended to solve a similar problem. Thompson and co-workers were software developers, unhappy with the facilities provided by the DEC systems on which they worked to support the task of software development. The had an old DEC mini that was essentially unused, and could start from scratch, creating a new OS better suited for developing software. Early versions of Unix were written in Macro-11. Around Unix v6, C became mature enough to be used, and most of Unix was rewritten in C. Only really low level code that interfaced with the hardware was coded in Assembler. The portability of C made it possible to bring up Unix on systems that weren't DEC minis, and it began to spread throughout AT&T. (An early driver of the spread was being able to use the vi screen editor when writing patent applications, instead of the line editors available up till then.) The earliest C compiler used in Unix "compiled" the C language statements into Assembler, and then called as, the system assembler, to generate the object code from the Assembler, and ld, the link editor, to put the parts together into an executable the user could run. It was possible to interrupt the compilation before as was called, and hand optimize the Assembler code before continuing. It was rather later that C compilers became sophisticated enough to comple directly to object code. Those early DEC minis had a 32K address space, so C had to be compiled in a low resource environment. But generating the *smallest* executable wasn't the main goal. There is always a tradeoff between speed and code size. The fastest possible code is in line, but the more code that is in line, the larger the object file will be. To make code small, you isolate code that will be executed multiple times as a function, and you call the function, but calling the function has overhead and your code isn't as fast. In addition, C encouraged the development of libraries, where functions used in many programs could be stored for reuse, and you passed the compiler a parameter telling it where to look for libraries used by your program. When you compiled your code, and a function was encountered that was not in the code you wrote, the linker would search the libraries passed for the code than implemented that function, and include it in the executable. Doing all that took resources, The compiler had to have a temporary file where the compiled output was stored, buffers in memory to hold the code being compiled, and tables in memory to store information about the code being compiled and what should occur. The early DEC systems were virtual memory systems, so a 32K workspace wasn't an insuperable imposition, because everything didn't have to be held in memory. On something like a C64, it *was* an imposition, because you had a 48K workspace by default (unless you twiddled a memory management bit and didn't map the BASIC interpreter into the 6510's address space), and that memory was further fragmented by the memory mapping the C64 implemented. (There was a 4K block of RAM between the 8K blocks occupied by the KERNEL and BASIC ROMS, and a 1K work area at the bottom of user memory with things like pointers and the cassette tape I/O buffer.) Forget virtual memory, when disk was a 1541 floppy drive with a 300 baud serial interface. It was no surprise that the C compiler for the C64 had limitations. (IIRC, no support for unions.) Turbo-C under MS-DOS faced similar hurdles, because DOS was not a virtual memory system. And using the GUI added ease but reduced flexibility, as it largely limited you to what the defaults were as implemented by the compiler. To generate really small code, you had to understand what took up space in the executable, and in some cases write your own code which would replace the system library code with something that took less space. The advantage to C was that it could potentially generate faster (albiet larger) code, and the code you wrote could potentially be recompiled on a completely different machine with a different architecture and still do the same thing. (Writing truly portable code was an art form few really learned, and the learning process generally involved trying to compile your code on another machine, watching it die horribly, and making the fixes so it would compile.) C isn't magic. There are things doable in C not easily doable in other languages, but they don't happen automatically. You must understand the language, what it does, and how it does it, to make them happen, and generating small object code is one of those places were knowledge is critical. > Z. ______ Dennis ------------------------------------------------------------------------------ Open source business process management suite built on Java and Eclipse Turn processes into business applications with Bonita BPM Community Edition Quickly connect people, data, and systems into organized workflows Winner of BOSSIE, CODIE, OW2 and Gartner awards http://p.sf.net/sfu/Bonitasoft _______________________________________________ Freedos-user mailing list Freedos-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/freedos-user