Programming is, among other things, a kind of writing. One way to learn writing is to write, but in all other forms of writing, one also reads. We read examples—both good and bad—to facilitate learning. But how many programmers learn to write programs by reading programs?
Gerald M. Weinberg, The Psychology of Computer Programming,
Van Nostrand Reinhold, 1971.
This is a book of programs—a collection of complete, runnable, utility commands for the CP/M operating system. Each one is worked out from its initial functional specification, through a pseudo-code design, to source code for the 8080 CPU and the MAC assembler. The book has one main goal and three subordinate ones.
Programming is neither an art nor a science, but a craft. There is a subject called "computer science"; it is a branch of mathematics. There can be artistry in a program (and there may be such a thing as "computer art"), yet I maintain that, in its day-to-day practice, programming most resembles a craft like woodworking, pottery, or blacksmithing. Like those crafts, programming has the goal of producing utilitarian objects: things that serve the needs of their users. Like those crafts, its practice calls for the application of skills developed by long practice, and for the application of the artisan's own good taste and imagination, to the elaboration of conventional designs. And like any good crafts-person, the good programmer strives to reach beyond mere utility to efficiency, elegance, and beauty.
The advent of cheap personal computers has made it possible for tens of thousands of eager people to try their hands at programming. This huge infusion of new talent into a once-arcane field promises great things for the future. But that promise can't be realized until the newcomers have learned the craft.
No mason, smith, or potter—no artisan in any medium—ever learned a craft by reading about it. A person who only reads can become, at best, a critic. The practioner learns by practicing, and by observing the work of other practitioners. You, the reader of this book, are assumed to be a would-be artisan in the medium of computer programs. I, a journeyman programmer, invite you to join me at my work. The main aim of this book is to let you watch and lend a hand as an experienced programmer goes about constructing programs, from the selection of the raw material to the final coat of varnish.
The programs we will build are all CP/M commands written in assembly language. Assembly language has a bad reputation, and for good reason. It takes longer to make an assembly-language program, and it takes extra time to modify it later. The extra cost can be kept to a tolerable level, but only by lavishing great care on the design of the program. One of the subordinate aims of the book is to show various techniques of designing and documenting a program so as to reduce the cost of building and modifying it.
Another aim is to demonstrate how to make good use of the CP/M system interfaces. These interfaces are directly accessible only to assembly-language programs.
In any craft, the main difference between an apprentice and a journeyman is that the journeyman has a large vocabulary of techniques and, equally important, can tell from experience when each technique is appropriate. In these programs we will apply a number of standard techniques that are common to programs in any language (for example, binary search of an ordered table) as well as some that are unique to systems programs (for example, the manipulation of addresses in inverting a linked list). We'll discuss the choice of techniques, especially as it affects the performance of the programs.
The less an onlooker knows about a craft, the more its practice seems to resemble magic. When I watch a potter working at a wheel, it seems to me that the pot grows up of its own volition, like a plant. In my ignorance, I can only admire the performance; I cannot appreciate it because I have no personal experience of the work.
If you are a complete novice at programming you might enjoy reading this book, but you will learn little from it. It will probably seem that we are continually leaping from problem to conclusion without any intermediate steps. The programs will seem to grow up of their own volition, like plants.
If you have some experience with programming, perhaps in BASIC or Pascal, things will make more sense. From that experience you know what loops and branches are; you have had the experience of writing a program that looped once too many or once too few times, or one that branched on the wrong condition. You have known the satisfaction of working your way from a problem to an algorithm, and known the chagrin of thinking of a hole in your logic, weeks later. Because of this experience you will have an intelligent appreciation of the work being done here. The use of assembly language may be a stumbling block, but by comparing the pseudo-code designs to the assembly-language code, and by referring often to a good assembly-language manual[1] and a CP/M reference book[2] you should be able to follow the code.
If you are an experienced programmer, you enjoy reading other people's programs anyway. In that case, you are invited to tour the book as one artist might tour another's one-man show, noting useful techniques and getting enjoyment from catching errors.
There are errors in these programs; you can be sure of that. There are errors in every non-trivial program. I would very much like to receive letters from those who find errors in these. Read carefully!
David Cortesi
Palo Alto, 1982
[1]An excellent manual is 8080/8085 Assembly Language Programming, order number 9800940, Intel Corporation, 3065 Bowers Ave., Santa Clara, CA 95051.
[2]One adequate CP/M manual is Inside CP/M, David E. Cortesi, Holt, Reinhart, and Winston, 1982.