
A Reference Journal for Users of Home Computers 



>• 


IT'S The People’s Computer Company Series 





















































Dr. Dobb’s Journal 

For Users of Small Computer Systems / 


A Reference Journal for Users of Home Computers 


Volume Seven 



The People’s Computer Company Series 


00 

HAYDEN BOOK COMPANY 

a division of Hayden Publishing Company, Inc. 
Hasbrouck Heights, New Jersey 



Acknowledgments 


As always, the allegiance of all editors at Dr. Dobb’s Journal goes to the many people 
whose support has kept the pages of DDJ well fed. Our naive, optimistic beginnings were in 
the days when the microcomputer was still a somewhat dubious creation in the eyes of the 
mainframe elite, and was a virtual unknown to the public at large. Since then, it has become 
fashionable to clamber aboard one of the several popular bandwagons filled to overflowing 
with look alikes and cheaper imitations of soon-to-be-mediocre products. 

So we offer wholehearted thanks to all the authors and readers who have made DDJ 's 
seventh year of publication as exciting and important as its first. You have shown us that there 
is, more than ever, a tremendous need for blue-sky thinking, for a champion of the public 
domain, for a publication whose philosophy addresses human needs and the potential 
computers have to serve them. Your enthusiasm has been our inspiration. 

Marlin Ouverson 
Bound Volume Editor 
March I. 1984 


Bound Volume Staff » 

Editor: MARLIN OUVERSON 
Production Manager: JANE A. McKEAN 
Index: JULIE ANTON 

Cover: Linocut of griffin by Wendy Palmer. The mythological griffin, half lion 
and half eagle, has long stood as an enemy of ignorance. 


Copyright © 1984 by People’s Computer Company. All rights reserved. No 
part of this book may be reprinted, or reproduced, or utilized in any form or 
by any electronic, mechanical, or other means, now known or hereafter 
invented, including photocopying and recording, or in any information storage 
and retrieval system, without permission in writing from the Publisher. 


Printed in the United States of America 
23456789 PRINTING 


85 86 87 88 89 90 91 92 YEAR 



Editors Preface 


This is the “Blue Period” volume. 

Even the most casual observer of the microcomputer scene in 1982 knew the year 
belonged to IBM. It began with the Justice Department dropping a longstanding antitrust suit 
against “Big Blue” and ended with the computer newsweekly InfoWorld selecting IBM’s first 
personal computer as Product of the Year. 

IBM had introduced the PC the preceding August and by January 1982 the entire 
microcomputer software industry was already in IBM’s long, blue shadow. By March the 
PC-compatible hardware products were multiplying. Before Christmas, fBM had driven a 
wedge between Microsoft and Digital Research, caused a half-year delay in the release of a 
new version of what had been the industry-standard operating system, and made Apple 
Computer, Inc. revamp its entire marketing strategy. In short, the billion-dollar multinational 
corporation, with firm notions of corporate secrecy and a reputation for letting other 
companies take innovative risks, made very big waves that year. Those waves altered an 
industry that had been created from nothing over the preceding decade by a bunch of hobbyists 
and wild-eyed dreamers accustomed to openly sharing technological ideas. 

Among the swimmers watching the Big Blue wave roll in that year was Dr. Dobb’s 
Journal, a magazine founded back in the early months of the microcomputer revolution. DDJ 
continues the open sharing of updates on software tools as well as the promotion of clever, 
tight, innovative programming. The founders of the journal believed that the personal 
computer could and should be an unparalleled equalizing force in society, and that putting the 
best software tools in the hands of the brightest programmers was the quickest path to this 
goal. They were revolutionaries, while IBM had a somewhat different agenda. 

This volume will inform you of the plentiful software tools now available. You’ll find 
Dave Cortesi’s comparison of the leading operating systems for the PC—the first and probably 
still the best analysis of CP/M-86 and MS-DOS available. Then there are Ray Duncan’s 
articles on the 8087 math co-processor, color graphics for the PC, and his 8086 Forth 
assembler. Ray’s 8086 articles were so impressive that he was commissioned to write a regular 
column to promote the discussion and interchange of 16-bit software. Advanced processors 
such as the 8086 and 68000 were beginning to fascinate programmers in 1982 and Dr. Dobb’s 
Journal increased its attention to them dramatically without abandoning the CP/M world. Bob 
Blum’s popular CP/M Exchange column also began in 1982. In case you’re not familiar with 
Dr. Dobb’s Journal, I should point out that there are full implementations of languages and 
operating systems between these pages, as well as other useful and significant utility programs 
and software. 

But this volume is history, too. The material herein was originally written as the first 
phase of the personal computer revolution came to an end. As we have always done in these 
volumes, we’ve given you the full year of Dr. Dobb’s Journal: editorials, letters to the 
editor—the works. You’ll see attitudes expressed by DDJ’ s readers to IBM’s entry into the 
market. In fact, the magazine’s original subtitle was “Running Light Without Overbyte” (that 
is, programming so well as not to waste a byte of precious computer memory). One reader 
characterized IBM’s system software as “overbyte galore!” You may also read a blue 
wistfulness between the lines for the “ending era” in Marlin Ouverson’s editorials. And you’ll 
read of his concern for “the concept of cooperation and... the attitude that anything is possible 
and should be tried at least once.” These are principles that. Marlin says, "begat personal 
computing and are the parents of DDJ." That’s not rhetoric; it’s just how it was. 

No, the Big Blue wave didn’t wash DDJ away, and cooperation and idealism didn’t die in 
1982. The hobbyist era ended, but the revolution lived on. IBM is now part of it and its effect 
on the personal computer revolution has been largely salutary. But anything as big as IBM is 
by definition a monster, and not to be relied upon. 

So the Doctor’s work goes on; to look for and distribute the best software tools for 
advanced programmers and to provide a forum for discussing the merits of various 
programming methods. Personal computers can be the great equalizer, but the revolution 
needs nudging now and then. Any revolution with an IBM in it needs a Dr. Dobb’s Journal. 


Michael Swaine 
Editor-in-Chief 
Dr. Dobb’s Journal 


April 1984 



About People’s Computer Company 


People’s Computer Company, the publisher of Dr. Dobb’s Journal, was founded in 1972 
as a non-profit source of education and information about computers. It grew from the same 
roots as the Whole Earth Catalog and the Whole Earth Software Catalog. Both companies 
were offshoots of the Portola Institute of Menlo Park, California, an organization investigating 
and promoting the idea of alternative technology. For the founders of PCC, this meant 
promoting the use of computers as a liberating force in society. 

To make these ideas manifest, it has been necessary to think far ahead, to be creative and 
innovative. PCC published the first personal computing periodical in 1972, a time when the 
technical community at large found the thought of “personal” computers preposterous. 

PCC has initiated a number of service-oriented projects in order to empower people to 
take a more active part in a society in which computers are a significant factor. It has 
published a newspaper, three magazines, and several books on home and personal computing. 
It has also operated a neighborhood computer center, a mail-order bookstore, a computer van, 
and has sponsored telecommunications research (PCNET). 

The main emphasis of the company has been on small, personal computers—the kind 
anyone can learn to use and that increasingly more individuals can afford. ComputerTown, 
USA! is a major project begun with financial assistance from the National Science 
Foundation. It provides a model of how to make everyone in a small- to medium-size 
community “computer literate.” ComputerTown shares its experience and resources in a 
newsletter in the ComputerTown Books series, in the ComputerTown Guidebooks, and 
through classes and membership services. Affiliates exist in the United Kingdom, Europe, 
Australia, and across the United States. 

PCC today continues its consulting leadership in technology research, curriculum design, 
and training. In conjunction with the California State Library, PCC is working on the design 
of written materials supporting the creation of 12 public library resource centers in the state of 
California. The staff of PCC will provide the on-site training for the staffs of these centers and 
for the staffs of 71 additional public libraries. PCC continues its focus of developing a model 
of science as part of a continuing dialog with those affected by it. 

Dr. Dobb’s Journal, which was licensed to M&T Publications of Palo Alto, California in 
1984, was PCC’s second publication. The first issue was published in 1976 in order to provide 
short-term distribution of the newly written Tiny BASIC language. Reader response was so 
strong that it went immediately into monthly production. It has led the way since then by 
focusing on important advances in microcomputer software, printing public domain software, 
and fostering vital reader interaction on technical matters. Most readers describe their 
experience with computers as intermediate to extensive. About ten percent of them live outside 
the United States. 

Today Dr. Dobb’s Journal remains the prime source of information and software tools for 
advanced programmers. Its early issues are still in demand, and no part of the editorial content 
of DDJ has ever gone out of print. Volumes One through Seven of this series contain the entire 
editorial content of DDJ' s first seven years, and are available in matching, bound volumes 
from Hayden Book Company. 

The PCC staff members have a wide variety of personal and professional interests and 
experiences. Their work stems from a conviction that the personal computing revolution is of 
tremendous significance, and that familiarity with computers fosters confidence and greater 
control over one’s life. 

Bob Albrecht, one of the company’s founders, explained the inspiration for the company 
in the first issue of the PCC Newspaper: 

“Computers are mostly used against people instead of for people, used to control people 
instead of free them. It’s time to change all that. We need a People’s Computer Company.” 

People’s Computer Company 
P.O. Box E 

Menlo Park, CA 94025 



Contents 


VOLUME 7, NUMBER 63, 1982 


2 Editorial 

3 Dr. Dobb’s Clinic 

6 Of Interest 

8 Interfacing the 68000 to an AIM 65 Luca Fusina and Claudio Granuzzo 

13 A Portable Screen-Oriented Editor Edward K. Ream 

20 Small Shell: Part 2 of a North Star VOS J. E. Hendrix 


VOLUME 7, NUMBER 64, 1982 


54 Editorial 

55 Letters 

57 Of Interest D. E. Cortesi 
59 Recursion in FORTH Glyn Emery 
61 FORTH 8086 Assembler Ray Duncan 

64 Formal Definition of FORTH as a Programming Language C. H. Ting 
86 Excuse Me, What Time Is It? Alan Bomberger 
91 Background Information on Text Editors Leonard K. Nicholson 
93 Standards for Computerized Measurement Douglas Crockford 

95 Software Review 

“North Star Management Program” Gene Head 

96 Book Reviews 

“The Devil’s DP Dictionary" Joey Robichaux 
“LISP" Brian Gordon 


VOLUME 7, NUMBER 65, 1982 


98 Editorial 

99 Letters 

101 Dr. Dobb’s Clinic D. E. Cortesi 
104 Of Interest 

106 Runic: An Interactive, Extensible Compiler Marty Franz 

109 Put the H-8 Front Panel to Work D. C. Shoemaker 

111 Improvement Upon a Division Program by Leventhal W. D. Maurer 

114 A Pattern Classification Program K. F. Wegner and D. E. Raeside 

116 Pidgin for the 8080 Under CP/M Andrew L. Bender 

141 Book Reviews 

“The 8086 Book (Includes the 8088)" Ray Duncan 
“Pascal Programming Structures" Richard L. Lozes 
“Build Your Own Z80 Computer" George W. Jolly 

143 Software Review 

“The WORD” Gene Head 







145 Hardware Review 

“Universal Data Systems I03LP Modem” Dave Caulkins 


VOLUME 7, NUMBER 66, 1982 


149 Letters 
149 Editorial 

152 Dr. Dobb’s Clinic D. E. Cortesi 
154 Of Interest D. E. Cortesi 

156 8080/8086 Cross-Assembler. Part 2 Jonathan Miles 

165 Small-C DISKDOC: A Repair and Maintenance Utility Egil Kvaleberg 

172 Make the Most of Your Check Digits Peter Zilahy Ingerman 

175 A Poor Person’s Spelling Checker Alan Bomberger 

184 Son of Runic: Writing the Compiler Marty Franz 

187 Software Reviews 

“PIE” D. C. Shoemaker 
“Video Scribe" D. C. Shoemaker 

188 Hardware Review 

“The Sinclair ZX8I" Jerry Chamkis 

189 Book Reviews 

" The Logical Design of Multiple-Microprocessor Systems ” 

George W. Jolly 

“Threaded Interpretive Languages" H. T. Gorden 

“Microsoft BASIC Decoded ” James Cardell 


VOLUME 7, NUMBER 67, 1982 


193 Letters 
193 Editorial 

197 Dr. Dobb’s Clinic D. E. Cortesi 

199 Of Interest Michael Wiesenberg 

202 Program for a Modem: Forth Code From the Conference Tree JohnS. James 
208 North Star to Epson Connection Larry Shoer 
211 Add a System Clock Michael Kan 

217 New USER for CP/M Gene Head 

223 Direct Video Output from the Sinclair ZX81 Jerry Chamkis 

224 Using Computer Bulletin Boards Marlin Ouverson 

226 Software Review 

“COMMWHIZ: A Smart Terminal Package for TRS-SO's ” PCC Staff 
229 Book Reviews 

“Interfacing to S-100/IEEE 696 Microcomputers" George W. Jolly 

“Lecture Notes in Computer Science" Robert Irving 
“Introduction to Computer Organization" George W. Jolly 

231 Hardware Review 

“Hayes Stack Smartmodem" Rich Henderson-Gragg 

232 Guest Essay 

“Prior Censorship” John Gilmore 


VOLUME 7, NUMBER 68, 1982 


235 Letters 

235 Editorial 







237 Dr. Dobb’s Clinic D. E. Cortesi 

239 Of Interest Michael Wiesenberg 

241 PDP-1802—Hardware Simulator in Assembly Language 

Christopher L. Hamlin 

244 Multi-68000s in a Personal System Al Kossow 
248 An Improved LET Processor for LLL Basic Norman E. Thagard and 
George Glenn 

256 A Print Utility for CP/M Dan Daetwyler 

266 A Cross-Reference Generator in C Jeffrey L. Taylor 

271 Book Reviews 

“Elementary Pascal" D. C. Shoemaker 

“Pascal Programs for Scientists and Engineers" 

William G. Hutchison, Jr. 


VOLUME 7, NUMBER 69, 1982 


275 Letters 
275 Editorial 

277 CP/M Exchange Gene Head 

278 Dr. Dobb’s Clinic D. E. Cortesi 

280 CP/M-86 vs. MSDOS—A Technical Comparison Dave Cortesi 

292 Graphics on IBM’s Personal Computer Ray Duncan 

302 More on Checksums Robert Blum 

304 PDP-1802, Part 2—Hardware Simulator H. T. Gordon 

310 Of Interest Michael Wiesenberg 

313 Software Reviews 

“Volkswriter" Robert K. Funkhouser 

"Write-On!" Jerry Crimmins 
316 Small-C for the 9900 Matthew Halfant 
323 Book Reviews 

“ Ciarcia's Circuit Cellar Volume II” George W. Jolly 

"Using Structured Design" Chuck Ballinger 
“Computer Simulation in Business" Robert Ashworth 


VOLUME 7, NUMBER 70, 1982 


327 Letters 

328 Editorial 

329 Dr. Dobb’s Clinic D. E. Cortesi 

331 Argum—A “C” Command Line Processor Anthony Skjellum 

348 Performance Evaluation in Small Computers Michael Kan 

355 SEND/RECEIVE File Transfer Utilities Lawrence Hughes 
361 Intel’s 8087 Numeric Data Processor Ray Duncan 
364 Of Interest 


VOLUME 7, NUMBER 71, 1982 


371 Letters 

372 Editorial 

373 Dr. Dobb’s Clinic D. E. Cortesi 

377 Forth Floating Point Package A. J. Monroe 

386 Forth Programming Style N. Solntseff 

388 Relocating, Linking Loader in Forth Joe Barnhart 










393 H-19 Screen Editor in Forth A. S. Woodhull 

398 Z8000 Forth Lou Odette 

413 16-Bit Software Toolbox Ray Duncan 
415 Book Reviews 

"Starting Forth” Richard L. Lozes 
"Discover Forth ” George W. Jolly 

"Programming Language Translation’’ Edward T. Ordman 
417 Software Review 

“The Working Forth Learning System” Ray Duncan 
419 Of Interest Michael Wiesenberg 


VOLUME 7, NUMBER 72, 1982 


423 Letters 

423 Editorial 

424 Dr. Dobb’s Clinic Dave Cortesi 

427 68000 Cross Assembler Allen Kossow 

439 The Portable Pidgin: Z80 Macro-Assembly Implementation 
Herbert Gintis 

449 Simplified 68000 Mnemonics W. D. Maurer 
454 CP/M Exchange Gene Head 
462 16-Bit Software Toolbox Ray Duncan 
465 Of Interest Michael Wiesenberg 


VOLUME 7, NUMBER 73, 1982 


469 CP/M Exchange Gene Head 

469 Editorial 

471 Dr. Dobb’s Clinic David Cortesi 

472 Expand Wildcards Under UNIX Anthony Skjellum 
476 Tests for Pidgin William A. Gale 

486 A Novice Builds the Sinclair ZX81 John Connell, Jr. 

488 68000 Cross Assembler, Part 2 Allen Kossow 

500 Memory Management in BASIC Henry Seymour 

501 16-Bit Software Toolbox Ray Duncan 

503 Software Review 

"JRT Pascal” Dave Cortesi 

504 Book Review 

“Teaching Your Computer To Talk” Joseph B. Rothstein 

505 Of Interest Michael Wiesenberg 


VOLUME 7, NUMBER 74, 1982 


513 Letters 

514 Editorial 

515 16-Bit Software Toolbox Ray Duncan 

520 Small-C Compiler, v.2 J. E. Hendrix 

546 Interrupts and CP/M Alan Bomberger 

550 A Simple Vector Generation Algorithm Marek W. Michalski 

552 Guest Essay 

“Fifth Generation Computers" Richard Grigonis 

553 Dr. Dobb’s Clinic Jan-Henrik Johansson 
556 Of Interest Michael Wiesenberg 









R. 



For Users of Small Computer Systems 



$2.50 

($3.00 in Canada) 


OBB’S lOURNAL 


Number 63 January 1982 Volume 7, Issue 1 



Interface the 68000 to AIM 65 

Luca Fusina 


A (Really!) Portable 
Screen-Oriented Editor 

Edward K. Ream 

Small Shell, Pt. II of a 

North Star Virtual Operating System 

J.E. Hendrix 

and even more! 


Explore the 

16-Bit 

World... 

... Customize 
This Editor to 
Your Needs... 

... Using 
“Co-routines” 
for Multiple 
Tasks 



















Dr. Dobbs Journal 

For Users of Small Computer Systems J 

January 1982 Volume 7, Issue 1, Number 63 

CONTENTS 


Interfacing the 68000 to an AIM 65. 12 

by Luca Fusina and Claudio Granuzzo 

A Portable Screen-Oriented Editor. 18 

by Edward K. Ream 

Small Shell: Part 2 of a North Star VOS.27 

by J. E. Hendrix 

Departments 

Dr. Dobb’s Clinic. 4 

Of Interest. 10 


Editor — Marlin Ouverson 
Assistant Editor — Julie Anton 

Contributing Editors — Dave Caulkins and Dave Cortesi 

Marketing Director — Craig S. Harper 

Advertising Sales - Laird Foshay 

Circulation Assistants - Susan Hinton and Alice Hinton 

Art Director - Clifford West 

Production Manager — Barbara Ruzgerian 

Typesetter — Renny Wiggins 

Proofreader — Nancy Heubach 

©1981 by People’s Computer Company unless otherwise noted on 
specific articles. All rights reserved. 


Dr. Dobb's Journal (USPS 307690) is published twelve times per year by People’s Computer Company, Box E, 1263 El Camino Real, Menlo 
Park, CA 94025. Second class postage paid at Menlo Park, California 94025 and additional entry points. Address correction requested. Post¬ 
master: send form 3579 to Box E, Menlo Park, California 94025. 


EDITORIAL- 

Nothing in Las Vegas was flashier or more fatiguing 
than the CLONEDEX convention last November. At least, 
that’s what some were calling it. Four days was too much 
for anyone, even if there really were more than six hundred 
exhibitors. By the third afternoon, both tempers and the 
memorized sales pitches were getting shorter. That’s when 
we left. 

Communication at those events would be more open if 
there were a ban on three-piece armor. It is hard to trust 
someone so wrapped in corporate image that he takes off 
his individuality before donning his suit. Maybe Warren is 
right after all; roller skates and jeans require a kind of 
frankness that blue serge couldn’t wring out of a saint. 

If you are one of the thousands who didn’t wear your 
soles thin, you missed demos of distributed processing/ 
local networks, winchester-to-micro set-ups and some Visi- 
Clones (you’d have to check ’em all out yourself to discover 
the relative differences). I only have one question: where 


are all the geniuses who started this ball rolling? They sure¬ 
ly aren’t involved in making minor improvements on past 
achievements. We need some people thinking in terms of 
light years, not city blocks. 

So, each of you, consider this a 

CALL FOR INNOVATION 

Think big, dream Bigger. Guest essays, dream pieces, 
signposts and other nefarious schemes for advancing this 
micro technology are welcome here, in addition to your 
hard software contributions to the community. 

Now you have the whole story in a meager, encapsu¬ 
lated form. A few people were trying to figure why anyone, 
exhibitors or attendees, went to Las Vegas at all. I guess 
it was for the same reason people climb mountains — be¬ 
cause it was there. 

-MDO 


Subscription Rates: $25 per year within the United States: $40 for 
first class to Canada and Mexico; $58 for airmail to other countries. 
Payment must be in U.S. Dollars, drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be typed, double-spaced on 
white paper. Listings should be produced by the computer, using a 
fresh , dark ribbon on continuous white paper. Please avoid printing 
on perforations. Payment is in contributor’s copies. Requests to re¬ 
view galleys must accompany the manuscript when it is first sub¬ 
mitted. Authors may receive a copy of the complete writer’s guide¬ 
lines by sending a self-addressed, stamped envelope. 

Donating Subscribers Contributing Subscriber: $so/year ($25 
tax deductible). Retaining Subscriber: $75/year ($50 tax deduc¬ 
tible). Sustaining Subscriber: $100/year ($75 tax deductible). Life¬ 
time Subscriber: $1000 ($800 tax deductible). Corporate Subscriber: 
$500/year ($400 tax deductible, receives five one-year subscriptions). 


Contributing Subscribers: Eric H. Johnson, Jerry Horn, Edward W. 
Carr, Steven Fisher, Thomas H. Grohne, G. V. Elkins, Robert M. 
Connors, William J. McEown, Robert C. Luckey, Kim Leary, Robert 
N. Stabler, DeWitt S. Brown, John B. Palmer, E. Glion Curtis, Jack 
Miller, Burks A. Smith, Transdata Corporation, Mark Ketter, John 
W. Campbell, Friden Mailing Equipment, Howard E. Decker, Jim 
Wilson, Frank Lawyer, Chris Pettus. Retaining Subscribers: Osamu 
Shimizu, Scott B. Guthery, Robert L. Edens, Titus Purdin, Steven 
Fisher Enterprises. Sustaining Subscribers: Gordon Eubanks, Jr. and 
Pete Roberts. Lifetime Subscriber: Michael S. Zick. 

Foreign Distributors UK & Europe: LP Enterprises, 8/11 Cam¬ 
bridge House, Cambridge Road, Barking, Essex, 1G11 8NT, England 
(Tel. 01-591-6511, TLX 892395). Hofacker-Verlag, Tegemseer 
Strass 18, D-8150 Holzkirchen, West Germany. Asia & Austraila: 
Computer Store, POB 31-261, 22B Milford Road, Milford, Auckland 
9, New Zealand. ASCII Publishing Co., Ltd., Aoyama Building 5F, 
5-16-1 Minami Aoyama, Minato-ku, Tokyo 107, Japan. 


Dr. Dobb’s Journal, Number 63, January, 1982 

~ 2 ~ 


3 








DR. DOBB’S CLINIC 


The Matter of Coroutines 

In the September Clinic we presented 
William A. McWorter’s code for creating 
coroutine linkage between two programs. 
This month we have elaborations on that 
theme from two readers. 

We checked Knuth’s standard refer¬ 
ence on the subject. He says: 

“In contrast to the unsymmetric rela¬ 
tionship between a main routine and a 
subroutine, there is complete symmetry 
between coroutines, which call on each 
other .... The essential difference be¬ 
tween routine-subroutine and coroutine- 
coroutine linkage ... is that a subroutine 
is always initiated at its beginning, i.e., at 
a fixed place, while the . . . coroutine is 
always initiated at the place following 
where it last terminated.” 1 

Knuth attributes the coining of the 
term to M. E. Conway, who used it in an 
assembler in 1958 and who wrote the first 
published description of the structure in 
1963 2 . 

Multiple Coroutines .. . 

With that background, let us turn to 
a letter from David A. Shaw of Elmhurst, 
IL. He writes: 

“The combination of coroutines and 
message queues makes for a powerful 
set of tools for data communication 
work. I have used them to implement a 
communications system on an 8080 sys¬ 
tem, based on a subset of High Level 
Data Link Control (HDLC), which has 
seven separate tasks executing in “round 
robin” fashion. I am currently designing 
a protocol converter that uses 4 corou¬ 
tines, again running “round robin,” and 
will be using them again for a full SNA/ 
SDLC implementation on a Perkin-Elmer 
3220. 

“The enclosed listing [Listing I, page 
41 is a slight modification of the ‘SWAP’ 
routine that I am using for the protocol 
converter. This version lets the calling 
task specify the next task to be started. 
For example, if ‘TASK 1 ’ was running and 
wanted to pass control to ‘TASK3’, it 
would call ‘SWAP’ as follows: 

MVI A,T3.INDX Name next routine 

CALL SWAP Start‘TASK3’ 

“Anyone implementing coroutines 
on a system that uses interrupts should 
keep two things in mind. First, remember 
that interrupt service routines generally 
use the top of the user stack, so you 
should make each stack large enough to 


4 


Listing I 



00002 

00003 

00004 

00005 

00006 

00007 

00008 

00009 

00010 

00011 

00012 

00013 

00014 

00015 

00016 

00017 

00018 


Multiple-Coroutine Stack Manager 
Written by: David A. Shaw 

This routine provides stack management services for 14? 
to 128 separate coroutines. In this implementation, 
the routine that is giving tp control names its 
successor routine. 

Calling Sequence: 

MVI A,<coroutine stack index value> 

CALL SVftP 

The callers stack is preserved, but all registers can be 
assumed to be changed upon return. 


00020 

00021 

00022 

00023 


Stack Setup. 

Each task has its own stack. Each stack is pre-loaded 
with the first “Return" address for the task, which 





00024 

* 

should 

be its startup 

and initialization routines. 




00025 

* 







00026 

* 




000.031 



00027 

STAKSIZ 

BQU 

25 

Allow 25 words on stack 




00028 

* 




042.200 



00029 


DS 

(STAKSIZ-1)*2 

Allocate roost of stack 

042.260 

000 

050 

00030 

Tl.STRT 

DW 

T1 ENTRY 

Initialization entry for T1 

042.262 



00031 

T1STACK 

BQU 

* 

Actual stack address for Tl 




00032 

* 




042.262 



00033 


DS 

(STAKSIZ-1)*2 


042.342 

000 

060 

00034 

T2.STRT 

DW 

T2D7TRY 

Initialization entry for T2 

042.344 



00035 

T2STACK 

BQU 

* 





00036 

* 




042.344 



00037 


DS 

(STAKSIZ-1)*2 


043.024 

000 

070 

00038 

T3.STRT 

DW 

T3E2/TRY 

Initialization entry for T3 

043.026 



00039 

T3STACK 

BQU 

* 



043.026 

000.000 

043.026 260 042 


000.002 

043.030 342 042 
000.004 

043.032 024 043 


043.034 026 043 


00041 

00042 

00043 

00044 

00045 

00046 

00047 

00048 

00049 

00050 

00051 

00052 

00053 

00054 

00055 

00056 


Current Stack Address Table. 

There should be an entry in this table for each task. 
The table is used to hold the current stack pointer 
while the task is “swapped*. I have also taken 
this opportunity to define index constants that 
should be used to “name’ the next task to run. 

More tasks can be handled by aiding a stack 
and adding to the end of the Stack Address Table. 


STAKTAB BQU * 

* 

Tl.INDX EQU “-S TAKTA B 

DW Tl.STRT 


Index of T1 entry 
Initial stack pointer 


00057 

00058 

00059 

00060 

00061 

00062 

00063 

00064 

00065 

00066 

00067 

00068 

00069 


T2.DCX EQU 
DW 

* 

T3.DCX EQU 
DW 


•-STAKTAB 

T2.STOT 

•-STAKTAB 

T3.STRT 


Index of T2 entry 
Index of T3 entry 


* Pointer to table entry for currently executing task. 

* Should initially be set to the table entry of the 

* first task to be run. 

* 

CUHSTAK DW STAKTABtTl. DBX 


043.036 

043.036 052 034 043 


00071 

* 

Startup. 


00072 

* 



00073 

* 

This routine enters 

the first coroutine. 

00074 

* 



00075 

BEGIN 

BQU * 


00076 


Iitti) CURSTAK 

Get first table address 


(Listing I and text continued on page 6) 


Dr. Dobb’s Journal, Number 63, January, 1982 

~ 



allow for interrupt service as well as the 
user task. Likewise, an interrupt can 
occur anywhere, so there should always 
be a valid stack pointer.” 

.. . and Multiple Tasks 

The coroutine is a powerful tool for 
structuring some applications. Others, 
especially those that have to respond to 
unpredictable events, fall out better as 
completely independent tasks. The small¬ 
est operating system that supports multi¬ 
tasking (that we know of) is Digital Re¬ 
search’s MP/M, and it is not effective on 
a typical personal machine. If we want to 
design a program as a set of cooperating 
tasks, we have to supply the task- 
dispatching mechansim as part of the pro¬ 
gram. 

That is exactly what A. James 
Laurino of Philadelphia, PA did. He 
wrote to tell about it: 

“It is important to note that multi¬ 
tasking and similar approaches can tre¬ 
mendously simplify some very hard prob¬ 
lems. Many people shy away from multi¬ 
tasking because they feel it is too difficult 
to implement. Thus they lock themselves 
out of a lot of worthwhile uses for their 
machines that are too complex without 
some reliable structuring method. 

“I want to dispel some of the 
mystery around multi-tasking by showing 
a simple kernel that I have evolved over 
the last few years. The latest version was 
written for the 6800 and is only forty- 
one instructions long. Dijkstra’s sema¬ 
phore mechanism is used as the synchro¬ 
nization method. Briefly, a semaphore is 
a counter whose value represents the dif¬ 
ference between the number of times an 
event has occurred and the number of 
tasks that are waiting for the event. In 
particular, a negative count indicates that 
one or more tasks are waiting for the 
associated event. 

“In this realization a maximum of 
seven concurrent tasks was more than 
adequate. Each task has an associated 
priority, and tasks receive service in pri¬ 
ority order. A task is either ready to run 
or else it is blocked, waiting for some 
event. The implementation also allows for 
one level of interrupt and for a back¬ 
ground (non-blocking) task. 

“We use a series of queues to keep 
track of tasks. There is one queue that 
holds all the tasks that are ready to run, 
and there is one queue associated with 
each semaphore that holds all the tasks 


043.041 

176 


00077 


KJJ 

A,M 


043.042 

043 


00078 


INX 

H 


043.043 

146 


00079 


MCV 

H,M 


043.044 

157 


00080 


MOV 

I ,A 

(HL) - First stack pointer 

043.045 

371 


00081 


SPHL 


Load (SP) 

043.046 

311 


00082 


RET 


Start first coroutine 




00084 

* 

StAP 

- Suspend processing of this task and start 




00085 

* 


the next one. 





00086 

* 







00087 

* 

ENTRY 

- (A) - Index 

of STAKTAB entry of next 




00088 

* 


routine to be rim 




00089 

* 


(SP) - Current task stack pointer 




00090 

* 

EXIT 

- (SP) - Next task stack pointer 




00091 

* 


Will " 

return” to next routine 




00092 

* 

USES 

- A,F,H,L,D,E 





00093 

* 




043.047 



00094 

SWP 

BQU 

* 


043.047 

041 000 

000 

00095 


LX I 

H,0 


043.052 

071 


00096 


CAD 

SP 


043.053 

353 


00097 


XCHG 


(D£) ■ Current routine stack 

043.054 

052 034 

043 

00098 


LHLD 

CURSTAK 

(HL) « Addr of current table entry 

043.057 

163 


00099 


FCV 

M,E 

Put (SP) value in stack 

043.060 

043 


00100 


INX 

H 


043.061 

162 


00101 


MOV 

M,D 


043.062 

315 076 

043 

00102 


CALL 

GETADDR 

(HL) - Address of next table entry 

043.065 042 034 

043 

00103 


SHLD 

CURSTAK 

Save address for next 'swap' 

043.070 

136 


00104 


MOV 

E,M 

(DE) - New routine (SP) value 

043.071 

043 


00105 


INX 

H 


043.072 

126 


00106 


MZV 

D,M 


043.073 

353 


00107 


XCHG 



043.074 

371 


00108 


SPHL 


(SP) » New routine stack 

043.075 

311 


00109 


RET 


Start next routine 




00111 

• 

GETADDR 

- Get address of next stack table entry. 




00112 

* 







00113 

* 

ENTRY 

- (A) - Index 

into table 




00114 

* 

EXIT 

- (HL) - Table entry address 




00115 

* 

USES 

- A,F,H,L 





00116 

* 




043.076 



00117 

GETADOfi EQU 

* 


043.076 

041 026 

043 

00118 


LXI 

H,STAKTAB 

(HL) - Addr of front of table 

043.101 

205 


00119 


ADD 

L 

Add subscript value 

043.102 

157 


00120 


MOV 

L,A 


043.103 

320 


00121 


WC 


No carry - all done 

043.104 

044 


00122 


INR 

H 

Else buop high byte 

043.105 

311 


00123 


RET 





00125 

* Define sane dunny task starting addresses. 


00126 

* so this assembly will be clean. 


00127 

* 

050.000 

00128 

T1 ENTRY BQU 50000A 

060.000 

00129 

T2BfTRY BQU 60000A 

070.000 

00130 

T3EWTKY BQU 70000A 


00131 

* 

043.106 000 

00132 

END BEGIN E 


that are waiting for that event. Each 
queue is kept in priority order, of course. 

“A semaphore count is bounded by 
the precision of the counter used to 
model it. In this design a maximum count 
of +127 was more than adequate. The 
negative count of a semaphore is bounded 
by the number of tasks in the system. 
One byte thus suffices for each sema¬ 
phore count. A queue also has a maxi¬ 
mum size bounded by the number of 
tasks in the system. We can achieve a con¬ 
siderable reduction in the code and stor¬ 
age requirements over conventional de¬ 
signs by representing each task by a sin¬ 
gle bit position in a byte that represents a 
queue. The sign bit is set to indicate that 


the byte contains a queue, and each other 
bit that is set indicates that the associated 
task is in that queue. The semaphore 
queue can be the same byte that holds 
the semaphore count. When the count is 
positive, the queue is unused. When the 
count is negative, we represent the count 
by the number of bits set in the queue. 

“There are two calls to manipulate 
semaphores, signal and wait. A signal in¬ 
dicates that an event has occurred; the 
semaphore count must be increased by 
one and, if the count was negative, the 
highest priority task waiting in the queue 
must be moved to the ready queue. The 
wait is used to synchronize a task with 
an event outside it; the semaphore count 


6 

4 


Dr. Dobb’s Journal, Number 63, January, 1982 


must be decremented, and if the result is 
negative, the calling task must be re¬ 
moved from the ready queue and placed 
in the semaphore queue. I will return to 
the subject of queue manipulation after 
I have introduced the context switch 
mechanism. 

“By context switch I mean the pro¬ 
cess of allocating the processor to a new 
task. Interrupts perform this trick all the 
time, of course. In an interrupt, the pro¬ 
cessor registers are saved on a stack and 
control is transferred to the interrupt rou¬ 
tine. When the interrupt routine is done 
the old register values are restored from 
the stack and the interrupted routine 
resumes processing. In software multi¬ 
tasking, each task is assigned a stack of its 
own. After the task’s registers have been 
saved we also save the stack pointer. We 
decide which task is to run next by 
examining the ready queue. We load the 
saved stack pointer of the highest priority 
task in the queue, and then reload the 
processor registers from that stack. 

“Queue manipulation can be accom¬ 
plished by simple, parallel operations on 
the queue bytes if we observe the conven¬ 
tion that the highest priority task is as¬ 
signed to the rightmost bit position. The 
rightmost bit in a word can be isolated by 
ANDing the word with its two’s comple¬ 
ment. Once it is isolated, we remove the 
bit from the queue by XORing it against 
the queue byte. We place the bit into a 
new queue by ORing the bit into the 
queue byte. The only time that the bit ac¬ 
tually has to be identified is when we 
want to find the associated saved stack 
pointer. The example code [Listing II, 
page 7] does this by counting and shift¬ 
ing the ready queue until a bit arrives 
at the carry position. 

“Storage requirements are modest. 
Each task must have a stack, but 20 or 30 
bytes is usually sufficient. One byte is 
needed for every semaphore used. The 
kernel has a few private storage areas. 
One double byte is kept for each task to 
save its stack pointer. One byte is used 
for the ready queue. And a double byte is 
used to keep a pointer to the SP save area 
of the currently executing task to speed 
up the context switch. 

“Semaphore operations are invoked 
by a software interrupt; in the 6800, this 
conveniently saves all the registers on the 
stack [the comparable 8080 operation, is 
RST; it does not save all the registers]. 
Hardware interrupts can call the signal 
mechanism as well; they are treated 


Listing II 

Multi-Tasking Kernel for 6800 Microprocesor 


ENTRY: TSX 

LDX 5,X 
ASR 2,X 
LDX 3,X 
BCS SIGNAL 

WAIT: LDAA 0,X 

BLE BLOCK 
DEC 0,X 
RTI 

BLOCK: LDAB READY 

NEGB 

ANDB READY 

ABA 

ORAA #$80 

BRA DISP 

SIGNAL: LDAA 0,X 

BLT UNBLOK 
INC 0,X 

BVC . + 3 

DEC 0,X 

RTI 

UNBLOK: NEGA 

ANDA 0,X 

TAB 

EORA 0,X 

CMPA #$80 

BNE DISP 

CLRA 

DISP: STAA 0,X 

EORB READY 

STAB READY 

LDX CURNT 

STS 0,X 

LDX #SPSAV-2 
LOOP: INX 

INX 
LSRB 

BCC LOOP 

STX CURNT 

LDS 0,X 

RTI 


; task entry point. Note interrupts are off. 

; reach back to call to get arguments. 

; test function code. Note 0 and -1 won’t change. 

; get semaphore pointer into X. 

; 0 means Wait, leaves carry clear after ASR. 

; get and test the semaphore value. 

; 0 or less means this task must wait for event. 

; else, just decrease the count 
; and continue in the same task. 

; suspend the current task. Get bit of highest 
; priority task on Ready queue (calling task). 

; place this task bit in the semaphore queue. 

; make sure sign bit is set to mark as a queue. 

; go find a new task to run, finish update. 

; interrupt entry point. Note interrupts are off. 

; if there are tasks on sempahore queue, unblock one. 

; else, just count the event. 

; make sure the count can never overflow. 

; keep at max value in case of too many events. 

; continue in the same task as before. 

; activate highest priority task in the current queue. 

; get highest priority task bit in the queue. 

; save for Ready update below. 

; remove the bit from the semaphore queue. 

; test for an empty queue. 

; continue if not empty. 

; else, turn the queue back into a counter again. 

; run the highest priority task in the ready queue. 

; but first update Ready queue. B has bit to add 
; or to remove. Also save updated semaphore value. 

; get pointer to SP save area for the current task. 

; save the stack pointer for the current task. 

; set up to generate pointer to SP area of new task. 

; each pass through loop advances X to next SP area. 

; note SP areas are ordered highest priority first. 

; put right bit into carry, ready status of next task. 

; try next highest if this one not ready. 

; found one to run. Save copy of SP area pointer. 

; now reload hardware SP from this save area. 

; reload registers and resume running this task. 

End Listing 


NOTES: Interrupts store registers in order: flags, B, A, XH, XL, PCH, PCL. A non- 
blocking task must exit or the system will hang. If a dummy task is used (BRA .), its 
stack will never change and can be in ROM. Minimum stack is 7 bytes. Transparent call 
which preserves all registers allows reliable use of macros for semaphore operations. 


identically to an entry from an SWL in- SWI ; pass control to 

struction. The kernel expects to find the kernel 

the operation type and the semaphore ad¬ 
dress stored at the calling location. A 

typical call would look like this: (Continued on page 33) 


Dr. Dobb’s Journal, Number 63, January, 1982 


7 

5 







OF INTEREST 


Impressive Info 

Our attention was caught this month 
by pamphlets from two vendors. Torres 
Ribbon Service has a free brochure de¬ 
signed to make us more informed con¬ 
sumers of film ribbons for our printer. 
The brochure is said to explain different 
coating processes, the resulting variations 
in impression quality, and other matters. 
And Graphic Dimensions offers a $6.95 
booklet, “Getting the Type You Want,” 
which is said to be “especially helpful for 
word processor operators who are baffled 
by the technical jargon used in the type¬ 
setting industry.” 

A PCC Test Report 

We received an “ABS Doubler” free 
from ABS Suppliers. It’s a slip of stiff 
plastic with a hole in it, said to be “a pre¬ 
cision template to permit the conversion 
of single-side diskettes to ‘flippies’ or 
double-side diskettes.” The price of 
$3.50 seemed steep for something the 
size of a playing card, so the Editor was 
dragooned into testing it. Here is his re¬ 
port: 

“The template worked, but takes a 
very steady hand to insert a paper punch 
between the disk and its jacket without 
scratching the surface. With reasonable 
care it can be done, and at the cost of 
disks these days, it may be well worth the 
wracked nerves. Two ordinary diskettes 
were converted and both worked as ‘flip- 
pies’ on a TRS-80 III. No ‘bleed-through’ 
effect was evident.” 

What Price an Atari? 

The influential Minnesota Educa¬ 
tional Computing Consortium (MECC) 
sent a newsletter that tells of its award to 
Atari Inc. of a one-year contract to sup¬ 
ply computers to Minnesota schools. 
Atari, MECC says, will supply Atari 400 
computer systems for $575. That $257 
for the 400 console (RAM not specified), 
$243 for an 810 disk drive, and $75 for a 
black-and-white monitor. For compari¬ 
son, the mail-order houses are currently 
quoting the 400 at $350 and the 810 at 
$450. What makes the MECC prices even 
more remarkable is that the system will 
be sold through Atari dealers in Minne¬ 
sota. We can imagine the factory’s taking 
a loss on a big sale in exchange for the 
prestige and exposure that it will bring. 
But we can’t see a local dealer doing it, 
so those prices are probably close to deal¬ 
er cost. It’s of interest, isn’t it, when a 


small disk system costs less than a good 
business suit? 

Microsoft Moves 

Microsoft, Inc., a company you may 
have heard of, wants you to know that 
they have moved. Note the new address 
and phone number under Contact Points. 


Your 1982 Calendar 

Here are some conferences that you 
might like to attend this year. Start with 
January 28-29 in San Diego, at the Socie¬ 
ty for Computer Simulation’s conference 
on Modeling and Simulation on Micro¬ 
computers. Stay in the sunbelt to swing 
east to Orlando, Florida, for Computer 
Expo ’82 on February 26-28. It’s a show 
for the general public, sponsored by Ad¬ 
venture International. 

Educators will be well-served with 
conferences throughout the rest of the 
spring. MACUL ’82 is a confab put on in 
Kalamazoo, March 1-2, by the Michigan 
Association for Computer Users. Com¬ 
mander Grace M. Hopper will be the fea¬ 
tured speaker. 

Fly out the night of the second to 
Jersey City, NJ; you’ll just make Micro¬ 
computer Week ’82, March 3-7, spon¬ 
sored by CATALYST. This, to judge 
from a packed, 5-page release, will be the 
computer education conference of the 
year, featuring “150 leaders in the field” 
(are there so many?), 66 short courses 
with hands-on labs, and many general ses¬ 
sions and discussion groups. 

The Alaska Association for Comput¬ 
ers in Education (AACE) will be holding 
its 1982 conference in Anchorage, April 
1-3, at which “heavy attendance... 
from all over the state” is expected. It 
may not be too late to reserve a vendor 
booth when you read this. The Computer- 
Using Educators (CUE) will hold their 
1982 southern conference a month later, 
May 14-15 in Irvine, CA. 

Graphics and Robotics persons can, 
if they hustle, still submit a paper to the 
IEEE’s 1982 conference on Pattern Re¬ 
cognition and Image Processing. That 
is planned for June 13-17 in Anaheim, 
CA. 

The big conference outside of the US 
will be put on by Euromicro, September 
5-9 in Haifa, Israel. This one is a must for 
those planning an assault on the Europe¬ 
an market. Submit papers to C. J. van 
Spronsen. 


Comal and Pilot 

“COMAL” is a word that will be 
heard often at Euromicro ’82. COMAL 
(described recently in these pages) is 
being pushed as a better replacement for 
BASIC. The COMAL Users Group, in a 
transport of enthusiasm, claim it “gives 
you the ease of BASIC, along with the 
power of Pascal.” Hmmm. If you have a 
CBM machine with a disk, you can order 
their COMAL starter kit for $47.50 plus 
shipping and find out for yourself. It 
includes the interpreter, a manual, and a 
batch of sample programs. Or send a 
large envelope with 40 cents postage for 
an information packet. 

“Pilot” will doubtless be heard often 
at the US education conferences. It is 
usually touted as a simple language with 
which anyone can write CAI courses. A 
company called the International Insti¬ 
tute of Applied Technology (HAT), has 
prepared a $150, machine-independent, 
implementation of Pilot. They have ver¬ 
sions ready for most Z80 machines, and 
plan to add the IBM Personal Computer 
and some 6502 systems in 1982. 

Another outfit, Stok Computer In¬ 
terface, has a version of Pilot for CP/M 
that they claim is good for CP/M system 
control as well as for CAI courses. Stok 
Pilot can be either interpreted or com¬ 
piled into a .COM file. This $109 lan¬ 
guage, they say, can be used to write 
menu interfaces to any system of CP/M 
commands. 

The N/C Apple 

“N/C” is an acronym for “Numerical 
Control,” the term for driving an indus¬ 
trial milling machine or lathe through a 
sequence of simple movement instruc¬ 
tions expressed as numeric codes. The 
tool program used to be coded in paper 
tape, but we suppose that machines have 
gotten smarter these days. The problem 
of translating a complicated milling 
operation from human terms into de¬ 
tailed motion codes was attacked with 
computers almost as soon as there were 
computers; N/C languages were among 
the first problem-oriented computer lan¬ 
guages. They’ve traditionally been run 
from time-sharing terminals, but now 
Arrow Data Systems has build N/C soft¬ 
ware for the Apple. With an Apple and 
this $1795 package, they claim, “even the 
smallest N/C shop” can prepare N/C tapes 
with a computer. 


10 

6 


Dr. Dobb’s Journal, Number 63, January, 1982 



The Bisync Z80 

Lifeboat is now offering RBTE-80, 
a CP/M-based emulator for the IBM 
batch workstation terminals. Like Radio 
Shack’s similar product for the Model II, 
this package uses the IBM 2780 protocol 
to transfer files between the small system 
and any of a number of makes of main¬ 
frames. That lets the small machine’s 
owner upload jobs for the mainframe to 
do, and download the resulting datasets. 

Two things bother us about this an¬ 
nouncement. The $750 price seems stiff, 
even for a full-feature product with diag¬ 
nostics and line trace facilities. But if that 
judgement is right, the market will take 
care of the problem. There are plenty of 
people with the telecommunications ex¬ 
pertise to produce competitive products. 

In the longer run, it disturbs us to see 
what looks like a Bisync Bandwagon be¬ 
ginning to roll. The Bisync protocol is an 
old architecture. It is just adequate for 
communication on land lines; it falls flat 
when the long delays inherent in satellite 
communications are added. Yet the much 
more efficient, flexible, and reliable X25 
protocol and its near relatives, IBM’s 
SDLC and DEC’s HDLC, are being ig¬ 
nored. That, too, may be an effect of the 
marketplace, but it’s too bad. 

The Video TI 

Texas Instruments has announced a 
Video Controller that lets the 99/4A 
computer control some video tapes and 
the Pioneer video disc. With the accom¬ 
panying Course Designer software, the 
user can write a course that combines 
computer displays, segments of video 
material, and synthesized speech. The 
course software can be stored on the 
second audio track of the video medium. 
This sounds like an impressive package, 
one that will permit the creation of edu¬ 
cational material of terrific quality from 
very reasonably priced equipment. The 
Video Controller is priced at $700, and 
the software costs $200. 

The 1.5MB H89 

Hard on the heels of Heath’s an¬ 
nouncement of quad-density disks for 
the H/Z89 computer came an announce¬ 
ment from Percom. They have prepared 
a 4-drive controller card for their double¬ 
density 5” drives for the H89. The $250 
card contains an extra, parallel port. It 
does not replace the existing Heath con¬ 
troller. Instead, Percom claims that their 
controller and the regular one work in 


tandem. They say that any kind of disk¬ 
ette may be inserted into any drive, and 
their software patch will select the cor¬ 
rect controller to read it. 

The Sensitive Apple 

Strawberry Tree Computer have de¬ 
signed a thermometer card for the Apple 
II. The $260 card contains two independ- 
dent thermometers, each with a 10-foot 
probe, each measuring from -55 to 
+ 125 degrees C. Accompanying software 
takes, records, and displays the measure¬ 
ments, and can handle up to seven cards. 
Sounds like just the thing for monitor¬ 
ing a solar-power system, among other 
things. 


The TallS-100 

Inner Access Corp. has announced a 
couple of S-100 boards that might inter¬ 
est hardware folk. They have a prototype 
board in the new, 10” height. It will ac¬ 
commodate 112 ICs and has regulators 
for the 5- and 12-volt supplies. They also 
have a 13-inch extender card (needed to 
get above the height of a row of 10-inch 
boards). The prototype board is $120, 
the extender is $58. 

In the same vein, here’s a product 
idea for Inner Access or any other hard¬ 
ware outfit with S-100 know-how. Our 
system went out with bus problems re¬ 
cently, and while trying to diagnose it we 
thought of the ideal diagnostic tool. That 
would be a pair of S-100 boards joined 
by a cable. One board would plug into 
the busted bus to buffer and latch its sig¬ 
nals. The other would plug into a working 
system and present the state of the 
machine under test to diagnostic software 
through a set of I/O ports. Proper soft¬ 
ware could find a lot of bus problems, or 
even drive the test system in the manner 
of an in-circuit emulator. Send along the 
announcement as soon as you’ve got it 
working, please. 


Contact Points 

AACE ’82 Conference, 1602 Hillcrest Drive, 
Anchorage, AK 99503; exhibitors call Pat 
Stowers, (907)683-2278. 

ABS Suppliers, POB 8297, Ann Arbor, MI 
48107; (313) 971-1404. 

Arrow Data Systems, 5910 East Washing¬ 
ton, Los Angeles, CA 90040; (213) 726- 
9440. 

CATALYST Conference, HI 12, Jersey City 
State College, 2039 Kennedy Boulevard, 
Jersey City, NJ 07305; (201) 434-2154 or 
(201)547-3094. 

COMAL Users Group, 5501 Groveland Ter¬ 
race, Madison, WI 53716. 

Computer Expo ’82, Tom Blayney, Execu¬ 
tive Director, POB 1185, Longwood, FL 
32750;(305) 339-1731. 

CUE Computers in Education ’82, Craig 
Walker chairperson, Arrowview Intermedi¬ 
ate School, 2299 North “G” Street, San 
Bernadino,CA 92405; (714) 886-9118. 
Euromicro 1982 Conference, 4 Place Felix 
Eboue, 75012 Paris, France; (1)341.08.46; 
telex 211801. 

Graphic Dimensions, 8 Fredrick Road, Pitts- 
ford, NY 14534. 

IEEE Computer Society, 1982 Conference 
on Pattern Recognition, POB 639, Silver 
Spring, MD 20901; (301) 589-3386. Sub¬ 
mit papers to Dr. Richard P. Kruger, Los 
Alamos National Laboratory, Los Alamos, 
NM 87545. 

I1AT, 20010 Century Boulevard, German¬ 
town, MD 20767; (301) 428-9010. 

Inner Access Corp., 517-K Marine View, 
Belmont, CA 94002; (415) 591-8295. 
Lifeboat Associates, 1651 Third Avenue, 
New York, NY 10028; (212) 860-0300. 
MACUL ’82, c/o Carolyn Gilbreath, Oak¬ 
land Schools, 2100 Pontiac Lake Road, 
Pontiac, MI 48054; (313) 858-1898. 
Microsoft, Inc., 10070 Northup Way, Belle¬ 
vue, WA 98004; (206) 828-8080. 

Percom, 11220 Pagemill Road, Dallas, TX 
75243;(214) 340-7081. 

Society for Computer Simulation (SCS), 
POB 2228, La Jolla, CA 92038. 

C. J. van Spronsen, Euromicro Program 
Chairman, Delft University of Technology, 
P. O. Box 5031, 2600 GA Delft, The 
Netherlands; (31 )(15)786227; telex 38070. 

Stok Computer Interface, POB 501, Wood- 
side, NY 11377; (212) 426-7022. 
Strawberry Tree Computers, 949 Cascade 
Drive, Sunnyvale, CA 94087; (408) 736- 
3083. 

Texas Instruments, Customer Relations, 
POB 53, Lubbock, TX 79408. 

Torres Ribbon Service, POB 1727, Red¬ 
lands, CA 92373. 


Dr. Dobb’s Journal, Number 63, January, 1982 


7 



Interfacing the 68000 
to an AIM 65 


T oday there are several 16-bit CPUs on the market; for 
a number of reasons the most famous are only three, 
the 8086, the Z8000 and the Motorola MC68000. We 
have been hearing a lot about what they can and cannot do; as 
a matter of fact, boards employing one of such CPUs did not 
have too much luck. 

This recalls to memory what happened years ago: every¬ 
body realized that the Z80 was more powerful than the 8080, 
but an upgrading kit for 8080 machines simply did not sell. 
The reason was not the lack of Z80 software, because the Z80 
can run 8080 software. It was that the user was not willing to 
spend money for something maybe better but not “useful.” 

Nowadays we have to ask ourselves how useful is a 16-bit 
CPU; we feel it is not for the computer consumer, the one who 
buys a computer just to play games or little more. There is a 
range of applications requiring more computational power 
than what is currently available on 8-bit CPUs. When we say 
“computational power,” we do not only mean an extended in¬ 
struction set or the capability of running standard programs 
ten times faster: all those aspects have to be considered as a 
whole, along with all the hardware facilities. Many concepts 
developed for the old mainframes are becoming prominent in 
microsystem design: can you imagine a multi-task, multi¬ 
processor system without the test-and-set instruction and the 
user-supervisor environment? Even the hobbyist with little 
background can successfully experiment with concurrent pro¬ 
gramming on a fairly small system, provided he has the right 
CPU to start with. 

We think that a good 16-bit CPU has enough power to 
handle fairly sophisticated, concurrent programming. Among 
the available devices, the MC68000 is a good choice. Besides 
its nice hardware structure, the following points are to be 
taken into account: 

1) Its instructions are powerful but limited in number. We feel 
that a large instruction set does not necessarily make a pro¬ 
cessor more powerful, it may instead confuse the program¬ 
mer. 

2) The instruction set is microprogrammed; it may be im¬ 
proved without changing the overall structure. 

3) Its pipelined structure is optimized for speed. 

4) It is asynchronous; this feature allows for easy interfacing 
with all kinds of devices and peripherals. 

The 68000 has some drawbacks, too: 

1) It does not provide a dynamic memory refresh like the 
Z8000; this is a really handy feature, even if software re¬ 
fresh is an alternative. 

2) Its most interesting supporting chips are not scheduled to 
be available in the near future. 

3) Like most of its competitors, there is not too much soft¬ 
ware available if we exclude that delivered from Motorola 
for their boards and development systems (which, in any 
case, are quite expensive). 


Luca Fusina and Claudio Granuzzo 

Luca Fusina, Via Mocenigo 8, Verona 37100, Italy. 

All the article content may be used for any non-commercial 
purpose. 


Nowadays it seems that what really interests the computer 
consumer is software. He does not care too much about the 
underlying hardware, he is most concerned about the programs 
he can run on his machine. At most he considers the interface 
capabilities of his computer, but usually he even does not 
know the internal hardware structure. In our opinion there are 
still some people interested in system design: people who like 
to experiment with new devices. The tool for this kind of 
work is called a development system. After the hobbyist elimi¬ 
nates the ones that are too expensive, what is left is an evalua¬ 
tion system which basically is a single board equipped with a 
CPU and a handful of switches and LEDs. Experimenting 
with such boards is time consuming and not rewarding at all in 
any case. There must be a better solution. 

The Idea 

Almost all of the computer enthusiasts around already 
own a microcomputer. Why not use our own system to control 
a 68000? In this article we will describe this hardware and 
software implementation on a Rockwell AIM 65. For the read¬ 
er who is unfamiliar with this machine we will summarize its 
features. It is a single board based on the 6502 with a 
QWERTY keyboard, a 20-column thermal printer and an al¬ 
phanumeric display, 4K byte of RAM, an 8K byte ROM moni¬ 
tor, a 4K byte ROM assembler, and 2 Versatile Interface 
Adapter chips for I/O and expansion. We had to make only a 
few trivial hardware changes. 

We have said, indeed, that we are going to control our 
68000, but which way? We want to be able to control it dur¬ 
ing each read or write cycle (from now on simply cycle), in 
real time, changing the mode of operation according to neces¬ 
sity among all the ones available to our system. Furthermore, 
we want to be able to manipulate during each cycle all the 
68000 control signals; this way we can simulate interrupts, 
multi-processing and so on. 

The Hardware 

All we needed to implement our idea was nine eight-bit 
I/O ports and a couple of decoders. The 68000 became a peri¬ 
pheral connected to the AIM bus at a certain address. On the 
AIM expansion connector we found all we needed: the 8-bit 
bi-directional data lines, the 16-bit address lines, and two con¬ 
trol signals: R/W and 02 which are used for synchronizing 
R/W operations. Figure 1 (page 15) shows the block diagram of 
the interface; Figure 2 (page 16) is the schematic. For all the 
6502 timings, the reader can refer to the 6502 hardware manual. 

From now on we assume the reader understands 68000 
hardware and software details; refer to the MC68000 user’s 
manual for a complete description of this processor. 

As the 68 000 is asy nchronous, we can control each cycle us¬ 
ing the signal DTACK, which stands for data transfer acknow¬ 
ledge. When the 68000 wants to p erform a read or a write, it 
asserts the AS signal and waits for DTACK. At this point our 
AIM pro gram can do all it has to, and when finished it asserts 
DTACK by writing to location S8XXB, signaling the 68000 to 
continue. IC 20 (a 74LS74 flip-flop) takes care of negating 
DTACK when 68000 negates AS. 

All 68000 signals are interfaced to the AIM through six 
DM81LS95 buffers and three 74LS373 latches. The 68000 
interface is seen by the AIM as a 1Kbyte memory. The 6502 


n 

8 


Dr. Dobb’s Journal, Number 63, January, 1982 





can address up to sixty-four 1Kbyte pages and the board can 
be located anywhere inside them, provided there are no con¬ 
flicts with the AIM 65 requirements. This is accomplished with 
a DM8131 six-bit comparator (IC 10). To select the right page 
the user must supply the appropriate logic levels to the com¬ 
parator inputs. In our implementation the board is located at 
$8000. Inside this address space there are sixteen meaningful 
locations, from address $8XX0 to address $8XXF. Only 
twelve are, however, actually used and only the first nine are 
used to interface the 68000, by means of selecting one of the 
I/O ports. Selection 10 (signal Y9 in Figure 2, address S8XX9) 
is used to control the HALT li ne. Num ber ele ven is not con¬ 
nected. Number twelve asserts DTACK (signal Yl 1 in Figure 
2, address S8XXB). Refer to Figures number 3, 4, 5 (page 17) 
for a detailed explanation about how the ports are arranged. 
Note that with this hardware it is not possible to use the M 
command of the AIM monitor inside the board space. 

_Jhere are two 68000 signals not connected to any port: 

VMA (valid memory address) and E (enable). Motorola imple¬ 
mented these signals to maintain compatibility with existing 
6800 peripherals. In our opinion it is better to use them as test 
points. The user can easily add one additional port to the 
interface to monitor them under program control. 

The network of open collector inverting gates connected 
to the 555 timer and the S8 XX 9 selecti on is used to interface 
correctly the 68000 HALT and RESET signals, which are bi¬ 
directional. Two LEDs can be used to monitor their logic 
levels. The board performs an automatic power- on rese t; a 
manual reset is also provided, as well as software HALT and 
RESET control 

The Software 

Before entering into program details, it may be a good 
idea to lay down its objectives: 

Run-time control of the dynamic evolution of each 
68000 instruction step using the AIM keyboard. It is possible 
to execute a program stopping the 68000 every cycle, or to 
execute any number of instructions consecutively; a dynamic 
switch between these two modes is possible, too. 

Run-time control of the 68000 input control signal (IC 
19, #74LS374 latch). The AIM 65 keyboard can be used to 
supply a byte to be stored in that latch. We called this feature 
“dummy memory.” 

Output on display/printer of each 68000 cycle including 
addresses, data and control signals coming out from the 
processor. 

Dynamic allocation of memory. 68000 memory is seg¬ 
mented and each segment base address can be located any¬ 
where inside the AIM free RAM. If the 68000 is doing a read, 
it is possible to enter data from keyboard; if it is doing a write, 
it is possible to do a data display. This way no effective mem¬ 
ory operations are done. 

Use of all AIM 65 peripherals and utilities under 68000 
program control. We defined that a 68000 segment cannot 
be greater than 64Kbytes (in automatic mode). If a write is 
performed inside the first 256 bytes of the last 1Kbyte page 
available to a segment (address S00FCXX) it is assumed that a 
6502 subroutine call is made. The 68000 lower data byte is 
loaded in the 6502 accumulator. The 68000 upper data byte 
is used to index a table of pointers to 6502 subroutines. On 
return, the 6502 accumulator is copied into two locations, one 


inside the 68000 user data segment and the other inside its 
supervisor data segment. 

The 68000 is operated cycle by cycle by the program in 
Listing 1, p. 36. As the program currently running evolves, 
whatever happens is shown on the display/printer or whatever 
is connected to the AIM 65. Various instruction combinations 
can be tried, and the operation of the 68000 becomes clear. 

The five objectives that we have so far discussed are im¬ 
plemented in a program 5 19 bytes long. The user has to select 
the operating mode by storing an appropriate value in a con¬ 
trol byte, CONTRL. Each bit controls a mode as explained 
below. 

If bit 0 is set, after printing the 68000 address the AIM 65 
program requests a byte from the keyboard. It will be stored 
in the latch connected to the 68000 input control signals. 

If bit 1 is set, manual mode is selected, otherwise auto¬ 
matic mode is assumed. Manual mode corresponds to the 
dummy memory R/W mode previously discussed; in the auto 
mode, R/W is performed from memory._ 

If bit 2 is set, before issuing the DTACK signal the user is 
requested to validate all operations performed during the 
current cycle by entering a carriage return. This is also called 
step mode. Any other character will repeat the current cycle. 
No such validation check is made if bit 2 is cleared. 

If bit 4 is set, fast mode is selected. When this mode is 
selected 68000 cycle status output is suppressed. This allows 
for fast 68000 program running, as a great deal of the AIM 
housekeeping time is spent reporting things on display/printer. 

The previous modes can be mixed together. Fast mode 
overrides all the others. When it is set, the other modes are 
used to select the mode that will be entered upon error. Dy¬ 
namic mode changing can be accomplished by executing a 
68000 instruction that stores a new value in the control varia¬ 
ble. Thus, a 68000 program can put itself in Step mode. 

Memory segmented is implemented using two tables, 
FCTAB and MAXADD. They specify the AIM 65 base ad¬ 
dresses of each 68000 segment and their extension. These lat¬ 
ter values must be supplied, and they must be consistent with 
the former ones. Of course, each 68000 segment starts from 
location $0000000. 

Final Thoughts 

We have so far discussed how to build from scratch a small 
development system for Motorola’s 16-bit processor, the 
MC68000. The underlying concepts are quite general, and it 
should not be difficult to implement our idea using the read¬ 
er’s own computer instead of our AIM 65. The ones familiar 
with this machine will have already noted that the accompany¬ 
ing program was not listed with the 20-column thermal printer 
available on the AIM board, and that the assembler was modi¬ 
fied. 

In fact, besides using the AIM 65 as an experimental com¬ 
puter, we use it as our “big” system. Anyone who is interested 
and wants more information about how we did it may write to 
the authors. Let us now report the impressions about the 
MC68000 that we gained using the board we have here pre¬ 
sented. We appreciated most the power and simplicity of its 
instruction set. Some things shocked us, though. For example, 
you can try to execute a CLR to memory and see what hap¬ 
pens. Before clearing the desired locations, the processor reads 
them. This, of course, wastes time and has no usefulness. Any- 


Dr. Dobb’s Journal, Number 63, January, 1982 


13 

9 




way, summing up ail the againsts and fors, it proved to be a 
superior processor. After executing just a few programs, the 
user accustomed to 8-bit microprocessors will no longer be 
satisfied with them. 

The MC68000 architecture is a bit different from standard 
8-bit machines. The reader who will use our board might then 
have some problems. Let us give some hints that may prove 
useful. 

The 68000 has a pipelined structure. This means that it 
fetches one or more words before actually executing the in¬ 
struction. These words, which may be subsequent instructions, 
are printed and displayed. Such a thing may lead one to think 
that the processor is not executing properly; on the contrary, 
it is doing its job. Again, during stacking operations, words 
may not be stacked following the address ordering; the overall 
stacking procedure is still correct. 

The MC68000 is a 16-bit machine, therefore it addresses 
by words. Instructions must start on even boundaries. If the 
user specifies the initial PC to be at an odd address, the 68000 
will enter an address error exception. If the supervisor stack 
point also starts at an odd address, well, you will be in trouble. 


There are, of course, many other things that should be said, 
but it may be more interesting to explore the 68000 world 
yourself. 

Concluding, we would like to point out that everything 
we have said so far is not restricted to a particular machine. 
Some readers will like to experiment with a different CPU, say 
the Z8000, and we think they will not have too many prob¬ 
lems adapting our ideas to their needs. After a few weeks of 
experimenting with our board, the need for more sophisticated 
software may arise. It should not be too difficult to write a 
cross assembler using AIM BASIC. This would eliminate the 
need for hand compiling all the 68000 instructions. Again, it is 
possible to slightly modify the hardware to let the 68000 have 
an independent life, without passing through the AIM for 
executing its instructions. 

Italy is not that far away; anyone who wants to write us 
to exchange opinions about computers is encouraged to do so. 

»»J 

(Figures 2-6 on pages 16 and 17) 

(Listing begins on page 36) 



STEP 

CONTROL 


CODED 


IES 

6502 ADDRESS 
AND CONTROL BUS 


BOARD SELECTION 
AND DECODING 
LOGIC 



Dr. Dobb’s Journal, Number 63, January, 1982 

IF 


Figure 1 


15 










16 


Dr. Dobb’s Journal, Number 63, January, 1982 

11 


Schematic of MC68000/AIM 65 interface 

























68000 On-Board Selections 

Address (Hex) 

Selection 

8XX0 

68000 lower 8 data bit (WRITE) 

8XX1 

68000 upper 8 data bit (WRITE) 

8XX2 

68000 output control signals 


(refer to Figure 4) 

8XX3 

68000 input control signals 


(refer to Figure 5) 

8XX4 

68000 lower 8 address bit 

8XX5 

68000 middle 8 address bit 

8XX6 

68000 upper 7 address bit 

8XX7 

68000 lower 8 data bit (READ) 

8XX8 

68000 upper 8 data bit (READ) 

8XX9 

halt 

8XXA 

N.C. (not connected) 

8XXB 

DTACK 


Figure 3 


68000 Output Control Signals 
(IC22) 


Bit No. on AIM Data Bus Signal 
ADO WRITE 

ADI CDS 

AD2 UDS 

AD3 AS 

AD4 BG 

AD5 FC2 

AD6 FC1 

AD7 FCO 


write 

lower data strobe 
upper data strobe 
address select 
bus grant 
function code 2 
function code 1 
function code 0 



68000 Input Control Signals 
(IC19) 

Bit No. on AIM Data Bus Signal 


ADO 

bCaCk 

bus grant ack 

ADI 

BEr! 

bus error 

AD2 

N.C. (not connected) 

AD3 

VPa 

valid peripheral 
address 

AD4 

m 

bus request 

AD5 

IPL0 

interrupt priority 
level 0 

AD6 

IPL1 

interrupt priority 
level 1 

AD7 

IPL2 

Figure 5 

interrupt priority 
level 2 


Figure 4 


Meaning of the fields in the AIM listing of the 68000 
program: 


Data: 

68000 Data Bus 

Optional Field 1: 

Byte stored in the 68000 
Control Input Lines 

Optional Field2: 

M = ManualMode Else Blank 


Address: 

68000 Address Bus 

R/WCode: 

RW/WW=R/W Word 
WH/RH=R/W High byte of a 
Word 

RL/WL=R/W Low Byte of a 
Word 

68000 Function Code: 

SP = Supervisor Program 
UP = User Program 
SD = Supervisor Data 
UD = User Data 
IA = Interrupt Acknowledge 

Figure 6 


(Listing begins on page 36) 


Dr. Dobb’s Journal, Number 63, January, 1982 

IT 








A Portable Screen-Oriented 
Editor 


A re you tired of using a miserable 
line-oriented editor? Are you 
unwilling to pay several hundred 
dollars for a full-screen editor? Are you 
worried that your text editor will become 
obsolete if you change machines or oper¬ 
ating systems? Are you frustrated that 
you can’t make even simple changes to 
your editor? Are you unable to adapt 
your editor for more than one type of 
terminal? If so, here is an editor for you. 

In the past five years I have used 
several different text editors on my com¬ 
puter system at home. My first editor was 
a typical character-oriented text editor. 
This editor did have some good points, 
but most of the time it forced me to type 
a lot more than I wanted to. Also, this 
editor was unsafe to use. Some mistakes 
that I could easily make caused the editor 
to lose many lines of text. 

My second editor had more poten¬ 
tial. It allowed me to do simple things 
simply. There were easy-to-use commands 
to move the cursor along a line, and to in¬ 
sert and delete characters on a line. The 
editor was also safe. Dangerous com¬ 
mands took more typing than harmless 
commands so editing was much less nerve 
wracking. I never destroyed more than a 
few moments of work with this editor. 

This editor did have one major draw¬ 
back: it didn’t use the capabilities of 
the video screen I was using. As a rule, 
only one line of text was visible on 
the screen at a time and that line was al¬ 
ways on the bottom of the screen. So 
while the editor had all the commands 
needed to edit files quickly, in practice 
the editor was difficult to use. I kept 
wanting to see the lines above and below 
the line where I was in order to make sure 
that I was making changes in the proper 
context. 

I basically liked the editor so I modi¬ 
fied it slightly so the screen would show 
several lines above the line being edited. 
This modification was actually a very 
small one; the editor still wasn’t perfectly 
adapted to video displays (the cursor still 
couldn’t move off the bottom line), but 
the editor was almost as easy to use as a 
full-screen editor. 

Of course, I made other adjustments 
to that editor. I became fascinated with 
changing the editor’s commands. I no- 


Edward K. Ream 


Edward K. Ream, 1850 Summit Ave., 
Madison, WI 53705. 


ticed a ripple effect; a change in the de¬ 
sign of one command might lead me to 
modify five or six other commands. I 
spent many pleasant hours just thinking 
about how commands are interrelated. 

After several months, I thought I had 
a pretty good editor. It was safe. It was 
predictable. Although complicated edit¬ 
ing tasks sometimes took considerable 
work, simple editing jobs were very 
simple. 

This editor had only one flaw, but 
that turned out to be fatal. It was written 
in assembly language. The editor worked 
fine until I got a new set of disks and a 
new operating system (CP/M). It soon 
became woefully apparent that almost 
50% of the editor would have to be re¬ 
written in order to transport it from the 
old operating system to the new. It 
looked as though I would be spending 
many weeks on this unpleasant project. 

As luck would have it an alternative 
presented itself just at this time. Dr. 
Dobb's Journal published two articles by 
Ron Cain in which he presented a com¬ 
piler for a language he called Small-C. 
(See DDJ #45 and #48, May and Sep¬ 
tember, 1980.) Small-C is a subset of the 
full langauge called C, one of the best lan¬ 
guages for writing systems programs like 
compilers and editors. Small-C would be 
perfect as a language in which to write a 
new editor. Just as importantly, the com¬ 
piler for Small-C was written in Small-C 
itself. Although it may not be immediate¬ 
ly obvious, that meant that the compiler 
formed the basis of a completely portable 
computer system. All programs written 
in Small-C could be moved from one 
machine to another just by changing a 
few routines in the compiler. The compil¬ 
er was in the public domain, which meant 
I could use it or modify it however I 
wanted to. Clearly, the Small-C compiler 
was a great tool. 

I obtained an excellent version of 
this compiler for the CP/M operating sys¬ 
tem from a company called The Code 
Works (TM). I recommend this compiler. 
It is well documented; it works reliably; 
all the source for the compiler is provided ; 
and it’s all in the public domain. At $17 
it is one of the best bargains around. 

After becoming acquainted with this 
compiler, I started work on what I hope 
will be the last version of this editor. Re¬ 
member that the only thing wrong with 
my previous editor was that I couldn’t 
move it easily to a new operating system. 
Thus, portability became a top priority. 


I wanted this editor to adapt easily to 
new operating systems or new display de¬ 
vices. 

The Small-C editor shares many fea¬ 
tures with the old assembly language edi¬ 
tor. I saw no reason to change a success¬ 
ful design. As a result, the new editor is as 
simple to use and reliable as the old edi¬ 
tor was. However, the new editor has 
been completely rewritten. This has al¬ 
lowed me to improve many of the inter¬ 
nal details of the editor’s operation. I 
have also added full-screen-editing capa¬ 
bility and a prompt line. 

As far as I can tell the new editor is 
very portable. It has been used on widely 
differing terminals without making any 
programming changes. The editor comes 
with a configuration program which 
asks questions about your terminal. The 
configuration program then automatically 
produces two files that tailor the editor 
to your particular keyboard and display 
screen. I have not moved the editor to 
any other operating system besides CP/M, 
but I don’t expect great problems in 
doing so. All code that depends on a par¬ 
ticular operating system has been isolated 
to a few routines all located on one file. 
Moving to a new system requires only 
that these few routines be rewritten. 

Basic Features of the Screen Editor 

I hope by now you are eager to learn 
what this editor can do. Let’s take a clos¬ 
er look at it. We will start by talking 
about some of the basic concepts and 
terms that are used throughout to de¬ 
scribe the editor. 

The screen editor is comprised of 
several modes. You can switch between 
modes, but the editor can’t be in two 
modes at the same time. The editor be¬ 
haves differently in each mode, so you 
use each mode to do a particular type of 
editing. 

There are three modes: edit mode, 
command mode and insert mode. You 
use edit mode for making small changes 
in many different lines. Command mode 
is used for making larger (hence potential¬ 
ly more dangerous) changes to the whole 
file you are editing. You must be in com¬ 
mand mode to do anything that will 
change files on the disk. You use insert 
mode for making a series of insertions 
into the text. First drafts are often en¬ 
tered in this mode. 

You use commands to make things 
happen in each mode. Which commands 
you can use depends on what mode you 


18 


Dr. Dobb’s Journal, Number 63, January, 1982 

13 






are in. Do not confuse the terms “com¬ 
mands” and “command mode.” Every 
mode has a set of commands which you 
can use in that mode. Command mode 
has its own set of commands. 

Special characters are one-letter 
commands. Special characters must be 
control keys, so you can use these com¬ 
mands in places where the editor might 
not otherwise expect a command. 

The prompt line is the top line of the 
screen. It tells you things like what line 
you are editing and what mode you are 
in. If you get confused about what mode 
you are in, you can always glance at the 
prompt line and get your bearings. 

Figure 1 shows what the prompt line 
looks like. The line field tells what line 
of the file you are currently editing. The 
column field tells what column on the 
screen the cursor is on. The column field 
mainly helps you align columns of text 
correctly. The next field tells you the 
name of the file you are currently editing. 
This field is set and used by several 
command-mode commands which will be 
discussed later on. The last field tells you 
what mode you are in. 

Several edit-mode commands consist 
of two or more letters. These edit-mode 
commands are called extended commands. 
After you type the first letter of such a 
command, but before you type the last 
letter, the prompt line will indicate that 
you must type one more letter to finish 
the extended command. For example, 
after you type an “s” to enter the edit¬ 
mode search command the prompt line’s 
mode field will contain “edit: search”. 

The cursor is a distinctive character 
on the screen. On most video terminals 
this marker is a character shown with 
reverse video. In command mode you al¬ 
ways type commands on the bottom line 
so the cursor is always on the bottom 
line. In edit mode and insert mode the 
cursor is always on the current line. 

The current line is the only line you 
can edit. In command mode the current 
line may not be shown on the screen, but 
in edit and insert modes the current line 
is shown and it contains the cursor. If 
you want to make a change to a line you 
must first move the cursor to that line. 

The buffer is a part of the comput¬ 
er’s storage which holds the file you are 
editing. In order to edit a disk file, you 
must first read the disk file into the buf¬ 
fer using the load command. As you edit 
the file, the changes you make are made 
only to the buffer, not to your disk file. 


Before you end your editing session you 
must copy the buffer back to a disk file 
using the save or resave commands. The 
editor keeps track of whether you have 
done this; it won’t let you forget to save 
your work. 

The window is a part of the screen 
which shows a portion of the buffer. In 
edit and insert modes the window fills all 
of the screen except the prompt line. You 
can think of the file as a scroll of parch¬ 
ment which unwinds under the window 
as you move the cursor. The window is 
not shown in command mode. 

Now let’s look more closely at the 
editor’s commands. We’ll start with spe¬ 
cial characters, which are commands that 
may be used in either insert or edit 
modes. Then we will look at other com¬ 
mands which are clique to a particular 
mode. 

Special Characters 

Special characters act the same in all 
modes. Special characters must be control 
characters so that the editor may always 
distinguish special characters from regular 
text. 

There are 14 special characters; all 14 
may be used in either edit mode or insert 
mode. Only a few may be used in com¬ 
mand mode. Figure 2 shows how to 
switch between modes using three of 
these keys. Figure 3 summarizes what all 
these special keys do. 

You can use the configuration pro¬ 
gram to choose which keys on your key¬ 
board to use for each special character. 
Thus, I won’t be able to be specific about 
what key on your keyboard you will ac¬ 
tually hit in order to type, for instance, 
the down key. I’ll often refer to special 
characters as special keys; for example, 


I’ll call the down special character the 
down key. 

The left and right keys just move the 
cursor. They do not cause changes to 
lines. These keys are always “anchored” 
to the current line; you can’t move off 
the current line by using these keys. If 
you hit the right key while the cursor is 
at the right margin, nothing will happen. 
Similarly, nothing will happen if you hit 
the left key while the cursor is at the left 
margin. 

The up and down keys move the cur¬ 
sor up and down on the screen. You can’t 
move the cursor above line 1 of the file, 
nor can you move the cursor below the 
last line of the file. Both these keys also 
switch the editor to edit mode. 

The insert up key inserts a blank line 
above the current line while the insert 
down key inserts a blank line below the 
current line. Both these keys also switch 
the editor to insert mode. 

The delete character key deletes the 
character to the left of the cursor. This 
key is anchored to the current line; no¬ 
thing is deleted if the cursor is at the left 
margin. The delete line key deletes the 
entire line on which the cursor rests. 

The undo key always undoes what¬ 
ever editing you have done on the current 
line since the last time the cursor came to 
the current line. 

The insert key switches the editor to 
insert mode. Similarly, the command key 
switches the editor to command mode 
and the edit key switches the editor to 
edit mode. 

The split key splits the current line 
into two pieces. Everything to the left of 
the cursor stays right where it is. All 
other characters are moved from the 
current line. Both these keys also switch 
the editor to insert mode. 


Dr. Dobb’s Journal, Number 63, January, 1982 


19 



The join key is the opposite of the 
split key; it combines two lines into one 
line. The join key appends the current 
line to the line above it, then deletes the 
lower line. 

Edit Mode 

Edit-mode commands are normal let¬ 
ters; you don’t need to use special keys. 
This speeds typing. You can, however, 
use the special keys in edit mode if you 
want to. 

Besides the special characters you 
can use the following one-letter edit¬ 
mode commands: space, b, c, d, e, g, i, k, 
s, u, and x. These letters stand for begin, 
command, down, end, go, insert, kill, 
search, up, and exchange. Note that all 
these commands may be typed either in 
upper case or in lower case. Letters which 


are neither edit-mode commands nor spe¬ 
cial keys are simply ignored. Figure 4 is a 
brief summary of these commands. The 
following paragraphs explain what these 
commands do in greater detail. 

The space bar moves the cursor right 
one column. Nothing happens if the cur¬ 
sor is already on the rightmost column of 
the screen. 

The b command puts the cursor at 
the beginning (left-hand margin) of the 
line. 

The c command switches the editor 
to command mode. 

The d command causes the cursor to 
move down rapidly. The cursor keeps 
moving until it reaches the last line of the 
file or until you type any key. 

The e command moves the cursor to 
the right end of the line. 


command 

The command key switches 

mode 

to command mode. 

edit 

insert 

mode 

mode 

The edit key switches 

The insert key switches 

to edit mode. 

to insert mode. 

Figure 2: The Modes of the Editor 


The edit, insert and command special characters switch the editor from mode to 

mode. 



Special Character 

Function 

up key: 

move cursor up 1 row & enter edit mode 

down key: 

move cursor down 1 row & enter edit mode 

•left key: 

move cursor left 1 character 

right key: 

move cursor right 1 character 

insert up key: 

insert line above current line & enter insert mode 

insert down key: 

insert line below current line & enter insert mode 

•delete character key: 

delete character to left of the cursor 

•delete line key: 

delete the current line 

•undo key: 

undo all changes to the current line 

•insert key: 

enter insert mode 

•edit key: 

enter edit mode 

command key: 

enter command mode 

split key: 

split the current line into two lines 

join key: 

combine two lines into one line 

Figure 3: Special Characters 

Special characters are one-character commands that are valid in edit mode and 

insert mode. Special characters which may be used in command mode are indi¬ 
cated by an asterisk (•). 


The i command switches the editor 
to insert mode. 

The g command moves the cursor to 
another line. The g command is an ex¬ 
tended command; after you type the g, 
the cursor will move to the prompt line. 
The prompt line will show “edit: goto:” 
Now type a line number followed by a 
carriage return. The cursor will move to 
the line whose number you typed. If you 
do not type a valid number the g command 
does nothing. Leading blanks or minus 
signs are not allowed. The cursor will 
move to the last line of the buffer if the 
number you type is larger than the num¬ 
ber of lines in the buffer. 

The k command is a two-letter com¬ 
mand. The second letter you type (the 
first character after the k) is a search 
character. The k command deletes from 
the cursor up to but not including the 
next occurence of the search character to 
the right of the cursor. Everything from 
the cursor to the end of the line is deleted 
if the search character does not appear to 
the right of the cursor on the current line. 
After you hit the k and before you hit 
the search character the prompt line will 
show “edit: kill”. If you wish to cancel 
the k command you can hit any control 
character. The k command will be 
stopped and no deletion will be made. 

The r command is another two-letter 
command. The second character you type 
(the first character after the s) is a search 
character. The s command moves the cur¬ 
sor to the next occurence of the search 
character which appears to the right of 
the cursor. The cursor moves to the end 
of the current line if the search character 
does not occur to the right of the cursor. 
After you hit the s and before you hit the 
search character the prompt line will 
show “edit: search”. 

The u command moves the cursor up 
rapidly. The cursor keeps moving until 
it reaches the first line of the file or until 
you hit any key. 

The x command is another two- 
letter command. The second character 
you type replaces the character under the 
cursor. The prompt line will show “edit: 
exchange” until you hit the second char¬ 
acter. If you hit a control character no 
change is made and the x command is 
cancelled. 


Insert Mode 

Use insert mode to insert many lines 
of text at once. In insert mode anything 


20 


Dr. Dobb’s Journal, Number 63, January, 1982 





you type (except special keys) will be in¬ 
serted into the text to the left of the 
cursor. You may use special keys in in¬ 
sert mode exactly as in edit mode. 

Command Mode 

You use command mode to do po¬ 
tentially dangerous things like making 
multiple changes to the buffer or like up¬ 
dating your files. For this reason, all 
command-mode commands require you 
to type several characters with a carriage 
return at the end. 

The editor starts off in command 
mode after you invoke it from your 
operating system. 

You may use either the edit key or 
the insert key to exit from command 
mode. You can also use the g command¬ 
mode command or the find command¬ 
mode command to leave command mode. 
When the editor leaves command mode 
the screen is redrawn to show the current 
line. 

The cursor is on the bottom line of 
the screen whenever the editor is in com¬ 
mand mode. This line is called the com¬ 
mand line. As you type commands, what 
you type will be shown on this line. Use 
either the delete character key or the 
right key to delete the last character you 
typed. Use the undo key to delete the en¬ 
tire command line. 

Several command-mode commands 
take arguments. There are three types of 
arguments: range arguments, file names 
and line numbers. In the description be¬ 
low, range arguments will be denoted by 
<line range>, file name arguments will 
be denoted by < filename > and line 
numbers will be denoted by < n >. 


Range arguments denote the range of 
lines in the buffer for which a command 
will take effect. For example, 

list 25 50 

means list all lines from line 25 to line 50 
inclusive, 

list 

means list all the lines of the buffer, and 
list 300 

means list line 300 and all following lines. 
Range arguments, if present, must be 
nonnegative integers. If two numbers are 
entered, the first must be no larger than 
the second. 0 is equivalent to 1. A num¬ 
ber larger than the largest line number is 
equivalent to the largest line number. 

Filename arguments are the name of 
a file to be used in a command. For ex¬ 
ample, 

load myfile.doc 

causes the file myfile.doc to replace what¬ 
ever is in the buffer. Note that no quota¬ 
tion marks are used around filename argu¬ 
ments. Filename arguments optionally 
may be preceded by disk drive names. 
For example, 

load brmyfile.doc 

loads the buffer from the file myfile.doc 
which must be found on drive b. 

The editor protects you from de¬ 
stroying the buffer unintentionally. If a 
command would cause the buffer to be 
erased and you have not already saved the 
buffer on a disk file the editor will ask: 

buffer not saved, proceed ? 


If you type y or Y, the command will be 
done and the buffer will be erased. If you 
type anything else no change will be 
made to the buffer and the message 
“cancelled” will be printed on the screen. 
Note, however, that the delete com¬ 
mand does not protect you in this way. 
Use the delete command with caution. 

You may interrupt or cancel the 
change, find, list and search commands. If 
you type any character except a blank 
the command will be cancelled immedi¬ 
ately. If you type a blank the command 
will be temporarily suspended. Type 
another blank to continue, or any other 
character to cancel the command. 

The following paragraphs discuss all 
the command-mode commands. Figure 5 
gives a short summary of how to invoke 
these commands and how to use them. 

append < filename > 

The append command inserts the 
named file into the buffer after the cur¬ 
rent line. In other words, the position of 
the cursor affects where the file will be 
inserted. This command adds to the buf¬ 
fer; it does not delete what is already 
there. 

change < line range > 

The change command searches all 
lines in <line range > for an instance of a 
search mask. If the search mask is found 
it is replaced by the change mask. After 
you type change <line range > the com¬ 
mand will ask: 

search mask ? 

At this point type the pattern you are 
searching for, followed by a carriage re¬ 
turn. Then you will be asked: 

change mask ? 

Now you type the pattern you want the 
search mask to be replaced by. For exam¬ 
ple, 

change 100 300 
search mask ? abc 
change mask ? xyz 

will change abc to xyz in all lines from 
100 to 300. Thus, the line: 

know your abc’s 
would be changed into: 

know your xyz’s 

Only the first instance of abc on each line 
would be changed. The line: 

know your abc’s. The abc’s are 
very important. 


Command 

Mnemonic 

Function 

space 

(over) 

move cursor right 1 character 

b 

(Begin) 

move cursor to start of line 

c 

(Command) 

enter command mode 

d 

(Down) 

scroll screen down 

e 

(End) 

move cursor to end of line 

g<n> 

(Go) 

go to line number <n> 

i 

(Insert) 

enter insert mode 

k < char > 

(Kill) 

delete from cursor up to < char > 

s < char > 

(Search) 

move cursor right to H char K 

u 

(Up) 

scroll screen up 

x <char> 

(exchange) 

replace cursor with < char > 

Figure 4: Edit Mode Commands 


Edit mode commands are one letter long. They may be typed in either upper or 
lower case. 


Dr. Dobb’s Journal, Number 63, January, 1982 

Iff 



would be changed to: 

know your xyz’s. The abc’s are 
very important. 

Question marks may be used in both 
the search mask and the change mask. A 
question mark in the search mask 

matches any character at all. The search 
mask: 

12734 

will match any string of five character 
which starts with 12 and ends with 34. A 
question mark in the change mask 

matches the letter that matched the cor¬ 
responding question mark in the search 
mask. For example: 

change 99 109 
search mask ? trailing? 
change mask ? ?Ieading 

would change the line: 

trailingA 
into the line: 

Aleading 

The question mark in the search mask 
matched the “A”, so the question mark 
in the change mask became an “A”. You 
can use as many question marks as you 
like, but there must be at least as many 
question marks in the search mask as 
there are in the change mask. As another 
example: 

change 

search mask ? wh??e 
change mask ? fath?? 

would change the line: 

where is here, 
to the line: 

father is here. 

If the first character of the search 
mask is an up arrow (t), the search mask 
is anchored to the start of the line. In 
other words, the search mask will only 
match patterns which start at column 0. 
For example, the search mask: 

t abc 

will only match lines that contain abc in 
columns 0, 1 and 2. Anchoring the search 
mask dramatically increases the speed of 
the change command. 

An up arrow which is not the first 
character of the search mask is treated as 
a regular up arrow. An up arrow in the 
change mask never has any special signifi¬ 
cance. 


clear 

The clear command erases the entire 
buffer. If you have not saved the buffer 
you will be asked whether you want to 
proceed. 

delete < line range > 

The delete command erases all lines 
in the line range. Care must be used with 
this command because no check is made 
to see whether the buffer has been saved. 

dos 

The dos command exits the editor 
and returns to the operating system. If 
the buffer has not been saved, this com¬ 
mand makes sure that you really wanted 
to exit without saving the buffer. 

find 

The find command searches for the 
next occurrence of a search mask. If the 
search mask is found, the editor switches 
to edit mode and the cursor is set to the 
start of the pattern. If the search mask is 
not found the editor remains in command 
mode. 

You specify the search mask exactly 
as in the change command. 

g <n> 

The g command exits to edit mode. 
Line <n > is drawn on the top line of the 
window and becomes the current line. 
Typing g without the <n> is the same as 
typing the edit key. 

list < line range > 

The list command lists all lines in the 
line range to the current list device, i.e., 
the printer. Lines are formatted just as 
they are on the screen, but the length 
of the print line, not the width of the 
screen, determines where lines will be 
truncated if they are too long. Listing 
may be stopped at any time by typing 
any key. 

load < filename > 

The load command replaces whatever 
is in the buffer by the contents of the 
named file. If the buffer has not been 
saved on disk when the load command is 
given, the editor makes sure you really 
wanted to erase the previous contents of 
the buffer. If the named file exists, then 
< filename > becomes “the current file” 
and < filename> is shown on the prompt 
line. This file becomes the file used in the 
save and resave commands. The current 


file name does not change if the named 
file does not exist. 

After the file has been completely 
read from the disk into the buffer the 
screen is redrawn to show the first several 
lines of the file. 

name < filename > 

The name command sets the name of 
the file that will be used in the save and 
resave commands. This command is not 
often used because the load command is 
the usual way to set this file’s name. The 
name command does not cause any ac¬ 
tion immediately; it simply affects which 
file the save and resave commands will 
use. 

resave 

The resave command saves the entire 
buffer in the current file. The name of 
the current file is set by either the load or 
name commands and always appears on 
the prompt line. Note that this command 
does not take any arguments. All argu¬ 
ments to this command are ignored. 

The resave command requires that 
the current file already exist; if the file 
does not exist a warning is printed and 
nothing happens. 

save 

The save command works just like 
the resave command except that the file 
must not exist for the command to work. 
If the file does exist a warning is printed 
and nothing happens. This protection en¬ 
sures that files cannot be overwritten in¬ 
advertently. 

search < line range > 

The search command prints on the 
screen all lines in <line range > which 
contain an instance of the search mask. 
As soon as the search command is typed 
the editor will ask: 

search mask ? 

Now type the search mask. Just as in the 
change command, a question mark 
matches any character and a leading up 
arrow anchors the search mask to the 
start of the line. 

tabs < n > 

The tabs command controls how 
lines are listed on the screen and on the 
printer. Specifically, the tabs command 
sets tab stops every <n> columns. <n> 
must be an integer. The command tabs 0 
is equivalent to the command tabs 1. 


22 


Dr. Dobb’s Journal, Number 63, January, 1982 

TT 




Bringing Up & Changing the Editor 

Figure 6 shows what equipment you 
need to have in order to use the editor 
without making any changes to the pro¬ 
gram. The code in the listings should 
work on any 8080, Z80, or 8085 machine 
that runs the CP/M operating system. 
You will also need quite a bit of memory. 
The editor itself uses about 23K bytes 
and the file you are editing must fit in the 
memory that is left. You also need a dis¬ 
play screen that can be made to directly 
address the cursor. By that I mean that 
there must be some way to move the cur¬ 
sor wherever you like in one step. Every 
video board and terminal that I am aware 
of has this capability. 

If you don’t have access to the CP/M 
operating system then you will certainly 
have to make at least a few changes to the 
editor in order to get it up and running. 
But don’t despair quite yet; you should 
only have to change the programs in the 
file ed8.c. Basically, these routines mask 
the idiosyncrasies of your operating sys¬ 
tem from the rest of the editor. If you 
find that you must change a routine not 
on this file in order to get the editor run¬ 
ning on some other system, I’d like to 
hear about it. But I don’t think you will. 

Those of you with the CP/M 1.4 
operating system will have to make only 
a very minor change to the routines 
syscstat(), syscin() and syscoutQ on file 
ed8.c. The listings contain the CP/M 1.4 
versions of these routines commented 
out. Just comment out the CP/M 2.2 ver¬ 
sions and remove the comments from 
around the CP/M 1.4 versions. 


Those of you with displays that only 
work in block mode are going to have to 
work pretty hard to use this editor. (If 
you don’t know what a block mode ter¬ 
minal is, rejoice. You don’t have one of 
the beasts.) A somewhat uneducated 
guess is that you may have to rewrite all 
the routines in file ed6.ccc and many of 
the routines in file ed2.c. Frankly, I 
don’t think it is worth the trouble. If 
somebody out there does get the editor 
working with a block-mode terminal I’d 
like to hear about that, too. 

The files edl .ccc and ed6.ccc contain 
code which is produced by the configura¬ 
tion program. These files tailor the editor 
to a particular display device. If for some 
reason you do not want to use the con¬ 
figuration program, you will have to 
create your own versions of these files. 

One of the things that I learned while 
doing this project is that it is possible to 
change drastically how the editor looks to 
the user without really changing the guts 
the editor at all. From a programming 
point of view, the choice of which com¬ 
mands to include and which to exclude is 
pretty much arbitrary. Barry Dobyns’ 
article about the MINCE editor in the 
April 1981 issue of Dr. Dobb's Journal is 
a good source of ideas about what you 
might want to add to this editor. 

Everyone will have a favorite com¬ 
mand or two that has been left out of this 
editor. I miss being able to move blocks 
of text from one area of the file to 
another. Another improvement might be 
to have a new line generated automatical¬ 
ly in insert mode if the cursor reaches the 


end of the line. This is essentially an 
“auto-split” feature. These changes 
should be easy to make if you are so in¬ 
clined. 

The present version of this program 
limits editing to those files that can fit 
entirely into memory. This is not a funda¬ 
mental problem with the editor. In fact, 
the first thing I designed about the editor 
was a scheme to edit arbitrarily long files. 
Essentially, what one has to do is to re¬ 
write about half of the buffer module 
(file edlO.c). If there is enough interest, 

I may write another article telling how to 
do this. 

How to Get This Editor 

This editor is in the public domain. 
That means you can use it in any way 
you wish. You can move the editor to 
other machines, copy it however you like, 
and make whatever changes you think 
would make it better. In fact, I strongly 
encourage you to do these things. 

If you have the CP/M operating sys¬ 
tem, you can get this editor and several 
other programs from me. They come on 
two 8-inch, soft-sectored, single-density, 
IBM-compatible diskettes. On these disk¬ 
ettes are the following: 

1. Source code for the editor. 

2. Source code for the configuration pro¬ 
gram. 

3. Source code for the Small-C compiler 
as distributed by The Code Works 
(TM). 

4. Source code for a text formatter adapt¬ 
ed from the FORMAT program in the 
book, Software Tools, by Kernighan 
and Plauger, published by Addison- 
Wesley. 

5. Complete documentation. 

The cost for all the above programs is 
$50. I am making the cost somewhat 
higher than the cost of just copying the 
disks because I would prefer to send out 
just a few copies. It’s fine with me if you 
get your copy from somebody who al¬ 
ready has one. 

I cannot offer to provide extensive 
support for these programs. That might 
quickly take all of my time. I will, how¬ 
ever, pay one dollar to anyone who finds 
a bug in this program. Sorry, that’s the 
best I can do. 

If you use these programs and find 
them useful I hope you will add some¬ 
thing of your own to them. I think this 
is a good editor, but I’m sure some of you 
will think of improvements. I’d like to 


Command 

Arguments 

Function 

append 

< filename > 

insert file into buffer at cursor 

change 

< line range > 

make changes to lines in < line range > 

clear 


erase the buffer 

delete 

< line range > 

deletes lines in < line range > 

dos 


exit from editor to operating system 

find 


search for a pattern; enter edit mode 

8 

<n> 

enter edit mode and go to line <n> 

list 

< line range > 

print lines in < line range > to printer 

load 

< filename > 

replace buffer with file 

name 

< filename > 

set name of current file 

save 


save buffer to a new file 

search 

< line range > 

print all lines that match a pattern 

resave 


save buffer to existing file 

tabs 

<n> 

set tab stops at every <n> columns 

Figure 5: 

Command Mode Commands 

All command mode commands end with a carriage return. They may be typed in 

either upper or lower case. 

1 


Di. Dobb’s Journal, Number 63, January, 1982 
78" 




read about your ideas in Dr. Dobb's 
Journal. 

Technical Details 

Now that we have seen what the edi¬ 
tor does, you might be interested in the 
technical details of how the editor does 
what it does. You can skip this section if 
these details are of no use to you. But 
please, if you do intend to make changes 
to this editor, make sure you understand 
the way the editor is constructed. If you 
don’t, you are going to do violence to the 
design behind the editor. 

The screen editor is organized into 
separate modules, also known as abstract 
data types. If you understand how and 
why the program is organized into these 
modules then you understand the basics 
of the program. I followed three rules 
religiously while writing this program. 
These rules tell how modules are de¬ 
signed. If you modify this program I want 
you to follow them too. Here they are: 

Rule 1: 

No program may use any data con¬ 
tained in another module. That is, all ac¬ 
cess to data contained in a module must 
be via the “access routines” of that 
module. 

Rule 2: 

No access routine may reveal to the 
outside world the internal representation 
of data inside the- access routine’s own 
module. In other words, the access rou¬ 
tines of a module only indicate what the 
module does, not how the module does it. 

Rule 3: 

Every significant (i.e., relatively com¬ 
plex) data structure resides in one and 
only one module. 

Each module, then, is responsible for 
hiding the details about some important 
data structure. To be more precise, each 
module hides how the module’s internal 
data is represented. The idea is that the 
organization of the data may be changed 
inside a module without the programs 
that use the module knowing that any¬ 
thing has changed. 

Modules not only contain data; just 
as importantly they also contain access 
routines by which procedures outside the 
module may use or change the data. The 
access routines are to be considered part 
of the module’s data structure. I will 


sometimes speak of the “associated oper¬ 
ations” of a module or data structure. By 
that I will mean the externally visible ac¬ 
cess routines of the module. 

Since modules (or data structures) 
have associated operations, the concept 
of data structure widens to include dy¬ 
namic devices such as disk drives, video 
screens, and operating systems! Indeed, I 
use modules to shield the rest of the pro¬ 
gram from the details of such devices. 

Rule 1 says that programs outside 
a module can only use or change the data 
inside the module by calling the “access 
routines” of the module. No messing with 
other module’s data is allowed. 

Rule 2 says that these access routines 
are functions of the data. That is, the val¬ 
ues returned and the effects produced by 
the access routines are independent of 
how the data of the module is represent¬ 
ed. Rule 2 eliminates data dependencies 
between modules. 

Rule 2 doesn’t quite say enough. Not 
only must access routines hide their 
modules representation of data, access 
routines must provide a functional view 
of the module to the outside world. In 
other words, there must not be complex 
dependencies between access functions in 
the same modules. (By definition there 
are not dependencies between access 


functions of different modules.) Access 
functions can be linked in subtle ways. 
For example, it might be that the access 
functions of a module must be called in 
only certain orders. Such dependencies 
should be avoided if at all possible. 

Rule 3 says that all important data 
structures are protected from meddling 
from outside sources, or conversely, no 
program needs to know (or can know) 
about details of data structures outside 
it’s own module. 

A corollary of these rules is that 
there are no important global data struc¬ 
tures. Indeed, there is seldom, if ever, a 
need for any global variables at all. Vari¬ 
ables may be shared by more than one 
routine, but all such routines will reside 
in the same module. 

Not every routine needs to be a 
member of a module. Those routines that 
are not a member of any module know 
the details of none of the important data 
structures of the program. 

There is a certain optimal complexity 
for the data structure enclosed by a 
module. If the structure is too complex 
then too many routines (all of them 
inside the module!) know details of the 
data structure. On the other hand, if a 

(Continued on page 34) 


Computer: 8080, 8085, or Z80 (4 mhz or faster preferred) 

Operating system: CP/M 

Main Memory: at least 32K (editor uses 23K) 

Display: video screen with direct cursor addressing 


Figure 6: What You Need to Use the Editor 

You will have to make changes to the editor if you don’t have the kind of 
system listed above. 


Name of Module 

File Name 

window module 

ed4.c 

buffer module 

edlO.c 

line format module 

edS.c 

prompt line module 

ed7.c 

terminal output module 

ed6.ccc 

operating system module 

ed8.c 

command module 

ed2.c 

Figure 7: Modules 

The editor is made up of 7 modules. Each module controls an important data 

structure. Each module is on a separate file; modules do not share data. 


24 


Dr. Dobb’s Journal, Number 63, January, 1982 

19 




Small Shell 

Part 2 of a North* VOS 


M y last article (DDJ #61) de¬ 
scribed Small-VM, the first com¬ 
ponent of a virtual operating sys¬ 
tem (VOS) for North Star machines. It 
adds file management, memory manage¬ 
ment, and program control features to a 
standard, unmodified North Star DOS. It 
also constitutes a run-time library for 
Small-C and programs compiled by Small- 
C. This article presents the second com¬ 
ponent of VOS — a command processor 
dubbed Small-Shell. 

My objectives in designing the shell 
were: 

1. ease of use (user friendly) 

2. application worthiness (user proof) 

3. conceptual simplicity (clean design 
with no frills) 

4. small size (this version is 2K bytes) 

5. shell penetration (access to the un¬ 
derlying DOS) 

6. compatibility with all North Star 
software 

7. independence (works alone or with 
Small-VM) 

8. procedure files (with parameter sub¬ 
stitution, operator prompting, com¬ 
mand override, and abnormal proce¬ 
dure termination) 

9. no DOS irritants (command line too 
short, DEL does not rub out, super¬ 
fluous keyword GO, danger of acci¬ 
dental IN command) 

10. save and simple reentry of serially re¬ 
usable programs. 

Small-Shell is written in assembly 
language for Allen Ashley’s PDS macro¬ 
assembler. Using assembly language vio¬ 
lates the spirit of the VOS concept which 
emphasizes portability, and portability is 
a major goal of the VOS project; but I 
feel it is more important to keep the size 
of memory-resident system software 
down on a microcomputer with limited 
memory. Writing the shell in C also would 
have made it dependent on Small-VM; as 
it stands it may be used either with or 
without that system. 

A complete listing of Small-Shell ac¬ 
companies this article. Small-Shell is 
copyrighted and is published here for pri¬ 
vate non-commercial use only. 

Basic Concept of the Shell 

The shell exists as a self-contained 


J.E. Hendrix 


J. E. Hendrix, Rt. 1, Box 74-B-l, Oxford, 
MS 38655. 


Listing 

1 

2 I************************************************************* 

3 i* Small/Shell» Version 1,0 

4 l* A command processor for North Star DOS 

8 l* 

6 i* Copyright 1V8I J. E. Hendrix 

7 l* All rights reserved 

8 l* 

V »* Written for PDS MAKRO assembler 

10 i************************************************************* 

I I I 

• 2 «-DOS references 


13 

1 4 

1 

DOSbASEi 

EQU 

200CH 


1 0 

DOS* 

EOU 

DOSBASE+28H 

IlDOS WARM START 

1 / 

Cl Ni 

EQU 

DOSBASE* 1 OH 

I 1 CHAR INPUT 

18 

COUT • 

EOU 

DOSBASE+ODH 

1 ICHAR OUTPUT 

IV 

HDERRi 

EOU 

DOSBASE*I9H 

1IHARU DISK ERROR BRANCH 

20 

UOSERRi 

EOU 

DOSBASE*2CH 

IIDLOOK EILENAME ERROR BRANCH 

21 

DLOOKi 

EOU 

DOSBASE* ICH 

1IDIRECTORY L(X)KUP 

22 

DCOM • 

EOU 

DOSBASE*22H 

IIHD, WRT, VERIFY DISK 

23 

CM DBF! 

EOU 

DOSBASE+3IH 

IlDOS CMD BUFFER POINTER 

24 

1 




28 

1 —“■* non-standard DOS references 

20 

1 




27 

DOSCCP * 

EOU 

DOSBASE*0B 1 EH! 1 DOS CMD PROC (LXI H.dosbf) 

28 

DOSPRi 

EOU 

DOSBASE*0BI9H • • DOS PROMPT (CALL nnnn) 

2v 

f 




30 

31 

32 

1-mlsc. assembly constants 

BLKSZ* 

EQU 

286 

IlDISK BLOCK SIZE 

33 

DUfcN • 

EOU 

2 

IIDRIVE DENSITY 

34 

DCOMRi 

EOU 

i 

IlDCOM READ COMMAND 

38 

PAD« 

EOU 

0 

IlSMALL/VM BUFFER PAD CHAR 

36 

CTLCi 

EQU 

03H 

ll*C 

37 

CTLEi 

EOU 

08H 

1 l*E 

38 

CTLS« 

EOU 

I3H 

ll*S 

3V 

COMTi 

EQU 

' X* 

••COMMENT FLAG 

40 

DOSCMD» 

EOU 


1 1 TARGET DOS FOR CMD 

4 1 

JUMP! 

EQU 

/ / 

1 1 JUMP TO LOADED PROGRAM 

42 

NULPARMi 

EQU 

/ 

1«NULL PARAMETER FLAG 

43 

NOTE • 

EOU 

/ / 

1IOPEHATOR NOTE FLAG IN PROCEDURE FILF 

44 

PROMi 

EOU 

•v 

••PROMPT CHAR 

4b 

SUbMARKi 

EOU 

'S' 

• •MARKS SYMBOLIC PARAMETER IN PROCEDURE FI 

40 

SYSHLEi 

EOU 


• •IDENTIFIES A SYSTEM FILE 

47 

CONSOLE! 

EOU 

0 

• •NORTH STAR CONSOLE DEVICE 

48 

EX EC • 

EOU 

1 

• •TYPE OF EXECUTABLE FI EL 

4 V 

PROCi 

EOU 

11 

• •TYPE OF PROCEDURE FILE 

80 

CLSZi 

EOU 

o2 

••SHELL COMMAND LINE SIZE 

81 

DEHUWVi 

EOU 

1 

• •DEFAULT DRIVE FOR PROG AND PROC LIXIKUP 

82 

1 




83 

1 - 1 

nltiallzlng 


b4 

1 




88 


LXI 

H.BOSTACK 

• •SET SP TO BOTTOM OF STACK 

86 


SPHL 



87 


LHLD 

CMD BE 

• •SAVE/ALTER DOS CMD BUFFER VECTOR 

88 


SHLD 

CMDBFV 


89 


LXI 

H.CMDLINE 


60 


SHLD 

CMD BE 


61 


I NX 

H 

••ALTER DOS CMD PROC TO SEE SHELL CMD LIN 

62 


SHLD 

DOSCCP* 1 


63 


LHLD 

DOSPR*1 

• •SAVE/ALTER DOS PROMPT CALL 

64 


SHLD 

DOSPRV 


68 


LXI 

H,RETURN 


60 


SHLD 

DOSPR*1 


67 


LHLD 

HDERR*I 

• •SAVE/ALTER DOS HARD ERROR VECTOR 

68 


SHLD 

HDERRV 


69 


LXI 

H.HARDERR 


70 


SHLD 

HDERR*1 


7 1 


LHLD 

DOSERR*1 

• •SAVE FILENAME ERROR VECTOR 

72 


SHLD 

DQSERRV 


73 


LHLD 

DOS* 1 

• •SAVE/ALTER DOS WARM START VECTOR 

74 


SHLD 

DOSV 


78 


LXI 

H, RETURN 


76 


SHLD 

DOS* 1 


77 


SHLD 

LADDR 

1 UNIT LOAD A DDR 


(Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 
~ 20 " 


27 






Small Shell (Listing continued, text begins on page 27) 


North Star program which may be in¬ 
voked with the GO command. It is in 
control when other programs are not run¬ 
ning. Shell commands either invoke a pro¬ 
gram or a series of commands from a 
procedure file. When a running program 
returns to DOS, an altered jump-table ad¬ 
dress diverts control back to the shell. 
When the shell regains control from a pro¬ 
gram, it checks to see if control came 
through Small-VM; if so, then it checks 
for a non-zero return code which would 
terminate a procedure if one were in 
progress. The command to invoke a pro¬ 
cedure looks like a program execution 
command; the shell leams the difference 
by examining the file type. Regular DOS 
commands may be pushed through the 
shell for DOS processing. One may exit 
the shell by entering a control-E, but this 
feature, and the DOS commands as well, 
may be disabled for non-privileged appli¬ 
cations. Once out of the shell, it may be 
reentered by issuing a JP to its load ad¬ 
dress. The shell absolutely refuses to 
honor the IN command;one must exit to 
DOS to format diskettes. 

Command Syntax 

Regular (non-DOS) shell commands 
have the form “filename argl arg2 arg3 
.. where filename is a standard North 
Star file name with an optional drive 
number (e.g., prog,2). The arguments are 
optional depending upon the require¬ 
ments of the individual program or pro¬ 
cedure. If the named file is of type I, it is 
loaded and control is passed to its load 
address with HL pointing to the first 
command line character following file¬ 
name. If the file is of type II, it is taken 
for a procedure file; the individual lines 
within it are processed sequentially. Nest¬ 
ing of procedures is not supported. If the 
file is not found or if it is an illegal type 
of file, the command is rejected by dis¬ 
playing “?” followed by the full com¬ 
mand (after parameter substitution). A 
null line or any line with leading spaces 
is ignored. 

In place of filename, one may enter 
a period. This instructs the shell to jump 
to the last program loaded (after setting 
LH appropriately); this feature saves 
diskette I/O and typing while performing 
repetitive operations. 

The Shell, like UNIX (UNIX is a 
trademark of Bell Labs), prompts with a 
percent sign (%). Anything may be used, 
but it should differ from the symbol used 
by DOS (“+” for double-density sys- 


78 i 


79 


shell command 


80 

81 

82 

1 

DOCMDi ENTRY 

LXI 

H.CREHR 

I(ALTER DOSERR HERE SINCE BASIC CORRUPTS 

83 

SHLD 

D0SERR+1 


84 

LDA 

SKIPS* 

((SKIP THIS CMD7 

88 

ANA 

A 


86 

M VI 

A.O 


87 

STA 

SKIPS* 


88 

JNZ 

NEXTCMD 

1 IYES 

8V 

LDA 

CMDLINE 

IIFIRST BYTE OF CMD 

90 

CPI 

ODH 

1 ICR? 

91 

JZ 

NEXTCMD 

11 YES, IGNORE CMD 

92 

CPI 

/ / 

I (LEADING SPACE WOULD TELL DLOOK TO 

93 

JZ 

NEXTCMD 

II FIND 1ST AVAILABLE SECTOR 

94 

CHKSYS« CPI 

0 

IlSYS FILE? <<<<ALTERED AFTER BOOT>>» 

96 

JZ 

CMDERR 


96 

97 

( 

« RfcTUWN TO DOS? 


98 

99 

I 

CPI 

CTLE 

I l*E? 

100 

JNZ 

D0CMD2 

1 INO 

101 

LDA 

DOSPRIV 

1 1 YES , IS DOS PRIVILEGE SET? 

102 

ANA 

A 


103 

JZ 

NEXTCMD 

UNO — T(X> BAD 

1 04 

LHLD 

DOSV 

1IRESTORE DOS WARM START VECTOR 

106 

SHLD 

DOS* 1 


106 

LHLD 

CMDBFV 

1(RESTORE DOS CMD BUFFER VECTOR 

107 

SHLD 

CMDBF 


108 

SHLD 

DOSCCP+ 1 

II RES TORE DOS CCP 

109 

LHLD 

DOSPRV 

1 (RESTORE DOS PROMPT 

1 10 

SHLD 

DOSPR^I 


111 

LHLD 

HDERRV 

II RESTORE HARD ERR VECTOR 

1 12 

SHLD 

HDERR+I 


113 

LHLD 

DOSERRV 

1 (RESTORE FILENAME ERROR VECTOR 

1 1 4 

SHLD 

DOSERR*1 


1 16 

M VI 

A,JUMP 

1(PREPARE FOR REENTRY TO SHELL 

1 16 

STA 

CMDLINE 


1 1 7 

JMP 

DOS 

1 1 <- 

1 18 

1 19 

1 

1 JUMP ro A PREVIOUSLY LOADED PROGRAM? 

120 

121 

1 

DOCMD2• CPI 

JUMP 


122 

JZ 

GOPHOG 


123 

124 

1 


126 

126 

I 

CPI 

DOSCMD 


127 

JNZ 

LOOK 

1 INO 

128 

LDA 

CMDLINE+1 

II “IN'* CMD? 

129 

CPI 

'I' 


130 

JZ 

CMDERR 

IlYES, TOO DANGEROUS (MUST EXIT TO DOS) 

131 

CPI 

* 1 ' 

IIYES, “In" 

132 

JZ 

CMDERR 


133 

CPI 

ODH 

II "♦« ALONE? 

134 

JNZ 

DOCMD9 

1 1 NO 

136 

LDA 

PROCS* 

1 1 YES , IN A PROC? 

136 

ANA 

A 


137 

JZ 

CMDERR 

1 INO 

138 

LDA 

DOSPRIV 

IlYES, TOGGLE DOS PRIV SW 

139 

140 

CMA 

STA 

DOSPRIV 


14 1 

JMP 

NEXrCMD 


142 

143 

« 

DOCMD9I LDA 

DOSPRIV 

IlDOS PRIV SET? 

1 44 

ANA 

A 


143 

JZ 

CMDERR 

1 INO 

146 

STA 

CMDLINE-I 

llTELL SMALL/VM IT'S A DOS COMMAND 

147 

JMP 

DOSCCP 


148 

14V 

I 

1 - lookup 

named file 


150 
15 1 

1 

LOOK! LXI 

H,CMDLINE 

IIHL -» FILENAME 

152 

MV I 

A.DEFDHV 

1 IA « DEFAULT DRI VE 

153 

CALL 

DLOOK 

1 1 L>X)K FOR IT <- 

154 

JC 

CMDERR 

IlNOT FOUND 

156 

STA 

DRV 

IlSAVE ACTUAL DRIVE 

150 

XCHG 


1(FDE+S IN DOS 

157 

LXI 

H, DA 


158 

169 

XCHG 
MV I 

C.7 


160 

CALL 

BMOVE 

IlSAVE FDE FIELDS 

161 

162 

I 

LDA 

DRV 

1 (COMBINE DENSITY BIT AND DRIVE # 

163 

MOV 

C.A 


164 

LDA 

FTY 


165 

MOV 

B, A 



28 


Dr. Dobb’s Journal, Number 63, January, 1982 

TT 







166 


ANI 

8GH 

11 DENSITY BIT 

167 


ORA 

C 


168 


STA 

DRV 


169 

I 




170 


MOV 

A.B 

1 (EXECUTABLE FILE? 

17 1 


ANI 

7FH 


172 


CPI 

EXEC 


173 


JZ 

LOAD 

1 * YES 

174 


CPI 

PROC 

1 IPROCEDURE FILE? 

17b 


JZ 

DOPROC 

1IYES 

176 


JMP 

CMDERR 

II NO — T(X) BAD 

177 

1 




1 78 

»-load executable file 


179 

I 




180 

LOAD* 

LHLD 

TDI 

11 UPDATE LOAD ADDR 

181 


SHLD 

LADDR 


182 


LDA 

DRV 


183 


MOV 

C.A 

IlC • DEN, DRV 

184 


MV I 

B.DCOMR 

llB « DCOM READ COMMAND 

18b 


LDA 

FSZ 

IIA - FILE SIZE IN SECTORS (255 MAX) 

186 


LHLD 

LADDR 


187 


XCHG 


1 IDE - LOAD ADDRESS 

188 


LHLD 

DA 

UHL - DISK ADDRESS 

189 


CALL 

DCOM 

IlLOAD IT <- 

190 


JC 

SHELLERR 

1ITROUBLE 

191 

t 




192 

1-Jump to 

loaded program 

193 

t 




194 

GOPROG* 

LHLD 

LADDR 


19b 


SHLD 

G(HI 

1 IALTER JMP ADOR 

196 


LXI 

H.CMDLINE 

IlSET HL PER NORTH STAR PRACTICE 

197 

GOL(K)P t 

I NX 

H 


198 


MOV 

A.M 


199 


CPI 

2 IH 

11 1ST CHAR <» SPACE? 

200 


JP 

GOLOOP 

1INO 

201 


XRA 

A 

IITELL SMALL/VM IT'S A SHELL COMMAND 

202 


STA 

CMDLINE-I 


203 

GO* 

ENTRY 



204 


JMP 

SHELLERR 

!!<<<< THIS ADOR IS ALTERED >»> 

20b 

1 




206 

1 




207 

1 




208 

RETURN* 

ENTRY 



209 


XCHG 


1 IDE - RETURN CODE IF FROM SMALL/VM 

210 


LXI 

H.BOSTACK 

IlSET SP 

211 


SPHL 



212 


XRI 

OFFH 

IIRETURNED VIA SMALL/VM? 

213 


JNZ 

NEXTCMD 

• INO 

214 


ORA 

E 

IlYES. IS LSB OF RETURN CODE ZERO? 

21b 


JNZ 

UNPROC 

UNO, ABORT PROC CMD IF IN PROGRESS 

216 

« 




217 


next command 

to be found? 

218 

1 




219 

NEXT CMD* 

LDA 

PROCSW 


220 


ANA 

A 


22 1 


JNZ 

PFETCH 


222 

1 




223 

l-console 

1 nput 


224 

1 




22b 

PROMPT* 

MVI 

B.PROM 

1IPROMPT CHAR 

226 


CALL 

OUTCHAR 


227 


LXI 

H.CMDLINE 

UHL - DEST PTR 

228 


MVI 

C.CLSZ 

IlC » CHAR COUNTER 

229 

CINLOOP* 

MVI 

A,CONSOLE 


230 


CALL 

CIN 

IlFETCH NEXT CHAR <- 

231 


CPI 

08H 

UBS? 

232 


JZ 

RUBOUT 


233 


CPI 

7FH 

11 DEL? 

234 


JZ 

RUBOUT 


23b 


CPI 

CTLC 

1 l*C? 

230 


JNZ 

STONIT 

• INO 

237 


MVI 

A.ODH 

IlYES 

238 


STA 

CMDLINE 

II IGNORE CMD 

239 

STONIT* 

MOV 

M, A 


240 


I NX 

H 


24 1 


DCR 

C 


242 


JZ 

LINERR 

•INO MORE SPACE 

243 


CPI 

20H 

IICTL CHAR? 

244 


JP 

ECHO 

UNO, CONTINUE 

24b 


MVI 

A.ODH 

IlFORCE CR 

246 


MOV 

M.A 


24 7 

ECHO* 

MOV 

B.A 

• •ECHO CHAR 

248 


CALL 

OUTCHAR 

• •RETURNS CHAR IN -A" 

249 


CPI 

OAH 

1IOUTCHAR GENERATES AUTO LF AFTER CR 

2b0 


MVI 

A.O 

IlCLEAR SKIPSN 

2b 1 


STA 

SKIPSN 


262 


JZ 

DICMD 


253 


JMP 

CINLOOP 


254 

• 




255 

RUBOUT* 

MOV 

A, C 


25 0 


CPI 

CLSZ 

i tCMDLINE IS EMPTY (Continued on next 

257 


JZ 

CINLOOP 


terns). One should know whether he is 
conversing with DOS or the shell. 

DOS commands are entered with a 
leading plus sign; using the DOS prompt 
character seems to have mnemonic value. 
These commands are passed through the 
shell to DOS for processing. 

Procedure Files 

A procedure file is a simple ASCII 
file with each line terminated by a CR or 
a CR/LF sequence. The file is terminated 
by (1) a hex FF, (2) a zero byte, or 
(3) the physical end of file space. The last 
line is ignored if it is not properly ter¬ 
minated. 

Any valid console command is legal 
in a procedure. In addition, the following 
commands have special meaning only in a 
procedure: 

:< comment > 

Any line beginning with a colon is taken 
for a comment and is ignored by the 
shell. 

_<note> 

Any line beginning with a single under¬ 
score is displayed as a note to the opera¬ 
tor. 

_< prompt > 

Any line beginning with two underscores 
is also displayed. In this case, however, 
the message “waiting...” is then sent to 
the operator and the shell waits for a re¬ 
sponse. This serves two purposes. It per¬ 
mits the operator to change diskettes, 
ready the printer, etc., and it lets the 
operator decide whether to (1) continue 
normally, (2) skip the next command, or 
(3) cancel the procedure. 

A carriage return response continues 
the procedure. A control-S response skips 
the next command. Comments do not 
count as commands, but notes and null 
commands do. A command may be made 
unskippable by preceding it with a note or 
a blank line. A control-C response can¬ 
cels the procedure. Other responses cause 
the shell to redisplay the waiting message. 
+ 

A line consisting of a single plus sign (+) 
toggles the DOS-access privilege. Since 
the privilege is initially turned on, placing 
this command in the boot procedure 
automatically denies the operator DOS 
access. The privilege may be reinstated 
by processing another toggle command 
from a procedure file. This scheme is not 
foolproof, but it is adequate and it is not 


Dr. Dobb’s Journal, Number 63, January, 1982 
~ 22 ~ 


29 





Shell (Listing continued, text begins on page 27) 


difficult for a knowledgeable person to 
override (edit the command out of the 
boot file and reboot or use a procedure 
on a different diskette to toggle the privi¬ 
lege back on). One cannot create a proce¬ 
dure file containing this command since 
the privilege is required to set its file type 
toll. 

The shell, like UNIX, employs a posi¬ 
tional scheme for parameter substitution 
in procedures. Up to 9 parameters may 
follow filename when a procedure is in¬ 
voked. Within the procedure, these are 
referenced symbolically as SI, $2, $3, 
. . . $9. The symbol SO refers to file¬ 
name. These references may appear any¬ 
where on any procedure line regardless of 
the type of line. Operator notes, for in¬ 
stance, may vary according to the para¬ 
meters given when the procedure was 
invoked. 

Since the parameter substitution 
logic takes no account of syntax, sym¬ 
bolic references may be used in any con¬ 
text; they may form parts of fields, com¬ 
plete fields, or complete lines. A dollar 
sign followed by any non-numeric char¬ 
acter is dropped, but the following 
character is retained; thus, $$ yields $. 

If a referenced parameter is not given 
with the invoking command, the refer¬ 
ence becomes a null string. Trailing para¬ 
meters, when invoking a procedure, may 
be omitted by entering nothing after the 
last parameter given. Other parameters 
may be skipped by entering a period in 
their places. Thus, the command “abc .. . 
xx” invokes procedure abc replacing all 
references to $0 with abc, and $3 with 
xx; all other references are squeezed out. 

Two switches may be included with 
commands to invoke procedures. They 
may appear anywhere following the pro¬ 
cedure name, but are not seen as para¬ 
meters. The switch “-v” (meaning “view”) 
causes the shell to display each command 
after parameter substitution but before 
being processed. Comments are not dis¬ 
played. The switch “-n” (meaning “ne¬ 
gate”) causes processing of the commands 
to be skipped. The command “abc parml 
parm2 -v” will show the progress of pro¬ 
cedure abc. The command “abc parml 
parm2 -v -n” only displays the procedure 
text after parameter substitution; this is 
handy for debugging new procedures. 


Booting a System With the Shell 

The shell’s procedure processing fea- 


258 


INR 

c 


25V 


OCX 

H 


260 


PUSH 

H 


261 


LXI 

H , RUBMSG 


262 


CALL 

OUTSTH 


263 


POP 

H 


264 


JMP 

CINLOOP 


265 

1 




266 

1- 


Input 


267 

1 




268 

PFETCHi MVI 

A.CLSZ 

II BYTES LEFT IN CMDLINE 

26V 


STA 

CMDBYTES 


270 


LXI 

H.CMDLINE 

1 IN EXT CMDLINE DEST A DDR 

27 1 


SHLD 

CMDADDR 


272 


XRA 

A 

11CLEAR SUBSTITUTION FLAG 

273 


STA 

SUBFLAG 


274 

1 




275 

« 

IS A NEN SECTOR NEEDED? 


276 

1 




277 

PLOOPt LHLD 

MCNT 

11 CHARS LEFT IN BUFFER 

278 


MOV 

A.H 


27V 


ORA 

L 


280 


JNZ 

BUFMOVE 

1INO, MOVE NEXT CHAR 

28 1 

1 




282 

f 

ANY MORE SECTORS IN THE 

FILE? 

283 

1 




284 


LHLD 

MFSZ 


285 


MOV 

A.H 


286 


ORA 

L 


28 7 


JZ 

UNPROC 

1INO, END OF FILE 

288 

1 




28V 

I 

READ NEXT SECTOR 


2V0 

t 




2VI 


LDA 

MDRV 


2V2 


MOV 

C.A 

1 1C - DEN, DRV 

2V3 


MVI 

B.DCOMR 

1 IB - DCOM READ COMMAND 

2V4 


MVI 

A. 1 

IIA - # SECTORS TO READ 

295 


LXI 

D.MBUF 

1 IDE - BUFFER A DDR 

296 


LHLD 

MDA 

1 IHL » DISK A DDR 

29 7 


CALL 

DCOM 

IIREAD 1 SECTOR <- 

298 


JC 

SHELLERR 

1 ITROUBLE 

29V 


LXI 

H.BLKSZ*DDEN| UNIT MCNT 

300 


SHLD 

MCNT 


301 


LXI 

H.MBUF 

IIINIT NEXT BUFFER ADDR 

302 


SHLD 

MADDR 


303 


LHLD 

MDA 

11 BUMP PROC DISK ADDR 

304 


I NX 

H 


305 


SHLD 

MDA 


306 


LHLD 

MFSZ 

IIDECR PROC FILE SIZE (SECTORS LEFT) 

307 


DCX 

H 


308 


SHLD 

MFSZ 


309 

( 




310 

r 


byte to cmdllne from procedure buffer 

31 1 

i 




312 

BUFMOVEi LHLl) 

MADDR 


313 


MOV 

A ,M 


314 


I NX 

H 


315 


SHLD 

MADDR 


316 


LHLD 

MCNT 

1IDECR MCNT 

317 


DCX 

H 


318 


SHLD 

MCNT 


319 


PUSH 

PSN 

IIPREV CHAR A SUBSTITUTION MARKER? 

320 


LDA 

SUBFLAG 


32 1 


ANA 

A 


322 


JNZ 

PARMSUB 

1 1 YES 

323 


POP 

PSN 

1 INO 

324 


CPI 

SUBMARK 

llTHIS CHAR A SUBSTITUTION MARKER? 

325 


JNZ 

BUFMOV2 

1 INO 

326 


STA 

SUBFLAG 

1 1 YES , SET FLAG 

32 7 


JMP 

PLOOP 

11 AND CONTINUE 

328 

1 




329 

BUFMOV2* CPI 

OFFH 

IlPDS EOF FLAG? 

330 


JZ 

UNPROC 

IIYES. EOF 

331 


CPI 

PAD 

iismall/vm pad char? 

332 


JZ 

UNPROC 

••YES, EOF 

333 

BUFMOV3* CPI 

OAH 

1 ILF? 

334 


JZ 

PLOOP 

IlYES, IGNORE IT 

335 

BUFPUT * LHLD 

CMDADDH 

1 INEXT CMDLINE ADDR 

33o 


MOV 

M, A 


337 


CPI 

ODH 

1 ICR? 

338 


JZ 

PEOL 

1 1 YES . CMD IS FETCHED 

339 


I NX 

H 


340 


SHLD 

CMDADDR 


34 1 


LDA 

CMDBYTES 

IICMDLINE BYTES LEFT 

342 


OCR 

A 


343 


STA 

CMDBYTES 


344 


ANA 

A 

i ispace left? (Continued on page 32) 


30 


Dr. Dobb’s Journal, Number 63, January, 1982 

"23 






ture is a handy device for booting up a 
system of separate self-contained mod¬ 
ules. It is much neater and easier to ex¬ 
tend the DOS that way than to modify 
its internals. That approach also re¬ 
sults in a more flexible system. My first 
use of procedure files was to boot a sys¬ 
tem consisting of DOS, the shell, a video 
driver, and Small-VM. Setting the auto¬ 
start byte of DOS to zero tells it to auto¬ 
matically process whatever command is in 
its buffer at boot time. Having “GO 
•SHELL” in the DOS command buffer, 
then, automatically invokes the shell. 

The shell always executes the com¬ 
mand “‘BOOT” when it is first invoked. 
A procedure file by that name resides on 
the diskette; it contains: 

•VIDEO 

*VM 

_VOS Development Diskette 


5.2DQ. The context of these reference 
points is: 

MV I B.28H 

("♦" prompt symbol) 

DOSPRi CALL <output> 

CALL <lnput> 

DOSCCP» LX I H, <buf fer> 

(address stored at CMDBF) 

LX I B,<whatever> 

MOV A,M 

To facilitate communication between 
Small-VM and Small-Shell when transfer¬ 
ring control to and from program, Small- 
VM has been modified. The following 
partial listing highlights these changes 
with a vertical bar to the left of each 
modified line: (See below) 


This publication 
is available 
in microform. 


University Microfilms 
International 


300 North Zeeb Road 30-32 Mortimer Street 

Dept PR Dept PR 

Ann Arbor Mi 48106 London WIN 7RA 

USA England 


! UE CR2» CALL GTSOB 11RET ONLY IF SOB < PTH 

OCX H 

MOV A.M 


Presto! The video driver and the VM 
interface are initiated and the diskette 
identifies itself. One could easily give 
the operator prerogative over which com¬ 
ponents to boot by placing prompt com¬ 
mands in the boot procedure. 

The leading asterisk in the file names 
•BOOT, ‘SHELL, ‘VIDEO, and *VM 
identifies them to the shell as system files 
which are illegal to reference after boot 
time. This mechanism prevents the user 
from corrupting the system by invoking 
system modules or the boot procedure a 
second time. 


A Word of Warning 

Small-Shell makes two non-standard 
references to DOS. DOSCCP locates the 
point where DOS loads its command line 
buffer address in preparation for process¬ 
ing a command. The shell alters the ad¬ 
dress at DOSCCP+1 to trick DOS into us¬ 
ing the shell buffer instead of its own. It 
jumps to DOSCCP when a DOS command 
is ready to process. The second reference, 
DOSPR, locates a point traversed within 
the DOS just before it prompts for a new 
command. By altering DOSPR+1, the 
shell diverts control back to itself after a 
DOS command is finished. 

These references will likely need 
changing if the shell is to be used with 
any version of DOS other than release 


01 SOB« 

XCHG 




LHLD 

SOB 



X CHG 


1 ll)E>SOB, HL»PfH 


PUSH 

H 



CALL 

UCMP 



POP 

H 



RC 


llRET IF SUU<P1R 


POP 

B 

MR AST RET ADDR 


DCX 

H 

IIIS THIS SMALL-SHELL TALKING? 


MOV 

A.M 



ANA 

A 



JNZ 

SKPA 

UNO, IGNORE "GO" OR "JP" 


I NX 

H 



PUSH 

H 

IINEXT ARGV PTR 


OCX 

H 



CALL 

ARCS 


CCfcXITi 

fcNl'HY 




POP 

H 

IIWASr RET ADDR 


POP 

H 

II ERROR CODE? 


SHLL) 

TEMP 



MOV 

A ,H 



ORA 

L 



JZ 

EXIT0 

1 INO 


MOV 

B.L 


ABORTi 

XRA 

A 



STA 

TEMP* 1 



CALL 

cour 



STA 

TEMP 



MVI 

B.3FH 

II"?" 


XRA 

A 



CALL 

COUT 



LX I 

H,AMAX*FMAX+2llLASl FILE FU 


CALL 

UCMP 

1IDONE? 


LHLD 

TEMP 

IlSET UP REf G)DE FOR SMALL-SHELL 


MVI 

A.OFFH 

« 11ELL SMALL-SHELL A SMALL-VM PROG ENDED 


JZ 

DOS 

1 1 YEP 


• 


(Text continued on following page) 


Dr. Dobb’s Journal, Number 63, January, 1982 
14" 


31 




Small Shell 


(Listing continued, text begins on page 27) 


Future Plans 

For the future I hope to write an as¬ 
sembler, a linkage editor, and some utility 
progrms in C. The linkage editor will 
operate disk-to-disk and will assume a 
default load address; it will automatically 
set its output file to the correct type. 
That will eliminate the need for routine 
use of the SF and TY commands. Utility 
programs are needed for directory list¬ 
ings, multiple file copying, renaming and 
deleting. That should eliminate the need 
for routine use of the LI and DE com¬ 
mands, making it unnecessary to access 
DOS under normal conditions. 

The chief drawback to building on 
North Star DOS is its use of contiguous 
files. Once created, they cannot be dy¬ 
namically resized. Small-VM partially 
overcomes this inconvenience by permit¬ 
ting the last file created to be dynamical¬ 
ly expanded or contracted. It also dyna¬ 
mically creates files. I hope soon to ex¬ 
plore a simple scheme for supporting 
multiple file extents. It would make all 
files expandable and contractable and 
make all unused space available without 
compacting the diskette. This can be 
done •without (1) changing the simple 
DOS diskette format, (2) losing full com¬ 
patibility with standard North Star files, 
or (3) decreasing available diskette space. 
The penalty in memory usage may make 
this feature unattractive though. 

Many features could be added to the 
shell, but the ones presented here should 
meet most needs. One worthy addition 
might be the ability to run simultaneous 
foreground and background programs. If 
you have any ideas or suggestions, I 
would like to hear from you. 


345 JZ LINERR UNO, ABORT PROC 

346 JMP PLOOP IIYES, GO FOR NEXT BYTE 

347 I 

348 l- parameter substitution (PS* on top of stack) 

34V » 


350 

PARMSUBi XRA 

A 

1 (CLEAR SUB FUG 

351 


STA 

SUBFLAG 


352 


POP 

PS* 

I IF ETCH CHAR FOLLOWING SUBST MARKER 

353 


PUSH 

PS* 

HAND SAVE IT AGAIN 

354 


SUI 

30H 

IIREDUCE ASCII BYTE TO INTEGER 

355 


JM 

NOSUB 

• IL r ZERO 

356 


CPI 

10 


357 


JP 

NOSUB 

i ig r v 

358 


MOV 

C.A 

llPPTR OFFSET 

35V 


POP 

PS* 

IIWAST TOP OF STACK 

360 


LXI 

H.PPTRS 

1 1 1ST PPTR ADDR 

361 

SUBLOOPi MOV 

E,M 

1 IDE » NEXT PPTR 

362 


I NX 

H 


363 


MOV 

D.M 


364 


I NX 

H 


365 


MOV 

A.D 


366 


ORA 

E 


367 


JZ 

NULLPARM 


368 


OCR 

C 


36V 


JP 

SUBLOOP 


370 

1 




371 

» PPTR 

FOUND 



372 

t 




373 

SUBLOOP2IXCHG 


IlHL -» NEXT PARM CHAR 

374 


MOV 

A.M 

• •FETCH IT 

375 


CPI 

2IH 

IIEND OF PARM (LE SPACE)? 

376 


JM 

PLOOP 

IIYES. CONTINUE 

377 


I NX 

H 

IIBUMP PARM BYTE ADDR 

378 


XCHG 


1 IDE -» FOLLOWING PARM BYTE 

37V 


LHLD 

CMDADDR 

1 1 STORE BYTE IN CMDLINE 

380 


MOV 

M t A 


38 1 


I NX 

H 

• IBUMP BYTE ADDR 

382 


SHLD 

CMDADDR 


383 


LDA 

CMDBYTES 

IIDECH BYTES LEFT IN CMDLINE 

384 


DCR 

A 


385 


STA 

CMDBYTES 


386 


ANA 

A 

IISPACE LEFT? 

387 


JZ 

LINERR 

1 INO, ABORT PROC 

388 


JMP 

SUBLOOP2 


38V 

1 




3V0 

I NON- 

NUMERIC 

CHAR FOLLOWS SUBSTITUTION MARKER -- TREAT NORMAL 

3V 1 

1 




392 

NOSUBi 

POP 

PS* 

II RESTORE CHAR 

393 


JMP 

8UFMOV2 

HAND CONTINUE 

394 

1 




395 

1 NO PARAMETER 

1 GIVEN FOR SUBSTITUTION -- SUB NULL STRING 

396 

1 




39 7 

NULLPAHMiMVI 

A.OAH 

• 1FORCE BYTE TO BE SKIPPED 

398 


JMP 

BUFM0V3 


39V 

1 




400 

|- - 

end of 

procedure line 


401 

1 




402 

PEOL« 

LDA 

CMDLINE 


403 


CPI 

COMT 

11 COMMENT? 

404 


JZ 

PFETCH 

IIYES, IGNORE IT 

405 


CPI 

NOTE 

1 IOPERATOR NOTE? 

400 


JZ 

VIE* 

IIYES, DISPLAY THE LINE 

407 


LDA 

VS* 

1IVIE* SWITCH SET? 

408 


ANA 

A 


40 V 


JZ 

CKNSN 

• INO 

410 

VIEHi 

LXI 

H,CMDLINE 

1 1 YES 

41 1 


CALL 

OUTSTR 


412 

t 




413 

CKNSNi 

LDA 

NS* 

l INO-EXECUTE SWITCH SET? 

414 


ANA 

A 


415 


JNZ 

PFETCH 

IIYES, GO FOR NEXT COMMAND LINE 

410 

t 




417 


LDA 

CMDLINE 

•IOPERATOR NOTE? 

418 


CPI 

NOTE 


419 


JNZ 

DOCMD 

UNO, PROCESS THE COMMAND LINE 

420 


LDA 

CMDLINE*1 

•IOPERATOR RESPONSE? 

42 1 


CPI 

NOTE 


422 


JNZ 

PFETCH 

1 INO 

423 

MAIT« 

LXI 

H.NAITMSG 


424 


CALL 

OUTSTR 


425 


XRA 

A 

IIWAIT FOR A RESPONSE 

426 


CALL 

CIN 

II <- 

427 


PUSH 

PS* 

IIECHO CR.LF 

428 


MVI 

B.ODH 


429 


CALL 

OUTCHAR 


430 


POP 

PS* 


431 


CPI 

ODH 

• ICR? 


32 


Dr. Dobb’s Journal, Number 63, January, 1982 

"25 




432 

JZ 

PFETCH 

IIYES, CONTINUE 

433 

CPI 

CTLC 

1 l*C? 

434 

JZ 

UNPROC 

IIYES, ABORT PROC 

43b 

CPI 

CTLS 

ll*S? 

436 

JNZ 

WAIT 

1INO. KEEP WAITING 

437 

CMA 


IIYES, SET SKIP SWITCH 

438 

STA 

SKIPS* 


43V 

JMP 

PFETCH 

IlFETCH NEXT PROC COMMAND 

440 1 




44 1 i-error routines 


442 l 




44 3 CMUERRi 

LX I 

H.CMDLINE 


444 

JMP 

ERROUT 


44b LINERRi 

MV I 

B.ODH 


446 

CALL 

OUT CHAR 


44 7 

LXI 

H.LINEMSG 


448 

JMP 

ERROUT 


44V PAHMERRi 

LXI 

H.PARMSG 


4b 0 

JMP 

ERROUT 


4b1 SHELLERRiLXl 

H,SHELLMSG 


4b 2 

JMP 

ERROUT 


4b3 HARDERRi 

LXI 

H.HARDMSG 


4b4 

JMP 

ERROUT 


45b CRERRi 

LXI 

H.CRMSG 


456 

JMP 

ERROUT2 


457 NESTERRi 

LXI 

H.NFSTMSG 


458 1 




4b9 ERROUTi 

PUSH 

H 


460 

LXI 

H.OUESTMSG 


461 

CALL 

OUTSTR 


462 

POP 

H 


463 ERROUT2I 

CALL 

OUTSTR 


464 1 




46b l-terminate 

procedure | 

processing 

466 l 




467 UNPROCi 

XRA 

A 


468 

STA 

PROCSW 


46V 

MV I 

A.SVSFILE 

It REJECT FUTURE SYS FILE REFS 

470 

STA 

CHKSYS+1 


47 1 

JMP 

RETURN 

IIRESETS SP 4 GOES TO PROMPT 

472 1 




473 I-Initiate 

procedure processing 

474 1 




47b DOPROCi 

LDA 

PROCSW 

II ALREADY IN A PR(X.'? 

476 

ANA 

A 


477 

JNZ 

NESTERR 

IIYES, BUT CAN'T NEST THEM 

478 

CMA 


UNO, SET PROC SWITCH 

47V 

STA 

PROCSW 


480 

LXI 

H.MDRV 

IlSET UP PROC FDE FIELDS 

481 

X CHG 



482 

LXI 

H.DRV 


483 

MVI 

C.b 


484 

CALL 

BMOVE 


48b 

LXI 

H.O 

IlFORCE FIRST DISK READ 

486 

SHLD 

MCNT 


48 7 1 




488 1-parse procedure parameters 

48v i 




490 

XRA 

A 


49 1 

STA 

VS* 

••CLEAR VIEW SWITCH 

492 

STA 

NSW 

IlCLEAR NO-EXECUTE SWITCH 

493 

LXI 

H.PPTRS 

1 UNIT PPADDR 

494 

SHLD 

PPADDR 


49b 

LXI 

H.PBUF 

IIINIT DEST A DDR (DE) 

496 

X CHG 



49'/ 

LXI 

H.CMDLINE 

IIINIT SOURCE A DDR (HL) 

498 

MVI 

B, 10 

UMAX PARMS ALLOWED 

49V 

MVI 

C.O 

IlC ■ WORD SWITCH (ZERO BETWEEN WORDS) 

500 1 




501 PAHSLOOPiMOV 

A.M 

IlLOAD NEXT BYTE 

502 

I NX 

H 

IIBUMP SOURCE ADOR 

503 

CPI 

/ •/ 

IICMD LINE SWITCH? 

504 

JNZ 

PARSI 

1 INO 

50 b 

MOV 

A.C 

11 BEG INN INC OF A WORD? 

506 

ANA 

A 


507 

JNZ 

PARSOB 

UNO, CONTINUE 

508 

I NX 

H 


50V 

MOV 

A.M 

IITEST 3RD BYTE 

510 

DCX 

H 


511 

CPI 

2 IH 

• •SPACE OR CTL CHAR? 

512 

JP 

PARSOB 

UNO, CONTINUE 

513 

MOV 

A.M 

IITEST 2ND BYTE 

514 

CPI 

'V' 

11 —v ? 

bib 

JNZ 

PARSOA 

UNO 

516 

STA 

VSW 

IIYES, SET VIEW SWITCH 

517 PAHSOi 

I NX 

H 

HAND DROP SWITCH FROM THE COMMAND 

518 

JMP 

PARSLIXIP 


519 1 




520 PARSOA * 

CPI 

'n' 

l l-n? 

521 PARSOBi 

MVI 

A,'-' 

••RESTORE CHAR 

522 

JNZ 

PARSI 

UNO, CONTINUE 


Clinic (Continued from page 7) 

BRA .+5 ; skip around the 

calling arguments 
FCB operation ; 0 for wait, -1 for 

signal 

FDB semaphore ; address of the 
semaphore byte 

An interrupt routine can return through 
the signal routine to record an event and 
to possibly restart a task of higher priori¬ 
ty than the current one. The call would 
look like this: 

LDX #semaphore ; point index regis¬ 
ter at the sema¬ 
phore byte 

JMP Signal ; transfer to the 

signal routine 

“Note that the kernel can return 
control to the proper task by simply exe¬ 
cuting an interrupt return instruction, 
RTI.” 

Laurino’s letter ended with the ques¬ 
tion, “Can you find a fast algorithm to 
replace the iterative loop in the dispatch¬ 
er that doesn’t involve a tree of bit tests 
and branches? It is a kind of ‘identify the 
next element in the set’ function.” 

Help! 

Despite many favorable comments, 
the initial heavy mail for the Clinic has 
dropped off to a trickle. Your input is 
essential; without it this column is going 
to wither away. The range of material 
that can be used is very wide, and the ef¬ 
fort to send something in is quite small. 
The Clinic needs: operating system idio¬ 
cies, clever algorithms, sticky problems, 
brain teasers, unusual facts explained, 
striking fallacies exposed ... in short, al¬ 
most anything in software or hardware 
that interests you or gives you pause will 
also interest or surprise the other readers. 
Send ’em in! 

1 Donald E. Knuth, The Art of Computer 
Programming (Volume 1, Fundamental 
Algorithms), Second Edition. Addison- 
Wesley, 1973, page 190. 

2 Ibid, page 226. 


(Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 

~ 26 ~ 


33 






Small Shell (Listing continued, text begins on page 27) 


(Continued from page 24) 


structure is too simple, then wrapping a 
module around it increases the overall 
conceptual overhead of the program. 
Note that a single variable may often be 
suitable as the data structure of a module 
if the associated operations of the module 
are sufficiently complex. For example, 
the program counter in an assembler 
might make an ideal abstract data type. 

The editor program is composed of 7 
modules. Each module resides on a sepa¬ 
rate file. Thus, in regular C all global vari¬ 
ables in these 7 modules could be declared 
to be static. This would prevent any 
module from accessing the variables of 
other modules. Figure 7 shows what each 
of these modules does. BBj 

(Listing begins on page 42.) 

Author Ream's Editor is available on disk 
from the BDS C User’s Group (see ad on 
Page 17). 


523 

STA 

NSM 

IlYES, SET NO-EXECUTE SNITCH 

524 

JMP 

PARSO 


525 1 




526 PARS li 

XCHG 



527 

MOV 

M.A 


528 

I NX 

H 


529 

XCHG 



530 

CPI 

ODH 

1 1 END OF LINE? 

531 

JZ 

PARSEND 

«IVES 

532 

CPI 

2 IH 

1 ISPACE OR CTL CHAR? 

533 

MOV 

A.C 


534 

JP 

PARS2 

1INO 

535 

ANA 

A 

IlYES, IS NORD SNITCH CLEAR? 

536 

JZ 

PARSL(X)P 

IlYES, CONTINUE 

537 

MVI 

C.O 

UNO, CLEAR IT AND CONTINUE 

538 

JMP 

PARSLOOP 


539 « 




540 PARS2i 

ANA 

A 

ms NORD SNITCH SET? 

54 1 

JNZ 

PARSLIXIP 

IlYES, CONTINUE 

542 

MVI 

C.l 

UNO, SET IT 

543 

DCR 

B 

IINILL NEXT PARM FIT PPTRS ARRAY? 

544 

JM 

PARMERR 

1 INO 

345 1 




546 • LOAD 

NEXT PARM 

PTR 


547 1 




548 

PUSH 

H 

1ISOURCE 

54V 

PUSH 

D 

l IDEST 

550 

MOV 

A.M 

H2ND SOURCE CHAR <» SPACE? 

551 

CPI 

2 IH 


552 

XCHG 



553 

OCX 

H 



554 


JP 

PARS3 

UNO, CAN'T BE NULL PARAMETER 

555 


MOV 

A.M 

HIST DEST CHAR A NULL PARAMETER? 

556 


CPI 

NULPARM 


557 


JNZ 

PARS3 

1 INO 

558 


MVI 

A.' ' 

IlYES, FORCE PARM DELIMITER 

559 


MOV 

M.A 


560 

PARS3I 

XCHG 



561 


LHLD 

PPADDR 


562 


MOV 

M.E 


563 


I NX 

H 


564 


MOV 

M.D 


665 


I NX 

H 


566 


SHLD 

PPADDR 


567 


POP 

D 

1IDEST 

568 


POP 

H 

1 ISOURCE 

569 


JMP 

PARSLIXIP 


570 

« 




57 1 

, - 

terminate 

parsing 


572 

1 




573 

PAHSENDi XRA 

A 

11 CAP PPTRS NITH A NULL NORD 

574 


LHLD 

PPADDR 


575 


MOV 

M.A 


576 


I NX 

H 


577 


MOV 

M.A 


578 


JMP 

PFETCH 

IIGO PROCESS THE PROC 

579 

I 




580 

| — — — 

block move routine 


581 

1 

HL -> source, DE -> 

lest, C * length 

582 

HMOVEi 

MOV 

A ,M 


583 


I NX 

H 


584 


XCHG 



585 


MOV 

M.A 


580 


I NX 

H 


58 7 


XCHG 



588 


DCR 

C 


589 


JNZ 

BMOVfc 


590 


RET 



591 

« 




592 

| - 

output a 

char to the 

console 

59 3 

1 

8 » char. 

returns char In "A", auto LF 

594 

DUTCHAR• MVI 

A,CONSOLE 


69 b 


CALL 

COUT 

li <- 

596 


CPI 

OOH 

1 ICR? 

5V7 


HNZ 


1 INO 

69 tt 


MVI 

8,0 AH 

IlYES, GENERATE LF 


34 


Dr. Dobb’s Journal, Number 63, January, 1982 

~Z7 






69V 


MVI 

A. CONSOLE 


600 


CALL 

COUT 

1 1 <- 

601 


RET 



602 

1 




603 

l-output 

a string to 

the console 

604 

l HL -> string, ends 

after CR or before NULL 

600 

OU'ISTR * 

MOV 

B.M 


606 


MOV 

A, B 


607 


ANA 

A 


608 


R2 



60V 


I NX 

H 


610 


CALL 

OUTCHAR 


61 1 


CPI 

OAH 

IILE 

612 


JNZ 

OITTSTR 


613 


RET 



614 

1 




610 



0 1 6 

1 




61 7 

CMUADDRi 

DN 

0 

MCUW C MOLINE A DDR 

61 B 

CMDBYTESiDB 

0 

IICMDLINE BYTES LEFT 

61V 

nospRvi 

DM 

0 

IlDOS PROMPT VECTOR 

620 

CMDBEV» 

nw 

0 

IlDOS CMD BUFFER VECTOR 

62 1 

DOSVi 

DM 

0 

IlDOS WARM START VECTOR 

0 22 

HDERHVI 

DN 

0 

1IDOS HARD ERROR VECTOR 

623 

DOSERRVi 

DM 

0 

IlDOS FILENAME ERROR VECTOR 

624 

PROCSW« 

DB 

0 

IIPROC SNITCH 

o 2b 

SKIPSW t 

DB 

0 

IlSKIP NEXT PROC CMD 

626 

VSHi 

DB 

0 

1IVIEN SNITCH 

627 

NSW» 

DB 

0 

1INO-EXECUTE SNITCH 

628 

SUBFLAGi 

DB 

0 

IIPARM SUBST FLAG 

62V 

DOSPRIVi 

DB 

OEPH 

IlDOS ACCESS PRIVILEGE FLAG 


630 I 

631 l- shell command line 

032 I 

033 DB 0 I ITELL'S SMALL/VM WHETHER DOS OR SHELL COMMAND 

634 CMDLINEi DB '*B(X)T',ODH IIINITIAL COMMAND 

630 DS CLSZ-0 

o3o l 

637 I-program EDE & control fields 

638 l 


63V 

DRV i 

DB 

0 

IlDEN (BIT 7), DRIVE 

640 

DA i 

DN 

0 

IlDISK AUDR 

64 1 

fSZ» 

DM 

0 

IIFILE SIZE (SECTORS) 

642 

FTYi 

DB 

0 

IlFILE TYPE 

64 3 

TDI i 

□ N 

0 

1 lTYPE DEPENDENT INFO 

644 

LADDRi 

DN 

0 

IILOAD ADDR 

640 

1 




646 

l- procedure 

FDE 4 buffer fields 

647 

1 




648 

MDRVi 

DB 

0 

1 IDEN (BIT 7), DRIVE 

64V 

MDA • 

DM 

0 

IINEXT DISK ADDR 

600 

MFSZi 

DN 

0 

IISECTORS REMAINING 

601 

MBUFi 

DS 

BLKSZ*DDEN IIPROC BUFFER (ONE SECTOR) 

602 

MCNTi 

DN 

0 

11 BYTES LEFT IN BUFFER 

603 

MADDRi 

DM 

0 

1ICURRENT BUFFER BYTE ADDR 

604 

1 




600 




606 

1 




607 

CRMSCI 

DB 

ODH 


608 

QUESTMSGiDB 

' 7',ODH 


60 V 

NESTMSGi 

DB 

'program name expected', ODH 

660 

SHELLMSGiDB 

'shell error'.ODH 

661 

RUBMSGi 

DU 

08H ' ,08H, 0 

662 

PARMSGi 

DB 

'too many 

parameters',ODH 

663 

LINEMSGi 

DB 

'line too 

long',ODH 

664 

HARDMSGi 

DB 

'hard disk 

error',0DH 

660 

NAITMSGi 

DB 

NOTE,NOTE, 

'waiting,..0 

666 

1 



667 

1 -shell stack 


668 

1 




66V 


DS 

48 


670 

BOSTACKi 



IIBOTTOM OF STACK 

67 1 

1 




672 


pointers. 

buffer, etc. 

673 

1 




074 

PPTRSt 

DS 

22 

1111 WORDS 

670 

PBUFi 

DS 

CLSZ 

IIPARM BUFFER 

676 

PPADDRi 

DM 

0 

IIADDR OF CUR PARM PTR 

o77 


END 




End Listing 


Dt. Dobb’s Journal, Number 63, January, 1982 
"28" 








68000/AIM 65 

(Listing, text begins on page 12) 

(See Figure 6, page 1 7 for meaning of fields in Listing) 


H > - 801 00 00 00 00 

</> 0801 04 J 

*>-?ou 

< G > / 

SP RU 000000 0000 _ 

SP RU 000002 OOtF _ 

SP RU 000004 0000 . 

SP RU 000004 OOOH _ 

SP RU 000008 46EC - 

SP RU OOOOOA 0000 _ 

SP RU OOOOOC 4F/1 - 

UP RU OOOOOC 33E C 

OP RU OOOOOt 0100 . 

OP RU 000010 0000 
UP RU 00001? FCOO 
UP RU 0000 14 11F9 
UP UU OOF COO OS 

up ru 000014 noon 

OP RU 000018 0000 
OP RU 00001A ooon 
UP RH 000000 0004 
UP RU 00001C 0001 - 

OP UL 000000 OS 
UP RU 00001E 7E 4E71 
UP RU 000Q?0 7F4E71 
SO UU OtlOOFC FE001E 
1A RU F8FFFC EFM 0064- 
SP UU OOOIIF8 FKOOOO 
SP UU OOOOFA 

< H > -*80 I 05 00 00 on 

</> 0801 04 
• > -200 
<G> / 

SD UU OOOOFA 0000 

so ru 000190 h noon 

SD RU 000192 M 4000 

SP RU 1)04000 H 4E73 

SP RU 004002 H 4E/1 

SO RU 0000F8 0000 
SD RU OOOOFA 0000 
SO RU OOOOFC 001F 
UP RU 00001E 4F71 
UP RU 000020 4F7I 
OP RU 00002? 4E71 
UP RU 000024 4E71 
OP RU 000024 4F./1 


M)*-BO1 04 00 ( 
</> 0801 04 
• >*• 200 
(Q>7 

SP RU 000000 t 
SP RU 000002 P 
SP RU 000004 E 
SP RU 000004 F 
SP RU 004000 F 
SP RU 004002 F 
SP RU 004004 F 
OP RU 004004 F 
OP RU 004006 F 
OP RU 004008 F 
OD RU 007000 1 
00 RU 007002 F 
OP RU 0Q400A 1 
UO UU 007002 F 
OP UU 007000 F 
UP RU 004001' F 
UP RU 004001 1 
UP RU 004010 F 
UP RU 00401? I 
UP RU 004014 F 
OP RU 004016 I 
UP RU 004018 F 
UP RU 00401A I 

up ru 0040 n: f 

OP UU 008000 I 
UP RU 01)40 It I 
OP RU 0040?0 I 
UP RU 004022 I 
UP RU 004024 I 

so uu nnuFFt i 
SO UU OOOFt A I 
SO UU OOOF Fi' I 
SD RU 000014 I 

sd ru ooon 1 4 I 
SP RU 009000 I 
SP RU 009002 I 
SP RU OOOFFA I 
SD HU OOOFFi: I 
SP RU OOOFIF I 
OP RU 004024 I 
UP RU 004026 I 
OP RU 004028 I 
OP RU 00402A I 
OP RU 0040?i: I 
UP UU 006000 I 
UP RU 004021 I 


“CONTROL NODE TO AUTO AND 
STEP 
“RUN 


-U NO.SR SUirCH to USER PROGRAM 
FITCHE D BUI N01 EXECUTED (FBNF) 


.U Hi 100 r IF COO .L LINK A III SUBROUTINE REAOBYTE 


EAUBY1P. 1 HE MY1E SHOUN )N 1 HE DAT A FIFLP UAH 
ENIEREI) UITH THL AIN KEYBOARD) 

0000. L 000 1.1 


URI1E IOC. 0001 (NODE CONTROl IOC.) 

NOU IHE NODE IS CHANGED: IT IS REQUESTED A BY1E 10 BE 
STORED ON THE 68000 CONTROl INPUT LINES (LEW. 4 INI.) 

- STACK PC LOU < CNTRL BYTE«iFF, INT. Cl EARED) 

- IA AS FUNCTION CODE“IA. UE ARE 

- STACK STATUS IN MANUAL MODE J WECT.8-64 

ESCAPE FROM THE PROGRAM TO 

-"C H ANGE MODE: NOU UITHOUT THE 

CONTROL BYTE 


STACK PC HIGH 

"FETCH INI. WF.CT . <UE ARF IN MAN. MODE AS UE 
ARE OUT OF SOP. DATA SEGMENT 
MANUAL MODE AS Ul ARE OUT THE SUP. PROG. SEG 
FBNF. MANUAl MODE 
- UNSTACK PARAME TERS 


BACK 10 USER PROGRAM 


CONTROl FiODF TO MANUAL ANO 
SIEP 
' RON 


-MOWI.U NO.SR SUITCH TO USER PROGRAM 


-NOP FETCHED BUI N01 EXECUTED 1FBNE > 

-CLR.I 67000.U Cl.EAR LOC. *7000-*7n03 


RF ADS THE IONS UORD UINUSE1 III > 


~ NOP 

J MOW I .U Hi? 00(1. DP 


—mowf.. u po.ienoo.i 


14 BIT MULTIPLI CAT ION 


SHOW DO CONTENTS 


I HI RESUl T OF Mill. 0. U )S iHUOO 

“NOP 

-D1W0.U DO.MU ZERO DIVIDE: WHAT HAPPENS NOU^ 


RF TORN F ROM LXCLP I I ON 
I HHl 

—ONSIACK PAR AMT TINS 


BACK 10 USER I'ROI.HAO 


-MOW).W DO.*6000.1 


SHOW DO CONTI NiS AFIER I HI 
ZERO 01WIDF 


0029 0000 

0030 0000 

non ooon 
003? 0800 

0013 0800 

0034 0500 


0017 0500 

0038 0500 

00 TV OOF A 

004 I OOF A 
0042 OOF A 


004'. OOF 8 
0046 ODER 


0049 OOF C 
0050 OOFC 
005 I OOF D 
005? OOF l> 
0051 OOF F 
0054 OOF F 


005B OOFF 
0059 OOFF 
0060 OOFF 
0061 OOFF 


0065 0801 

0066 0801 
006 / 0801 
0068 8000 
0069 8000 

0070 8001 

0071 8001 

007? 800? 

0073 BOO? 
0074 8001 

0075 8003 

0076 8004 

0077 8004 

0078 8005 

(107V 8005 

0080 8006 
0081 8006 
008? 8007 

0081 8007 

0084 8008 

(1085 8008 

0086 8009 

008/ 8009 

01188 800A 

008V 800A 

0090 BOOR 


,-USFR MAY SPECIFY THESE VAR. ADOR. . IE SEGMENT ADOR . 
-.ARE CHANGED. THESE ADOR. MUST BE ACCORDING! Y DEFINED 
•-•800 

SAVE All IRFFFR TO THF CAI SUB ROUTINE 

* *500 

SAVFAB IRFFFR TO THE LAI SUB ROUTINF 


;P0(N1FR TO START AODR . OF 6502 SII8R . ADDR. TARl E 
• - *F A 

LOCJMP 


:THE EOllOUJNGS ARF USFD AS POINTER FOR 
;INDIRECT 650? ADDRFSSING 


(HIGH BYTE OF A POINTER USED 
FOR 68000 TO HEMORY OPERATIONS 


IIOU BYTF OF POINTER 


IIHF FOIL. ARE USED TO SAVE THF 68000 ADDR. 


(MODE CONTROl VARIABIE. THF ADOR. OF THIS VAR. 
.MUST BE INSIDF USER DATA SFGHENT. SO A 68000 
IPROGRAM CAN CHANGE IT 
* *801 

CONTRl 


(THE FOIl. ARE THF BOARD ADDR. I REFER TO THF TEXT 
.’HARDWARE DESCRIPTION FOR THE THEIR HEANING 
■-BRDADD 


•**200 
MMH6H SEI 

IDA N*FF 
STA con r 

l OOP .ISR C RI OU 
UAITAS lDA CIN 
AND MB 
HNF UAITAS 
l DA CONTRL 
AND UR 
RF« OUTFC 
JhP FAST 


(CLEAR 68000 INPUT SIGN. 


TUAIT FOR ADDR. SIROBE 
I SPEEDY HOOE CONTROL BIT 


0111 021A 

0112 021A 

0113 021A 

0114 021A AD02R0 


0115 0211) 

0116 02 IE 

0117 022(1 

0118 0221 
111 IV (122? 
0120 0221 
0121 0224 

0122 0227 


•OUTPUT 68000 FUNCTION CODE 

IU1 (UNDEFINED) ,1)2 (UNDEFINED) .UP (USER 

.PROGRAM).SP(SUPERVISOR PROGRAM). 

I UD ( USE R DATA) . S0( SIJPE R VISOR DATA), 

> 113(UNDEF 1 ME D ) . I A( INTERRUPT ACK . > 

01JI E C I DA CIN 


AND RX11100000 
l SR A 
L SR A 
l SR A 
I SR A 
TAX 

l DA TABFC.X 
ISR 0IJ1 PUT 
l DA TABFOI.X 
ISR OUTPUT 
.ISR BLANK 


000 ? 0000 
ODOi noun 


(1012 (1000 

ooli noon 


0016 Dunn 
001 ' 0000 

0019 noun 
0020 uono 
nn?i ooon 
0022 01)00 
0023 0000 

0024 0000 

0025 ooon 
0026 0000 


;* MC68000 IN I ERFACING PROGRAM 


l« URITTEN BY LUCA FU6INA ANO CLAUDIO GRANUZ/O 


I IF EIORF 6502 USE R SUBROUTINES ARF ADDED, THF IR FXACT 

.-NUMBER MUST BP SPECIFIED 

MAXR0U*-2 

.HOARD BASF ADDRESS 
BRDADD- *H(10Ci 

fATM 65 MONITOR SUBROUTINES FtttlATES 
CRl 0U»- *E Al 3 IOUTPUT CR.LF 

Bl ANK •E83E IOUTPUT A HI ANK 

NIIMA- *E A46 IOUTPUT A BYTE AS TUO HEX CHAR. 

OIJ rPUT J *E97A IOUTPUT A CHAR. 

RBYTF-BE3F D IREAD TUO HEX CHAR. FROM KEYBOARD 

; AND PACK THEM IN ONE BYTE 

RF AD-*E V3C IREAD ONE CHAR. 


: 01J1 PIJ T 68000 R/U COOF 

: UU(UR 11E UORD),RU(RFAP UORD),UH(UR ITE HIGH 
;8 Y T E >.UL(UR 11E LOU BYTE).RL(READ LOU BYTE), 
;RH(RE AD HIGH PYTE).UN(UNDFFINED) 

OUTRUl I DA CIN 
AND B7 
ASI A 
TAX 

lDA TABRUI.X 
JSR OUTPUT 
LDA TABRUL+1 »X 
JSR OUTPUT 
JSR BLANK 


I OUT PUT 68000 ADDRESSES 
;ue: hui tiply by tuo to convfrt from 
1680(10 UORD ADDR. TO BYTE ADDR. 
OUTADD I DA AOOL 
ASI A 
STA SAVEL 
lDA ADDM 
ROL A 
STA SAVEM 
I DA ADOH 
R 01 A 


36 


Dr. Dobb’s Journal, Number 63, January, 1982 

■29 






0154 0259 

cuss o?58 


or.>8 0261 

oir.v 0245 


0163 026B 

0 164 024F 


016/ 0270 

1)148 OP/? 
0169 0275 

01/0 0?78 


017'.. 027F 

0176 0?7F 

017/ 027F A94D 

0178 0281 207AF9 

0179 0284 703EE8 

0180 0P87 A00P80 

0181 0P8A P901 
0182 02RC OOOF 

0184 028F 

OIR'i 028F AD0180 
01BA 0291 204AFA 
018/ 0294 AD0080 

0188 0297 2046FA 

0189 0P9A 401703 

0191 029D 

0192 029D 

0193 029D 20F0F3 

0194 02A0 800880 

019', 02A3 20FDF3 

0196 02AA 800780 
0197 (I2A9 401703 


OPOO opai: 

0201 02Af ADOPHO 


STA SAVEH 
ISR HIIMA 
I DA SAVFM 
•SR HOMA 
l DA SAVE! 
JSR NUMA 
-JSR 81 ANK 


l DA TONTRl 
AND Ml 


BFQ NOCMO 
JSR RBYTF 
STA COOT 
I DA CONTRL 
AND N? 

BFO AUTO 


JUITH THIS BIT SF T A BYTF IS 
FNTFRFD FROM KEYBOARD 
TO CONIROI THF A8000 INPUT SGN. 


I MANUAL OR AUTO MODF CNTR. BIT 


1 MANIIAI MODF i RFAD FROM KEYBOARD. 

5 MEMORY URITF TO DISPLAY/PRINTFR ONLY 
MANUAI L DA M»4D 

ISR OUTPUT JOUTPUr 'M' 

JSR BLANK 
IDA CIN 

AND Ml ITFST 68000 R/U 

BNE READM 

* IF URITF OUTPUT 68000 DATA BUS 
UR r TFM I DA OIH 
JSR NUMA 
I DA Dll 
JSR NUMA 
IMP TSFR 

JIF RFAD. GET TUO BYTES FROM KFYBOARD AND PUT THFM 
.ON THF 68000 INPUT DATA LATCHFS 
RFADM JSR RBYTF 
STA DOH 
JSR RBYTF 
STA DOL 
.IMP TSFR 


? All I 0 MODF i R/U FROM HFMORY 
AUTO IDA FIN 

;I1F MOR Y SEGMENTATION SECTION ; IF OVERFI.OU 
1FRR0R OR INTA STATE SWITCH TO MANUAL MODE 
FTADD AND MX11100000 

LSR A 
LSR A 
l SR A 
I SR A 
I SR A 
TAX 

CPX M7 

BFO MANUAL 168000 HAS ACK. AN INTERRUPT 

I DA SAVEH 

BNE MANUAI (IFr.MINT GREATER IHAI 

LDA SAVFM 

CMP M»FC 16502 SUBROUTINE CALI 


GREATER I HAN 6 4K. 


0231 (I2D5 8r.fR 

0232 0PD7 ADUPUO 
0233 02DA 2901 
0214 I120C 0025 

0236 02DF 

0217 OPDF A 0028(1 

0238 02E1 290? 

OP 19 02E3 DOHA 

0241 021. r. 

024? OPl 5 AOOO 
0243 OPE 7 AD0180 
0P44 02EA 91FB 
024.fi 02F.T 20461A 

0246 02EF A00280 
0247 02F? 2904 

0248 02F4 DOOA 

0250 02F 6 

0251 OPE 6 A001 

025? OPF 8 AD0080 

0251 OPF8 91FB 

0254 OPF D P046EA 
0255 0300 401703 

0257 0303 

0258 0101 AOOO 

0259 010!, B1FP 

1)260 0307 800880 

0261 010A 2046FA 

0262 030D AOO1 

0261 010F B1FB 

0244 0311 8D0780 

026*.. 0114 2046LA 


BNE LABU 
.IMP CAl SUB 
CMP MAXADD.X 
BCS MANUAI 

n r 

ADC FC1AB.X 


STA FI 
I OA SAVFI 


STA FO 
I DA CIN 
AND Ml 
BNE READA 


16502 SUBROUTINE CALL IF 48000 
ADDR . IS EGUAl TO ftOOFCOO 


IERR. IF SEGMENT IS 
OUT OF ITS RANGE 

• ADD SFG. OFFSFI 10 FFFFCTIVE 
68000 ADDR.. SO TO SELECT THF 
RIGHT MEMORY lOCAIIOMS IN THF 
AIM MEMORY SPACF 


1 TEST 68000 R/U 


? AUTO URITF IN MEMORY 
URITA LDA CIN 
AND N? 

8NF NOUDS 

1 WRITE UPPFR DATA BYTE 
WRIUDS LOY MOO 
I DA DIH 
STA (FO) rY 
JSR NUMA 
NOUDS LDA CIN 
AND M4 
BNE MOLDS 


ITFST 68000 UPPER DATA STROBE 


TEST 68000 LOWFR DATA STROBE 


:URITF 68000 LOUER DATA BYTE 
WRll.DS I DY Ml 
LDA Dll 
STA <FO>»Y 
JSR NUMA 
NOl.DS IMP TSFR 

'.RFAD A WORD FROM HFMORY 
RF ADA lDY MO 

l.DA (FO). Y 
STA DOH 
JSR NUMA 
LDY Ml 
IDA (FO).Y 
STA 001 
JSR NUMA 


02/9 1)128 

ClPBO 0328 ADORNO 

0P81 0328 4C04UP 


0284 01PF 

028/ 032F AD0480 

0288 011 I OA 


0347 039C AD0B8II 

0348 03VF 401)902 


0351 03A2 

0152 U1A2 
0353 03A? 

0354 01A2 

035!. 03AP 
0356 03A2 

0357 03A2 

1)358 03A2 

0359 03A2 

0360 03A? 

0361 03A5 

0362 03A7 

0363 03A9 

0364 03AC 
0365 CI3AF 
0366 0381 

036/ 03B 3 

0368 03B 4 

0369 03B5 

03/0 0388 

0371 038A 

0372 0380 

0373 038F 

0374 03C2 

0375 03C5 

0376 03C8 

0377 03CB 
0178 03CE 


0384 031)4 

0385 0304 46EA 

0386 03D6 F0E3 

0388 0308 

11389 03DR 5757 


1 ISSUE OTACK 
DIA LDA DTACK 

JMP I OOP 


IF AST AUTO MODF: NO OUTPUT IS PERFORMFD 


1 SAVE 48000 ADDR. 
FAST LDA ADDL 
ASI A 


STA FO 
I OA ADOH 
ROl A 
STA SAVFM 
LDA ADOH 
ROL A 
BEG FASTI 
JMP OUTFT 


1HUITIPLY BY TUO 


ISKIP IF SFG. IS l ESS THAN 64K 
lERR.s OUTPUT CYCIE STAT. 


;Mf MORY SEGMENTATION SECTION; ON ERROR 
ISTANOARD CYCIF HANOI IMG IS ENTFRFD. AND 
5F AST MODE IS RF FNTERFD NFXT CYCLF 
FASTI I DA CIN 


AND MtFO 
I SR A 
I SR A 
LSR A 
1 SR A 
I SR A 
TAX 

CPX M7 
BE 8 OUT FI 
LDA SAVEM 
CMP M*FC. 

BFO CAl SUB 
IDA SAVFM 
CMP MAXADD.X 
BCS 0UTF1 
Cl C 

ADC FCTAB.X 
STA FI 
LDA CIN 
AND Ml 
BNF READF 

;FASI MEMORY URITE 
UR)TF I DA CIN 
AND N? 

BNF NOUDSF 
URFUOS I DY NO 
I DA DIH 
STA (FO).Y 
NOUDSF I DA CIN 
AND M4 
BNF NOLDSF 
URFI.DS LDY Ml 
I DA Dll 
STA (FO).Y 
NOI DSF l DA DTACK 

JMP WAITAS 

; I AST HFMORY RFAD 
RFADF lDY MO 

I DA (FO) .Y 
STA DOH 
l DY Ml 
LDA (FO).Y 
STA DOL 


I DA DTACK 
JMP UAITAS 


;68000 FUNCTION ( ODE 


1650? SUBROUTINES CAl L 


1OUT OF SFG. RANGE FRR. 


I ADO SFG. OFFSET 


ITFST 481)00 R/U 


;6502 SUBROUTINES HANDLER. 68000 UPPFR 
5 DATA BY1E IS THE INDEX TO THE SUBROUTINES 
:ADDRFSS TABLE; 68000 10WER 
.DATA BY1F IS I OAOFO IN THE 6502 ACC. 

ION RF1 URN THF 6502 ACC. IS COPIFD IN 

DUO I OCATIONS SPECIFIED BY THE USER I 

1 SAVE All IS l OLA TED IN THE USER DATA SF.GMF NT 1 

;SAVE AS IS 10CATFD IN THF SUPERVISOR 

•DATA SFGMENT 

CAl SUB I OA CIN 

AND Ml ITFST 68000 R/U BECAUS 


BEG CALSII1 

FRR JMP MANUAL 

CAl Sill l.DA DIH 

CMP MMAXROU 
BCS FRR 
ASI A 
I AX 

I DA TABSUB.X 
STA LOCJMP 
l DA TABSUB-H ,X 
STA LOCJMP+1 
lDA DIL 
JSR JMPSUB 
STA SAVEAU 
STA SAVEAS 
IDA DTACK 
JMP I OOP 

JMPSlIB JMP (LOC.IMP ) 


1 4502 SIIBR . TABLE 
TABSIJB . WORD NUMA 
.WORD RBYTF 


JTFST 68000 R/U BECAliSF 
;ONLY URITF IS Al l OUFD 


1SUBR. ADDR. TABLF OVERELOU 


• 68000 R/U CODER 

TARRUl .BYTF ’WWKWWLRLUHRHUNUN’ 


0268 031/ 

0269 (1317 

1)270 0317 

0271 0317 AD010B 

0272 031A 2904 

0273 031C FOOA 

0274 031E 203CE9 

0275 0321 C90D 

0276 0323 F003 

027/ 0325 4C060? 


1 1F STEP MOOE IS SELECTED. UAIT FOR A CHAR. FROM 
;Kf YBOARDi IF IT IS NOT A CR DO NOT ISSlIl 

.DTACK. ANO REPEAT THE CICLE 

TSFR LDA CONTRl 

ANO N4 .STEP MOOE CONTROL BIT 

BEG DTA 
ISR READ 
TMP M400 
BEG OTA 
JMP lOOP 


039 1 03F.8 

0392 03F8 

0394 03F 8 

03V5 03F8 

0396 031B 

1)397 OIF 8 


168000 FUNCTION I OOFS 

TABFC .8YIE 'U1U2UPSPU0SDU3IA' 

5SEGMFNT START ADDR.. EXPRFSSFD IN PAGES OF 256 
;BYTES EACH. USER MAY CHANGE THESE VALUES; TF 
IHF D0( S SO HE HAS TO CHANGE ALL THE RElATFD 
;VAR IABI F ADDRESSES (SFF 10P OF PROGRAM). 

; HF MAY HAVF TO CHANGE VAl UF.S IN THE MAXADD 


(Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 


37 


68000/AIM 65 

(Listing continued, text begins on page 12) 


0199 03FR It A81F»TOO 

0400 03FB 00 FCTAB .BYTE 0 t UNDF FINED 

0401 03F9 00 .BYTE 0 > IINOEFI NED 

040? 03FA Ot; .BYTE BOC (USER PROGRAM 

0403 03FB 04 .BYTE 6 ^SUPERVISOR PROGRAM 

0404 03FC OB .BYTE B I USER DATA 


Pas* OB 

040S 03FD 05 .BYTF 5 ISUPFRVISOR DATA 

0406 03FF. 00 .BYTE 0 »UNDF.F INFO 

0407 03FF 00 .BYTE 0 J(INTA) 


0410 0400 !NUMBER OF PAGES AVAILABIE TO EACH SEGMENT. 

0411 0400 tUSER MAY CHANGE THESE VALUES! HOWEVER THEY 

041? 0400 ;MUST BE CONSISTENT WITH THE SEGMENTS START 

0413 0400 I ADDRESSES JUST DEFINED 

0414 0400 00 MAXAOO .BYTE 0 )UNDEFINED 

0415 0401 00 .BY1E 0 5 UNDFFI NED 

0416 0402 04 .BYTE 4 !USER PROGRAM <1K> 

0417 0403 0? .BYTE ? !SUP. PROGRAM <51? BYTES) 

0418 0404 04 .BYTE 4 JUSER DATA <1K> 

041V 0405 01 .BYTE 1 !SUP. DATA <256 BYTES) 

0420 0406 00 .BYTE 0 !UNDFFINED 

0421 0407 00 .BYTE 0 HINTA) 


0424 0408 ;FNO OF PROGRAM 

0426 0408 .END 

1RR0RS • 0000 


HAXROU A« 0002 BROAD!) At 8000 CRLOW A! FA13 BLANK Ai E83E 

NUHA AJ EA44 OMVPUT Ai F97A RBYTE A* FIFO REAO At E93C 

SAVE All A i 0800 SAVF.AS Ai 0500 I Of.IMP At OOF A FO At OOFB 

FI At OITFC SAVE!. AJ OOFO SAVEM Ai OOF E SAVEH Ai OOFF 

tONIRI At 0801 OIL At BOOO DIH At 8001 TIN At 8002 

COlir A J 8001 ADDl At 8004 ADDM At 800". *AODH At 8006 

OC! At B007 DOH At BOOB MALT At 8009 RES At 800A 

D rACK A: 800B HMM6B At 0200 I OOP AI 0?06 WAITAS Al 0209 

0011C Al 021A OUTRWI. Ai 0233 OUTADO Ai 0?49 INCMD Ai 026B 

CHI) Ai 027? NOCMO A: 0278 MANUAL At 027F WRITEM At 02BE 

Rt ADM At 0?9D AUTO Ai 02AC FCADD At 02AF LABO Ai 02C8 

UKUA At 02DE WRIIIOS Ai l)?E3 NOUOS Al 02FF WRIIDS Al 02F6 

NO! DS At 0300 READA At 0303 TSFR A: 0317 DTA At 0328 

1AST AJ 032E OUT FI At 0340 FASTI At 0343 WRITF Al 036C 

MR 1 1 IDS \l 0373 NOUOSF At 037A WRFLDS A: 03B1 NOt.DSF At 0388 

RFA01 J 038E CALSUH Ai 03A2 ERR At 0 !AV CAlSU1 Al 03AC 

IMP SU 03D1 1ABSUB At 0304 TABRWl At 03DB TABFC At 03F 8 

FC TAB .. 03F8 MAXADD At 0400 

End Listing 


38 


Dr. Dobb’s Journal, Number 63, January, 1982 

~ 



Screen Oriented Editor 

See bug fixes, DDJ Bound Volume page 193. 

bred.c May 11, 1981 page 1 

/• Include file for screen editor 


Idefine SCRNW 64 
Idefine SCRNW1 63 
Idefine SCRNL 16 
Idefine SCRNL1 15 
Idefine SCRNL2 14 
Idefine LISTW 132 


• Source: ed.c 

• Version: Feb. 10, 1980. 

•/ 


linclude 

edO. c 

/• 

1include 

ed1.ccc 

/• 

linclude 

ed2. c 

/• 

linclude 

ed 3. c 

/• 

linclude 

ed 4. c 

/• 

linclude 

ed5. c 

/* 

1 include 

ed6.c cc 

/• 

linclude 

ed7. c 

/• 

linclude 

ed 8. c 

/• 

linclude 

ed 9. c 

/* 

linclude 

ed10 . c 

/* 

linclude 

c801ib 

/• 

edO. c 


Sep 


constant (system) globals •/ 


• command mode commands •/ 
edit mode module •/ 
output format module •/ 
display screen module •/ 
prompt line module •/ 
operating system module •/ 
utility routines •/ 
memory buffer module •/ 
machine language library •/ 


September 8, 1981 


page 1 


/• Screen editor: non-user defined globals 

• 

• Source: edO.c 

• Version: June 19, 1980. 

•/ 


/* Define global constants •/ 

/• Define constants describing a text line •/ 

Idefine MAXLEN 133 /• max chars per line •/ 

Idefine MAXLEN1 134 /• MAXLEN ♦ 1 */ 

/• Define operating system constants */ 

Idefine SYSFNMAX 15 /• CP/M file name length ♦ 1 •/ 

/• Define misc. constants •/ 


Idefine 

EOS 

0 

/• 

code sometimes assumes \0 •/ 

Idefine 

OK 

1 




Idefine 

ERR 

-1 

/• 

error. must be <0 

•/ 

Idefine 

EOF 

-2 

/• 

end of file. must 

be <0 •/ 

Idefine 

YES 

1 

/• 

must be nonzero •/ 


Idefine 

NO 

0 




Idefine 

CR 

13 

/• 

carriage return •/ 


Idefine 

LF 

10 

/• 

line feed */ 


Idefine 

TAB 

9 

/• 

tab character •/ 


Idefine 

HUGE 

32000 

/• 

practical infinity 

•/ 


ed1.c cc 


September 8, 1981 


page 1 


/• 

Screen editor: special key definitions 
Source : ed1.ccc 

This file was created by the configuration program: 
Version 2: September 6, 1981. 

•/ 

/• 

Define which keys are used for special edit functions. 

•/ 


September 8, 1981 page 1 

/• Screen editor: main program 

• Source: ed2.c 

• Version: September 5, 1981. 

•/ 


/• define signon message */ 

Idefine SIGNON "small-c editor, version 2: September 5, 1981." 

/* the main program dispatches the routines that 
• handle the various modes. 

•/ 


Idefine CMNDMODE 1 
Idefine INSMODE 2 
Idefine EDITMODE 3 
Idefine EXITMODE 4 


/• enter command mode flag •/ 
/• enter insert modes flag */ 
/• enter edit mode flag */ 

/• exit editor flag •/ 


main( ) 

{ 

int mode; 

/• fmt output by default goes to screen •/ 
fmtassn(NO) ; 

/• set tabs, clear the screen and sign on •/ 

fmtset(8 ); 

outc1r( ); 

outx y(0,SC RN L 1 ) ; 

message(SIGNON ) ; 

outx y(0,1); 

/• clear filenamet) for save(), resaveO •/ 
name( "" ) ; 

/• clear the main buffer •/ 
bufnew(); 

/• start off in command mode •/ 
modesCMNDMODE ; 

/• get null line 1 for editO •/ 
edgetln( ); 
while(1 ) { 

if (mode==EXITMODE) { 
break ; 

} 

else if (mode==CMNDM0DE) { 
mod e=command( ) ; 

) 

else if (modes=EDITM0DE) { 
modesedit(); 

) 

else if (modessINSMODE) { 
modesinsert(); 

) 

else { 

syserr("main: no mode"); 
modesEDITMODE; 


/• 

• handle edit mode. 

• dispatch the proper routine based on one-character commands. 

•/ 


ed2. c 


September 8, 1981 


page 2 


Idefine UP 1 10 
Idefine DOWN 1 13 
Idefine UP2 21 
Idefine D0WN2 4 
Idefine LEFT 1 8 
Idefine RIGHT 1 18 
Idefine INS1 14 
Idefine EDIT 1 5 
Idefine ESC 1 27 
Idefine DELI 127 
Idefine ZAP 1 26 
Idefine ABT1 24 
Idefine SPLT1 19 
Idefine J0IN1 16 

/* 

Define length and width of screen and printer 

•/ 


editO 

( 

char buffer[SCRNW1 ]; 
int v; 
int x ,y ; 
char c; 

/• we can't do edgetln() or edgo() here because 
• those calls reset the cursor. 

•/ 

pmted i t( ); 
whi le( 1 ) { 

/• get command •/ 
cstolower(syscin()); 
if ((c= =ESC1)!(c= = 'c')) { 

/• enter command mode. •/ 
return(CMNDMODE); 

} 


42 

32 


Dr. Dobb’s Journal, Number 63, January, 1982 



if ((c==INS1):( c = * ' 1')) { 

/• enter Insert mode •/ 
return(INSMODE); 

if (special(c) == YES) { 

if ((c = s UP 1)!(c = = DOWN 1) ) { 
return(INSMODE); 

> 

else { 

continue; 

) 


pmted i t(); 

} 

/• do nothing if command not found •/ 


/• insert mode. 

• in this mode the UP1, UP2 keys reverse their roles, 

* as do the D0WN1, and D0WN2 keys. 

•/ 


if (control(c)s=YES) { 
continue; 

if (css' ') { 
edright(); 
pmtool( ); 

if (c== ' b' ) { 
edbegin( ); 
pmtcolC); 

if (e*«'d') ( 

/• scroll down •/ 
pmtmode("edit: scroll"); 
while (bufnrbot()==N0) { 

if (chkkey()*=YES) { 
break; 

) 

if (eddn()*=ERR) ( 
break; 


insert() 
( 

char c; 


pmtmode("insert"); 

September 8, 1981 

while (1) { 

/• get command •/ 
c:syscin(); 
if (c=sESC1) { 

/• enter command mode •/ 
return(CMNDMODE); 

) 

else if (cssEDITI) { 

/• enter edit mode •/ 
return(EDITMODE); 

) 

else if (cssINSI) { 

/• do nothing •/ 


pmtedit(); 

if (c = = ’e' ) { 

edend( ); 
pmtcol(); 


else if (special(c)ssYES) { 

if ( (c *= UP2) (c = = D0WN2) ) { 
return(EDITHODE); 


if (cst'g') { 

/• save x.y in case don't get number •/ 
x = outgetx(); 
ysoutgety(); 

September 8, 1981 page 


else if (control(c)s=YES) { 

/• ignore non-special control chars •/ 
continue; 


pmtcmnd("edit; goto: ".buffer); 
if(number(buffer,&v)) { 
edgo(v,0); 

) 

else ( 

outxy(x,y); 

) 

pmtedit(); 

) 

else if (c s s'k') ( 

pmtmode("edit: kill"); 
czsyscin(); 

if ((special(c)ssNO) & 

(control(c) = *N0)) { 
edki11 (c); 

) 

pmtedit( ); 

) 

else if (css's') { 

pmtmode("edit: search"); 
cssyscinC ); 

if ( (special(c)ssNO) & 

(control(c)=*N0)) { 
edsrch(c) ; 

) 

pmtedit( ); 

) 

else if (css'u*) { 

/• scroll up •/ 
pmtraode("edit: scroll"); 
while (bufattop()ssNO) { 

if (chkkey()ssYES) { 
break; 

) 

if (edup()s =E R R) { 
break; 

) 

) 

pmtedit(); 

} 

else if (c=='x’) { 

pmtmode("edit: exchange"); 
cs syscin( ); 

if ((special(c)ssNO) & 

( controK c) s=N0) ) { 
edchng(c); 


/• insert one char in line */ 
ed i ns(c); 
pmtcol(); 


/• return YES if c is a control char •/ 

control(c) char c; 

( 

if (cs=TAB) { 

return(NO); /• tab is regular •/ 

) 

else if (c> s127) l 

return(YES); /• del or high bit on •/ 


else if (c<32) ( 

return(YES); /• control char */ 


return(NO); 


/• normal */ 


* handle the default actions of all special keys. 

• return YES if c is one of the keys. 

•/ 

special(c) char c; 

{ 

int k; 

if (c= = JOIN 1) { 

sd2.c September 8, 1981 t 

edjoin(); 
pmtline(); 
return(YES); 

) 

if (cs =SPLT1) { 

ed split( ); 
pm11ine( ); 
return(YES) ; 


Dr. Dobb’s Journal, Number 63, January, 1982 


43 

33 




/• 

• command!) dispatches command routines while 

* in command mode. 

•/ 

command() 

( 

1 n t v; 
char c; 

char argsISCRNWI]; 
char *argp; 
int topline; 
int ypos; 
int oldline; 
int k; 

/* command mode commands may move the current line. 

* command mode must save the current line on entry 

* and restore it on exit. 

•/ 

edrepl(); 

/• remember how the screen was drawn on entry •/ 

oldlines bufln( ); 

yposxoutgety(); 

toplinexoldline-yposvl; 

whiled) { 

outiy(0,SCRNL1); 

fmtcrlf(); 

pmtmode!"command:"); 
getcmnd(args ,0); 
fmtcrlf ( ); 


pm111ne( ); 
cxirgs[0 ]; 

if ((cxxEDITl)!(cxxINSI)) ( 

/• redraw screen •/ 
if (oldlinexxbuflnd) ( 

/• get current line •/ 
edgetlni); 

/• redraw old screen •/ 
bufout(topline,l,SCRNL1); 
outiy(0,ypos); 


/* update line and screen •/ 
edgo(bufln() ,0); 

) 

if (cxxEDITl) { 

return (EDITMODE >; 

) 

else ( 

return (INSMODE); 

) 

) 

else if (tolower(args(0])>x'g')( 
argpxskipbl(argsvi); 
if ( argp [ 0 ) x xEOS ) 1 

edgo(oldline.O); 
return!EDITMODE); 

) 

else if (number(argpv)xxYES) ( 
edgo(v,0); 
return(EDITMODE); 

September 8, 1981 page 7 


message("bad line number"); 


else if (lookup!args,"append")) ( 
append(args); 

) 

else if (lookup!args."change")) ( 
change!args); 

) 

else ir (lookup!args."clear")) I 
clear!); 

) 

else ir (lookup!args."delete")) ( 
delete!args); 

1 

else if (lookup!args,"dos*)) t 
if (chkbuf()xxYES) ( 

return (EXITMODE); 

) 

) 

else if (lookup!args,"find")) ( 
if ((k x find!)) >x 0) 1 

edgo!bufln(),k); 
return(EDITMODE); 


/• get current line •/ 
bufgo(oldline); 
edgetln!); 

/* stay in command mode */ 
message! "pattern not found"); 


else if (lookup!args,"11st")) ( 
list(args); 

) 

else if (lookup(args,"load")) ( 
load(args); 

) 

else if (lookup!args."name")) 1 
name!args); 

) 

else if (lookup!args,"resave")) l 
resave!); 

) 

else if (lookup!args,"save")) ( 
save!); 

) 

else if (lookup!args,"search")) ( 
search!args); 


else if (lookup!args,"tabs")) ( 
tabs!args); 

1 

else ( 

message!"command not found"); 


44 

34 


Dr. Dobb’s Journal, Number 63, January, 1982 


ed2.c September 8, 1981 p< 

/• return YES if line starts with command •/ 

lookup (1 i ne , command ) char Mine, ^command; 

{ 

whi1e(•command) { 

if (tolowe r ( *1 i ne + * ) ! = •commands ) { 
return(NO); 

) 

} 

if((•linexsEOS)i(•line*** ')!(*1ine=*TAB)) { 
return(YES); 

} 

else { 

return(NO); 

) 


/• get next command into argument buffer •/ 
getcmnd(args.offset) char *args; int offset; 


i nt J , k ; 
char c; 


outxy(offset.outgety( )); 
outdeol(); 
kxO; 

while ((c:syscin())IxCR) { 

if ((cxxEDITI)!(cxxINSI)) { 
args[0 ] *c; 
return; 

) 

if ((cxxDELI)!(cxxLEFTI)) { 
if (k>0) { 

outxy(offset,outgety()); 
outdeol(); 
k —; 

J*0; 

while (J<k) { 

outchar(args[ _)♦♦]); 

) 


else if (cxsABTI) ( 

outxy(offset,outgety( )); 
outdeol(); 
k = 0; 

) 

else if ( (c!xTAB)4( (c<32)! (cx=127))) { 
/• do nothing •/ 
continue; 


char locfnCSYSFNMAX]; /• local file name •/ 

/• get file name which follows command •/ 
if (name 1 (args,1ocfn)x=ERR) { 
return; 

) 

if (locfn[0)==E0S) { 

message("no file argument"); 
return; 

) 

/• open the new file •/ 
if ((fi1e=sysopen(locfn,"r"))==ERR) ( 
message("fi1e not found"); 
return; 

) 

/• read the file into the buffer •/ 
while ((nxreadlineCfile.buffer.MAXLEN))>x0) { 
if (n>MAXLEN) { 

message("line truncated"); 
nxMAXLEN; 

) 

if (bufins(buffer.n)xxERR) { 
break; 

) 

if (bufdn()xxERR) { 
break ; 

) 

) 

/• close the file •/ 
sysclose(file); 

/• redraw the screen so topline will be at top 
• of the screen after command() does a CR/LF. 

•/ 

toplinexmax(1,bufln()-SCRNL2); 
bufout(topline.2.SCRNL2); 
buf go(topline); 


/• global change command •/ 


September 8, 1981 


if (<k*offset)<SCRNW1) ( 
args[k**]:c; 
outchar(c); 

) 


args[k]= E OS; 


September 8. 1981 


• Screen editor: command mode commands 

a 

• Source: ed3.c 

• Version: September 5, 1981. 


/• data global to these routines •/ 
char fllenameCSYSFNMAX]; 


/• append command. 

• load a file into main buffer at current location. 

• this command does NOT change the current file name. 

•/ 


append(args) char *args; 

{ 

char buffer[ MAXLEN]; 
int file; 
int n; 

int topline; 


/• disk line buffer •/ 


change(args) char *args; 

{ 

char old 1ine[MAXLEN1]; /• reserve space for EOS •/ 

char newline[MAXLEN1]; 

char oldpat[MAXLEN1]; 

char newpat(MAXLEN1); 

int from, to, col, n, k; 

if (get2args(args,4 from,4to)xxERR) { 

return; 

) 

/• get search and change masks into oldpat, newpat •/ 
fmtsout("search mask ? ",0); 

getcmnd(oldpat,15); 
fmtcr1f(); 

if (oldpat[0]==E0S) { 
return; 

) 

pmtline(); 

fmtsout("change mask ? ",0); 

getcmnd(newpat,15); 
fmtcrlf(); 

/• make substitution for lines between from, to •/ 
while (from<xto) { 

if (chkkey()x =YES) { 
break; 

} 

if ( bufgo( from^-OxxERR) { 
break; 

} 

if (bufatbot()xxYES) { 
break; 

) 

nxbufgetln(oldline,MAXLEN); 
nxminCn,MAXLEN); 
oldlineC n]xEOS; 

/• '*• anchors search •/ 
if (oldpat[0]«s 1 *') { 

if (amatch(oldline.old>at^1,0)xxYES) ( 
kxreplaceColdllne,newline, 
oldpat*1,newpat,0); 
if (kxxERR) { 

return; 

) 

fmtcr1f(); 

putdec(buf1n(),5); 

fmtsout(newline,5); 

outdeol(); 

bufrepl(newline,k); 

) 


(Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 


45 

35 


Screen Oriented Editor 

(Listing continued, text begins on page 18) 

continue; 

) 

/• search oldline for oldpat •/ 
col = 0; 

while (col<n) { 

if ( am atch(oldline,oldpat,col4«-)s*YES)( 
kxrepiace(oldline,newline, 

oldpat,newpat,col-1); 
if (kssERR) { 

retur n; 

} 

fmtcr1f(); 

ed3.c September 8, 1981 page 3 


} 

) 

} 

fmtcr1f(); 


putdec(bufln( ),5); 
fntsout(newline,5); 
outdeol( ); 
bufrepl(newline.k); 
break; 


} 

/• print lines one at a tine to list device •/ 

1ine= fron; 

while (1ine< = to) { 

/• make sure prompt goes to console •/ 
fmtassn(NO); 

/• check for interrupt •/ 
if (chkkey()*=YES) { 
break; 

) 

/• print line to list device •/ 
fntassn(YES); 
if (bufgo(line**) !xOK) { 
break; 

) 

if (bufatbotO) ( 
break; 

) 

n = bufgetln(linebuf.MAXLEN1 ); 

n = min(n,MAXLEN ) ; 

linebuf[n]*CR; 

fmtsout(linebuf,0); 

fmtcr1f( ); 

) 

/• redirect output to console •/ 
fmtassn( HO) ; 

/• restore cursor •/ 
bufgo(oldline) ; 


/• clear nain buffer and file nane •/ 


/• load file into buffer •/ 


clear( ) 

{ 

/• make sure it is ok to clear buffer •/ 
if (chkbu f()* *YES) { 

filename[0 ] =0 ; 
pntfi 1 e( ""); 
outclr(); 
out* y(0,SCRNL1); 
bufnewt ); 

message("buffer cleared"); 

) 

) 

/• multiple line delete conmand •/ 

delete(args) char *args; 

( 

int from, to; 

if (get2args(args,&from,&to)**ERR) { 
return; 

) 

if (fron>to) { 
return; 

) 

/• go to first line to be deleted •/ 
if (bufgo(from)*=ERR) { 
return; 

) 

/• delete all line between from and to •/ 
if (bufdeln(to-from^1)x:ERR) { 
return; 

) 

/• redraw the screen •/ 
buf out(bufln(),1,SCRNL1); 

) 

/• search all lines below the current line for a pattern 

• return -1 if pattern not found. 

• otherwise, return column number of start of pattern. 

•/ 

find ( ) 

( 

return(search1(bufln()4l,HUGE,YES)); 

) 

/• list lines to list device •/ 
list(args) char *args; 

ed3*c September 8, 1981 page 4 

l 

char linebuf[MAXLEN1]; 
int n; 

int from, to, line, oldline; 

/• save the buffer’s current line •/ 
old 1 ine = bufln(); 

/• get starting, ending lines to print •/ 
if (get2args(args,&from,4to)**ERR) { 
return; 


load (args) char "args; 

{ 

char buffer[MAXLEN); 
char locfn [SYSFNMAX]; 
int n; 
int file; 
int topline; 


/• disk line buffer •/ 

/• file name until we check it •/ 


/• get filename following command •/ 
if (name 1 (args,1ocfn)r:ERR) { 

return; 

} 

if (locfn[0]=sE0S) { 

message("no file argument"); 

return; 

) 

/• give user a chance to save the buffer •/ 
if (chkbuf()*=M0) { 
return; 

) 

/• open the new file •/ 

if ((fi1e=sysopen(locfn,"r"))x*ERR) { 

September 8, 1981 pag 

message("flie not found"); 
return; 

) 

/• update file name •/ 
syscopfn(locfn, filename); 
pmtfile(filename); 

/• clear the buffer •/ 
buf new(); 

/• read the file into the buffer •/ 

while ((nxreadline(file,buffer, MAXLEM))>x0) { 

if (n>MA XLEN ) ( 

message("1ine truncated"); 
nxMAXLEN; 

) 

if (bufins(buffer,n)xxERR) ( 
break; 

} 

if (bufdn()xxERR) { 
break; 


/• close the file •/ 
sysclose(file); 

/• indicate that the buffer is fresh •/ 
buf saved(); 

/• set current line to line 1 •/ 
bufgo(1); 

/• redraw the screen so that topline will be 
• on line 1 after commandO does a CR/LF. 

•/ 

topiinexmax(1,bufln()-SCRNL2) ; 
bufout(topllne,2,SCRNL2); 
bufgo(topline); 


/• change current file name •/ 
name(args) char *args; 


46 

36 


Dr. Dobb’s Journal, Number 63, January, 1982 


name 1 (args,filename); 
pmtfile(filename); 


/• check syntax of args. 

• copy to filename. 

• return OK if the name is valid. 


name 1 (args , fi1ename) char *args, ^filename; 

{ 

/• skip command •/ 
args=skiparg(args); 
args=skipbl(args); 

/• check file name syntax •/ 
if (syschkfn(args)==ERR) { 
return(ERR); 

} 

/• copy filename •/ 
syscopfn(args,filename); 
return(OK); 


ed3.c September 8, 1981 

/• save the buffer in an already existing file •/ 


char linebuf[MAXLEN]; 
int file, n, oldline; 

/• make sure file has a name •/ 
if (filename[0]==E0S) { 

message("file not named"); 
return; 

) 

/• the file must exist for resave */ 
if ((fi1e=sysopen(fi1ename t "r"))==ERR) { 
message("fi1e not found"); 
return; 

} 

if (sysclose(file)s=ERR) { 
return; 

} 

/• open the file for writing •/ 
if ((fi 1 e = sysopen(fi1ename,"w"))s=ERR) { 
return; 

} 

/• save the current position of file •/ 
old1ine = buf1n( ) ; 

/* write out the whole file •/ 
if (bufgo(1)==ERR) { 

sysclose(file); 
return; 

) 

while (bufatbotC)==N0) ( 

n=bufgetln(1inebuf,MAXLEN); 
n=min(n.MAXLEN); 

if (pushline(file,1inebuf,n)==ERR) { 
break; 

) 

if (bufdn() = =E R R) { 
break; 

) 

) 

/• indicate if all buffer was saved •/ 
if (bufatbot( )) { 

buf saved( ); 

) 

/• close file and restore line number •/ 
sysclose(file); 
bufgo(oldline) ; 


/• save the buffer in a new file •/ 

save( ) 

{ 

char linebuf[MAXLEN]; 
int file, n, oldline; 

/• make sure the file is named •/ 
if (filename[0]==E0S) { 

message("file not named"); 

return; 

) 

/• file must NOT exist for save •/ 
if ((fi1e=sysopen(fi1ename,"r"))!=ERR) { 


September 8, 1981 

sysclose(file); 
message("fi1e exists"); 


/• open file for writing •/ 
if ((fi1e=sysopen(fi1ename,"w"))==ERR) { 
retur n ; 

) 

/• remember current line •/ 
oldline=bufln(); 

/• write entire buffer to file •/ 
if (bufgo(1)==ERR) { 

sysclose(file); 

return; 

) 

while (bufatbot()==N0) { 

n=bufgetln(linebuf,MAXLEN); 
n=min(n,MAXLEN); 

if (pushline(fi1e,1inebuf,n)s=ERR) { 
break; 

} 

if (bu fd n() = =ERR) { 
break ; 

} 

} 

/* indicate buffer saved if good write •/ 
if (bufatbot()) { 

buf sav ed( ); 

) 

/• restore line and close file •/ 
bufgo (oldline); 
sysclose(file); 


/• global search command */ 

search(args) char *args; 

{ 

int from, to; 

if ( get 2args(args,&from ,& to ) = =ERR ) { 
return; 

} 

search 1(from, to, NO); 


/• search lines for a pattern. 

• if flag == YES: stop at the first match. 

• return -1 if no match. 

otherwise return column number of match 

• if flag == NO: print all matches found. 

•/ 

search 1 (from, to, flag) int from, to, flag; 

{ 

char pat [MAXLEN1]; /• reserve space for EOS •/ 

char line [MAXLEN1]; 
int col, n; 

/• get search mask into pat •/ 
fmtsout("search mask ? ",0); 

geternnd(pa t, 1 5 ) ; 
fmter1f( ) ; 

ed3.c September 8, 1981 page 8 

if (pat[0]==E0S) { 
retur n ; 

) 

/• search all lines between from and to for pat •/ 
while (frora< = to) { 

if (chkkeyC ) = =YES ) { 
break ; 

) 

if ( bufgo( from*0:=ERR) { 
break ; 

} 

if (bufatbot( ) = =YES) { 
break ; 

} 

n=bufgetln(line,MAXLEN); 
n = min(n,MAXLEN ) ; 
line[n]=EOS; 

/• * anchors search •/ 
if (pat[0 ] = = ' “ ' ) { 

if (amatch(line,pat+1,0)r=YES) { 
if (flag= =N0) { 

fmtcrlf( ) ; 
putdec(bu f1n( ) , 5 ) ; 
fmt sout(1ine,5); 
outdeol(); 

} 

else { 

retur n(0 ) ; 


(Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 


47 

37 



Screen Oriented Editor 

(Listing continued, text begins on page 18) 


) 


> 

) 

continue; 

> 

/* search whole line for natch •/ 
col sO; 

while (col<n) 1 

If ! anatch! line,pat,col**)ssYES) ( 
if (flagssNO) { 

fmtcrlf( ); 
putdec! bufln(),5); 
fnt sout(1ine,5); 

outdeoK ); 
break; 

) 

else { 


) 

/• all searching is finished 
IT (flagizYES) { 

return(-1); 

) 

else ( 


return!eol-1 ); 


•/ 


) 


f n t c r 1 f ( ); 


if (number(args,val1)ssHO) ( 

messageCbad argunent"); 
return(E RR); 

) 

/• skip over first argunent •/ 
argss skipargC args); 
args:skipbl(args); 

/• 1 arg: arg 2 is HUGE •/ 
if (•args*»EOS) ( 

•val2.HUGE ; 


ed 3 . c 


September 8, 1981 


) 


return(OK); 

) 

/• check second argunent •/ 
if !number(args,val2)ssNO) 1 

message("bad argunent"); 
return(ERR); 

) 

else 1 

return(OK); 

) 


/* skip over all except EOS, and blanks •/ 


sk1parg(args) char *args; 

1 

while 1!"ergs!sEOS)t!"argsl*' •)) ( 
args**; 

) 

return!args): 


/• set tab stops for fnt routines •/ 


/• skip over all blanks •/ 


page 10 


tabsiargs) char *args; 

I 

ed3.c Septenber 8, 1981 page 9 

lnt n , junk; 

if (get2args(args,tn,4 Junk)«zERR) { 
return; 

) 

fmtset!n); 


/• return YES if buffer nay be drastically changed • / 

chkbuf!) 

( 

if ibufchng!)*sN0) I 

/* buffer not changed, no problem •/ 
returnlYES); 

) 

fntsout!"buffer not saved, proceed ? ",0); 

pmtllne!); 

if !tolower!syscout(syscln!))) Ie' y' ) ( 
fntcrlf!); 

message!"cancelled"); 
return(NO); 

) 

else { 

fntcrlf!); 
return!YES); 

) 

) 

/• print message from a command •/ 

message(s) char *s; 

I 

fntsout!s ,0); 
fntcrlf(); 


sklpbl(args) char "args; 

I 

while ("args*.' •) ( 

args**; 

) 

return!args); 

) 

/• return YES if the user has pressed any key. 

" blanks cm use ■ transparent pause. 

•/ 

chkkey!) 

1 

lnt c; 

casyscstat!); 
if ( c s a 0 ) ( 

/* no character at keyboard •/ 
return(NO); 

) 

else if (ce e' ') { 

/• pause. another blank ends pause • / 
pn 111 n e ( ); 

i f ( syscln! )ee' 1 ) ( 

return(NO); 

) 

) 

/* we got a nonblank character • / 
return(YES); 

) 

/• anchored search for pattern in text line at column col. 
• return YES if the pattern starts at col. 

•/ 

snatch!line .pat,col) char "line, "pat; lnt col; 

1 

lnt k; 

ksO; 

ed3.c Septenber 8, 1981 page 11 


/* get two argunents the argunent line args. 

* no argunents imply 1 HUGE. 

* one argument implies both args the sane. 

•/ 

get2args!args,val1,val2) char "args; lnt "vail, "val2; 

1 

/• skip over the conmand */ 
argstsklparg!args); 
argss skipbl!args); 
if !"argss=E0S) I 
•val1xl ; 

•val2sHUGE; 
return!0K); 

) 

/* check first argunent •/ 


while !pat[k]isEOS) l 

if (pattk)xxllne!col]) ( 
k"»; 
coles; 

) 

else if ((pat[k)ss'?')t(llnetcol]IsEOS)) 
/* question nark matches any char 
k*«; 
cola*; 

) 

else ( 

return(HO); 

) 


) 

/• the entire pattern matches •/ 
returnlYES); 


•/ 


48 

38 


Dr. Dobb’s Journal, Number 63, January, 1982 



/• replace oldpat in oldline by newpat starting at col. 

* put result in newline. 

* return number of characters in newline. 

•/ 

replace(oldllne,newline,oldpat,newpat,col) 

char •oldline, •newline, •oldpat, # newpat; int col; 

{ 

int k; 

char •tail, *pat; 

/• copy oldline preceding col to newline •/ 

k = o; 

while (k<col) { 

newline[k**]**oldline**; 

) 

/• remember where end of oldpat in oldline is •/ 
tallsoldllne; 
pat=oldpat; 
while (*pat**IzEOS) { 
tai1**; 

) 

/• copy newpat to newline. 

• use oldline and oldpat to resolve question marks 

• in newpat. 

•/ 

while (*newpat!= EOS) { 

if ( k>M AXLE N-1) { 

message("new line too long"); 
return(ERR); 

) 

if (•newpat!*'?•) { 

/• copy newpat to newline •/ 
newline[k**]: # newpat**; 
continue; 

} 

/• scan for •?• in oldpat •/ 
while (•oldpat!*'?• ) { 

if (•oldpatxsEOS) { 
message( 

"too many ?'s in change mask" 

); 

return(E RR); 

) 

oldpat**; 


edredraw(); 
edbegin(); 
edcflag=NO; 


/• put cursor at beginning of current line •/ 

edbegin() 

{ 

ed i t psO ; 

outxy(0,outgety()); 

) 

/• change editbuf[editp] to c 
• don't make change if line would become to long 

•/ 

edchng(c) char c; 

{ 

char oldc; 
int k; 

/• if at right margin then insert char •/ 
if (editp>seditpraax) { 
edins(c); 
return; 

1 

/• change char and print length of line •/ 
oldc=editbuf[editp]; 
editbuf[editp]=c; 
fmtadj(editbuf,editp,editpraax); 
k=fratlen(editbuf,editpmax); 
if (k>SCRNW1) { 

/* line would become too long •/ 

/• undo the change •/ 
editbuf[editp]soldo; 
fmtadj(editbuf,edltp,editpmax); 


/* set change flag, redraw line •/ 
edcflag=YES; 
ed11p* *; 
ed red raw( ) ; 

September 8, 1981 I 


September 8, 1981 


page 12 


/• delete the char to left of cursor if it exists •/ 


oldline*♦; 

) 

/• copy char from oldline to newline •/ 

newline[k**]s*oldllne**; 

oldpat**; 

newpat**; 

} 

/• copy oldline after oldpat to newline •/ 
while (•tail!*EOS) ( 

if (k> sMAXLEN-1) ( 

message("new line too long"); 
return(ERR); 

) 

newllne[k**]s*tall**; 

) 

newllne[k]sEOS; 
return(k); 

) 


edU.c September 8, 1981 page 1 

/• 

• Screen editor: window module 

• 

• Source: ed4.c 

• Version: August 20, 1981. 

•/ 


/• data global to this module •/ 


char 

editbuf[MAXLEN] ; 

/• 

the edit buffer •/ 

int 

ed1tp; 

/• 

cur sor: 

: buffer index •/ 

int 

editpm ax ; 

/• 

length 

of buffer •/ 

int 

edcflag; 

/• 

buffer 

change flag •/ 


/• abort any changes made to current line •/ 


edabt( ) 

{ 

/• get unchanged line and reset cursor •/ 
edgetln(); 


eddel () 

{ 

int k; 

/• Just move left one column if past end of line •/ 
if (edxposO < outgetxO) { 

outx y ( outge tx ( )- 1 , outgetyO); 
return; 

) 

/• do nothing if cursor is at left margin •/ 
if (editpssO) { 
return; 

) 

edcflagsYES; 

/• compress buffer (delete char) •/ 
k*editp; 

while (k<edltpmax) { 

editbuf(k-1)seditbuf[k); 
k**; 

} 

/• update pointers, redraw line •/ 
editp--; 
editpraax--; 
edredraw( ) ; 

} 

/• edit the next line. do not go to end of buffer •/ 

eddn( ) 

{ 

int oldx; 

/• save visual position of cursor •/ 
oldx=outgetx(); 

/• replace current edit line •/ 
if (edrepl()!=0K) { 
return(ERR); 

} 

/• do not go past last non-null line •/ 
if (bufnrbot()) { 

return(0K); 

} 

/• move down one line in buffer •/ 
if (bufdn()!=0K) ( 

(Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 


49 

39 




Screen Oriented Editor 

(Listing continued, text begins on page 18) 

retur n(E RR); 

) 

edgetln(); 

/• put cursor as close as possible on this 
• new line to where it was on the old line. 

•/ 

editpsedscan(olds); 

/• update screen •/ 
if (edatbot()) ( 

edsup(bufln(J-SCRML2) ; 
outsy(olds. SCRNL1); 

) 

else ( ' 

outxy(oldx, outgety()»1); 

) 


) 

/• insert character, update pointers •/ 
editbuf[editp]cc; 
editpa*; 
editpaax*♦; 

/• recalculate print length of line •/ 
fBtadJ(edltbuf,edltp-1 .editpaax); 
ksfatlen(edltbuf.edltpaax); 
if (k>SCRNW1) ( 

/* line would becoae too long •/ 

/• delete what we Just inserted •/ 
eddel( ); 

I 

else ( 

/• set change flag, redraw line •/ 
edcf1agsYES; 
edredraw(); 

) 

) 


«dR.c Septeaber 8, 1981 page 3 

return(OK); 

) 


/• Join (concatenate) the current line with the one above it •/ 

edJoint ) 

( 

int k; 


/• put cursor at the end of the current line •/ 

edend( ) 

l 

editpied1tpaax ; 

outxy(edxpos(),outgety()); 

/• coament out - put cursor at end of screen 

outxy(SCRNW1, outgetyO); 

----- end coament out •/ 

> 

/• start editing line n 
• redraw the screen with cursor at position p 

•/ 

edgo(n, p) int n, p; 

( 

/• replace current line •/ 
if (edrepl().«ERR) ( 
return(ERR); 

) 

/* go to new line •/ 
if (bufgotn) = »ERR) ( 
return(ERR); 

) 

/• prevent going past end of buffer •/ 
if (bufatbotO) ( 

if (bufup()**ERR) ( 
return(ERR); 

) 

) 

/• redraw the screen •/ 
bufout(bu f1n(),1,SCRNL1); 
edgetlnt ); 

edltpialntp, edltpmax); 
outsy(edxpost), 1); 
return(OK); 

) 

/• insert c into the buffer if possible •/ 

edlns(c) char c; 

< 

int k; 

/• do nothing if edit buffer is full •/ 
if (edltpmaxXsMAXLEN) ( 
return; 

) 

/• fill out line if we are past its end •/ 
if ((editp ss edltpmax) A (edxposO < outgetxO)) ( 
k s outgetxO - edxposO; 
edltpmax s editpaax ♦ k; 
while (k-- > 0) 1 

edltbuf [editp**) s ' '; 

) 

editp s edltpmax; 

) 

edU.c Septeaber 8, 1981 page 4 

/• aake rooa for Inserted character •/ 
ksedltpaax ; 
while (k>edltp) ( 

edltbufCklsedltbuftk-1]; 
k —; 


/* do nothing if at top of file •/ 
if ( bufattop( )) ( 
return; 

) 

/* replace lower line temporarily •/ 
if (edreplt) Is OK) ( 
return; 

) 

/• get upper line into buffer •/ 
if (bufupO 1= OK) ( 
return; 

) 

k s bufgetlnteditbuf, MAXLEN); 

/* append lower line to buffer •/ 
if (bufdnt) Is OK) ( 
return; 

) 

k s k ♦ bufgetln(edltbuf♦k, HAXLEN-k); 

/• abort if the screen isn't wide enough •/ 
if (k>SCRNW1) ( 
return; 

) 

/• replace upper line •/ 
if (bufupO Is OK) ( 
return; 

) 

editpaax s k; 
edcflag s YES; 
if (adrepio Is OK) ( 
return; 

) 

edU.c Septeaber 8, 1981 page 5 

/* delete the lower line •/ 
if (bu f d n( ) Is OK) ( 
return; 

) 

if (bufdelO != OK) ( 
return; 

) 

if (bufup() Is OK) ( 
return; 

) 

/• update the screen •/ 
if (edattopO) ( 

edredriwl); 

) 

else ( 

k s outgety( ) - 1; 

bu f out(bu f1n(),k,SCRNL-k); 

outxy(0,k); 

edredraw(); 

) 

) 

/* delete chars until end of line or c found •/ 

edkill(c) char c; 

( 

int k.p; 

/• do nothing if at right margin •/ 
if (editpssedltpmax) ( 

return; 

) 

edcflagsYES; 

/• count number of deleted chars •/ 

ks 1 ; 


50 

40 


Dr. Dobb’s Journal, Number 63, January, 1982 




while ( (e<Jitp*k) <editpmax ) { 

if ( edi tbuf [ edltp+k ] s*c) { 
break ; 

) 

else { 

k + + ; 

} 

) 

/• compress buffer (delete chars) •/ 
p = ed i t p-fk ; 

while (p<editpmax) { 

editbuf[p-k]seditbuf[p] ; 

P^*J 

} 

/• update buffer size, redraw line •/ 

editpmaxseditpmax-k; 

edred raw( ); 


/• move cursor left one column. 

• never move the cursor off the current line. 

•/ 


edleft() 

{ 

lnt k; 

/• if past right margin, move left one column •/ 


edk.c September 8, 1981 page 6 

if (edxposO < outgetxO) { 

outxytnax (0, ou t ge tx ( ) -1 ) , outgetyO); 

) 

/• inside the line. move left one character •/ 
else if (editp!*0) { 
editp--; 

outxy(edxpos( ) .outgety( )); 

) 

) 


ed4. c 


September 8, 1981 


page 7 


/• start editing the zero length line •/ 
edgetlnC); 

/• update the screen */ 
if (edattop()) { 

edsdn(bufln()); 
outxy(edxpos(),1); 

) 

else { 

k=outgety(); 

bufout(bufln(),k,SCRNL-k) ; 
outx y(edx pos(),k) ; 

> 

) 


/• move cursor right one character. 

• never move the cursor off the current line. 

•/ 


edright( ) 

( 

/• if we are outside the line move right one column •/ 
if (edxpos() < outgetxO) { 

outxy ( min (SCRNW 1 , out getx ( ) ♦ 1 ) , outgetyO); 

) 

/• if we are inside a tab move to the end of it •/ 
else if (edxposO > outgetx ( )) { 

outxy (edxposO, outgetyO); 

} 

/• move right one character if inside line •/ 
else if (editp < editpmax) { 
editp + ♦ ; 

outxy(edxpos().outgety( ) ); 

) 

/• else move past end of line •/ 
else { 

outxy (min(SCRNW1, outge tx ( ) ♦ 1 ) , outgetyO); 

) 


) 


/• Insert a new blank line below the current line •/ 

ednewdn() 

{ 

lnt k; 

/• make sure there is a current line and 
* put the current line back into the buffer. 

•/ 

if (bufatbotO) { 

if (bufins(editbuf,ed1tpmax)!*0K) ( 
return; 

) 

) 

else if (edrepl()t*0K) ( 
return; 

) 

/• move past current line •/ 
if (bufdnOlsOK) { 
return; 

} 

/• insert place holder: zero length line •/ 
if (bufins(editbuf.0)!*0K) ( 
return; 

) 

/• start editing the zero length line •/ 
edgetln( ); 

/• update the screen •/ 
if (edatbotO) { 

/• note: buflnO >* SCRNL •/ 
edsup(buf1n()-SCRNL2); 
outxy(edxpos().SCRNL1); 

) 

else { 

ksoutgety(); 

bufout(bufln(),k*1.SCRNL1-k); 
outxy(edxpos(),k+1); 

) 

1 

/• Insert a new blank line above the current line •/ 

ednewup() 

( 

lnt k; 

/• put current line back in buffer •/ 
if (edreplO !*0K) ( 
return; 

) 

/• insert zero length line at current line •/ 
if (buflns(edltbuf.O)! = 0K) ( 
return; 

) 


/• split the current line into two parts. 

• scroll the first half of the old line up. 

•/ 

edsplit( ) 

l 

lnt p, q; 
lnt k; 

/• indicate that edit buffer has been saved •/ 
edcflag = HO; 

/• replace current line by the first half of line •/ 
if (bufatbot()) { 

if (bufins(editbuf, editp) Is OK) { 
return ; 

) 

) 

else { 

if (bufrepl(editbuf. editp) != OK) { 
return ; 

) 

) 

/• redraw the first half of the line •/ 

ed4.c September 8, 1981 page 8 

p s editpmax; 
q = editp; 
editpmax = editp; 
editp = 0; 
edredraw(); 

/• move the second half of the line down •/ 
editp = 0; 
while (q < p) { 

editbuf [editp^+l = editbuf [q+*]; 

) 

editpmax = editp; 
editp * 0; 

/• insert second half of the line below the first •/ 
if (bufdn() != OK) { 
return; 

) 

if (bufins(editbuf. editpmax) != OK) { 
return; 

) 

/• scroll the screen up and draw the second half •/ 
if (edatbot()) ( 

ed sup(buf1n()-SCRNL2); 
outx y(1.SCRNL1); 
edredraw(); 

) 

(Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 


5J_ 

41 




Screen Oriented Editor 

(Listing continued, text begins on page 18) 

else { 

k s outgetyO; 

bufout ( buf ln( ) , k-fl, SCRNLl-k); 
outx y( 1 , k♦1 ) ; 
edredr aw( ) ; 

} 

} 

/• move cursor right until end of line or 
• character c found. 

•/ 


edsrch(c) char c; 
{ 


) 


/• do nothing if at right margin 
if (editp = = editpmax ) { 
return ; 

} 

/• scan for search character •/ 


editp*^; 

while (editp<editpraax ) { 

if (editbuf[editp]ssc) { 
break ; 

} 

el se { 

editp^*; 

} 


} 

/• reset cursor •/ 
outxy(edxpos() , outgety( )); 


•/ 


/• move cursor up one line if possible •/ 

edup() 

{ 

int oldx ; 

September 8. 1981 


page 9 


/• save visual position of cursor •/ 
oldx = outgetx( ); 

/• put current line back in buffer •/ 
if (edrepl() !*OIO { 
return(ERR); 

) 

/• done if at top of buffer •/ 
if (bufa ttop( )) { 

return(OK); 

} 

/• start editing the previous line •/ 
if (bufup()fsOK) { 

return(ERR ); 

) 

edgetln( ); 

/• put cursor on this new line as close as 
• possible to where it was on the old line. 

•/ 

editpsedscan(oldx); 

/• update screen •/ 
if (edattop( )) { 

edsdn(bufln( )); 
outx y(oldx , 1); 

} 

else l 

outx y(oldx , outgety()-1 ); 

) 

return(OK); 


/• delete the current line •/ 


ed zap( ) 

{ 

int k; 


/• delete the line in the buffer •/ 
if (bufdel()!sOK) { 
return; 

} 

/* move up one line if now at bottom •/ 
if (bufatbotO) { 

if (bufup()!=0K) { 
return ; 

} 

edgetln( ); 

/• update screen •/ 
if (edattopO) { 

edredraw(); 

} 


else ( 

outdelln(); 
outxy(0,outgety()-1); 

) 

return ; 

} 

/• start editing new line •/ 
edget1n( ) ; 

/• update screen •/ 
if (edattop( ) ) { 

ed sup(bufln() ) ; 
outx y(0 , 1 ); 

) 

«d4.c September 8, 1981 page 10 

else { 

k = outgety( ); 

bufout(bufln(),k,SC R N L-k); 
outx y(0,k); 

} 

) 

/• return true if the current edit line is being 

• displayed on the bottom line of the screen. 

•/ 

edatbot( ) 

{ 

return(outgety()==SCRNL1); 

> 

/• return true if the current edit line is being 

• displayed on the bottom line of the screen. 

•/ 

edattop() 

( 

return(outgety( ) = r 1 ) ; 

} 

/• redraw edit line from index to end of line •/ 

/• reposition cursor •/ 

edredraw() 

{ 

fratadj(editbuf,O.editpmax ) ; 

rmt9ubs(editbuf,max(0,edit p-1).editpmax); 
outxy(edxpos( ) .outgety( )); 

) 

/• return the x position of the cursor on screen •/ 

edx pos() 

( 

return(min(SCRNW1,fmtlen(editbuf,editp))); 

) 


/• fill edit buffer from current main buffer line. 

• the caller must check to make sure the main 

• buffer is available. 

•/ 


edgetln() 

( 

int k; 

/• put cursor on left margin, reset flag •/ 
editp = 0 ; 
edc f1ag = NO ; 

/• get edit line from main buffer */ 
ksbufgetln(editbuf.MAXLEN); 
if (k>MAXLEN) { 

error("line truncated"); 
editpmax=HAXLEN; 

) 

else { 

edi tpraax = k; 

*d4.e September 8, 1981 page 11 

> 

fmtadj(editbuf,O.editpmax); 


/• replace current main buffer line by edit buffer. 

• the edit buffer is NOT changed or cleared. 

• return ERR is something goes wrong. 

•/ 


edrepl() 

( 

/• do nothing if nothing has changed •/ 
if (edc f1ag= sNO) ( 

return(OK); 


52 

42 


Dr. Dobb’s Journal, Number 63, January, 1982 



• the list device. 

•/ 


/• make sure we don't replace the line twice •/ 
edcflagsNO; 

/• insert instead of replace if at bottom of file •/ f®tassn(11stf1ag) int listflag; 


If (bufatbotO) ( 

return(bufins(editbuf,editpmax>); 

} 

else { 

return(bufrepl(editbuf,editpmax)); 

} 


/• set editp to the largest index such that 
• buf[editp] will be printed <* xpos 

•/ 

edscan(xpos) int xpos; 

( 

editp = 0; 

while (editp<editpmax) { 

if (fmtlen(editbuf.editp)<xpos) { 
editp4>; 

} 

else { 

break; 


return(editp); 


/• scroll the screen up. topline will be new top line •/ 

edsup(topiine) int topline; 

{ 

if (outhasup()ssYES) ( 

/• hardware scroll •/ 
out sup( ); 

/• redraw bottom line •/ 
bufout(topiine*SCRNL2.SCRNL1, 1); 


if (listflagssYES) { 
fmtdev=YES; 
fmtwidth=LISTW; 


fmtdevrNO; 
fmtwidthsSCRNW1; 


/* adjust fmtcol[] to prepare for calls on 

• fmtout() and fmtlenC) 

• 

• NOTE: this routine is needed as an efficiency 

• measure. Without fmtadj(), calls on 

• fmtlen() become too slow. 


fmtadJ(buf.rainind.maxind) char *buf; int minind.maxind; 

{ 

int k; 

/• line always starts at left margin •/ 
f mtool[0] = 0; 

/• start scanning at minind •/ 
ksminind; 

while (k<maxind) { 

if (buf[k]:zCR) { 
break; 

} 

fmtcol[k^1]rfmtcol[k]^fmtlench(buf[k],fmtcol[k]); 
k-**; 

ed5.c May 11, 1981 page 2 


/• redraw whole screen •/ 
bufout(topline,1.SCRNL1); 


/• scroll screen down. topline will be new top line •/ 


/• return column at which at which buf[i] will be printed 

fmt1en(buf,i) char *buf; int i; 

{ 

return(fmtcol[i]); 

) 


ed*4.c September 8, 1931 

edsdn(topiine) int topline; 

( 

if (outhasdn()s*YES) ( 

/• hardware scroll •/ 
outsdn(); 

/• redraw top line •/ 
bufout(topline,1,1); 


/• redraw whole screen •/ 
bufout(topline,1,SCRNL1); 


ed5.c May 11, 1981 

/• Screen editor: output format module 

• 

• Source: ed5.c 

• Version: March 6, 1981. 


/• Define variables global to this module •/ 

/• define maximal length of a tab character •/ 
int fmttab; 

/• define the current device and device width •/ 


int fmtdev; 
int fmtwidth; 


/• fmtcolti] is the first column at which 

• buf[i] will be printed. 

• fmtsubO and fratlen( ) assume fmtcol[] is valid on entry. 

•/ 

int fmtcol[MAXLEN1]; 

/• direct output from this module to either the console or 


/• print buf[i] ... bufCj-1] on current device so long as 
* characters will not be printed in last column. 

•/ 

fmtsubsCbuf,1,j) char *buf; int i, j; 

{ 

int k; 

if (fmtcol[i]>sfmtwidth) { 
return ; 

) 

outxy(fmtcol[i],outgety()); /• position cursor •/ 

while ( i< J ) { 

if (buf[i]**CR) { 
break; 

) 

if (fmtcolti*1]>fmtwidth) { 
break ; 

) 

fmtoutch(buf[i],fmtcol[i]); 


outdeo1(); 


/• clear rest of line •/ 


/• device — YES/NO s LIST/CONSOLE •/ 
/• devide width. LISTW/SCRNW1 •/ 


/• print string which ends with CR or EOS to current device. 
• truncate the string if it is too long. 

•/ 

fmtsout(buf.offset) char *buf; int offset; 

( 

char c; 
int col,k ; 

col=0; 

while (c=*buf4-0 { 

if (cs=CR) { 

break ; 

) 

ksfmtlench(c.col); 
if ((col^k^offset)>fmtwidth) { 
break; 

) 

fmtoutchCc,col); 
col * col♦k; 

) 

(Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 




Screen Oriented Editor 

(Listing continued, text begins on page 18) 

) 

/• return length of char c at column col •/ 

fffltlench(c.col) char c; int col; 

{ 

If (cssTAB) ( 

/• tab every fmttab columns */ 


ed5 . c 


May 11, 1981 page 3 

return!fmttab-(coltfmttab)): 

) 

else If (c<32) 1 

/• control char •/ 
ret urn(2); 

) 

else { 

return!1); 

) 


) 


/* output one character to current device. 
• convert tabs to blanks. 

•/ 

fmtoutch(c,col) char c; lnt col; 

( 

lnt k; 

If (cssTAB) { 

k=fmtlench(TAB,col); 
while ((k—)>0) ( 

fm' levch(' '); 

) 

) 

else If (c<32) I 

fmtdevch!'* *); 
fmtdevch(o+6A); 

) 

else { 

fmtdevch!c); 

) 

) 

/* output character to current device •/ 


Screen editor: terminal output module 
Source: ed6.ccc 

This file was created by the configuration program: 
Version 2: September 6, 1981. 

•/ 

/• 

Define the current coordinates of the cursor. 

•/ 

int outs, outy; 

/• 

Return the current coordinates of the cursor. 

•/ 

outgetx() 

( 

returntoutx); 

) 

outgety() 

( 

return!outy); 

) 

/* 

Output one printable character to the screen. 

•/ 

outchar(c) char c; 

l 

syscout! c); 
outs♦♦; 
return!c); 

) 

/* 

Position cursor to position x,y on screen. 

0,0 Is the top left corner. 

•/ 

outx y(x,y) lnt x , y ; 

l 

o u t x = x ; 
outy=y; 
ayscout!27); 
syscout('='); 
syscout(x»32); 
syscout(y*32); 

) 


fratdevch(c) char c; 

1 


) 


If !fmtdev = sYES ) { 
syslout!c); 

) 

el se ( 

outchar(c); 

) 


/• output a CR and LF to the current device •/ 


fmtcrlf! ) 

{ 


If !fmtdevaeYES) { 

syslout!CR); 
syslout(LF); 

) 

else ( 

/* kludge: this should be In out module •/ 
/• make sure out module knows position •/ 
outxy!0,SCRNL1); 
syscout(CR); 
syscout(LF); 

) 

) 


ed5. c 


May 11, 1981 


/• set tabs at every n columns •/ 


page 1 


fmtset(n) int n; 

{ 

fmttabamax(1,n); 

) 


ed6.ccc 


September 8, 1981 


page 1 


/• 

Erase the entire screen. 

Make sure the rightmost column Is erased. 

•/ 

outclr!) 

( 

int k; 

ed6.ccc September 8, 1981 

k:0; 

while (k < S C R N L) ( 

outx y(0,k«» ); 
outdelln!); 

) 

outx y(0,0); 

) 

/• 

Delete the line on which the cursor rests. 
Leave the cursor at the left margin. 

•/ 


outdelln!) 

l 

outxy(0.outy); 
outdeol( ); 

) 

/• 

Delete to end of line. 

Assume the last column is blank. 

•/ 

outdeol() 

( 

syscout(27); 
syscout!•E '); 

) 


page 2 


/• 


/• 


54 

44 


Dr. Dobb’s Journal, Number 63, January, 1982 



Return yes If teralnal has indicated hardware scroll. 

•/ 

outhasup() 

! 

return!YES); 

I 

outhasdnt ) 

( 

return!YES); 

) 

/• 

Scroll the screen up. 

Assume the cursor is on the bottom line. 

•/ 

outsup!) 

{ 

/* auto scroll •/ 
outiyCO,SCRNL1); 
syscout(10); 

) 

/• 

Scroll screen down. 

Assume the cursor is on the top line. 

•/ 

outsdn() 

ed5 - coc September 8. 1981 ... 


/• auto scroll •/ 
outiy(0,0); 
syscout(27); 

syscout!•“•>; 



edT.c May 11, 1981 page 1 


/* Screen editor: prompt line module 

• 

• Source: ed7.c 

• Version: March 6, 1981. 

•/ 

/• Define the prompt line data •/ 

char pratln[MAXLEM ]; /• mode •/ 

char pmtfn[SYSFMMAX]; /• file name •/ 

/• put error message on prompt line. 

• wait for response. 

•/ 

pmtmess(s 1.s2) char *s1, *s2; 

{ 

int i,y ; 

/• save cursor •/ 
xzoutgetx(); 
y = outget y(); 
outxy(0,0); 

/• make sure line is correct •/ 
outdelln(); 
pntline1(); 
pm tool 1(x); 

/• output error message •/ 
fmtsout(s1,outgetx()); 
fmtsout(s2,rutgetx()); 

/• wait for input from console •/ 
syscin( ); 

/• redraw prompt line •/ 

pm11ine 1 (); 

pmtcol1(x); 

pmtfile 1 (pmt fn); 

pmtmode 1(pmtln); 

/• restore cursor •/ 
outxy(x ,y); 

} 

/• write new mode message on prompt line •/ 

pmtmode(s) char *s; 

{ 

int x,y; /• save cursor on entry •/ 

/• save cursor •/ 
xzoutgetx(); 
yz outgety(); 


/• redraw whole line •/ 

outxy(0,0); 

outdelln(); 

pmtline1(); 

pmtcol1(x); 

pmtfile1(pratfn); 

pmtmode 1 (s); 

/• restore cursor •/ 
outxy(x,y); 

} 

/• update file name on prompt line •/ 

ed7.c May 11, 1981 page 2 

pmtfile(s) char *s ; 

{ 

int x, y; 

/• save cursor •/ 
xzoutgetx( ) ; 
yz outgety( ) ; 

/• update whole line •/ 

outxy(0,0); 

outdel ln( ) ; 

pmtline 1 ( ) ; 

pmtcol1( ); 

pm t f i 1 e 1 ( s) ; 

pmtmode 1 (pmtln); 

/• restore cursor •/ 
outxy(x , y ) ; 

) 

/• change mode on prompt line to edit: •/ 
pmtedit() 

pmtmode("edit:"); 

) 

/• update line and column numbers on prompt line •/ 

pmtline() 

( 

int x ,y; 

/• save cursor •/ 
xzoutgetx( ) ; 
yzoutgety( ) ; 

/• redraw whole line */ 

outxy(0,0); 

outdel1n( ) ; 

pmt1 ine 1 ( ) ; 

pmtcol1(x ) ; 

pmtflie 1(pmtfn); 

pmtmode1(pmtln); 

/• restore cursor •/ 
outxy(x.y); 

) 

/• update just the column number on prompt line •/ 

pmtcol( ) 

{ 

int x ,y; 

/• save cursor •/ 
x:outgetx( ) ; 
yzoutgety( ); 

/* update column number */ 
pmtcol1(x); 

/• update cursor •/ 
outxy(x , y); 

) 

/• update mode. call getcmnd() to write on prompt line •/ 

pmtcmnd(mode .buffer) char •mode, *buffer; 

( 

int x ,y; 

ed7.c May 11. 1981 page 3 

/• save cursor •/ 
xzoutgetx( ); 
yzoutgety(); 
pmtmode1(mode); 

/• user types command on prompt line •/ 
getcmnd(buffer,outgetx( )); 

/• restore cursor •/ 

} 

/• update and print mode •/ 

pmtraodel(s) char *s; 

{ 

int i; (Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 



Screen Oriented Editor 

(Listing continued, text begins on page 18) 

o u t x y ( 4 0,0 ); 
fmtsout(s,40 ) ; 
irO; 

while (pratlnt!♦♦]=•»♦♦) { 

} 

) 

/• print the file name on the prompt line •/ 

protfi1e 1 (a) char # s ; 

{ 

i n t i ; 

outxy(25,0); 
if (*s = = E0S ) { 

fmtsout("no file",25); 

} 

else { 

frotsout(s,25); 

) 

i = 0; 

while ( pmt fn ] = *s + * ) { 

) 

) 

/• print the line number on the prompt line •/ 

pmt1ine1() 

{ 

outxy(O.O); 
fmtsout("line: ",0); 
putdec(bufln() ,5) ; 

) 


/• print column number of the cursor •/ 

pmtool 1(x ) int x ; 

l 

out x y(12,0 ); 

fmtsout("column : ",12); 

putdec < x , 3)• 

) 


ed8.c September 8, 1981 page 1 

/• Screen editor: operating system module 

• 

• Source: ed8.c 

• Version: June 19, 1981. 

•/ 

/• all calls to the operating system are made here. 

• only this module and the assembler libraries will have to 

• rewritten for a new operating system. 

•/ 

/• the routines syscstat(), sysclnC) and syscout() come in 

• two flavors: CP/M version 2.2 and CP/M version 1.4. 

• Comment out which ever you don't use. 

*/ 


syscout(c) char c; 

{ 

c pm ( 6 , c ) ; 
return(c) ; 

) 


/• CP/M 1.4 versions of syscstatC), syscin(), syscout() */ 

/• start comment out - 

fasm 

; bios(n.bc) 


call the n'th bios routine. 

be is put into the bc-register as a parameter, 
returns whatever bios puts into the a-reg. 


QZ BIOS: 




POP 

H 

;get return address 


POP 

B 

; be 


ed8. c 


September 8, 1981 page 

2 

POP 

D 

; n 


PUSH 

D 

;restore stack the way it was 


PUSH 

B 



PUSH 

H 



LHLD 

1 

;point hi at start of BIOS Jump 

table 

DCX 

H 



DCX 

H 



DCX 

H 



MOV 

A. E 

;put index into jump table into 

de 

ADD 

A 



ADD 

E 



M VI 

D.O 



MOV 

E, A 



DAD 

D 

;point hi at proper entry in jump table 

PUSH 

H 

;push call address 


LX I 

H.QZBIOS1 ;polnt hi at return address 


XTHL 


;push return address, get call 

address 

PCHL 


;call proper BIOS routine 


QZ BIOS 1: 




MOV 

L. A 

;put return code from BIOS into 

hi 

MV I 

H.O 



RET 


; go back to small-c 



lend asm 


sysc st a t() 
{ 


) 


if (bios(2,0 ):*255 ) { 
return(-1 ); 

) 

else { 

retur n(0 ); 

) 


syscin() 

{ 

return(bios(3,0)); 

) 


syscout(c) char c; 

{ 

bios(4 , c ); 
return(c) ; 

1 

--end comment out •/ 


/• CP/M 2.2 versions of syscstatC), syscln(), syscout() •/ 

/• return -1 if no character is ready from the console. 

• otherwise, return the character. 

•/ 

syscstat( ) 

{ 

return(cpm(6,-1)); 

) 

/• wait for next character from the console. 

• do not echo it. 

•/ 

syscin() 

( 

int c; 

while ((cscpm(6,-1 )) = s0) { 

) 

return(c); 

) 

/* print character on the console •/ 


/• print character on the printer •/ 

syslout(c) char c; 

{ 

cpm(5 . c ) ; 

return(c); 

) 


I asm 

; sysendC) 

; return address of last usable memory location. 


QZSYSEND: 
ed8. c 


LHLD 6 

DCX H 

RET 

lendasm 

/• open a file •/ 


September 8, 1981 

;get address of BD0S-1 
;return 


sysopen(name .mode) char ‘name, •node; 


page 3 


56 

46 


Dr. Dobb’s Journal, Number 63, January, 1982 







int file; 

if ((fi1e:fopen(name.node))**0) { 
ret urn(ERR); 

} 

else { 

return(file); 

) 

) 

/• close a file •/ 

sysclose(file) int file; 

{ 

/• fclose doesn’t reliably return OK •/ 
fclose(file); 
return(0K); 


/• read next char from file */ 

sysrdch(file) int file; 

{ 

int c; 

if ((csgetcCfile))**-1) { 
return(EOF); 

) 

else l 

return(c); 

) 

) 

/• write next char to file •/ 

syspshch(c,fi1e) char c; int file; 

( 

if (putc(c,file)**-1) { 

error("disk write failed"); 
return(ERR); 

) 

else { 

return(c); 

) 


/• read one char from END of file •/ 

syspopch(file) int file; 

{ 

error("syspopch() not implemented"); 
returnCE RR); 

) 

/• check file name for syntax •/ 
ed8.c September 8, 1981 


syschkfn(args) char *args; 

( 

return(OK); 

) 

/• copy file name from args to buffer •/ 
syscopfn(args,buffer) char 'args, ^buffer; 


nsO; 

while (n< SYSFNMAX-1) { 

if (args[n]*sEOS) { 
break; 

) 

else ( 

buffer[n]sargs[n]; 
n^ ♦; 

) 

) 

buffer[n]*E0S; 


/• move a block of n bytes down (towards HICH addresses). 

• block starts a source and the first byte goes to dest. 

• this routine is only called from bufmovdn() as follows 

• sysmovdn( nsto-from^l, deststo+length. sourcetto); 

•/ 


page A 


# asm 

QZSTSMOVDN: 

POP 

POP 

POP 

XTHL 

JMP 


H ;get return address 

B ;BC * source 

D ;DE * dest 

;HL : n, restore return address 
SYSM0VDN2 ;go enter loop 


; this code is 

15 

times 

faster than the c-code it 

replaces. 

SYSMOVDN 1: 





LDAX 

B 


;*dest-- r ^source-- 


STAX 

D 




DCX 

B 




DCX 

D 




DCX 

H 


;whi1e ((n—)>0) 


SYSMOVDN 2: 





MOV 

A , 

L 



ORA 

H 




JNZ 

SYSMOVDN 1 


XTHL 



;HL s return address 


PUSH 

H 


;restore stack 


PUSH 

H 




PUSH 

H 




RET 



;r etur n 


fend asm 





/• move a block 

of 

n bytes up (towards LOW addresses). 

• the block starts at 

source and the first byte 

goes to dest. 

• this routine 

i s 

called only from bufmovup() as 

follows: 

• sysmovup( 

ns to- 

from-fl, destsfrora-length. 

sources from): 

•/ 





edtt.c 


September d, 1981 

page 5 

f asm 





QZSYSMOVUP: 





POP 

H 


;get return address 


POP 

B 


;BC s source 


POP 

D 


;DE s dest 


XTHL 



;HL s n, save return address 

JMP 

SYSM0VUP2 ;go enter loop 


; this code is 

15 

times 

faster than the c-code it 

replaces. 

SYSM0VUP1: 





LDAX 

B 


;*dest^4 * 'source** 


STAX 

D 




IN X 

B 




IN X 

D 




DCX 

H 


;while ((n--)>0) 



SYSM0VUP2: 

MOV 


A , L 
H 

SYSM0VUP1 


;HL s return address 
jrestore stack 


May 11. 1981 


/• Screen editor: general utilities 

• 

• Source: ed9.c 

• Version: May 3, 1981. 

•/ 

/• convert lower case to upper case •/ 

toupper(c) int c; 

( 

if ((c<'a 1 )!(c> ’z' ) ) ( 
retur n(c ) ; 

) 

else ( 

return(c-32); 

) 

) 

/• convert upper case to lower case •/ 

tolower(c) int c; 

( 

if ((c<'A•)J(c>'Z•)) ( 
return(c); 

) 

else ( 

return(c-* 32); 

) 

) 

/• return: is first token in args a number ? •/ 
/• return value of number in *val •/ 

number(args,val) char *args; int *val; 


char c; 


cs*args*+; 


(Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 


57 

47 




Screen Oriented Editor 

(Listing continued, text begins on page 18) 

If ((c<'0')!(c>"5')) ( 
return(NO); 

} 

•valsc-'O'; 

while (c: , args++) { 

if ((c< '0 ' )!<c>'9')) { 
break; 

} 

*val=( # val # 10)-»c- , 0*; 

} 

return(YES); 

) 

/* convert character buffer to numeric ■/ 

ctoi(buf,index) char *buf; int index; 

{ 

int k ; 

while ( (buf[index]ss ' ') 

(buf[index] s=TAB) ) { 
index**; 

} 

k = 0; 

while ( (buf[index]>='0')4(buf[index]<='9') ) { 
k=(k*10)*buf[index]-’0•; 

ed 9 .c May 11, 1981 page 2 


return(k); 


str[i + *]s(absvalj10)*'O’ ; 
May 11, 1981 

ab sv al = ab sv al / 1 0 ; 
if (absval:=0) { 
break; 

} 

} 

/• generate sign •/ 
if ((i<size)4(n<0)) ( 
strCi**]:'-'; 

} 

1 e n = i - 1 ; 

/• reverse sign, digits */ 
i--; 
j = 0; 

while (j<i) { 

ksstr[i ]; 
str[i]sstr[j ] ; 
str[j] =k ; 
i - - ; 


return( len) ; 


/• return absolute value of n •/ 

abs(n) int n; 

{ 

if (n<0) { 

return(-n); 

} 

else ( 

return(n ) ; 

} 


/• return maximum of m,n * / 

max(m,n) int m,n; 

( 

if (m> = n) { 

return(m); 

} 

else { 

return(n); 

} 


/* return minimum of m,n •/ 

min(m.n) int m,n; 

{ 

if (m< = n) { 

return(m); 

} 

else { 

return(n) ; 

} 


/• put decimal integer n in field width >= w. 
* left justify the number in the field. 

•/ 

putdec(n ,w) int n,w ; 

l 

char chars[10]; 
int i ,nd; 

nd=itoc(n,chars,10); 
i = 0; 

while ( i <nd) { 

syscout(chars[i** ]); 

} 

i = nd; 

while (i**<w) { 

syscout(' ' ); 

} 


/* convert integer n to character string in str */ 

itoc(n,str,size) int n; char # str; int size; 

{ 

int absval; 
int len; 
int i, j,k; 

absval = abs(n); 

/• generate digits •/ 
str[0 ] = 0 ; 
i = 1 ; 

while (i<size) ( 


/* system error routine •/ 

syserr(s) char *s; 

{ 

pmtmess("system error: ",s); 


/• user error routine •/ 

error (s) char • s ; 

{ 

pmtmess("error: ",s); 

) 

/• disk error routine •/ 

diskerr(s) char # s; 

{ 

pmtmess("disk error: ",s); 

} 

/• read the next line of the file into 

• the buffer of size n that p points to. 

• Successive calls to readline() read the file 

• from front to back. 

•/ 

«d9.c May 11, 1981 page 4 

read1ine(fi1e,p,n) int file; char *p; int n; 

int c; 
int k; 

k = 0; 

while (1) { 

c = sysrdch(file); 
if (c==ERR) { 

return(ERR); 

“} 

if (c = = EOF) { 

/• ignore line without CR •/ 
return (EOF); 

) 

if (c==CR) { 

return(k); 

} 

if (k<n) ( 

/• move char to buffer •/ 

*p++sc; 

} 

/• always bump count */ 
k + *; 


/• push (same as write) line to end of file. 


58 


Dr. Dobb’s Journal, Number 63, January, 1982 


• line is in the buffer of size n that p points to. 

• lines written by this routine may be read by 
B either readline() or popline(). 

•/ 

pushline(fi1e , p , n) int file; char *p; int n; 

{ 

/• write all but trailing CR •/ 
while (( n — ) >0 ) { 

if (syspshch(*p + ♦,file)s=ERR) { 
return(ERR ); 

} 

} 

/• write trailing CR •/ 
return(syspshch(CR.file) ); 

} 

/• pop a line from the back of the file. 

• the line should have been pushed using pushlineC). 

•/ 

popline(fi1e,p t n) int file; char *p; int n; 

( 

int c; 

int k, km ax, t; 

/• first char must be CR •/ 
c = syspopch(file) ; 
if (c = = EOF) { 

/• at START of file •/ 
return(EOF); 

} 

if (c = = CR) { 

/• put into buffer •/ 

•p*4. = CR ; 
k = 1 ; 

ed9.c May 11, 1981 page 5 

} 

else { 

syserr("popline; missing CR"); 
return(ERR) ; 

) 

/• pop line into buffer in reverse order •/ 
while (1) { 

c=syspopch(file); 
if ( c = = E R R ) { 

return(ERR ) ; 

) 

if (c = = EOF) { 

break; 

) 

if (cssCR) { 

/• this ends ANOTHER line •/ 
/• push it back •/ 

if (syspshch(CR,file)==ERR) { 
return(ERR); 

) 

break; 

) 

/• non-special case •/ 
if (k<n) { 

/• put into buffer •/ 

•p**sc; 

} 

/• always bump count •/ 
k+ ♦; 

) 

/• remember if we truncated the line •/ 
kraaxsk ; 

/• reverse the buffer •/ 
k=min(k,n-1); 
t = 0; 

while (k>t) { 

/• swap p[t], p[k] •/ 
c=p[k]; 
p[k]=p[t]; 
p[t]sc; 
k —; 
t ♦♦; 

) 

return(kmax); 

} 

edIO.c May 11, 1931 page 1 

/* Screen editor: buffer module 

« 

• Source: edIO.c 

• Version: April 7, 1931. 

•/ 

/* Define the variables global to this module. 

• Buffer must be declared after all other variables 


* of the entire program. 

* Note: buffer must have nonzero dimension. 

•/ 

int bufcflag; /■ main buffer changed flag •/ 

char *bufp; /• start of current line */ 

char *bufpmax; /• end of last line •/ 

char *bufend; /* last byte of buffer */ 

int bufline; /* current line number •/ 

int bufmaxln; /• number of lines in buffer •/ 

char buffer[1]; /* start of buffer •/ 

/• This code is built around several invariant 

* assumptions: 

* First, the last line is always completely empty. 

* When bufp points to the last line there is NO 

* CR following it. 

* Second, bufp points to the last line if and only if 

* buf1ine = = bufmax In* 1 . 

* Third, bufline is always greater than zero. 

* Line zero exists only to make scanning for the 

* start of line one easier. 

*/ 


/• Clear the main buffer •/ 

bufnew() 

{ 

/• point past line 0 •/ 
bufp=bufpmax = buffer+1 ; 

/* point at last byte of buffer •/ 

/ • allow space for stack ■/ 
bufend = sysend( ) — 1000; 

/• at line one. no lines in buffer •/ 
buf1 i n e = 1 ; 
bufmaxln=0; 

/• line zero is always a null line •/ 
buffer[0 ]=CR ; 

/* indicate no need to save file yet •/ 
bufcflagsNO; 


/* return current line number •/ 

bufln( ) 

{ 

return(bufline) ; 

} 

/• return YES if the buffer (i.e., file) has been 
* changed since the last time the file was saved. 

•/ 

edIO.c May 11, 1931 page 2 

buf chng() 
l 

return(bufc f1ag); 

} 

/• the file has been saved. clear bufcflag. */ 

bufsaved( ) 

{ 

bufcflagsNO; 

1 

/• return number of bytes left in the buffer */ 

buf free() 

{ 

return(bufend-bufp); 

) 

/• Position buffer pointers to start of indicated line •/ 

bufgo(line) int line; 

{ 

/* put request into range, prevent extension •/ 
linesminCbufmaxln+l.line); 
linesmax(1.line); 

/• already at proper line? return. •/ 
if (1ines = buf1 ine) { 

return(OK); 

} 

/• move through buffer one line at a time */ 
while (1ine<buf1ine) { 

if (bufup( )s=ERR) { 

return(EH R ) ; 

} 

} 

while (1 ine>buf1ine) { 

if (bufdn()s=ERR) { 

return ( err ); (Continued on next page) 


Dr. Dobb’s Journal, Number 63, January, 1982 


59 

49 





Screen Oriented Editor 

(Listing continued, text begins on page 18) 

} 

\ 

/* we have reached the line we wanted » / 
retur n(OK); 

} 

/* move one line closer to front of buffer, i.e., 

* set buffer pointers to start of previous line. 

• / 

bufup( ) 

{ 

char "oldbufp; 

oldbuf p = bufp; 

/* can't move past line 1 */ 
if (bufattopC)) { 

return(OK ) ; 

} 

/* move past CR of previous line •/ 
if ("--bufp!= CR) l 

syserr("bufup: missing CR"); 
bufp = oldbuf p; 
return(E RR ) ; 

edio.c Hay 11, 1981 pafe 3 

1 

/* move to start of previous line */ 
while (*--bufp!=CK) f 

) 

b u f p + ♦ ; 

/* make sure we haven't gone too far */ 
if (bufp<(buffcr+1 ) ) { 

syserr("bufup: bufp underflow"); 

bufp=oldbufp; 

return(ERR) ; 

} 

/* success! we ARE at previous line */ 
bufline--; 
return(OK); 

} 

/* Move one line closer to end of buffer, i.e., 

* set buffer pointers to start of next line. 

»/ 

bufdn( ) 

{ 

char "oldbufp; 

oldbuf p = bufp ; 

/* do nothing silly if at end of buffer */ 
if (buf atbot( ) ) { 

return(OK) ; 

} 

/* scan past current line and CR »/ 
while (*bufp + +I sCR ) { 

} 

/* make sure we haven't gone too far */ 
if (bufp>bufpmax ) ( 

syserr("bufdn: bufp overflow"); 

bufp=oldbufp; 

return(ERR) ; 

} 

/* success! we are at next line */ 
buf1ine++; 
return(OK) ; 

} 

/* Insert a line before the current line. 

* p points to a line of length n to be inserted. 

* Note: n does not include trailing CR. 

*/ 

bufins(p,n) char * p; int n; 

l 

int k; 

/* make room in the buffer for the lino */ 
if (bufext(n+1) = = ERR ) { 
return(ERR) ; 

} 

/ " put the line and CR into the buffer */ 
k = 0; 

while (k<n) { 

*(bufp + k) = *(p + k) ; 
k + ♦; 

} 


edio.c May 11, 1931 page 4 

*(bufp+k)=CR; 

/* increase number of lines in buffer »/ 
bufmaxln++; 

/* special case: inserting a null line at 

* end of file is not a significant change. 

*/ 

if ((n = =0 ) h (bufnrbot())) { 

1 

else { 

bufcflag=YES; 

} 

return(OK); 

} 

/* delete the current line */ 

buf d e1() 

( 

return(bufdeln(1)); 

} 

/* delete n lines, starting with the current line »/ 

bufdeln(n) int n; 

{ 

int oldline; 
int k ; 

char "oldbufp; 

/• remember current buffer parameters »/ 

oldline=bufline; 

oldbufp = bufp ; 

/" scan for first line after deleted lines »/ 
k = 0 ; 

while ((n— ) > 0) { 

if (bufatbot( ) ) { 
break ; 

} 

if (bufdnC ) = =ERR) { 

bufline = oldline ; 
oldbuf p = bufp; 
return(ERR) ; 

} 

k ♦ ♦ ; 

) 

/* compress buffer. update pointers »/ 

bufmovup(bufp,bufpmax-1,bufp-oldbufp); 

bufpmax=bufpmax-(bufp-oldbufp); 

bufp=oldbufp; 

bufline=oldline; 

buftnaxln = bufmaxln-k ; 

bufcflag = YES ; 

return!OK ) ; 

) 

/* replace current line with the line that 
* p points to. The new line is of length n. 

»/ 

bufrepl(p.n) char *p; int n; 

{ 

int old len , k ; 

edio.c May 11, 198 T page 5 

char "nextp; 

/* do not replace null line. just insert */ 
if (bufatbot!)) { 

return(bufins(p,n)); 

} 

/" point nextp at start of next line */ 
if (bufdn()==ERR) { 

return(ERR); 

} 

nextp=bufp; 
if (bufup()==ERR) { 

return(ERR); 

1 

/* allow for CR at end */ 
n = n + 1 ; 

/" see how to move buffer below us; 

* up, down, or not at all. 

»/ 

oldlenrnextp-bufp; 
if (oldlen<n) { 

/* move buffer down "/ 
if (bufext(n-old1en)==ERR) ( 
return(ERR); 

} 

bufpmax=bufpmax+n-oldlen; 

1 

else if (oldlen>n) { 


60 


Dr. Dobb’s Journal, Number 63, January, 1982 



/* move buffer up •/ 
bufmovup(nextp,bufpmax-1,oldlen-n) ; 
bufpmaxsbufpmax-(oldlen-n) ; 

} 

/• put new line in the hole we just made •/ 
k = 0; 

while (k<(n- 1 ) ) { 

buf p[k] = p[k ] ; 
k* ♦ ; 

} 

buf p[k]=CR ; 
bufc flag = YES; 
return(OK ) ; 

} 

/* copy current line into buffer that p points to. 

* the maximum size of that buffer is n. 

* return kslength of line in the main buffer. 

* if k>n then truncate n-k characters and only 

* return n characters in the caller's buffer. 

»/ 

bufgotln(p.n) char # p; int n; 

{ 

int k ; 

/* last line is always null • / 
if (bufatbotO) { 
return(O) ; 

) 

/ * copy line as long as it not too long • / 
k = 0 ; 

while (k<n) { 

if (*(bufp + k) = sCR ) 1 
return(k) ; 

} 

edIO.c May 11,1931 p a g e 6 

•(p + k)s•(bu f p*k ); 
k + ♦; 

} 

/* count length but move no more chars •/ 
while (*(bufp + k) ! sCR ) { 
k* ♦; 

} 

return(k ) ; 


/• move buffer down (towards HIGH addresses) •/ 

bufmovdn(from , to , 1 ength) char •from, *to; int length; 

{ 

/ * this code needs to be very fast. 

• use an assembly language routine. 

•/ 

sysmovdn(to-from*1,to*length,to); 

) 

/• the call to sysmovdnO is equivalent to the following code; 

int k; 

k = to-f ronu 1 ; 
while ((k-- ) >0 ) { 

•(to*length)=*to; 
to--; 

) 


/• move buffer up (towards LOW addresses) •/ 

bufmovup(from,to,length) char •from, *to; int length; 

{ 

/• this code must be very fast. 

• use an assembly language routine. 

•/ 

sysmovuptto-from^l.from-length, from); 

I 

/• the call to sysmovup() is equivalent to the following code: 
int k; 

k = to-f rom +1 ; 
while ((k— ) >0 ) { 

•(from-length)= # from; 
from**; 

) 


/• return true if at bottom of buffer. 

• NOTE 1: the last line of the buffer is always null. 

* NOTE 2: the last line number is always bufmaxln+1. 

*/ 


bufatbot() 

l 

return(bufline>bufmaxln) ; 

) 


edIO.c May 11. 1981 page 7 

/• return true if at bottom or at the la3t 

• real line before the bottom. 

•/ 

bufnrbot( ) 

( 

return(bufline> = bufmaxln) ; 

) 

/• return true if at top of buffer */ 

buf atto p() 

{ 

return(bufline==1); 

} 

/• put nlines lines from buffer starting with 

• line topline at position topy of the screen. 

•/ 

bufout(topiine,topy , n1ines) int topline, topy, nlines; 

l 

int 1,p ; 

/• remember buffer's state •/ 

Is buf1ine ; 
p = buf p ; 

/• write out one line at a time •/ 
while ((nlines--)>0) { 

outxy(0.topy++)S 

bufoutln(topline*0; 

\ 

/• restore buffer's state •/ 
buf1inesl; 
buf p = p; 

1 

/• print line of main buffer on screen •/ 

bufoutln( 1 ine) int line; 

{ 

/• error message does NOT go on prompt line •/ 
if (bufgo(line)==ERR) ( 

fmtsout("di sk error; line deleted" , 0 ) ; 
outdeol( ) ; 
return ; 

} 

/• blank out lines below last line of buffer •/ 
if (bufatbot( ) ) { 
outdeol( ); 

) 

/• write one formatted line out •/ 
else { 

fmtsout(bufp,0); 
outdeol( ) ; 

) 

) 

/• simple memory version of bufext. 

• create a hole in buffer at current line. 

• length is the size of the hole. 

•/ 


edIO.c May 11, 1981 page 3 

bufext(length) int length; 

( 

/• make sure there is room for more •/ 
if ((bufpm ax♦1 ength)> = bufend ) { 

error("main buffer is full"); 
return(ERR) ; 

} 

/• move lines below current line down •/ 
bufmovdn(bufp,bufpmax-1,length); 
buf pmax = bufpmax*length; 
return(OK) ; 

) 


End Listing 


Dr. Dobb’s Journal, Number 63, January, 1982 


61 

51 







For Users of Small Computer 

Number 64 February 1982 Volume 7, Issue 2 


52 50 

■ ($3.00 in Canada) 

OBB’S lOURNAL 

mputer Systems y 



Excuse Me, What Time Is It? 

Alan Bomberger 


Background Information on Text Editors 

Leonard K. Nicholson 

Includes Special FORTH Section: 

FORTH 8086 Assembler 

Ray Duncan 

Formal Definition of FORTH 
As a Programming Language 

C.H. Ting 

Recursion in FORTH 

Glyn Emery 

and much more inside 


When (and How) 
to Use 

Interrupts ... 

... a Look at 
Standard 
Measures ... 

... and more 
on FORTH! 











Dr. Dobbs Iournal 

For Users of Small Computer Systems W 


February 1982 Volume 7, Issue 2, Number 64 

CONTENTS 


Recursion in FORTH. 12 

by Glyn Emery 

FORTH 8086 Assembler. 14 

by Ray Duncan 

Formal Definition of FORTH 

As a Programming Language. 19 

by C. H. Ting 

Excuse Me, What Time Is It?.50 

by Alan Bamberger 

Background Information on Text Editors.55 

by Leonard K. Nicholson 

Standards for Computerized 

Scientific Measurement.57 

by Douglas Crockford 


Letters. 6 Book Reviews 

Of Interest. 8 

Software Review . . 59 



© 1981 by People’s Computer Company unless otherwise noted on 
specific articles. All rights reserved. 


Dr. Dobb's Journal (USPS 307690) is published twelve times per year by People’s Computer Company, Box E, 1263 El Camino Real, Menlo 
Park, CA 9402 5. Second class postage paid at Menlo Park, California 94025 and additional entry points. Address correction requested. Post¬ 
master: send form 3579 to Box E, Menlo Park, California 94025. 


EDITORIAL 


Blue-sky thinking, the kind that opens the mind to 
new levels of possibility, brings with it many challenges. 
First, the imagination must break out of old patterns into 
unexplored territory. It must defeat the same critical self- 
consciousness which makes us feel embarrassed by our little 
non-conformities. 

Next the mind itself is dared to entertain concepts 
which don’t fit its preconceptions. This is where most blue- 
sky thinking gets doused with a strong dose of skepticism 
before it even has a shot at justifying itself. Knee-jerk cen¬ 
sorship discards any notion not bearing a societal/peer/ 
professional seal of approval — which, of course, any truly 
new idea cannot have obtained. 

If some wonderfully chancy, ground-shaking, 
dimension-bursting thought makes it past all these rigid 
internal mechanisms of too-linear thinking, then it must 
pass a still greater challenge, that of finding even a small 
audience which will ponder it without haste or snickers. 
This is the last burial ground for blue-sky inspirations, here 


they die in the presence of those who have undertaken to 
preserve the technological state-as-it-is. 

I believe that the unexplored territories of technology 
have not been diminished by the microcomputing revolu¬ 
tion; rather, new frontiers are open to us. We are still sod- 
hut dwellers under the open sky, albeit connected by net¬ 
works and terminals, by mutual interests in system tools, 
language development, and by the immensely powerful 
concept of personal computing. How will we nurture these 
things, and how will we use them to transform ourselves? 

The only things hampering even greater progress than 
we have seen thus far, are found within our own creative 
processes and in the way we accept strange new worlds 
of thought when they impinge (too rarely) on our con¬ 
sciousness from without. DDJ will provide the forum for 
those who unleash their visions; ours is a company which 
began publishing personal computing periodicals before per¬ 
sonal computers existed, before most people would seri¬ 
ously consider the idea. The stage is set. . . the sky’s the 
limit! - MDO 


Subscription Rates: $25 per year within the United States; $40 for 
first class to Canada and Mexico; $58 for airmail to other countries. 
Payment must be in U.S. Dollars, drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be typed, double-spaced on 
white paper. Listings should be produced by the computer, using a 
fresh, dark ribbon on continuous white paper. Please avoid printing 
on perforations. Payment is in contributor’s copies. Requests to re¬ 
view galleys must accompany the manuscript when it is first sub¬ 
mitted. Authors may receive a copy of the complete writer’s guide¬ 
lines by sending a self-addressed, stamped envelope. 

Donating Subscribers Contributing Subscriber: $so/year ($25 
tax deductible). Retaining Subscriber: $75/year ($50 tax deduc¬ 
tible). Sustaining Subscriber: $100/year ($75 tax deductible). Life¬ 
time Subscriber: $1000 ($800 tax deductible). Corporate Subscriber: 
$500/year ($400 tax deductible, receives Jive one-year subscriptions). 


Contributing Subscribers: Eric H. Johnson, Jerry Horn, Edward W. 
Carr, Steven Fisher, Thomas H. Grohne, G. V. Elkins, Robert M. 
Connors, William J. McEown, Robert C. Luckey, Kim Leary, Robert 
N. Stabler, DeWitt S. Brown, John B. Palmer, E. Glion Curtis, Jack 
Miller, Burks A. Smith, Transdata Corporation, Mark Ketter, John 
W. Campbell, Friden Mailing Equipment, Howard E. Decker, Jim 
Wilson, Frank Lawyer, Chris Pettus. Retaining Subscribers: Osamu 
Shimizu, Scott B. Guthery, Robert L. Edens, Titus Purdin, Steven 
Fisher Enterprises. Sustaining Subscribers: Gordon Eubanks, Jr. and 
Pete Roberts. Lifetime Subscriber: Michael S. Zick. 

Foreign Distributors UK A Europe: LP Enterprises, 8/11 Cam¬ 
bridge House, Cambridge Road, Barking, Essex, 1G11 8NT, England 
(Tel. 01-591-6511, TLX 892395). Hofacker-Verlag, Tegemseer 
Strass 18, D-8150 Holzkirchen, West Germany. Asia A Australia: 
Computer Store, POB 31-261, 22B Milford Road, Milford, Auckland 
9, New Zealand. ASCII Publishing Co., Ltd., Aoyama Building 5F, 
5-16-1 Minami Aoyama, Minato-ku, Tokyo 107, Japan. 


Dr. Dobb’s Journal, Number 64, February 1982 

14" 


3 














LETTERS 


Epson Salts 

To the Good Doctor: 

I would like to point out that co- 
trary to Alan Boinberger’s article on 
“MX-80 to NorthStar Connections” 
(DDJ #35), 1 have found that directly 
making the connections to the NorthStar 
output port works perfectly. 

The details: 

1) The key point here is the duration of 
the output strobe pulse (active LO) that 
is made available by the NorthStar 
motherboard at the parallel port control 
header. A close look at the circuit dia¬ 
grams shows that the pulse in question is 
between 1.5 and 2 “T” states long. At 
4 MHz this works out to be between 
0.375 and 0.5 micro-seconds. Well the ol’ 
MX indeed requires 0.5 /us minimum thus 
we can’t guarantee it! But guess what? It 
works flawlessly anyway. 

2) Connect pin 4 to pin 12 on the port 
header; this directs our slightly fast strobe 
pulse to pin 8 of the output port connec¬ 
tor on the back panel. This goes to pin 1 
on the Epson. 

3) Connect pin 3 to pin 13 on the header; 
this makes pin 7 on the output port con¬ 
nector the input line for the acknowledge 
from the MX (active LO). Connect pin 7 
to pin 10 on the MX. This completes the 
handshaking signals. 

4) Connect the 8 data lines and ground. I 
used ribbon cable without any twisted 
pairs of ground and data, and there is no 
data loss problem, though if the distance 
exceeded 10 feet or the environment was 
particulary noisy the twisted pairs might 
become necessary. 

5) The ultra-simple input code as given in 
the NorthStar manual is all it takes to get 
that printer buzzing. A cash register print¬ 
out tape will never sound the same! 

With all respect to Alan, the output 
pulse is on the short side but for all 
those NorthStar users trying to make the 
connection to the Epson MX printer: the 
direct connection has not missed a bit in 
hundreds of listings. 

A footnote to the NorthStar manual 
on the subject of port addresses. There 
are numerous references to IN 6 and OUT 
6 as the appropriate instructions to access 
the motherboard status byte and control 
byte respectively. Please note that the 
port number instead of reading 6, should 
read 6 + port base. Long were the hours 1 
couldn’t get some simple code running 
when following their instructions because 
I had changed my port base address to 


accommodate some other board’s hard¬ 
wired port addressing and IN 6 or OUT 6 
were connected to bizarre and unpredict¬ 
able data. 

Print On, 

William Smith 
P. O. Box 497 
Valley Ford, CA 94972 

MARCH Hare . . . 

Dear Mr. Ouverson: 

Here is clear proof of the soundness 
of your policy of requesting actual list¬ 
ings of programs. I had lots of excuses for 
not making one for my MARCH program 
(DDJ #62), but I’m sure we will all be 
sorry now. Line 12 of the program is 
missing. It should be RNZ ; return if 
the pattern is incorrect. 

Otherwise the article looks as nice as 
the rest of the magazine, and I’m very 
proud to be a part of it. Thank you very 
much. Keep up the good work, and stick 
to that policy. 

Regretfully, 

James Laurino 

414 South 47th Street 

Philadelphia, PA 19143 

Small-C Notes, Bug Fix 

Dear Marlin, 

Thank you for your kind words and 
your enthusiasm for my work with small- 
c. As time permits, I would like to con¬ 
tinue writing for DDJ. 

The answer to your question about 
the effect of my changes to the small-c 
expression analyzer is that some existing 
programs may need changing slightly. In 
such cases, however, the original code 
would be improperly written and would 
not work if compiled with another com- 
iler. No doubt some users of small-c have 
discovered that when the compiler fails to 
double a value added to an integer array 
name, for instance, they can force the de¬ 
sired result by explicitly doubling the 
value in the program itself. Such code will 
not operate properly after the change. 

I did encounter one situation, how¬ 
ever, where a program adjustment avoid¬ 
ed trouble with the old expression ana¬ 
lyzer and also worked with the new one. 
The expression (*intptr-l) would sub¬ 
tract 2 from the integer pointed to by 
intptr. The problem went away by writ¬ 
ing (-1 + *intptr) instead. That is when I 
knew the binary plus and minus operators 
were not being handled symmetrically. 
Ironically, one analyzer bug (asym¬ 


metry) corrected the error of another 
(after applying the asterisk operator to 
intptr the result should no longer have ap¬ 
peared to be a pointer). 

Since writing my article (DDJ # 62) 
about the expression analyzer, I dis¬ 
covered one more change that was need¬ 
ed. Line 387 of the listing should read: 

387 lval[ 01 = Ival [ 2 ] =0; 

Sincerely, 

J. E. Hendrix 
Rt. 1, Box 74-B-l 
Oxford, MS 38655 


La Triviata (sic) 

Dear People: 

Once, long ago, 1 won some Latin 
contests in the state of Illinois. I never 
thought I’d have to use that knowledge 
again, but: 

There is no such thing as HOMO- 
SAP1EN (Nicol, R. L., “Actors, Property 
Lists, and LISP,” DDJ #62, p. 15). 
“Homo sapiens” is the scientific name of 
mankind. It means “wise man” (singular). 
“Wise men” would be “homines sapi- 
entes.” 

(A related “astounding fact” is that 
there is no such thing as a suburb, ety¬ 
mologically. The area near a city is its 
“suburbs” — singular. The areas (plural) 
near two cities (plural) are their “sub- 
urbes” (plural — three syllables, and the 
the last one pronounced “bees”). The 
city itself is the “urbs,” and cities, plural, 
are “urbes.”) 

Sincerely, 

W. D. Maurer, Professor 

George Washington University 

S. E. A. S. 

Washington, DC 20052 

Reclaim to Fame? 

Dear Marlin, 

I received your letter about the pro¬ 
posed new Small-C issue and am hoping 
to contribute something before your 
deadline. I have also contacted other 
people and some interest has been gener¬ 
ated. 

I have something that may be of use, 
and give your readers a useful program. 

There have been several disk test¬ 
ing routines launched onto the market 
over the last few years. One of the first, 
and potentially most useful is RECLAIM 


6 


Dr. Dobb’s Journal, Number 64, February 1982 

IF 




published by Lifeboat Associates. How¬ 
ever, it was flawed by not working on all 
systems. In my case it was a Morrow 
Discus 2D. Through dissassembly I found 
the reason: the program makes direct 
calls on the BIOS when doing the actual 
testing of the disk surface. It makes the 
assumption that the zero flag is set on a 
return from read or write to indicate suc¬ 
cess. This is not so in all cases for the 
Morrow Chios and others, I believe. The 
CP/M documentation confirms that no 
flag settings are used by Bios to indicate 
success — only that A is 0 for success, 
1 otherwise. 

I confirmed this by inserting a ORA 
A instruction immediately after the direct 
Bios read and write calls and having a suc¬ 
cessful run. It can also be fixed by the 
same patch in the Bios for those who do 
not wish to patch the program directly. 

Another important point with disk 
testing routines is the built-in re-try 
count in the Bios. Re-tries may be great 
when trying to recover valuable data, but 
they can hide all the flaky sectors on the 
disk. I typically change this to 2 with the 
debugger, instead of the usual 10 before 
any testing. A good system seldom does a 
re-try anyway — I have used the system 
like this for hours with no bad sector er¬ 
rors. 

I hope you find some use in this 
letter and hope to see more of your 
magazine soon. 

Yours faithfully, 

Angus S. Bliss 
P. O. Box 293 
Hamilton 2303 
Australia 


In Search Of . . . 

Dear Sir: 

I am looking for a “Tiny Basic” for 
use with the Signetics 2650 cpu. As a 
relative newcomer to small computers, I 
have not had any luck in finding the 
material I need to prepare a program for 
this obscure but quite workable cpu. 

A study of one of your compendi- 
ums of early Dr. Dobb’s Journals indi¬ 
cates that a number of people were con¬ 
tributing articles on Tiny Basic for the 
8080, and that you were calling for con¬ 
tributions for other microprocessors. Did 
anyone ever do anything with the 2650? 
If so, I would appreciate your help in be¬ 
ing guided to the source of this material. 


I have been examining Li-Chen 
Wang’s Palo Alto Tiny Basic, which ap¬ 
peared in your May 1976 issue, with the 
idea of converting it over to 2650 lan¬ 
guage. This appears to be a formidable 
task, especially for a neophyte. Because 
of this, I would be happy to hear from 
you any comments on this matter. I 
would also be happy to correspond with 
any of your readers who are knowledg- 
able on the 2650. 

Thank you for your attention. 
Sincerely, 

George A. Luce 
2907 Greenlawn Pkwy. 
Austin, TX 78757 

*»J 


Dr. Dobb’s Journal, Number 64, February 1982 
"56" 


7 



OF INTEREST 


by D. E. Cortesi 


April Showers .. . 

Another batch of show announce¬ 
ments turned up this month, enough to 
fill all the empty spaces in your spring 
calendar. The second annual Eighty/ 
Apple show, a show for TRS-80 and 
Apple users, will take place in New York 
on April 2-4. Contact Kengore for de¬ 
tails. 

The National Computer Shows or¬ 
ganization will stage expositions of com¬ 
puters and office equipment at three sites 
this spring: Dallas, TX April IS-18, the 
Nassau Coliseum on Long Island April 
22-25, and in Los Angeles, CA, May 6-9. 

John Craig’s Computer Swap Ameri¬ 
ca, after a February 6 swap meet in Costa 
Mesa, CA that will probably be over when 
you see this, will return to San Jose, CA 
on April 24th. Craig is prepared to offer 
the use of his trademark and a complete 
promotion package to “qualified indi¬ 
viduals or organizations” that want to put 
on their own swap meets. 

.. . and a November Show 

The California Educational Comput¬ 
ing Consortium (whew!) will hold their 
sixth annual conference in San Diego, CA 
on November 18-19. There is still time to 
submit a paper dealing with computers 
and applications of interest to college- 
level educators; send a draft by March 1 
to Professor Frances Grant. 

Radio Shack Info 

Registered TRS-80 users receive 
Tandy’s newsletter, TRS-80 News. The 
first 20 issues of that paper, through the 
December 1980 number, have been re¬ 
printed in a $5 paperback that may be 
found at Radio Shack dealers. 

There are other sources of TRS-80 
information. Kengore has started the 
Eighty System Newsletter, a weekly for 
“users, retailers, distributors, or manu¬ 
facturers of TRS-80 related products.” 
Each issue is said to contain both late 
news of “the TRS-80 industry” and a 
bibliography of related articles from 
“over 100” other publications. An annual 
subscription is $39. 

Soft Wares 

The Software Toolworks has updated 
its C/80 compiler (originally based, we 
believe, on Cain’s Small-C). The latest 
version generates assembly source that is 
compatible with both the standard ASM 
assembler and with Microsoft’s Macro-80 


relocatable assembler. An execution pro¬ 
file facility — a means of mapping the fre¬ 
quency of use of each program statement, 
and a priceless development tool - has 
been added to the runtime library. The 
package is an outstanding buy at $40 
plus shipping; present owners can have an 
update for $ 10. 

Scientists, engineers, and educators 
who use Apple Pascal should look into 
the DIFF E-Q package from Sage Soft¬ 
ware. It’s basically a set of programs for 
solving differential equations up to the 
24th order, but it also contains high- 
resolution graphics operations for display¬ 
ing families of curves. That, the makers 
claim, makes it “ideal for lecture demon¬ 
strations.” 

High-resolution plots in another 
medium can be had with AccuChart from 
Datagraph. This CP/M program writes 
graphs, bar charts, and pie charts using a 
Diablo (-compatible) daisy printer. The 
data to be plotted may be entered from 
the keyboard or taken from a disk file. 
The price is $295. 

Miken Optical have implemented an 
unusual idea for CP/M - an interactive 
BIOS. IBIOS apparently adds a rudimen¬ 
tary command interpreter to the BIOS, 
upstream of the rest of the system. With 
it in place, you can perform some useful 
functions at any time, regardless of 
what’s going in the transient program 
area. The $60 program is distributed as 
8080 source, and must be customized to 
your system. 

Harder Wares 

The AIM, that endlessly-useful little 
machine, is the base for two new hard¬ 
ware products. One, from Columbus In¬ 
struments, is a board that carries sixteen 
channels of 12-bit analog-to-digital con¬ 
version, a clock-calendar, and four “uni¬ 
versal” memory sockets. An AIM so 
equipped, they say, is a complete system 
for laboratory data acquisition and log¬ 
ging. The A/D conversion channels oper¬ 
ate in 25 microseconds; the clock has bat¬ 
tery backup; and when equipped with 
2764 or equivalent chips, the board pro¬ 
vides 32K bytes. The full board costs 
$1270 (ouch) but the A/D and clock can 
be left off to reduce the price. 

The second AIM add-on is an SS-50 
bus from Percom. The AIM’s expansion 
pins plug into an interface board from 
which extends an SS-50 bus motherboard. 
With it, according to the release, users 
“can add disk storage, a CRT, and other 


. . . System-50 modules available from 
several vendors.” The board costs $90. 

Comdex Extravaganza 

To judge from the press release pile, 
everyone and his dog announced some¬ 
thing at the Comdex show. Here is a sam¬ 
pler of the more interesting ones. 

Tecmar was the first to come out 
with add-ons for the IBM Personal Com¬ 
puter: hard disk, clock-calendar, voice 
output, BSR X10 driver, IEEE 488 driv¬ 
er, A/D and D/A converters, etc. Oh, and 
an expansion chassis to plug them all into 
(An expansion chassis? This is where we 
came in!). 

Alspa Computer used the new, skin¬ 
ny, 8-inch drives to squeeze a two-drive, 
64K, Z80 system into a unit rather small¬ 
er than a breadbox (about 6 x 9 x 17 
inches), with an attractive $3000 price- 
tag. 

Dynabyte’s newest unit is a little 
larger, but it claims to support up to eight 
concurrent MP/M or Oasis users at just 
over $1000 per user. Their model 5505 
contains a 16MB, 5-inch hard disk, a 
1MB 5-inch diskette drive for backup, 
and “400K bytes” of RAM. 

Did Dynabyte’s 5505 frighten Altos? 
For whatever reason, the latter company 
announced price reductions of about 
$1000 on their 8000-2 and 8000-15 
models. 

Well, both those companies had 
better check out CompuThink’s Hawk-32 
model, a multi-user system with a 5-inch 
hard disk and a 68000 CPU, to be sold 
for “under $10,000.” This system runs 
yet another UNIX look-alike operating 
system. 

Net Works 

A press release from Stanford Univer¬ 
sity passes on Nobel laureate Joshua 
Lederberg’s praise for computerized text 
systems. Stanford is extensively wired, 
with terminals in most buildings and 
several related time-sharing services in 
operation. Lederberg notes the usual ad¬ 
vantage of word processing (“You are 
really in close touch with your literary 
product .... You can go through an in¬ 
definite number of drafts .. .”) but finds 
equal or greater value in the bulletin- 
board style of communication. “We 
found that internal communication on 
the Stanford campus, separated by not 
more than a few hundred yards, was in 
fact greatly facilitated by handling a great 
deal of our discourse over the wire. It 


8 


Dr. Dobb’s Journal, Number 64, February 1982 

"57 





Dr. Dobb’s Journal, Number 64, February 1982 


ended up we did 95 percent of our com¬ 
munications, . . . the elaboration of ideas, 
getting criticisms about proposals, over 
the wire rather than the telephone. Rare¬ 
ly did we ever do a written communica¬ 
tion.” 

“Terminals of this kind and their 
searching capabilities are going to give 
one access to the libraries of the world,” 
Lederberg said, but he wants more: “You 
should be able to write marginal notes on 


the stuff you have read, looked at, and 
wish to criticize. Since you can do this 
nondestructive^, you can be helpful in 
informing other users of the same library 
in a way that would not be tolerated at 
the present time.” 

We don’t know if Dr. Lederberg got 
that last idea from Ted Nelson’s Project 
Xanadu, but that is just the kind of thing 
that Nelson describes in his book Literary 
Machines, available from the Project for 


$15. The Xanadu (tm) system. Nelson 
claims, exists in prototype form. It allows 
any user to make nondestructive notes in 
the margin of a retrieved document, and 
has a number of other remarkable prop¬ 
erties as well. We have a copy, and it’s a 
fascinating read, guaranteed to fill any 
computerist’s head with dazzling visions 
and daring possibilities. 


* 

Computer uses slim-line 8-inch 
es. 


Contact Points 

Alspa Computer, Inc., 300 West Harvey 
Blvd., Santa Cruz, CA 95060; (408) 429- 
6000. 

Altos Computer Systems, 2360 Bering 
Drive, San Jose, CA 95131; (408) 946- 
6700. 

Columbus Instruments International Corpo¬ 
ration, 950 N. Hague Avc., Columbus, OH 
43204; (614) 488-6176. 

Computer Swap America, POB 52, Palo 
Alto, CA 94302;(415) 494-6862. 
CompuThink, 965 West Maude Ave., Sunny¬ 
vale, CA 94086; (408) 245-4033. 


Datagraph, P. O. Box D, Arnold, CA 95223; 
(209) 795-5104. 

Dynabyte, 521 Cottonwood Drive, Milpitas, 
CA 95035; (408) 263-1221. 

Professor Frances Grant, Center for Infor¬ 
mation and Communications Study, Califor¬ 
nia State University, Chico, CA 95929. 
Kengore Corporation, 3001 Route 27, 
Franklin Park, NJ 08823; (201) 297- 
2526. 

Miken Optical Company, 53 Abbett Ave¬ 
nue, Morristown, NJ 07960; (201) 267- 
1210. 

National Computer Shows, 824 Boylston 


Street, Chestnut Hill, MA 02167; (617) 
739-2000. 

Percom, 11220 Pagemill Road, Dallas, TX 
75243; 800-527-1222. 

Project Xanadu, Box 128, Swarthmore, PA 
19081. 

Sage Software Company, 1322 La Loma 
Ave., Berkeley,CA 94708;(415) 843-0863. 
Software Toolworks, 14478 Gorietta Drive, 
Sherman Oaks, CA 91423; (213) 986-4885. 
Stanford University News Service, Stanford, 
CA 94305;(415)497-2558. 

Tecmar, Inc., 23600 Mercantile Road, 
Qeveland, OH 44122; (216) 464-7410. 




Recursion 


R ecursion, which is the ability of a 
procedure to use itself (either di¬ 
rectly or indirectly) as a subpro¬ 
cedure, is regarded by most programmers 
as a fundamental requirement of pro¬ 
gramming languages. Not only are many 
mathematical functions most convenient¬ 
ly expressed in recursive form; but there 
is a large number of non-numeric opera¬ 
tions that can most conveniently be ex¬ 
pressed recursively. This is particularly 
true of operations on list or tree struc¬ 
tures. Thus, any operation on a tree can 
be expressed by the following algorithm: 

1. Perform the operation on the root of 
the tree 

2. Perform the operation in turn on all 
the subtrees. 

A recursive definition consists of two 
parts: 

1. A definition of how the procedure is 
to be applied to a terminal value. 

2. A definition of how the procedure is 
to be applied to an arbitrary value, ex¬ 
pressed in terms of the same procedure 
applied to the predecessor of that 
value. The predecessor of a tree is re¬ 
garded as the set of subtrees that are 
left when the root is removed. The 
predecessor of a positive argument of a 
numeric function is that argument 
diminished by unity. Thus we may 
define a recursive schema for a func¬ 
tion F operating on positive integers 
as follows: 

F(n) = A (n - 1) 

= 6 (n. F (n')) (n > 1) 

where A is a constant, G is a second 
function that may be defined indepen¬ 
dently of F, and n is the predecessor 
of n. To take a simple example, the 
factorial function may be defined 

F (2) = 2 

FCn > 1) = n * F (rr l) 

in which the multiply operator plays 
the part here of the function G in the 
schema above. 


by Qlyn Emery 


Glyn Emery, Dept, of Computer Science, 
Adran Gwyddor Cyfrifiadur, University 
of Wales, Aberystwyth, Coleg Prifysgol 
Cymru, Wales SY23 3BZ 


12 


in FORTH 


The above procedures are auto¬ 
recursive, or self-recursive; i.e., they are 
defined directly in terms of themselves. 
There is, however, a class of procedures 
that are defined in terms of a second 
procedure, which in turn is defined, 
either directly or indirectly, in terms of 
the first. This form of definition is known 
as mutual recursion. In many cases 
mutual-recursion definitions can be re¬ 
duced to cases of self-recursion; but there 
are functions that can be defined by mu¬ 
tual recursion but not by self-recursion. 
Nevertheless, even when a reduction to 
self-recursion can be carried out, it may 
not be convenient, since doing so may ob¬ 
scure the algorithm and make a program 
more difficult to develop. 

Although FORTH functions are eval¬ 
uated using a stack mechanism, which is a 
fundamental requirement for recursive 
programming, FORTH unfortunately can¬ 
not provide users directly with the ability 
to use it recursively. The possibility of 
self-recursion is explicitly excluded from 
FORTH by the smudging process, which 
ensures that a word cannot be found in 
the dictionary until its definition has 
been completed. Smudging inverts the bit 
in the “32” position of the length byte in 
the name field at the start of compilation. 
In the case of function definitions, this 
bit is returned to its original value only 
when the semicolon operator is obeyed at 
the end of the compilation. Throughout 
the compilation, therefore, the length 
byte is “wrong” and the word cannot be 
matched unless, of course, we are per¬ 
forming a redefinition of a word that is 
already present in the dictionary. 

Nor can mutual recursion be achieved 
in FORTH. This is because any reference 
within a FORTH definition must be to a 
word that has already been defined and is 
already present in the dictionary. This re¬ 
striction does not apply to other high- 
level langauges, since most compilers 
operate in two or more passes. An early 
pass is used to assign locations to identi¬ 
fiers: a subsequent pass enters references 
to these locations wherever they are 
appropriate. We might note here that, 
were it possible to achieve mutual recur¬ 
sion in FORTH, then it would be possible 
to achieve self-recursion in spite of the 
smudging process, since function F could 
refer internally to function G, which in 
turn could be defined as identical to F. 

One technique for achieving self- 
recursion is to plant the code-field ad¬ 
dress of the word in the appropriate posi¬ 


tion in its own parameter field by some 
means other than the normal dictionary 
search. Fortunately, this can be done 
without much difficulty, since a new 
word is added to the current vocabulary 
right at the start of its compilation. 
The definition in Figure A defines a 
word that will place on the stack the 
code-field address of the last word 
added to the vocabulary. This word 
must be declared immediate, since we 
shall require it to do its work during 
compilation. Notice that two “contents” 
operators are required, since CURRENT 
actually points to a word within the 
vocabulary definition itself, and this in 
turn points to the last word defined. 

The word LITERAL, which is also 
immediate, if obeyed during compilation, 
places the top stack item in the next 
available space in the dictionary, and will 
therefore compile the address generated 
by THISCODE. At execution time, this 
address will simply be transferred to the 
stack, and can therefore be executed by 
obeying the word EXECUTE. Thus, a 
complete recursive definition of the fac¬ 
torial function would be as found in 
Figure B. 

An alternative way of performing 
self-recursion is to define the desired 
function initially as a dummy. See 
Figure C. The function can now be used 
in the definition of itself, except that, to 
avoid redefinition, we must give the full 
definition an alias. An example is found 
in Figure D. In the dummy definition, 0 
ensures that a single 16-bit word is allot¬ 
ted, provided of course that 0 is a real 
dictionary entry, as it is in most dialects 
of FORTH. The final requirement is to 
construct a thread to lead from FAC to 
FACALIAS. In a sense this is a renaming, 
so we might write 

RENAME FACALIAS FAC 

where RENAME is defined as in Figure E. 
The “tick” operator is immediate, so 
[COMPILE] must be used to make sure 
that it is compiled into the definition of 
RENAME. Notice that it is [COMPILE] 
and not COMPILE that must be used 
here. This is because the tick must be 
forced to execute in compilation mode, 
not in execution mode, since in the latter 
mode it operates in the same way as the 
word LITERAL and so in this instance 
would merely stack the code-field ad¬ 
dresses of CFA and !. Treated in this 
way, the “tick” operators ensure that the 


Dr. Dobb’s Journal, Number 64, February 1982 

■59 




Figure A 
Figure B 

Figure C 
Figure D 
Figure E 
Figure F 

Figure G 

Figure H 

Figure I 
Figure J 

Figure K 


Figure L 


: THISCODE CURRENT S S PFA CFA ; IMMEDIATE 

: FAC DUP 2 = IF ELSE DUP 1 - THISCODE LITERAL EXECUTE 

* ENDIF ; 


: FAC 0 ; 

: FACALIAS DUP 2 = IF ELSE DUP 1 - FAC * ENDIF ; 


: RENAME [COMPILE! 1 CFA [COMPILE! 1 ! ; 


f Cx + 1) 
g(x > 1) 
f (1) 
q(1) 


x ♦ g(x> ♦ f(x) 
2f(x) ♦ 1 
1 
0 


(x > 1) 
<x > 1) 


: EFF 0 ; 

: DEE 1 DUP 0 > IF CFF 2 * 1+ ENDIF ; 

: FALIAS 1 - -DUP 0= IF 1 ELSE DUP GEE OVER EFF 

♦ ♦ ENDIF ; 

RENAME FALIAS EFF 


: DIPS DUP 0 DO 0 SWAP LOOP SP3 2+ SWAP DUP ♦ OVER OVER 
♦ ROT ROT CMOVE ; 

: DROPS 0 DO U.;OP LOOP ; 


n(x> 2) 

= x ♦ 1 



n(x. y*1> 

= qCx.y.x) 

(y 

> i> 

q(Xry<0) 

= 1 



q(x.y.L-) 

- 2 v(xry<s~1) q(x.y.s-l) 

(s 

i> 

v(X(>'.0) 

= n(x.y) 




q(x.y.s) , 



vCx.y.r.) 

= n(x »y> 




: EXP OVER SWAP -DUP 0- If ELSE 0 DO OVER « LOOP 
ENDIF SWAP / ; 

: OQO 0 ; 

: NNN DUP 2 = IF DROP 1+ ELSE 1 - OVER OQQ ENDIF ; 

: MU -DUP 0= IF NNN ELS'.- 3 DUOS 000 >R DRCF SWAP 

P.> EXP SWAP NNN ENDIF ; 

: QALIAS -DU? 0= IF ? DROPS 1 ELSE 1 - i DUPS 

NU >R QQQ R> ♦ DUP + ENDIF ; 

RENAME QALIAS QQQ 

; TRACE EMIT SPACE CUP 1+ DUPS 0 DO . LOOP DROP ; 



code-field address of FACALIAS is 
stored in the parameter field of FAC in 
place of the 0. 

The same technique can be used to 
achieve mutual recursion. Consider the 
recursive system found in Figure F. The 
function f could in fact be expressed in a 
self-recursive schema; but this example 
will do for present purposes. In FORTH, 
the system becomes as in Figure G. 

The examples considered so far have 
involved functions with only one argu¬ 
ment, so that a simple DUP has been suf¬ 
ficient to provide a copy for a recursive 
call. For general recursive use it is conven¬ 
ient to provide a word that will “pass” an 
arbitrary number of parameters to any 
called function by making copies of them 
on the stack. The word found in Figure H 
does this; so that the call 

ri DUPS 

makes a copy of the top n stack items 
(excluding n itself). Another useful word 
in this connection is shown in Figure I. 

In Khinchin 1 a recursive function 
n(x,y) is defined in a manner equivalent 
to that found in Figure J. 

Thus n(x,y) is defined for all x > 1 
and all y > 2. This function cannot in 
fact be reduced to a case of self-recursion, 
though it can be expressed more simply 
than this; but, using the techniques de¬ 
veloped above, we can easily evaluate it in 
FORTH. See Figure K. 

Unfortunately only a few values of 
this function can be evaluated in single¬ 
length arithmetic. The same words could, 
however, be used in double or multiple 
length, if the arithmetic and stack opera¬ 
tors were suitably redefined. 

A useful operator to use when de¬ 
veloping FORTH functions is found in 
Figure L. This outputs the top stack item 
as an ASCII character, followed by a 
number of stacked parameters. Thus, 

81 3 TRACE 

outputs a Q followed by the top three 
stack items (not counting the 81 and the 

3). 




Reference 

1. Khinchin, A. Y. Three Pearls of Num¬ 
ber Theory, Gaylock Press, 1952, 
p. 13. 


Dr. Dobb’s Journal, Number 64, February 1982 
"60" 


13 



FORTH 8086 
Assembler 


I BM’s selection of the Intel 8088 as the 
heart of their Personal Computer has 
ensured that the 8086/8088 family 
will be a hot item for years to come. 
Many companies (including my own) are 
preparing FORTH program development 
systems and application programs to run 
on these machines. Although FORTH as¬ 
semblers are a vital part of the FORTH 
programming environment, writing and 
debugging them is a relatively bleak task. 
We are placing the accompanying code in 
the public domain so that FORTH pro¬ 
grammers can use their time more profit¬ 
ably elsewhere. 

FORTH assemblers are used in two 
distinct ways. The first is as an integral 
part of the FORTH runtime system for 
creation of new machine language primi¬ 
tives in the FORTH dictionary. This capa¬ 
bility is useful in applications such as pro¬ 
cess control that are highly time depen¬ 
dent; many FORTH programs can be 
speeded up to a surprising degree by re¬ 
coding a few frequently used words (such 
as the components of inner loops) in as¬ 
sembly language. The other common 
application for an assembler is meta¬ 
compiling; that is, the generation of 
FORTH programs on a host processor 
for a different target processor. 

Paradoxically, although FORTH as¬ 
semblers are crucial to both the power 
and transportability of the FORTH lan¬ 
guage, they tend to be poor examples of 
“good” FORTH programming style. The 
necessary decoding of address modes and 
manipulation of bit fields results in code 
that is complex, terse, and obscure - in 
contrast to FORTH application programs, 
where the highest level words have 
simple, short definitions that describe 
exactly what they do. 

This 8086 assembler was originally 
prepared to be embedded in the Nautilus 
Systems Cross Compiler, and was used to 
transport FORTH onto the Lomas Data 
Products 8088 microcomputer. The ver¬ 
sion presented here is written in standard 
fig-FORTH for use as part of a FORTH 
runtime package. Due to the many ad¬ 
dressing modes and the highly asym¬ 
metric architecture of the 8086/8088 
family, the code is bulky and includes a 
generous amount of error-checking logic 


by Ray Duncan 


Ray Duncan, c/o Laboratory Microsys¬ 
tems, 4147 Beethoven Street, Los An¬ 
geles, CA 90066. 


compared to traditional FORTH assem¬ 
blers. For those readers who wish to cut 
down the memory space requirements, a 
few suggestions are included at the end of 
the article. 

In spite of the assembler’s syntax 
checking and error reporting, it is still 
easy to produce garbage code and crash 
the FORTH interpreter/compiler. For 
this reason, when one is writing assembler 
code, it should be edited into disk screens 
and loaded in small modules for debug¬ 
ging. Be careful to preserve the interpre¬ 
tive pointer and return stack pointer 
across FORTH words (their actual loca¬ 
tion is implementation dependent, see the 
installation manual for your FORTH sys¬ 
tem). Modification of these registers will 
result in an immediate crash of the inter¬ 
preter/compiler. 

Using the Assembler 

Each new word definition must begin 
with the word CODE, followed by the 
new FORTH name. This sequence creates 
a dictionary header with the contents of 
the code field address pointing to the 
parameter field so that when the word is 
invoked, control is transferred by the 
inner interpreter directly to the machine 
language routine. The ASSEMBLER vo¬ 
cabulary is automatically selected. A 
series of mnemonics and operands may 
then be entered in postfix notation. The 
entire definition must be closed by the 
word NEXT, which does some error 
checking, reselects the FORTH vocabu¬ 
lary, and encodes an unconditional 
branch back to the inner interpreter. 

Here is a simple example using the 
Assembler to create a fast integer multi¬ 
ply by ten routine (expects the argument 
on top of stack, and leaves the result on 
top of stack; see Figure 1). 

Execution control when coding as¬ 
sembler primitives is provided through 
the use of BEGIN . .. UNTIL, IF . . . 
ENDIF, and IF. . . ELSE.. . ENDIF con¬ 
structs very similar to those in the usual 
FORTH vocabulary. The primary differ¬ 
ence is that the assembler versions of these 
constructs operate on the basis of the 
CPU status flags rather than the top of 
stack parameter; they do not change the 
CPU flags or the contents of the para¬ 
meter stack. Here is an example of a loop 
which repeatedly reads port #1, waiting 
for bit #2 to be set (See Figure 2). 

A more general purpose version 
could be coded which would accept a 


port number and bit mask on the stack 
(See Figure 3). 

The assembler follows the Intel mne¬ 
monic as closely as possible, with the fol¬ 
lowing exceptions: 

• Postfix notation. Operands precede 
the instruction mnemonic. Destination 
operands are terminated by a comma. 
For example: 

AX. DX MOV 

means copy the contents of register 
DX into register AX. 

• Parts of the operand must be separated 
by spaces. For example: 

AX, DX MOV 

is legal, while 

AX, DX MOV 

will cause an assembler error. 

• Immediate data values are designated 
with the “#” operator, similar to the 
DEC macro-assembler. For example: 

AX, # 0001 MOV 

means load the value 0001 into the 
AX register, while 

AX, 0001 MOV 

indicates load the contents of location 
0001 into the AX register. 

• When a numeric value occupies the 
destination operand field, it must be 
followed by a free-standing comma. 
For example, to store the contents of 
the AX register into memory location 
010A, you would write: 

010A , AX MOV 

• When indexed addressing is used, any 
displacement must precede the index 
register specification. For example: 

AX, 4 CBXD MOV 

means load the contents of the address 
pointed to by register BX plus 4 into 
the AX register. 

• In general, the assembler relies on flags 
set by the operands to determine the 
addressing mode. In a few special cases 
the W (word/byte) flag cannot be in¬ 
ferred from the operand field and 
must be explicitly set with the BYTE 
or WORD operators. If not set by the 


14 


Dr. Dobb’s Journal, Number 64, February 1982 

~ 






CODE 

AL. 01 

AL. # 02 

PORT-WAIT 

BEGIN 

IN 

TEST 

UNTIL 

NEXT 

( road port #1 
( chock if bit 
( loop until Z 

) 

2 sot ) 
flag falso ) 



Figure 2 



CODE 

PORT-WAIT 

DX 

POP 

BX 

POP 


BEGIN 

AX, DX 

IN 

AX, BX 

TEST 


UNTIL 


NEXT 


( port number > 

( bit mask ) 

( read port ) 

( check status bit ) 

< loop until Z flag false ) 

Figure 3 


programmer, the mode defaults to 
byte. Examples: 

BYTE LODS 
WORD STOS 
BYTE 5 CBX3 NEC 

• The following instructions are not im¬ 
plemented: ESC, INT, LDS, LES, and 
SEG. 

• Memory direct addressing with the 
arithmetic or logical instructions such 
as ADD and OR is not supported at 
present. However, all varieties of direct 
addressing involving the MOV instruc¬ 
tion are supported. 

• When coding jumps, conditional 
branches, or calls, you must supply the 
absolute offset address. The assembler 
calculates the displacement and issues 
an error message if the target address is 
out of range. 

• Intersegment “long” jumps and calls 
are not supported. 

• In order to keep the assembler from 
becoming even more bulky, certain 
special case machine code sequences 
are not supported. This causes the as¬ 
sembled code to be slightly longer in a 
few instances but does not result in 
any logical difference at execution 
time. For example, the 8086 instruc¬ 
tion set includes a special CMP instruc¬ 
tion for comparison of AX with im¬ 
mediate data, and a more general pur¬ 
pose but slightly longer CMP instruc¬ 
tion to compare any register with an 
immediate data value; only the latter is 
implemented in this assembler. 


Operation of the Assembler 

Because of the generality of the 8086 
instruction mnemonics, the addressing 
mode usually cannot be inferred from the 
instruction itself, as it can in the 8080 
(e.g., LXI, LHLD). Consequently, the as¬ 
sembler relies on the operands for this 
information. Each register-related source 
or destination operand is defined through 
a BUILDS . . . DOES statement, so that 
at execution time they will appropriately 
set up the variables containing the word/ 
byte flag, the direction flag, any indexing 
offsets, addressing type, and the register 
codes. In those cases where an operand 
field is not a register or register index, 
other operators (“#” and are pro¬ 
vided to set the flags. 

Because of the FORTH postfix nota¬ 
tion, when the instruction mnemonic is 


executed all information is already avail¬ 
able in the variables for it to assemble 
the final machine code. The final assem¬ 
bly itself can be very complex. For ex¬ 
ample, the MOV instruction must be able 
to hand over 25 legal addressing combina¬ 
tions while screening out impossible 
transfers (such as trying to copy an 8-bit 
register into a 16-bit register). 

The 8086 instructions are divided 
into fourteen groups for assembly pro¬ 
cessing based on the structure of the ma¬ 
chine code: 

1. Simple single byte instructions (no 
operand). 

2. Conditional branches and loops with 
1 byte offset. 

3. String instructions CMPS, LODS, 
MOVS, SCAS, and STOS. 

4. PUSH and POP. 

5. Intrasegment jumps and calls of the 
form “JMP disp 16” or “JMP reg/ 
mem”. 

6. IN and OUT. 

7. Two operand arithmetic/logical in¬ 
structions: ADC, ADD, AND, CMP, 
OR, SBB, SUB, TEST, and XOR. 

8. Single operand arithmetic/logical in¬ 
structions: DIV, IDIV, IMUL, MUL, 
NEC, and NOT. 

9. Various shifts: RCL, RCR, ROL, 
ROR, SAL, SAR, SHL, and SHR. 

10. Simple two byte instructions (no 
operand). 


CODE 

FAST10* 



AX 


POP 



BX, 

AX 

MOV 



AX, 

AX 

ADD 

( * 

2 ) 

AX, 

AX 

ADD 

< * 

4 ) 

AX, 

BX 

ADD 

( * 

5 ) 

AX, 

AX 

ADD 

( * 

10 ) 

AX 


PUSH 





NEXT 




Figure 1 


16 

62 


Dr. Dobb’s Journal, Number 64, February 1982 





Table I 


11. INC and DEC. 

12. Various MOV instructions. 

13. Various XCHG instructions. 

14. TEST instruction. 

A number of internal primitives are 
used by the assembler to produce ma¬ 
chine code. Ordinarily, these are not used 
by the FORTH application programmer, 
but their operation is described in Table I 
to facilitate extension and modification 
of the assembler itself. 


Pruning the Assembler 

Those readers who need to reduce 
the size of the assembler module may 
consider the following suggestions: 

1. Remove error checking code. 

2. Replace the CASE statements with 
Kim Harris’ Case-Colon constructs or 
nested “IF . . . ELSE .. . THEN” con¬ 
structs. Alternatively, use a machine 
language implementation of “OF” (see 
Dr. Eaker’s original article for an ex¬ 
ample). 

3. Remove infrequently used instructions 
and addressing modes altogether. 

4. Modify the register BUILDS . . . DOES 

definition so that it increments a 
counter; from this it can detect 
whether it is processing the source or 
destination register. This would allow 
you to eliminate one set of register 
names and one of the register process¬ 
ing routines. BBj 

(Listing begins on page 33) 


!<SP> Set the local stack pointer to the current parameter stack 

position. 

?<SP> Leave the depth of the local stack on top of the stack. Used by 
the register decoding routines to determine whether a displace¬ 
ment has been specified. 

?W Leave the “ W” (word/byte) flag on top of stack. 

?TD Leave the internal addressing indicator of the destination 

operand on top of stack. This takes on a value in the range 0-5 
which may be interpreted as follows: 

0 Direct addressing 

1 Immediate operand 

2 8-bit register 

3 16-bit register 

4 Base relative indexed addressing 

5 16-bit segment register 

?TS Leave the internal addressing indicator of the source operand 

on top of stack. This takes on a value of 0-5 as above. 

?RD Leave the code 0-7 of the destination register on top of stack. 

?RS Leave the code 0-7 of the source register on top of stack. 

?OD Leave the displacement of the destination operand on top of 

stack. Only valid for the direct indexed and base relative 
indexed addressing modes. 

?OS Leave the displacement of the source operand on top of stack. 

Only valid for the direct indexed and base relative addressing 
modes. 

RESET Clear all assembler flags and modes. 

OFFSET8, Calculate the displacement from the address on top of stack to 
HERE and store it as an 8-bit field into the assembled code. 
Used by conditional branches and loops. If the branch is out 
of range, issue an error message. 

OFFSET16, Calculate the displacement from the address on top of stack to 
HERE and store it as a 16-bit field into the assembled code. 

DISP, According to the operand type and displacement value, set 

the MOD field, store the forming byte on top of stack into the 
assembled code, then store an eight- or sixteen-bit displace¬ 
ment value if necessary. 

DSET Check whether the source or destination operand uses base 

relative indexed addressing and set the direction flag accord¬ 
ingly. 

BYTE Force the W flag to indicate byte mode. 

WORD Force the W flag to indicate word mode. 

The following primitives assemble flag fields into the lower byte of the 
word on top of stack: 

+W Merge the word/byte flag with the forming byte. 

+ D Merge the direction flag with the forming byte. 

+ RD Merge the destination register code with the forming byte. 

+ RS Merge the source register code with the forming byte. 

MODI Set the mod field to the bit pattern 01. 

MOD2 Set the mod field to the bit pattern 10. 

MOD3 Set the mod field to the bit pattern 11. 


18 


Dr. Dobb’s Journal, Number 64, February 1982 

"63 




Formal Definition 
of FORTH 


F ORTH was developed as a program¬ 
ming tool to solve real-time control 
problems. 1 While it has never been 
formally defined as a programming lan¬ 
guage, I think FORTH is mature enough 
now that it can be defined rigorously. 
The wide-spread use of this powerful 
tool requires that a common base be es¬ 
tablished to facilitate the exchange of 
programs and ideas in a standardized lan¬ 
guage form. The publication of FORTH- 
79 Standard 2 clearly reflects this neces¬ 
sity. To define FORTH as a programming 
language also helps us to focus our atten¬ 
tion on the basic characteristics of 
FORTH, and to understand it more fully. 

This article will present the defini¬ 
tion of FORTH in the Backus Normal 
Form (BNF) notation. The basic syntax is 
presented in Table I, in which the focal 
point is the definition of “word”. Some 
detailed clarifications on colon defini¬ 
tions and defining words are worked out 
in Tables H and III. Explanatory notes 
are arranged by section to highlight some 
problems not clearly expressed in the for¬ 
mal definitions. 

Programming Language 

A programming language is a set of 
symbols with rules (syntax) of combining 
them to specify execution procedures to 
a computer. A programming language is 
used primarily to instruct a computer to 
perform specific functions. However, it 
can also be used by programmers to docu¬ 
ment and to communicate problem solv¬ 
ing procedures. The most essential in¬ 
gredients of a programming language are 
therefore the symbols it employs for ex¬ 
pressions and the syntax rules of combin¬ 
ing the symbols for man-machine or 
man-man communications. 

FORTH uses the full set of ASCII 
characters as symbols. Most programming 
languages use subsets of ASCII characters, 
including only numerals, upper-case al¬ 
phabets, and some punctuation charac¬ 
ters. Use of punctuation characters differs 
significantly from language to language. 
Non-printable characters are generally re¬ 
served exclusively for the system and are 
not available for language usage. In em¬ 
ploying the full ASCII set of characters, 
FORTH thus allows the programmer a 


by C.H. Ting 


C. H. Ting, Offetc Enterprises, Inc., 1306 
S. B St., San Mateo, CA 94402. 


much wider range of usable symbols to 
name objects. On the other hand, the pro¬ 
lific use of punctuation characters in 
FORTH makes comprehension very diffi¬ 
cult by uninitiated programmers. 

Only four of the ASCII characters 
are used by FORTH for special system 
functions and are not for programming 
usage: NUL (ASCII O), RUB (ASCII 
127). CR (ASCII 13), and SP (ASCII 32). 
RUB is used to delete the previously en¬ 
tered character. It is used at the keyboard 
interactively to correct typing errors. 
NUL, CR, and SP are delimiting charac¬ 
ters to separate groups of characters to 
form words. All other characters are used 
to form words and are used the same 
way. Non-printable characters are treated 
the same as printable characters. Because 
non-printable characters are difficult to 
document and communicate, their usage 
is discouraged in normal programming 
practice. However, the non-printable 
characters are very useful in maintaining a 
secured system. For terminals that have 
function keys, their control sequences 
may be used as the names of the opera¬ 
tions each performs. 

Words 

Words are the basic syntactical units 
in FORTH. A word is a group of charac¬ 
ters separated from other words by de¬ 
limiting characters. With the exception of 
NUL, CR, SP and RUB, any ASCII char¬ 
acter may be part of a word. Certain 
words for string processing may specify a 
regular character as the delimiting charac¬ 
ter for the word immediately following it, 
in order to override the delimiting effect 
of SP. However, the delimiting effect of 
CR and NUL cannot be overridden. 

The usage of “word” in FORTH 
literature is very confusing because many 
quite different concepts are associated 
with it. Without sorting out these differ¬ 
ent aspects of “word” into independently 
identifiable entities, it is impossible to ar¬ 
rive at a satisfactory description of this 
language. Here the word is defined as a 
syntactical unit in the language, simply a 
group of characters separated from other 
words by delimiting characters. Seman¬ 
tically (concerning the meaning of a 
word), a word in FORTH can be only one 
of three things: a string, an instruction, or 
a number. 

A FORTH program is thus simply a 
list of words. When this list of words is 
given to a computer with a FORTH 
operating system loaded in, the computer 


will be able to execute or interpret this 
list of words and perform functions as 
specified by this list. The functions may 
include compilation of new instructions 
into the system to perform complicated 
functions not implemented in the original 
operating system. 

A string is merely a group of charac¬ 
ters to be processed by the FORTH com¬ 
puter. To be processed correctly, a string 
must be preceded by an instruction which 
specifies exactly how this string is to be 
processed. The string instruction may 
even specify a regular character as the de¬ 
limiting character for the following string 
to override the effect of SP. It is often 
appropriate to consider the string to be 
an integral part of the preceding instruc¬ 
tion. This would disturb the uniform and 
simple syntax rule in FORTH and it is 
better to consider strings as independent 
objects in the language. 

String processing is a major compo¬ 
nent in the FORTH operating system be¬ 
cause FORTH is an interpretive language. 
Strings are needed to supply names for 
new instructions, to insert comments into 
source text for documentation, and to 
produce messages at run-time to facilitate 
human interface. The resident FORTH in¬ 
structions for string processing are all 
available to programmers for string mani¬ 
pulations. 

A number is a string which causes the 
FORTH computer to push a piece of data 
onto the data stack. Characters used in a 
number must belong to a subset of ASCII 
characters. The total number of charac¬ 
ters in this subset is equal to a “base” 
value specified by the programmer. This 
subset starts from 0 and goes up to 9. If 
the base value is larger than 10, the 
upper-case alphabets are used in their 
natural sequence. Any reasonable base 
value can be specified and modified at 
run-time by the programmer. However, a 
very large base value causes excessive 
overlapping between numbers and in¬ 
structions, and a “reasonable base value” 
must avoid this conflict in semantical in¬ 
terpretation. 

A number can have a leading “-” 
sign to designate data of negative value. 
Certain punctuation characters such as 

are also allowed in numbers depend¬ 
ing upon the particular FORTH operating 
system. 

The internal representation of num¬ 
bers inside the FORTH computer de¬ 
pends upon implementation. The most 
common format is a 16-bit integer num- 


Dr. Dobb’s Journal, Number 64, february 1982 


19 




ber. Numbers are put on the data stack to 
be processed. The interpretation of a 
number depends entirely on the instruc¬ 
tion which uses the number. A number 
may be used to represent a true-or-false 
flag, a 7-bit ASCII character, an 8-bit 
byte, a 16-bit signed or unsigned integer, 
a 16-bit address, etc. Two consecutive 
numbers may be used as a 32-bit signed 
or unsigned double integer, or a floating 
point number. 

FORTH is not a typed language in 
which numerical data types must be de¬ 
clared and checked during compilation. 
Numbers are loaded on the data stack 
(hereafter called the “stack”) where all 
numbers are represented and treated iden¬ 
tically. Instructions using the numbers on 
the stack will take whatever they need for 
processing and push their results back on 
the stack. It is the responsibility of the 
programmer to put the correct data on 
the stack and use the correct instructions 
to retrieve them. Non-discriminating use 
of numbers on the stack might seem to be 
a major source of errors in using FORTH 
for programming. In practice, the use of 
the stack greatly eases the debugging pro¬ 
cess in which individual instructions can 
be thoroughly exercised to spot any dis¬ 
crepancies in stack manipulations. The 
most important advantage gained in the 
uniform usage of data stored on the stack 
is that the instructions built this way can 
be context-free, allowing them to be re¬ 
peatedly called in different environments 
to perform the same task. 

Numbers and strings are objects or 
nouns in a programming language. Typed 
and named numbers in a program provide 
vital clues to the functions and the struc¬ 
tures in a program. The explicitly defined 
objects or nouns make statements in a 
program easy to comprehend. The impli¬ 
cit use of data objects stored on the data 
stack makes FORTH programs very tight 
and efficient. However, statements in a 
program deprived of nouns are difficult 
to understand. For this reason, the 
most important task in documenting 
a FORTH program is to specify the stack 
effects of the instructions, indicating 
what types of data are retrieved from the 
stack and what types of data are left on 
the stack upon exit. 

Standard Instructions 

In a FORTH computer, an instruc¬ 
tion is best defined as “a named, linked, 
memory resident, and executable entity 


which can be called and executed interac¬ 
tively.” The entire linked list of instruc¬ 
tions in the computer memory is called a 
“dictionary.” Instructions are known to 
the programmer by their ASCII names. 
The names of the instructions in a 
FORTH computer are words that a pro¬ 
grammer can use either to execute the in¬ 
struction interactively or to build (com¬ 
pile) new instructions to solve his pro¬ 
gramming problems. 

In FORTH literature, instructions are 
called “words,” “definitions,” or “word 
definitions.” The reason that I chose to 
call them “instructions” is to emphasize 
the fact that an instruction given to the 
FORTH computer causes immediate ac¬ 
tions performed by the computer. The in¬ 
structions in the dictionary are an instruc¬ 
tion set of the FORTH virtual computer, 
in the same sense as the instruction set of 
a real CPU. The difference is that the 
FORTH instructions can be executed di¬ 
rectly and the FORTH instructions are 
accessed by their ASCII names. There¬ 
fore, FORTH can be considered as a high- 
level assembly language with an open in¬ 
struction set for interactive programming 
and testing. The name “instruction” con¬ 
veys more precisely the characteristics of 
a FORTH instruction than “word” or 
“definition,” and leaves “word” to mean 
exclusively a syntactical unit in the lan¬ 
guage definition. 

Instruction set is the heart of a 
computer as well as of a language. In 
all conventional programming languages, 
the instruction set is immutable and 
limited in number and in scope. Program¬ 
mers can circumvent the shortcomings of 
a language by writing programs to per¬ 
form tasks that the native instruction set 
is not capable of. The instruction set in 
a FORTH computer provides a basis or a 
skeleton from which a more sophisticated 
instruction set can be built and optimized 
to solve a particular problem. 

Because the instruction set in 
FORTH can be easily extended by the 
user, it is rather difficult to define pre¬ 
cisely the minimum instruction set a 
FORTH computer ought to have. The 
general requirement is that the minimum 
set should provide an environment in 
which typical programming problems can 
be solved conveniently. FORTH-79 Stan¬ 
dard suggested a convenient instruc¬ 
tion set as summarized in Table I. These 
instructions provided by the operating 
system are called “standard instructions,” 
and are divided into nucleus instructions, 


interpreter instructions, compiler instruc¬ 
tions, and device instructions. 

User Instructions 

Instructions created by a user are 
called “user instructions.” There are sever¬ 
al classes of user instructions depending 
upon how they are created. High level in¬ 
structions are called “colon instructions” 
because they are generated by the special 
instruction Low level instructions 

containing machine codes of the host 
CPU are called “code instructions” be¬ 
cause they are generated by the instruc¬ 
tion CODE. Other user instructions in¬ 
clude constants, variables, and vocabu¬ 
laries. 

Instructions are verbs in FORTH lan¬ 
guage. They are commands given to the 
computer for execution. Instructions 
cause the computer to modify memory 
cells, to move data from one location to 
the other. Some instructions modify the 
size and the contents of the data stack. 
Implicitly using objects on the data stack 
eliminates nouns in FORTH programs. It 
is not uncommon to have lines of 
FORTH text without a single noun. The 
verbs-only FORTH text earns it the repu¬ 
tation of a “write-only” language. 

FORTH is an interpretive language. 
Instructions given to the computer are 
generally executed immediately by the 
interpreter, which can be thought of as 
the operating system in the FORTH com¬ 
puter. This interpreter is called “text in¬ 
terpreter” or “outer interpreter.” A word 
given to the FORTH computer is first 
parsed out of the input stream, and the 
text interpreter searches the dictionary 
for an instruction with the same name as 
the word given. If an instruction with 
matching name is found, it is executed by 
the text interpreter. The text intepreter 
also performs the tasks of compiling new 
user instructions into the dictionary. The 
process of compiling new instructions is 
very different from interpreting exist¬ 
ing instructions. The text interpreter 
switches its mode of operation from 
interpretation to compilation by a group 
of special instruction called “defining 
instructions,” which perform the func¬ 
tions of language compilers in conven¬ 
tional computers. 

Syntax of these defining instructions 
is more complicated than the normal 
FORTH syntax because of the special 
conditions required of the compilation of 
different types of user instructions. The 


20 


Dr. Dobb’s Journal, Number 64, February 1982 

"65 


syntax of the defining instructions pro¬ 
vided by a standard FORTH operating 
system is summarized in Table II. The 
most important defining instruction is 
the or colon instruction. To define 
colon instructions satisfactorily, a new 
entity, “structure,” must be introduced. 
This concept and many other aspects in¬ 
volving defining instructions are discussed 
in the following subsections. 

Structures and Colon Instructions 

Words are the basic syntactical units 
in FORTH language. During run-time 
execution, each word has only one entry 
point and one exit point. After a word is 
processed by the interpreter, control re¬ 
turns to the text interpreter to process 
the next consecutive word. Compilation 
allows certain words to be executed re¬ 
peatedly or to be skipped selectively at 
run-time. A set of instructions, equiva¬ 
lent to compiler directives in conven¬ 
tional programming languages, are used to 
build small modules to take care of these 
exceptional cases. These modules are 
called structures. 

A structure is a list of words bound¬ 
ed by a pair of special compiler instruc¬ 
tions, such as IF-THEN, BEGIN-UNTIL, 
or DO-LOOP. A structure, similar to an 
instruction, has only one entry point and 
one exit point. Within a structure, how¬ 
ever, instruction or word sequence can 
be conditionally skipped or selectively 
repeated at runtime. Structures do not 
have names and they cannot be executed 
outside of the colon instruction in which 
it is defined. However, a structure can be 
given a name and defined as a new user 
instruction. Structures can be nested, but 
two structures cannot overlap each other. 
This would violate the one-entry-one- 
exit rule for a structure. 

Structure is an extension of a word. 
A structure should be considered as an 
integral entity like a word inside a colon 
instruction. Words and structures are the 
building blocks to create new user in¬ 
structions from low level to high level. All 
the instructions created at low levels are 
available to build new instructions. The 
resulting instruction set then becomes the 
solution to the programming problem. 
This programming process contains na¬ 
turally all the ingredients of the much 
touted structure programming and soft¬ 
ware engineering. 

Using the definition of structures, 
the precise definition of a colon instruc¬ 


tion is: “a named, executable entity equi¬ 
valent to a list of structures." When a 
colon instruction is invoked by the inter¬ 
preter, the list of structures is executed in 
the order the structures were laid out in 
the colon instruction. 

When a colon instruction is being 
compiled, words appearing on the list of 
structures are compiled into the body of 
the colon instruction as execution ad¬ 
dresses. Thus, a colon instruction is simi¬ 
lar to a list of subroutine calls in conven¬ 
tional programming languages. However, 
only the addresses of the called subrou¬ 
tines are needed in the colon instruction 
because the CALL statement is implicit. 
Parameters are passed on the data stack 
and the argument list is eliminated also. 
Therefore, the memory overhead for a 
subroutine call is reduced to a bare mini¬ 
mum of two bytes in FORTH. This justi¬ 
fies the claim that equivalent programs 
written in FORTH are shorter than those 
written in assembly language. 

Compiler instructions setting up the 
structures are not directly compiled into 
the body of colon instructions. Instead, 
they set up various mechanisms such as 
conditional tests and branch addresses in 
the compiled codes so that execution 
sequence can be directed correctly at run¬ 
time. The detailed codes that are com¬ 
piled are implementation dependent. 

Code Instructions 

Colon instruction allows a user to ex¬ 
tend the FORTH system at a high level. 
Programs developed using only colon in¬ 
structions are very tight and memory ef¬ 
ficient. These programs are also trans¬ 
portable between different host comput¬ 
ers because of the buffering of the 
FORTH virtual computer. Nevertheless, 
there is an overhead in execution speed in 
using colon instructions. Colon instruc¬ 
tions are often nested for many levels and 
the interpreter must go through these 
nested levels to find executable codes 
which are defined as code instructions. 
Typically, the nesting and unnesting of 
colon instructions (calling and returning) 
cost about 20% to 30% of execution 
time. If this execution overhead is too 
much to be tolerated in a time-critical 
situation, instructions can be coded in 
machine codes which will then be execut¬ 
ed at the full machine speed. Instructions 
of this type are created by the CODE in¬ 
struction, which is equivalent to a 
machine code assembler in conventional 
computer systems. 


Machine code representation depends 
on the host computer. Each CPU has its 
own machine instruction set with its par¬ 
ticular code format. The only universal 
machine code representation is by num¬ 
bers. To define code instructions in a 
generalized form suitable for any host 
computer, only two special compiler in¬ 
structions, (comma), and “C,” are 
needed. “C,” takes a byte number and 
compiles it to the body of the code in¬ 
struction under construction, and 
takes a 16-bit integer from the data stack 
and compiles it to the body of the code 
instruction. An assembly code is thus a 
number followed by “C,” or The 
body of a code instruction is a list of 
numbers representing a sequence of ma¬ 
chine codes. As the code instruction is 
invoked by the interpreter, this sequence 
of machine codes will be executed by the 
host CPU. 

Advanced assemblers have been de¬ 
veloped for almost all computers com¬ 
mercially available based on this simple 
syntax. Most assemblers use names of 
assembly mnemonics to define a set of 
assembler instructions which facilitates 
coding and documenting of the code 
instructions. The detailed discussion of 
these advanced instructions is outside the 
scope of this article. 

Constants, Variables, and Vocabulary 

The defining instructions CON¬ 
STANT and VARIABLE are used to in¬ 
troduce named numbers and named mem¬ 
ory addresses to the FORTH system, re¬ 
spectively. After a constant is defined, 
when the text interpreter encounters its 
name, the assigned value of this constant 
is pushed to the data stack. When the 
interpreter finds the name of a prede¬ 
fined variable, the address of this variable 
is pushed to the data stack. Actually, the 
constants defined by CONSTANT and 
the variables defined by VARIABLE are 
still verbs in the FORTH language. They in¬ 
struct the FORTH computer to introduce 
new data items to the data stack. How¬ 
ever, their usage is equivalent to that of 
numbers, and they are best described as 
“pseudo-nouns.” 

Semantically, a constant is equivalent 
to its preassigned number, and a variable 
is equivalent to an address in the RAM 
memory, as shown in Table II. 

VOCABULARY creates subgroups of 
instructions in the dictionary as “vocabu¬ 
laries.” When the name of a vocabulary is 


22 


Dr. Dobb’s Journal, Number 64, February 1982 


called, the vocabulary is made the “con¬ 
text vocabulary,” which means it is 
searched first by the interpreter. Normal¬ 
ly the dictionary in a FORTH computer 
is a linearly linked list of instructions. 
VOCABULARY creates branches to this 
trunk dictionary so that the user can 
specify partial searches of the dictionary. 
Each branch is characterized by the end 
of the linked list as a link address. To 
execute an instruction defined by VO¬ 
CABULARY is to store this link address 
into a memory location named CON¬ 
TEXT. Hereafter, the text interpreter will 
first search the dictionary starting at this 
link address in CONTEXT when it re¬ 
ceives an instruction from the input 
stream (e.g., the console terminal). 

Instructions defined by VOCABU¬ 
LARY are used to switch context in 
FORTH. If all instructions were given 
unique names, the text interpeter would 
be able to locate them without any am¬ 
biguity. The problem arises because the 
user might want to use the same names 
for different instructions. This problem is 
especially acute for single character in¬ 
structions, which are favored for instruc¬ 
tions used very often to reduce the typ¬ 
ing chore or to reduce the size of source 
text. The usable ASCII characters are the 
limit of choices. Instructions of related 
functions can be grouped into vocabu¬ 
laries using vocabulary instructions. Con¬ 
text will then be switched conveniently 
from one vocabulary to another. Instruc¬ 
tions with identical names can be used 
unambiguously if they are placed in dif¬ 
ferent vocabularies. 

Creating Defining Instructions 

FORTH is an interpretive language 
with a multitude of interpreters. This is 
the reason why FORTH can afford to 
have such a simple syntax structure. An 
instruction is known to a user only by its 
name. The interpreter which interprets 
the instruction is specified by the instruc¬ 
tion itself, in its code field which points 
to an executable machine instruction rou¬ 
tine. This executable routine is executed 
at run-time and it interprets the informa¬ 
tion contained in the body of the instruc¬ 
tion. Instructions created by one defining 
instruction share the same interpreter. 
The interpreter which interprets high 
level colon instructions is called “address 
interpreter,” because a colon instruction 
is equivalent to a list of addresses. Con¬ 
stants and variables also have their re¬ 
spective interpreters. 


24 


A defining instruction must perform 
two different tasks when it is used to 
define a new user instruction. To create 
a new instruction, the defining instruc¬ 
tion must compile the new instruction 
into the dictionary, constructing the 
name field, link field, and code field — 
which point to the appropriate inter¬ 
preter — and the parameter field, which 
contains pertinent data making up the 
body of this new instruction. The defin¬ 
ing instruction must also contain an inter¬ 
preter, which will execute the new in¬ 
struction at runtime. The address of this 
interpreter is inserted into the code field 
of all user instructions created by this 
defining instruction. The defining instruc¬ 
tion is a combination of a compiler and 
an interpreter in conventional program¬ 
ming terminology. A defining instruction 
constructs new user instructions during 
compilation and executes the instructions 
it created at runtime. Because a user in¬ 
struction uses the code field to point to 
its interpreter, no explicit syntax rule is 
necessary for different types of instruc¬ 
tions. Each instruction can be called di¬ 
rectly by its name. The user does not 
have to supply any more information ex¬ 
cept the names, separated by delimiters. 

The most exciting feature of FORTH 
as a programming language is that it not 
only provides many resident defining 
instructions as compiler-interpreters, but 
also supplies the mechanism for the user 
to define new defining instructions, to 
generate new classes of instructions or 
new data structures tailored to specific 
applications. This unique feature in 
FORTH amounts to the capability of ex¬ 
tending the language by constructing new 
compilers and new interpreters. Normal 
programming activity in FORTH is to 
build new instructions, which is similar to 
writing programs and program modules 
in conventional languages. The capability 
to define new defining instructions is ex¬ 
tensibility at a high level in the FORTH 
language. 4 This unique feature cannot be 
found in any popular programming lan¬ 
guage. 

There are two methods to define a 
new defining instruction as shown in 
Table III. The :-<CREATE-DOES>-; 
construct creates a defining instruction 
with an interpreter defined by high level 
instructions very similar to a structure list 
in a regular colon definition. The inter¬ 
preter structure list is put between 
DOES>and The compilation proce¬ 
dure is contained between <CREATE and 


DOES>. Since the interpreter will be 
used to execute all the instructions creat¬ 
ed by this defining instruction, the inter¬ 
preter is preferably coded in machine 
codes to increase execution speed. This 
is accomplished by the 

:-<CREATE— ;CODE — 

construct. The compilation procedure 
is specified by instructions between 
<CREATE and ;CODE. Data following 
;CODE are compiled as machine code 
which will be used as an interpreter when 
the new instruction defined by this defin¬ 
ing instruction is executed at run-time. 


Conclusion 

Computer programming is a form of 
art, far from being a discipline of science 
or engineering. For a specified program¬ 
ming problem, there are essentially an 
infinite number of solutions, entirely de¬ 
pendent upon the programmer as an arti¬ 
san. However, we can rate a solution by 
its correctness, its memory requirement, 
its execution speed, and other qualities. 
A solution must be correct. For some 
applications, the best solution has 
to be the shortest and fastest. The only 
way to achieve this goal is to use the 
oomputer with an instruction set opti¬ 
mized for the problem. Optimization of 
the computer hardware is clearly imprac¬ 
tical because of the excessive costs. Thus, 
one would have to compromise by using a 
fixed, general purpose instruction set of¬ 
fered by a real computer or a language 
compiler. To solve a problem with a fixed 
instruction set, one has to write programs 
to circumvent the shortcomings of the in¬ 
struction set. 

The solution in FORTH is not a- 
chieved by writing programs, but by 
creating a new instruction set in the 
FORTH virtual computer. The new in¬ 
struction set in essence becomes “the” 
solution to the programming problem. 
This new instruction set can be optimized 
at various levels for memory space and 
for execution speed, including hardware 
optimization. FORTH allows us to sur¬ 
pass the fundamental limitation of any 
computer, which is the limited and fixed 
instruction set. This limitation is also 
shared by conventional programming lan¬ 
guages, though at a higher and more ab¬ 
stract level. 


Dr. Dobb’s Journal, Number 64, February 1982 

"67 





FORTH as a programming language 
allows programmers to be more creative 
and productive because it enables them to 
mold a virtual computer with an instruc¬ 
tion set best suited for the problems at 
hand. In this sense, FORTH is a revolu¬ 
tionary development in computer science 
and technology. 


References 

1. Moore, C. H„ “FORTH: A New Way 
to Program in Minicomputer,” Astron. 
Astrophys. Suppl. 15, pp. 497-511, 
(1974). 

2. “FORTH-79: A Publication of the 
FORTH Standards Team,” FORTH 
Interest Group, P. O. Box 1105, San 
Carlos, CA (1980). 

3. Main, R. B., “FORTH vs. Assembly,” 
FORTH Dimensions 1, 33 (1978). 

4. Harris, K., “FORTH Extensibility,” 

BYTE, 5, ,(1980). 


(See pages 28 - 30 for tables) 


Dr. Dobb’s Journal, Number 64, February 1982 
" 68 " 


27 



Formal Definition of FORTH as a Programming Language 
(Tables I, II, and III) 


Table I 


LANGUAGE DEFINITION OF FORTH 


laracter> 


• AC13. code 


!del i mi ting character'- ::= NUL ! CR ! SP ! (designated character) 
■ delimiter> :s -- (delim11ing character > ! 

<de 11 mi. t :i. n <3 ch ar act.er >< del iiruter > 


word) ::= (instruction> ! (number) ! (string) 

s t r 1 n g > s : •- < c h a r a c t e r > I < c h a r a c t e r > < s t. r :i n g ) 
number) s s- (integer) ! —(integer > 
i n t e g e r > : : •= < d i g i t > i (d i g i t > < i n t e g e r > 
d i g i t) : : = 0 ! 1 12! ... ! 9 ! A ! E ! ... 


base. 1 ;■ 


instruction) s — (standard instruction) ! (user instruction) 

standard instruction) :s = (nucleus instruction) ! 

< i n t e r p r e t. er i 11 s t r u c t: i on > I 

< c o m p i 1 er i n s t; r u. c t i o n > ! < d e v ice i n s t r u c t i o n ) 


;nucleus instruction) s : ~ ! I # I %/ ! #/MOD I ! +•! ! I — DUP ! ) 


/MOD ! 0 ! 0-- I 0) ! 1+ ! 1 
ABB ! AND ! C! ! C3 ! CMOVE 
EXECUTE ! EXIT ! FILL ! MAX 
OVER I R) ! RQ i ROT ! SWAP 


i 2 + : 2 : ( : = : > 1 )R 1 ® 1 
D+ : D: ! DNEGATE ! DROP ! DUP ! 

MIN I MOD ! MOVE ! NEGATE ! NOT ! OR 
U# ! U/MOD I U( i XOR 


interpreter instruction > s 2 -- # ! #) ! i " ! ( ! -TRAILING) ! .. I (# ! 

) IN ! ? ! ABORT ! BASE ! ! CONTEXT S CONVERT ! COUNT ! CURRENT 

DECIMAL ! EXPECT ! FIND ! FORTH ! HERE i HOLD ! NUMBER ! PAD I 
QUERY : QUIT ! SIGN ! SPACE ! SPACES I TYPE 1 U. ! WORD 

‘compiler instruction; +-L.00P ! , ! . " i : ! ; ! ALLOT ! BEGIN ! 

COMPILE I CONSTANT ! CREATE ! DEFINITIONS I DO ! DOES': ! ELSE ! 
FORGET ! I ! IF ! IMMEDIATE ! J ! LEAVE i LITERAL ! 

LOOP ! REPEAT : THEN ! UNTIL ! VARIABLE ! VOCABULARY ! WHILE ! 
t ! [COMPILE3 1 I 

:device instruction) s:= BLOCK ! BUFFER ! CR ! EMIT ! EMPTY-BUFFERS I 
FLUSH ! KEY ! LIST ! LOAD ! SCR ! UPDATE 


!user instruction)- (colon instruction> ! 

coi '1 stant ;■ ! -.variable.--- ! vocafcu 1 arv 


: : a d e .1 n s t. r u c 1 .1 o n ) I 


Dr. Dobb’s Journal, Number 64, l-ebruary 1982 

"69" 














Table II 


USER INSTRUCTIONS 


The statement in parenthesis is according to the FORTH syntax. 


COLON INSTRUCTION 

< c o 1 o n i n s t r u c t. i o n > : : ~ < s t. r u c t u r e list > 

: (colon instruction;:- < structure 1 i st > ; ) 

< st r uc t. ure 1 i st > : s - < s t. r uc t ur e < deli m i t er ) ! 

<str ucture><de1im 1 1er ><structure list> 

< structure.':- : : == (word; 1 (if.else---then; I <begin—unti 1 > ! 

<begi n—whi 1 e-repeat; > ! <do~loop> 

< i -f el se-then ; : s = I F<del i mi ter >< structure 1 i st) THEM 

IF -.del i mi ter ; < structure 1 i st >ELSE<del i mi ter )< structure list THEN 
<begin - - un ti1> ::- BEGIN<d eIim 1 1er)<strue t ur e 1ist ; UNTIL 
Cbegi n -whi 1 e—repeat, s : = 

BEGIN delimi ter <structure 1ist>WHILE<de1imi ter. <structure list(REPEAT 

<do-loop structure; <structure) I 1 i J I LEAVE 

•(do loop structure list)- : : = (do-loop structure) (del i mi ter > ! 

< d o -1. o o p s t r u cture; . d el i m i t e r > < do-lo o p s t r u c: t u r e 1 i s t. > 

<do loop) s : * DO (del i mi ter (do.loop structure list )L.QOP ! 

DO (del i mi ter ><do-1 oop structure 1 1 st ■ H..OGP 

CODE INSTRUCTION 

(code instruction) ::= (assembly code list) 

CODE (code instruction) assembly code list: ) 

(assembly code list ) (assembly code) (del i mi ter )• ! 

•. as semb 1 y c: ode ( < de 1 i m 1 1. er >< assembl y code 1 1 st 
(assembly code; :s = (number ; < delimi ter >, ! < number X deli miter)C, 

CONSTANT INSTRIJCTI ON 
* constant) s:= (number. 

(number) CONSTANT (constant) > 

VARIABLE INSTRUCTION 
<v ari able) :s = < addre ss) 

VAR1ABLE C variab1e > ) 

<’adclress) s : = -(integer )• 

VOCABULARY INSTRUCTION 
<context vocabulary) ::= <vocabu1 ary> 

VOCABULARY (vocabulary) ) 


(Table III on next page) 


Dr. Dobb’s Journal, Number 64, February 1982 

To" 


29 



Table III 


CRI 

LEA' 

riNG 

Nl 

EW DEFINING 1 

NSTRUCTIDNS 






< h 

igi 

h.1. e 

V 0 

1 d 65 f i n i n q i n 

struction> 

n : 

= 







CR 

IE ATE < del i mi te 

r >< compiIer 

s 

tructure 

1 X 

st 

■i DOES> < de 1 l mi t < 




< i 

nterpreter st 

ructure lis 

t > 





5 


l"i i q h 

-I 

revel de f :i. n i rig 

:i nstructi o 

n > 

CREATE 

r st 

rue 

ture list DOES> 





truelure list 

> ; > 






<i 

QW 

.lev 

el 

clef i ni ng i ns 

traction > ; 

'*■ 








CR 

E A T E < d e 3. i m 1 1 e 

r ><compi1er 

S 

tructure 

3 i 

st :• 

;CODEEdelimi ter 




< i 

n t e r p r e t e r a s 

semb.1 y code 

1 

i st > 




: 


1 aw- 

■ 1 e 

v 651 defining 

instruction 


CREATE < 

str 

UC t 

ure list > ;CODE 




< L 

n t e r p r • e t e r a s 

semb1y code 

1 

i st > ) 




\ c 

Dili 

p 11 e 

-r 

structure 1is 

t> : := str 

uc 

ture 1 i s 

t > 



< i 

n t 

er pr 

et. 

er structure 

1 i st > : ; - < 

st 

r uct.ur e 

3 i s 

t > 


< i. 

nt 

erpr 

et 

er assembly c 

ode 3. i st 2 

a 

ci.SSOiTib 

i y 

cod 

le list > 


30 


Dr. Dobb’s Journal, Number 64, l ebruary 1982 

TT 






FORTH 8086 Assembler 

(Listing, text begins on page 14) 

Screen # 6 

0 ( Error messages for 8086 Assembler ) 

1 16 bit register not allowed 

2 8 bit register not allowed 

3 address out of range 

4 immediate data value not allowed 

5 missing source register 

6 missing destination register 

7 illegal operation 

8 illegal operand 

9 instruction not implemented 

10 illegal destination register 

11 illegal source register 

12 illegal condition code 

13 register mismatch 

14 destination address missing 

15 


Screen # 7 

0 < 8086 Assembler - variables ) 

1 

2 VOCABULARY ASSEMBLER IMMEDIATE ASSEMBLER DEFINITIONS HEX 

3 


4 

0 

VARIABLE 

<#> 

< immediate data flag ) 


5 

0 

VARIABLE 

■■-'TDD 

< destination addressing 

type ) 

6 

0 

VARIABLE 

<TS> 

( source addressing type 

) 

7 

0 

VARIABLE 

<RD> 

< destination register ) 


8 

0 

VARIABLE 

<RS> 

< source register ) 


9 

0 

VARIABLE 

<W> 

( word/byte flag ) 


10 

0 

VARIABLE 

cwd> 

< destination word/byte 

flag ) 

11 

0 

VARIABLE 

<0D> 

< destination offset ) 


12 

0 

VARIABLE 

<0S> 

< source offset ) 


13 

0 

VARIABLE 

<D> 

< direction flag for R/M 

) 

14 

0 

VARIABLE 

<SP> 

( local stack pointer ) 


15 

— 

-> 





Screen # 8 

0 < 8086 Assembler - CASE statement ) 

1 

2 < CASE statement by Charles E Eaker > 

3 ( from FORTH Dimensions- Volume II- No 3- page 37 ) 

4 


5 

: CASE 

?COMP CSP @ 'CSP 4 ; 

IMMEDIATE 

6 

OF 

4 7PAIRS COMPILE OVER COMPILE 

- 

"7 

/ 


COMPILE OBRANCH HERE 0 - 


8 


COMPILE DROP 5 ; 

IMMEDIATE 

9 

ENDOF 

5 7PAIRS COMPILE BRANCH HERE 

0 , 

10 


SWAP 2 [COMPILE! ENDIF 4 > 

IMMEDIATE 

1 1 

: ENDCASE 

4 7PAIRS COMPILE DROP 


12 


BEGIN SP@ CSP @ = 0= 


13 


WHILE 2 [COMPILED ENDIF 


14 


REPEAT CSP ! ; 

IMMEDIATE 

15 

—> 


(Continued on next page) 


Dr. Dobb’s Journal, Number 64, February 1982 
~72 


33 



FORTH 8086 Assembler 

(Listing continued, text begins on page 14) 


Screen # 9 

0 ( 8086 Assembler - miscellaneous primitives ) 

1 

2 < save the current stack pointer as base of local stack > 

3 : !<SP> SP@ <SP> 1 ; 

4 (. return number of items on local stack > 

5 ?<sp:- <SP> @ SPA - 2 - 2 / i 

6 

7 < these redefinitions for error printing prevent ) 

8 ( printing of garbage from HERE after assembly has begun ) 

9 

10 < print error message ) 

11 ERROR " ? " MESSAGE SPI QUIT , 

12 < conditionally print error message ) 

13 ''ERROR SWAP IF ERROR ELSE DROP END IF 

14 —> 

15 


Screen # 10 

0 < 8086 Assembler - destination register processing ) 

1 


3 

4 

5 

6 

8 
9 
10 
1 1 
12 

13 

14 

15 


DREG CEUILDS C, C, C, 

DCES> 

DUP C@ DUP OFF = 

IF DROP ELSE DUP <W> 
1+ DUP C@ <TD> ! 

1+ C« <RD> ! 

<#> @ 24 7ERR0F 

<td> e 4 = 

IF ?<SP> o > 

IF <0D> ! END IF 
END IF 


( store input parameters .< 

< word/byte flag > 

' <WD> ' ENDIF 

< addressing type ) 

( set register code ) 

< illegal immediate data ) 
( indexed addressing'' ) 

( yes. any displacement-' > 

< save displacement ) 


Screen # 11 

0 < 8086 Assembler - source register processing ) 

1 

2 SREG <BUILDS C. C. C. < store input parameters 

3 DOES> 


4 

5 

6 

7 

8 
9 

10 
1 1 
12 

13 

14 

15 


DUP C@ DUP OFF = 

IF DROP ELSE <W> 1 
1+ DUP C@ <TS> 1 
1+ CS <RS> 1 
<TS> 0 4 = 

if ?<sp> o : 

IF <0S> 1 ENDIF 
END IF 


( word/byte flag ) 

END IF 

( addressing type ) 

< set register code ) 

< indexed addressing? ) 

< yes. any displacement? 

< save displacement ) 


) 


) 


34 


Dr. Dobb’s Journal, Number 64, February 1982 

13 




source register definitions > 


Scr p on # 12 

0 < 8086 Assembler - 

1 


2 ( re g type 


4 o 

5 1 

6 2 

7 3 

8 4 

9 5 
10 6 

11 7 

12 —> 

13 

14 
1 5 


o 

r._ 

o 

o. 

p 

n 

tz 

p 


U) 


o 

0 

0 

0 

o 

0 

o 

0 


SR EG 

name 

AL 

SREG 

CL 

SR EG 

DL. 

SREG 

BL 

SREG 

AH 

SREG 

CH 

SREG 

DH 

SREG 

BH 


Screen # 13 

0 < 8086 Assembler - 


T'eg t y p e 


UJ 


4 0 3 

5 1 3 

6 2 3 

7 3 3 

8 4 3 

9 5 3 

10 6 3 

1 1 7 3 

12 — > 

13 

14 

15 


1 

1 

1 

1 

l 

1 

1 

1 

1 


source register definitions ) 



name 

SREG 

AX 

SREG 

CX 

SREG 

DX 

SPEC 

ex 

SREG 

SP 

SREG 

BP 

SREG 

SI 

SREG 

DI 


Screen # 14 

? k 8086 Assembler - source register definitions ) 


2 i r e q 

type 

w 


3 0 

4 

-1 

SREG 

4 0 

4 

-1 

SREG 

5 1 

4 

-1 

SREG 

6 1 

4 

-1 

SREG 

'7 

/ Cn 

4 

- 1 

SREG 

8 2 

4 

-1 

SREG 

9 3 

4 

-1 

SREG 

10 3 

4 

-1 

SREG 

1 1 4 

4 

-1 

SREG 

12 5 

4 

-1 

SREG 

13 6 

4 

-1 

SREG 

14 7 

15 — > 

4 

_ 1 

JL 

SREG 


name 3 
CB X+SI3 
CSI+BX3 
CBX+DI3 
CDI+BX3 
CBP+SI 3 
CSI+BP3 
CBP+DI3 
CDI+BP3 
CSI 3 
CDI 3 
[ BP 3 
COX 3 

(Continued on next page) 


Dr. Dobb’s Journal, Number 64, February 1982 
74 


35 


FORTH 8086 Assembler 

(Listing continued, text begins on page 14) 

Screen # 15 

0 < 8086 Assembler - segment register definitions ) 

1 


2 ( r eg 

3 

type 

UJ 


name 

4 0 

«=; 

-1 

SREG 

ES 

5 1 

5 

-1 

SREG 

CS 

6 2 

5 

-1 

SREG 

SS 

7 3 

8 

5 

-1 

SREG 

DS 

9 0 

5 

-1 

DREG 

ES, 

10 1 

5 

-1 

DREG 

CS, 

11 2 

5 

-1 

DREG 

SS, 

12 3 

13 —> 

14 

15 

5 

-1 

DREG 

DS, 


Screen # 16 

0 < 8086 Assembler - destination register definitions ) 

1 


2 ( r e g 

3 

type 

UJ 


name 

4 0 

n 

CL. 

0 

DREG 

AL, 

5 1 

n 

CL. 

0 

DREG 

CL, 

6 2 

n 

CL. 

0 

DREG 

DL, 

7 3 

n 

0 

DREG 

3L, 

8 4 

n 

CL. 

0 

DREG 

AH, 

9 5 

n 

CL. 

0 

DREG 

CH, 

10 6 

n 

0 

DREG 

DH, 

11 7 

12 —> 

13 

14 

15 

2 

0 

DREG 

BH, 


Screen # 17 

0 < 8086 Assembler - destination register definitions ) 

1 


2 ( r e g 

3 

type 

UJ 


name ) 

4 0 

3 

1 

DREG 

AX, 

5 1 

3 

1 

DREG 

CX, 

6 2 

n 

1 

DREG 

DX, 

7 3 

75 

.1 

DREG 

BX, 

8 4 

75 

1 

DREG 

SP, 

9 5 

7) 

1 

L 

DREG 

BP, 

10 6 

3 

1 

DREG 

SI, 

11 7 

12 —> 

13 

14 

15 

3 

1 

X 

DREG 

DI, 


36 


Dr. Dobb’s Journal, Number 64, lxbruary 1982 

75" 




destination register definitions 


Screen # 18 

0 ( 8086 Assembler - 

1 


2 ( reg 

type 

w 


name ) 

3 0 

4 

-1 

DREG 

CBX+SI3. 

4 0 

4 

-1 

DREG 

CSI+BX3.. 

5 1 

4 

-1 

DREG 

CBXtDU, 

6 1 

4 

-1 

DREG 

CDI+BX3. 

-r n 

f e_ 

4 

-1 

DREG 

C BP+SI1, 

O 

'—i e- 

4 

-1 

DREG 

CSI+BP.l,. 

9 3 

4 

-1 

DREG 

CBP+DI 3, 

10 3 

4 

-1 

DREG 

CDI+BP3.. 

11 4 

4 

-1 

DREG 

C SI 3 , 

12 5 

4 

-1 

DREG 

lDI 1, 

i 

X -1 

4 

-1 

DREG 

cep:.- 

14 7 

4 

-1 

DREG 

C B X 3, 


15 --> 


) 


Screen # 19 


0 

• 8086 

Assembler - miscellaneous 

1 

?W 

<W> a , 

—> 

c- 

?TD 

CTD> a ; 

o 

_f 

~‘7S 

<TS> a ; 

4 

?RD 

:pd> a , 

5 

*'RS 

<fs> a • 

6 

?OD 

cod> a •, 

"7 

■'OS 

;:os> a , 

8 

+ D 

<d> a 2 * + i 

9 

+W 

<w> a + > 

10 

+RD 

<rd> a + ■, 

1 1 

+RS 

<rs> a + 

12 

MOD 1 

3F AND 040 OR ; 

13 

M0D2 

3F AND 080 OR ; 

14 

MCD3 

3F AND 0C0 OR ■ 

15 

— > 



operators ) 

' fetch u) ord/'byte f .1 a a ) 

< fetch d e s t a d d r type ) 
( source addr type ) 

>. dest register code ) 

( source register code ) 

< dest displacement ) 

> source displacement ) 

< merge direction flag ) 
v merge word/byte flag ) 
v merge dest reg code 

( merge source reg. code 
( set, mod field to 01 ) 

( set mod field to 10 ) 

( set mod field to it ) 


) 


0 ( 8086 Assembler - miscellaneous operators ) 

1 

2 < equates to addressing modes > 

3 0 CONSTANT DIRECT 3 CONSTANT REG 16 

4 1 CONSTANT I TIMED 4 CONSTANT INDEXED 

5 2 CONSTANT REG 8 5 CONSTANT SEGREG 

6 

7 ( initialize all variables and flags > 


8 

RESET 

0 <#> ' 0 <W> ' 

0 <os> 

1 0 <CRD> ! 

9 


0 <TD> 1 0 <TS> 1 

0 <0D> 

! !<SP> 

10 


0 <D> ' 0 <WD> ! 

0 <RS> 

! 

1 1 

C mitiali 

z e direction pointer for 

mem/reg 

instructions ) 

12 

. DSET 

?TS INDEXED = <D> 

t 


13 

( set t h e 

direction flag true ) 



14 

: Dt 

1 <D> : , 



15 

—> 



fContinued on next page) 


Dr. Dobb’s Journal, Number 64, Tcbruary 1982 

W 


37 





FORTH 8086 Assembler 

(Listing continued, text begins on page 14) 


Screen # 21 

0 < 8086 Assembler - miscellaneous operators ) 

1 ( calculate and store relative offset for branches and loops ) 

2 ( issue error message if target out of addressing range ) 

3 OFFSETS, HERE 1+ - DUP AI3S 07F > 23 TERROR C, ; 

4 ( calculate and store 16 bit offset for JNP and CALL ) 

5 : OFFSET16, HERE 2+ ~ , 


6 ( calculate and store displacement for mem/reg instructions > 


7 DI SP, 

<D> @ IF ?0S ELSE ~0D ENDIF DUP 

( get displ 

8 

IF DUP ABS 07F > 

< check size 

9 

IF SWAP M0D2 C, , 

( two bytes ) 

10 

ELSE SWAP NODI C, C, ENDIF 

( one byte ) 

1 1 

ELSE DROP DUP 7 AND 6 = 

( no displ ) 

12 

IF NODI C, 0 C, 

( except CBP3 

13 

ELSE C, END IF 

( a 1ways gets 

14 

ENDIF i 

< 1 byte ) 

15 — > 




Screen # 22 

0 ( 3086 Assembler - instruction processing, groups 1-3 ) 

1 

2 ( single byte instructions without operands > 

3 INI C3UILDS C. 

4 DQES> C@ C, RESET ; 

5 

6 ( conditional jumps and loops, 1 bute + offset ) 

7 2NI CBUILDS C- 

8 DOES> C® C, OFFSETS, RESET ; 

<=> 

10 ( string instructions ) 

11 3NI CBUILDS C, 

12 does:- ce +w c, reset , 

13 — > 

14 

15 


Screen # 23 

0 < 8086 Assembler - instruction processing, group 4 ) 

1 

2 ( register PUSH and POP > 

3 . 4MI CBUILDS C, C, 

4 DOES> 

5 ?TS v operand type ) 

6 CASE 

7 REGlo OF 1+ C@ +RS C, ENDOF < usual 16 bit reg) 

8 SEGREG OF C<? ?RS 8 * + C, ENDOF ( segment reg ) 

9 28 ERROR < illegal operand ) 

10 ENDCASE RESET ; 

11 —> 

12 

13 

14 

15 


38 


Dr. Dobb’s Journal, Number 64, l ebruary 1 982 

77 




instruction processing, group 5 ) 


Screen # 24 

0 ( 8086 Assembler - 


4 

5 

6 

-> 

r 

e 

9 
10 
i l 
12 

13 

14 

15 


( 

( 


inst-rasegment JMP and CALL, 16 bit offset or reg/mem ) 
intersegment long JMPs and the short JMP are not supported ) 
5MI CBUILDS C, C, 

DCES> 

V T'S < operand type ) 

CASE 


DIRECT OR 1+ C<? C, OFFSET 16, 

REG 16 OF OFF C, C@ M0D3 +RS C, 
INDEXED OF DSET OFF C, C<£ +RS DISP, 
28 ERROR 
ENDCASE RESET , 


ENDOF < disp 16 ) 
ENDOF < via r e g > 
ENDOF ( indexed ) 

( illegal operand) 


Screen # 25 

0 ( 8086 Assembler - instruction processing, group 6 ) 

1 


-I 

e_ 

'3 

4 

5 

6 

7 

8 
9 

10 
1 1 
12 
13 


IN and OUT > 

6 MI <BUILDS C, C, 
DOES> 

DUP C@ 2 AND 
IF ?TD ?TS 
ELSE ?TS ?TD 
END IF 

REG 16 = <W> ' 

REG 16 = 

IF 1+ C@ +W C, 
ELSE C@ +W C, C, 
ENDIF RESET ; 


< IN or OUT" ) 

( if true is OUT instr ) 
( get operand types ) 

< TOS = data width ) 

( NOS = port addr type ) 

< set word/byte transfer 

< check if register- addr 
( via DX ) 

( via inline port # ) 


14 


15 


) 

) 


Screen # 26 

0 ( 8086 Assembler - instruction processing, group 7 ) 

1 


4 

5 

6 

~7 

f 

8 

9 

10 
11 
12 

13 

14 

15 


( ADC, 
7MI 


ADD, AND, CMP, OR, SBB, SUB, and XOR ) 

•CBUI LDS C, C , C, 

DOES> 

?TS IMMED = ( source = immediate data ) 

IF 1+ DUP 1+ C@ +W C, 

"’TD CASE < check dest type ) 

REG8 OF C@ M0D3 +RD C, C, ENDOF 

REG16 OF C@ M0D3 +RD C, , ENDOF 

INDEXED OF DSET C@ -*-RD DISP. 

?W IF , ELSE C, END IF ENDOF 
28 ERROR ENDCASE 

ELSE DSET C@ +D +W C, ( source = reg/mem ) 

?TD CASE. < check dest type ) 


(Continued on next page) 


Dr. Dobb’s Journal, Number 64,1-cbruary 1982 
78" 


39 


FORTH 8086 Assembler 

(Listing continued, text begins on page 14) 


Screen 
0 ( £ 
1 
2 

3 

4 

5 

6 

7 

8 
9 

10 
11 
12 

13 

14 

15 —: 


8086 Assembler - instruction processing, group 7 cont ) 


REG8 OF ?TS CASE 

REG8 OF ?RS 8 


+RD M0D3 


INDEXED OF ?RD 8 * +RS 
28 ERROR ENDCASE 
REG 16 OF ?TS CASE 

REG16 OF ?RS 8 * +RD M0D3 C, 
INDEXED OF ?RD 8 * +RS DISP, 
28 ERROR ENDCASE 
INDEXED OF ?TS CASE 

REG8 OF ?RS 8 * +RD DI 
REG16 OF ?RS 8 * +RD DI 
28 ERROR ENDCASE 
28 ERROR ENDCASE ENDIF RESET 


+RS DISP, ENDOF 


+RD DISP, 
+RD DISP, 


( 8 bit dest. reg ) 
ENDOF < 8 bit source) 
, ENDOF ( indexed s. > 
ENDOF 

( 16 bit dest. reg ) 

, ENDOF ( 16 bit 5. ) 

', ENDOF ( indexed s. ) 
ENDOF 

( indexed dest. ) 

ENDOF ( 8 bit source ) 
ENDOF < 16 bit source 

ENDOF 


Sere 

O 

1 


en # 28 

( 8086 Assembler - 


— instruction processing, group 8 ) 


DIV, IDIV, IMUL., MUL, NEG, and NOT 
SMI CBUILDS C, C, 

DOES> 

DUP 1+ C® +W C, 

•’TS 
CASE 

REG8 OF C® +RS M0D3 
REG 16 OF C® +RS M0D3 
INDEXED OF DSET C® +RS 
28 ERROR ( direct, imm 
ENDCASE RESET ; 


0D3 C, 

0D3 C, 

+RS DISP, 
immediate, 


< operand type 

ENDOF ( 8 bit reg ) 

ENDOF ( 16 bit reg > 

ENDOF ( indexed ) 


segment 


i 11 e g a 1 


Screen # 29 

0 ( 8086 Assembler - 


— instruction processing, group 9 ) 


< various shift instructions ) 


CBUILDS C, 
DOES> 

DUP 1-f C@ '■ 
■^TS 1 > IF 
?TD CASE 
REG8 OF 
REG16 OF 
INDEXED OF 
28 ERROR ( 
ENDCASE 
?TS 2 < IF 


;• @ + 

- ENDIF C, 

C® M0D3 +RD 
C® M0D3 +RD 
DSET C® +RD 


ujord/byte flag ) 
shift 1 or c ount 
operand to be sh 
ENDOF ( 8 b 
ENDOF ( 16 


nt in CL? 
shifted ) 


DISP, 


direct, immediate, 


DROP ENDIF RESET 


ENDOF < 

* segment 

< clean i 


8 bit reg ) 
16 bit reg 
indexed ) 
reg illegal 


stack 


Dr. Dobb’s Journal, Number 64, February 1 982 

79 




Screen # 30 

0 ( 8086 Assembler - instruction processing, group 10 ) 

1 

2 < 2 byte simple instructions without operands ) 

3 

4 : 10MI <BUILDS C, C, 

5 DOES> DUP C@ SWAP 1 + C@ C, C, RESET , 

6 — > 

"7 

/ 

8 
9 
10 
1 1 
12 

13 

14 

15 


Screen # 31 

0 < 8086 Assembler - instruction processing, group 11 ) 

1 

2 ( INC and DEC instructions ) 

3 11 MI CBUILDS C, C, 

4 DOES> 

5 3TS CASE ( operand type ) 

6 REGS OF OFE C, 1+ C(? M0D3 +RS C, ENDOF ( 8 bit req ) 

7 REG16 OF C@ +RS C, ENDOF ( 16 bit reg ) 

8 INDEXED OF DSET OFE +W C, 

1+ C(? +RS DISP, ENDOF ( indexed ) 

10 28 ERROR ( direct, immediate, or segment reg illegal ) 

11 ENDCASE RESET , 

12 —> 

13 

14 

15 


Screen # 32 

0 < 8086 Assembler - instruction processing, group 12 ) 

1 ( MOV instructions reg/reg, reg/mem, or reg/immediate ) 

2 : 12MI CBUILDS 

3 DOES> DROP DSET ?TD 

4 CASE 

5 DIRECT OF '^TS CASE ( destination = memory direct ) 

6 ( source = 8 bit general register ) 

7 PEG8 OF ?RS IF 088 C, ?RS 8 * 6 + C, , < reg ) 

8 ELSE 0A2 +W C, , ENDIF ENDOF ( acc ) 


9 
10 
1 1 
12 

13 

14 

15 


< source = 16 bit general register ) 

REG16 OF ?RS IF 089 C, '^RS 8 * 6 + C, , < reg ) 

ELSE 0A2 +W C, , ENDIF ENDOF i acc ) 

( source = segment register ) 

SEGREG OF 08C C, ?RS 8 * 6 + C, , ENDOF 
28 ERROR ENDCASE ENDOF 

(Continued on next page) 


Dr. Dobb’s Journal, Number 64, February 1982 

lo" 


41 


FORTH 8086 Assembler 

(Listing continued, text begins on page 14) 


Scree 
0 ( 

1 

2 

3 

4 

5 

6 
f 

8 

9 

10 
1 1 
12 

13 

14 - 

15 


# 33 

8086 Assembler - instruction processing, group 12 cont ) 

REG 8 OF ?TS CASE ( destination = 8 bit general reg ) 

< source = memory direct ) 

DIRECT OF ?RD IF 08A C, ?RD 8 * 6 + C, , 

ELSE OAO +W C.. , END IF ENDOF 
( source = immediate data ) 

INNED OF OBO +RD C, C, ENDOF 
( source = 8 bit general reg ) 

REG 8 OF Dt 88 +D C, "'RD 8 * +RS NODS C, ENDOF 
REG 16 OF 2D ERROR ENDOF 
( source = indexed address ? 

INDEXED OF 88 +D +W C.- "'RD 8 * +RS DISP, ENDOF 
28 ERROR ENDCASE ENDOF 


Screen # 34 

0 < 8086 Assembler - instruction processing, group 12 cont. ) 

1 REG16 OF "•’TS CASE < destination = 16 bit general reg ) 

2 ( source = memory direct) 

3 DIRECT OF ?RD IF 08B C, ?RD 8 * 6 + C, , 

4 ELSE OAO +W C, . ENDIF ENDOF 

5 ( source = immediate data ) 


6 

y 

8 

9 

10 
11 
12 

13 

14 

15 


INNED OF 0B8 +RD C, , ENDOF 
( source = 16 bit general reg ) 

REG 16 OF Dt 88 +W +D C, 

' 7 RD S * +RS M0D3 C, ENDOF 
( source = indexed address ) 

INDEXED OF 88 *D +W C, ?RD 8 * +RS DISP, ENDOF 
< source = segment register ) 

SEGREG OF 8 C C, ?RS S"* +RD N0D3 C, ENDOF 
28 ERROR ENDCASE ENDOF 


Screen # 35 

0 < 8086 Assembler - instruction processing, group 12 cont. ) 

1 

2 INDEXED OF ?TS CASE ( destination = indexed address ) 

3 < source = immediate data ) 

a INNED OF 0C6 +W C, ?RD DISP, 

5 ?W IF , ELSE C. ENDIF ENDOF 

6 (source =8 bit general reg ) 

7 REG 8 OF 88 +D +W C, ?RS 8 *~+RD DISP, ENDOF 

8 (source =16 bit general reg ) 

9 REG 16 OF 88 +D +W C, ?RS 8 * +RD DISP, ENDOF 

10 ( source = segment register ) 

11 SEGREG OF OSC C, ?RS 8 * +RD DISP, ENDOF 

12 28 ERROR ENDCASE ENDOF 

13 —> 

14 

15 


42 


Dr. Dobb's Journal, Number 64, February 1982 

IT 





Screen # 36 

0 ( 8086 Assembler 

1 

X 

2 SEGREG OF 


' - instruction processing, group 12 cent. 

?TS CASE ( destination = segment register ) 
( source — memory direct ) 

DIRECT OF OSE C. ?RD 8 * 6 + C, , ENDQF 
( source = 16 bit general register ) 

REG 16 OF 08E C, ?RD 8 * +RS M0D3 C, ENDOF 
( source — indexed addressing > 

INDEXED OF 08E C, ?RD 8 * +RS DISP, ENDOF 
28 ERROR ENDCASE ENDOF 


28 ERROR ( illegal destination types ) 
ENDCASE RESET , 


Screen # 37 

0 < 8086 Assembler - 


— instruction processing, group 13 


XCHG instructions ) 

13MI CBUILDS 

DOES> DROP DSET ?TD 
CASE 

< if missing des*t reg 
DIRECT OF ?TS REG16 = 
IF 90 + RS C, 

( exchange of 8 bit r 
REGS OF 86 +W C.. ?TS 
REG8 OF ?R 


destination type'? 


assume 


IF 90 +RS C, ELSE 28 ERROR END IF 
ge of 8 bit register with req or 
86 +W C, ?TS CASE. ( source type 
REG8 OF ?RD 8 * +RS M0D3 C, E 
INDEXED OF ?RD 8 * +RS DISP- END 
28 ERROR ENDCASE ENDOF 


ERROR 
with i 


ENDOF 
memory > 
> ) 


ENDOF 

ENDOF 


Scresr; 
0 ( 

1 


# 38 

3086 Assembler - instruction processing, group 13 cont ) 

i exchange 16 bit- register with register or memory ) 
REG16 OF 86 +W C, ?TS CASE 

PEG16 OF 7RD 8 * +RS M0D3 C, ENDOF 
INDEXED OF ?RD 8 * +RS DISP, ENDOF 
28 ERROR ENDCASE ENDOF 

28 ERROR ENDCASE RESET , 


(Continued on next page) 


Dr. Dobb's Journal, Number 64, I'cbruary 1982 
~B2 


43 


FORTH 8086 Assembler 

(Listing continued, text begins on page 14) 

Screen # 39 

0 < 8086 Assembler - instruction processing, group 14 ) 

1 < special routine for TEST instruction ) 

2 14MI CBUILDS DOES: DROP ?TS CASE 

3 DIRECT OF 28 ERROR ENDOF < direct ad dr illegal ) 

4 IMMED OF 0F6 rw C, ?TD CASE < immediate TEST data ) 

5 REGS OF ?RD MODS C, ?W IF , ELSE C, ENDIF ENDOF 

6 REG 16 OF -RD MODS C, ?W IF , ELSE C, ENDIF ENDOF 

7 INDEXED OF -•‘PD DISP, ?W IF . EL SE C, END IF ENDOF 

8 28 ERROR ENDCASE ENDOF 

9 SEGPEG OF 28 ERROR ENDOF ( segment reg illegal ) 

10 ?TD REGS I ?TD REG 16 > OR 28 TERROR < other illegals ) 

11 84 +W C, ?RD 8 * +RS ( TEST reg with reg/mem ) 

12 ?TS INDEXED 0 IF M0D3 C, ( source = general reg ) 

13 ELSE DISP, END IF ( source = indexed ) 

14 ENDCASE RESET , 

15 —> 


Screen # 40 

0 ( S086 Assembler - instruction definitions ) 

1 


2 

r>~7 



1 M I 

AAA 

80 

38 38 

7MI 

CMP 

n 

-j 

D5 

OA 


10 MI 

AAD 

A6 


3MI 

CMP 3 

4 

D4 

OA 


10 MI 

AAM 

'?<? 


1 MI 

CWD 

5 

3F 



1 MI 

AAS 

27 


1 MI 

DAA 

6 

80 

10 

1 0 

I 

ADC 

2 F 


IMI 

DAS 

■y 

SO 

00 

00 

7MI 

ADD 

08 

43 

1 IMI 

DEC 

o 

•_j 

80 

20 

20 

7MI 

AND 

F6 

30 

3MI 

DIV 

9 

E8 

10 


5MI 

CALL 




< ESC ) 

10 

98 



1 M I 

CEW 

FA 


IMI 

HLT 

1 1 

F 8 



1 MI 

CLC 

F6 

38 

8 MI 

IDIV 

12 

FC 



1 MI 

CLD 

F6 

28 

SMI 

IMUL 

13 

FA 



1MI 

CLI 

EC- 

E4 

6 MI 

IN 

3 4 

F5 



1 MI 

CMC 

00 

40 

1 IMI 

INC 


15 — > 


Screen # 41 

0 ( 8086 Assembler - instruction definitions ) 

1 


c. 



( I NT ) 

E9 20 

5MI 

JMP 

"3 
•—/ 

CE 

IMI 

INTO 

76 

2MI 

•JNA 

4 

CF 

IMI 

IRE T 

72 

2MI 

JNAE 

5 

/ t 

2MI 

JA 

7 J 

2MI 

JNB 

6 

73 

2MI 

JAE 

77 

2MI 

JNBE 

/ 

' c_ 

2MI 

JB 

75 

2MI 

JNE 

8 

76 

2MI 

JBE 

7E 

2MI 

JNG 

9 

E3 

2MI 

JC X Z 

7 C 

2M1 

JNGE 

10 

74 

2MI 

JE 

7D 

2MI 

JNL. 

1 1 

7F 

2MI 

JG 

7F 

2MI 

JNLE 

12 

7D 

2MI 

JGE 

71 

2MI 

JNO 

13 

70 

2MI 

JL 

TO 
’ O 

2MI 

JNP 

14 

7E 

2MI 

JLE 

79 

2MI 

JNS 

15 

—■> 







44 


Dr. Dobb’s Journal, Number 64, February 1982 

"83 




Screen # 42 


0 

1 

i. 8086 A 

ssembler - instruction 

definitions ) 


X 

c. 

75 

2MI 

JNZ 

EZ 


2MI 

LOOP 

rs 

j 

70 

2ft I 

JO 

El 


2MI 

LOOPE 

4 

7A 

2MI 

JP 

EG 


2MI 

LOOPNE 

5 

7 A 

2MI 

JPE 

EG 


2MI 

LOOPNZ 

A. 

7B 

2MI 

JPO 

El 


2MI 

LOOP Z 

7 

78 

2MI 

JS 



12MI 

MOV 

8 

74 

2MI 

JZ 

A4 


3MI 

MOVS 

9 

9F 

1MI 

LAHF 

F6 

20 

8MI 

MUL 

10 



( LDS ) 

F6 

18 

8MI 

NEG 

11 

SA 8A SA 

7 MI 

LEA 

90 


1MI 

NOP 

12 



( LES ) 

F6 

10 

8MI 

NOT 

13 

FO 

1MI 

LOCK 

80 

08 

08 7MI 

OR 

14 

AC 

3MI 

LODS 

EE 

E6 

6MI 

OUT 


15 —> 


Screen # 43 

0 < 8086 Assembler - instruction definitions ) 

1 


c_ 

58 

07 

4MI 

POP 

DO 

08 

9MI 

ROR 

n 

•-/ 

9D 


1 MI 

POPF 

9E 


1MI 

SAHF 

4 

50 

06 

4MI 

PUSH 

DO 

38 

9MI 

SAP 

5 

9C 


1MI 

PUSHF 

80 

18 

18 7MI 

SBI3 

6 

DO 

10 

9MI 

RCL 

AE 


3MI 

SCAS 

*7 

f 

DO 

18 

9MI 

RCR 




( SEG 

8 

F3 


1 MI 

REP 

DO 

20 

9MI 

SAL 

9 

F3 


1MI 

REPE 

DO 

20 

9MI 

SHL 

10 

F2 


1MI 

PEPNE 

DO 

28 

9MI 

SHR 

1 1 

F2 


1MI 

REPNZ 

F9 


1 MI 

STC 

12 

F3 


1MI 

REP Z 

FD 


1MI 

STD 

13 

C3 


1MI 

RET 

FB 


1MI 

STI 

14 

DO 

00 

9MI 

ROL 

AA 


3MI 

S T OS 

15 

- - ;■ 









Screen # 44 

0 ( 8086 Assembler - instruction definitions ) 

1 


n 

CL 

30 

28 

23 

7MI 

SUB 

3 




14MI 

TEST 

4 

9B 



1MI 

WAIT 

5 




13MI 

XCHG 

6 

D7 



1MI 

XLAT 

7 

30 

30 

30 

7MI 

XOR 


8 

9 

10 — > 

11 
12 

13 

14 

1 5 (Continued on next page) 


Dr. Dobb’s Journal, Number 64, February 1982 

TkT 


45 


FORTH 8086 Assembler 

(Listing continued, text begins on page 14) 


Screen # 45 

0 < 8086 Assembler - control structures ) 

1 < IF ENDIF or IF. ELSE...ENDIF provides conditional ) 

2 < execution based on the state of the CPU's Z fI a q ) 

3 : IF 074 C, 0 C, HERE RESET , ( stores JZ ) 

4 ELSE OEB C, 0 C.■ DUP ( stores JMP ) 

5 HERE SWAP - DUP ABS 07F > 23 "'ERROR 

6 SWAP 1- C' HERE RESET ; 

7 ENDIF DUP HERE SWAP - DUP ABS 07F > 23 TERROR 

8 SWAP 1- C! RESET ; ( resolves branches ) 

9 

10 ( BEGIN . UNTIL construct provides controlled repetitive ) 

11 ( execution, exit from loop taken if Z flag is false ) 

12 : BEGIN HERE RESET ; < leaves address ) 

13 . UNTIL 074 C, HERE 1+ - ( stores JZ ) 

14 DUP ABS 07F > 23 TERROR C, RESET ; 

15 —> 


Screen # 46 

0 ( 8086 Assembler - special operators ) 

1 


Cm 

( 

force 

byte addressing mode ) 

3 


BYTE 

0 <W> 1 0 <WD> 1 i 

4 




5 

( 

force 

uiord addressing mode ) 

6 


WORD 

1 <W> ! 1 <WD> ! ; 

/ 

8 

( 

set immediate data flag ) 

9 


# 

1 <#> 1 1 <TS.:> * ; 

10 




1 1 

< 

c omma 

delimits destination field for direct 

12 



DEPTH 1 < 2E TERROR 0 <TDC 1 


13 —> 

14 

15 


Screen 47 

0 < 8086 Assembler - loading termination ) 

1 

2 ( CODE, ;CODE, and NEXT delimit a code definition ) 

3 : NEXT 0E9 C, NEXT-LINK OFFSET 16, RESET 

4 TEXEC ^CSP SMUDGE [COMPILE] FORTH ; IMMEDIATE 

5 

6 FORTH DEFINITIONS 

7 ■CODE TCSP COMPILE (;CODE> [COMPILE] [ ASSEMBLER 

8 RESET FORTH [COMPILED ASSEMBLER ; IMMEDIATE 

9 : CODE "'EXEC ! CSP CREATE ASSEMBLER RESET FORTH 

10 [COMPILED ASSEMBLER , IMMEDIATE 

11 

12 DECIMAL 

13 CR CR " 8086 Assembler loaded. " 

14 CR SP@ DP © - U. bytes left in dictionary " CR CR ;S 

1 5 End Listing 


46 


Dr. Dobb’s Journal, Number 64, February 1982 

"85 




Excuse Me, 
What Time Is It? 


T he article “Time On The Horizon” 
by D. J. Yates in DDJ number 57 
stimulated me to explore the 
timer hardware on the Horizon mother 
board. Dr. Yates points out that the 
major weakness of his timing routine is 
that it fails to keep time without program 
intervention. This weakness can be over¬ 
come by using interrupts. 

Interrupts are common in the world 
of large computers and are, in fact, the 
heart of multiprogramming systems, for 
without them, timesharing a computer is 
difficult. The micro-user, however, rarely 
timeshares; most systems rely on simple 
program loops for delays such as are 
necessary in disk drivers. With no need to 
keep multiple tasks running simultane¬ 
ously, delays necessary for floppy disk 
head movement are most easily accom¬ 
plished with programmed loops. If ac¬ 
curate timing of external events must be 
overlapped with computation, this tech¬ 
nique breaks down. The method Dr. 
Yates uses to time events allows for over¬ 
lap of computation and timing only to 
the extent that the computations take no 
more than a single clock period and the 
clock is sampled continuously by all parts 
of the system. The method described here 
allows for consistently accurate timing 
except through periods of disk access. 

I run CP/M on my Horizon and the 
programs described here are written in 
FORTRAN-80 and MACRO-80. The use 
of interrupts and the actual method of 
using the Horizon hardware clock can be 
adapted to North Star BASIC or any 
other language and operating system. 

First, a discussion of the use of hard¬ 
ware interrupts on 8080 and Z80 com¬ 
puter systems is in order. The 8080 and 
Z80 share a common mode of operation 
that allows for 8 different external inter¬ 
rupts to be processed. When the external 
interrupt is presented to the computer, 
one of the 8 RST instructions is forced 
into the instruction fetch cycle of the 
computer. The RST instruction is a 
CALL to a specific location in the com¬ 
puter memory determined by the actual 
instruction. An RST 4 causes a CALL to 
location 20H at the end of the currently 
executing instruction. The code found at 

by Alan Bombarger 


Alan Bamberger, 3721 Starr King Circle, 
Palo Alto, CA 94306. 


location 20H will execute until either 
another interrupt occurs or an RET in¬ 
struction is encountered. An RET instruc¬ 
tion causes the executing program to re¬ 
sume operation as if nothing has hap¬ 
pened except for some time delay deter¬ 
mined by the number of instructions in 
the program started at location 20H. If 
the interrupt routine changes the con¬ 
tents of any register and does not restore 
the register, then the program will con¬ 
tinue with the new register contents. 

The Horizon mother board allows 
the clock and many other signals to cause 
any one of the 8 interrupts. Since the 
Horizon is a Z80 computer, it must be as¬ 
sumed that the Z80 is in interrupt mode 
0 (8080 compatibility mode), and it is 
the responsibility of the programmer to 
ensure this operating mode. I chose to 
have the clock flag force an RST 4 in¬ 
struction for no other reason than 20H 
was a nice even number (also it did not 
interfere with any preassigned address in 
CP/M). I chose a timer interval of 26 ms 
as a tradeoff between the precise timing 
available with short intervals and longest 
maximum period available with a two- 
byte counter. The choice of 26 ms allows 
for a maximum software interval of 14 
minutes with a two-byte counter (15-bit 
positive numbers only), where the choice 
of 3 ms allows for a maximum software 
interval of 1.5 minutes with a two-byte 
counter. The use of four-byte integers 
(allowed in FORTRAN-80) would all but 
eliminate any need for trade-offs. 

Once the interrupt header is proper¬ 
ly wired, the execution of an OUT 6 in¬ 
struction with C0H in the A register will 
arm the clock interrupt. The first time 
the clock flag goes high an RST 4 instruc¬ 
tion will be forced, the computer will 
CALL location 20H, and will undoubted¬ 
ly get stuck in some kind of hideous loop. 
It is necessary to patch location 20H to 
jump to some subroutine that preserves 
the status of all registers and ends with an 
RET instruction. The construction of the 
subroutine and the patch of the JMP to it 
can be accomplished via POKE in BASIC 
but is done in my example with a FOR¬ 
TRAN callable subroutine. 

The subroutine is divided into two 
parts. The first part is called by FOR¬ 
TRAN and contains two entries. One 
entry, SETTIM, sets a time interval in a 
memory location called CLOCK and the 
other entry, INTVAL, waits for that in¬ 
terval to expire (returning the time that 
remained at the time it was called). The 


second part is the actual interrupt routine 
that executes each time the hardware 
clock flag goes high and decrements 
CLOCK once. Its last action before re¬ 
turning is to reset the hardware clock flag 
so that the routine will be called again at 
the end of the next interval. 

The program does not illustrate the 
complete range of options available. The 
programmer may wish to have an entry 
that returns the time remaining without 
waiting for the interval to elapse. Also a 
global “Time of Day” field can be updat¬ 
ed at each interrupt. Several interval 
timers can be decremented to zero at 
each interval allowing events to be sam¬ 
pled with overlapping intervals. What is 
important is that the interrupt routine 
is called each time the clock flag goes 
high no matter what the main program is 
doing, as long as interrupts are enabled. 
The version of CP/M I use has the option 
of running with interrupts enabled ex¬ 
cept when the disk drivers are active. 
These drivers contain programmed loops 
which are sensitive to timing and cannot 
be interrupted. The North Star system 
has a similar user-selected option. 

Several comments need to be made 
about the timer routine presented here. 
First, this is only an interval timer and 
the clock interrupts are disabled at the 
completion of the interval. This helps to 
ensure that the timer is not left running 
after the program completes. If the clock 
interrupt is left enabled after the program 
that defines the interrupt routine is com¬ 
pleted and overlayed by another program, 
then the next interrupt will cause execu¬ 
tion to begin at some random place with¬ 
in the loaded program. This can cause un¬ 
expected and disastrous results. If a 
“Time of Day” clock is to be kept 
throughout operation of the operating 
system then the interrupt routine must be 
loaded somewhere where it won’t be 
overlayed. This could probably be some¬ 
where in high memory or part of the resi¬ 
dent system. 

Second, note the use of DI and El in¬ 
structions both during the setting of the 
timer and during the interrupt routine. 
Neither of these is strictly necessary but 
they protect the code from other inter¬ 
rupts that might fiddle with the clock 
values. An example where DI is absolute¬ 
ly required is an entry that extends the 
interval. Such a routine picks up the 
clock value and adds a new value to the 
remaining time and returns it. If a clock 
interrupt occurs during this operation, 


50 

86 


Dr. Dobb’s Journal, Number 64, February 1982 



the restored value may be one TIC too 
large, but worse, the interrupt may have 
reduced the clock value to zero and dis¬ 
abled further interrupts. Thus, the sub¬ 
sequent call to INTVAL will wait for the 
timer to be reduced to zero but there are 
no active interrupts to do so. The use of 
Dl and IE around the instructions that 
add time to the interval prevents such an 
occurrence. 

Finally, note that the timer inter¬ 
rupt routine uses the stack to store regis¬ 
ters needed to update the clock. This 
routine is simple and uses only 6 bytes 
of stack (the PC on the CALL and the 
PSW and HL), but a more complicated 
routine might need to save many more 
registers. Programs written to run in an 
environment where interrupts are used 
must have sufficient stack space to ac¬ 
commodate the largest use of the pro¬ 
gram and the additional space required by 
the interrupt routine. It is axiomatic that 
if an interrupt can be fatal to a program 
then it will occur at precisely the place 
the program is vulnerable every time the 
program is run. 

Interrupts can be very . . . Excuse 
me, What time is it . . . useful, and a mas¬ 
tery of them will lead to a better under¬ 
standing of multi-user systems. 

•»I 

(Listing begins on page 52) 


Dr. Dobb’s Journal, Number 64, February 1982 


51 

87 



What time is it? 

(Text begins on page 50) 


Listing I 

INTEGER TENSEC 
TEN8EC - 10.0/ .026624 +1 

DO lOO 1-50,1000,50 
CALL SETTIN(TENSEC) 

DO 50 J-1,I 
B-J/IOOO. 

A—SIN(B) 

50 CONTINUE 

K«INTVAL <TENSEC> 

TIME-(TENSEC - K> * 26.624 
IF(K.EQ.O) GO TO 60 
WRITE(3,200) I,TINE 

200 FORMAT(’ LOOP OF LENGTH’,15,’ TOOK *,F9.3,' MILLISECONDS’) 

lOO CONTINUE 

WRITE(3,201) 

201 FORMAT(* *) 

STOP 

60 CONTINUE 

WRITE(3,202) I,TIME 

202 FORMAT(' LOOP OF LENGTH*,15,' INCOMPLETE IN *,F10.3,* MS’,/) 
STOP 'FAIL* 

END 


Listing II 

.8080 

ENTRY SETTIN,INTVAL 
I 

) THIS IS A SINGLE CLOCK TIMER ROUTINE THAT IS 
| FORTRAN CALLABLE 

I 

| ENTRY TO SETTIH 18 N1TH THE NUHIER OF TICS 
( TO SET AS AN INTERVAL 

I 

| RETURN FROM INTVAL IS AFTER THE TOTAL INTERVAL 
) HAS ELAPSEO BUT NITH THE NUMBER OF TICS LEFT IN 

; THE INTERVAL AT THE TINE OF THE CALL AS A FUNCTION 

; VALUE 

I 

| THIS ROUTINE USES THE HARDWARE CLOCK ON THE HORIZON 

I MOTHER BOARD IN INTERRUPT MODE SO THAT CONCURRENT 

) COMPUTATION CAN TAKE PLACE DURIN6 THE TIMING INTERVAL 

I 

VECTOR EBU 020H | VECTOR ADDRESS FOR RST 4 

I 

SETTIHi 
I 

) FORTRAN CALLS SETTIN NITH HL POINTING TO AN INTEGER 

| NUMBER OF TICS TO SET AS TIMER VALUE 

I 

F3 01 ; DISABLE INTERRUPTS WHILE FOOLING 

; NITH THE CLOCK VALUE 

7E MOV A,H ) GET NUMBER OF TICS 

32 OOSB’ STA CLOCK 


0020 

0000 ’ 

0000 ’ 

ooor 

0002 ’ 


52 

88 


Dr. Dobb’s Journal, Number 64, l-cbruary 1982 



0005’ 

23 


INI 

H 


0006' 

7E 


NOV 

A,N 


0007’ 

32 005C’ 


STA 

CLOCKM 

; SET INTERVAL 

000A’ 

21 0020 


LX I 

H,VECTOR; SET UP FOR INTERRUPT 

000D’ 

36 C3 


HVI 

H,0C3H 

| A JUMP TO INTERRUPT VECTOR 

OOOf’ 

21 0035’ 


LII 

H,TICKER; ADDRESS OF INTERRUPT ROUTINE 

0012' 

22 0021 


SHLD 

VECTOR*!; TO INTERRUPT VECTOR 

0015’ 

3E SO 


HVI 

A,050H 

| RESET CLOCK FLA6 

0017’ 

D3 06 


OUT 

6 

; ON HOTHER BOARD 

0019’ 

3E CO 


HVI 

A.OCOH 

; ARM CLXK INTERRUPTS 

001B’ 

D3 06 


OUT 

6 

; ON HOTHER BOARD 



.280 




001D’ 

ED 46 


in 

0 

; BE SURE IN 8080 NODE 



.8080 




001F’ 

FB 


EI 


; ENABLE INTERRUPTS 

0020’ 

C9 


RET 


; RETURN TO FORTRAN 

0021’ 


1 

INTVAL: 






1 

1 

WAIT FOR INTERVAL TO ELAPSE 



1 

RETURN NITH UNEIPIRED NUN8ER OF TICS AS FUNCTION VALUE 

0021’ 

2A 0058’ 

1 

LHLD 

CLXK 

| XT CLOCK VALUE LEFT 

0024’ 


1 

IMTLli 




0024’ 

3A 005C’ 


LDA 

CLOCK+l 

; H16H ORDER NUNBER OF TICS 

0027’ 

FE 00 


CPI 

0 


0029’ 

C2 0024’ 


JNZ 

INTL1 

| NAIT 

002C* 


1NTL2I 




002C’ 

3A OOSB’ 


LDA 

CLOCK 

| LON ORXR AS XLL 

002F’ 

FE 00 


CPI 

0 


0031’ 

C2 002C’ 


JNZ 

INTL2 


0034’ 

C9 


RET 


; RETURN NITH UNUSED TICS IN HL 

0035’ 


1 

TICKER) 






1 

1 

ACTUAL INTERRUPT ROUTINE THAT EXECUTES EACH CLOCK TIC 

0035’ 

F3 

1 

DI 


| KEEP US SAFE FROM OTHERS 

0036’ 

F5 


PUSH 

PSN 


0037’ 

E5 


PUSH 

H 

; RUST RESTORE MX FOR PR08RAH RUNNING 

0038’ 

2A OOSB’ 

1 

LHLD 

CLXK 

; XT CURXNT CLOCK 

0038’ 

28 


DCX 

H 

; DECREHENT 

003C' 

22 005B' 


SHLD 

CLOCK 

; NEH VALUE - NOT XT CONDITION COX 

003F’ 

7C 


HOV 

A,H 

; HIGH BYTE 

0040’ 

FE 00 


CPI 

0 

| IS IT ZERO 

0042’ 

C2 0048’ 


JNZ 

TICTX 

; NO KEEP TICKIN6 

0045’ 

7D 


HOV 

A,L 

; LON BYTE 

0046’ 

FE 00 


CPI 

0 

; IS IT ZERO 

0048’ 

CA 0053’ 


JZ 

TICOFF 

; STOP CLXK INTERRUPTS 


(Listing continued on next page) 


Dr. Dobb’s Journal, Number 64, February 1982 


53 

89 





What time is it? 

(Listing continued, text begins on page 50) 


004B’ 

0048’ 

3E 50 

TICTOC* 

MV I 

004D’ 

D3 06 


OUT 

004F ’ 

El 


POP 

0030’ 

FI 


POP 

0051’ 

FB 


El 

0032’ 

C9 


RET 

0053’ 

0053’ 

3E 40 

TICOFF t 

MVI 

0055’ 

D3 06 


OUT 

0057’ 

El 


POP 

0058’ 

FI 


POP 

0059’ 

FB 


El 

003A’ 

C9 

! 

CLOCK: 

RET 

0058’ 


DS 


END 


A,050H ; RESET FLAG 
6 ; ON MOTHER BOARD 

H 

PSN 

I RESUME INTERRUPT NODE 
| RESUME PR06RAM 

A,040H ; DISARM CLOCK INTERRUPTS 
6 | ON MOTHER BOARD 

H 

PSN ; RESTORE WORLD 

| RESUME INTERRUPTS 


2 | THE CLOCK NORD 


Macron 

Syaboln 

CLOCK 003B’ INTL1 0024’ INTL2 002C’ INTVAL 00211’ 

SETTIH 00001’ TICKER 0035’ TICOFF 0033’ TICTOC 004B’ 

VECTOR 0020 


No Fatal *rror(») 


End Listing 


54 

90 


Dr. Dobb’s Journal, Number 64, February 1982 


Background Information on 
Text Editors 


T ext editors, once very vogue sys¬ 
tems programming projects, seem 
to have fallen from grace in re¬ 
cent years. Happily, there are some early 
signs that this trend is being reversed 
under the various guises such as “program 
editors,” “structure editors” and “pro¬ 
gramming environments.” I read with in¬ 
terest the recent DDJ articles on editors. 
The authors have several interesting opin¬ 
ions. In order to “stimulate the bril¬ 
liant — unconventional — hardworking Dr. 
Dobb’s community to start thinking in 
the direction of what a really good pro¬ 
gram editor should do,” I offer this bibli¬ 
ography on the subject and the sage: 

“In discussing editors firm opinions 
abound: everyone, from greenhorn 
to old hand, knows exactly what the 
best and worst features of given edi¬ 
tors are and just how new editors 
ought to be designed. The only prob¬ 
lem is the striking lack of consensus.” 
Embley, David W., and George Nagy, 
Behavioral Aspects of Text Edi¬ 
tors. ACM Computing Surveys 
13( 1 ):35, March 1981. 

Available References 

Barstow, David R., Howard E. Shrobe, and 
E. Sandewall, Eds., Interactive Pro¬ 
gramming Environments. McGraw- 
Hill: New York, NY, 1981. 

Brown, M. R. and S. R. Wood, 

A Display-oriented Program Editor. 
Extended Abstract, Yale University, 
Dept, of Computer Science, New 
Haven, CT, January 1979. 

Card, Stuart, 

Studies in the Psychology of Com¬ 
puter Text Editing Systems. Ph.D. 
Thesis, Carnegie-Mellon University, 
Technical Report SSL-78-1, Xerox 
Palo Alto Research Center, Palo 
Alto, California, 1978. 

Courlouris, F. F., et al.. 

The Design and Implementation of 
an Interactive Document Editor, 
Software Practice and Experience 6: 
271-279 (April-June 1976). 

Dam Van, Andreas and D. E. Rice, 

On-line Text-editing: A survey. 


by Leonard K. Nicholson 


Leonard K. Nicholson, Tulane University, 
School of Engineering, Department of 
Computer Science, New Orleans, LA 
70118. 


ACM Computing Surveys 3(3):93- 
114, Sept. 1971. 

Deutsch, P. L., and B. W. Lampson, 

An Online Editor, Communications 
of the ACM 10( 12):793-803, De¬ 
cember 1967. 

Donzeau-Gouge, V. G., et al., 

A Structure Oriented Program Edi¬ 
tor: A First Step towards Computer 
Assisted Programming. Technical Re¬ 
port 114, Iria-Laboria, France, April, 
1975. 

Donzeau-Gouge, V. G., et al.. 

Programming Environments Based on 
Structured Editors: The MENTOR 
Experience. Technical Report, Iria- 
Laboria, France, April, 1980. 

Douglas, Craig C., 

C — A Guide to the Yale C Editor. 
The Quasi-Portable C Editor. Yale 
University, Dept, of Computer Sci¬ 
ence, New Haven, CT, 1980. 

Ellis, John R., 

MUF: Multiple User Forks. Technical 
Report 191, Yale University, Dept, 
of Computer Science, New Haven, 
CT, 1981. 

Embley, David W., and George Nagy, 

Behaviorial Aspects of Text Editors. 
ACM Computing Surveys 13(1 ):33- 
70, March 1981. 

Feiler, Peter H., and Raul Medina-Mora, 
An Incremental Programming Envi¬ 
ronment. Technical Report, Carnegie- 
Mellon University, Dept, of Comput¬ 
er Science, Pittsburgh, PA, April 
1980. 
also in 

IEEE Transactions on Software 
Engineering SE-7(5):472-482, 
September 1981. 

Finseth, Craig A., 

Theory and Practice of Text Editors 
or a Cookbook for an EMACS. B.S. 
Thesis Massachusetts Institute of 
Technology, Technical Report TM- 
165, Massachusetts Institute of Tech¬ 
nology, Cambridge, MA, May, 1980. 

Hazel, P., 

Development of the ZED Text Edi¬ 
tor. Software Practice and Experi¬ 
ence 10( 1):57-76, January 1980. 

Hunke, H., Ed., 

Software Engineering Environments. 
North-Holland, 1981. 

IEEE Tutorial: Software Development 
Environments. IEEE Computer So¬ 


ciety, 1981. 

Irons, E. T., and F. M. Djorup, 

A CRT Editing System. Communica¬ 
tions of the ACM 15(1): 16-20, Jan¬ 
uary, 1972. 

Kernighan, B. W., 

Advanced Text Editing on UNIX. 
Bell Labs Technical Report, Murray 
Hill, NJ, February, 1979. 

Kernighan, Brian W. and P. J. Plauger, 
Software Tools. Addison-Wesley, 
1976. 

Lampson, Butler, 

Bravo Manual. Xerox Corporation, 
Palo Alto, California, 1978. 

Lewis, J. W., and D. F. Porges, 

AI.BE/P: A Language-Based Editor 
for Pascal. Technical Report, Yale 
University, Dept, of Computer Sci¬ 
ence, 1978, 
also in 

Proceedings of Eighth Texas Con¬ 
ference on Computing Systems, 
November 1979. 

Newman, Ken, 

PTED: A Standard Pascal Text Edi¬ 
tor Based on the Kernighan and 
Plauger Design. Technical Report 
CSRG-120, University of Toronto, 
Dept, of Computer Science, Octo¬ 
ber 1980. 

Nix, Robert, 

Experience with a Space Efficient 
Way to Store a Dictionary. Commu¬ 
nications of the ACM 24(5):297- 
298, May 1981. 

Peterson, James L., 

Design of a Spelling Program: An Ex¬ 
periment in Program Design. Lecture 
Notes in Computer Science, Vol. 96, 
Springer-Verlag, New York, NY, Oc¬ 
tober, 1980. 

Peterson, James L., 

Computer Program for Detecting and 
Correcting Spelling Errors. Commu¬ 
nications of the ACM 23( 12):676- 
687, December 1980. 

Proceedings of the ACM SIGPLAN/ 
SIGOA Symposium On Text Mani¬ 
pulation. Portland, Oregon, June 8- 
10, 1981. ACM Order No. 548810, 
ACM SIGPLAN Notices 16(6), June 
1981. 

Roberts, Teresa L., 

Evaluation of Computer Text Edi¬ 
tors. Ph.D. Thesis, Stanford Univer¬ 
sity, November 1979, Technical Re- 


Dr. Dobb’s Journal, Number 64, February 1982 


55 

91 



port SSL-79-9, Xerox Palo Alto 
Research Center, Palo Alto, Califor¬ 
nia, 1979. 

Samuel, A., 

Essential E. Technical Report STAN- 
CS-80-796, Stanford University, 
Dept, of Computer Science, March 
1980. 

Sandewall, Erik, 

Programming in an Interactive Envi¬ 
ronment: The Lisp Experience. ACM 
Computing Surveys 10(1): 35-71, 
March 1978. 

Shapiro, E. G., et al., 

PASES: A Programming Environ¬ 
ment for PASCAL. Schlumberger 
Programming Environment Work¬ 
shop, June, 1980. 
also in 

ACM SIGPLAN 16(8):50-57, 
August, 1981. 

Stallman, Richard M., 

EM ACS: The Extensible, Customiz¬ 
able Display Editor. Artificial Intelli¬ 
gence Lab Memo 519a, Massachu¬ 
setts Institute of Technology, Cam¬ 
bridge, MA, 1981. 


Teitelbaum, Tim, and Thomas Reps, 

The Cornell Program Synthesizer: A 
Syntax Directed Programming En¬ 
vironment. Communications of the 
ACM 24(9):563-573, September 
1981. 

Weiner, P., Singh, I., Mostow, D. J., and 
E. T. Irons, The Yale Editor E A 
CRT Based Text Editing System. 
Technical Report 19, Yale Univer¬ 
sity, Dept, of Computer Science, 
New Haven, CT, 1980. 

Wood, Steven R., and John R. Ellis, 

A Bliss Programming Environment. 
Technical Report, Yale University, 
Dept, of Computer Science, New 
Haven, CT, 1980. 

Wood, Steven R., 

Z - The Last Word in a Series of 
Single Letter Yale Editors. Yale 
University, Dept, of Computer Sci¬ 
ence, New Haven, CT, 1980. 

Wood, Steven R., 

The Design of a Program Editor: An 
Alternative. Ph.D. Thesis in prepara¬ 
tion, Yale University, Dept, of Com¬ 
puter Science, New Haven, CT, 1981. 


Notes 

The material from the ACM may be 
obtained at modest cost from: 

Association for Computing Machinery 
1 133 Avenue of the Americas 
New York, NY 10036 
Phone: 212/265-6300 

The material from Yale University 
may be obtained by sending a self- 
addressed, stamped envelope and a nice 
cover letter to the respecive authors: 

Mr. Craig C. Douglas 
Yale University 
Dept, of Computer Science 
2158 Yale Station 
10 Hillhouse Ave. 

New Haven, CT 06520 

Mr. Steven R. Wood 
Yale University 
Dept, of Computer Science 
2158 Yale Station 
10 Hillhouse Ave. 

New Haven, CT 06520 

Other technical reports may be ob¬ 
tained from the respective contributors 
either free or at nominal charge. 


56 


Dr. Dobb’s Journal, Number 64, February 1982 


Standards for Computerized 
Measurement 


15 


876593210 

ino bp s i i i i i i i i i 

i incriea i i i i i i i i i 



::::::: 1/256 

:::::: 1/128 
: : : : : 1/64 

: : : : 1/32 

: : : 1/16 

: : 1/8 

: 1/4 

1/2 



(Fig, i) 


14 13 12 11 10 9 8 7 6 5 4 3 2 0 

1 

• 

1 

1 

1 1 

1 1 

1 1 

1 1 

1 

1 

I I I ! I | fluid drams! 






: : : : fluid ounce 






: : : tablespoon 






: : gill 






: chopin 






pint 





quart 




: pottle 





gallon 





: peck 





demibushel 




firkin 




kilderkin 



(fig. 2) 


W e should hope that the Metric 
standard is not adopted in 
this country because Metric, 
with its base of ten, aggravates the prob¬ 
lems binary computers have always had 
with floating point numbers. Customary 
measure is easier to deal with, both for 
people and computers. It is expected that 
FORTH enthusiasts will adopt everything 
that follows without question. 

It is easier to divide something (like 
a stick or a pie) into 16 parts than into 10 
parts. That is because dividing by 2 has 
been well understood for centuries. Di¬ 
viding by 5 is much more complex. 

Consider the inch. On most rulers, 
inches are broken down into halves, quar¬ 
ters, eights, and so on, depending on the 
resolution of the ruler. Such fractions are 
easily represented in a computer and may 
be acted upon by simple binary arithme¬ 
tic. Suppose a measurement is to be con¬ 
tained in a word (Figure 1). The high 
order byte could contain the number of 
whole inches. The low order byte could 
contain the fraction of inches, with very 
fine resolution. We will return to the inch 
later. 

Many of the customary measures 
show conventional wisdom in the choice 
of binary units. The most remarkable are 
the fluid measure (Table 1), which can 
easily and efficiently be represented in a 
computer (Figure 2), with varying magni¬ 
tude and resolution. (Many of the names 
are archaic. It is left to the reader to 
decide which are archaic, and which are 
as up-to-date as tomorrow’s newspaper). 

Many of our standard weights are 
also based on binary units: an ounce is 16 
drams, and a pound is 16 ounces (Table 
2). To these I add the Crockford Stone, 
the Crockford Hundredweight, the Crock- 
ford Ton, which is a compromise between 
the U.S. ton and the Metric ton. Notice 
that these are scientific units of measure. 
They are not based on superstitious non¬ 
sense like the length of my arm or the 
diameter of a Krypton atom. 

As we have seen, the customary inch 
is an excellent unit of measure. The 
Crockford foot is eight inches long, which 
is good news for foot-long hot dog fans 
in these days of high meat prices (Table 
3). Also, I am defining the Crockford 


by Douglas Crockford 


Douglas Crockford, 14541 Countrywood 
Lane, Irvine, CA 92 714. 


Rod, The Crockford Furlong, and the 
Crockford Mile, which is a couple thou¬ 
sand inches longer than the old, unscien¬ 
tific mile. It should be just the right length 
for giving directions: “You go down the 
road a good Crockford Mile .. 

Our customary measures of time are 
based on 60. The Crockford Minute and 
Crockford Hour correct this oversight, in¬ 
creasing to 64 (Table 4), giving us more 
time to listen to Andy Rooney. Other 
new units are the Crockford Day, the 
Beatle Week, the Crockford Month, and 
the Crockford Year. These units do not 
pretend to be based on astrological sig¬ 
nificance. Standing on the scary brink, as 
we are, of interplanetary travel, Earth- 
based time reckoning is unreasonable. 
Standard Crockford Time will be a boon 
to business data processors, who have had 
to work in strange units like Julian dates 
in order to do time computations. 


Finally, in Table 5, we have the 
Crockford Dollar, which makes truth of 
the complaint that the dollar is only 
worth 64 cents (if that). BBj 


Dr. Dobb’s Journal, Number 64, February 1982 


57 

93 



























Dr. Dobb’s Journal, Number 64, February 1982 


SOFTWARE REVIEW 


ZEN 

North Star Management Program 
from Zenrad Controls Company 

1575 A. P. S. 

Santa Barbara, CA 93103 
Disc and Manual $75, Manual alone $15 
Reviewed by Gene Head 

“ZEN IS HERE .. 

“ZEN is the most comprehensive 
management program available for the 8- 
bit microprocessor of its size.” Quoted 
from the ZEN user’s manual. 

Well, you can’t believe everything 
you read in print. (Not even software 
reviews.) “. . . of its size”, just may be the 
operative phrase here. ZEN has some 
good features and is probably a useful 
tool, but “. . . the most comprehensive 
.. etc., etc. Hardly! 

Overview 

ZEN is a North Star disk-based pro¬ 
gram with a screen editor, system moni¬ 
tor, and 8080 assembler. The disk has 
three copies of ZEN object code (Type 1 
files) addressed at 800-H, 8800-H, and 
A800-H. A version of ZEN compatible 
with the 100-H North Star DOS (CP/M) 
is also on the disk. The assembler object 
file is automatically loaded whenever 
ZEN operations require assembly. The 
screen editor and system monitor are con¬ 
tained within ZEN. ZEN will work in as 
little as 16K but requires 32K to assem¬ 
ble itself. Assemble itself? Yes, both ZEN 
(the editor/monitor), and ZASM (the as¬ 
sembler) source files are delivered on the 
disk. This is one of the few really good 
features of ZEN. The source files, though 
not well commented, give the user real 
control. I like that! Alot! 

Screen Editor 

ZEN does a pretty good job of edit¬ 
ing, although I wouldn’t call it a screen 
editor. What you see on the screen is not 
always what you get. In actuality, ZEN 
uses the North Star line editor with some 
very good results but clearly not screen 
editing as I define it. 

For instance, as you move the cur¬ 
sor down the screen, everything looks like 
what you’d expect. Lines are added at the 
bottom and scroll off the top of the 
screen. However, moving the cursor up 
works just fine until the top of the screen 
is reached. On my twenty-four line dis¬ 
play, lines two through twenty-four stay 
put and line one changes with each cursor 
movement up. This means when you start 
back down, all lines above the cursor are 


in the proper position but lines displayed 
below the cursor have not been adjusted. 
Now this is no major problem so long as 
you are accustomed to it. A few com¬ 
mands to home and clear followed by 
cursor down movement will work pretty 
well on shorter files, but forget it on the 
long ones. 

Each line can be edited using the 
standard North Star edit commands. Here 
again, this type of editing is pretty pri¬ 
mitive. When you insert text into a screen 
line it doesn’t “open up” or expand as 
new characters are entered. If you forget 
(me, forget?) to move the cursor to the 
end of the edited line before a C/R, your 
line is truncated to the last cursor posi¬ 
tion. It’s exactly like editing programs in 
North Star BASIC. Very usable in a line- 
oriented file, but not for screen editing. 

ZEN Monitor 

There are eleven monitor commands. 
Standard features include input and out¬ 
put to specific I/O ports, ASCII and hex 
durnps, jump to, very simple memory 
test, and hex-to-decimal conversion. The 
move-memory feature is somewhat dif¬ 
ferent, as overlays are permitted in either 
direction. This means you can slide any 
amount of memory forward or backward 
by any offset value. I’m not certain of the 
usefulness of this feature but I know my 
system monitor can’t do it! 

The READ and WRITE features of 
the monitor are also questionable when it 
comes to “Why would you need that 
feature?” READ will output the contents 
of memory to a listing device one line at 
a time. Any keyboard entry except 
control-C will continue this crude listing 
feature. The WRITE feature allows abso¬ 
lute keyboard echoing to numbered de¬ 
vices until a control-C is entered to ter¬ 
minate the WRITE function. If there are 
any North Star users out there without a 
software-controlled printer-activate func¬ 
tion let me know and I’ll send you my 
version of the DOS users area. 

Assembler 

The assembler can assemble 8080 
code without putting any code on disk or 
into memory. I like this feature, especial¬ 
ly when writing user area routines. I can 
write a modified version of my DOS user 
keyboard input routine and assemble it 
without changing memory. If there are 
no errors and I actually think the code 
will work, I can then assemble it with a 
zero offset and it will assemble into 


RAM. I can supply an offset value that 
allows source code to be assembled for 
execution at, say, address 1000-H and 
store the object code at address 2000-H. 
ASME will assemble as above but only list 
any errors encountered. 

The LAB command will list all the 
addresses of labels in the program. Labels 
are global, as one label buffer is used 
when assembling more than one file from 
disk. The LAB command does not show 
addresses that reference a label. 

Up to six breakpoints can be set and 
registers displayed when the break point 
address is executed. Continuation after a 
break is accomplished with the CONT 
command. 

Object code is saved to the object file 
after exiting ZEN, using the CR and SF 
commands in North Star DOS. 

Conclusion 

The manual has a few typos and is 
pretty confusing in places. I sat down to 
get a feel for ZEN about five times in a 
two-month period. It was not the most 
pleasing experience I’ve encountered. I 
had to work at it, not just to learn t’.e 
syntax and procedures, but to try to 
figure out what exactly the manual was 
trying to say. 

I think ZEN was developed at a 
time when North Star needed an editor/ 
assembler. However, with CP/M available, 
the software houses are providing really 
quality program development tools at rea¬ 
sonable prices. I would expect ZEN 
would have been very valuable three or 
even two years ago, but not today. 


Dr. Dobb’s Journal, Number 64, February 1982 


59 

95 





BOOK REVIEWS 


The Devil’s DP Dictionary 
By Stan Kelly-Bootle 
Published by McGraw-Hill 
$7.50, 141 pages 
Reviewed by Joey Robichaux 

I’ve got this terrible problem. 

You see, I’m supposed to review The 
Devil's DP Dictionary by Stan Kelly- 
Bootle, but ... well, it’s a long story. 

The other day I brought the book 
with me when I went to work. I hoped to 
read some of it during any (rare) free 
time I had. When I got to the office, I 
found out the computer was down 
because of hardware problems and would 
be down all day. 

Naturally, the programming staff 
took this as a divine sign to gather and 
bullshoot in the breakroom all day. Want¬ 
ing to shoot my share of bull, I entered 
the break room with my copy of The 
Devil’s DP Dictionary. 

‘What’s that you’ve got there?” 
popped up almost immediately. 

We passed the book around and 
everyone got a chuckle out of it. The 
chuckles grew a little louder; of course, 
more people had to drop in to see what 
was so funny. This made the chuckles 
even louder, so even more people came 
by, which made it even louder, so ... 

Big happy party, right? So where’s 
the problem? 

Somehow, during all the confusion 
and merry-making, I managed to get 
separated from my copy of The Devil’s 
DP Dictionary. 

I tried to track it down, though. 

Loud, uproarious laughter would 
spring up down the hall. When I’d get 
there. I’d find red faces and eyes teary 
from laughing, but the darned book al¬ 
ways seemed one step ahead of me. 

So how am I supposed to review this 
book when it wouldn’t stay still long 
enough for me to finish reading it? I’ll 
try from memory. 

I remember a buffer was defined as 
“an old, greasy, and abrasive rag used to 
clean tape heads.” 

I remember that BASIC was “origi¬ 
nally a simple mid-level language used to 
test a student’s ability to increment line 
numbers.” 

I remember that my wife, who 
knows nothing about computers, didn’t 
think it was funny. 

1 remember that our programming 
staff, who also sometimes knows nothing 
about computers, loved it. 

***** 


A few days have passed. I’ve found 
the elusive copy of The Devil's DP Dic¬ 
tionary. It’s dogeared, the binding is 
cracked, the pages are worn from use. It 
looks like a copy of Candy that’s been 
passed around an eighth-grade class. 

Our shop certainly enjoyed The 
Devil’s DP Dictionary. I hope you do, 
too. 


LISP 

By Patrick Henry Winston and Berthold 

Klaus Paul Horn 
Published by Addison Wesley 
$13.95, 430 pages 
Reviewed by Brian Gordon 

Almost all “serious” intelligent or 
seemingly intelligent computer programs 
are written in the same language - LISP. 
Structurally, LISP is a general purpose list 
processing language; its data elements are 
atoms and lists composed of atoms 
and/or other lists, and its processing 
power involves the formation of symbolic 
expressions. As such, LISP is vastly dif¬ 
ferent from FORTRAN, BASIC and 
other arithmetic-oriented languages more 
familiar to home computer users; and 
from Pascal, Forth and other powerful 
high-level languages popular with the 
same audience. 

Traditionally, LISP has been the lan¬ 
guage of the artificial intelligence (AI) 
community, running only on large “main¬ 
frame” computers. Despite its potential 
as a general purpose list processing lan¬ 
guage, LISP has remained best known as a 
fairly special-purpose language. It current¬ 
ly has two major dialects, MACLISP and 
INTERLISP. 

Winston & Horn’s book, LISP, ap¬ 
pears to be aimed at college or graduate 
students in AI, and concentrates on the 
MACLISP version of the language, using 
an appendix to discuss the significant 
differences in INTERLISP. Since at least 
one vendor now advertises a micro-based 
MACLISP, there is reason for interest 
among home-computer users - and this 
is an interesting book. 

For a reader who met LISP back in 
the sixties, and who has not seen the 
changes from the old LISP x.x implemen¬ 
tations, the book does a good job of re¬ 
introducing the constructs of the lan¬ 
guage. For someone with no LISP back¬ 
ground, but familiarity with one or more 
other high-level languages, the book may 
be disconcerting — a lot of material must 
be covered, and a previous programming 


background may give you a “mind set” 
which must be overcome. That is, how¬ 
ever, a characteristic of the language, not 
of the presentation. With no program¬ 
ming background at all, the learning of 
LISP, while very different from the learn¬ 
ing of most other languages, should be no 
harder. Again, that is a result of the 
nature of LISP and its most frequent ap¬ 
plications areas, not of this specific pre¬ 
sentation of it. 

Given access to a suitable computer 
environment, this book should help any¬ 
one learn the rudiments of the language. 
That appears to be half the intent of the 
text. 

The other purposes of the text are 
many: the teaching of the proper style of 
LISP programming, some insights into 
using the language to extend itself, tech¬ 
niques for writing large programming sys¬ 
tems, and a fairly large dose of some of 
the techniques of AI itself. How well each 
of these objectives is met can best be de¬ 
bated by experts in the various fields in¬ 
volved, but suffice it to say that the con¬ 
scientious reader will learn the author’s 
views on these and many related topics. 

In summary, the book is a readable 
introduction to at least one dialect of 
LISP. It contains many examples as well 
as exercises with solutions, and an exten¬ 
sive bibliography. Its overall usefulness is 
most limited by your interest in the sub¬ 
ject matter, and your access to a machine 
which speaks MACLISP. 


60 


Dr. Dobb’s Journal, Number 64, February 1982 





R. LyOBB S 

For Users of Small Computer Systems 



$2.50 

($3.00 in Canada) 


OURNAL 


Number 65 March 1982 Volume 7, Issue 3 



Runic: An Interactive, Extensible Compiler 

Marty Franz 


A Pattern Classification Program 

K.F. Wegner and D.E. Raeside 

Put the Heath H-8 Front Panel to Work 

D.C. Shoemaker 


Look inside for even more! 


Tightening 

Leventhal... 

...Fast-branch 

BASIC... 

...Pidgin on 
8080 & CP/M 






Dr. Dobb s Journal 

For Users of Small Computer Systems W 


March 1982 Volume 7, Issue 3, Number 65 

CONTENTS 

Runic: An Interactive, Extensible Compiler. . . 12 

by Marty Franz 

Putting the Heath H-8 Front Panel to Work ... 17 
by D. C. Shoemaker 
An Improvement Upon a Division 


Program by Leventhal.20 

by W. D. Maurer 

A Pattern Classification Program.23 

by K. F. Wegner and D. E. Raeside 

Pidgin for the 8080 Under CP/M. 25 

by Andrew L. Bender 


Editor - Marlin Ouverson 
Contributing Editors - 

Dave Caulkins, Dave Cortesi 
Marketing Director - Craig Harper 
Advertising Sales - Laird Foshay 
Circulation — 

Ari Taylor, Terri Marty 


EDITORIAL 

Have you ever watched synchronicity? Editors have to. 
In the absence of real geniuses (genii?) it seems everyone 
ends up doing roughly the same things at roughly the same 
time. Variations on themes which are just other variations 
on other themes. . . But as Heinlein noted in his 
great Foundation trilogy, mutants are unpredictable. They 
defy synchronicity except when it pleases them. Think of 
“mutants” as free-thinkers, unbounded by mediocrity or 
convention. 

We had already known this would be the year of syn¬ 
chronous announcements about hard-disk interfaces for 
micros. And some 16-bit machines made their expected 
appearances at the top end of the market. Rumors of an 
Atari to include dual 68000’s presages a 16-bit consumer/ 
hobbyist micro, as did the gossip mongers from Apple and 
Japan. But all was upstaged by Radio Shack’s announce¬ 
ment in January of their Model 16, with an MC68000 cpu. 
What, you ask, only one? Well, they threw in a Z80 to 


Art Director — Clifford West 
Production Manager - 
Barbara Ruzgerian 
Typesetter - Renny Wiggins 
Proofreader - Nancy Heubach 
Cover Illustration — 

A1 McCahon 


Letters. 4 

Dr. Dobb’s Clinic. 6 

Of Interest. 10 

Book Review. 54 

Software Review.56 

Hardware Reviews.61 


©1981 by People’s Computer Company unless otherwise noted on 
specific articles. All rights reserved. 


Dr. Dobb’s Journal (USPS 307690) is published twelve times per 
year by People’s Computer Company, Box E, 1263 El Camino 
Real, Menlo Park, CA 9402 5. Second class postage paid at Menlo 
Park, California 9402 5 and additional entry points. Address correc¬ 
tion requested. Postmaster: send form 3579 to Box E, Menlo Park, 
California 9402 5. 


handle mundane things like I/O. 

We will bring you more on the machine as soon as we 
get our eager hands on one. For your information, it costs 
$4999 if you need only one disk drive (after all, these disks 
hold 114 Megs). And the TRS-Folks amiably allow their 
new pet the run of all Mod 2 software. Just an added con¬ 
venience. 

My, how times have changed! DDJ got its start trying 
to fit a tiny version of Basic into a mere handful of bytes 
(do 6K fit in one hand or two?) and here we are, almost 
casually mentioning a micro which upgrades to 512K RAM 
(a slight 128K is standard) and supports multi-users. 

I wonder what’ll happen next month? 

Marlin Ouverson — Editor 


Subscription Rates: $25 per year within the United States; $40 for 
first class to Canada and Mexico; $58 for airmail to other countries. 
Payment must be in U.S. Dollars, drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be typed, double-spaced on 
white paper. Listings should be produced by the computer, using a 
fresh, dark ribbon on continuous white paper. Please avoid printing 
on perforations. Payment is in contributor’s copies. Requests to re¬ 
view galleys must accompany the manuscript when it is first sub¬ 
mitted. Authors may receive a copy of the complete writer’s guide¬ 
lines by sending a self-addressed, stamped envelope. 

Donating Subscribers Contributing Subscriber: $50/year ($25 
tax deductible). Retaining Subscriber: $75/year ($50 tax deduc¬ 
tible). Sustaining Subscriber: $100/year ($75 tax deductible). Life¬ 
time Subscriber: $1000 ($800 tax deductible). Corporate Subscriber: 
$500/year ($400 tax deductible, receives five one-year subscriptions). 


Contributing Subscribers: Eric H. Johnson, Jerry Horn, Edward W. 
Carr, Steven Fisher, Thomas H. Grohne, G. V. Elkins, Robert M. 
Connors, William J. McEown, Robert C. Luckey, Kim Leary, Robert 
N. Stabler, DeWitt S. Brown, John B. Palmer, E. Glion Curtis, Jack 
Miller, Burks A. Smith, Transdata Corporation, Mark Ketter, John 
W. Campbell, Friden Mailing Equipment, Howard E. Decker, Jim 
Wilson, Frank Lawyer, Chris Pettus. Retaining Subscribers: Osamu 
Shimizu, Scott B. Guthery, Robert L. Edens, Titus Purdin, Steven 
Fisher Enterprises. Sustaining Subscribers: Gordon Eubanks, Jr. and 
Pete Roberts. Lifetime Subscriber: Michael S. Zick. 

Foreign Distributors UK & Europe: LP Enterprises, 8/11 Cam¬ 
bridge House, Cambridge Road, Barking, Essex, 1G11 8NT, England 
(Tel. 01-591-6511, TLX 892395). Hofacker-Verlag, Tegernseer 
Strass 18, D-8150 Holzkirchen, West Germany. Asia & Australia: 
Computer Store, POB 31-261, 22B Milford Road, Milford, Auckland 
9, New Zealand. ASCII Publishing Co., Ltd., Aoyama Building 5F, 
5-16-1 Minami Aoyama, Minato-ku, Tokyo 107, Japan. 


Dr. Dobb’s Journal, Number 65, March 1982 

"98" 


3 












He Picks IBM’s Nits 

Dear Doctor Dobb: 

I have bought an IBM Personal Com¬ 
puter and discovered a few annoying 
items. 

Nit #1: the system demands a date 
on power-up (with DOS). This I do not 
like (right now), but I do not want to 
subterfuge it because *someone* hope¬ 
fully will make a CMOS date/time clock 
board with software to load those fea¬ 
tures automatically on power-up. 

Nasty Nit #2: FORMAT program 
will format virtually any disk, no matter 
how bad. It gives no information while 
running (like what track it is on, is it 
‘F’ormatting, ‘E’rror, or ‘Verified). 
Disks with large scratches and badly 
warped surfaces are blithely accepted 
with absolutely no comment. The display 
is no different with good diskettes. 

Related Nasty Nit #3: CHKDSK 
tells only how many files there are, and 
by a little calculation, one can discover if 
a file BADTRACK was written. Beyond 
this, the error information is absent. A 
formatted display of the error info in 
BADTRACK would be helpful here, as 
well as when FORMAT is complete. 

Nit #4: There is absolutely no way 
to use CHKDSK on other diskettes, in 
a single drive system, despite instructions 
to the contrary. 

Nit #5: The monochrome display/ 
printer adapter card has un-documented 
features: 

a) J1 (2-pin connector) 

open (normal) = normal operation 

shorted (test??) = disable monochrome 
display. Horizontal drive gets killed, 
but the schematic shows vertical 
drive being disabled, along with 
underline being toggled. 

b) J2 (6-pin connector) 

• This is near the 9-pin DB connector 
on the adaptor card, and is for a 
light pen. 

• The schematic is incomplete on 
page D-20 (Technical Reference 
Manual): it does not indicate that 
pin 1 goes to “+ LPEN (SHT 6)”. 

• For positional & pin documenta¬ 
tion, see color graphics monitor 
adaptor, page 2-63. 

• For I/O register programming data, 
see page 2-63 and assume port ad¬ 
dress x ‘3BB\ Using DEBUG to 
address either port 389 or 3BB re¬ 
sulted in a x ‘FF’, no matter what 
state (open, ground or +5v) pins 1 
and 3 on J2 were set to. So either 


my board is bad, or the hardware 
on J2 is window dressing. 

Nit #6: I realize that up to 256K of 
RAM can be put inside the system unit 
(Godbout, et al. . .. How about a 256K 
memory board for us?? Later, a 512K 
board??). And that 1 Megabyte is addres¬ 
sable. 

BUT, there is no excuse for (a) 48 K 
of ROM, where only 8K is available for 
the user (read 40K of SYSTEM ROM!!), 
and (b) the ROM routines mostly are not 
written as subroutines, so many otherwise 
useful routines need to be duplicated 
elsewhere. 

OVERBYTE GALORE! 

Nit #7: there is no software/ 
hardware interface for Winchester drives, 
or for that matter, for 8-inch floppy(ies). 
A big machine like this needs mass stor¬ 
age (5 Megabytes or more) for reasonable 
business (and some hobby) applications. 

Please help! 

Yours, 

“Polarbaer on an Ice Flow” 

Robert Baer 
921 Lincoln Ave. 

Palo Alto, CA 94301 

Getting Hyper? 

Dear Marlin: 

William Brogden’s guest editorial 
about program editors in the June issue 
of Dr. Dobb’s definitely got my attention 
and prompted this letter. I have been in¬ 
formally studying various editors off and 
on for the last few months. I intend to 
use what I learn to improve the editor on 
my own system. My first ideas for im¬ 
provement came from my own experi¬ 
ences since I have used many different 
editors at work to develop engineering 
applications programs. My desired im¬ 
provements, however, quickly got out of 
hand so I turned to textbooks and com¬ 
puter science journal articles. 

The article “On-line text editing: a 
survey,” by A. van Dam and D. E. Rice in 
the September 1971 Computer Surveys 
gives a thorough description of several 
different editing systems. Three of these 
systems are very much like the system 
sketched out by Brogden. Brown Univer¬ 
sity developed HES and FREES while the 
Augmented Human Intellect Research 
Center at Stanford Research Center devel¬ 
oped the NLS system. These systems 
allow the user to link text areas together 
to form a cross-referenced “hypertext.” 
(HES stands for Hypertext Editing Sys¬ 


tem.) This cross-reference system can be 
used to display the hierarchy of the pro¬ 
gram in a two-dimensional manner under 
the control of the user. 

My descriptions of these systems are 
very sketchy and incomplete since I am 
writing from brief notes about a general 
review article. I also have not covered any 
recent work since I could not readily find 
a more recent review article. This letter 
merely points the way to past work on 
advanced text editing systems done at 
Brown University and Stanford Research 
Center. This past work would provide a 
strong foundation on which Brogden’s 
advanced text editor could be built. 
Sincerely, 

G. Wayne Smith 
7413 S. Woodward 
Woodridge, IL 60517 

Editor’s Note: Anyone interested in some 
creative thought on text editing should 
read Literary Machines, by Ted Nelson. 
Send $15 to him at Box 128, Swarth- 
more.PA 19081. 

TEKnicalities 

Dear Mr. Ouverson: 

Here are some notes concerning my 
article, “TEK4010: A Tektronix Simula¬ 
tor,” DDJ #60, October 1981. First, in 
the introductory paragraph, the line “or 
perhaps C) could be directly on” should 
include “run” after “be.” Second, on 
page 10 paragraph 1 (9th line), 0F00H 
should read 0F000H. There was also a 
slight problem which occurred in a 
machine-dependent part of the program 
listing. Apparently, one line in a subrou¬ 
tine SIOISR was lost when the source 
code was transferred from one computer 
to another for printing. The fourth 
instruction SIOISR should be “INP A”. 
This should cause no trouble to this 
implementing TEK4010 since it is in the 
machine dependent code section. How¬ 
ever, anyone who studies this routine for 
the purpose of producing their own 
circular input buffering would have been 
confused by the lack of this instruction. 

As a final note, I should also like to 
mention that the DIV8 routine which 
does 16-by-8-bit division is by no means 
optimal. I recommend use of a more 
standard type algorithm if this routine 
proves too slow for a given implementa¬ 
tion of TEK 4010. DDJ' s “Clinic” has 
discussed division routines on several 
occasions including the October issue 
where TEK4010 appeared. 


4 


Dr. Dobb’s Journal, Number 65, March 1 982 

"99 




I would enjoy hearing from anyone 
who works with TEK4010 or has any 
reaction to this software package. 
Sincerely, 

Anthony Skjellum 

1695 Shenandoah Road 

San Marino, California 91108 

Tutti-Frutti AI 

Dear DDJ: 

Many thanks for the introduction 
of the subject of LISP and some allusions 
to artificial intelligence, in the form of 
Ronald Nicol’s December issue piece, 
“Actors, Property Lists, and LISP.” We 
have a long battle ahead of us to convince 
the public that AI, far from evil magic, is 
simply another method of processing 
orientation, data-directed, which permits 


this 


I gnor 

What message? 


Dear DDJ , 

I read with interest the articles on 
printer drivers for the MX-80 printer 
in the December issue. My problem 
is that I do not have room in my BIOS 
for more than a very short printer 
driver so I have had to use an alter¬ 
nate approach to insert printer con¬ 
trol codes into the text. 

Some of the control codes for the 
printer are used for other purposes by 
CP/M or by ED and may not be sent to 
the printer driver. Some of the printer 
control codes are preceded by an 
ESCape, which in my case is a problem 
because ESCape is used to leave a 
terminal emulator to return to the sys¬ 
tem. 

This problem also occurs for the 
Centronix printers. R. L. Brechwald 
of our department had developed a 
procedure for inserting printer control 
codes into text that I have found to be 
a satisfactory solution. The procedure 
is to develop a set of library files that 
can be used with ED to insert code to 
turn on or off various features of the 
printer when the text is printed. The 
main drawback of this approach is that 
the library files consist of a few bytes 
of code, but use up a minimum of IK 
of disk space. The S mode of DDT of 
SID can be used to create such files. 
For example, an SO or OEH followed 
by 1AH, an end of file, can be saved 
as SO.LIB. This can be inserted with 
the R command of ED to turn on the 


a computer to acquire greater decision¬ 
making independence. As such, AI tech¬ 
niques of many flavors have already left 
the realm of this computer science epi¬ 
thet to settle in as viable real-world ap¬ 
plication tools. All are encouraged to 
familiarize themselves with the difference 
between procedural languages, and list¬ 
processing languages; but more so, on the 
necessity to build any software around 
carefully planned data structures. 

As one who struggled horribly with 
Winston, feeling stupid at her inability to 
comprehend his jargon, despite the aid of 
attendance in a very clear seminar on the 
very same historic summary of AI, given 
at Camegie-Mellon; and had worse begin¬ 
ner’s trembles wrestling through Nilsson, 
and CMU’s own Newell and Simon, at 

> message ! 


double width letter mode of the 
printer. DC4.LIB can contain the code 
to turn off the double width mode. 

In the above example, an en¬ 
hanced double-printed, double-width 
line will be printed followed by a line 
printed in compressed text. The exam¬ 
ple demonstrates that this is not an 
elegant solution to the problem but it 
does allow one to use all of the print¬ 
er’s features. 

John S. Neff 
Professor of Astronomy 
University of Iowa 
Iowa City, IA 52242 


A >ED EXAMPLE.TXT 

NEW FILE 

t *#AV 
i *RFF 
i *RSO 
i tRESCE 


Ignore this message ! 


li 

2i 

i *rdc4 
i *resc* 
i *resch 
i ti 


i trsi 

i *1 

3i What message? 

4s 

i *rdc2 
: tri i 
i #b22t 

Is ''L' V N <S CE~CG Ignori 

2s ~T~CF~CH 

3i What message 1 

41 "-R^L* 

2s -t-cf^CH 


Ignore this message 


A>TYPE EXAMPLE.TXT 


the very time these august gentlemen 
lectured live in front of her classroom 
seat twice weekly; I must object to the 
bibliography appended to the article. 
These references will likely turn off the 
beginning researcher, discouraging further 
attempts to abandon old computing 
methodologies in favor of AI types. (In- 
cidently, Nilsson, also very lucid in per¬ 
son, comments that AI cannot currently 
be fixed in definition, so that our coming 
students will still wander freely with their 
own experimentations, expanding this 
fledgling science. Nilsson’s popularly 
shared opinion has prevented the prepara¬ 
tion of a comprehensive beginning text or 
lay source in AI.) 

The article itself aims at Dr. Dobb’s 
highly sophisticated audience, and seems 
difficult for a fairly new computerist to 
absorb, though list and AI concepts are 
not. Nor, of course, is it complete show¬ 
ing primarily the property Ust, and 
a few other basic LISP functions. There 
are many other approaches which bypass 
property listing all together. But maga¬ 
zine pieces are, by necessity focused to 
narrow subject matter. 

So where does the interested reader 
go to expand his awareness? First, avoid 
Siklossy. He is outdated, inaccurate, 
hard-to-read. Postpone Winston, or you 
may not figure out that CONS = IF . . . 
THEN, since all is clothed in friendly, but 
high-falutin’ academic style. The best start¬ 
up I know is a darling, public-oriented, 
slightly-old paperback by Bertram 
Raphael entitled The Thinking Computer 
(Mind Inside Matter.) San Francisco: W. 
H. Freeman and Co., 1978. Second, if 
you have access to a video player, and are 
willing to splurge or chip in with some 
friends, consider renting the tv Nova 
series episode, Mind Machines, from 
Time Life Video. This presentation of AI 
conducted by the originators themselves, 
makes an excellent program for computer 
club or school audience. 

Unfortunately, the only tutorial on 
LISP for beginners I know about, an ex¬ 
tremely well-done series of lessons pre¬ 
pared and tested in a live classroom, 
remains as yet unpublished. But if you 
are willing to do a little work to translate 
DEC20-oriented MacLisp to your ver¬ 
sion, and would like to learn much more 
about AI, predicate calculus, recursion, 
(explained by a dragon), Turing, and 
much more, program a robot to wander 
about a house, and generally ape all the 

(Continued on page 22) 


Dr. Dobb’s Journal, Number 65, March 1982 
100 



DR. DOBB’S CLINIC 


by D. E. Cortesi, Resident Intern 


It Ain’t Necessarily So 

Here’s a true, sad story. It seems that 
one of the first APL interpreters ever 
built suffered a bit of overhead in passing 
from one line of program text to the 
next. Word got around in the tiny com¬ 
munity of users that one way to speed up 
a program was to cram as much onto one 
line of code as possible, rather than 
spreading the logic out over several lines. 
Those users became the gurus of the next 
generation of users, and they of the next, 
and so on. The bit of folklore was passed 
along and accepted uncritically by all 
who heard it. It’s easy, and wickedly 
enjoyable, to cram a lot into one line of 
APL code. It’s still done today, even 
though no interpreter built in the last ten 
years has imposed any significant penalty 
on a multi-line program. Those who use 
the language think (without verifying it) 
that they are optimizing their code; those 
who don’t use the language find the one- 
liners impossible to read. 

Something similar is happening today 
with BASIC. The interpreters written for 
today’s personal machines apparently im¬ 
pose a time penalty on program branches, 
a penalty proportional to the position of 
the target line in the program. Hobbyists 
and hackers discover this, and pass the in¬ 
formation on to others. “Put critical sub¬ 
routines at the top of the program,” the 
folklore runs. “Put program initialization 
code at the end; the main code will run 
faster.” “A delay loop has to be a one- 
liner, or the delay will vary depending on 
the line number.” And so on. 

All this is thoroughly bad advice. Not 
necessarily false advice, but bad advice. 
Programs are distorted into unreadable 
shapes in order to compensate for the 
failings of the language implementation. 
Those failings could be corrected easily, 
and probably will be corrected in later 
interpreters. But the folklore will go on, 
long after the system builders remove its 
rationale. 

In this column we will review several 
different ways in which a BASIC inter¬ 
preter could implement branches (GOTOs 
and GOSUBs). We’ll see how ordinary 
techniques of systems programming can 
reduce the overhead cost of a branch to a 
trivial level and make it independent of 
the target line’s position. 

Defining Terms 

First we must set up some termi¬ 
nology. A BASIC interpreter works on a 


program text which is composed of lines. 
The lines are adjacent in storage. We’ll as¬ 
sume a line consists of a sequence of 
bytes, 

NN X . ..X T 

where NN is a 16-bit integer, the line’s 
number. The variable number of bytes 
X . . . X are the text of the line, and the 
byte T is a unique terminator that marks 
the end of one line and the start of the 
next. There are n lines in the program 
text; they have an average length of b 
bytes. 

We’ll discuss algorithms in pseudo¬ 
code; in the pseudo-code all variables re¬ 
present 16-bit values, declared as integers 
or as addresses. We’ll assume that the 
interpreter keeps two global addresses 
A and Z. A points to the first line; Z 
points to a dummy line that follows the 
last line of the program text. Another 
global address, P, points to the current 
line. 

The function NUM(A') denotes the 
number of the line addressed by X. 
SCANfT) denotes advancing X to the suc¬ 
ceeding line by scanning one byte at a 
time to the byte after a terminator. 

The problem we want to solve is this: 
given a target line number T, assign a 
value to P so that T^NUMCP). 

Simple-Minded Method 0 

Method 0 is the method that people 
attribute to Microsoft BASIC for the 
TRS-80 and to the Apple and Atari 
BASICS. Its logic is painfully simple (Fig¬ 
ure 1). In order to analyze it we must 
make some assumptions about the dis¬ 
tribution of the target lines the program 
will reference. 

We’U make a simple (and not very 
realistic) assumption that T is a uniform, 
random selection from all the line num¬ 
bers in the program. Then a call of 
Method 0 will on the average invoke 
SCAN(X) half as many times as there are 
lines in the program. The further the tar¬ 
get line is from the start of the text, the 
more times SCAN will be called, and the 
longer the branch will take. 

Mediocre Method 1 

A ridiculously simple improvement 
can be made on Method 0, an improve¬ 
ment that is so trivial it is hard to see why 
it isn’t in use now. All that is required is 
that the interpreter distinguish between 
forward and backward branches (Figure 
2). If the target line number T is less than 



NUM(-P) then the search should start at 
the top of the text and proceed to P. If 
T is equal to or greater than NUM(P) then 
the scan should start at P and proceed to 
Z. Note that this logic defines a branch 
from line P to line P as a forward branch, 
so that when T=NUM(P) initially, the 
routine takes minimum time. 

If we assume that P and T are inde¬ 
pendent — almost certainly not the case 
— then Method 1 scans a partition of the 
program text that is, on average, n/2 in 
size. Since T is assumed to be uniformly 
distributed, Method 1 will find it half 
way through that partition, looking at 
n/4 lines, or half as many as Method 0. 
We can do better. 

Somewhat Brighter Method 2 

Suppose that, as part of executing 
the RUN command, the interpreter whips 
through the program text and sets M, 
the address of the line that begins nearest 
to the midpoint of the text. That 
wouldn’t cost much time, and it only has 
to be done once when the program is 
started. Then the branch logic of Method 
2 can be implemented (Figure 3). 

Method 2 is an extension of Method 
1; it chooses one of six overlapping parti¬ 
tions of the program text to scan. It can 
never scan more than n/2 lines. Under 
the assumptions that P and T are indepen¬ 
dent and uniformly distributed, we ex¬ 
pect it to look at n/6 lines. That’s a 50% 
improvement on Method 1 and three 
times as fast as Method 0. We can do 
better. 

Methods 3, 4, and 5 

The fundamental problem with all 
these methods of branching is that they 
rely on the procedure SCAN, a byte-by¬ 
byte scan over a line. SCAN must take 
time proportional to the average line- 
length, b. Method 0 takes time propor¬ 
tional to bn/2, Method 2 time propor¬ 
tional to bn/ 6. Now, b is a fairly large 
number; 40, say, in a typical program and 
120 or more in some very dense games. 
We can get real speed by doing away with 
the factor b. 

That can be done at a storage cost of 
two bytes per line. Re-specify the form 
of a line to be 

NN LL X . . . X T 

where LL is a length word that gives the 
distance in bytes to the start of the next 
line. A BASIC interpreter is in part a text 
editor, and it might be awkward to have 


6 


Dr. Dobb’s Journal, Number 65, March 1982 

ToT 



Method_0: 

qlobal addresses A, P, Z 
local address S 

if ( T=NUM(P) ) then exit. 

S := A 

while ( NUM(S)<>T ) and ( S<Z ) do SCAN(S) 

if ( S=Z ) then ERROR 
else P := S 

end Method_0. 

Figure 1 


Method i: 


global addresses A, P, z 
local addresses S, Q 


if ( T<NUM(P) ) then { 

backward branch } 

S : = A ; Q : = P 

else { 

forward branch } 

S := P ; 0 := Z 

endif 


while ( NUM(S)<>T ) and ( 

S<Q ) do SCAN(S) 

if ( NUM(S)<>T ) then ERROR 

else P : 

= S 

end Method 1. 


Figure 2 



to maintain LL while editing. That 
doesn’t matter. The editor need only al¬ 
low for the extra two bytes. When the 
RUN command is given, the interpreter 
can pass once over the program text to 
set the correct length in each LL word. 
If the editor will be kind enough to set 
LL negative when a line is changed, this 
pass can be made even more quickly. 

With LL available, we can replace 
SCAN(A') with SUCC(Z), a procedure to 
increase the contents of X by the value of 
LL in the line it points to. Let’s suppose 
that SUCC takes about the same time as a 
SCAN of a 4-byte line. Then using SUCC 
means that the factor b has been replaced 
wih a constant of 4. Methods 3, 4, and 
5 are simply Methods 0, 1, and 2 with 
SUCC replacing SCAN. Method 0 takes 


time proportional to bn/ 2; Method 5 
takes time proportional to 4n/6. If b is 
around 40, then Method 5 runs in about 
3% of the time of Method 0, or 30 times 
faster. We can do better. 

Method 6 

The procedure SUCC has to perform 
an add in order to develop the address of 
the next line. Why not keep the actual 
address in the LL word instead? The LL 
word probably should not contain an 
address at all times. When the program 
text is written to a file, lengths would be 
more appropriate. And addresses compli¬ 
cate matters even more for the editing 
phase. 

Addresses are needed only during 
execution; that is, from RUN time to 


END time. Suppose that, at RUN time, 
the interpreter passed over the 
text and set all LL fields to contain the 
address of the next line (that might even 
be quicker than setting lengths). Then at 
END time it could pass over the text 
again and replace the addresses with 
lengths. 

Now the operation SUCC(A') be¬ 
comes a simple 16-bit load. That can be 
assumed to run in half the time of 
SUCC(A") when lengths are used. Method 
6, then, is Method 5 with this change 
made; under the assumptions we’ve been 
using, it would use less than 2% of the 
time of Method 0. A branch still takes an 
amount of time relative to the position of 
the target line, but the absolute numbers 
are getting very small. However, we can 
do better. 


Smart Method 7 

So far we have made smaller parti¬ 
tions of the text and scanned them faster. 
One bottleneck remains: in our search 
for line T we make a number of compari¬ 
sons where TO NUM(S’). If we could re¬ 
duce the number of comparisons, the 
code would go faster. In order to do so, 
we have to eliminate sequential searching. 

Remove the LL words from the lines. 
Instead, keep a global count of the n 
number of lines in the program text. At 
RUN time, allocate n words of free stor¬ 
age and call it vector V. Pass over the pro¬ 
gram text looking for terminator bytes, 
and set every V,- to be the address of the 
ith line of the program. The storage cost, 
note, is still two bytes per line. 

Define new variables a, z, and p such 
that V a =A, V z =Z, and V p =P. Now the 
problem of finding a branch target be¬ 
comes one of finding i such that 
NUM(Ej) = r, and then setting p=i and 
P= V, 

This can be done with a standard bi¬ 
nary search, which we can expect will 
iterate about log2(n) times. A pseudo¬ 
code sketch of such a search looked as if 
one iteration of the search loop was 
about equal in complexity to four itera¬ 
tions of the Method 6 while-loop. 

Suppose we had a 240-line program. 
We would expect Method 7’s loop to iter¬ 
ate about log2(240) or 8 times. Method 
6’s while-loop would iterate roughly n/ 6, 
or 40, times. Method 7, then, has an aver¬ 
age expected time cost about 80% of 
Method 6’s. 


8 

102 


Dr. Dobb’s Journal, Number 65, March 1982 





More important, the time taken by 
Method 7 is independent of the location 
of the target line - it depends only on n, 
the number of lines. This removes the 
underpinnings of the folk-wisdom on 
organizing programs. The initialization 
code and explanatory comments can go 
at the top, the subroutines at the bottom, 
and no time penalties will be incurred. 
This advantage (as well as a significant 
overall speed-up in execution) is achieved 
at a storage cost less than 10% of the size 
of the program text, given typical line- 
lengths, and a small overhead cost at 
RUN time. 

Method 8 

If we are willing to pay a cost of 
three bytes per line, we can do better 
still. At RUN time, set aside 1.5« words 
of storage in a table H, and zero it. Then 
pass over the text and form a hash code 
from each line number. Use the hash code 
as an index to store the address of the 
line in H. 

With a table of size 1.5 n, and assum¬ 
ing a decent hash function, there should 
be few collisions, and they can be dealt 
in a number of standard ways. A con¬ 
servative estimate would be that any 
target line T could be found in 1.5 
probes of the table, on the average. 
The performance of Method 8 would 
depend on the speed of the hashing func¬ 
tion. In a machine that has an integer 
divide instruction in hardware, Method 8 
should be considerably faster than 
Method 7, with the result that a branch 
to any line could be executed in a time 
that is just not significant. Furthermore, 
the minuscule time penalty would be a 
constant, independent of program size. 

Conclusion 

There are well-known ways in which 
a BASIC interpreter could execute 
branches in a trivial amount of time, and 
independently of the location of the tar¬ 
get line. Methods 7 and 8 require extra 
data space amounting to less than 10% of 
the program size, and at most a few hun¬ 
dred bytes of interpreter code. Method 

7 is most suitable for 8-bit CPUs, Method 

8 for machines like the 8086, that have 
hardware divide. With 64K becoming a 
standard size and larger storage appearing 
frequently, the extra space taken by 
these methods will become unimportant 
in a very few years. Even now, an inter¬ 
preter could start out using Method 7, 


then drop back to Method 2 if free 
storage ran short. 

We can expect, then, that the conven¬ 
tional wisdom on how to organize a BASIC 
program for speed will lose all basis in 
fact in a fairly short time. Writers who 
advocate such conventional tricks with¬ 
out emphasizing their implementation- 
dependent nature do a disservice to their 
readers. Programmers who use the tricks 
when not absolutely necessary design ob¬ 
solescence into their code. 

Work Remaining 

The casual analyses done here are 
based on the unrealistic assumption that 
T (the target line) and P (the current line) 
are independent, random variables. Better 
definitions of T and P would allow better 
analyses and perhaps lead to the dis¬ 
covery of better methods. It should be 
possible to trace the dynamic behaviour 
of a sample of real BASIC programs to 
arrive at a better definition of T and its 
relation to P. Such a study would make 
an excellent article for DDJ\ 


The speed of Method 8 depends 
critically on the hash function used. What 
is a good hash function for use with 
BASIC line numbers? What are the 
characteristics of line numbers as used in 
real programs, and can the hash function 
take advantage of them? »*j 


Method_2: 

global addresses A, M, P, Z 

local addresses S, Q 

if ( P<M ) then 

if ( T<NUM(P) ) then { backward in upper half } 

S := A; Q := P { n/4 } 

else 

if ( T<NUM(M) ) then { forward in upper half } 

S := P; Q := M ' { n/4 } 

else { forward to lower half } 

S := M; Q := Z { n/2 } 

endif 
endif 

else 

if ( T<NUM(P) ) then { backward in lower half } 

if ( T<NUM(M) ) then { backward to upper half } 

S := A; Q := M { n/2 } 

else { backward in lower half } 

S := M; Q := P { n/4 } 

endif 

else { forward in lower half } 

S := P; Q := Z { n/4 } 

endif 

endif 

while ( NUM(S)<>T ) and ( S<Q ) do SCAN(S) 

if ( NUM(S)<>T ) then ERROR 
else P := S 

end Method_2. 

Figure 3 


Dr. Dobb’s Journal, Number 65, March 1982 


9 

103 





ui- INTEREST 


If you want to follow up one of these 
announcements, look in the text for a 
name in bold-faced type. That name is 
the contact point for the product; 
you’ll find it in alphabetical order in 
the Contact Points box at the end of 
the column. 


Adorable Drives 

We’re in love with a photograph — 
the picture of Seagate Technology’s 
ST706 disk drive. This has to be the most 
adorable piece of hardware we’ve ever 
seen. It is a hard disk with a removable 
media cartridge, and it fits in the space 
of a 5-inch diskette drive. Until now, 
hard disks for personal systems have had 
a very serious disadvantage: you couldn’t 
move the media around. That made it 
hard to back data up, and created all sorts 
of other operational difficulties. The ST 
706 goes a long way toward solving all 
these problems; it appears to offer the 
convenience of interchangeable cartridges 
with the speed and capacity of a hard 
disk. The metal disk in the cartridge holds 
5 megabytes (formatted). Can you 
imagine slipping a pair of these little 
jewels into your TRS-80 III? Your North 
Star? Your IBM PC? 

Well, don’t hold your breath. We 
tried hard to get more info, but Seagate 
isn’t ready to be specific about the 
ST706. The device exists in prototype, 
and should be available in sample quanti¬ 
ties near the end of 1982. Quantity pro¬ 
duction won’t begin until 1983. They re¬ 
fused to speculate about the price of the 
drive. And they were mum on the most 
crucial question of all — the price of 
the cartridge. If that isn’t cheap enough 
to be bought in quantity by individuals, 
the little beauty will have priced herself 
out of our reach. Pray, brethren. Better 
yet, write to Seagate. Tell them how 
much you want an ST706, and what you 
think a cartridge ought to cost — say, the 
same as the box of quality diskettes it 
replaces. 

Spring Out to a Conference 

It’s to be an event-packed Spring. 
Readers in the Baltimore, MD area may 
see this in time to attend the “Hamboree 
and Computerfest” on March 28th; it 
will feature speakers, a “large” vendor 
area, and flea market spaces. Contact 
GBH&C. 


!£ 

104 


Computer makers will be putting on 
their three-button armor and their busi¬ 
nesslike faces in preparation for the 1982 
Office Automation Conference, spon¬ 
sored by AFIPS. It will be held in San 
Francisco’s new Moscone Center April 
5-7. 

Then, May 14-16, East-coast Apple 
fans have the Boston Applefest to enter¬ 
tain them. It’s run by National Computer 
Shows, who claim it will be “the largest 
Apple-specific computer show in the 
country.” 

The National Educational Computing 
Conference (NECC-82) will be held June 
28-30 in Kansas City, MO. It’s too late 
to submit a paper, but you might still be 
able to reserve exhibit space; try Jon 
Rickman. 

Spring Off to the Far East 

Could you pass for a “top electronics 
executive”? Would you like to check out 
the Japanese and other far-East competi¬ 
tion at first hand? Then you should join 
the Spring Electronics Tour; it wilt visit 
the Tokyo Communications show, the 
Hong Kong Electronics show, and points 
in South Korea and Taiwan. There is an 
optional extension to the Canton Trade 
Fair and another to Beijing, both in the 
PRC. Call Ellen Chang and be ready to 
leave April 4th. Of course, if you go, 
you’ll miss Computer Swap America in 
San Jose, CA that same day. 

Sorting Cinema 

Ronald Baecker and David Sherman 
of the Unviersity of Toronto’s Dynamic 
Graphics Project have produced a 30- 
minute film on computer sort algorithms. 
The entire film is computer-generated 
animation, in color, with an original 
musical score. From the stills included in 
the brochure, they’ve done an outstand¬ 
ing job of visualizing the operation of the 
nine different algorithms they chose. It 
looks like a very desirable item for club, 
classroom, or library use. The film is 
available in 16mm or any of three video¬ 
tape cartridge formats. No prices were 
given, but it can be purchased or rented 
through the Distribution Office. 

Flock Together 

We’ve had notification of two new 
User Groups. The Autumn Revolution is 
a romantically-named association of users 
of the IBM Personal Computer. It aims to 
do all the usual things - have a newslet¬ 


ter, build a software library — and also to 
have a technical hotline phone. Who’ll 
man it? Dues are $30 a year. The release 
contained no phone number, nor any 
personal names of the organizers. 

Cary Davids is forming a User Group 
for those who own the SD Systems Z80 
Starter Kit. A newsletter, ZSTART, is 
the main group product. No dues are 
mentioned. 

(Parenthetically, isn’t “<product > 
User Group” a better phrase than 
“< product > Users Group,” or “Users’ 
Group,” or “User’s Group”? There’s a 
great temptation to put an “s” on 
“User,” and then it seems to need an 
apostrophe. The Autumn Revolution peo¬ 
ple write “Users Group,” but that’s re¬ 
dundant; a group has multiple members 
by definition. Cary Davids writes “Users’ 
Group.” While grammatical, it says that a 
number of Users own the Group. They 
don’t; they are the group. “User’s Group” 
implies that there is only one User — he 
has a gang, perhaps, but they don’t Use. 
No, we think that a Group of Users is a 
User Group.) 


Insider’s Info 

Sources of information for people 
with various professional interests in com¬ 
puting: Custom Cassette says that they 
both manufacture, and duplicate the con¬ 
tents of, cassette tapes. They claim that 
because they do both, they do it all 
better and maybe cheaper. . . Market 
Data Retrival prepare CIC’s School Di¬ 
rectories, which list each school, public 
or private, elementary or high, in the na¬ 
tion, state by state. Locations, enroll¬ 
ment, names and numbers of principals 
and district officers — everything you 
could need to market a product direct to 
educators. A typical one-state volume 
costs $32 . . . Barbara Schiffman edits 
W.P. News, a bimonthly newsletter which 
aims to inform professional writers using, 
or contemplating the use of word proces¬ 
sors. It offers, she says, equipment re¬ 
views, user interviews, and idea exchanges 
.. . Vogeler Publishing produce Micro . . . 
Publications in Review, a monthly quick 
reference to articles in “70+ Micro, Mini, 
and Technology publications.” They re¬ 
print tables of contents and cross-index 
by subject, computer, and operating sys¬ 
tem. A subscription is $56 for 12 months 
.. . DP Directory is similar, but it ap¬ 
parently aims to cover the whole data 


Dr. Dobb’s Journal, Number 65, March 1982 




processing field and doesn’t mention 
index categories; $48 for 12 months . . . 
and Elliam Associates have updated their 
$20 database of CP/M articles to include 
1981 entries. 

OK, Richard . . . 

Richard Roth, vice president of Info- 
Soft, writes us a plaintive personal letter. 
“We’ve been subscribers of Dr. Dobb’s 
since its inception ... to date, not one of 
our press releases has been printed . ..” 
The releases he enclosed do look inter¬ 
esting. InfoSoft’s primary product, it ap¬ 
pears, is a pair of CP/M-compatible 
operating systems, I/OS and Multl/OS. 
The latter is a multi-user system support¬ 
ing up to 16 concurrent tasks; it can be 
run on an enhanced TRS-80 Model II, 
among other systems. They have net¬ 
working software for linking clusters of 
systems, and a smart-terminal package 
(I/TERM) that can be driven by scripts 
prepared off-line, allowing minimal 
connect-time. 


RAT-BAS? 

An outfit called TerraSoft has pro¬ 
duced FloBASIC, a structured pre¬ 
processor for BASIC code. As with the 
well-known RATFOR preprocessor for 
FORTRAN, FloBASIC allows the pro¬ 
grammer to write with a “set of control 
constructs very much like those used in 
Pascal and C.” The program translates 
those into ordinary BASIC suitable for 
“BASIC compilers and interpreters,” 
which ones we don’t know. The price for 
what could be a most useful product is 
$75. 


Join a Mainframe Plot 

Among mainframers, CalComp is a 
big name among plotters, and CalComp’s 
Basic Subroutine Package (BSP) is a de 
facto standard for plotting software. En¬ 
ter Tesseract Associates, who have cre¬ 
ated QCAL. That’s a set of software tools 
that emulate the BSP on a CP/M system. 
With QCAL and Microsoft’s FORTRAN 
you can “employ the standard calls to the 
CalComp BSP, but utilize many other 
graphic output devices.” The $195 pack¬ 
age can be ordered with a device driver 
for Houston Instrument’s HIPLOT or for 
an NEC Spinwriter, and it comes with in¬ 
structions for writing your own device 
driver. • »j 



The Seagate ST706, a cartridge disk drive that excites lust in the hearts of hobbyists. 


Contact Points 

AFIPS, 1815 N. Lynn St., Arlington, VA 
22209; (703) 558-3612. 

Autumn Revolution, POB 55329, Tulsa, 
OK 74155. 

Ellen Chang, Commerce Tours Internation¬ 
al, 870 Market Street, Suite 742, San Fran¬ 
cisco, C A 94103; (415) 433-3072. 
Computer Swap America, POB 52, Palo 
Alto, CA 94302; (415) 494-6862. 

Custom Cassette Cartridge Company, 6228 
W. Oakton Street, Morton Grove, 
IL 60053; (312) 478-2620. 

Cary Davids, 6000 Puffer Rd., Downers 
Grove, IL 60516. 

Distribution Office, University of Toronto 
Media Centre, 121 St. George Street, Toron¬ 
to, Ontario, Canada M5S 1A1; (416) 978- 
6565. 

D. P. Directory, POB 562, Bloomfield, CT 
06002. 

Elliam Associates, 24000 Bessemer Street, 
Woodland Hills, CA 91367. 


GBH&C, POB 95, Timonium, MD 21093; 
(301) 561-1282. 

InfoSoft, 25 Sylvan Road South, Westport, 
CT 06880; (203) 226-8937. 

Market Data Retrieval, POB 510, Westport, 
CT 06881; (203) 226-8941. 

NECC-82, E. M. Staman, General Chairman, 
University of Missouri-Columbia, 305 Jesse 
Hall, Columbia, MO 65211. 

Jon Rickman, NECC Exhibits Co-ordinator, 
Northwest Missouri State University, Com¬ 
puting Center, Maryville, MO 64468. 
Barbara Schiffman, 1765 N. Highland #306, 
Hollywood, CA 90028; (213) 463-4171. 
Seagate Technology, 360 El Pueblo Rd., 
Scotts Valley, CA 95066; (408) 438- 
6550. 

TerraSoft, Dept. M, 25 Bryan Road, Roway- 
ton, CT 06853; (203) 852-0374. 

Tesseract Associates, Stinson Lake Road, 
Rumney, NH 03266; (603) 786-9561. 
Vogeler Publishing, Inc., 455 Crossen Ave., 
Elk Grove Village, IL 60007; (312) 228- 
0951. 


Dr. Dobb’s Journal, Number 65, March 1982 


11 

105 





Runic: An Interactive, 
Extensible Compiler 


fter I heard about them, I wanted an extensible com¬ 
piler, too. 

A what, you ask? An extensible compiler. FORTH 
is an example of one: it has a set of instructions, called 
“words,” that control a virtual stack machine and a way to de¬ 
fine new instructions based on those that already exist. This is 
a bald description, of course; the salient feature of a com¬ 
piler like FORTH is that the structure of the programming 
language it translates is accessible to the programmer. He can 
invent new data types or logic structures as needed for a par¬ 
ticular application. 

Boy, did I want one. The problem was that when I first 
found out about extensible compilers, back in 1977, I didn’t 
know about FORTH. It wasn’t until this last year, after read¬ 
ing about and using FORTH, that I learned enough to write 
these articles. 

To make a long story short, my fascination with exten¬ 
sible compilers led me to try writing one of my own. The re¬ 
sult of my efforts is a compiler I call Runic. What I’ve devel¬ 
oped isn’t the same as FORTH, and I make no apologies for it. 
It is, however, a working compiler, and I hope this tour of its 
design and internals will be of interest to readers working on 
similar projects. 

Like all compilers, Runic translates a high-level source 
language into (ultimately) a set of machine actions. This par¬ 
ticular article will talk about that source language’s structure. 
My next article will discuss the compiler’s construction. 

Before starting, though, a quick word about the name, 
Runic. Runic means “consisting of runes” which, according to 
my dictionary, are “characters of a magical or mysterious na¬ 
ture.” What better name for a terse, RPN-based programming 
language? 

A good way to describe Runic is through its virtual ma¬ 
chine. Interactive compilers create a machine in software that 
the programmer controls with his source statements. This soft¬ 
ware machine is easier to use than the actual hardware, since it 
usually works with higher-level objects like strings and vari¬ 
ables rather than bytes and addresses. Runic is no exception to 
this practice. The “Runic machine” consists of: 

• A data structure containing the names and definitions 
of all the words (instructions) that the Runic machine 
knows at any point in time. This is called the “dic¬ 
tionary.” 

• A last-in, first-out data stack for keeping intermediate 
data during execution. This is simply called the 
“stack.” 

• A global condition code tested by Runic words to 
allow conditional execution. This is called the “con¬ 
dition flag.” The condition flag, stack, and dictionary 
together are the Runic machine’s store. Lastly, there’s: 

• The current statement the compiler is processing. 

Now let’s clear up the fuzzy notions of “statements” and 

“words.” A Runic statement is a sequence of words, separated 
by blanks and terminated by a comment or newline. Com- 

by Marty Franz 


Copyright © 1981 by Marty Franz. 

Marty Franz, 525 W. Walnut St., Kalamazoo, MI 49007. 

12 _ 

106 


ments begin with an open parenthesis, and “newline” means 
the combination carriage-return and linefeed (CRLF). 

By “word,” we mean either an integer constant (a se¬ 
quence of digits, possibly beginning with a sign), a quoted 
string (a sequence of characters enclosed in double quotation 
marks), or what’s called an “ordinary word” (a sequence of 
characters that isn’t an integer constant or quoted string). 
Numbers (integers) and strings are the basic data types in 
Runic. Ordinary words are the names of entries in the dic¬ 
tionary; the compiler has to look them up to determine exact¬ 
ly how to interpret them. 

An ordinary word can have one of several meanings. It can 
refer to a numeric or string data object and thus act like a vari¬ 
able in other programming languages. Words defined as num¬ 
bers or strings must first be declared; they can then be assigned 
or recalled as needed. Below is an example of how they’re used 
in Runic. The character “>” is Runic’s prompt, the text after 
the open parenthesis is a comment. 

> “total” number ( This declares an integer variable 

> “myname” string ( This declares a string 

10 ttotal “Runic” t myname ( Assign them values . 

> total ? myname ? (Recall and print their values 

10 

Runic 

> 

Values are assigned to variables by using a variable’s name with 
an assignment operator (“ t ”) placed directly in front of it 
with no blank. This takes whatever is topmost on the stack 
currently and stores it as the variable’s definition. To use the 
variable’s contents in a statement, we just use the variable’s 
name as an ordinary word. When the compiler scans “total” 
and “myname” in the last statement, it will automatically 
push their contents back on the stack. Nowhere in Runic does 
a user need to explicitly know a variable’s address. 

The “?” is an example of another type of ordinary word. 
If we enter 

> “?”show 

we get back 

( Size is 7 bytes ) 

Say 

> 

> 

“?” is a user definition: a word defined as a list of other Runic 
words. User definitions are extensions to the language created 
by the programmer. They are entered with the “:” word, 
shown below. The words “say” and are examples of still 
another kind of ordinary word, one that is written in the tar¬ 
get machine’s language. These types of words are called ker- 


Dr. Dobb’s Journal, Number 65, March 1982 




nel functions, and they are the bedrock of functions that the 
Runic machine supports. “Say” is used to display whatever is 
on top of the stack, regardless of type, and the word prints 
a newline. 

A user definition can contain any sequence of Runic 
words: numeric constants, quoted strings, other user defini¬ 
tions, or kernel functions. Comments, if they are entered as 
part of the definition, are stripped off and now saved — source 
can be annotated in disk files if need be. If a word isn’t in the 
dictionary at the time it is referenced, Runic creates a dummy 
entry for it and lets the current definition continue. This allows 
a set of user definitions to be written top-down, with a 
“main” definition calling sub-definitions. This forward- 
reference ability doesn’t apply to variable assignments, though, 
since Runic has no typing information about variables that 
haven’t been declared yet. When this happens, an error mes¬ 
sage is printed and the definition is cancelled. 

Here’s how a user definition is entered, using the state¬ 
ment we used earlier to demonstrate variables: 

> “printvars” : 
total ? 

my name ? 

> printvars ( Now test the new word 
10 

Runic 

> 

A definition is ended by entering a semicolon When the 

definition is ended it is added to the dictionary and becomes 
available for use in statements. 

With the Runic machine now essentially described, here’s 
a summary of the rules of scanning statements: 

1. Get the first word in the statement. 

2. If the word begins with an assignment operator, the 
topmost data item on the stack is popped and stored as 
the word’s definition (assuming types match). Go to 
step 7. 

3. If the word is a numeric constant or quoted string, 
push it on the stack. Go to step 7. 

4. If the word is a variable, push its contents on the stack. 
Go to step 7. 

5. If the word is a kernel function, execute it. Go to 
step 7. 

6. If the word is a user definition, then the words that 
make up its definition become the new current state¬ 
ment. Go to step 1. 

7. Get the next word in the statement until all the words 
have been processed. Return to the previous statement, 
or to the console if there is none. 

Normally, processing goes sequentially from left to right 
through the statement. This quickly leads to useless programs 
unless there is the ability to test the virtual machine’s state and 
alter control flow, so Runic has kernel words for doing just 
that. 


Runic has two basic control structures, conditional and 
iterative. They resemble control structures of Pascal or C 
rather than FORTH: namely, they are not RPN-based. The 
conditional structure is the traditional if-then-else: 

If < condition > then 

< wordsl > 

Else 

<words2> 

Endif 

where < condition > is a sequence of words that sets the con¬ 
dition flag to a “true” or “false” value. Scanning continues 
with the sequence < wordsl > if the condition flag is true, or 
jumps to <words2> if not. The “else” part of this structure 
is optional; when omitted, if the condition flag is false, scan¬ 
ning resumes with the word immediately after the Endif. 

The iterative structure is the do-end. The terminating con¬ 
dition can be specified by placing a “while” or “until” word 
before the < condition > words. The “while” structure looks 
like this: 

While < condition > do 

< words > 

End 

As long as the < condition > words set the condition flag 
“true,” < words > will be scanned. As with “while” loops in 
most programming languages, evaluation occurs before the 
loop body is executed. The “until” flavor is similar to “until” 
loops in other languages, too: conditional evaluation occurs 
after the loop body has been executed. Scanning of < words> 
in an “until” loop will occur as long as < condition > sets the 
condition flag “false.” 

Here’s a sample definition that uses these two types of con¬ 
trol structures. It prints a list of numbers from 1 to 50 in 
tabular form with a newline every 5 numbers. First the main 
definition is entered: 

> “table” : 

1 

while dup 50 <= do 
dup say 
tab 

- Tab word created 

if dup 5 mod 0 = then ( “mod” is remainder ) 

. ( Print newline ) 
endif 

1 + ( Add 1 to top of Stack ) 

end 

drop 


Dr. Dobb’s Journal, Number 65, March 1982 


13 

107 




and then the definition for “tab”: 


> “tab” : 

9 >char say ( “>char” makes ASCII code a string 


The “tab” word is worth an extra mention. It’s an example of 
forward-referencing in Runic. The compiler, confronted with 
a reference in “table” to a word that didn’t exist, went ahead 
and created a dummy reference to “tab.” This is what the mes¬ 
sage 

— Tab word created 

indicates. Executing “table” at that point would have resulted 
in an error message when the word “tab” was scanned. After 
“table” was completed, “tab” was filled in and that resolved 
the undefined reference. Running “table,” we get 


> table 


1 

2 

3 

4 

5 

6 

7 

8 

9 

10 

11 

12 

13 

14 

15 

16 

17 

18 

19 

20 

21 

22 

23 

24 

25 

26 

27 

28 

29 

30 

31 

32 

33 

34 

35 

36 

37 

38 

39 

40 

41 

42 

43 

44 

45 

46 

47 

48 

49 

50 


> 


Going back to the definitions again, notice that only the stack 
was used as a data store: neither “table” nor “tab” reference 
any variables. This is a feature of RPN languages that is often 
abused, so in the example shown the stack’s use is (more or 
less) direct. 

The Runic virtual machine, the language’s control struc¬ 
tures, and some kernel functions have been presented. This 
was the source language for which I wanted to write my com¬ 
piler. Unfortunately, when I began work, many of my ideas 
were incomplete or ill-considered. For example, I had no idea 
how I was going to allow forward-referencing dictionary 
entries. All I knew was that I wanted the ability to enter and 
test definitions top-down. As it turns out, allowing pending or 
incomplete definitions (like “tab” in the last example) 
critically affected the dictionary’s structure. But I’m getting 
ahead of myself. 

I’ll end here for now by saying that, incomplete ideas or 
not, I went forth (!) to write Runic. I’ll begin telling how in 
my next article. 


14 

108 


Dr. Dobb’s Journal, Number 65, March 1982 


Put the H-8 Front Panel 
to Work 


I n this day of computers-in-a-box, one 
of the most distinctive features of 
Heath’s H8 remains the front panel, 
with its keypad and nine seven-segment, 
light-emitting diodes (LED’s). The LED’s 
are especially eye-catching when the H8 
is equipped with a disk system, as they 
continually reflect the sweep of the stack 
pointer or the program counter (or any 
other register pair or memory location 
you might want to keep an eye on). How¬ 
ever, with just a little effort, these LED’s 
can be used to print out messages, display 
information, and in general spice up your 
computer operations, all while running 
BASIC, C, Pascal, FORTRAN, tiny 
BASIC, FORTH, or any other language 
that allows you to send a byte out to an 
address in the computer’s memory. 

The H8’s front panel displays infor¬ 
mation in three groups, with the numeri¬ 
cal data usually shown in split octal nota¬ 
tion, and the register name by means of 
two letters (SP, HL, DE and so on). The 
register identification is replaced with the 
contents of memory whenever the front 
panel is set to display a memory location 
in the two leftmost groups. It should be 
noted that it’s simple to modify the disk 
operating system to allow display of data 
and addresses in hexadecimal, for those 
of you who prefer that notation. If you 
make a minor modification to the Heath 
assembler, you can do all your work in 
hex instead of split octal. I mention that 
only because many people have made the 
comment to me that it was regrettable 
that Heath chose to use only split octal. 
Not true; you do have a choice. 

For the purposes of this article, we 
will restrict our choice of language to 
BASIC, primarily to make it easier to il¬ 
lustrate the techniques used, but also be¬ 
cause virtually every H8 owner has at 
least one version of BASIC; whether he or 
she uses it for much of anything is an¬ 
other matter. We will also make use of a 
feature peculiar to Heath’s Benton Har¬ 
bor BASIC, the CNTRL-0 command 
used to jump to a special subroutine. This 
isn’t really very important, but it makes 
the demonstration more effective. Ignore 
it if you’re using Microsoft BASIC or 
some other language. 

Now for a bit of background. Heath’s 

by D.C. Shoemaker 

D. C. Shoemaker, 2000A Foxridge, 
Blacksburg, VA 24060. 


Benton Harbor BASIC, like most other 
extended BASIC’s, either disk or tape, 
supports the POKE command that al¬ 
lows the user to send a byte to any of the 
computer’s memory locations. A little 
research through the Heath manuals re¬ 
veals the fact that the LED’s contents are 
contained in addresses 8203 through 
8211 (decimal). This makes it easy to 
control the display. The next useful bit 
of information is that the LED’s will re¬ 
spond to any decimal digit POKE’d out 
into them. There are 255 patterns that 
each LED will produce; the chart in Fig¬ 
ure 1 shows what each one is. 

Figure 1 requires a brief explanation. 
It’s arranged as a matrix, such that the 
decimal digits across the top and down 
the left side give the patterns. To deter¬ 
mine what numbers produce what pat¬ 
terns, it’s only necessary to read over to 
the intersection point. For instance, deci¬ 
mal 129 gives a hollow rectangle that 
could be a zero or the letter “O”. To see 
that, read across the top to the least sig¬ 
nificant digit (9, in our example) then 
down to the other digits (12, in this case). 
Simple, when you get used to it. 

Now to the listings. Listing 1 is a 
demonstration routine that generates all 
possible patterns, and displays on the ter¬ 
minal the decimal number which pro¬ 
duced that pattern. In this case, all six 
left-most LED’s produce the same pat¬ 
tern. This need not be the way you im¬ 
plement the program; it was just easier to 
write that way. The routine does its work 
in two ways. First, it will produce all the 
patterns automatically, with no operator 
intervention. It makes use of the CNTRL- 
O feature of B-H BASIC to interrupt the 
generation and hold the pattern for exam¬ 
ination. When you tire of that approach, 
however, you may use the other mode of 
operation and enter a decimal number to 
check what the pattern looks like. This 
routine is probably best used to become 
familiar with which patterns can be pro¬ 
duced, and what they look like on the 
front panel. All look good, but obviously 
some letters come across better than 
others. 

Listing 2 is a simple application of 
what we’ve seen so far. It is used to send 
a travelling display across the H8 front 
panel, from right to left, theater-marquee 
style. The phrases are simple, but easily 
read, and can be altered as to timing and 
sequence so that they come closer to¬ 
gether or farther apart. By changing the 


data statements at the end of the pro¬ 
gram, any desired message can be sent. 
This is a technique that can be readily in-’ 
corporated into any of your BASIC pro¬ 
grams, especially since the only “exotic” 
feature of BASIC you need is the POKE 
statement, or the equivalent command in 
whatever language you choose. 

If you have an H8, you have a front 
panel. Why not make use of it? Few other 
systems give you the degree of freedom 
and flexibility available with the H8. For 
me the front panel is the most valuable 
single hardware feature of the entire sys¬ 
tem. 

Technical Addendum 

For those who are interested in more 
fully utilizing the H8 front panel, here are 
some other memory locations you can 
POKE. The first, 8199, controls the mem¬ 
ory display. To use it, POKE 8199,1. To 
display a register, POKE 8199,2. Then 
POKE 8197,N where the value of N is 
selected from the following: 

N Register 

0 SP 

2 AF 

4 BC 

6 DE 

8 HL 

10 PC 

By selecting the appropriate values of 
N, you may call up any information you 
want on the front panel. This can be 
especially useful in debugging and in 
interfacing work, and in the incorporating 
of machine-language subroutines into 
programs written in BASIC and other lan¬ 
guages. 

(Listing begins on page 34) 


Dr. Dobb’s Journal, Number 65, March 1982 


17 

109 




Figure 1. Possible LED pattern combinations 


5 6 7 8 9 


2 

IS 

3 

1—. 


□. H U. 


ID 


an 


i i 


5 H. 


6 


C=3. I_I. 


8 Ril 


9 F. 


n e. c. 


3. I_R. n. H. 


rp.h.i '.F.r. 


a u. a a a 


E. 


R. 1 


cd. i_l. □. 


ddEFc 


n. i i. E. 


□. a _i. 


13 bd 


14 EEtL 


15 HI iPP 


16 3 □ a u 


I I 


17 


18 R 


H. 


B □ 


bLEDdU 


nnHi ir 


HI 1 f r H 


5 3 3 3 3 3 


' I 


''■I 


E 


21 H 


22 


23 


24 R 3 H 


'■ 3 


33 


d 


l—II I I—I 


d Jdudi _i 


33 


, i 3 3 F 


3 3 3 55 


Dr. Dobb’s Journal, Number 65, March 1982 






























































































































































































Improvement Upon a Division 
Program by Leventhal 


T he purpose of this paper is to give 
an improvement in timing, without 
affecting memory requirements 
and by changing only two instructions, 
in a 16-bit-by-8-bit division program for 
the 6502, due to Leventhal (Ref. 1, pp. 
8-15). 

The original algorithm is reproduced 
in Figure 1. It assumes that the 16-bit 
number in hexadecimal locations 40 and 
41 (with bytes reversed, as usual) is being 
divided by the 8-bit number in location 
42 to produce a quotient in location 43 
and a remainder in location 44. All quan¬ 
tities are unsigned, but the leftmost bit of 
location 41 and the leftmost bit of loca¬ 
tion 42 are both assumed to be zero; this 
would be the case if the division were ori- 


by W.D. Maurer 


W. D. Maurer, George Washington Univer¬ 
sity, S.E.A.S., Washington, DC 20052. 

Figure 1 


ginally a signed division and the absolute 
values of the signed quantities had been 
taken. Overflow and division by zero are 
not checked. 

The improvement is concerned with 
eliminating the INC instruction. Notice 
that INC adds one to the quotient, thus 
setting the current bit of the quotient to 
1. If the INC is not done, the current bit 
of the quotient is zero. 

Notice, however, that if INC is exe¬ 
cuted, SBC has just been executed, and 
this subtraction has produced a non¬ 
negative result. Hence the carry bit will 
be equal to 1. On the other hand, if INC 
is skipped, by branching on carry clear to 
CHCNT, then the carry bit will be equal 
to zero. 

Hence, in either case, the carry bit 
will be equal to the current bit of the 
quotient. This will be true at CHCNT, 
and therefore also at DIVID when we go 
back to the start of the loop, so that the 
bit can be rotated into the quotient by 


changing the ASL $43 to ROL $43 at this 
point. 

The last time through the loop, the 
final bit of the quotient will still be in the 
carry bit, so that an extra ROL $43 is 
necessary immediately following the 
BNE. The two instructions changed are 
therefore: 

(1) Change ASL $43 to ROL $43. 

(2) Eliminate INC $43 and put an¬ 
other ROL $43 between BNE 
DIVID and STA $44. (All of the 
four instructions above have the 
same length, so that the memory 
requirements of the program are 
not affected.) 

Note that the first time through the 
loop, the ROL at DIVID inserts a non¬ 
sense bit into hexadecimal location 43. 
This nonsense bit is then rotated all the 
way through this location and becomes 
the final value of the carry bit when the 



LDX 

#8 

; NUMBER OF BITS 

IN DIVISOR = 8 


LD A 

$40 

;START WITH LSB 

'S OF DIVIDEND 


STA 

$43 




LD A 

$41 

; G ET MSB'S OF DIVIDEND 

DIVID 

ASL 

$43 

; SHIFT DIVIDEND 

, QUOTIENT LEFT 1 BIT 


ROL 

A 




CMP 

$42 

;CAN DIVISOR BE 

SUBTRACTED ? 


BCC 

CHCNT 

;NO, GO TO NEXT 

STEP 


SBC 

$42 

;YES, SUBTRACT 

DIVISOR (CARRY = 1) 


INC 

$43 

;AND INCREMENT 

QUOTIENT BY 1 

CHCNT 

DEX 


;LOOP UNTIL ALL 

8 BITS HANDLED 


BNE 

DIVID 




STA 

$44 

; STORE REMAINDER 


BRK 





20 


Dr. Dobb’s Journal, Number 65, March 1 982 

TiT 




final ROL is done. 

This fact suggests a further improve¬ 
ment in the program. We have noted that 
overflow and division by zero are not 
checked in this program and therefore 
must be checked externally; this takes at 
least two instructions. Suppose, however, 
that we were to check this in the given 
division routine itself. These two instruc¬ 
tions would then be moved into the rou¬ 
tine from outside it, thus causing again, 
no change in space requirements. The in¬ 
structions might be CMP $42 and BCS 
ERROR inserted just before DIVID. 
(This works because the contents of loca¬ 
tion 41 are in the A register at this point. 
If the contents of location 42 are less 
than or equal to this, the carry will be set, 
and we have either the division-by-zero 
case, where location 42 contains zero, or 
the overflow case.) 

Figure 2 

DIV LDX # 


Now notice that, in this case, the 
nonsense bit, as mentioned above, will al¬ 
ways be zero, because when the first ROL 
is done the carry will be clear (otherwise 
we branched on carry set). Therefore the 
final value of the carry bit will also be 
jzero, after the nonsense bit has passed 
through location 43. On the other hand, 
jn either of the two abnormal cases, the 
Carry will be set. 

The further improvement is now as 
follows. Instead of branching to ERROR 
on carry set, we simply branch to the end 
df the program. We can now make the 
program into a subroutine by adding an 
RTS, and since this leaves the carry flag 
Unaffected, it can serve, in the calling pro¬ 
gram, as an indication of error. Thus, for 
ekample, if the name of the subroutine is 
DIV, then JSR DIV followed by BCS 
ERROR will serve, in the calling program. 


; NUMBER OF BITS 


to go to ERROR in either of the error 
cases and continue in the normal case. 
The program with all these improvements 
is illustrated in Figure 2. 

If only the initial two changes are 
made, the timing improvement will be 
5(n-l) cycles, where n is the number of 
one-bits in the quotient. The first change 
makes no difference; the new ROL takes 
5 cycles, outside the loop, while the eli¬ 
minated INC takes 5 cycles for each one- 
bit in the quotient. 

Reference 

'Leventhal, L. A., 6502 Assembly Lan¬ 
guage Programming, Osborne/McGraw- 
Hill, Berkeley, California. 


N DIVISOR = 8 


DIVID 


CHCNT 


$40 

$43 

$41 

$42 

DONE 

$43 

A 


CMP 

$42 

; CAN 

BCC 

CHCNT 

; NO, 

SBC 

$42 

; YES 


DIVID 

$43 

$44 


DONE 


;START WITH LSB'S OF DIVIDEND 


GET MSB’S OF DIVIDEND 
SHOULD BE LESS THAN DIVISOR 
IF NOT, ERROR EXIT (CARRY = 1) 

SHIFT DIVIDEND, QUOTIENT LEFT 1 BIT 
(AND NEW ANSWER BIT — SEE DEX BELOW) 
CAN DIVISOR BE SUBTRACTED? 

NO, GO TO NEXT STEP (CARRY = 0) 

YES, SUBTRACT DIVISOR (CARRY = 1) 

NOTE CARRY = NEW ANSWER BIT 
LOOP UNTIL ALL 8 BITS HANDLED 
SHIFT IN THE LAST ANSWER BIT 
; STORE REMAINDER (CARRY = 0 HERE) 

; QUIT (CARRY 0, NORMAL, CARRY 1, ERROR) 


Dr. Dobb’s Journal, Number 65, March 1982 
H2 


21 



H-8 Front Panel (Listing continued, text begins on page 17) (Continued from page 35) 


390 POKE A + 2,255:POKE A+1.L 
400 PAUSE 20 

410 POKE A+1,255:POKE A , L 
420 PAUSE 20 

430 POKE A+1,255:PAUSE 20:POKE A.L 
440 PAUSE 20 
450 POKE A,255 
460 NEXT K 

470 REM Number of characters to print 
480 DATA 27 

490 REM Data for characters 

500 DATA 146,254,128,164,144,162,164,146,140,143,143,129,255,159,200,224,178 
510 DATA 164,132,241,128,176,129,255 
520 DATA 134,162,136,255 
530 END 

End Listing II 


Letters (Continued from page 5) 

historic accomplishments presented by 
Raphael and the Nova tape, perhaps a 
letter to David Touretsky, Computer 
Science Dept., Carnegie-Mellon Univer¬ 
sity, Pittsburgh, PA 15213 will convince 
this AI researcher/instructor to release 
his rough draft to you for some reason¬ 
able price. 

Hofstadter ( Godel , Escher, Bach of 
course) gives a nice example of recursion 
in language generation beginning on page 
130. The charts here mirror those com¬ 
monly used by Pascal hackers, so P- 
coders, welcome to the AI programmers’ 
circle! The discussion on chess players is 
also quite clear, p. 150. 

An AI/Robotics group has started up 
here again; interested parties willing to 
exchange information can write to me. 

Good luck! 

Abby Gelles 
185 W. Houston St. 

New York, NY 10014 

Modem Routine on RCPM 

DDJ. 

I have rewritten the receive routines 
I used (“Terminal Programs for North 
Star,” DDJ #61) in MODEM.PAS so they 
no longer rely on X-ON/X-OFF to con¬ 
trol the transmission of data from the 
PRIME. The changes allow me to receive 
data at the same rate I can transmit and 
with more reliability. I have also modified 


MODEM.PAS to work with a PMMI- 
103 modem and added auto-dial, retry, 
and baud rate change. I placed a copy of 
this version on the Hyde Park RCPM/ 
RBBS in Chicago (312-955-4495). 
Sincerely, 

Richard Blessing 
Rt. 4, Box 5 
Geneseo, IL 61254 

Editor Notes 

Dear Sirs: 

Enclosed find my check for $39.00, 
please renew my subscription. I had really 
felt that the magazine had somehow lost 
that fantastic ability to have at least one 
or two articles in each issue that were 
exactly what I had been looking for, or 
had not even thought of. The January 
issue arrived this morning and you have 
done it again. Not two days ago I was 
grumbling about needing to get some sort 
of screen editor written, and now it looks 
like Ream’s editor will do most of what I 
need. 

Some of the points brought up in the 
article on the 68000 are very relevant, in 
particular the statement about the lack 
of software published for the sixteen-bit 
machines. I am working on a small Z8000 
design and hope to get it running soon. 
This all depends on failing to improve the 
design to a point that it never gets built. 
If I can restrain myself, I hope to submit 


a monitor-debugger to you. This should be 
followed by a simple, resident assembler, 
and patches to Cain’s C compiler, with no 
register allocation optimizing, yet. I must 
warn you that my track record is only 
fair, and I make no guarantees. 

Keep up the good work. 

Sincerely, 

Don Taylor 

627 S.W. Third #3 

Corvallis, OR 97333 


22 


Dr. Dobb’s Journal, Number 65, March 1982 

m 





A Pattern Classification 
Program* 


*Based on Fisher’s Methods 

P attern classification computer pro¬ 
grams, such as the one presented in 
this paper, have applications in in¬ 
dustry, science, medicine, and business. 
Their use in artificial intelligence systems 
is rapidly increasing. 

Pattern classification involves the 
computer manipulation of measurable 
features of objects from various classes 
for the purpose of classifying the objects 
without human intervention. This paper 
describes a two-class pattern classifica¬ 
tion computer program written in Data 

by K.F. Wegner and 
D.E. Raeside 

Work supported in part by funds provid¬ 
ed by Richard and Addie Fleischaker. 
K. F. Wegner and D. E. Raeside, Depart¬ 
ment of Radiological Sciences, University 
of Oklahoma Health Sciences Center, 
Oklahoma City, Oklahoma. 


General Extended BASIC which is suit¬ 
able for use on small computer systems 
(the program contains Hazeltine 1420 
CRT terminal screen control commands). 
The program assumes the availability of 
a sufficient number of objects of known 
classification (training samples) to permit 
samples of unknown classification to be 
classified automatically. The program 
uses Fisher’s method (see pages 114-121 
of Reference 1), a method of transform¬ 
ing complicated pattern classification 
problems into simple ones. As an example 
of the simplification afforded by Fisher’s 
method, imagine a classification problem 
in which the two features Fj and F 2 are 
used to classify samples. Each pair of 
measurements may be represented as a 
point in a two-dimensional plot of F, 
versus F 2 (see Figure 1). Fisher’s method 
can be viewed as the projection of these 
points onto a line. When the direction 
upon which the points are projected is 
properly chosen, good class separation is 
obtained (as in Figure 2). Figure 3 shows 
the destruction of class separation pro¬ 
duced by projecting the points onto some 


other direction. 

The training data base selected to 
illustrate the authors’ program consists of 
100 samples, 50 from each of two classes. 
Each datum consists of measurements of 
the sepal and petal lengths and widths of 
an iris plant (see Figure 4) belonging to 
the species iris setosa or iris versicolor 
(the data are taken from Fisher’s original 
paper, Reference 2). The projected point 
for each training sample is shown in 
Figure 5. An unclassified sample is shown 
in Figure 6 as a letter “A”. It can be clas¬ 
sified by simply noting which training 
cluster it is closest to. This particular un¬ 
known sample should be assigned to class 
2 (iris versicolor). SBj 

References 

1 R. O. Duda and P. E. Hart. Pattern Clas¬ 
sification and Scene Analysis. Wiley - 
Interscience, New York, 1973. 

2 R. A. Fisher. “The use of multiple mea¬ 
surements in taxonomic problems.” 
Annals of Eugenics, 7 (1936) 179. 

(Listing begins on page 37) 


Figure 1. 

A simple two-class pattern classification 
problem. The open circles represent data 
from Class I and the solid triangles re¬ 
present data from Class II. The coordi¬ 
nates F[ and F 2 are measurable features 
common to Class I and Class II objects. 



Class a Class c 


Figure 2. 

An illustration of the simplification which Fisher’s method 
provides for the pattern classification problem of Figure 1. 
Good class separation is obtained with a good choice of the 
direction upon which the data are projected (P* can be used as 
a boundary separating the two classes). 


Dr. Dobb’s Journal, Number 65, March 1982 

TT4 


23 





FISHER LINEAR DISCRIMINANT PLOT 


2 

1 11 

2 

1 11 

2 22 

1 11 1 

22 22 2 2 

1 111 1 

22 22 22 2 

11 11111 

22 22222 2 2 2 

in inn i i 

22222222222222222 

1 11 111111111 11 11 


I I I 

-0.8835 -O.HH 0.6008 



24 


Dr. Dobb’s Journal, Number 65, March 1 982 

115 





Pidgin for the 8080 
Under CPfM 


There are many ways to approach 
a problem and even more ways to 
solve it. This is by no means the only 
possible implementation and both Bill 
Gale and / invite others out there in 
the reader audience to make an idea 
better. How about an 8086 version? 

- Andrew L. Bender 


T he recent publication of “Pidgin, A 
Systems Programming Language” in 
Dr. Dobb’s Journal (DDJ #57) was 
an invitation to those interested in pro¬ 
gramming languages to prepare a specific 
implementation for a specific processor. 
After an initial look at things, I was 


by Andrew L. Bender 


Andrew L. Bender, M.D., Neurological 
Services, Inc. 336 Center Ave., West- 
wood.NJ 0 7675. _ 

Copyright © 1981 by Andrew L. Bender, 
M.D. Permission is granted for individual, 
personal use in a non-commercial manner. 
All commercial rights reserved. 


tempted to implement my version of 
Pidgin by writing the macro processor, 
Tincmp, in assembly code using a macro 
assembler. This turned out to be more 
than a trivial task despite the excellent 
software tools which can be used under 
CP/M. Tincmp is a large program and 
there are many non-trivial bookkeeping 
tasks associated with the translation of 
this size program into assembly code. Not 
only are these tasks boring, but also 
checkout of such a large program is 
fatiguing and slow. 

I initially investigated higher level 
languages, as were suggested in the Dr. 
Dobb's article. In both languages available 
to me, BASIC and FORTRAN-80, 
Tincmp would have been too cumber¬ 
some and difficult to get running. I had a 
copy of the new Digital Research PL/I-80 
compiler and I knew that it would be 
easy to program the Tincmp compiler in 
PL/I-80 but I felt that my lack of experi¬ 
ence with this compiler would make for 
slow going, and the average hobbyist 
would probably not have this compiler 
available. I found in Volume 51 of the 
CP/MUG library a program which was 
a relative of Tincmp. This program, 


STAGE2, was implemented by Dick 
Curtiss step-by-step from the text Im¬ 
plementing Software for Non-Numeric 
Applications by William Waite. If Tincmp 
was written in Pidgin and Pidgin could 
be compiled by a macro processor then, I 
reasoned, STAGE2 could compile 
Tincmp written in Pidgin if it were pro¬ 
vided with a suitable set of STAGE2 
macros designed to translate Pidgin. I 
would let STAGE2 do the translation 
while I learned about STAGE2. 

A decision had to be made at this 
point as to how Tincmp was to imple¬ 
ment Pidgin. It was easiest to take the as¬ 
sembly language approach. First of all, 
the 8080/Z80 processors do not lend 
themselves to the easy production and 
execution of relocatable programs. The 
6502, like the 6800 or 6809 can easily 
run in an environment of relocatable pro¬ 
grams because most of the instructions of 
these microprocessor series see memory 
as a relative set of locations rather than 
the more physical organization of the 
8080 or Z80, whose organization de¬ 
pends on the actual operand address as 
a part of many instructions. Where the 
6502 might approach an address as 5 


Comments on 8080 Pidgin 
by William A. Gale 

This is the first implementation of 
Pidgin for a non-6502 chip that I am 
aware of, and I am delighted to see it. 
OSI users may be interested to know 
that a version has been brought up on 
an OSI Challenger with tape storage by 
Walter Anderson. 

Bender’s decision to use Stage 2 
rather than Basic is probably a good 
one for efficiency in the initial step. 
My Basic version (of a precursor to 
Tincmp) would have taken about one- 
and-a-half hours to compile Tincmp, 
while Anderson reported 10 hours for 
his Basic version of Tincmp! That 
Tincmp can compile itself in 3 minutes 
shows the efficiency of compiled code. 

The advantage of being able 
compile Pidgin for a relocating linking 
loader are numerous. My own purpose 
in designing Pidgin included being able 
to write such a program, however. I 
have now written such a relocating, 
linking loader in Pidgin, called Maclod. 

The 6502 relative branch instruc¬ 
tions are not actually useful for Pid¬ 
gin as compiled by Tincmp. The 


reason is that Tincmp has no idea how 
far ahead a transfer may be going. As 
a result, all branches become five 
bytes, and include a jump to an ab¬ 
solute location in the form 

BNE 3 

JMP absolute 

for example. The relative branch just 
jumps over the absolute jump. The 
worst of both worlds! The 8080 three- 
byte test branches would be more ef¬ 
ficient for Tincmp. A smarter compil¬ 
er, such as Meta4, can get the two- 
byte branch where it is possible. This 
is done in a compiler for a high-level 
language, Spartan, now written for 
Meta4. However, a smart compiler is 
not written for Pidgin. Anyone in¬ 
terested? 

The use of parameter statements 
to help isolate machine dependencies 
may be a good idea. I could have done 
better in the Tincmp code, perhaps, by 
putting all such assignments as the first 
statements of the main program. I did 
mark lines I considered system depen¬ 
dent with strings of exclamations. 
However, neither of these techniques 
is a complete solution, because the 


length of buffers is system dependent 
and is set by constants in Pidgin. A 
related problem is keeping the internal 
setting of a variable holding the length 
of an array matched with its declared 
length. 

Bender’s discussion of the use of 
prefixes to make unique labels should 
be useful to anyone else implementing 
Pidgin. You will find similar prefixes 
buried in the 6502 Pidgin macros, but 
no discussion of their use. If you are 
relying on Tincmp for the assembly 
stages of the compilation, making 
labels with prefixes diagnostic of the 
kind of statement needed to generate 
a definition helps in debugging. When 
you see FI05 written out as a mis¬ 
matched line in the third pass, for in¬ 
stance, you know that an ENDIF is 
missing in the source code. 

The use of a special $$=+000 
macro is an example of a slight opti¬ 
mization possible in the Tincmp 
framework. A slighter optimization in 
the 6502 setting would be to make a 
special macro for 

I $$=+00000 

as 


Dr. Dobb’s Journal, Number 65, March 1982 

lie 


25 





locations from here in a forward direction 
or 7 locations back from here in a back¬ 
ward direction (forming the effective ad¬ 
dress in hardware during instruction exe¬ 
cution) the 8080/Z80 needs to have the 
actual address of each operand for its 
memory reference instructions and, with 
a few exceptions on the Z80, even for 
its jump instructions. In the second 
place, the 8080/Z80 have available 
operating systems and operating-system- 
dependent programs which demand the 
physical loading of programs at certain 
memory addresses. CP/M, as an example, 
demands that the user programs be 
loaded into a transient program area 
which in the standard version of CP/M 
begins at 256 (100H). Other versions of 
CP/M were used but they had a different 
transient program starting address or 
“bias.” If Pidgin was to be useful on all 
different systems it would be necessary to 
provide some convenient means of chang¬ 
ing the address of the start of the pro¬ 
gram other than changing the HIM EM 
and LOMEM values. As a matter of fact, 
these values shouldn’t appear in a relo¬ 
catable program at all. 

Some statements were therefore not 


implemented for the 8080/Z80 series. 
The statements not implemented are 
discussed here: 

1. LOMEM This command is not 
used by this version of Pidgin and 
could be used in an absolute as¬ 
sembly to assemble an ORG card. 

2. HIMEM This command is also 
not used. In an absolute assembly 
it might be used to assemble an 
ORG card for a data region. 

3. REGISTER This command does 
nothing. 

The specific implementation of Pid¬ 
gin for the 8080 is slightly different than 
the implementation described by Bill 
Gale. Pidgin for the 8080 compiles to 
assembly code. This code is written to the 
output file in a format suitable for assem¬ 
bly with either Microsoft’s MACRO-80 
assembler or RMAC, Digital Research’s 
macro assembler. Both of these assem¬ 
blers produce relocatable code which can 
be positioned anyplace in memory when 
the code is link edited. The task of pre¬ 
paring relocatable code suitable for direct 
input to a linkage editor accepting a bit 
stream format (such as Microsoft’s L80 


or Digital Research’s LINK-80) with 
Tincmp was investigated but felt to be be¬ 
yond the capabilities of Tincmp. How¬ 
ever, suggestions are given below for the 
implementation of this for the CDL 
LINKER linkage editor. All of the macro 
templates and expansion directives are 
contained in the file MACROS.PGN and 
there are a few more macros in the 8080 
implementation. 


Differences Between 8080 and 
6502 Pidgin 

Discussion of these particular altera¬ 
tions is needed in order show the user 
how each fits the 8080/Z80 system under 
CP/M. 

The parameter statement PARAME¬ 
TER K$$ = $$$ was designed because it 
was not possible to put all of the machine- 
dependent and system-dependent code in 
one area without it. As an example, the 
6502 system for which Pidgin was de¬ 
signed uses 141 as an end-of-line new- 
line mark, and the 8080/Z80 uses 13. 
End-of-file in the 6502 I/O system is de¬ 
fined as 255, and in the standard 8080/ 


LDA #0 

TAX 

which will save a byte. These work 
because Tincmp scans its list of 
macros from first to last. If the more 
specific macro is placed before the less 
specific, the more specific lines will be 
matched sooner. These optimizations 
might save ten bytes in several thou¬ 
sand. Bender made another optimiza¬ 
tion to get rid of an unusable jump in¬ 
struction that is generated by the first 
CASE statement of a CHOOSE ON. 
This was possible through compiling 
code for an assembler — he could reset 
the ORG and obliterate the offending 
jump. Code generated for Maclod 
could also use this trick, but absolute 
code generated by Tincmp cannot. 

I’m not sure I understand 
Bender’s treatment of the information 
on closing a buffer, or his suggestion 
of separate buffers for each file. I 
have deliberately reused buffers, once 
a file has been completely read and 
closed, in order to save space. I believe 
this corresponds, however, to reassoci¬ 
ating a new file name with the buffer, 
and it may not be what he is referring 


to. I have found it useful to put a 
statement to close a buffer immediate¬ 
ly before each open statement. This 
obviously reflects a design problem, 
perhaps the same one. For me, quick 
on the reset button when a program 
isn’t running right, the failure to 
close files on such a panic exit meant 
the program might not run when re¬ 
started because trying to open an 
opened buffer gives an error. 

Bender’s related closing of files 
before exiting is a good thing to auto¬ 
mate and is possible in the framework 
of an operating system. But don’t be 
lulled — a Pidgin program should close 
files before exiting anyhow. I had 
hoped not to assume an operating sys¬ 
tem for Pidgin, so that operating sys¬ 
tem software could be written in Pid¬ 
gin. However, I’m glad to see a version 
that will support development of Pid¬ 
gin programs in a friendly environ¬ 
ment. 

I am interested to see Bender’s 
estimate that only a 20% gain in space 
could be achieved by handcoding. I 
have estimated that it might be 30- 
40%, but I have not done a study of it. 


The reason is that programs keep 
changing for a long time, and the ease 
of changing and porting a Pidgin pro¬ 
gram would be worth a factor of two 
in space — at least for programs no 
larger than 10K as compiled by Pidgin. 
As soon as a hand optimization was 
done, one would be very reluctant to 
change the program further. I believe 
Bender has made more use of run¬ 
time subroutines than I did. This 
achieves more compact code at a slight 
time penalty. In Spartan, I have made 
this tradeoff for compactness. 

Both Bender and Anderson have 
made use of seven Pidgin programs 
which test the Pidgin macro defini¬ 
tions fairly thoroughly. These are 
available for the asking to anyone in¬ 
terested in implementing Pidgin. 

Maclod and Spartan are available 
from Bootstrap Toolkit, 439 S. Orange 
Ave., S. Orange, NJ 07079. Write for 
prices and detailed descriptions of 
them, as well as of 8080 Tincmp, Pid¬ 
gin and Meta4. The CP/M version con¬ 
tains the source code, assembly code 
and object files on an 8-inch, single¬ 
density CP/M format disk. 


26 


Dr. Dobb’s Journal, Number 65, March 1982 

TFT 





Z80 system it is 26. Putting these in a 
parameter statement makes all of these 
machine-dependent items easy to spot 
and change, increasing the portability of 
the program and clarifying its design. The 
6502 Pidgin system can resolve these 
parameter references during the third pass 
and the 8080/Z80 system generates 
“EQU” statements to deal with the para¬ 
meter statement. In order to properly 
process the assignment of parameter vari¬ 
ables, the construction of the $$=+K$$ 
template was specifically designed to get 
the proper reference to a parameter vari¬ 
able. Thus, consider the statements 
shown here: 

PARAMETER KLF=010 

PARAMETER KNL=013 

PARAMETER KEF=026 


BEGINMAIN(AC,IAV) 


EF=+KEF 

LF=+KLF 

NL=+KNL 


Assuming that NL,LF and EF were all 
declared BYTE, in the 8080/Z80 system 
the following code would be generated: 
.KLF EQU 10 
.KNLEQU 13 
.KEF EQU 26 


7START: LXI SP,?STACK 
CALL ?INIT 
EXTRN 7INIT 


MVI 

A,.KEF 

STA 

.EF 

MVI 

A,.KLF 

STA 

,LF 

MVI 

A,.KNL 

STA 

.NL 


It is necessary to comment at this 
point on the format of the assembly code 
generated by the 8080/Z80 version of 
Pidgin. In order to prevent the corrup¬ 
tion of certain symbols which the assem¬ 
bler has self-declared as sacred and in¬ 
corruptible (such as register names, and in 
the case of RMAC, the actual operation 


Dr. Dobb’s Journal, Number 65, March 1982 

TuT 


codes themselves), I have generated al¬ 
most all labels with a leading period. This 
makes all declared symbols unique in 
that, for example, the casual use of “SP” 
as a byte variable in a Pidgin program 
won’t blow the stack pointer assignment 
during the assembly of the resulting pro¬ 
gram. All subroutine references are gener¬ 
ated with two leading periods so that a 
subroutine name could be unique and dis¬ 
tinct from a variable name. As an exam¬ 
ple the Pidgin statement GOSUB ER 
would generate CALL ..ER. GOTO 
statements in Pidgin require label refer¬ 
ences elsewhere in the program. These 
references are always encoded with a 
leading question mark followed by the 
two letters “LL” which give a clue as to 
which statement generated the label. As 
an example, the statement GOTO 12 
generates JMP 7LL012 and its label coun¬ 
terpart always generates 7LL102:. This 
also makes jump labels distinct from sub¬ 
routine names. The informal syntax of 
Pidgin as stated in the article by Gale 
makes no restrictions on these labels so 
I have assumed them to be all unique. 
The WHILE statement always generates 
a .Xnnn: label which is the top of the 
loop statement. ENDWHILE generates a 
.Wnnn: label which identifies the bottom 
of the loop. Just prior to the .Wnnn: tag 
the compiler always compiles a jump in¬ 
struction to the top of the loop. Within 
the WHILE . . . ENDWHILE sequence the 
ON statement generates a fetch and test 
sequence to jump to the bottom of the 
loop tag. Similarly, all the control se¬ 
quences generate .iinnn: tags. An IF state¬ 
ment generates .Fnnn, CHOOSE ON gen¬ 
erates no sequence, ENDCHOOSE gener¬ 
ates an .XC sequence, and CASE gener¬ 
ates a .UP sequence. These tags are im¬ 
portant to the Pidgin programmer be¬ 
cause in the case of unpaired statements, 
the assembly will produce undefined sym¬ 
bols in the area close to where the error 
occurred. 

Whenever the BEGINMAIN directive 
is encountered, 8080/Z80 Pidgin always 
compiles two closed subroutines: 
7 SET AC and 7INTCK. 7SETAC is used 
by the comparison operators in setting 
the accumulator to one or zero depending 
on the outcome of the logical tests being 
performed and 7INTCK is used for inte¬ 
ger inequality tests. A cell .ERASER, is 
also set aside for the CHOOSE ON/CASE 
statements. Since Tincmp is blind with 
regard to what has been happening over¬ 
all in your program, it is difficult, with¬ 


out a second pass, to generate this code 
only if it is needed. After these standard 
sequences, the START label is generated 
and then the code to set the stack point¬ 
er. The subroutine 7INIT is then called. 
This subroutine may be coded to do any¬ 
thing the user wants done at initial entry 
to the Pidgin program. In this version of 
Pidgin (Version 1.05) it extracts the file¬ 
names from the user control statement 
and sets the global variable AC to the 
number of file names in the call line. Up 
to six names can be used in the call line. 
7INIT then returns control to the user. 

The TOP statement in 8080/Z80 
Pidgin generates EXTRN statements for 
7INIT, 7ENDING, 7MSG and 7BOOT 
labels. It then declares all of the system- 
wide global variables. Specifically, these 
are ER, the error indicator byte from the 
I/O System; IAV, an unused integer vec¬ 
tor used to convey file information in the 
Apple II implementation; and AC, which 
contains the number of files mentioned in 
the user control statement. All of these 
values are generated in IOCTRL and 
labelled common. A “blank” common de¬ 
claration is then generated so that all of 
the BYTE and INT declarations which 
follow it will be in “blank” common. 
This is done so that later versions of 
Pidgin will allow independently compiled 
external procedures. The subsequent oc¬ 
currence of the BEGINMAIN statement 
then forces the end of the “blank” com¬ 
mon region by the generation of a DSEG 
directive and a single word of DSEG 
memory “.ERASER.”. This byte is then 
followed by the CSEG directive and the 
actual instructions generated by Pidgin. 

The ENDMAIN directive generates a 
call to the closed subroutine “7ENDING” 
which in this version of Tincmp loops to 
close all open files. Return from 7END- 
ING is to a JMP 7BOOT which reboots 
from zero in CP/M. BOTTOM generates 
a stack of length 60 and an END 7START 
directive. RETURN and ENDSUB each 
generate RET instructions. There is no 
check for unbalanced SUB . .. ENDSUB 
directives or for RETURN in a main pro¬ 
gram segment. 

There is a special template $$=+000 
which is used to generate the XRA A, 
STA .$$ code sequence. This eliminates 
one byte from the generated code. Since 
the 6502 has no “zero address” or im¬ 
mediate address operands, these special 
cases are not included in the original dis¬ 
tribution. 

Although discussed more fully 


27 




below, the statement ASSOCIATE FCB $ 
WITH I $ $ is used to attach the nth file 
in the control statement to a particular 
file number contained in an integer vari¬ 
able. Admittedly somewhat peculiar, this 
statement was contrived in an attempt to 
reduce the operating system interface 
problems between the Apple II 6502 im¬ 
plementation and the 8080/Z80 CP/M 
implementation. While not implemented, 
ASSOCIATE $$ WITH I$$ is the more 
general form of this statement. In this 
statement, $$ is the first of twelve byte 
locations. This location contains a blank 
if the default drive is to be used for the 
subsequently named file or the letter cor¬ 
responding to a drive identifier.. The next 
eleven bytes contain the full, unambigu¬ 
ous file name of the file to be used. I $ $ 
should contain a file number in the low 
order seven bits. 

I/O Control System Description 

The I/O Control System for Pidgin 
on the 8080/Z80 (PIOCS) is designed to 
run under CP/M 2.2 or 1.4. It will handle 
all of the usual CP/M file conventions and 
can access any sequential file written by 
CP/M. With some modifications it could 
do random file I/O as well. For the pur¬ 
pose of this discussion, the routines 
referred to are all in the element 
“IOCMPLX.ASM” and “SYSTEM.ASM”. 
Note: the two routines READBUF and 
WRITEBUF are not implemented in this 
release of Pidgin, since they were not 
used in Tincmp. 

The first routine to discuss is ?INIT. 
This subroutine gains control from the 
main program at the invocation of the 
BEGINMAIN statement. 7INIT examines 
the temporary buffer which has been set 
by CP/M to contain the processor call 
image. If there are characters in this 
image then 7INIT will scan each file name 
in the image, constructing an FCB (File 
Control Block) for each filename found. 
Even if you do not use these files, the 
FCB’s are constructed. As each FCB is 
built, an area of memory called 7IOCTL 
is also initialized. This area consists of six 
seven-word entries, one for each possible 
open file in the system. The first word in 
this seven-word entry is the operation to 
be performed on each file. This currently 
is read (bit zero=l) or write (bit one=l) 
and a state called prepare (bit two=l). 
The prepared state means that the Pidgin 
program has established an association be¬ 
tween the filename and an internally as¬ 
signed file number. Currently, in order to 


use Pidgin, you need to assign all of the 
files in the processor call, but that need 
not be the only way to associate files 
with file numbers. The prepared bit is bit 
two=l. When the ASSOCIATE FCB n 
WITH Ixx is executed, the FCB number n 
in the processor call line is equated in the 
7IOCTL table with file number Ixx. In 
order to keep compatible with other ver¬ 
sions of Pidgin, Ixx is used but 8080/Z80 
Pidgin only looks at the low order seven 
bits of Ixx. This means that file numbers 
which do not have unique bits 0-6 are 
considered the same file by this I/O pack¬ 
age. After 7INIT sets up the I/O tables it 
exits back to the users. 

7ATACH is the routine invoked by 
the ASSOCIATE statement. It inserts the 
proper information into the 7IOCTL 
table and marks the file “prepared” so 
that it many now be properly referenced 
by number of buffer, as described in the 
6502 Pidgin description and the 65 02 file 
system description (see DDJ #57). 

7IOPEN is called when the user exe¬ 
cutes an OPEN statement. At this time, 
the read/write bit is set in 7IOCTL and 
the prepared bit is cleared. The buffer 
address for the user buffer is stored in 
7IOCTL as well as the FCB address and 
the file number. 7IOPEN then calls the 
resident file system to open a read file or 
delete and make a write file. The buffer 
counter is set to 128 in the case of a read 
file, or to zero in case of a write file. This 
will cause read to read a buffer full of 
data as soon as it is entered for the first 
time; write will assume that its buffer is 
empty. 

7BREAD is called to read a single 
character. It examines the 7IOCTL table, 
looking for a read file with the proper 
buffer address, and then looks at the buf¬ 
fer counter. If less than 128 characters 
have been transferred from the read buf¬ 
fer, 7BREAD gets the next character in 
turn and gives it to the user. If the buf¬ 
fer counter is equal to 128 then a read is 
initiated through the resident file system 
using the FCB assigned to the buffer. If 
an end file is reached, 7BREAD returns a 
standard CP/M end-of-file character, 
which is 26 rather than 225. ER is set to 
1 if an end-of-file is detected. Note that 
the file is not closed on an end-of-file, 
and it is certainly possible to keep issuing 
reads on a file beyond the end-of-file. 

7BWRIT is similar to 7BREAD. The 
character to be written is added to the 
buffer, which is written out in blocks of 
128 bytes as each buffer is filled. When 


the file is closed (see below), the buffer is 
padded out with all end-of-file characters 
(26’s) and the final block is written to 
disk. 

7BCLOF is a close file routine. This 
routine destroys all of the information in 
7IOCTL so that it is no longer possible to 
read, write, or even to open the file as¬ 
sociated with the buffer mentioned in a 
close statement. For this reason I strongly 
urge the use of separate buffers for each 
file open at the same time, considering 
this a bad structural weakness in Pidgin. 
7BCLOF flushes the write buffer before it 
closes it out. The previous entry in 
7IOCTL is made re-useable by other calls 
to ASSOCIATE, OPEN, etc. 

7ENDING is the last routine in the 
PIOCS. When it is invoked by ENDMAIN, 
it examines the information in 7IOCTL 
and clears all of the open write buffers by 
“flushing” them. The write files are then 
closed by calls to CP/M. Similarly, each 
read file found in the 7IOCTL table 
causes a call to CP/M to close it. 7END- 
ING then returns control to the Pidgin 
program, executing the next statement, 
which is a jump to the 7BOOT entry 
point. 

The entries to CP/M are defined in 
SYSTEM.ASM so that you can use Pidgin 
under MP/M. No address is hard-coded 
except in the SYSTEM element. Also in 
SYSTEM is the load DE register from the 
address in HL. 

7WRNXT is in WRNXT.ASM along 
with 7RNXT. These routines write and 
read the console device. 7ISTOP is also 
in WRNXT and is used to display the 
message “STOP STATEMENT n EN¬ 
COUNTERED IN SOURCE PROGRAM” 
where n is the stop number 0 through 9. 
This, of course, could be changed to any¬ 
thing else you desire if it is not satisfactory. 

The Arithmetic Package 

Certain integer functions in Pidgin 
cannot be performed directly in 8080/ 
Z80 hardware. For example, multiplica¬ 
tion and division are not hardware func¬ 
tions unless the multiplier is a power of 
two or the divisor is a power of two, in 
which case the option of using left- and 
right-shift instructions is available. In 
these cases and others as well, closed sub¬ 
routines are provided to perform the 
functions not provided in hardware. All 
of these subroutines are provided in the 
relocatable element PIDMATH.ASM. This 
element was written by Richard Curtiss 
and is provided here with his permission. 


28 


Dr. Dobb’s Journal, Number 65, March 1982 

119 




Certain functions are also provided which 
allow you to do other arithmetic func¬ 
tions, such as modulus arithmetic, signed 
and unsigned arithemetic and the like, 
but these functions are not essential for 
use in Pidgin programs and are not direct¬ 
ly called by Pidgin. Nevertheless, they re¬ 
main in the package for your use. 

Integer subtraction is provided di¬ 
rectly by the subtract instruction for un¬ 
signed eight-bit quantities, but for the 
8080 processor, a double-precision sub¬ 
tract instruction is not provided in the 
hardware so the routine ?ISUB in the 
math package is used. In the Z80 there is 
a direct subtract instruction, but it sub¬ 
tracts with carry, meaning that the carry 
bit needs to be cleared prior to subtrac¬ 
tion. This could be directly implemented 
in the hardware by performing an ORA A 
first, but since Pidgin was written for an 
8080, the ?ISUB routine was used. For 
multiplication, ?IMUL is used and for 
division ?IDIV is used. An outline of the 
closed subroutine arithmetic routines is 
given in the assembly language listing of 
Pidmath. 

Certain comparison functions require 
that some arithmetic be performed and 
then a logical indicator set to the result 
of the comparison. 7CDEHL compares 
the values in the DE and HL registers. In 
certain instances, the relation between 
the two values compared is tested. If the 
relation is true, code is executed to return 
a low-order one bit, and if the relation¬ 
ship is false, a zero is returned. Some of 
this code is generated in-line in the Pidgin 
program. Where the code would be com¬ 
plex, out-of-line subroutines are in¬ 
cluded. 

Logical operations performed on 
bytes are always performed by in-line 
code, and the code generated always re¬ 
turns either a low-order one bit or a zero 
bit. At the conclusion of any logical 
operation, the left seven bits are always 
zero. When a logical test is to be per¬ 
formed, the operand of the test is loaded 
into the accumulator and an ORA A in¬ 
struction is executed to set the proper 
flag bits to zero or non-zero. Zero al¬ 
ways implies that the logical value was 
false, and non-zero always means true. 
Because only one bit is used, operations 
on this bit always influence the logical 
meaning of the logical expression. 

Getting Pidgin Running 

There are two ways to get Pidgin up 
and running on your computer. The easi¬ 


est way is to use the COM file Tincmp, 
the macro file MACROS.PGN and your 
source code in Pidgin to produce a file of 
assembly code. This method can be used 
for any machine on which CP/M is run¬ 
ning and the TPA (Transient Program 
Area) starts at 100H. You will need about 
15 Kilobytes of free memory to hold the 
Tincmp compiler, its tables and sub¬ 
routines. This method may not be suit¬ 
able for all readers and some may have to 
begin generation of Tincmp at another 
start address or desire some different 
features. In any case, you can start over 
with STAGE2 or use the assembly lan¬ 
guage output by Tincmp during its own 
operation. By hand coding the file 
TINCMP.MAC you could save about 20 % 
of the memory required for the Tincmp 
program, but this is such a small area that 
it won’t buy much. Because the I/O lights 
on the disk file are on all the time during 
operation of the Tincmp, I don’t think 
you will save much time by hand opti¬ 
mizing the Tincmp compiler. 

If you want to include operations for 
a Z80 processor, 1 suggest the following: 
use the Tincmp compiler as supplied here 
to process a new file of MACROS.PGN. 
These macros could be written to take ad¬ 
vantage of the Z80 instruction set. When 
you have a working set of macros, recom¬ 
pile Tincmp and test it. When you are 
sure that you have a working copy of 
Tincmp, replace the 8080 version with 
the Z80 version. Then, work your way 
through the I/O complex, recoding that 
for the Z80. I wrote the one supplied 
here with the Z80 in mind. Later, change 
the other routines as you have more time. 

1 don’t believe that any changes will give 
a significant increase in execution speed, 
since many Z80 instructions are just as 
long and slow as the multiple 8080 in¬ 
structions that they replace. As an ex¬ 
ample, consider the load DE from mem¬ 
ory in the Z80. In the 8080 you need a 
load HL from memory and an exchange. 
Assuming that HL need not be saved prior 
to this use, and in my macro set there are 
no examples of this at this writing, each 
instruction is four bytes long and the 
8080 pair of instructions take 20 T 
cycles, just as the Z80 single instruction 
does. Since the 8085 is a superset of the 
8080 instruction set, the instructions 
need not be changed to make use of the 
8085 processor. 

If you have a copy of the CDL 
LINKER program (Computer Design 
Labs of Trenton, NJ) you can have your 


Tincmp compiler turn out direct code 
without assembly. You will need three 
passes through Tincmp. Your macros will 
be structurally similar to Bill Gale’s set 
for the 6502. The LINKER program, 
unlike the Microsoft Link 80 routine or 
the Digital Research Link routine, accepts 
hexadecimal as input and generates link¬ 
age edited absolute modules from this in¬ 
put. You will have to modify the Pidgin li¬ 
brary routines so that the CDL MACR02 
assembler can assemble them and use 
them as library routines, because the CDL 
LINKER cannot accept the Microsoft 
relocation format used by both Microsoft 
and Digital Research. The net result is 
that your program will compile faster 
with the three passes through Tincmp 
than it would going through Tincmp once 
and then being assembled. Assemblers 
which are powerful are slow. MACRO80 
and RMAC are not exceptions to this 
rule. MACR02, although somewhat faster 
than both RMAC and MACRO80, still 
requires more time than the additional 
two passes through Tincmp would. The 
negative side of this three pass compila¬ 
tion is that the resulting object code is 
difficult to “clean up” or hand optimize. 
In addition, the macros are far more 
complex than in the one-pass com¬ 
pilation. 

Availability 

The 8080/Z80 version of Tincmp 
operating under CP/M is available from 
the author on eight-inch, single-density 
floppy disk in CP/M format for $25. It is 
also available from the SIG/M group of 
the Amateur Computer Group of New 
Jersey at a more reasonable price. No 
matter where you purchase the disk, 
please note that all of the programs on 
the disk are copyrighted. Gale, Curtiss 
and Bender all hold copyrights on the 
programs on the disk, and allow the 
owner of the disk to make as many copies 
as desired for non-commercial, personal 
use. Commercial use is forbidden without 
the written consent of each of the 
authors. No copies may be made for 
commercial use. 

The disk contains the following: 
STAGE2 written in FLUB as a COM file. 
STAGE2 macros for Pidgin, Tincmp writ¬ 
ten in Pidgin. A COM file of Tincmp. Pid¬ 
gin macros for Tincmp. The library rou¬ 
tines for Pidgin. This document and a 
short guide to getting Pidgin up on other 
assemblers. After 1982, if you are writing 
to me (directly) for a copy of the disk, 


Dr. Dobb’s Journal, Number 65, March 1982 
120 


29 



inquire first. I will be happy to answer 
any questions you might have concerning 
Tincmp or Pidgin, but please write them 
out and enclose a self-addressed, stamped 
envelope. 

Acknowledgements 

The author acknowledges the help of 
Dr. William Gale, the originator of Pidgin, 
who made many valuable suggestions dur¬ 
ing this work. I also acknowledge the 
groundwork done by Richard Curtiss in 
his development of a super implementa¬ 
tion of STAGE2 for the 8080 processor 
and for his kind permission to use all of 
the routines included in his CP/MUG li¬ 
brary distribution. »»j 

Bibliography 

Gale, W. A.: “Pidgin: A System Program¬ 
ming Language.” Dr. Dobb’s Journal 6: 
10 #57, July 81. 

Gale, W. A.: “A Tiny File System.” Dr. 
Dobb's Journal 6:20 #56, June 81. 

Waite, W. M.: Implementing Software for 
Non-Numeric Applications. Prentice- 
Hall, Inc. Englewood Cliffs, NJ, 1973. 
Curtiss, R.: “STAGE2, FLUB and associ¬ 
ated materials.” CP/MUG Library Disk 
#51. Order from CP/M Users Group NY, 
NY. Current cost about $8. 

CP/M, LINK-80, RMAC, PL/I-80 
and MP/M are registered trademarks of 
Digital Research Inc., Pacific Grove, CA. 
Z80 is a trademark of Zilog Division of 
Exxon, Inc., Cupertino, CA. 

The author has been involved in 
computer programming for the past 21 
years. He practices medicine, specializes 
in neurology and likes kids, cats and Bach 
although not necessarily in that order. 

(Listing begins on page 40) 


30 


Dr. Dobb’s Journal, Number 65, March 1 982 

121 


H-8 Front Panel (Text begins on page 17) 


Listing I 

Listing 1. This program, written in Heath's Benton Harbor BASIC, 
provides a run-through of all possible combinations of LED patterns. 

00 100 A = 8203:FOR I = 0T0 9:P0KE A + I,255:NEXT I:REM Clear the display 
00110 CNTRL 2,1:REM Turn H-8 display on without update to write to the LEDs 

00120 PRINT "This program demonstrates the use of the H-8 front panel LEDs." 

00130 PRINT "To view a run-through of all possible combinations, enter '1'." 
00140 PRINT "To select particular displays, enter '2'." 

00150 PRINT "To halt the run at a given display, type 'CTRL-B'" 

00160 PRINT "To exit program 2, enter '-1.'" 

00170 INPUT "Enter your choice: ";A 
00 1 80 IF A =1 THEN 210 
00 1 90 IF A = 2THEN 340 

00200 PRINT :PRINT "Illegal option. Re-enter.":PR INT :G0T0 130 
00210 CNTRL 0,310:REM When CTRL-B is pressed, goto 310 

00220 A=8203:B=8204:C=8205:D=8206:E=8207:F=8208:REM Set initial LED locations 
00230 PRINT : PRINT "Decimal It corresponding to LED:" 

00240 FOR I=1T0 257:REM Full circle on the patterns 
00250 POKE A,I:P0KE B,I:POKE C,I:P0KE D,I:P0KE E,I:P0KE F,I 
00260 PRINT I;:REM Show what number was just displayed 
00270 PAUSE 200:REM Wait a bit so user can see pattern 

00280 PRINT CHR$(13);:REM CR without LF:REM To keep display from scrolling off 
00290 NEXT I 
00300 GOTO 120 

00310 PRINT "The display corresponds to";I;"; press RETURN to continue." 

00320 PAUSE :REM Wait for a RETURN to be entered to continue 
00330 GOTO 290 

00340 A=8203:B=8204:C=8205:D=8206:E=8207:F=8208 

00350 PRINT "Enter the number to be displayed (-1 to end): 

00360 INPUT "";I 

00370 IF I=-1THEN 120 

00380 POKE A , I:P0K E B,I:P0KE C,I:P0KE D,I:P0KE E,I:P0KE F,I: REM Same for all LED 


34 

122 


Dr. Dobb’s Journal, Number 65, March 1982 


s 


00390 GOTO 360 
00400 END 


Listing II 


End Listing I 


Listing 2. This program prints a simple message on the front panel 
LED display of the H8 computer. 

100 PRINT "LED PROGRAMMING DEM0NSTRAT ION":PR INT 

110 PRINT "To operate, enter data starting at line #500. Enter the number of" 

120 PRINT "data entries at line #480." 

130 PRINT :PRINT "To run the program with existing data, press 'RETURNPAUSE 
140 REM Turn on LED's without update 
150 CNTRL 2,1 

160 REM Port number for left-most LED 

170 A=8203 

180 REM Erase LED 

190 FOR I = OTO 8:POKE A + I,255:NEXT I 

200 REM Read number of characters to print 

210 READ N 

220 FOR K = 1 TO N 

230 REM Read data for each character 
240 READ L 

250 REM Write each character, then erase (right to left) 

260 POKE A+8,L:POKE A+7.L 
270 POKE A + 8,255 

280 PAUSE 20:REM Wait a bit so user can read the display 
290 POKE A+7,255:POKE A+6.L 
300 PAUSE 20 

310 POKE A+6,255:POKE A+5.L 
320 PAUSE 20 

330 POKE A+5,255:POKE A+4,L 
340 PAUSE 20 

350 POKE A+4,255:POKE A+3.L 
360 PAUSE 20 

370 POKE A+3,255:POKE A+2.L 

380 PAUSE 20 (Continued on page 22) 


Dr. Dobb’s Journal, Number 65, March 1982 


35 

123 




Pattern Classification 

(Text begins on page 23) 


0010 RED: ft BASIC PROGRAB TO DETERMINE FISHER'S LINEAR DISCRiniHANT 

0020 REN 

0030 REN 

GOTO REN 

0050 REN 

0040 REN: PRESENT REV: 1.04, AUGUST 31, 1981. 

0070 ON ESC THEN SOTO 2930 
0080 CLOSE 

0090 ON ERR THEN SOTO 0110 
0100 OELETE "PLOTDAT" 

0110 ON ERR THEN STOP 
0120 PAGE =80 
0130 G0SU8 2990 
0140 PRINT 

0150 PRINT "FISHER’S LINEAR DISCRININANT." 

0140 PRINT 

0170 PRINT " PROGRAN OPTIONS:" 

0180 PRINT 

0190 PRINT * 1 - BUILD, ADD TO, OR EDIT AN EXISTING TRAINING DATA FILE." 

0200 PRINT 

0210 PRINT " 2 - CORPUTE THE FISHER’S LINEAR DISCRINIHANT FOR AH EXISTING "! 

0220 PRINT " TRAINING DATA FILE. (ALLOWS SELECTION OF UNCLASSIFIED POINTS 

)." 

0230 PRINT 

0240 PRINT * 3 - PRINT AN EXISTING TRAININ6 DATA FILE." 

0250 PRINT 

0240 INPUT " HUNGER OF THE DESIRED PROGRAN OPTION ? ",1 

0270 ON ESC THEN GOTO 0070 

0280 IF I<1 THEN SOTO 0240 

0290 IF I>3 THEN GOTO 0240 

0300 DIN N1(13),A1(!),A1M24),C(1> 

0310 PRINT 

0320 INPUT "WHAT IS TOUR TRAINING DATA FILE NANE? ",N» 

0330 PRINT 

0340 1HPUT "HON NANT FEATURES IN EACH SANPLE?(NAX=25) ",N2 

0350 IF N2<1 THEN GOTO 0340 

0340 IF N>25 THEN GOTO 0340 

0370 DIN X(N2),T(2,N2),N1(N2),N2(N2),U1(N2),U2(1) 

0380 IF 1-2 THEN GOTO 0440 

0390 IF 1=1 THEN GOTO 0420 

0400 60SUB 3740 

0410 GOTO 2930 

0420 60SUB 3320 

0430 GOTO 2930 

0440 PRINT 

0450 LET U=0 

0440 LET R=0 

0470 INPUT "DO TOU NISH TO PLOT AN UNCLASSIFIED DATA POINT’ ",A» 

0480 PRINT 

0490 IF A«="Y" THEN 60SUB 3020 
0500 ON ESC THEN GOTO 2930 

0510 PRINT "THANKTOU. THE FISHER’S LINEAR DISCRININANT IS BEING CONFUTED." 

0520 OPEN FILE (0,0),H» 

0530 REN: CONFUTE THE UNPROJECTED SARPLE VECTOR NEANS. 

0540 LET 1=0 
0550 LET J=0 
0540 LET K=0 

0570 NAT READ FILE (0,I),C.X 
0580 LET C=C(1) 

0590 IF EOF(D) THEN GOTO 0740 
0400 IF C=1 THEN GOTO 0430 
0410 IF C=2 THEN GOTO 0490 
0420 GOTO 2810 

0430 REN: CLASS 1 T0TALI2AT10N. 

0440 FOR L=1 TO N2 

0450 LET T(l,l)=T(l,L)tX(L) 

0440 NEXT L 
0670 LET J=J»1 
0480 SOTO 0740 

0690 REfl: CLASS 2 TOTALIZATION. 

0700 FOR L=1 TO N2 

0710 LET T(2,L)=1(2,D4X(D 

0720 NEXT L 

0730 LET K=K*1 

0740 LET 1=1*1 

0750 60T0 0570 

0760 IF J=0 THEN GOTO 2850 

0770 IF K=0 THEN GOTO 2850 


0780 FOR L=1 TO N2 
0790 LET N1(L)=T(1,L)/J 

0800 LET N2(L)=T(2,L)/K 

0810 NEXI L 
0320 LET N=J*K 
0830 LET P=N2 

0840 REN: CONFUTE SCATTER RATRICES. 

0850 DIN Sl(P,P),S2(P,P),yi(P,P),D(P),Dl(P),D2(P,P) 

0860 NAT S1=ZER(P,P) 

0870 NAT S2=ZER(P,P) 

0880 FOR 1=0 TO N-l 

0390 NAT READ FILE (0,I),C,X 

0900 LET C=C(1) 

0910 IF C=2 THEN GOTO 0970 
0920 NAT D=X-N1 
0930 NAT 01=TRN(D) 

0940 RAT D2=DiDl 
0950 RAT S1=S1+D2 
0960 GOTO 1010 
0970 NAT D=X-R2 
0980 NAT D1=TRN(D) 

0990 RAT D2=D*01 
1000 NAT S2=S2*D2 
1010 NEXT I 
1020 NAT W1=S1*S2 

1030 REN: CONFUTE THE WITHIN CLASS SCATTER NATRIX INVERSE. 

1040 DIN V(P,P),R3(25),X1<25> 

1050 ON ERR THEN GOTO 2870 
1060 NAT V=INV(W1> 

1070 ON ERR THEN STOP 

1080 REN: CORPUTE THE WEIGHTING VECTOR U. 

1090 DIN HIP) 

1100 NAT N3=N1-N2 
1110 NAT H=V*R3 

1120 REN: CONFUTE THE SCALAR PROJECTED POINTS. 

1130 DIN T(1),Y1(J),T2(K) 

1140 LET J1=0 
1150 LET K1=0 
1160 NAT X1=TRN(U) 

1170 FOR 1=0 TO H-l 

1180 NAT READ FILE (0,I),C,X 

1190 LET C=C(1) 

1200 IF C=2 THEN GOTO 1250 
1210 LET J1=J1»1 

1220 NAT Y--X1IX 

1230 LET Y1(J1)=Y(1) 

1240 GOTO 1280 
1250 LET K1=K1+1 

1240 NAT Y=XHX 

1270 LEI Y2(K1)=Y(1) 

1280 NEXT 1 

1290 IF U=0 THEN GOTO 1330 
1300 NAT U2=XHU1 
1310 LET U2=U2(1) 

1320 IF R=1 THEN GOTO 1720 
1330 PRINT 

1340 INPUT "DO YOU HISH TO SEE A LISTING OF THE PROJECTED POINTS? ",A1 

1350 IF AJ="Y" THEN GOTO 1370 

1340 GOTO 1720 

1370 LET L=0 

1380 LET L7=0 

1390 LET 18=0 

1400 GOSUB 2990 

1410 PRINT " PROJECTED POINTS FOR:" 

1420 PRINT 

1430 PRINT * CLASS 1 "!" "i" CLASS 2 

1440 NOESC 

1450 FOR 1=1 TO 18 

1460 LET L=L*1 

1470 LET L7=L7*1 

1480 PRINT " *) 

1490 IF L7>J THEN GOTO 1520 

1500 PRINT USING "-#.8I»B8»",Y1(L)5" "! 

1510 GOTO 1530 
1520 PRINT " "! 

1530 LET L8=L8*1 

1540 IF L8>K THEN GOTO 1560 

1550 PRINT USING "-B.!TS«89",Y2(L)) 

1540 PRINT 
1570 NEXT 1 
1580 ESC 

1590 ON ESC THEN GOTO 2930 
1600 PRINT 

1610 INPUT "PRESS RETURN TO CONTINUE.",A» 

1620 IF L>J THEN GOTO 1640 
1630 SOTO 1400 


Dr. Dobb’s Journal, Number 65, March 1982 
124 



Pattern Classification 

(Listing continued) 


1640 IF L>K THEM GOTO 1640 
1450 6010 1400 
1660 IF U=0 THEM GOTO 1720 
1670 PRINT 


1680 PRINT -PROJECTION OF THE UNCLASSIFIED POINTS 

1690 PRINT USING "-I.IH9HMI2 

1700 PRINT 

1710 INPUT -PRESS RETURN TO CONTINUE.",A» 

1720 REN: PLOT THE PROJECTED DISTRIBUTION. 

1730 60SUB 2990 

1740 PRINT -ONE MOMENT PLEASE." 

1750 PRINT -THE PLOT MATRIX IS BEING COMPUTED." 

1760 IF R=1 THEN GOTO 1960 

1770 REN: SCALE THE PROJECTED POINTS: (0<=Y<=70). 

1780 LET Ll=Yl(l> 


1790 LET L2=Y1(1) 

1800 FOR 1=2 TO J 

1810 IF YKIKL1 THEN LET L1=Y1(1> 

1820 IF Y1<1»12 THEN LET L2=Y1(I) 

1830 NEXT I 
1840 FOR 1=1 TO K 

1850 IF Y2LIXL1 THEN LET ll=Y2(I) 

1860 IF Y2CI»L2 THEN LET L2=Y2(I) 

1870 NEXT I 
1880 LET L3=L2-L1 
1890 DIN Y3CJ)>Y4(K) 

1900 FOR 1=1 TO J 

1910 LET Y3(I1=INT(U(Y1(I)-L1)/L3H70H.5) 
1920 NEXT I 
1930 FOR 1=1 TO K 

1940 LET Y4(I>=INT«((Y2(I)-ll)/L3>»70>*.5) 
1950 NEXT I 
1960 LET E=0 

1970 IF U=0 THEN GOTO 2080 

1980 LET U3=INT(<(<U2-ll)/L3)«70)*.5> 

1990 IF U3<0 THEN GOTO 2010 
2000 60T0 2030 
2010 LET U3=0 
2020 GOTO 2060 

2030 IF U3>70 THEN GOTO 2050 
2040 GOTO 2070 
2050 LET U3=70 
2060 LET E=1 

2070 IF R=1 THEN GOTO 2280 
2080 REN: BUILD FISHER PLOT FILE. 

2090 LET R1=0 
2100 LET L4=0 
2110 DIN 11(80) 

2120 IF R=I THEN GOTO 2150 
2130 OPEN FILE (2.0),-PLOTOAT” 

2140 DIN 2(N) 

2150 FOR 1=1 TO J 
2140 LET 2(1)=Y3(I1 
2170 NEXT I 
2180 LET K7=J 
2190 LET Pl=”l" 

2200 G0SU8 3150 
2210 FOR 1=1 TO X 
2220 LET 2(I)=Y4CI) 

2230 NEXT I 
2240 LET K7=K 
2250 LET P>=“2" 

2260 60SUB 3150 

2270 IF U=0 THEN GOTO 2380 

2280 LET Z(1)=U3 

2290 LET R1=R1*1 

2300 IF Rl<27 THEN GOTO 2320 

2310 LET Rl=Rl-26 

2320 LET A1$=*ABCDEFGHIJKLHN0PQRSTUVNXYZ" 
2330 LET P1=A11(R1,R1) 

2340 IF E=0 THEN GOTO 2360 
2350 LET Pl=" " 

2360 LET K7=l 
2370 GOSUB 3150 

2380 REN: PLOT THE PROJECTED POINTS. 


2390 GOSUB 2990 

2400 IF L4>12 THEN GOTO 2440 

2410 FOR 1=1 TO 13-L6 

2420 PRINT 

2430 NEXT I 

2440 PRINT " FISHER LINEAR DISCRIMINANT PLOT- 

2450 PRINT 

2460 FOR 1=0 TO L6 

2470 READ FILE (2,L6-I),L$ 

2480 PRINT * ";U(1,721 

2490 NEXT I 

2500 PRINT " I"; 

2510 FOR 1=1 TO 14 
2520 PRINT 
2530 NEXT I 
2540 PRINT " I 
I* 

2550 FOR 1=0 TO 2 
2560 LET L9=Ll*(L3*I/2) 

2570 PRINT USING !.B«II",L9! 

2530 IF 1=2 THEN GOTO 2600 

2590 PRINT " "i 

2600 NEXT I 

2610 PRINT 

2620 PRINT 

2430 PRINT -SCALE FACTOR: EACH SPACE= "1 
2640 PRINT USING "—S.4#S#\L3/70:“ “i 

2650 IF U=0 THEN GOTO 2780 
2460 PRINT "UNCLASSIFIED POINT "iP»;"="i 

2670 PRINT USIN6 •-J.MIIIIM’.U2 

2680 IF E=0 THEN GOTO 2700 

2690 PRINT - (EXCEEDS PLOT BOUNORIES S 

HORN)" 

2700 INPUT 'DO YOU NISH TO PLOT ANOTHER UNCLASSIFIED POINT? \AI 

2710 IF A!="Y“ THEN GOTO 2730 

2720 GOTO 2800 

2730 GOSUB 2990 

2740 GOSUB 3020 

2750 ON ESC THEN GOTO 2930 

2760 LET R=l 

2770 GOTO 1300 

2780 INPUT -DO YOU NISH TO PLOT AN UNCLASSIFIED POINT? \Ai 
2790 IF A1=‘Y" THEN GOTO 2730 
2800 6010 2930 
2810 PRINT 

2820 PRINT -A DATA HISCLASSIFICATION HAS OCCURED. PLEASE* 

2830 PRINT "CORRECT THE PROBLEM IN THE DATA BASE AND TRY AGAIN.- 
2840 GOTO 2930 

2850 PRINT -EITHER CLASS 1 OR CLASS 2 HAS NO ELEAENTS. THEREFORE, CLASSIFICATION 
IS MEANIHGLESS." 

2860 GOTO 2930 
2870 ON ERR THEN STOP 
2880 GOSUB 2990 
2890 PRINT 

2900 PRINT -THE HITKIN CLASS SCATTER MATRIX IS SINGULAR. THEREFORE, • 

2910 PRINT "THE CURRENT DATA CANNOT BE USED IN THIS PROGRAM.- 
2920 PRINT -EXECUTION IS ABORTED ill- 
2930 CLOSE 

2940 ON ERR THEN GOTO 2960 
2950 DELETE "PLOTDAT" 


2960 ON ERR THEN STOP 
2970 PAGE =72 
2980 END 

2990 REM= SUBROUTINE TO FORM FEED THE 1420 CRT. 
3000 LNR1TE “'<23>" 

3010 RETURN 

3020 REN: SUBROUTINE TO INPUT FISHER DATA. 

3030 ON ESC THEN GOTO 3120 
3040 LET U=1 
3050 PRINT 
3060 LET 1=1 

3070 PRINT -COORDINATE #-}!;-? "; 

3080 INPUT ”,U1(I) 

309D LET 1=1*1 

3100 IF I>N2 THEN GOTO 3130 

3110 GOTO 3070 

3120 LET U=0 

3130 PRINT 

3140 RETURN 

3150 RER: SUBROUTINE TO COMPUTE THE PLOT NATRIX. 

3160 LET 1=1 

3170 LET 11=0 

3180 READ FILE (2,I1),L1 

3190 IF Ll=“" THEN GOSUB 3300 

3200 IF L5(Z(I)*1,Z(I)*1>=" " THEN GOTO 3250 


38 


Dr. Dobb’s Journal, Number 65, March 1 982 

125 






3210 LET LF="“ 

3220 LET 11=11+1 

3230 IF 11>L6 THEN LET L6=I1 

3240 GOTO 3180 

3250 LET LF(2(IM,Z(IM)=PF 
3260 WRITE FILE (2,11),L» 

3270 LET I=H1 

3280 IF I>K7 THEN GOTO 3310 

3290 GOTO 3170 

3300 LET LF=” 

■ 

3310 RETURN 

3320 RER’.SUBROUTINE TO BUILD A FISHER DATA BASE FROA TRAINING DATA. 
3330 Dill F(N2) 

3340 OPEN FILE (0,0),NF 
3350 G0SU8 2990 
3360 PRINT 

3370 ON ESC THEH GOTO 3730 

3380 INPUT "BEGINNING (OR NEXT) SARPLE (RECORD) NUHBER? M 

3390 ON ESC THEN GOTO 3350 

3400 GOSUB 2990 

3410 IF 1=0 THEN GOTO 3440 

3420 BAT READ FILE (0,1-1),C,X 

3430 IF EOF(O) THEN GOTO 3340 

3440 PRINT "RECORD «: "!l 

3450 PRINT 

3440 LET C(1)=0 

3470 BAT READ FILE (0,I),C,X 

3480 IF C(I)=0 THEN GOTO 3580 

3490 PRINT “CURRENT CONTENTS OF RECORD M)":" 

3500 PRINT "CLASS= "iC(l) 

3510 PRINT “FEATURES:" 

3520 FOR J=1 TO N2 

3530 PRINT USING —S.SASSSMU); 

3540 PRINT " "I 

3550 NEXT J 
3540 PRINT 
3570 GOTO 3590 

3530 PRINT "THIS ENIRT IS CURRENTLY EBPTT." 

3590 PRINT 

3600 BAT INPUT "CLASS (1 OR 2)? ",C 
3610 IF CdKt THEN GOTO 3600 
3620 IF C(l)>2 THEN GOTO 3600 
3430 PRINT 
3440 LET J=i 

3650 PRINT "FEATURE l"iJi" ? "I 
3460 INPUT ”“,F(J) 

3470 LET J=J*1 

3680 IF J>H2 THEN GOTO 3700 

3690 GOTO 3650 

3700 BAT WRITE FILE (0,1),C,F 
3710 LET 1=1+1 
3720 GOTO 3400 
3730 RETURN 

3740 REH: SUBROUTINE TO PRINT TRAINING DATA BASE. 

3750 ON ESC THEN GOTO 3980 

3760 GOSUB 2990 

3770 OPEN FILE (0,0),N» 

3780 PRINT "DATA BASE: "INF 
3790 PRINT 

3800 PRINT "RECORDS CLASS: FEATURES:" 

3810 LET 1=0 

3820 RAT READ FILE (0,I),C,X 
3830 IF EOF(O) THEN GOTO 3980 
3840 IF I>9 THEN GOTO 3860 
3850 PRINT " “! 

3860 PRINT Ii" "iC(l):" "! 

3870 LET J=1 

3880 PRINT USING • -|.«S«",X(J>i 

3390 IF J-{(INT(J/7))*7».01 THEN GOTO 3920 

3900 PRINT 

3910 PRINT " "i 

3920 LET J=JH 

3930 IF J>N2 THEN GOTO 3950 

3940 GOTO 3830 

3950 PRINT 

3940 LET 1=1+1 

3970 GOTO 3820 

3980 ON ESC THEN GOTO 4010 

3990 PRINT 

4000 INPUT “PRESS RETURN TO CONTINUE.",AF 
4010 RETURN 


End Listing 


Dr. Dobb’s Journal, Number 65, March 1982 
126 


8080 Pidgin (Text begins on page 25) 


Listing I 

TOP? TINCMP COPYRIGHT <C> 1981 W.A.GALE 

PARAMETER KLF-010? CP/M MODIFICATION AND 8080 RECODING 

PARAMETER KCR-013? BY A. L* BENDER r M. D. 

PARAMETER KEF-026? NEW MODS AND REWORKING COPYRIGHT <C) 1981 A L. BENDER t M D 

BYTE AA? WORK 

BYTE BB5 WORK BYTE 

BYTE DD? WORK 

BYTE EE ? WORK BYTE 

BYTE BF(080)5 EXPANSION BUFFER 

BYTE bl? blank- 

byte BP? POINTER INTO BF 

BYTE CO? CONSTANT ZERO 

BYTE Cl? CONSTANT ONE 

BYTE C2 ? CONSTANT TWO 

BYTE C3 ? CONSTANT 3 

BYTE C4 ? CONSTANT 040 

BYTE C8? CONSTANT 080 

BYTE C9 ? CONSTANT 9 

BYTE CC? INPUT CHARACTER 

BYTE CX? CONSTANT TEN 


BYTE DG? DIGIT FROM PARAMTER TREATMENT DEFINITION 

BYTE DS<010)? DIGIT STACK FOR SUB SD 

BYTE EF? END FILE CHARACTER 

BYTE FI(00128)5 INPUT BUFFER 

BYTE F2(00128)? OUTPUT BUFFER 

BYTE HA? 'A' 

BYTE HF? 'F' 

BYTE LE? END OF LIST 

BYTE LF? LINE FEED CHARACTER 

BYTE L.S (09000) ? LIST OF MACRO DEFINITIONS 

BYTE MF 5 MACRO REPLACEMENT OPERATOR FLAG 

BYTE ML? MACRO LENGTH 

BYTE MM? MINIMUM MACRO LENGTH 


BYTE ND? NUMBER OF DIGITS USED IN SUB SD FOR NUMBER OUTPUT 

BYTE NL? NEW LINE 

BYTE 015 FETCH CODE 

BYTE 02? INDEX CODE 

BYTE 03? DISPOSE CODE 

BYTE OA? ' + ' ADD OPERATOR 

BYTE OB? '!' POP STACK OPERATOR 

BYTE OC 5 'C' CHARACTER DISPOSE 

BYTE OD 5 'V' DIGIT CONVERSION FETCH 

BYTE OE 5 ESCAPE CHARACTER 

BYTE OG 5 IGNORE CHARACTER 

BYTE OH? 'H' HEX CONVERSION FETCH 

BYTE OL? 'L' LITERAL FETCH 

BYTE OM? MULTIPLY DISPOSE 

BYTE ON? 'N' NUMERIC LITERAL FETCH 

BYTE OP? 'P' PARAMETER FETCH OR DISPOSE 
BYTE OR? REDUCE (SUBTRACT) DISPOSE 

BYTE OS? "S' STACK FETCH OR DISPOSE 

BYTE OT? TRACE FLAG TURN ON 
BYTE PP? POINTER INTO IPR 
BYTE RB 5 BEGIN DEFINITION FLAG 


40 


Dr. Dobb’s Journal, Number 65, March 1982 

J27 


BYTE RC? (COMMENT) END OF LINE FLAG 
BYTE SF? SUBSTITUTION PARAMETER FLAG 
BYTE SP? STACK POINTER 
BYTE TR5 TRUE IF NO TRACE 

BYTE UG? USE IGNORE? TRUE UNLESS OG IS 'X' 

BYTE UN ? NOT X— FLAG FOR NOT SUPPRESSING NEW LINES ON OUTPUT 

BYTE UO5 USE OPERATIONS. TRUE UNLESS MF IS 'X' 

BYTE UT ? USE TRACE TRACE MODE IS ON 

BYTE ZR? CHARACTER ZERO 

INT 100? CONSTANT ZERO 

INT 1015 CONSTANT 1 

INT .109? CONSTANT 9 

INT 1.1.0? CONSTANT 10 

INT .116 5 CONSTANT 16 

INT IAA ? WORK 

INT IBB? WORKING STORAGE 

INT IBC? BUCKET NUMBER 

INT IDP? DEFINITION POINTER WHILE MATCH 
INT IED5 POINTS TO END OF DEFINITIONS 
INT III? POINTER TO L WHILE READING 
INT IJJ5 POINTER TO L READING CODE 
INT l'LM5 MAXIMUM LIMIT FOR STORING IN L 

INT IL..P (01000) 5 POINTERS TO MACROS 

INT IMP5 MACRO POINTER DURING EXPANSION 

INT INM? NUMBER OF MACROS 

INT IP R(010)? PARAME TER VA LUES 

INT ISS(040)? INT TO HOLD NUMBERS-MAIN STACK 

INT ITU? VALUE OF PARAMETER TO USE 

INT IUU 5 SYMBOL GENERATOR<UNIQUE) 

INT IXX5 WORK 
INT IYY5 WORK 
BEGINMAIN(AC»IAV) 

NL-+KCR 
LF-tKLF 
GOBUB CR 

MS "COPYRIGHT' 

MS " (C) 1981" 

MS " W ♦ A.GALE" 

GO SUB CR¬ 
MS "8080 TINC" 

MS "MR COMP IL." 

MS "ER CP/M V" 

MS "ERSION 1." 

MS "05/T[NCMP" 

GO SUB CR¬ 
MS "COPYRIGHT" 

MS (C) 1981" 

MS " A L BEND" 

MS "ERy MD 
GOSUB CR 
GOSUB IN 
GOSUB RM 
LOC ()0 
WHILE 

READ CC FROM FI 
AA=ER=~CO 

ON AA 5 THAT ISy UNTIL EOF IS REACHED ON INPUT 
IF UG 

WHILE 

BB-CC--NL 

(Continued on next page) 


Dr. Dobb’s Journal, Number 65, March 1982 

T28 


41 




8080 Pidgin (Listing continued) 


DD=CC=—LF 

AA~CC=~OG 

EE-BBTDD 

BB"C C=~BL 

AA=BB?AA 

AA~EE?AA 

ON AA5 IGNORE LEADING CHARACTERS 
GOSIJB GC r READ CC FROM FI 

ENDWHILE 

END IF 

BP=C15 BUF POINTER 

BF(CO)~CC 

WHILE 

GOSUB GCy READ CC FROM FI 
AA=CC==NL 
IF AA 

GOSUB GC i READ CC FROM FI 
AA=CC~=LF 
IF A A 
CC=NL 
END IF 
END IF 
AA=CC!«NL 
BB-BP!-C8 
AA=AA8BB 

ON AA 5 WHILE LESS THAN 80 CHAR AND NOT NEWLINE 

BF(BP)=CC? THEN PUT IT IN BUFFER FOR MULT COMP 
BP++ 


ENDUHILE 
WHILE 
AA=CC!=NL 
ON AA 


GOSUB GC y READ CC FROM FI 
ENDWHIL.E5 HERE WE ARE DUMPING A LONG INPUT LINE 
BF(BP)=RC 
BP++ 

BF <BP)=NL 

LE=BP 

AA=BPOMM 

IF AA i TOO SHORT TO MATCH 
ML=+000 
GOTO 17 

ELSE 

ML=+001 

END IF 

IDP=IOO 

PP=CO 

IJJ=IOO 

INM-CO 

WHILE 

AA=IDP<!IED5 DEF PTR < END OF DEFINITIONS 

ON AA 

BP~CO 

WHILE 

AA=BP<=LE 

ON AA 

AA=LS <IJJ) 

aa=aa==rc 


42 


Dr. Dobb’s Journal, Number 65, March 1 982 

129 




03=BF(BP) 

03=03==RC 

AA-AAX03? CHECK EOL MATCH TARG & TEMPLATE 
IF AA 

GOSUB DM ? DO MACRO EXPANSION 
GOTO 00 

ELSE 

AA=BF(BP) 

BB=LS(IJJ) 

AA=AA==BB 
IF AA 

GOTO 0.1? MATCHING 


AA~ : BB ! =SF ? NOT A TEMPLATE PARAMETER FLAG 
IF A A 

GOTO 10? MISMATCHED 
ELSE? THIS IS A PARAMETER 
PP+ + 

AA=BF(BP) 

IAA=AA 
IPR(PP)=IAA 

END IF 
END IF 
END IF 

LOG 01 

BP++ 

IJJ+ + 

ENDWHILE 

LOC 10 

PP=CO 

INM++ 

IDP=ILP <INM) 

IJJ=IDP 

ENDWHILE 

LOC 17 

BP=CO 

WHILE 

CC=BF(BP) 

G1=BP+C1 
AA-BF(01) 

AA=AA ! =NL. 

ON AA 

IF ML? THEN ALSO WRITE 
WRITE CC 

END IF 

WRITE CC INTO F2 
BP++ 

ENDWHILE 
IF ML 

GOSUB CR 

ENDIF 

IF UN? ONLY IF NOT SUPPRESSING 
WRITE NL INTO F2 
WRITE LF INTO F2 

ENDIF 

ENDWHILE 

LOC 88? END OF SATISFACTORY COMPILATION 
MS 'TINCMP CO' 

MS 'MPILATION' 

MS ' FINISHED' 

GOSUB CR? 

CLOSE FI 

Cl OSE F2 (Continued on next page) 


Dr. Dobb’s Journal, Number 65, March 1982 
"130 


43 


8080 Pidgin (Listing continued) 


ENOMAIN 

SUB GC? GETS THE NEXT CHARACTER INTO CC GOES TO 88 ON END 
READ CC FROM FI 
AA ; =ER ! =C0 

IF AA 5 IF NOT NORMAL READ OPERATION 

GOTO 88? !!!! NOT GOOD PROGRAMMING PRACTICE AT ALL !!!! 

ENDIF 

AA~CC~=EF? IF CHARACTER WAS EOF MARK 

IF AA5 IN CP/M SYSTEM THIS CAN BE RETURNED TO USER 

GOTO 88? !!!! NOT GOOD PROGRAMMING PRACTICE AT ALL !!!! 

ENDIF 

ENDSUB? GC ~ GET CHARACTER FROM INPUT FILE 

SUB SD? CONVERTS TOUSE TO A NUMBER WITHOUT ZRO LEADING 

AA»ITU<!100 
IF A A 

BB=+001 
ITU —ITU 

ELSE 

BB--+000 

ENDIF 

AA--ITU=“IOO 
IF A A 

ND--C1 
DS(CO)=ZR 

ELSE 

ND--CO 

WHILE 

AA=IOO<!ITU 

ON AA 

IYY=ITU/I10 
IAA=I10*IYY 
IXX : =ITU~IAA 

ITU=IYY 

AA : -IXX 

AA=AA+ZR 
DS < ND)“AA 
ND+f 

ENDWHILE 

ENDIF 
DS < ND)“OR 

ND-ND+BB? INCR FOR NEG INTEGER ONLY 
ENDSUB 

SUB WN 5 WRITE NUMBER INTO F2 

GOSUB SD? STACK THE DIGITS 
WHILE? NOW WRITE THEM OUT FIRST TO LAST 
IAA=ND 
AA“IOO<!IAA 

ON AA 

ND — 

AA=DS < ND) 

WRITE AA INTO F2 
ENDWHILE 
ENDSUB 

SUB PN? WRITE THE NUMBER ON THE TERMINAL 

GOSUB SD? STACK THE DIGITS 
WHILE 


44 


Dr. Dobb’s Journal, Number 65, March 1982 

w 





IAA=ND 
AA=IOO<!IAA 

ON AA 

ND— 

AA=DS(ND) 

WRITE AA 
ENDWHILE 
WRITE BL 
ENDSUB 

SUB CD f 

BB=ZR<=AA 
CC=AA<=C9 
BB=BB&CC 
IF BB 

AA=AA-ZR 

RETURN 

END IF 
AA-CO 
ENDSUB 

SUB CH f 

BB=ZR<=AA 

CC~AA<=C9 

BB-BBXCC 


IF BB 

AA=AA-ZR 

RETURN 

END IF 
BB=HA-= 

:>-AA 

CC=AA< 

::=HF 

BB=BBXCC 

IF BB 

AA=AA~HA 

AA=AA+CX 


RETURN 


END IF 
AA~CO 
ENDSUB 


CONVERT AA AS A DECIMAL DIGIT 


CONVERT AA AS HEX DIGIT 


SUB IN? INITIALIZE 


ILM=+08920 

I00=+00000 

I01=+00001 

I10=+00010 

109^+00009 

co=+ooo 

Cl=+001 

C2=+002 

C3~+003 

EF=+KEF 

C4=+040 

C8=+080 

I16=+00016 

SP=+000 

C9='9' 

ZR~ ' 0' 

BL=' ' 
HF='F' 


Dr. Dobb’s Journal, Number 65, March 1982 
T32 


(Continued on next page) 

45 


8080 Pidgin (Listing continued) 


HA='A' 

CX-+010 
IBC=I01 
TR-'R' 

CLOSE FI 

ASSOCIATE FCB 1 WITH IBC 
OPEN FI FOR TR AT IBC 
TR='W' 

IBC++ 

CLOSE F2 

ASSOCIATE FCB 2 WITH IBC 
OPEN F2 FOR TR AT IBC 

READ AA FROM FI? X SUPPRESSES NEW LINE OUTPUT 
OT='T' 

UT=+000 
BB-'X' 

UN=AA!=BB? UN SAYS CHARACTER WAS NOT X SO DONT SUPPRESS 
READ RB FROM FI 

READ RC FROM FI? COMMENT AND EOL FLAG 
READ SF FROM FI? TEMPLATE PARAMETER FLAG 
READ MF FROM FI? EXPANSION OPERATION FLAG 


BB-'X' 

AA=MF==BB 
IF A A 

UO=CO 

ELSE 

U0=C1 

END IF 

0P~' P' ? PARAMETER DESIGNATOR IN OPERATION SEQUENCE 
0E='@'? ESCAPE CHARACTER 

0D =' V' ? CONVERT PARAMETER TO DIGIT IN ACTION SEQUENCE 
0B='!'? POP STACK DESIGNATOR IN OPERATION SEQUENCE 
OS^'S'? STACK DESIGNATOR IN OPERATION SEQUENCE 
OH- 'H '? HEX CONSTANT FETCH AND WRITE 

ON-'N'? LITERAL NUMERIC FETCH 
0L='L'5 LITERAL BYTE FETCH 
OC='C'? CHARACTER OUT DESIGNATION 
0A='+'? ADD TO STACK DESIGNATION 
OR-'-'? SUBTRACT (REDUCE) FROM STACK 
OM='*'? MULTIPLY STACK BY BASE AND ADD 
READ OG FROM FI? IGNORE CHARACTER 
AA='X' 

BB=AA--OG 
IF BB 

UG-+000 

ELSE 

UG=+001 

END IF 

READ CC FROM FI? NEW LINE 
AA=NL!-CC? NL IS NEWLINE 
IF A A 

MS 'FLAG LINE' 

STOP 1 

END IF 

I UU- + OO.L 00 
ENDSUB? IN 

SUB RM 5 READ MACROS 

III^IOO 


46 


Dr. Dobb’s Journal, Number 65, March 1 982 

133 



INM-CO 
M M ~+ 12 7 
WHILE 

READ CC FROM FI 
AA=ER==CO 


ON AA 

CHOOSE ON CC 

CASE OE ? ACCEPT THE NEXT CHARACTER UNCRITICALLY 
READ CC FROM FI 
GOTO 77 

CASE RB?BEGIN A DEFINITION 
ILP<INM)=III 
INM++ 

ML."+000 


CASE NL i IGNORE 
CASE LF?IGNORE 

CASE RC5IGNORE FOLLOWING COMMENTS AND MARK LINE END 
LS(III)~RC 
III++ 

AA=ML<!MM 

IF AA > THIS LINE IS SHORTEST YET 
MM = ML 

ENDIF 

WHILE 

READ CC FROM FI 


A ACC ! L.F 

ON AA 
ENBWHI LET 

CASE OG5 IF USING IGNORE r .IGNORE 
IF UG 
ELSE 

GOTO 77 


ENDIF 

DEFAULT r 
LOC 77 

LS(III)"CC 
III++ 

AA=ILM<!Ill 
IF A A 

MS 'MACMEMXST' 
GOSUB CR 
CLOSE FI 
STOP 5 

ENDIF 

ML-H- 

ENDCHOOSE 
ENDWHILE 
AA~CC!=EF 
IF AA 

MS 'DEFN READ ' 

STOP 2 

ENDIF 
CLOSE FI 
IBC=+00003 

ASSOCIATE FCB 3 WITH IBC 
TR='R' 

OPEN FI FOR TR AT IBC 
IED"111»END OF DEFINITIONS 


Dr. Dobb’s Journal, Number 65, March 1982 
f34 


(Continued on next page) 

41 


8080 Pidgin (Listing continued, text begins on page 24) 


MS 'LOADED...' 

ITU=III 
GOSUB PN 
MS '.BYTES FO' 

MS 'R DEFINES' 

GOSUB CR 
ILP(INM)=III 
ITU=INM 
GOSUB PN 
MS '.MACROS..' 

ITU=MM 

GOSUB PN 

MS ' MIN LEN.' 

GOSUB CR 
ENDSUB? RM 

SUB CR? DO CARRIAGE RETIJRN/LINE FEED SEQUENCE 

WRITE NL. 

WRITE L.F 
ENDSUB? CR 

SUB DMy DO MACRO EXPANSION 


IMP=IJJ+I01 
INM+ + 

IDP=ILP<INM) 

WHILE 

AA=IMP<!IDP 

ON AA? UNTIL WE HAVE READ UP TO THE NEXT MACRO DEFINITION 
AA=LS(IMP) 

IF UO 

AA=AA==MF 


ELSE 

AA~CO 

END IF 

IF AA? OPERATION CODE 
IMP++ 

01=LS(IMP)5 FROM INDICATOR 
IMP + + 

AA=LS(IMP) 

02~AA 

GOSUB CD? FOR DIGIT CONVERSION 

DG=AA 

IMP+ + 

03=LS< IMF') ? DESTAD 

IF LJT 

WRITE 01 
WRITE 02 
WRITE 03 

END IF 

CHOOSE ON 01 

CASE OP? FETCH PARAMETER 
ITU=IPR(DG) 

CASE OD? CONVERT FROM DIGIT TO CHARACTER 
IAA“IF'R < DG) 

AA-IAA 
GOSUB CD 
ITU“AA 

CASE OB? POP STACK 
ITU=ISS(SP) 


48 


Dr. Dobb’s Journal, Number 65, March 1982 

135 




IF AA 


MS 'S STACKER' 
GOSIJB CR 
SP=C1 

ENDIF 
SR— 


CASE OS? FETCH FROM STACK WITHOUT POPPING IT 
ITU=ISS<SP) 

CASE OH? FETCH AND WRITE HEX CONSTANT BYTE 
AA-02 
GOSUB CIH 
IAA=AA 
IAA=IAA*I16 
AA=03 
GOSUB CH 
IBB”AA 
ITU=IAA+IBB 
03=0C 


CASE 01. ? LITERAL BYTE FETCH 
ITU-02 

CASE ON? LITERAL DIGIT FETCH 
AA-02 
GOSUB CD 
ITU=AA 

CASE OT? TURN ON TRACE MODE 
UT = + 001. 

DEFAULT? FETCH A UNIQUE NUMBER 
ITU=IUU 
IUU++ 


ENDCHOOSE 
IF UT 

III-ITU 
GOSUB PN 
ITU^ISS < SP) 
GOSUB PN 
ITU=SP 
GOSUB PN 


ITU-III 
GOSUB CR 

ENDIF 

CHOOSE ON 03 

CASE OC? CHARACTER OUTPUT 
AA-ITU 

WRITE AA INTO F2 
CASE OS? PUT ON STACK 
SP+ + 

AA-C4<-SP 
IF AA 

MS 'S OVERFLO' 
GOSUB CR 
SP=C4 

ENDIF 

ISS(SP)-ITU 


(Continued on next page) 


Dr. Dobb’s Journal, Number 65, March 1982 

736 


49 


8080 Pidgin (Listing continued) 


CASE OP? PUT INTO PARAMETER LOCATION 
IPR(DG)“ITU 

CASE OA? ADD TO STACK 
IAA--ISS ( SP) 

IAA"IAAtITU 
ISS(SP)~IAA 

CASE OR5 REDUCE (SUBTRACT) FROM STACK 
IAA-ISS(SP) 

IAA-IAA-ITU 
ISS(SP)=IAA 

CASE 0M» MULTIPLY BY BASE AND ADD 
IAA" :: ISS ( SP ) 

IAA=IAA*I10 
IAA==IAA +ITLJ 
ISS(SP)=IAA 

CASE OH y OUTPUT HIGH BYTE 
UNPACK(ITUy AA *BB) 

WRITE AA INTO F2 

DEFAULT i WRITE OUT AS A DECIMAL NUMBER 
GOSUB WN 

ENDCHOOSE 

ELSE f END OF ACTION SECTION 
AA-LS(IMP) 

IF UN 

BB-AA!~RC 

ELSE 

BB--C1 

END IF 
IF BB 

WRITE AA INTO F2 

ELSE 

WRITE NL INTO F2 

WRITE LF INTO F2 

END IF 
END IF 
IMPtt 
ENDWHILE 
UT=+000 
ENDSUB 5 DM 

BOTTOM5 END OF TINCMP 8080 CP/M COMPILER 


End Listing I 


Listing II 


stop; 


0 

EXTRN0 

?MSG? 

0 

EXTRN0 

?BOOT >?INIT rTENDING 

0 

COMMON0 

/IOCTRL/f 

• er ©:0 

DB0 

Of 

♦ AC0J0 

DB0 

Of 

♦ iav0: 

0 DW0 

o 

o 

o 

o 

o 

o 

0 

CQMMON0 

/ / F 

J BEGINMAIN(AC r 

IAV) f 


0 

DSEG? 


.ERASER.!?: DBB 

Of 

0 

CSEG t 


TSETAC0J0 

Mk;i0 

Af 1 F 

0 

RM r 


0 

RZi 


0 

XRA0 

Af 

0 

RET r 



50 


Dr. Dobb’s Journal, Number 65, March 1 982 

137 





7INTCK0J0 

MVI0 

Byly 

0 

LDAX0 

D? 

0 

CMP0 

My 

0 

JNZ0 

0$ + 8? 

0 

INX0 

H ? 

0 

INX0 

El? 

0 

LDAX0 

Ely 

0 

XRA0 

My 

0 

RZ? 


0 

M0V0 

A y B y 

0 

ret; 


7START0 J 0 

LXI0 

SP y ?STACK? 

0 CALL0 

7INIT? 


:PARAMETER K$$= 

$$$? 


JMS '$$$$$$$$$' 

? 


0 CALL0 

7MSG? 


0 DB@ 

' "PIC" 

P2C~P3C"P4C~P5C 

:gosub **» 

0 

CALL0 

.."Pic"P2c; 

:goto *$} 

0 

JMP0 

?LL0~P1C"P2Cf 

j**-+ooo» 

0 

XRA0 

Ay 

0 

STA0 

♦ ”P1C”P2C ? 

:i*$=+ooooos 

0 

LXI0 

HfOf 

0 

SHLD0 

.I"P1C"P2Cf 

:i*$=+k**s 

0 

LXI0 

H i .K"P3C"P4C} 

0 

SHLD0 

.I"P1C~P2C> 

i PACK' (I$$ F $$ F $*) } 


0 

LDA6 

."P5C"P60 

0 

MOV0 

Lr A. 

0 

LDAB 

."P3C"P4Cf 

0 

MOV0 

h f a } 

0 

SHLDe 

.I"P1C"P2Cf 


F7C~P8C"P9C '; 


0 

LHLD0 

•I"P1C~P2Cf 

0 

MOV0 

AfLf 

0 

STA0 

.~P3C"P4C) 

0 

MOV0 

AfHf 

0 

STAG 

,"PE5C“P6C} 

CALL. 

0 

LXI0 

H>0t+s; 

0 

PUSH0 

H) 

0 

LHL.H0 

.I"P1C"P2C? 

0 

PCHL} 


** = + K*$»* 

0 

MVI0 

A,.K"P3C"P4C 

0 

STA0 

♦ "F’1C"P2C} 


0 

MVIB 

A »' "P3C'> 

0 

STA0 

."P1C~P2C} 

**=+*$*} 

0 

MVIB 

Af"V3S"V4*"V: 

0 

STA0 

,"P1C"P2C} 

!$$=+$$$$$; 

0 

L.XI0 

Hf"V3S~V4*"V! 

0 

SHLD0 

.I"P1C"P2C} 

**=$$} 

0 

L.nA0 

."P3C~P4Cf 

0 

STA0 

,"P1C"P2C5 

$*++» 

b 

LXI0 

Hy"PlC~P2Cy 

0 

INRB 

M? 

■ift 

■eft 

1 

i 

0 

LXI0 

H y♦”P1C"P2C ? 

@ 

DCRB 

My 

1**=**} 

@ 

LHL.DB 

."P3C~P4C} 

0 

MV 10 

h»o; 

0 

SHLB0 

,I"P1C"P2C) 

:$*-!**} 

0 

L..DA0 

•I"P3C"P4C} 

0 

STA0 

."P1C~P2Cf 


0 

LHLDB 

,I"P3C"P4C; 

0 

SHLD0 

.I"P1C"P2C» 

;$$-$$($$)s 

@ 

LHLH0 

>"P5C"P6C} 

0 

MV 10 

H r 0! 

0 

LXI0 

D»,"P3C"P4Cf 

0 

DAH0 

n; 

@ 

MOV0 

A f M} 

0 

STA0 

."P1C~P2Cf 


0 

LHLDO 

„ p5 C«p 6C ; 

0 

MVI0 

HyO? 

0 

LXI0 

Ely » I"P3C~P4C 

0 

[i A Ei 0 

H? 

0 

Ei A D 0 

El? 

0 

LX 10 

Ely ♦ I”P1C”P2C 

0 

MOV0 

A y M ? 

0 

STAX© 

El? 

0 

I NX © 

D? 

0 

INX0 

H? 

0 

MOV0 

A y M ? 

0 

STAX0 

D? 

:$$=$$(!$$) ; 

0 

LHLD0 

.I~P5C"P6Cf 

0 

LX 10 

Df,"P3C"P4C} 

0 

Ei A D 0 

Df 

0 

MOV0 

AfMf 

0 

STA0 

."P1C"P2C} 


0 

LHLD0 

♦ I”P5C' n P6C ? 

0 

LXI0 

Ely I~P3C"P4C 

0 

D A D 0 

H? 

0 

DADO 

D? 

0 

MGV0 

E y M ? 

0 

ENX0 

H? 

0 

MOV0 

DyM? 

0 

XCHG ? 


0 

SHLD0 

♦ I”P1C”P2C ? 

:$$($*)=$*) 

0 

LHLD0 

♦ ”P3C"P4C ? 

0 

MVI0 

HyO? 

0 

LX 10 

Dy ~P1C~P2C? 

0 

Ei A D 0 

D? 

0 

L DAO 

♦”P5C”P6C? 

0 

MOV0 

M y A ? 

:i**($$)=i$*} 

0 

L.HLD0 

.~P3C~P4C? 

0 

MV 10 

HyO? 

0 

DADO 

H? 

0 

L..XI0 

Dy I~P1C~P2CI 

0 

DADO 

D? 

0 

L..XI0 

Ely . I”P5C”P6C > 

0 

LDAX0 

D? 

0 

MGU0 

Mr A? 

0 

INX0 

D? 

0 

I NX 0 

H? 

0 

LDAX0 

D? 

0 

MGV0 

MyA? 

:**<!*$)=**; 

0 

LHLDO 

.I"P3C"P4C! 

0 

L.XI0 

Df ,~P1C~P2Cf 

0 

DADO 

Df 

0 

LDAO 

>“P5C"P6C f 

0 

MOV© 

MfA} 

:i*$(i**>=i**) 

0 

LHLDO 

.I"P3C~P4Cf 

0 

LX 10 

Df«I"P lC"P2Ci 

0 

Ei A Ei 0 

Hf 

0 

DADO 

Df 

0 

XCHG? 



0 

LHLDO 

.I"P5C"P6Cf 

0 

M0V0 

AfLf 

0 

STAX© 

Df 

0 

INX0 

Df 

0 

M0V0 

AfHf 

0 

STAX© 

Df 


0 

LX 10 

Hf,~P5C"P6C 

0 

LDAO 

f"P3C"P4Cf 

0 

ADD0 

Mf 

0 

STA0 

."P1C"P2Cf 

$$=$$-$$; 

0 

LX 10 

Hf."P5C~P6C 

0 

LDA0 

."P3C"P4C} 

0 

SUB© 

M} 

0 

STA0 

."P1C"P2C} 

$$=$$*$$} 

0 

LX 10 

Hf."P5C"P6C 

0 

LDA0 

,"P3C"P4Cf 

0 

ANA0 

Mf 

0 

STA0 

."P1C"P2Cf 

:$$=$$?$$; 

0 

LXIB 

Hy ~P5C~P6C 

0 

LDAB 

. '■*P3C' n P4C ? 

0 

ORAL? 

M ? 

0 

STAG 

.~P1C"P2C? 


(Continued on next page) 


Dr. Dobb’s Journal, Number 65, March 1982 


51 


8080 Pidgin (Listing continued) 


:i**++; 


0 

LHLII0 

. I"P1C"P2C8 

0 

INX0 

H 8 

0 

SHLD® 

.I"P1C"P2C8 

Sit*—8 

0 

lhld® 

.I"P1C"P2C8 

0 

DCX® 

H» 

0 

SHLD® 

•I"P1C"P2C8 

:i**=-i**s 

e 

LHLD® 

♦I"P3C"P4C 8 

e 

CALL® 

TIC0MP8 

0 

EXTRN0 

?ICOMP 8 

e 

SHLD0 

.I"P1C"P2C8 

8I**=I**+I**8 

0 

LHLD® 

♦I~P5C~P6Ci 

0 

xchg; 


0 

LHLD® 

♦I”P3C~P4Ci 

0 

DAD® 

D i 

0 

SHLD® 

.I~PlC"P2Ci 

8I**=I**-I**8 

0 

LHLD0 

♦ I"P5C' n P6C i 

0 

XCHG 8 


0 

LHLD® 

*I~P3C~P4Ci 

0 

CALL0 

?ISUBi 

0 

EXTRN® 

TISUBi 

0 

SHLD® 

♦I”PlC~P2Ci 

:i**=i***i**s 

@ 

LHLD0 

.I"P5C"P6C8 

0 

XCHG i 



0 

LHLD® 

♦ I''P3C”P4C i 

0 

CALLS? 

?IMULi 

0 

EXTRN® 

?imul; 

0 

SHLD® 

♦I~P1C"P2Ci 

:i$$=i$$/i$$i 

0 

LHLD® 

•I"P5C"P6CS 

0 

XCHG S 


0 

LHLD® 

.I"P3C"P4C8 

0 

CALL® 

?idiu8 

0 

EXTRN® 

tinivs 

0 

SHLD® 

.I"P1C"P2C8 

t $$=$$==$$ f 

0 

LXI0 

Hr *~P3C~P4Ci 

0 

LDA0 

• "P5C"P6C i 

0 

CMP0 

Mi 

0 

JZ0 

0$+5i 

0 

XRA0 

Ai 

0 

LXI0 

B * 013EHi 

0 

STA0 

♦~PlC~P2Ci 

:**=**i=**; 

0 

LXI® 

H r•”P5C"P6Ci 

0 

lda® 

»"P3C~P4C i 

0 

CMP® 

Mi 

0 

JNZ® 

0$+5i 

0 

XRA® 

Ai 

0 

LXI® 

Br013EHi 

0 

STA® 

*~PlC~P2Ci 

:$$=$♦<«$$ f 

0 

LXI0 

H r ♦ '"P5C”P6C i 

0 

LDA0 

*"P3C~P4Ci 

0 

CMP0 

Mi 

0 

CALL0 

TSETACi 

0 

STA0 

♦"P1C”P2Ci 

:$$=$$<!$$? 

0 

LDA0 

♦~P3C"P4Ci 

0 

LXI0 

H r ♦ ''P5C"P6C i 

0 

CMP0 

Mi 

0 

RAL i 


0 

ANI0 

1 i 

0 

STA0 

*"PlC~P2Ci 

:$$=!$$* 

0 

LDA0 

♦P3C~P4Ci 

0 

CMA i 


0 

ANI0 

l i 

0 

STA0 

♦~PlC~P2Ci 

:**=i**==i**s 

0 

LXI0 

Dr.I~P5C~P6C 

0 

LHLD0 

»I"P3C''P4C i 

0 

LDAX0 

Di 

0 

XRA0 

Li 

0 

JNZ0 

0$+i2i 

0 

INX0 

Di 

0 

LDAX0 

Di 


0 

XRA0 

Hi 

0 

JNZ0 

0$+6i 

0 

MU .10 

A» li 

0 

LX 10 

B r 003EHi 

0 

STA0 

♦~PlC”P2Ci 

$$=!$$!=I$$i 

0 

L.XI0 

Hr ♦I~P5C”P6Ci 

0 

LX 10 

Hr♦I”P3C”P4Ci 

0 

CALL0 

TINTCKi 

0 

STA0 

♦~PlC~P2Ci 

$$=l$$<=l$$i 

0 

LHLD0 

.I"P5C"P6CS 

0 

XCHG i 


0 

LHLD0 

*I"P3C"P4C S 

0 

CALL0 

TCDEHLS 

0 

EXTRN0 

TCDEHLS 

0 

CALL 6 

TSETAC8 

0 

STA0 

."P1C"P2CS 

$♦=!$*<!I$$i 

0 

LHLD0 

.I~P5C~P6Ci 

0 

XCHG i 


0 

LHLD0 

♦ I' n P3C"P4C i 

0 

CALL.0 

7CDEHLi 

0 

EXTRN0 

TCDEHLi 

0 

RALi 


0 

ANI0 

1 i 

0 

STA0 

."PlC"P2Ci 

CASE tts 

"!OP"!9P"!8P 


0 

JMP0 

♦XC"PONi 

0 

ORG0 

0$-”P9Ni 

♦ UP~P8N0 J 0 

LDA0 ♦^PlC~P2Ci 

0 

CMP0 

Mi 

0 

JNZ0 

♦UP"U1S^S8N”N0S”P0Si 

ASSOCIATE FCB 

$ WITH 

I$$i 

0 

L.XI0 

Dr?IFCB+<<~P1C-1>*36 

0 

LXI0 

Hr.I~P2C~P3Ci 

0 

CALL.0 

?AT ACHi 

0 

EXTRN0 

7ATACH r 7IFCBi 

WRITE t*S 

0 

LDA0 

*~PlC~P2Ci 

0 

CALLS 

TWRNXTi 

0 

EXTRN0 

TWRNXTi 

:CLOSE t*S 

0 

LX 10 

Hr.~PlC~P2Ci 

0 

CALL0 

7BCL.0F i 

0 

EXTRN0 

7BCL0Fi 

:stop $i 

0 

MU 10 

Ar~PlCi 

0 

CALLS 

TISTOPi 

0 

EXTRN0 

TISTOPi 

! OPEN $$ FOR $t> 

AT I$$ 

i 

0 

LX 10 

Dr.~PlC~P2Ci 

0 

I..DA0 

♦”P3C”P4Ci 

0 

LHL.D0 

♦I~P5C~P6Ci 

0 

CALL0 

TIOPENi 

0 

EXTRN0 

TIOPENi 


ENDSUBi 



0 

RETi 


RETURNi 



0 

RETi 


EXTERNAL PROCEDURE t*S 


0 

CALL.0 

. *$$i 

0 

EXTRN0 

. .$$i 

READ $$ FROM 

$$ r 


0 

LXI0 

Hr*”P1C”P2Ci 

0 

LXI0 

Dr ♦ ' , P3C”P4C i 

0 

CALL0 

TBREADi 

0 

EXTRN0 

7BREADi 

WRITE $$ INTO 

$$i 


0 

LDA0 

.~PlC~P2Ci 

0 

LXI0 

Dr »~P3C~P4Ci 

0 

CALL0 

7BWRITi 

0 

EXTRN0 

7BWRITi 

ENDMAINi 



0 

CALL0 

TENDINGi 

0 

JMP0 

TBOOTi 

LOC $$i 



?LL0"P1C"P2C®S S 


CHOOSE ON $$i 



0 

LDA® 

.~PlC~P2Ci 


52 


Dr. Dobb’s Journal, Number 65, March 1982 

139 




s Lxie 

@ Move 

s default; 

"!0P"!9P"!8P 
e jmp0 

e ORG0 

.UP"F'8N0S ; 
"POS 

sendchoose; 

.XC"!ON0iy 

suhile; 

"uos.x"son@: ; 

:on $*; 

0 LDA0 

0 ORA0 

0 jze 

SENDUHILES 

0 JMP0 

.w"!on@:; 

:sub *$; 

.."P1C"P2C@S; 

:if tti 

0 LDA0 

0 ORA0 


H..ERASER .t 
M.A"U0S"N3S"U1S; 


.xc"pon; 

*-"P9n; 


."pic"P2c; 

A r 

.w"son; 

•x"son; 


."pic"P2c; 

Ai 


® Jze .f"uos"son; 

selse; 

0 JMP0 .F"UOP"PON"!9P» 

.f"P9nb:; 

"POS 

sendif; 


.F"!ON@!! 

•BYTE 


♦~P1C~P 

2C0S0 

use 

i; 

JINT l'$$5 

♦I~P1C~ 
J BYTE $$<*$$$$) 

P2CSS0 

nse 

2 ; 

♦~P1C~P 

2 ce: s 

DS0 

"V3S"V4*"V3*"VA*"V7*" ! 0N» 

.•BYTE $*<**$>; 

.'Tic~P2ce:e 

JINT I$$($$$*$); 

nse 

"V3S"V4*"V5*"!0N; 

.I"P1C" 

P2C0: s 

nse 

2#"V38"V4*"VS*"V6#"V7*"!ON 

SINT !«(«$)» 

.I"P1C" 

P2C0J0 

nse 

2#"V3S"V4*"V5*"!0N; 

: bottom; 

e 

dseg; 



0 

DS0 

ao; 


?STACK0 

se 

DW@ 

o; 

0 

SREADBUF $$» 

ENDS 

TSTART? 


0 

LXI0 

Dr."PIC 

"P2c; 

0 

CALLS 

1’rdbuf; 


0 

EXTRN0 

?rdbuf; 


!WRITEBUF *$? 

0 

LXI0 

Dr."PIC 

"P2c; 

0 

CALLS 

ywrbuf; 


0 

EXTRN0 

turbuf; 


SREAD $*; 

0 

CALL® 

?RNX i 


0 

EXTRN0 

7RNX i 


0 STAS 

slocal variables; 

S dseg; 

♦~P1C~P 

2 c; 

SENDLOCALP 

0 

cseg; 




:EXTERNAL PROCEDURE NAME *$; 

0 PUBLICS .."P1C"P2C; 

0 CSEGP 

.."P1C"P2C0J } 

:PROCEDURE end; 

0 RET > 

e end; 

*; 

1 REGISTER^**; 

:lomem=*****; 

:himem=*****; 


End Listing II 


Dr. Dobb’s Journal, Number 65, March 1982 
140 


53 



BOOK REVIEWS 


The 8086 Book (Includes the 8088) 

By Russell Rector and George Alexy 
Published by Osbome/McGraw-Hill 
$16.99, about 550 pages 
Reviewed by Ray Duncan 

Publishers have taken notice of the 
rapidly expanding, highly profitable 
microprocessor marketplace and have 
begun to flood computer stores with 
handbooks. All too often, these are poor¬ 
ly written and indexed, shot through with 
inaccuracies, or just blatant ripoffs creat¬ 
ed by paraphrasing the manufacturer’s 
technical literature. 

Happily, there are exceptions. The 
8086 Book is, for the most part, a lucid, 
well-organized, detailed guide to the 
Intel 16-bit microprocessor. Every pro¬ 
grammer working with the 8086 or 8088 
devices will find this book helpful. 

Before describing the good features 
of this book, I would like to do a little 
editorializing of my own. It seems that 
most of the handbooks traditionally 
begin with few pages giving a bonehead 
explanation of “what is a computer” on 
approximately the fourth-grade level, just 
before diving into the technical details 
directed at skilled engineers and program¬ 
mers with years of computer experience. 
This book follows the trend, and it is 
hard to understand how the authors 
could write some of the material with 
a straight face. A quote from chapter 
one: 

“The CPU operates with Is and 0s.” 

Could that statement possibly be 
aimed at the same audience which is ex¬ 
pected to comprehend, in chapter 8, 
“The first up-down counter tracks the 
depth of the queue, while a second up- 
down counter captures the queue depth 
on a match”? Please, budding authors, 
don’t try to make your books be all 
things to all people. 

After disposing of the foundations of 
computer science in about thirty pages, 
we get to a beautifully laid-out section 
on the 8086 instruction set, which com¬ 
prises the majority of the book. Mne¬ 
monics are explained, one to a page in 
alphabetical order. Since the 8086 has a 
large number of addressing modes which 
are sometimes hard to visualize, many 
specific examples are supplied together 
with their effects on the various CPU 
registers and flags. Diagrams are used 
liberally. 

There follows a set of tables of in¬ 
structions grouped by their various 


classes; i.e., data movement, arithmetic, 
shifts, transfers, etc. This is handy for 
those occasions when you know what 
you need the computer to do but can’t 
remember the mnemonic name, or aren’t 
sure whether an addressing mode is avail¬ 
able. 

The last few short chapters contain 
technical information concerning the 
8086 and 8088 microprocessors, such as 
timing diagrams and specifications of bus 
signals; largely a rehash of the Intel litera¬ 
ture which is available for free. Most of 
this would be unintelligible to a program¬ 
mer without an engineering background. 

The 8086 Book will be most useful 
to experienced assembly language pro¬ 
grammers with a fair amount of hardware 
expertise. It is not a guide to program¬ 
ming style on the 8086, although a few il¬ 
lustrative programs are sprinkled through¬ 
out the text. As a reference tool, it is well 
worth the money and is far superior to 
any other book about the 8086 I have 
seen. 

Pascal Programming Structures: An 

Introduction to Systematic 

Programming 
By George W. Cherry 
Published by Reston Publishing Co. 
$14.95, 313 pages 
Reviewed by Richard L. Lozes 

The first thing I noticed about this 
book was that it mentions no institution¬ 
al affiliation of the author. Nonetheless, 
the overall structure and particular de¬ 
tails lead me to believe that the author 
has had no meager experience in teaching. 

Pascal Programming Structures is a 
well-conceived text, meeting the needs of 
the novice programming student. It 
should also serve well, as it has in my 
case, to initiate hackers of other lan¬ 
guages, to the entirety of this now- 
famous language, Pascal. (This last state¬ 
ment begs clarification — author Cherry 
claims completeness, but without the 
ANSI standard at hand I had no way to 
verify that.) 

A student should never feel that he 
needs to read the next chapter before be¬ 
ing able to write real programs. Mr. 
Cherry is quite emphatic about displaying 
full, albeit simple, programs from the 
start. The text increases in difficulty as it 
moves along, making it simple for the 
professor trying to squeeze the last bit of 
information into the end of a course. 

Two positive remarks are in order. 
First, the traditional fog of bits, words, 


machine states, numerical representa¬ 
tions, and other points ordinarily found 
in introductory programming texts, but 
wholly lacking relevance, are absent. 
Second, the useful techniques of pro¬ 
gramming (top-down development, step¬ 
wise refinement) are presented and il¬ 
lustrated without the preachiness which 
has marred many other texts of recent 
vintage. 

Two negative comments are also in 
order. I found the style a bit too relaxed; 
I prefer not to see subject-verb contrac¬ 
tions, although I suppose the TV genera¬ 
tion will not notice. Far more important, 
1 dislike intensely the author’s practice 
of bracketing remarks by the 
likes of “Remark.” . . . “End of remark.” 
The English language already has conven¬ 
tions to serve this purpose: the parenthe¬ 
sis pair, and the footnote. The author 
seems to have confused English with Pas¬ 
cal, and in the interest of avoiding C. P. 
Snow’s “two cultures,” that confusion 
should never have reached print. 

Nevertheless, a solid introductory 
programming course could be built 
around this text. With determination, the 
entire text could be covered in a semester 
to good effect. 

Build Your Own Z80 Computer 
By Steve Ciarcia 

Published by BYTE Books/ McGraw-Hill 
$15.95, 332 pages 
Reviewed by George W. Jolly 

Have you ever thought that only an 
electrical engineer could design his own 
computer? I had begun to think so when 
this book came along. If you have a basic 
understanding of electronics, and a desire 
to build (or understand) your own micro¬ 
computer, then this book is for you. It is 
for technically-minded people who really 
want to learn. It assumes the ability to 
read schematic diagrams, and knowledge 
of common electronic components. It is a 
valuable book even if you do not choose 
to build a computer. 

Although the subject is a Z80-based 
computer, the text has wider application. 
Ciarcia presents the computer’s capabili¬ 
ties as a series of building blocks that you 
may arrange as you need. Most of these 
capabilities are not dependent on the 
choice of microprocessor. Design deci¬ 
sions are discussed in a straightforward 
manner, without introducing purely 
theoretical problems. The book’s empha¬ 
sis is on designing with standard, off-the- 
shelf components. Build Your Own Z80 


54 


Dr. Dobb’s Journal, Number 65, March 1982 

uT 




Computer offers fascinating insights into 
the computer design process. 

As the basic system circuits are pre¬ 
sented, procedures for testing them are 
explained. These discussions show you 
how computers work internally. The sub¬ 
ject of testing input and output intro¬ 
duces the concept of diagnostic software. 
Tiny programs are presented that allow 
you to test most of the basic computer, 
heightening your appreciation of the 
relationships between the parts of a com¬ 
puter. 

The system described is a single¬ 
board computer intended for a beginner’s 
experimentation. A monitor program is 
given, complete with assembled listing. 
Even better, flow charts for the func¬ 
tional modules of the monitor are shown 
and discussed at some length. The moni¬ 
tor handles a hexadecimal keypad similar 
to those found on commercially available 
single-board evaluation systems. Com¬ 
mands are provided to examine and 
change memory or registers, and to exe¬ 
cute a program in memory. The display 
consists of six output ports which drive 
hexadecimal display chips. 

Other peripherals covered are: a 
2708 EPROM programmer, an RS-232C 
serial port, a cassette-tape storage inter¬ 
face, and analog/digital conversions. For 
the more ambitious builder, an entire 
chapter is devoted to the design of a CRT 
display. The circuit shown is a 16-line, 
64-character format, but notes on design 
of a 24-by-80 display are also provided. 
Two integrated circuits do most of the 
work in this circuit. Most of the design 
work demanded by the project involves 
choosing parameter values to feed into 
these chips. The CRT display is not a 
memory-mapped video board, but a 
separate terminal using a serial port. A 
schematic for the serial port and ASCII 
keyboard encoder is provided, but not 
discussed at length. 

One particularly pleasant surprise in 
the book is the long tutorial on analog/ 
digital conversion. Several methods are 
explained, complete with actual circuits. 
One of the circuits is taken from a digital 
voltmeter; it differs from other circuits 
in that its results are in binary-coded 
decimal digits. A driver program is 
shown that can operate this circuit. 
Equally important, the basic theory of 
signal sampling is presented. Such possi¬ 
ble applications as voice reproduction and 
recording temperatures are discussed. 

Dr. Dobb’s Journal, Number 65, March 1982 
142 


Build Your Own Z80 Computer pro¬ 
vides appropriate technical information 
about the less-common integrated cir¬ 
cuits used. Data sheets for many of the 
integrated circuits used in the book, 
and the instruction set descriptions for 
the Z80 processor are provided. 

If you do wish to build from this 
book, you should read the construction 
techniques in appendix A. Remember, 
you will be prototyping your own lay¬ 
out, not “painting by the numbers.” 
Layout considerations are pointed out, 
but you will need to know how to physi¬ 
cally build circuits. Appendix A also 
lists a company that can provide pre¬ 
programmed EPROMS and kits. 

Ciarcia’s style is friendly and conver¬ 
sational. His pleasant manner makes for 
easy reading, an invaluable asset. His con¬ 
fidence and enthusiasm will inspire you. 
Build Your Own Z80 Computer is not a 
handholding construction book for those 
without electronics knowledge. However, 
this book offers a readable sampling of 
the author’s considerable experience. 


SOFTWARE REVIEW 


The WORD 

A proofreading, word look-up and 
writing toolkit for users of word pro¬ 
cessors. 

8” single density CP/M diskette 
(North Star, Superbrain, Apple 
w/Softcard); includes superb manual 
with clear instructions and examples. 
$75 from 
Oasis Systems 
2765 Renard Way 
San Diego, CA 92103 
Reviewed by Gene Head 


OASIS SYSTEMS in San Diego did 
three really remarkable things when 
they developed and began marketing The 
WORD, a spelling checker for CP/M files. 

First, they managed to cram a 
40,000+ word dictionary on a mini¬ 
floppy disk and still have room for the 
operating programs! 

Second, the entire spelling package 
costs just $75.00. 

Third, and especially important in 
my mind, is the fact that they have 
maintained the concept of software 
“tools” and have avoided the locked-in, 
do-everything, menu-driven mess that 
seems to be increasing in popularity 
among programmers! 

Overview 

The WORD is a package of software 
tools designed to eliminate spelling errors 
in files created in the CP/M environment. 
Usually these files would be created by a 
word processor, but The WORD will 
work with any ASCII file. My version was 
delivered on a single North Star mini¬ 
floppy with “un-packing” instructions. 
To “un-pack” the disk, two operational 
disks are copied from the master disk. 
Each disk has a copy of the main dic¬ 
tionary and copies of programs to meet 
specific needs. 

The manual is forty-two pages long 
and very comprehensive. Examples are 
used to walk the reader through the de¬ 
tails of every tool. Operation is quite 
simple even though a complete proof¬ 
reading session requires several steps. 
Here is where the “tools” concept has 
won out over the single-key-stroke won¬ 
der. Each program is independent of the 
others and each performs a unique func¬ 
tion. Generally, the procedure to proof¬ 
read a text file requires the execution of 


the SPELL, REVIEW and the MARK 
programs. Here is how it flows: 

SPELL 

The SPELL program will check every 
unique word in the file against the words 
in the main dictionary and any special 
dictionary the operator designates. Op¬ 
tions include “switches” to skip words 
with all capital letters (like XYZ INC.), 
or lines that begin with a period or colon. 
Many word processors use the period or 
colon in the first line position to indicate 
dynamic output formatting, especially 
.C+ for centering or .L63 for maximum 
line length. 

Un-matched words, words not 
located in the dictionaries, can be listed, 
printed, and/or written to a file called 
ERRWORDS.TXT. In the normal three- 
step operation, the file ERRWORDS.TXT 
is used by both the REVIEW and MARK 
programs. 

REVIEW 

REVIEW looks at the ERRWORDS.¬ 
TXT file. The ERRWORDS.TXT file con¬ 
tains all the words not found in the dic¬ 
tionaries. Now, it is obvious that not 
every word in your text file will be found 
in the dictionaries. Technical words, 
especially, may have been omitted. The 
REVIEW program will automatically dis¬ 
play each un-matched word from the 
ERRWORDS.TXT file and request opera¬ 
tor action. The operator has four options 
with each word. 

Add word to: 

U > pdate dictionary 
S >PECIALS.CMP file 
M > isspelled words list 
D > iscard 

Other options: 

P >revious word 
N >ext word 
R > esume review 
Q>uit and return to CP/M 
Note: The main dictionary can not be al¬ 
tered by the operator. 

The UPDATE dictionary is an ex¬ 
tension of the main dictionary and will 
automatically be searched whenever it is 
present on a disk with the main dic¬ 
tionary in the UPDATE file. Less 
common words of a special nature (like 
jargon or acronyms) would go into the 
SPECIAL dictionary. Unlike the UP¬ 
DATE dictionary file, the SPECIAL dic¬ 
tionary file is searched only if the special 
search switch is activated. Of course, 


some words (like personal names) are so 
unique they should just be discarded. 

The other options allow for stepping 
forward or backward through the list. Ad¬ 
ditionally, after a word has been pro¬ 
cessed and recalled by the Previous word 
option, the current status of the word is 
displayed instead of the hyphen. 

—> ALPHA D 

This prompt indicates the word 
ALPHA has been previously set to be 
Discarded. 

Finally, REVIEW will write the ap¬ 
propriate words to the UPDATE, SPE¬ 
CIAL, and ERRWORDS files. The MARK 
program will now use the ERRWORDS 
file that has been REVIEWED and con¬ 
tains only words that are really mis¬ 
spelled. 

MARK 

MARK is the simplest program and 
has only one option. When executing 
MARK a file must be specified as the file 
to be marked. 

A> MARK B :TEXTFILE.PCL 

The above example will cause the file 
named TEXTFILE.PCL on drive B to be 
searched for matches to the words in the 
ERRWORDS.TXT file.Whenever a match 
is found the misspelled word is marked 
with a The original TEXTFILE.PCL 
is renamed TEXTFILE.BAK and a new 
file named TEXTFILE.PCL is written and 
includes the inserted “*” to denote mis¬ 
spelled words. The word processor can 
now be used to locate “*” and all mis¬ 
spelled words. Editing commands of the 
word processor should make fixing the 
misspelled words especially easy. I men¬ 
tioned earlier the use of only one option 
when running MARK. If you want to use 
a different character to mark the mis¬ 
spelled words, the option is: 

A > MARK B :TEXTFILE.PCL $M# 

The “$M” sets the mark character 
switch and the new mark character be¬ 
comes the “#” character. 

Additional Programs 

Two similar programs, LOOKUP and 
FIND, will help you locate the correct 
spelling if the word is in any of the dic¬ 
tionaries. The FIND program searches for 
words and recognizes both the “?” and 
the as wild-card characters. If, for 
instance, you want to spell ABASEMENT 
but can’t remember if the word is spelled 
ABASMENT or ABASEMENT then the 


56 


Dr. Dobb’s Journal, Number 65, March 1 982 

143 






following command would return all the 
words beginning with ABAS regardless of 
actual total length. 

A>FIND ABAS* 

Likewise, to locate all words in the 
dictionary that are exactly five letters 
long and begin with the letters “SHO” 
use the following command line. 

A > FIND SHO?? 

The dictionaries have an internal in¬ 
dex table for each letter of the alphabet. 
The search algorithms utilize this index 
table to decrease search times. If the first 
letter of the word in question is given, 
only the words beginning with that letter 
will be searched. In the last example only 
the words beginning with the letter “S” 
will be searched. Avoid especially a wild¬ 
card “?” in the first character position as 
this will cause the entire dictionary to be 
searched! 

LOOKUP uses a different approach 
based on the assumption that most mis¬ 
spelled words fall into one of four cate¬ 
gories: 

1 . Added extra letters (ACCUTE in¬ 
stead of ACUTE) 

2. Dropped a needed letter (ABSESS 
instead of ABSCESS) 

3. One letter wrong (ACCUR instead 
of OCCUR) 

4. Two letters reversed (ACER in¬ 
stead of ACRE) 

Using these four assumptions the 
proper spelling of most misspelled words 
can be found in the dictionary file. 

For those who still have trouble with 
THERE and THEIR or CAPITOL and 
CAPITAL, the HOMONYM HELP pro¬ 
gram will locate most common homo¬ 
nyms and mark them in the text file. Ob¬ 
viously, this helper can’t choose which 
homonym is the correct usage but it can 
quickly locate possible trouble spots for 
careful consideration. 

In addition to the three dictionaries 
already mentioned (MAIN, UPDATE and 
SPECIAL) the user can merge any dic¬ 
tionary (except the MAIN dictionary) 
with any other dictionary using the PIP 
program in CP/M. Several SPECIAL and 
UPDATE dictionaries can be combined 
and then sorted using the DICTIONARY 
SORT program. All combined diction¬ 
aries must be sorted before they can be 
properly used by the SPELL program. 
Remember, the dictionaries have an index 
to speed up searches. 

Finally, the WORD COUNT program 
and the WORD FREQUENCY program 


are especially useful to writers. The first 
simply counts the words in the text file. 
The second will determine the frequency 
of each word. The output can be to a text 
file called TEXTFILE.FRQ or to the 
printer or the console. The output can be 
sorted either alphabetically or by fre¬ 
quency of usage. Sorted by frequency of 
usage, the most used word (usually 
“the”) will be listed first with the number 
of times it was used in the text. Getting a 
little tired of seeing the word “especially” 
in this article? It was used seven times, or 
about five times too many for easy 
reading. 


Conclusion 

For those seeking a single-key-stroke 
approach, this can almost be achieved 
using CP/M’s SUBMIT program with the 
proper instruction file (.SUB). 

All of the programs are relatively 
slow on my 2 MHz, mini-floppy system. 
However, the manual indicates significant 
speed increase for CPU’s running at 4 
MHz or better, and eight-inch floppies or 
hard disks. It took about four minutes 
and ten seconds to completely correct 
this article with ten words originally mis¬ 
spelled. The correct spelling of every mis¬ 
spelled word was located using the 
LOOKUP program. I suppose this indi¬ 
cates I misspell like most misspellers. The 
words FORMATTING, FLOPPIES, and 
MISSPELLERS were not in the diction¬ 
ary. Of course, I knew how to correctly 
spell all the words. There were four easy 
typo’s and I purposely made mistakes for 
timing considerations only. 

As a test, I subjected two text files 
that were written over a year ago to the 
SPELL program. The first was an article 
I wrote reviewing a popular word proces¬ 
sor. I had reviewed the manuscript several 
times and was pretty sure of its accuracy. 
The second file was a university term 
paper written by my wife. The paper re¬ 
ceived a grade of “A”. It was written for 
a Technical Writing course and spelling 
was considered a prime area of evalua¬ 
tion. It was returned with no errors de¬ 
tected. The SPELL program found three 
misspelled words in the term paper and 
seven misspelled words in my article! 

I enthusiastically recommend The 
WORD to all serious writers. Manuscripts, 
term papers, and official documents will 
always look just that much better with no 
spelling errors. The versatility of the pro¬ 
grams make The WORD simply a set of 


writing tools and not a cure-all, do-all- 
for-everybody, turn-key, single program. 
Like any useful tool, the user must under¬ 
stand the limits and the designed purpose 
of the tool. 

The WORD is not tutorial. While it is 
quite friendly and easily learned, it re¬ 
quires time and effort to become familiar 
with the many features found in the pro¬ 
grams. For me, The WORD has become a 
necessary extension of my word pro¬ 
cessor. 


Dr. Dobb’s Journal, Number 65, March 1982 
U4 


57 



HARDWARE REVIEW 


Universal Data Systems 103LP Modem 
Universal Data Systems 
5000 Bradford Drive 
Huntsville, AL 35805 

Reviewed by Dave Caulkins 


T he UDS 103 LP is a 300 baud 
RS232 interface, answer/originate 
line-powered FCC Part 68 certified 
modem. The most important of these are 
the FCC certification and line-powered 
features. FCC certification means the 
103LP can be directly connected to the 
phone line via a standard modular jack; 
direct connection improves the perfor¬ 
mance of the modem considerably over 
that possible with acoustic coupling. 
“Line-powered” means that the modem 
draws the power it needs from the phone 
line; there is no need for a 110V AC con¬ 
nection. This is a neat feature and as far 
as I know unique to UDS. It means you 
don’t have to go hunting around for an 
AC outlet that’s near the telephone jack. 

The modem is quite small and light; 
it’s designed to fit under a standard tele¬ 
phone. Installation is very easy; connect 
your terminal or computer to the RS232 
female connector on the back of the 
modem, plug a standard telephone instru¬ 
ment into the modular jack labelled 
“TELSET” on the back of the modem, 
plug the telephone line into the modular 


jack labelled “TELCO” and you’re ready 
to go. Set the switch on the back of the 
modem to “TERMINAL”. If you’re ori¬ 
ginating the call, set the switch on the 
back of the modem to “ORIGINATE”. 
Make sure the switch on the front of the 
modem is set to “TALK”, then dial the 
number of the answer modem with which 
you wish to communicate. When you get 
the modem answer tone, change the 
DATA/TALK switch to DATA; the LED 
should come on. At this point you can 
hang up the phone and start data transfer. 
When you’ve finished transferring set the 
DATA/TALK switch back to TALK to 
hang up the phone. 

We’ve used the UDS 103LP to talk 
to a wide variety of computer systems 
and never had a lost or garbled character. 
The one problem we’ve had has been with 
the line-powered feature — there are 
some places in Menlo Park where the 
phone company evidently does not meet 
its own spec for central office battery, 
the power source needed by the UDS 
103LP. It’s hard to argue with the phone 
company about matters that don’t relate 
to plain old voice service; if you get a 
UDS 103LP, make sure the company that 
supplies it to you will either allow you to 
return it or be prepared to deal with the 
phone company in case you are in one of 
those rare locations where the 103LP 
won’t work. 


SPECIFICATIONS 

The UDS Model 103LP is a fully Bell-compatible, originate only modem with 
the following operating characteristics: 

Operation - full duplex on two-wire circuit 

Data Rate - 0 to 300 bps asynchronous 

Modulation - phase coherent, frequency shift keyed (FSK) 

Operating Mode — Switch-selectable, originate or answer 
Line Type — DDD network 

Carrier Frequencies — Compatible with Western Electric 300 bps modems 
Line Impedance — 600 ohms 
Transmitter Level-9 db 

Receiver Sensitivity —8 to -46 dbm; meets FCC requirements, Part 68 
Digital Interface - RS-232C, CCITT V.24, TTY 

Controls and Indicators — Data/Talk switch; data ON light emitting diode 
Originate/Answer Switch 

FCC Registration — Model 1031LP; Registration Number AK396F-67636- 
DM-E; Ringer Equivalence 0.0B; Data Jack RJ-11C 
Package — stand-alone 


Dr. Dobb’s Journal, Number 65, March 1982 


61 

145 











8080/8086 Cross Assembler 
Part II 

Jonathan Mills 


Son of Runic 

Marty Franz 

Small-C DISKDOC 

Egil Kvaleberg 


A Poor Person’s 
Spelling 
Checker. .. 

. . . Check 
Digits 

Maximized. .. 

. . .Elliptical 
Algebra 


and much more! 













CONTENTS 


Dr. Dobbs Journal 

April 1982 Volume 7, Issue 4 


Editor - Marlin Ouverson 
Contributing Editors — 

Dave Caulkins, Dave Cortesi 
Marketing Director — Craig Harper 
Marketing Assistant - Ari Taylor 
Advertising Sales — Laird Foshay 
Circulation - Gloria Romanoff, 

Theresa O’Rourke, Terri Marti 
Art Director — Clifford West 
Production Manager - Barbara Ruzgerian 
Typesetter - Renny Wiggins 
Proofreader — Nancy Heubach 
Cover Illustration - A1 McCahon 


© 1982 by People’s Computer Company 
unless otherwise noted on specific articles. 
All rights reserved. 

Subscription Rates: $2 5 per year within the 
United States; $40 for first class to Canada 
and Mexico; $58 for airmail to other coun¬ 
tries. Payment must be in U. S. Dollars, 
drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be 
typed, double-spaced on white paper. List¬ 
ings should be produced by the computer, 
using a fresh, dark ribbon on continuous 
white paper. Please avoid printing on perfo¬ 
rations. Payment is in contributor’s copies. 
Requests to review galleys must accompany 
the manuscript when it is first submitted. 
Authors may receive a copy of the complete 
writer’s guidelines by sending a self- 
addressed, stamped envelope. 

Donating Subscribers Contributing Sub¬ 
scriber: $50/year ($25 tax deductible). Re¬ 
taining Subscriber: $75/year ($50 tax de¬ 
ductible). Sustaining Subscriber: $ 100/year 
($75 tax deductible). Lifetime Subscriber: 
$1000 ($800 tax deductible). Corporate 
Subscriber: $500/year ($400 tax deductible, 
receives five one-year subscriptions). 

Contributing Subscribers: Eric H. Johnson, 
Jerry Horn, Edward W. Carr, Steven Fisher, 
Thomas H. Grohne, G. V. F.lkins, Robert M. 
Connors, William J. McEown, Robert C. 
Luckey, Kim Leary, Robert N. Stabler, 
DeWitt S. Brown, John B. Palmer, E. Glion 
Curtis, Jack Miller, Burks A. Smith, Trans¬ 
data Corproation, Mark Ketter, John W. 
Campbell, Friden Mailing Equipment, 
Howard E. Decker, Jim Wilson, Frank 
Lawyer, Chris Pettus, Paul Lutus, Ben 
Goldfarb, Rodney Black, Steven Weiss, Pat 
Phelan, John Brodie, James Fleming, Unison 
World. Sustaining Subscribers: Gordon 
Eubanks, Jr., and Pete Roberts. Lifetime 
Subscriber: Michael S. Zick. 

Foreign Distributors UK & Europe: lp 

Enterprises, 8/11 Cambridge House, Cam¬ 
bridge Road, Barking, Essex, iGl I 8NT, 
England (Tel. 01-591-651 1, TLX 892395). 
Hofacker-Verlag, Tegernseer Strass 18, D- 
8150 Holzkirchen, West Germany. Asia & 
Australia: Computer Store, POB 31-261, 
22B Milford Road, Milford, Auckland 9, 
New Zealand. ASCII Publishing Co., Ltd., 
Aoyama Building 5F, 5-16-1 Minami 

Aoyama, Minato-ku, Tokyo 107, Japan. 


16 8080/8086 Cross-Assembler, Part 2 

by Jonathan Mills 

Last year’s most widely acclaimed DDJ article was part one of this series, which 
covers the activities of the Z-88 Project. The author’s latest contribution covers 
some features of the XASM-86 development language and of Intel’s 8087 
Numeric Data Processor chip. 

26 Small-C DISKDOC: A Repair and Maintenance Utility 

by Egil K vale berg 

A down-to-earth addition to the toolkit of anyone who uses and prepares pro¬ 
grams for diskettes. This program is written to be compiled by Ron Cain’s 
Small-C compiler (sec our back issues, esp. #45 and #48) and is meant to be 
used in a CP/M environment. Its appeal is even broader in scope, as it is written in 
a high-level language and has a general, easily adaptable structure. 

36 Making the Most of Check Digits 

by Peter Zilahy Ingerman 

Check digits — once you know how to use them - can be much more than just 
simple error indicators. They can tell if there was one error or several, what the 
errors most likely were, and the probable correction. 

42 A Poor Person's Spelling Checker 

by Alan Bomberger 

New proofreading and spelling correction programs seem to appear every month. 
Dictionaries contain more words, and editing functions become (somewhat) less 
cumbersome - yet most still leave much to be desired. This version is published to 
foster wider interest in the features and foibles of such software. Can anyone find 
a better way? 

54 Son of Runic: Writing the Compiler 

by Marty Franz 

When this author opted for CP/M over his older Pet, he found the environment he 
needed for language development. This article describes some of the implementa¬ 
tion details of his Forth-like Runic, an interactive, extensible compiler described 
in last month’s issue. 


4 Editorial 

4 Letters to the Editor 

Wherein readers correspond, despond, describe and diatribe over their upsets, 
subsets, sobriquets and sob stories. 

9 Dr. Dobb's Clinic 

Among the many cases and cures at the Clinic is a special patient; help our Intern 
ease the hyperbole! 

12 Of Interest 

As usual, the tides of industry brought bushels of press releases to our editorial 
shores. The foremost amid the flotsam can be found in this column . . . 

58 Software Reviews 

59 Hardware Review 

60 Book Reviews 


Dr. Dobb's Journal (UPSP 307690) is published twelve times per year by People’s Computer 
Company, Box E, 1263 El Camino Real, Menlo Park, CA 94025. Second class postage paid at 
Menlo Park, California 94025 and additional entry points. Address correction requested. 
Postmaster: send form 3579 to Box E, Menlo Park, California 94025. 


Dr. Dobb’s Journal, Number 66, April 1982 
148 


3 


LETTERS 


Back To BASIC Bugs 
In Santa Barbara 


Pascal Compiler and more. Sort of what 5. Unary Minus function not coded 

you find on SI00 machines, but faster. properly. 



Dear Dobbs, 

Thank you for your letter of the 
22nd January concerning my query about 
SBTB in issue #55. From the other letter 
you enclosed it must seem that 6809 
owners are a wild-eyed bunch given to 
such strange practices as hand entering 
object code (probably using toggle 
switches). Fortunately this is not the 
case, since this 6809 system supports a 
good (but not great) Macro Assembler, 
Son of EMACS full screen Text Editor, 
NROFF-style Text Processor, Sort/Merge 
package, Debugging facilities based on a 
full software emulation of the ’09 pro¬ 
cessor, Extended BASIC interpreter, 


Now, on to SBTB, and its ills. I had 
noted the bugs referenced in the letter 
from Mr. Barton, plus others. Enumerat¬ 
ed, they were: 

1. Macro definition of HERE would 
not assemble. 

2. Macro expansion of TSTC pro¬ 
duces assembly errors. 

3. No “not equals” expression in the 
expression analyzer. 

4. The “less than” (<) comparison 
operator not a signed compare. 


6. LIST command would only list 
the first line of the program. 

To correct the HERE macro, make 
the definition of the first FCC pseudo op 
read “&1”. The quotes are part of the 
definition. 

To correct the TSTC problem, at 
every substitution instance of TSTC in 
the source code, make the compare quan¬ 
tity a quoted string, as TSTC “’ ;”,FI1. 
The TSC Macro-Assembler requires the 
quoted string, and I do not know how the 
assembly listing published was accom¬ 
plished in a 0 ERROR(S) DETECTED 
condition. 

The no “not equals” bug requires 
changing the definition of HERE ’=’ on 
page 26 of the original. Make it read 
HERE ’#’ and make the BEQ op code 
read BNE. 

Similarly under HERE ’ < ’ make the 
BLS read BLE to create a signed com¬ 
pare. 

The Unary minus problem may be 
corrected on page 27 by making the code 
read: 

COMA 
COMB 
ADDD #1 

Strangely, this 16-bit two’s comple¬ 
ment was coded properly later on in the 
code. 

To correct the LIST problem, re¬ 
place the TSTA instruction found six 
lines from the top of page 31 with a 
LDD ,Y which will then pass the next line 
number of the FNDLNP routine, allowing 
it to indeed find the next line pointer. 

At this point, I have given at least 
first level testing to all the keywords and 
I am satisfied that they will perform 
nominal case actions. One final correc¬ 
tion, from the text of the original PATB 
article, the abbreviation for “RETURN” 
is “RET.”. 

If anyone is interested in an all- 
FLEX version of SBTB, I will be happy 
to provide a listing in exchange for 
postage. 

Very truly yours, 

Douglas K. Beck 
995 Lundy Lane 
Los Altos, CA 94022 


EDITORIAL 


Wanted: Silicon Visions 

Clandestine meetings to stifle foreign competition in the computer 
marketplace? Some industry leaders fear Japan is planning to repeat in Silicon 
Valley what it has done to Detroit. Unlike the cumbersome Motown giants, 
though, they aren’t stubbornly content with roles as sitting ducks on a target 
range. They see the danger and aim to meet fire with fire. 

The whole concept revolves around a fifth generation computer, destined 
to replace current technology in the 1990’s. (Ha! Don’t bet it will take that 
long . ..) Who will be the first to produce it, and just what will it be? Some 
computer and semiconductor firms are considering a joint venture to ensure 
that whatever it is, it won’t be Made in Japan. I prefer to take the optimistic 
view, that this is an experiment in cooperation and won’t end in monopoly. 
Although, there is that adage about power and corruption . .. 

While the lawyers worry about anti-trust laws and Board members 
scrutinize profit margins, the international community of DDJ readers could 
set the pace by writing of their own ideas about the next generation of 
computers. Send in your silicon visions — regardless of country of origin — 
and we will get them in print as space permits. We will carry the spirit of 
cooperation to a global scale. There will be no editorial value judgments: be 
as ingenious, reasonable, outrageous or droll as you like. 

Instead of independently re-inventing the wheel for clonish new 
products, the thought of foreign companies making serious inroads into U.S. 
profits may motivate the industry leaders to lend an ear to the innovators. It’s 
time the mainframe makers began listening to the micro community without 
smirking! Ours is a younger, fresher viewpoint, a trait that has built more 
than one empire, in more than one nation. 

Think about the concept of cooperation and about the attitude that 
anything is possible and should be tried at least once. They begat personal 
computing, and are the parents of DDJ. If we carry on the tradition a while 
longer, who knows? As long as we are thinking big, let’s think BIG . . . 

Editor 


4 


Dr. Dobb’s Journal, Number 66, April 1 982 

149 





The Eve of ADAM 

Dear Dr. Dobb’s: 

You can pick up any issue of the 
SIGPLAN notices nowadays and see 
statements like 

Subsetting [of Ada] has become so 

necessary that it is administratively 

forbidden. 

What is the penalty for writing a 
compiler for an Ada subset? Will the Pen¬ 
tagon dispatch an Ada Compliance Death 
Squad (ACDS) to your house? Do you 
want to take that chance? 

Just to play it safe, 1 recommend 
that all Ada-like languages be given slight¬ 
ly different names. I am placing the fol¬ 
lowing words into the Public Domain 
to be used to identify languages derived 
from Ada and for languages derived from 
other sources but dressed up to look like 
Ada in order to be fashionable. 

A Partial Solution to the Ada Problem 

ADACTYLOUS GRADATION 

ADAGE GRANADA 

ADAGIO HAGGADA 

ADAM HEADACHE 

ADAMANT LACKADAISICAL 

ADAPT MACADAM 

ARMADA MADAM 

CADAVER NEVADA 

CICADA NOWADAYS 

DEGRADATION PLEADABLE 

GADABOUT RADAR 

GONADAL READABLE 

Other words can be derived from 
these, and I think it is especially instruc¬ 
tive that ADAMANTINE is almost a 
synonym of STEELMAN. Notice that 
some of the Ada-like languages might be 
well suited for military applications, 
particularly ARMADA and RADAR. My 
personal interest is in GADABOUT, 
which will be an Ada-like language that 
can compile and run on a 6502. 

Douglas Crock ford 
14541 Countrywood Lane 
Irvine, CA 92417 

H8 Feature Not Quirky 

Dr. Dobb's, 

I noticed an item of interest in the 
November, 1981, issue of DDJ. It may 
already have resulted in a reply from 
another reader, since I admit that I got 


this issue from the “newsstand” rather 
late. But if it is still of interest, here goes. 

Terrence Hills of Ontario wrote in 
about a “dangerous quirk in the Heath 
H8” front panel software monitor. The 
“quirk” results from a “feature” of the 
monitor, which is also shared by the 
monitor in the H88/H89 computer, 
namely HALT detection. The monitor 
attempts to detect the CPU’s execution 
of a HLT instruction and exit to the 
monitor if found. As you described, the 
monitor does this by checking the opcode 
at the return address -1 for equality with 
166 Octal (76 Hex), the value of the HLT 
instruction. As you pointed out, there is 
the possibility of other opcodes and data 
bytes trailing with a 166Q value that the 
monitor might be fooled into thinking is 
such an instruction. In theory, there is a 
risk of re-entry of the front-panel moni¬ 
tor every 2 milliseconds, when the clock 
interrupt occurs! 

In practice, this risk is quite small. I 
have used the H88/H89 computers for 
several years and never had an unexpect¬ 
ed re-entry to the monitor because of 
HLT detection. The reason would seem 
to be easily explained, it turns out. Con¬ 
sider the worst-case chance of a random 
166Q byte being inadvertently decoded 
as a HLT. In the 2ms interval from one 
clock interrupt to the next, with a 2MHz 
clock, there will be 2,000,000/500 or 
4000 clock cycles (assuming that the 
clock interrupt routine takes zero cycles 
— remember this is a worst case analysis). 
Of the opcodes available that could 
possibly contain a 166Q byte, the slowest 
8080 code would be CALL xxxx where 
xxxx was an address having 166Q as the 
high byte; or the Z80 codes, the slowest 
ones ending in 166Q would be the INC 
(IX+ 166Q) , INC (IY+166Q), DEC (IX + 
166Q) , and DEC (IY+166Q). The 8080 
CALL requires 20 clock cycles, and the 
Z80 INC/DEC instructions on the index 
registers requires 23 clock cycles. This 
gives a worst-case chance of 20/4000 
(0.5%) or 23/4000 (0.575%) that one of 
these opcodes would randomly fall just 
at the time of a clock interrupt. 

Naturally, the chance of erroneous 
HLT detection is markedly increased if 
the CPU spends a lot of time executing 
opcodes with 166Q’s in them, such as in 
a tight loop. Consider the potentially 
meaningful program in listing one. In that 
extreme example, the CPU spends only 14 
clock cycles of each loop iteration total¬ 
ing 68 clock cycles, executing an instruc¬ 


tion that does not end in 166Q! This loop 
has a 54/68 chance (79%) of landing in 
the monitor at any 2ms clock tick! Obvi¬ 
ously, one would not want to use such 
code in an H8 or H89. It would have a 
99% chance of bombing out within 6 
milliseconds! 

But that is not strictly true! Heath 
software engineers weren’t way out in 
left field when they wrote the ROMs for 
the H8 and H88/H89. They recognized 
that software HLT detection would be a 
handy way for user programs to return 
to the monitor, but also a potentially 
great liability with certain program se¬ 
quences. So they built in the ability to 
disable HLT detection, and made it an 
automatic feature invoked every time 
that their own disk operating system, 
HDOS, is booted up! This means that no 
H8 or H89 program running under HDOS 
is at risk of accidental monitor re-entry 
from “pseudo-HLT” unless the code 
specifically re-enables HLT detection! 

As I have said, I’ve never had an 
accidental “HLT” with the cassette tape 
software provided by Heath (which uses 
HLT detection) nor, naturally, with 
HDOS disk software (since HLT detec¬ 
tion is suspended automatically). But for 
the user who wishes to “guarantee” free¬ 
dom from accidental monitor re-entry, it 
is quite simple. Listing two shows a sim¬ 
ple piece of code that disables HLT de¬ 
tection in assembly language (and also 
shows subsequent re-enabling of HLT 
detection and re-entry of the monitor 
as Heath intended). Listing three shows 
the same functions in Benton Harbor 
Basic, and listing four shows Microsoft 
Basic (but MBASIC is only available on 
a disk system, and as I said, HLT detec¬ 
tion is already disabled for you). 

Hopefully, l have put reader Hills 
(and other H8 and H88/H89 owners) 
at ease about this potential problem. An 
experienced reader of 8080 assembly 
code can actually see how HLT detection 
words (and how it can be disabled) by 
examination of the H8’s PAM-8 monitor 
code listing (or the H88/H89’s MTR-88 
ROM), which Heath provides free of 
charge with any of their cassette or disk 
software operating systems. Proof of HLT 
detection disabling under HDOS comes 
from inspection of the source code for 
HDOS, which can be purchased from 
Heath for $195.00. I have inspected both 
quite closely, and can state without reser¬ 
vation that the Heath software is solidly 
dependable and well-written, and in fact 


_ 6 _ 

150 


Dr. Dobb’s Journal, Number 66, April 1982 


ADDRESS 

OPCODE BYTES LBL 

OPCODE 

OPERAND 

COMMENTS CLOCK 

CYCLES 

166.166 

333 

166 

LOOP 

IN 

166Q 

;get a byte from port 166Q 

10 

166.170 

346 

166 


AN I 

166Q 

;mask out unwanted bits 

7 

166.172 

300 



RNZ 


;got a value, so return to caller 

5 

166.173 

315 

201 

166 

CALL 

NOTYET 

;deal with "no input" situation 

20 

166.176 

303 

166 

166 

JMP 

LOOP 

;and go back to try again 

10 

166.201 076 

166 

NOTYET 

MV I 

A,166Q 

;set limit in A 

7 

166.203 

270 



CMP 

B 

;test against B 

4 

166.204 

300 



RNZ 


;return if limit not reached 

5 







Total = 

68 

LISTING 

ONE 

Section of code highly susceptible to PAM-8/MTR-88 HLT detection. 



.MFLAG 

EQU 

04^010A 

;monitor mode flag byte address 

DISAB 

LDA 

.MFLAG 

;get flag byte in A 

;set the "UO.HLT bit"(200Q or 1O00OO00B) 


ORI 

200Q 


STA 

.MFLAG 

;put flag byte back, and HLT will now be ignored! 

EANB 

LDA 

.MFLAG 

;Get flag byte 


AN I 

177Q 

;Strip off “UO.HLT bit" 


STA 

.MFLAG 

;put back flag byte, adjusted (enable HLT detection) 


El 


;make sure the 2ms clock can tick! (enable CPU interrupts) 


HLT 


;Halt, let PAM-8 or MTR-88 take over. 

LISTING 

TWO: 

Disabling and 

re-enabling HLT detection by Heath Monitor, in assembly 

language. 


65000 F0 = PEEK(8200) 

REM Get monitor flag byte 

65010 F0 = F0 OR 128 

REM Make sure high bit is set 

65020 POKE 8200,F0 

REM Store newly-adjusted flag. HLT detection is now gone 

65030 RETURN 

REM All done 

65000 POKE 8200,(PEEK(8200) OR 128) : RETURN : REM Same as above, compacted. 

65000 F0 = PEEK(8200) 

REM Get flag byte 

65010 F0 = F0 AND 127 

REM Remove the high bit 

65020 POKE 8200,F0 

REM Store adjusted flag byte. HLT detection now active 

65030 RETURN 

REM All done 

65000 POKE 8200,(PEEK(8200) AND 127) : RETURN : REM Same as above, compacted 

LISTING THREE: Disabling and enabling HLT detection in Benton Harbor BASIC. 


65000 'Disable HLT detection by PAM-8 or MTR-88 ROMs 

65010 MF = &O040 * 256 + &O010 'Split-Octal address of .MFLAG converted to decimal 

65020 POKE MF,(PEEK(MF) OR 128) 'Re-Store with high bit set 

65030 RETURN 'HLT detection is now gone 


65000 'Enable HLT detection by PAM-8 or MTR-88 ROMs 

65010 MF = &O040 * 256 + &O010 'Split-Octal address of .MFLAG changed to decimal 

65020 POKE MF,(PEEK(MF) AND 127) 'Re-Store with high bit cleared 

65030 RETURN 'HLT detection is now re-enabled 


LISTING FOUR: Disabling and enabling HLT detection in Microsoft BASIC 


contains even more “hidden” features 
that many users are unaware of! 

John P. Toscano 
614 Portland Mews 
Burnsville, MN 55337 

(More on this aspect of the Heath com¬ 
puters may be found in this month’s 
Clinic. - Ed.) 


Bracketeer? 

Dear Sir: 

My letter of complaint concerning 
the Heath Company, which you saw fit to 
print in issue 56, drew two responses. My 
first response came from a member of the 
Heath User’s Group. Unfortunately, it 
caught us as we were relocating from 
Massachusetts to Colorado and was lost 
before 1 had a chance to answer it. The 
writer informed me that Heath, out of 
the goodness of their collective heart, re¬ 
fused to sell me the brackets because 
mounting a drive in the terminal enclo¬ 
sure is not such a good idea anyway and 
is doomed to cause problems. The writer 
chose to ignore Heath’s eagerness to sell 
the brackets — complete with a $230- 
Siemens drive — to anyone willing to part 
with $450. 

The second response appeared in 
your issue 60. Mr. Shoemaker, who seems 
to be a real Heath fan, states that the 
required parts are stocked in “large num¬ 
bers” by the Alexandria Heath Centre. A 
call to the folks in Alexandria revealed 
that these parts are not in stock. 
However, Mr. Shoemaker included in his 
correspondence a list of the part num¬ 
bers (Part 206-1331, a Mu-metal shield, 
is now 206-1346), and for this I am very 
grateful. A call to Heath produced an 
actual order, and for $31.80 I now have 
a drive mounted in my H-19 terminal. 
One last note: Heath will not accept a 
charge order for parts, although they just 
LOVE to charge for instruments. To sum¬ 
marize: my feeling about Heath has not 
changed. Anyone who plans to buy any¬ 
thing from that company, should know 
what after sale service to expect. 

Sincerely yours, 

R. A. Hoffman 

1341 Ginny Lane 

Colorado Springs, CO 90818 




Dr. Dobb’s Journal, Number 66, April 1982 


7 

151 













DR. DOBB’S CLINIC 


by D. E. Cortesi, Resident Intern 


The Continuous H8 

In the November Clinic (DDJ #61) 
we noted a complaint from Terence Mills. 
He’d found that PAM, the panel monitor 
of his H8 took a timer interrupt every 
2ms. While processing the interrupt, PAM 
checked the interrupted instruction; if it 
appeared to be a HLT, PAM would return 
to console mode under the assumption 
that the program had quit. Trouble was, 
Terrence said, there are instruction se¬ 
quences that look like a HLT to PAM but 
aren’t. 

Two readers, Edgar Howell of Simi, 
CA, and David Shaw of Elmhurst, IL, 
sent clarifications. Shaw’s gives the most 
detail: 

“Actually, this is a feature that can 
be quite useful when entering and debug¬ 
ging programs from the front panel. As 
described on page 16 of the PAM-8 refer¬ 
ence guide, a halt instruction may be in¬ 
serted where a breakpoint is desired. 
When the program gets to the breakpoint, 
control is returned to the PAM-8 moni¬ 
tor. Pressing the GO key will continue 
program execution. 

“This feature and several others are 
under programmer control by setting and 
clearing bits in the .MFLAG byte. You 
can, for example, stop PAM-8 from up¬ 
dating the front panel display, turn the 
display off altogether, or request clock 
interrupt service. Other control flags al¬ 
low you to turn off the 2ms clock, turn 
on the built-in speaker, and enable single- 
step hardware. All of these features are 
documented in the PAM-8 source listing, 
Appendix A of the reference manual. 


“Setting the UO.HLT bit will inform 

PAM-8 that breakpoints are not wanted: 

„MFLAG EQU 

400 i 0A 

LJG.HLj EQU 

1OOOGoouR 

LB A 

.. MFLAG 

OR I 

UO.HLT 

ST A 

,MFLAG 


HDOS turns on UO.HLT when you boot 
up, so you don’t have to do it yourself 
unless you are programming through 
the front panel; I assume that Heath 
CP/M does the same thing.” 

ED Finds Them All 

Many people buy a full-screen editor 
with their CP/M system and so never 
really learn the ED editor that comes 
with it. ED isn’t a very elaborate editor — 
we wouldn’t touch it for writing purposes 


— but it has its uses as a utility. One of its 
charms is its Macro command, which 
allows you to execute any sequence of 
commands repeatedly. 

W. G. Hutchison, Jr., of Exton, PA, 
sent us a “sponse” in this regard. “Here is 
a way to generate special purpose indexes 
of programs using ED. Use the following 
command string: 

B#MF strinq 'ZOLlTlL 

This can be used to list all function defi¬ 
nitions in a C BASIC program (string is 
‘DEF’), to list all function calls (string is 
‘FN’), to list all uses of integer variables 
(string is '%’), etc.” 

If you haven’t explored the use of 
Macro, you’ll enjoy working out what 
Hutchison’s command string does. There 
ought to be a lot of clever things that can 
be done with Macro; what others can you 
find? When driven by a script of com¬ 
mands via SUBMIT and XSUB, ED has 
considerable power as a file-manipulation 
utility. What uses can you find for that 
combination? 

Robotics Help Needed 

Ray Poli of Flint, MI, needs a line on 
information sources. He writes, “Could 
you please help me get started writing 
programs to control a robot I’ve built? 

I can’t seem to find any literature on the 
subject. I have a 64K H8 with CP/M, and 
can use ideas, suggestions, etc.” 

It seems clear that Ray needs general 
background information, and also needs 
contact with other experimenters in ro¬ 
botics. We’ve heard of one source. Ro¬ 
botics Age magazine, a recent press re¬ 
lease tells us, has been bought by a New 
Hampshire firm and will be edited by 
Carl Helmers, once founding editor of 
BYTE. Under the new management, 
“Heavy emphasis is placed on practical 
tutorial information.” The magazine costs 
$15 a year; its address is 174 Concord 
Street, Peterborough, NH 03458. 

That’s the only publication we know 
of, but surely the readers know of more. 
Tell us the books and magazines that 
have good info on robotics, and let us 
know the addresses of the experimenter’s 
organizations. We’ll print a list here. 

An Elliptical Query 

Don Taylor, of Corvallis, OR, has a 
simple question. You’d better hear it in 
his own words, because we haven’t a clue: 

“I am looking for the algebraic 



formula for an arbitrary ellipsoid, rotated 
in all three axes, projected on the X-Y 
plane. In other words, given 



rotate it around the X axis D degrees, 
then the Y axis E degrees, and then the 
Z axis F degrees. Take the resulting el¬ 
lipsoid and find the projection on the 
X-Y plane. 

“I believe the resulting curve is an 
ellipse, but am unable to prove that. I 
have attacked the problem in several 
ways. One method was to use rotation of 
axis substitutions to obtain the general 
formula for the oriented ellipsoid, and 
then consider the formula as a quadratic 
in Z. The projection consists of all points 
that have a single value for Z, and this im¬ 
plies that the discriminant must equal 
zero. 

“The number of terms involved pre¬ 
cludes hand computation, so I wrote a 
small algebra handling program in ALISP 
and ran it on the local Cyber. I got as 
far as finding the a, b, and c for the 
discriminant’s b 2 - 4ac. The supervisor in 
ALISP informed me that I had run 14 
garbage collections, was in control of 80% 
of core, and did not have enough room to 
complete the calculation. The program 
was trying to multiply 25- to 40-term 
polynomials, each with three variables, 
and sines and cosines of three angles. 

“There should be some elegant 
method of finding the formula of the 
solution, but 1 just don’t see it. It’s been 
suggested that I solve the problem in 
spherical coordinates and translate the 
solution back to cartesian, but the initial 
work didn’t seem to be much better. Use 
of matrices and performing a change of 
basis was suggested, but the equations are 
not linear. Locating four extreme points 
and solving for the elipse that goes 
through all the points might be a possi¬ 
bility. 1 had some luck with this method 
until I found I was not solving what I 
thought I was. 

“Now that I have blown you away 
with what I have tried to do, HELP!” 

Touch-Tone ASCII 

Several readers responded to our 
query for a simple way to encode alpha¬ 
betic input through a Touch-Tone key¬ 
pad (“Touch-Tone,” by the way, is a Bell 
trademark). Everyone observed that most 


Dr. Dobb’s Journal, Number 66, April 1982 
152 


9 


of the alphabet is already on the keypad, 
three letters per key. There are three 
problems; how to shift from numbers to 
letters, how to signal which of the three 
possible letters is meant by a particular 
key-press, and what to do about Q, Z, 
and the blank. 

The usual solution to the third prob¬ 
lem is to pretend that Q, Z and blank are 
printed on either the zero- or the one- 
key, which don’t have any letters. Then 
those letters can be handled in the same 
way as the others. 

Andrew Sackheim proposes that “to 
enter letters, you first enter **’, then the 
number the letter appears on, then the 
digit corresponding to the relative posi¬ 
tion of the letter (1, 2, or 3), and finally 
an optional *#’. The word ‘help’ would 
be entered as ‘*42*32*53*71#.’” 

Bruce Komusin of Huntington, NY, 
proposes a variation on that theme. He 
notes that the keypad has a left special 
key, “*”, and a right special key, “#”. 
He’d use these to mean “left letter” and 
“right letter” respectively. He also sug¬ 
gested that pressing “*#” in succession 
should mean “middle letter,” but that is 
redundant. If a letter is neither left nor 
right, it has to be middle. So, presuming 
the system knows you intend alphabetic 
input, the modified Komusin code would 
give the world “help” as “435#7*.” If 
you have to tell the system which kind of 
input is coming, the sequence “##” 
could be used for “numeric shift,” and 
“**” could be used for “alpha shift.” 
This code yields the shortest key se¬ 
quences of any general scheme proposed. 

W. Hutchison notes that in certain 
cases, no special coding is needed for the 
letters. When the system expects a re¬ 
sponse chosen from a limited vocabulary 
of keywords, the user can press the ap¬ 
propriate letters and the system can 
figure out which keyword is meant. All 
that is needed is to choose the vocabu¬ 
lary of keywords so that there are no ab- 
biguities. For instance, you couldn’t have 
both “cow” and “boy” in the list because 
they would both be spelled “269.” 

Dan Dugan of San Francisco, CA, 
brought up an important point. “The Bell 
System special features offered by newer 
exchanges (call-waiting, call-forwarding, 
etc.) have established the “#” key as hav¬ 
ing an ENTER or RETURN function.” If 
you want to be compatible with the Bell 
conventions, you should reserve the “#” 
to be a delimiter or terminator. How im¬ 
portant is that? 


Dan Samuel of Palo Alto, CA, sug¬ 
gested a variation on the same code pro¬ 
posed by Sackheim. But he had other 
news, too. We’d asked for a design for a 
complete Touch-Tone interface for a 
small computer. Steve Ciarca addressed 
the design basics in an excellent article 
in the December, 1981 issue of BYTE, 
but Samuel’s company, Digital Pathways 
(1060 E. Meadow Circle, Palo Alto, CA 
94303), have gone further. They make 
the SLC II, a unit that “attaches to the 
phone line and provides full 16-tone 
encoding and decoding as well as synthe¬ 
sized speech output over the phone.” 
It can be driven as a peripheral via an RS- 
232 interface, but it is a computer itself, 
having a 6502 CPU, 80KB of banked 
storage, BASIC, a clock and calendar, and 
four serial ports (but no disk interface). 
So the “world’s smartest phone-answering 
machine” that we asked for already 
exists. 

Pass The Hat 

We have our reply mechansim in 
place now; we’U start an acknowledge¬ 
ment your way within two weeks of re¬ 
ceiving your letter. You know, the let¬ 
ter you were just about to write, with a 
question, a discovery, an algorithm, or a 
problem. 


10 


Dr. Dobb’s Journal, Number 66, April 1 982 

153 




OF INTEREST 


by D. E. Cortesi 

Tandy’s New Machines 

In January, Radio Shack announced 
three new products, each a highly signifi¬ 
cant machine in its field. Their 16-bit 
desktop machine, video terminal, and en¬ 
hanced pocket computer will each make 
waves in the industry. Taken together, 
they show that Tandy Corp. is a comput¬ 
er company that doesn’t have to apolo¬ 
gize to anyone. 

The new Model 16 is most exciting. 
It is a desktop machine similar in appear¬ 
ance to the TRS-80 Model II. Where the 
Model II had a single 8-inch diskette 
drive, the Model 16 fits a pair of the new, 
slim, double-sided drives, giving it 2.5MB 
of disk capacity within its case. 

Inside, the Model 16 is to have 
128KB of RAM (expandable to 512KB) 
and a pair of CPU’s: a Z80 and an 
MC68000. The early press releases are not 
at all clear on the relation between these 
two processors. The Z80, it is said, “re¬ 
lieves the MC68000 of time-consuming 
housekeeping chores,” but it can’t be 
limited to that because the presence of 
the Z80 allows “software compatibility 
with existing Model II software.” We 
wonder how they accomplish the switch¬ 
over from running Model II software on 
the Z80 to running new software on the 
MC68000. Regardless, the Model 16 is 
said to be powerful enough that it can 
support two additional terminals. “This 
lets three users access programs and in¬ 
formation at the same time, with no per¬ 
ceptible loss of performance” — an inter¬ 
esting claim. 

The Model 16 is to sell for $5800 
with two disk drives and 128KB. This 
puts it one up on the much-touted 
Fortune 32:16, which has only a single 
5-inch drive at that price. The MC68000 
CPU, big drives, multi-user ability, and 
compatibility with existing programs all 
work to put the machine ahead of the 
IBM Personal Computer, and at a price 
that isn’t much greater. A $1500 upgrade 
kit will be available to add the 16-bit 
CPU, 128KB of storage, and multi-user 
TRSDOS to existing Model II machines. 

Radio Shack also announced the 
DT-1, a 24-line by 80-column video 
terminal, with a price tag of $700. It 
will emulate any of four popular termi¬ 
nals and supports reverse video, blinking, 
underline, and low-intensity display 
fields - but not graphics. It has a stan¬ 
dard typewriter keyboard and both serial 
and parallel interfaces. Its configuration 


12 

154 


parameters are set from the keyboard and 
are remembered over power-down. 

As if those weren’t enough, an en¬ 
hanced version of the Pocket Computer 
was announced as well. The PC-2 has an 
extended version of BASIC in a 16K 
ROM, its keyboard has been rearranged 
into typewriter layout, and its display 
now supports lowercase letters and graph¬ 
ics. Its initial 2600 bytes of program¬ 
mable storage can be upgraded to 16KB 
in 4K increments. A four-color printer (!), 
two-drive cassette interface, and RS-232 
port are promised. The PC-2 brings us 
spookily close to the kind of pocket 
secretary that is a standard prop in con¬ 
temporary science fiction. All that’s lack¬ 
ing is a multi-line display and pocketable 
mass storage. Can they be far off? (Read¬ 
er Service No. 301) 


A Significant Decision 

Much has been written about the at¬ 
tempts by Atari and others to lock up the 
rights to computer games. These disputes 
are not over the implementation of a 
game - but over the rights to the game’s 
situation and its appearance on the 
screen. Atari, for instance, has moved 
against some of the entrepreneurs selling 
clones of Pac Man for different personal 
computers, despite the fact that the pro¬ 
grams involved are the work of the sellers. 

Now the U.S. Court of Appeals for 
the Second Circuit has made a significant 
ruling in this area. The case involved the 
popular “Scramble” arcade game, which 
was licensed to Stern Electronics of 
Chicago. A company called Omni Video 
Games brought out a very similar game, 
using their own software. Stem asked for 
an injunction, which was granted and 
which has now been upheld by the 
Appeals court. The way “Scramble” was 
registered for copyright is significant. 
Rather than registering the software that 
produced the game, a video tape of the 
game was registered as an audiovisual 
work. Omni Video Games protested that, 
since no two plays of the game will pro¬ 
duce the same sequence of images, there 
was no single “work” to be copyrighted. 
The court disagreed, pointing out that the 
game’s elements — the various spacecraft, 
the missiles, the terrain, the explosions, 
the sound — are constant, and therefore 
the whole comprises a “work” that can 
be copyrighted, even though the sequence 
of its presentation varies with the player’s 
skill and luck. 


This decision will add strength to 
Atari’s attempts to control the marketing 
of Pac Man and other games. If you’ve 
had the notion to program a version of 
some arcade game for your Apple or 
Atari, perhaps you should think again. 
And if you come up with an original 
game idea, don’t just register a program 
listing for copyright. Get a video tape re¬ 
corder and register a game session com¬ 
plete as an audiovisual work. If this de¬ 
cision holds up, you might then own a 
game for any computer, not just your 
specific implementation of it. 

Information on Tap 

In our opinion, the greatest social 
impact of personal computers will come 
from the networking they allow — the 
connection of poeple to people and of 
people to information sources. There are 
already a lot of public databases to be 
tapped, enough of them that the tire¬ 
less counters-and-sorters at Datapro 
have found it worthwhile to publish a 
new Directory of On-Line Services. They 
claim it’s “the most comprehensive refer¬ 
ence of its kind, with over 100 on-line 
services and 500 databases.” As is usual 
with Datapro directories the information 
is categorized and cross-indexed to a fare- 
thee-well, and it carries their customary, 
stiff price tag: $390 for two fat binders 
and a year’s monthly supplements. 
There’s a publishing opportunity there for 
a competitor. (Reader Service No. 311) 

One of the largest on-line systems is 
Dialog. They are about to add two data¬ 
bases of interest to users of personal com¬ 
puters. File 233 is to contain a microcom¬ 
puter magazine index. It will have 6,000 
entries initially; 1,200 more will be added 
each quarter. File 232 will contain a 
microcomputer software directory; its 
initial 5,000 entries are to be updated 
monthly. (Reader Service No. 321) 

One of the oldest on-line systems is 
the tickertape service provided by the 
New York Stock Exchange. Its data are 
available through other systems, but with 
a 15-minute delay. Now, Wall Street 
Software has prepared a $500 hardware 
and software package with which an 
Apple II can connect directly to the 
NYSE’s “A” tape. The hardware is a com¬ 
munications card. The software scrolls 
the ticker across the top of the screen, 
and it extracts quotes for the stocks you 
are interested in for display in a fixed 
area below. (Reader Service No. 331) 


Dr. Dobb’s Journal, Number 66, April 1982 



More Info, Asked and Given 

Thinking of starting your own busi¬ 
ness? Of course you are; we all plan to, 
someday. Wildfire Publishing have pre¬ 
pared a two-volume work under the title 
Your Fortune in the Microcomputer Busi¬ 
ness which, they claim, is a complete 
manual for starting and managing your 
own business. Each volume costs $20. 
Volume I tells how to survey the market, 
select a product, get capital, and start 
the business. Volume II “deals with the 
problems and decisions a person faces 
when their business really takes off.” A 
canny person might postpone buying that 
one until they’re sure they’ll need it. 
(Reader Service No. 341) 

Sapana Micro Software is poised to 
leap upon the IBM bandwagon; they are 
collecting vendor information with a view 
to publication of a catalog of hardware and 
software for the IBM PC. Vendor entries 
are solicited. (Reader Service No. 351) 

Users of the Nevada COBOL compil¬ 
er may be interested in knowing that a 
Nevada COBOL User Group is now being 
formed. No dues are mentioned. (Reader 
Service No. 361) 

Software, Sophisticated . . . 

Here are three language items that 
caught our notice this month. Curry As¬ 
sociates have prepared a set of FORTH 
programming aids. One is a decompiler 
(dis-forth-er?) that will convert compiled 
FORTH words into structured source 
code, for documentation or revision. An¬ 
other is a command to find the words 
called by a specific word to any level. It 
can be used, they say, to extract the set 
of words needed to compile a program of 
minimal size, or to examine the words 
called within a loop, the better to opti¬ 
mize the code. (Reader Service No. 371) 

Last month we mentioned a struc¬ 
tured pre-processor for BASIC. It’s clear¬ 
ly an idea whose time has come, and now 
we’ve heard of another one. This one is 
BLX from Quelo. The programmer writes 
using a “rich assortment of structured 
programming statements with full nest¬ 
ing,” and using names for subroutines. 
The pre-processor rewrites the pro¬ 
gram into a form suitable for either 
CBASIC or M BASIC. The pre-processor 
costs $65; a utility to convert existing 
programs into BLX-BASIC is available for 
another $30. (Reader Service No. 381) 

The ADA language is big in certain 
circles, and RR Software moves in them. 


Dr. Dobb’s Journal, Number 66, April 1982 


They publish a compiler called JANUS, 
which processes “an ADA subset.” 
JANUS is available in 8080 form for 
CP/M, and in 8086 form for CP/M-86 
and for IBM DOS. It costs $480. We 
think this product is “of interest,” but 
we’d like to remind you that in one 
sense there is no such thing as a subset of 
ADA. The language spec includes no pro¬ 
vision for subset implementations. Un¬ 
official subsets are inevitable given the 
complexity of the language, but strictly 
speaking, no subset is really ADA. A sub¬ 
set can be at best “ADA-like,” and 
couldn’t be acceptable to the Department 
of Defense — if you care. (Reader Service 
No. 391) 

. . . And Not. 

Several nice little programs turned up 
this month. Among them was Donald 
Fielding’s WILDCAT. It’s a $42 disk cata¬ 
log system for the TRS-80 Model I, with 
versions for TRSDOS and three levels of 
NEWDOS. The cataloged information in¬ 
cludes not only the file’s name and vital 
statistics, but the first line of its contents 
as well, providing a sort of file-abstract 
function. (Reader Service No. 401) 

Another is the 3D Drawing Board for 
the Color Computer, from Computer- 
ware. It aids the drawing, scaling, and ro¬ 
tating of 3-D objects on the screen, and 
allows the drawing to be saved on tape or 
disk; it costs $25 on cassette. (Reader 
Service No. 411) 

A third is L1NE#DATA, for the 
TRS-80 Model I with a disk, from En¬ 
joy. This $10 program converts data into 
DATA statements. It will read the screen 
memory, or take strings from cassette or 
disk, convert what it finds into DATA 
statements, and save them on disk for later 
merging into a program. En-Joy also sell 
a clever TRS-80 screen template for $4. 
The clear plastic template is sized to fit 
exactly the layout of character positions 
on the screen. You build a picture on the 
screen, lay the template over it, and 
read the position or POKE indexes direct¬ 
ly from it. (Reader Service No. 421) 


Harder Ware 

The “Grafyx Solution” from Micro- 
Labs is a $300 hardware mod for the 
TRS-80 Model III, with supporting soft¬ 
ware. The hardware gives the screen a 
resolution of 512 by 192 pixels (which 
dimension is up and which is sideways?). 


The software provides 80-column charac¬ 
ters and the ability to save and load 
graphics screens or copy them to a print¬ 
er. The hardware consists of an add-on 
circuit board with 12K bytes of graphics 
storage. Installation, in the words of the 
release, “is as easy as clipping on some 
micro-clips, cutting one trace, and re¬ 
moving two ICs from sockets.” That 
easy? (Reader Service No. 431) 

Users of the Osborne 1 are no longer 
constrained to buy Osborne’s video moni¬ 
tor if they want to relax their squint. 
Best Computer Stores have prepared an 
adapter that will connect the machine to 
any standard composite video monitor. 
It’s a $60 flat box that plugs into the 
front panel; they say you can close the 
machine’s case while leaving the adapter 
plugged in. (Reader Service No. 441) 

And we note that DEC have 
squeezed the “base level” instruction set 
of the PDP-11 into a single, 40-pin chip. 
The Micro/T-11, as they call it, should 
be available in sample quantities now. It 
will cost $75 per chip when ordered in 
quantity. Any bets on how soon we’ll see 
one on an S-100 board? *»j 


13 

155 




Part II 

8080/8086 Cross Assembler 


T hank you, gentle readers, for your interest in the Z-88 
Project, and specifically the XASM-86 Cross-Assembler 
(DDJ #56). Marlin Ouverson has relayed your enthusi¬ 
asm, as have those of you who wrote me (but, alas, were not 
answered). I can only say that in most cases requests for 
source or object code on variously formatted disks will not be 
honored, because I have neither the time, the inclination, nor 
the appropriate disk drives to do so. 

In this installment I will discuss some of the features of 
XASM-86, as well as share some exciting news about a 
superior arithmetic processing chip, the 8086 Numeric Data 
Processor by Intel. 

XASM-86 is a development language tailored to my 
needs, and based on my past experience. This includes a range 
of computing equipment from Hewlett-Packard and Texas 
Instrument calculators to IBM, DEC and Burroughs minis and 
maxis. Languages include COBOL, FORTRAN, RPG II, 
BASIC, PASCAL, various assemblers and programmable calcu¬ 
lator “lingo’s” and, recently, database languages and specialty 
languages, such as NUFORM by the A.S. Thomas company. 

All of this is mentioned to keep me from being branded as 
“crazy” by various persons in the computing community. I 
enjoy using these languages, and do not fanatically defend or 
condemn any of them. I do have some strong opinions on the 
use of programming languages, which have helped to guide the 
development of XASM-86. These opinions are: 

Structured programs are the result of structured program¬ 
mers. It is possible to write structured code in any language, as 
well as unstructured code. The difference lies in the training 
and motivation of the programmer. (If you don’t believe me, 
and think that Pascal always produces structured code, 
examine the APL interpreter published in The BYTE Book of 
Pascal.) 

Some languages have better tools to use to build struc¬ 
tured code. While you can open a bottle of wine with an axe, 
it is much easier to use a corkscrew. In a similar fashion, those 
languages with clearly defined programming structures 
(sequence; if-then-else; do-while loop; and case-of-condition) 
allow the programmer to spend time concisely implementing 
his or her algorithm instead of wrestling with a language’s 
deficiencies. Other tools that I feel are essential are: 

• 15-character or greater variable names 
• data declaration and typing 

• easily applied “pretty-printing,” such as blank lines 
between modules, and moderate indentation. 

A language should help the user write, debug, maintain, 
and document the program. These goals tend to work against 
each other. COBOL can be made self-documenting, but it then 
becomes a horrendous task to write and debug the program. 
On the other hand, it is very easy to write and debug a BASIC 
program in the heat of creativity. Six months later, though, 
another programmer may think it extremely difficult to mod¬ 
ify this same program, especially if the documentation is non¬ 
existent! There is no happy medium here, unless it is the one 


by Jonathan Mills 


Jonathan Mills, copyright © 1981 by Programmers Publishing 
Company , Box 2571 Kalamazoo, MI 49003 


practiced by assembly language programmers: write the code, 
and place the explanation next to it. Even this, by the way, 
can be carried to extremes. Examine a listing where every in¬ 
struction is commented. It soon becomes bewildering. 

XASM-86 is my attempt to create a development tool 
that includes the best of those languages in my background, 
avoids the worst, and is easy and pleasant to use. Since I am its 
prime user (along with others I have trained, but who were 
“naive” assembly language programmers) i feit no need to con¬ 
form to any past practices that I detested, nor to cater to the 
inertia present in a large body of users who expected Intel 
standard mnemonics, or six-character labels, or other foolish¬ 
ness. 

XASM-86 is new, and will set its own standards. Two of 
its features I fully expect will be found in other languages in 
the future. The first is the DITTO OPERATOR (”) which was 
discussed in the last article. You will find it in the listings 
accompanying this article; those who have seen XASM-86 in 
operation frankly wonder why it hasn’t been used before. 

The second feature is less obvious (in some cases it is in¬ 
visible!) but is just as useful. It is called SIGNIFICANT TEXT. 
Using this, it is possible to write assembly language programs 
that can be mistaken for Pascal programs, that are as self- 
documenting as COBOL programs, but are easy to key in and 
simple to debug. Some claims, right? Let’s define significant 
text, and then look at a listing using it. 

SIGNIFICANT TEXT Upper-case letters and num¬ 
bers used to define labels, mnemonics, and data; 
certain special characters used as operators and to 
control the assembly process. All other characters, 
such as lower-case letters, blanks, etc., and any sig¬ 
nificant text following the significance switch charac¬ 
ter— in XASM-86 this is a period (.) - will be ig¬ 
nored by the language processor, and dropped from 
the compiled or assembled output. 

Now examine the source and object code shown in Figure 
1. This short routine is purposely made into a very bad exam¬ 
ple of assembly language at its worst. If it were not for the 
header comments, it might have been a day or more before the 
purpose of this routine was discovered. However, there are no 
visually distracting parts of the code that would confuse a pro¬ 
grammer trying to debug this routine. XASM-86 will accept 
this type of code, which is useful at times for quick test 
routines. 

The listings in Figure 2 show the opposite end of the 
input spectrum handled by XASM-86. In Figure 2a we find 
significant text used (somewhat excessively ) to illustrate its 
benefits. First, the source code is very well documented and 
commented. Note the use of operand equates that are 
combined with other, insignificant text to virtually duplicate 
the algorithm as it was written in English. The object code 
(Figure 2b) though, is quite different. It is sparse, having had 
all the insignificant text removed by XASM-86. What remains 
is useful when the routine is debugged, and has nothing in it to 
confuse the eye. Since I am using XASM-86 as the language 
for our commercial development project, some of you will de¬ 
cide that I must be a confirmed masochist. Nothing of the 
sort! XASM-86 is not demanding in its input expectations. 
Listings 3a and 3b show a typical program development to 
test the operation of our 8086 Numeric Data Processor exten- 


16 

156 


Dr. Dobb’s Journal, Number 66, April 1982 



sion to the Z-88 CPU board. Notice that both types of text, bly language instructions that will calculate the sine of a num- 

and several commenting options have been mixed to create a ber to 18-digit precision, and convert the result to a binary- 

self-documenting source. However, the object code is reduced coded decimal number 10 bytes long in a millisecond (sorry 

to the bare-bone fundamentals! This one feature of XASM-86 to be so slow, but our sample only runs at 2 megahertz instead 

allows the unprecedented production of reliable, maintainable of 5 or 8). Actually, a library routine with data checking and 

software that is very large. Currently, our in-house project is scaling might take a little longer, but it is possible to have the 

scheduled for completion in late 1983, and will probably have calculation run concurrently with other portions of the rou- 

over 90 Kbytes of object code ... all written and maintained tine, so I might very well be over-estimating the time, 

in XASM-86 assembly language. This type of arithmetic is on a par with that found on an 

This is as good a time as any to lead off with a discussion IBM 370 in its precision, and is superior to the instructions at 

of the Intel 8087 Numeric Data Processor. Perhaps the best the assembly language level available on any Digital Equipment 

thing to say is that it is incredible ! Imagine writing 11 assem- computer 1 am familiar with, up to and including the VAX 
















series to date. The 8087 breaks the “number-crunching bar¬ 
rier” which formerly limited the microcomputer. What we will 
find on the other side will depend on the ingenuity of its users, 
but I expect a generation of superb low-cost graphics termi¬ 
nals for starters. The IBM personal computer should be able to 
host an 8087, at which time the 6502 machines will no longer 
be the fastest kids on the block. One enterprising individual I 
have come in contact with intends to mate the 8086+8087 
duo to his 68000 add-on board for the Pet and Apple com¬ 
puters. Hmmmm. 

Here at Programmers Publishing Company, we have suc¬ 
cessfully matched the 8087 to our Z-88. This little trick was 
somewhat touchy, since our 8088 was configured for the mini¬ 
mum (or very simple) mode, while the 8087 required that 
the 8088 run in the maximum (or multi-processing bus) mode. 
Although a possible solution was simply to rebuild the Z-88, 
it was not generally well-received. Instead, a circuit was de¬ 
signed that made the maximum mode 8088+8087 combo 
“look like” a single, minimum mode 8088. Voila! After much 
examination of bus loading, ringing, clock speeds, and data 
and control signal skew, we managed to build a daughter board 
for the Z-88. This board connects to the Z-88 via a 40-pin 
DIP jumper, which may not be elegant, but is at least efficient 
(ever tried to plug 40 wires together one by one?). 

In any event, the 8087 sample has proved remarkably re¬ 
liable. It has no opcodes that we have yet been able to observe 
that don’t work; some of them work even better than Intel in¬ 
tended! For example, the partial tangent (FPTAN) instruction 
is valid on our sample from greater than zero radians to 1.35 
radians, instead of only pi/4 radians as specified. Since we are 
not in the business of providing quality assurance for Intel, 
only those instructions we use are checked, but those we 
checked, worked. For a complete discussion of the 8087, the 
Intel Numerics Supplement to the 8086 Family User’s Manual 
is essential. Application Note AP-113, “Getting Started with 
the Numeric Data Processor,” is very helpful. Both may be 
ordered from Intel’s Literature Department, 3065 Bowers 
Avenue, SV 3-3, Santa Clara, CA 95051. The supplement costs 
$2.00, the application note I have is not priced, but probably 
won’t cost more than $2.00 either. 

I hope you have found this material interesting and stimu¬ 
lating. XASM-86 and the Z-88 have given us a very low-cost 
development system for sophisticated 16-bit systems and soft¬ 
ware. Puh-leeze direct all correspondence to Dr. Dobb’s\ 
Our next project is underway, and there is not a chance of 
your letter being answered if you write here. I promise to pro¬ 
vide XASM-86 and utilities for “the people,” but someone 
else must pass it around. When you do get your hands on 
XASM-86, remember that the primary reason for its being was 
to have a development tool that would allow users to write 
structured, documented, maintainable code . . . that would 
work! »»j 

Late note: The Editor and I agree that keying in 1 7 kilo¬ 
bytes of object code in hex, or its equivalent of 250 pages of 
source code is patently ridiculous. Machine-readable code is 
being made available through my arrangements with RD Soft¬ 
ware, 1290 Monument St., Pacific Palisades, CA 90272. Please 
contact them directly. 

(Listing begins on page 20) 


Dr. Dobb’s Journal, Number 66, April 1982 


19 

159 




o 


i is 

* <r co 

3 uj 

<r £ y 


ii * 


25 OD & ~ 


i *1 


oO©0®0 0 ® o o 
oooooOoOoo 


o o 0 o 
00 ^ o r; 

-H rsi (N 

o O o o 


©®©®0°®®©®©®< 

S £* (N N <n oj ft ft ro 52 m iO i 
®OO®O 0 O0°OO‘ 


| §8 

r - co 

* $ co 

«r £ £j 

5 |£ 

CD h- ►— 

z — 

~ x CD 

5 

3 ro 


motojivU.I'i'OaoNooj 


® © ® ©0©0©0©©©© 
Oo®OOOOOOOOoO 
OOOOOOOOOOOOO 
©00©0o®©®0®0© 


S 5 8 ) 2 « S 2 8 2 & a £ 2 


QC Z 
- UJ — 

•• oc y- o w- 

•• 11 LU z d — -UJV- 

-SSzoz zz iS 

assays BiueS-£ 

* loluj 1 - -OOZliltlAl 

^£ s .u]S5S8« s .^5S 

j«h 1 II y - - 

8tt38&iS£§»§£ 

a.|j)^«l^ooSuJiflOa 


* * * * * * * 


Dr. Dobb’s Journal, Number 66, April 1982 











h- h- 'X 2 
I Xh S 
O UJ O' g 

UJ UJ UJ I 

£ $ 4 S 

1 X 1 co a: 3 : 


ssag&i& 


a Ci i k 

Sbg S 

H 5 Lt K 
Q. U. CL <S) 


~ W «■? 53 

-»wJ?: 


>©®O®®®O®C?£ oOo P o “© O ® 0o £ 


* * UJ 

o°o' =, oCo ,=> o'^oOo c 'o l= o 0 o'^’o 

§Sgg§§§ggSIsS 81 SSiSSli 


cp O* 1 cn 

lily 


*a§i; 


ooooooooo 
o©o©o©o©® 
O o o © O © O © © 
O o o © O © © © O 


> aj al & 8 a! o) & 


o ^ o ° o ©©©©©© 

■ #^ 3?S:3 s s s s g * 

© © © © _ — — -* 


. ® O © O ° O 

; « ^ m ^ ip 3 


8 2 3 2 X 

ft 

2 K 8 

£ ass 8 

o 

o 

& 5 ft £ 


£ 52 t 

gc O i O 

C Q_ *— *-• 

S - 5 - 4 a < 

2 £ _l £ S 2 £ 

I> X _J ~ </» QC ►-. 

Ss^iTcl^'I’^z^; 


z ■o 

UJ O yfi 

lD € * 

* 

+* -C «- 


5 ^ 

5 § 


Dr. Dobb’s Journal, Number 66, April 1982 


21 

161 










3 

.5 

s ?,= 

J=> * fc 

co * 

00 

3 


s 

J 

2 a 


*£ : 


l l 


UJ X 5f 


£ 

UJ 

OL 


=J 

3a 

UL w 

a =f*i£ 


^ _j 



vO 

o 

oo 

CO 

a 

c 

o 

(A 

C 

’So 

£ 


x 

a> 


T3 

<L> 

3 

# g 

-w 

C 

O 

o 

00 

c 


o 

s 

E 

a> 

w 

« 

w 

<0 

o 


(0 

00 

o 

00 

3 

00 

o 

00 


J S: 


O) 

¥ 


t => ~ ~ « 

,, £ _ _ — ao 



$ „ 

?s & s g, « & Hi 

zo. 5 £ a! ^ £ 

~ z J(j<3 ~R 

i 

« SO 

si 

ii 


ao oo 

iS 


H 

& 

_j 

o o O o o 

^ ® ^ o- 
~ <N (N 


£ 

~ r- 
cd ru 


-O 
o 
3 

•S 

■*•* 

3 
O 
o 

00 

8 

'3 ° 




IllllllllillllllllUl 


8 I 


* o o 0 
-r^n- 


« 0 ?o®o e o< 

Ss$??s?«Kl 


X 
LU 

°St«?°I^S2S° s ?S5nSSS 0o =o»ooos 

“3SSSS2SCR! k||C SnIr 


®N |O 

!*Sfc 

00 K) u. 

»(N t 

Sgg 

o o o 


u. 

s> 


J Z 

■ fc 5 * 

Vr 

t * • 


ii 


* 

?«• 

ii 


© Z 

•- UJ 

ii 


z 

£ 


2 si 
¥ ~ 
- «» 


■ - > 

! a * 

I* 


: n 

ii 


^ z 


2 c 

S5 


i k x 

~ 2 St! 


Mi 

S- 


o 


X 

I 


3 

z 


JO 

ill 

fe 1 2 

£ UJ 
• * •-» 


IT) 

O 

u. ao 

U. UJ 

•X* .1 

t? w 


:8 

c -I 

£2 

i. 

^ CD 

* Sl 


O o o 
O O o 

Q? vJD rv 


5 Q 00 00 

00 00 UJ Ui 


8 


■ 00 
■ UI 


O O o O O o 


I 

? 


ao •—• 

*■* UJ 
Cl ►- E 
a. z • 

2£t 

! 5 § 

i cn u 

* W e 

?o" 

*5$ 

tSe- 

* %*l 
§$55 

-i <3 o 


z 

I 


CO 3 

K I 


!8 

C -I 

* 

£ 2 

U 

£ 00 
3 Sl 


9? 5 

© C4 

8 8 
o o 


a 

S 

5. 


o c 


- •- z '• 
I - Ixl I 

I?5i 

o o ui 3 
o y (0 

I T 

7 <X X 



<T 

s 


S3 

o ® 

<¥ * 
V 8 

Z © 


3 VC 

O UJ 
\fi O' 
88 


?! o c 


22 

162 


Dr. Dobb’s Journal, Number 66, April 1982 






iges 

— u CO —■ 
i ~ o c» 


at *- 

LU aJ Qt 

*- 5 l —‘ 

z '7> a: oj 


2^ 8 
z eft W 
►- uj tt. >- 
O Ct C D 
Cl | <0 ~ 
i a ” c 


i © •- o a a £ Ci ^_i «; s- o 

~ ^ ^ O r ^ ^ ^ 2 ^ ^ ~ ^ Z S I O ' ^ 

o w I o « j u yi I c m 2 o col m y o 

S £a{2£^s £sS28:£S ^ s! s & 5 S 


0, 2 5 ¥ 

? i* 1 

i k *, ^ t 

s 

a Isas 
S 8 S ‘i 5 a , 


QQ CD -> l 

i6i£s?5 *i i 


i£e$g Slifesi iiiSsi gslit! 


Issgic £ 


'-0 0 0^o°0' 

!S££*So$£s; 


O o O o o ° o 

*£* 2 *5° 


® ® e o “= < 
-N|2 ?£■ 
O © ® C O < 
N IN IN N | 


o2o2op°Oo UJ 0 O 

fSjfO^.lTl^N.cO'T’O 5 fi 

— ~ ~ — <NJ i in n 0^ 

(\j CM f j CM <\j <N (\j (N (vj ^ <\| ,-j CM 


O 0 0o'= - O ,=, 0 0 o00'=>< 

— t IP ^i N a 'T' ^ ^ IN ^2 ' 

(N N CJ |Nj N N N N ^ fO M K) >0 f 

CM ,'4 (N ^ (N rj N N CN N (N N ^ ( 


l«ro«» 
i< N (N N (N 


o o O 0 o 0 

~ <M >0 «• I/O V0 

j! ^ TT 

CM f\< (N (M CM <\j 


u '. < u y '-> 'N ' 

tstsss a 8' 


> UJ CM «■ \f> 

; fa 8 $ 8 

> o o O o 


O' CD Q fO in 

8 812$ £ 

O o o o o O 


cm rs. o rs. o 

S&alliS <3 

isisil g 

O o o O o O o 


e . ° * 

K - C Jt 

55 *22 

£ - § - o 

K £ 8 O £ 

■4 c *sia 

BJ o 3 „ '•= 

rs: ss 
ii £ ^5 

| a o gc jjc o 

i ^; 

51 E5r: 


J co 

^§2 

^ ^ 

= ~* 
?$£ 5 


o u W 

a. * -* 
o K l — TD 
*. ~< K *. 

* o j n 

N M s © 

Q| 0) ~ L 

O QC i UJ a- 

“ S V £ J £ 

Si*; ?£ 

£•25* : s 

O a >— K oh- o 
a: w § 2 a § ? 

S £ u , =1 g 2 2 

i • a s s a - 

g*ta.uj<r» = 
at? ct — i. 
- oo ® aj 3 3 
w> k- 

§2 82 ?g tS 


Dr. Dobb’s Journal, Number 66, April 1982 


23 

163 














Small-C DISKDOC 

A Repair and Maintenance Utility 


D iskdoc is a utility which, like its 
name implies, is intended for re¬ 
pair and maintenance of diskettes 
and other random access mass storage 
media. Tasks accomplished include: 

• Making backups (also in a single 
drive system). 

• Verifying data integrity. 

• Restoring previously deleted files 
(by manual patching). 

• Repairing faulty sectors. 

• Debugging disk driver routines 
and controller hardware. 

• Debugging file systems. 

Diskdoc has been in frequent use for 
about two years now (including a one- 
year assembly language childhood), and 
has proved a valuable companion when 
exploring the oh-so-vulnerable world of 
diskettes. 

The version shown here runs under 
CP/M, but adapting to other operating 
systems will hopefully not be found too 
difficult a task to accomplish. As ex¬ 
plained in the listing, the program is writ¬ 
ten to be compiled by the Ron Cain 
Small-C compiler. Small-C is smaller than 
standard C, and connoisseurs of the C 
language will find some of the construc¬ 
tions used quite primitive. If you prepare 
the program for a richer dialect of C, you 
might consider rewriting parts of the pro¬ 
gram. Except for efficiency, perhaps, 
there is little reason to take the bother 
since Small-C is a true subset of C. 

Talking To Diskdoc 

Diskdoc always tries to give self- 
explanatory prompts. The default value 
can usuallly be displayed by typing <cr> 
once. If you should enter an inappropri¬ 
ate character, Diskdoc simply refuses to 
echo it. Entries may be corrected by 
using the backspace key. A final <cr> 
will, as usual, end the input line. 

The Command Level 

Starting up, Diskdoc will enter the 
command level, requesting a single-letter 
command: 

a Adapt to terminal type. You will 
be asked to enter the character that will 


by Egil Kvaleberg 


Egil Kvaleberg, Studpost 111, N-7034 
Trondheim-NTH, Norway. 


move the cursor home. An excape se¬ 
quence is acceptable. This is all that is 
required to adapt Diskdoc to virtually 
any video terminal. It is assumed that the 
width of the screen is 80 characters. 

b Backup entire diskette, on a 
sector-by-sector basis. You will be asked 
to enter the source and destination drive 
names (a-h). It is crucial to double check 
the direction of data flow. The same drive 
might be assigned as both source and des¬ 
tination, in which case Diskdoc will re¬ 
quest a diskette change whenever neces¬ 
sary during the copy process. If an error 
is detected in the source diskette, 
Diskdoc will ask whether the sector read 
operation should be retried, the error ig¬ 
nored, or the backup aborted. It is recom¬ 
mended to retry a few times before de¬ 
claring a sector unrecoverable, thereby 
filtering out intermittently occuring er¬ 
rors. If desired, backup can be aborted 
by typing any character. 

c Compare the contents of two 
diskettes. Every discrepancy will be re¬ 
ported. Abort by typing any character. 

e Exit. You will be prompted to 
insert a system diskette before leaving. 

p Patch. Look at and optionally 
patch selected sectors. For patch subcom¬ 
mands, see below. 

s Scan diskette by reading every 
sector. The test will quickly locate any 
sector that doesn’t give a proper CRC. 
The test may be interrupted by typing 
any character. 

t Test diskette. A test pattern will 
be written, and the entire diskette will 
then be read back and compared. The 
write operation may be omitted. The 
command provides useful verification of 
disk controller hardware and software 
operation. 

z Zero diskette. The specified num¬ 
ber of tracks will be erased by filling the 
EBCDIC character “V” (0e5h). 


Patch Commands 

<sp> Move the cursor to the next 
byte. 

<bs> Move the cursor to the pre¬ 
vious byte. 

<cr> Move the cursor down, i.e., 
16 bytes forward. 

<hex> To patch, enter the new 
hex byte directly. After having entered 
the first digit, a <bs> will “undo” it. 
After having entered the second, the cur¬ 


sor will move to the next byte. 

’ To enter an ASCII character, type 
a single quote followed by the desired 
character. 

1 Read the logically following sec¬ 
tor. The command is useful where a map¬ 
ping between physical and logical sectors 
exists, such as in standard CP/M single¬ 
density diskettes. 

n Read the next sequential sector. 
The next track is accessed when the end 
of the current one is reached, 
q Quit patch mode, 
r Re-read. Read the current sector 
once again. 

s Shift the rest of the sector one 
bit-position to the right. The command is 
useful when attempting to repair sectors 
where the disk controller has lost a few 
bits here and there. 

t Select a new track and/or sector, 
w Write back the current sector. Re¬ 
member to use this command after having 
made any changes, since no automatic 
write is performed. 


Regarding the CP/M Version 

The CP/M version, as listed, will 
adapt to the physical characteristics of 
the drive being used (track and sector 
counts). This is accomplished by reading 
the disk parameter block returned by the 
BIOS drive select call. CP/M version 2.0 
or better is required. For drives using sec¬ 
tor blocking/deblocking schemes, the sec¬ 
tors that Diskdoc works with will not cor¬ 
respond directly to the physical sectors. 

Adapting to Other 
Operating Systems and/or 
Compilers 

All implementation-dependent func¬ 
tions are contained in the file 
“ddocsys.c”. These functions are all very 
low-level, and thus very non-standard. 
You will have to write these functions 
yourself, since no C runtime library will 
support them. If automatic size adapta¬ 
tion and/or logical to physical sector 
mapping aren’t required, the functions 
seldrv() and lnaext(), respectively can be 
considerably simplified. 

(Listing begins on page 28) 


26 


Dr. Dobb’s Journal, Number 66, April 1982 

165 




Small-C DISKDOC (Text begins on page 26) 


See bug fixes, DDJ Bound Volume page 193. 

/* TAB Si,4 FILE DISKDOC.C 

* 

* diskdoc 

* a utility for diskette maintainance 

* 

* by egil kvaleberg 

* studpost 111 

* n7034 trondheim-nth 

* norway 

* 

* diskdoc is intended for use and distribution 

* among amateur computer users only, please respect this. 

* compile using the Ron Cain small C compiler as distributed 

* by The Code Works, if you use the version of the compiler shown 

* in the Dr. Dobbs Way 1980 issue, you must ensure that the stack 

* is properly initialized, if you use another C compiler, you'll 

* have to revise (parts of) the file ddocsys.c. good luck. 

*/ 

•define VERSION "ver c - 1 nov 81" 

•define WHOMADEIT "by egil kvaleberg" 

/* 

* constants, change as required 
*/ 

•define SECLEN 1?8 /* sector length, 128 or 256 is ok */ 

•define VOID 229 I* character used when zeroing diskette */ 

•define DHOME 26 /* default home character */ 

•define ESC 27 /* lead-in character */ 

•define CR 13 /* various ascii equates */ 

•define LF 10 
•define BS 8 
•define QOT 39 

/* 

* globals 

*/ 

int tracks, /* number of tracks and sectors */ 

sectors,firstsector; 

int dfltrk,dfIsec; /* default values */ 

char dfldrv; 

char secbufCSECLENT; /* buffer for patch */ 

char vfybufCSECLEN]; /* buffer for write verify */ 

int home; /* character to move cursor home */ 

/* 

* begin 
*/ 

mainO 

{ char cmd; 

dfldrv='a'; dfltrk=0; dflsec=0; 
home=DH0ME; 

if (sysok()==0) exitO; 

nl(); putsC'welcome to the world of diskdoc "); 
nlO; puts(VERSION); nl(); puts(WHOMADEIT); 
nl(); nl(); putsC'kindly enter your request"); 
cmd=0; 

while (cmd! =, e') { 
nlO; 

putsC'adapt, backup, compare, exit, patch, scan, test or zero ?"); 

cmd=getcmd("abcepstz",'e'); 

if (cmd= =, a') adapt(); 

else if (cmd== , b') backupO; 

else if (cmd^'c') compareO; 

else if (cmd== , p') patchO; 

else if (cmd=='s') scanO; 

else if (cmd== , t l ) testO; 

else if (cmd= =, z') zeroO; 

else { 

nl(); putsC're-insert the system diskette and type <cr> "); 

if (conlowerO !=CR) cmd=0; 

nl(); 

> 

> 

nl(); putsC'thanks for having consulted diskdoc"); 
exit (); 

> 

/* 

* adapt to terminal 
*/ 

adapt() 

{ nl(); nl(); putsC'type character to move cursor home.."); 

putbyte(home=conin()); / 

if (home==ESC) { 

putsputbyte(home=conin()); 
home=home+128; 

> 

nl(); 

> 


/* 

* backup, copy entire diskette 

*/ 

backupO 

i int trk,ftrk,ltrk; 

char sdrive,ddrive; char *adr; 
if (seltwo(8sdrive,&ddrive, 

"source diskette in drive (a-h) ?", 

"destination diskette in drive (a-h) ?")==0) return; 
if (cont()==0) return; 
trk*-1; 

while (nextt(&trk)) < 
adr=botmem(); 
ft rk=t rk; 

if (baksel(sdri ve,ddrive,"source")==0) return; 
while (1) < 

if (reedtrk(trk,adr)==0) return; 
ltrk=t rk; 

adr=adr+(SECLEN*sectors); 

if ((adr+(SECLEN*sectors))>=topmem()) break; 

if (nextt(8trk)==0) break; 

> 

adr=botmem(); trk=ftrk; 

if (baksel(ddrive,sdrive,“destination")==0) return; 
while (1) { 

if (writetrk(trk,adr)==0) { 

putsC'backup aborted"); nl(); 
return; 

> 

if (trk>=ltrk) break; 
nextt(Rtrk); 

adr=adr+(SECLEN*sectors); 

> 

> 

nl(); putsC'backup finished"); nl(); 

> 

/* 

* compare contents of fwo diskettes 
*/ 

compareO 
< int trk,sec; 

char drivel,drive?; 

char *adr1,*adr2; 

if (seltwo(8drivel,Rdrive?, 

"compare diskette in drive (a-h) ?", 

"to diskette in drive (a-h) ?")==0) return; 
if (cont()==0) return; 
trk=-1; 

while (nextt(Rtrk)) < 
adrl=botmem(); 
adr2=?dr1♦(SECLEN*sectors); 
if (baksel(drivel,drive?,"first")==0) return; 
if (readtrk(trk,adr1)==0) return; 
if (baksel(drive?,drivel,"second")==0) return; 
if (readtrk(trk,adr2)==0) return; 
sec=firstsector-1; 
while (nexts(&sec)) < 

if (easec(adrl,adr2)==0) { 

dfltrk=trk; dflsec=qskew(sec); 

nlO; putsC'compere error in "); putsec(dfltrk,dfIsec); 

> 

adr1=adr1+SECLEN; adr2=adr2+SECLEN; 

> 

> 

nlO; putsC'compare finished"); nlO; 

> 

/* 

* zero diskette contents 
*/ 

zeroO 

{ int trk,trkmax,n,m; 
char *adr; 

nlO; nlO; putsC'zero diskette in drive (a-h) ?"); 
if (getsel()==0) return; 

nlO; putsC'zero how many tracks (0-"); putnum(tracks-1); puts(") ?"); 

trkm?x=getnum(tracks-1,0,tracks-1); 

if (cont()==0) return; 

n=0; adr=botmem(); m=SECLEN*sectors; 

while (n<m) adrCn++3=V0lD; 

trk=0; 

while (trk<trkmax) { 

if (writetrk(trk,botmem())==0) return; 
nextt(&trk); 

} 

nlO; 


/* 

* test a diskette by writing a pattern first, 

* and then reading it back 
*/ 

test() 

{ int trk,sec,n; 
char *adr,*p; 

nlO; nlO; putsC'diskette to test in drive (a-h) ?"); 
if (getsel()==0) return; 


28 

166 


Dr. Dobb’s Journal, Number 66, April 1982 


nl(); putsC'the test will destroy the contents of the diskette"); 
if (cont()==0) return; 

p="**** diskdoc **** test pattern /* length is 22 */ 
n=0; /* fill pattern to compare to */ 

while (n<SECLEN) { 

secbufCn]=p[n831D; 

++n; 

> 

putsC'does diskette already contain test pattern (y-n) ?"); 
if (getcmdC'yn",'o' )=='n') { 

nlO; putsC'writing test pattern..."); 
trk=0; sec=firstsector-1; 
while (next(8trk,8sec)) { 

secbufC03=trk; secbufClD=qskew(sec); 
if (tstbrkO) return 0; 
if (write(trk,qskew(sec),secbuf)==0) { 

nl(); putsC'error writing "); put sec(trk,oskew(sec)); nl(); 
return 0; 

> 

> 

> 

trk=-1; /* read test */ 

nl(); putsC'reading test pattern..."); 
while (nextt(8trk)) { 

if (readtrk(trk,botmem())==0) return; 
sec=firstsector-1; adr=botmem(); 
while (nexts(8sec)) -C 

secbuf CCl]=t rk; secbuf Cl ]=qskew( sec); 
if (eosec(adr,secbuf)==0) < 

dfItrk=trk; dflsec=qskew(sec); 

nl(); puts(“bad test pattern in "); putsecCdfltrk,dfIsec); 

> 

adr=adr+SECLEN; 

> 

> 

nl(); putsC'test completed"); nl(); 

> 

/* 

* scan: check all sectors for crc errors etc. 

*/ 

scanO 

•C int trk,sec; 

nl(); nl(); putsC'scan diskette in drive (a-h) ?"); 
if (getsel()==0) return; 
if (contO) { 
nl(); 

trk=0; sec=firstsector-1; 
while (next(8trk,8sec)) < 
if (tstbrkO) return; 
if (sec==firstsector) { 

putsC'track "); putnum(trk); conout(CR); 

> 

if (read(trk,qskew(sec),vfybuf)==0) ( 
putsC'the dubious quality of "); 

put sec(trk / qskew(sec)); puts(" has been detected"); nl(); 
dfltrk=trk; dflsec=qskew(sec); 

> 

> 

putsC'scan finished"); nl(); 

> 

> 

/* 

* patch 
*/ 

patchO 
< int pos; 

nl(); nl(); putsC'patch diskette in drive (a-h) ?">; 
if (getsel()==0) return; 

if (dflsec<firstsector) dflsec=firstsector; 
getsec(8dfltrk,8dfIsec); 
putnls(60); gohomeO; 

puts("<sp>=next-byte, <bs>=previous-byte, <cr>=next-line, <hex>, ',"); 
nl (); 

puts("next / logical-next, trk-sec, re-read, shift-bit, write or quit ?"); 
putnls(4); 

put $(" +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f"); 

puts(" 0127456789?bcdef"); 

pos=pread(); 

while ((pos=petchcmd(pos))>=0); 
putnls(60); 


/* 

* one patch command 

* return new position, -1 if quit 
*/ 

patchcmd(pos) 
int pos; 

i char cmd,dig; 
cmd=conlower(); 
if (cmd=='q') return -1; 
else if (cmd==‘ ') pos=(pos+1)%SECLEN; 
else if (cmd==BS) pos=(pos+SECLEN-1)%SECLEN; 
else if (cmd==CR) pos=(pos+16)%SECLEN; 
else if (cmd= =, s') pos=pshift(pos); 
else if (cmd 22 '^) pos=pnsect (); 
else if (cmd=='l') pos=plsect(); 
else if (cmd=='t') pos=psetts(); 
else if (cmd=='r') pos=pread(); 
else if (cmd=='w') pos=pwrite(); 
else if (cmd==Q0T) -C 
conout(QOT); 


cmd=conin(); 
conout(BS); 

if (cmd==BS) tbyte(pos); 
else pos=patchpos(pos,cmd); 

> 

else if ((dig=makhex(cmd))>=0) { 
putdig(dig); 

while ((cmd=conlower())!=BS) if (makhex(cmd)>=0) break; 
conout(BS); 

if (cmd==BS) tbyte(pos); 

else pos=patchpos(pos,(dig«4)+makhex(cmd)); 

> 

return poscur(pos); 

> 

/* 

* patch one byte, update screen 

* and return new position 
*/ 

patchpos(pos,new) 
int pos,new; 

■( int tpos; 

secbufCpos3=new; 
tpos=pos++; 

if (pos>=SECLEN) pos=0; 
while (tbyte(tpos++)>0); 
return pos; 

> 

/* 

* shift one bit at current position 
*/ 

pshift(pos) 
int pos; 

i int tpos,byte,carry; 
tpos=pos; 
carry=0; 
while (1) { 

byte=secbuf[tpos]8255; 

secbufCtposD=(byte>>1)|(carry<<7); 

carry=byte81; 

if (tbyte(tpos++)==0) break; 

> 

return poscur(pos); 

> 

/* 

* next sector 
*/ 

pnsect () 

{ next(8dfItrk,8dfI sec); 
return preadO; 

> 

/* 

* next logical sector 

* useful only in systems with mapping between logical and physical 

* sector numbers 

*/ 

plsect () 

{ Inext(8df 1 1 rk,8dflsec); 

return preadO; 

> 

/* 

* set new track/sector address 
*/ 

psettsO 

{ gohomeO; putnls(2); putsps(38); 
gohomeO; nlO; 
getsec(8dfltrk,8dfIsec); 
return preadO; 

> 

/* 

* read and display one sector during patch 
*/ 

preadO 
{ char *p; 
int pos; 
pos=0; 

while (pos<SECLEN) secbufCpos++D=0; 
gohomeO; putnls(2); 

if (read(dfltrk,dfIsec,secbuf)==0) putsC'error reading "); 

put sec(dfltrk,dfIsec); 

putsps(18); nlO; putsps(24); 

poscur(pos=0); 

while (tbyte(pos++)); 

return poscur(O); 

> 

/* 

* write one sector during patch 

* verify by reading back 
*/ 

pwriteO 
•C int c; 

gohomeO; putnls(2); c=cont(); 

(Continued on next page) 


Dr. Dobb’s Journal, Number 66, April 1982 




Small-C DISKDOC (Listing continued, text begins on page 26) 


gohomeO; putnls(3); 
if (c) < 

if (write(dfltrk,dflsec,secbuf)==0) putsC'error writing"); 

else if (read(dfltrk,dflsec,vfybuf)==0) putsC'error reading back"); 

else if (eqsec(secbuf,vfybuf)==0) putsC'error on read verify"); 

putsps(22); 
return poscur(O); 


* position cursor during patch 

* position is returned 

*/ 

poseur(pos) 
int pos; 

( int n; 

gohomeO; putnls(6); puts("00 "); 

n=pos/16; while (n—) conout(LF); 
n=(pos/16)*16; while (n<pos) tbyte(n++); 
return pos; 

> 

/* 

* print byte in patch table 

* returns -1 if end of line 

* 0 if end of page 

* 1 otherwise 


tbyte(pos) 
int pos; 

< putbyte(secbufCpos++3); /* print byte */ 
putsC "); 

if (posX16) return 1; 

puts(" '"); /* print ascii equivalents */ 

pos=pos-16; 

while (1) i 

conout(makep(secbufCpos++D)); 
if ((posX16)==0) break; 

> 

puts("'"); nl<); 
if (pos==SECLEN) return 0; 

putbyte(pos); /* print address too */ 

putsC "); 
return -1; 


*/ 

getsec(t,s) 
int *t,*s; 

<■ nl (); putsC'track (0-"); putnum(tracks-1); putsC) ?"); 
*t=getnum(*t, 0 ,tracks- 1 >; 

nl(); putsC’sector ("); putnum(firstsector); puts("-"); 
putnum(sectors-1+firstsector); putsC) ?"); 

^ *s=getnum(*s,firstsector,sectors-1+firstsector); 

/* 

* get drive name, select and reset 

* 0 if cannot select 
*/ 

getsel() 

< if (seldrvUdf ldrv=getdrv(dfIdrv)),8tracks,8sectors,&firstsector)== 0 ) { 
nl(); putsC'drive not ready"); nl(); 
return 0; 

> 

rstdrvO; 
return 1; 


/* 

* select two drives 

* parameters of drives selected must be equivalent 

*/ 

seltwoCdl,d2,text1,text 2) 
char *d1,*d2; 
char *text1,*text?; 

( int dtracks,dsectors,dfirstsector; 
nl(); nlO; puts(textl); 

*d1=dfldrv=getdrv(dfIdrv); 
nl(); puts(text2); 

*d2=getdrv(dfIdrv); 

seldrv(*d1,&tracks,&sectors,&firstsector); /* establish constants */ 
rstdrvO; 

seldrv(*d2,8dtracks,Sdsectors,&dfirstsector); 
rstdrvO; 

if ((dtracks!=tracks)|(dsectors!=sectors)|(dfirstsector!=firstsector)) { 
nlO; putsC'drives are not compatible"); nlO; 
return 0; 

> 

return If 


/* 

* read one track 

* assume that drive is already selected 
*/ 

readtrk(trk,adr) 
int trk; 
char *adr; 

( int sec; 
char cmd; 
sec=firstsector; 
while (1) { 

if (tstbrkO) return 0; 
if (read(trk,qskew(sec),adr)==0) i 

nlO; putsC'error reading "); putsec(trk,qskew(sec)); 
nlO; putsC'continue, retry or quit ?"); 
cmd=getcmd("qcr" / 'r'); 
if (cmd== 1 r 1 ) { 

read(0,firstsector,vfybuf); /* reposition */ 
continue; 

> 

dfltrk=trk; dflsec=qskew(sec); 
if (cmd= =, q') return 0; 

> 

adr=adr+SECLEN; 
if (nexts(8sec)==0) return 1; 

> 

> 


/* 

* increment track and sector, 0 if no more 

*/ 

next(t,s) 

int *t,*s; 

< if (nexts(s)) return 1; 


return nextt(t); 

> 

/* 

* increment sector, 0 if no more 
*/ 

nexts(s) 
int *s; 

< if ((++*s)>(sectors-1+firstsector)) { 
*s=firstsector; 
return 0; 

> 

return 1; 

> 

/* 

* increment track, 0 if no more 

*/ 


/* 

* write one track 

*/ 

writetrk(trk,edr) 
int trk; 

char *adr; 
i int sec; 

sec=firstsector; 
while (1) < 

if (tstbrkO) return 0; 
if (write(trk,qskew(sec),adr)==0) i 

nlO; putsC'error writing "); putsec(trk,qskew(sec)); nlO; 
return 0; 

> 

adr=adr+SECLEN; 
if (nexts(8sec)==0) return 1; 

> 

> 

/* 

* get track and sector numbers 


nextt(t) 

int *t; 

( if ((++*t)>=tracks) return *t=0; 
return 1; 


/* 

* return skewed sector number, skew factor is two. 

* this function is not equivalent to InextO. 

* the only purpose of this function is to optimize 

* scan and backup operations. 

* hard disks will operate faster without a skew. 

* hard disk is assumed if there are more than 100 tracks (!). 

*/ 

qskew(sec) 
int sec; 

{ if (tracks>100) return sec; 
sec=sec+sec-firstsector; 
if (sec>(sectors-1+firstsector)) 

return sec-sectors+((sectors&1)==0); 
return sec; 


30 

168 


Dr. Dobb’s Journal, Number 66, April 1982 



> 


* compare two sectors 

* false if not equal 
*/ 

easec(seel,sec2) 

char *sec1,*sec2; 

{ int n; 
n=0; 

while (n<SECLEN) < 

if (seelCn]!=sec2Cn]) return 0; 
++n; 

> 

return 1; 

> 

/* 

* select drive during backup 

* return 0 if something fishy 

*/ 


> 

> 

return n; 

> 

/* 

* make character printing 

*/ 

makep(ch) 
char ch; 

( ch=ch&127; 

if ((ch>=' ’)&(ch<127)) return ch; 
return ' 

> 

/* 

* put track and sector numbers 

*/ 


baksel(drv,otherdrv,name) 

char drv,otherdrv; char *name; 
i int dummy; 

if (drv==otherdrv) { 

nlO; putsC'insert "); puts(name); puts(" diskette"); 
if (cont()==0) return 0; 

> 

if (seldrv(drv,&dummy,&dummy,&dummy)==0) { 

nl(); puts(name); puts(" drive is not ready"); nl(); 
return 0; 

> 

return 1; 

> 

/* 

* get drive name, enter with default drive 
*/ 

getdrv(df l) 
char dfl; 

{ return getcmd("abcdefqh",dfl); 

> 


putsec(t ,s) 
int t,s; 

< putsC'track "); putnum(t); 
puts(" sector "); putnum(s); 

> 

/* 

* put decimal number, 

* return number of digits printed 

*/ 

putnum(n) 
int n; 

( int d; 

if (n>9) d=putnum(n/10); 
else d=0; 
put dig(n%10); 
return d+1; 

> 

/* 

* put hex byte 

*1 


/* 

* ask for continue or quit, true if continue putbyte(n) 

*/ int n; 

i putdiq(n>>4); 

contO putdig(n); 

{ char cmd; ^ 

nl(); put sC'conti nue or quit ?"); 

cmd=getcmd("cq",'c'); nl(); I* 

return cmd= =, c'; * Put digit 

> */ 


/* 

* get single character command, 

* enter with possible commands and default command 

*/ 

getcmd(cmds,dfl) 
char *cmds,dfl; 

{ char cmd,ch; 
while (1) < 

if ((cmd=conlower())==CR) cmd=dfl; 
if (member(cmd,cmds)==0) continue; 
conout(cmd); 
ch=0; 

while (ch!=BS) if ((ch=conlower())==CR) return cmd; 
unput(); 

> 

> 


putdig(d) 
int d; 

< if ((d=d&15)>9) conout(d-10+'a'); 
else conout(d+'O'); 

) 

/* 

* put string 

*/ 

put s(st r) 

char *str; 

{ while (*str) conout(*str++); 

> 

/* 

* put spaces 
*/ 


/* 

* see if character can be found in a string 
*/ 

member(ch,str) 

char ch,*str; 

{ while (*str) if (*str++==ch) return 1; 
return 0; 


putsps(n) 
int n; 

{ while (n—) conout(' '); 

> 

/* 

* new tine 
*1 


/* 

* get a unsigned decimal number 

* enter with default, minimun and maximum values 

*/ 

getnum(dfl,min,max) 
int dfl,min,max; 

< int n,digits,newn; char ch; 
if (dfl>max) dfl=max; 
n=digits=0; 
while (1) < 

if ((ch=conlower())==CR) { 
if (digits) { 

if (n>=min) break; 

> else digits=putnum(n=dfl); 

> else if (ch==BS) < 

if (digits) -C 

—digits; n=n/10; 
unput(); 

> 

> else if (((makdec(ch))>=0) & ((newn=n*10+makdec(ch))<=max)) < 

if ((newn>0)|(digits==0)) i 
++digits; n=newn; 
conout(ch); 


nlO 

{ COnout(CR); conout(LF); 

> 

/* 

* put newlines 
*/ 

putnls(n) 
int n; 

< while (n—) nlO; 

> 

/* 

* erase previous character 
*/ 

unput() 

■C conout (BS); conout (' '); conout (BS); 

> 

/* 

* move cursor to home position 

*/ 


Dr. Dobb’s Journal, Number 66, April 1982 


31 

169 




Small-C DISKDOC (Listing continued, text begins on page 26) 


yohomeO 

{ if (home>=128) conout(ESC); 
conout(home & 127); 

> 

/* 

* convert decimal digit, -1 if error 

*/ 

makdec(ch) 
char ch; 

{ if ((ch=ch-'O')<0) return -1; 
if (ch<=9) return ch; 
return -1; 

> 

/* 

* convert hex digit, -1 if error 

*/ 

makhex(ch) 
char ch; 

{ if (ch<*0*) return -1; 

if (ch<='9') return ch-'O'; 
if ((ch=ch-'a'+10)<10) return -1; 
if (ch<=15) return ch; 
return -1; 


/* 

* test for break, true if yes 
*/ 

tstbrkO 

{ if (constO) < 

nl(); puts("break"); 
if (cont()==0) return 1; 

> 

return 0; 

> 

/* 

* get character, no echo 

* upper case is converted to lowpr 
*/ 


conlowerO 
{ char ch; 

if (((ch=conin())>='A 1 )&(ch<='Z')) ch=ch+'a'-'A'; 
return ch; 


/* 

* system dependant functions 
*/ 

^include ddocsys.c 


/* 

* the small C runtime library (as shown in the Dr. Dobbs 

* September 1980 issue and as distributed by The Code 

* Works) must be named ddoclib and edited 

* so that it contains the primitive functions only: 

* ccgchar,ccgint,ccpchar,...,ccmult,ccdiv 
*/ 

#include ddoclib 


int lastglobal; /* dirty trick, will work in small-c */ 
botmemO 

{ return RlastglobaL; 

> 

/* 

* top of free memory 

* rpmemb°r that the stack needs some space too 

*/ 

topmemO 

i char *p,topofstack; 
p=Stopofstack; 
return p-700; 

> 

/* 

* return true if enviroment seems to be ok 

*/ 

sysokO 
{ char *p; 

#asm 


mvi 

c,12 

;check version number 

call 

5 


ani 

Of Oh 


cpi 

70h 

;v e r 2.x? 

) nz 

nogood 


mov 

p,h 


ora 

a 

;cp/m? 

jz 

ok 


nogood: 

Ixi 

h,0 

;false if no good 

pop 

d 



ret 

ok: 

flpndasm 

p=1; 

return (*p== 3 ); /* check if xsub or despool is active */ 


/* 

* return console status, true if ready 

*/ 

const() 

{ return bios(2,0); 

> 

/* 

* get character from console, no echo 
*/ 

coninO 

{ return bios( 7 ,0); 

> 

/* 

* put character t-o console 

* no character conversion should be performed 
*/ 

conout(ch) 
char ch; 
t bios(A,ch); 

> 


/* TAB SI,4 FILE DDOCSYS.C 

* 

* system dependant functions for diskdoc 

* 

* required are: 

* botmem,topmem,sysok,conin,conout,const 

* seldrv,lnext,read,write,rstdrv 
*/ 

/* 

* this version is for small C and cp/m 8080 version 2.x. 

* since bios must be used for sector read and write, 

* character i/o functions use bios directly too. 

* cp/m "compatible" operating systems will probably 

* need to have these functions rewritten. 

*/ 

char *xlt; /* sector xlate table, used by cp/m version */ 

/ * 

* return pointer to bottom of free memory 
*/ 


/* 

* select drive, drive name is 'a^'b' etc. 

* set values for track, sector counts and first sector 

* return true if ok 

* to see wh?t this version does, 

* refer to the cp/m 2.0 alteration guide 


seldrv(drv,pt,ps,pf) 
char drv; 

int *pt,*ps,*pf; /* where to put track, sector and firstsector */ 

{ int *dph,*spt,*dsm,*off,halfsecs,trks; 
char *dpb,*bls; 

if ((dph=bios(9,drv- , a'))==0) return 0; 

xlt=dph[0T; /* look at disk parameter header */ 

dpb=dph[5]; 

if (xlt) *pf=xltC0D; 

else *pf=0; 

spt=8dpbC03; *ps=*spt; /* and at disk parameter block too */ 


32 

170 


Dr. Dobb’s Journal, Number 66, April 1982 


bls=&dpbC23; 
dsm=8dpbC5]; 
off=8dpbC13D; 

/* this is tricky since unsigned divide isn't supported */ 
hal fsecs=(*dsm+1 )«(*bls-1); 

trks=((halfsecs/(*spt))*2)+(((halfsecs%(*spt))+(*spt-1))/(*spt)); 
*pt=trks+*off; 
return 1; 


flendasm 

> 

/* 

* some small C library functions need redefinition 
*/ 

#asm 

ccgo: 

ret 

azexit: 

jmp 0 


/* 

* return next logical track/sector 

* replace by a call to nextO if not required 

* cp/m version sets sector number according to translate table 
*/ 

End Listing 

int *t,*s; ° 

i int l; 

if (xlt) < 

1=0; 

while (xltCl++1!=*s); 
if (l>=sectors) { 
nextt(t); 

1=0; 

> 

*s=xltCl]; 

> else next(t,s); 


/* 

* reset the currently selected drive 

* used prior to any other operation on a drive 

* no error code is returned 
*/ 

rstdrvO 
< bios(8,0); 


/* 

* read sector, false if error 
*/ 

read(trk,sec,adr) 
int trk,sec; 
char *adr; 

< bi os(10,trk); 
bios(11,sec); 
bios(12,adr); 
if (bios(13,1)) return 0; 
return 1; 

> 

/* 

* write sector, false if error 
*/ 


write(trk,sec,adr) 
int trk,sec; 
char *adr; 

< bios(10,trk); 


bios(11,sec); 
bios(12,adr); 
if <bios(14,1>> 


return 1; 


> 


return 0; 


/* 

* bios call 

* will only work with the original small C 

* other C compilers will usually have the argument sequence reversed 

*1 


bios(fun,arg) 

int fun,arg; 

{ char *ofs; 

ofs=(fun-1)*3; 

#asm 


pop 

d 

;of s 

pop 

h 

; ret 

pop 

b 

;arg 

push 

b 


push 

h 


push 

d 


l h Id 

1 

;get pointer to bios 

dad 

d 

;add offset 

Ixi 

d,retn1 


push 

d 


pchl 


;go 

•etnl: 
xchg 
mov 

1,8 


mvi 

h,0 


pop 

b 

;of s 

push 

b 


mov 

a,c 

* 

cpi 

(9-1)*3 

;select disk function? 

jnz 

retn2 


xchg 


;yes 


retn2: 


Dr. Dobb’s Journal, Number 66, April 1982 


33 

171 




Make the Most of Your 

Check Digits 


T here was a question about check 
digits in Dr. Dobb’s Clinic. I wrote 
an answer to it, and was asked to 
produce a small paper. Here it is. 

All of the programming examples in 
the paper are written in CBASIC. 

Definition 

A check digit is a digit used to pro¬ 
vide some kind of check on the number 
with which it is associated; usually, the 
check is to assess any “damage” that may 
have occurred to a number between the 
time the number is created and the time 
of its being revalidated. 

Depending on the way the check 
digit is designed, it can simply identify 
that there has, probably, been an error, 
or several errors; it may be able to indi¬ 
cate what the error or errors probably 
were, and what the correction probably 
is. 

Note that word “probably”! It is 
not possible to guarantee that a check 
digit will always do the job for which it 
was intended — it is merely possible to as¬ 
sign a reasonably high probability to its 
being able to do that job. 

The Basic Underlying Concept 

Check digits can be used in any num¬ 
ber system; let’s start with binary. Con¬ 
sider the binary representations of the 
numbers from 0 to 3: 00, 01, 10, and 11. 
Arrange these in a table: 



01 

_ 1 _ 

10 

11 

00 

! 1 
“H 

T 

i 

__j._ 

1 » 

A 1 

9 

01 

l _ 

~ ’f 

T 

i 

i 

_.L_ 

+ “ 

o « 

i. 1 

_J._ 

i 

i /> 

JL V 

l _ 

T 

i 

1 

1 

i 


where the entries in the table are the 
number of bits by which the two binary 
representations differ. (Note that all pos¬ 
sible combinations are in the table - it’s 
arranged the way it is to conserve space!) 

Now, consider those same four bi¬ 
nary representations — but this time, with 


Peter Zilahy Ingerman 


Peter Zilahy Ingerman, Systems Consul¬ 
tant, 40 Needlepoint Lane, Willingboro, 
NJ 08046-1997. 


a parity bit added to make the number of 
l’s odd: 

010 100 111 

AA 1 i n i o i n 

V v X I I JC. I 4, 

- + - + - + - 

010 ! - ! 2 ! 2 

- + -+- + - 

t AA 1 — 1 — 1 O 

.1 V V I I I iL 

Now the minimum number of bits that 
change between any two binary repre¬ 
sentations is 2. That means that if any 
single bit changes, an illegal representa¬ 
tion will be produced. There is no infor¬ 
mation as to what bit is in error, but the 
fact that some single bit is in error will 
be known. 

When we add this bit, we are taking 
a subset of all possible combinations of 
three bits, and electing to use only half of 
these possible combinations, in such a 
way that “between” every permitted 
combination of three bits there is a for¬ 
bidden combination of three bits. How¬ 
ever, since there is only one forbidden 
combination “between” every permitted 
combination, there is no way of telling, 
when an error occurs, which permitted 
combination was the original. 

If two bits change, there will be no 
indication of an error. Hence, a single 
parity bit is a single-error-detecting 
check digit. 

More formally, the minimum number 
of bits that change between any two bi¬ 
nary representations is called the distance 
for that representation method. If the dis¬ 
tance for a representation is n, the repre¬ 
sentation will be able to detect n-1 er¬ 
rors (where an “error” is defined as a 
bit-change). 

Suppose we design a representation 
so that, between every permitted combi¬ 
nation, there are two forbidden combina¬ 
tions. Now the minimum distance is 
three, so that this is a double-error¬ 
detecting representation. However, we 
might have enough confidence in our 
source of binary representations so that 
we feel confident that only one bit will 
have changed (that is, that there will have 
been at most a single error). 

Then, in this representation, any for¬ 
bidden combination of bits has a “near¬ 
est” permitted combination of bits, and 
we may choose to presume that the near¬ 
est permitted combination of bits was the 
original representation. If we do this, we 


can describe the representation as being a 
single - error- correcting representation. 

There is a trade-off between error 
detection and error correction. An n- 
error detecting representation is an n- 
over-2-error-correcting representation; if 
we believe that at most n-over-2 errors 
will occur, we can correct them with such 
a code, but we will still have a problem if, 
in fact, more than n-over-2 errors occur 
(although we still could detect n errors). 
However, you can’t have both. If you are 
detecting n errors, you must have given 
up correcting n-over-2 errors, and vice 
versa. 

The first decision, then, that has to 
be made in designing a check digit is 
whether the intent is to detect errors or 
to attempt to correct errors. If a check 
digit is error-detecting, how many errors 
(in the sense of flipped bits) is it desired 
that it detect; if a check digit is error- 
correcting, a similar question must be 
answered. Check digits are usually intend¬ 
ed as error-detection devices, since it is 
usually safer to refer an error to a human 
being for correction than to take the 
chance that a sufficiently small number 
of errors have occurred so that automatic 
correction is reasonable. 

The Modulo 9 Check Digit 

(“Modulo 9” means “the remainder 
upon division by 9”.) 

Now let’s turn to decimal numbers. 
Check digits are associated with decimal 
numbers to protect against undetected 
errors in transmission from one point to 
another; human beings may or may not 
be involved. Go to Figure 1. Note that 
the scan proceeds in that Figure from 
right to left. This makes no difference 
here, but will in some other cases, so it is 
a good idea to get used to doing it that 
way. 

Now — how does it work? Consider 
a decimal number “abc” as a polynomial: 

a*10 t 2 + b*10 + c 
Rewrite 10 in a funny way: 

a*(9+1) t 2 + b*(9 + l) + c 
and expand this to get 

a*9 12 + 2*a*9 + a + b*9 + b + c 

Hence, the remainder upon dividing the 
decimal number “abc” by 9 is 

a + b + c 

since all of the other terms in the expan¬ 
sion have 9 as a factor (and hence are 
divisible by 9). 


36 


Dr. Dobb’s Journal, Number 66, April 1982 











Figure 1 

If Hi it, the number whose check disit is to be calculated? then! 


Check digitX=0 
rc {.EWNS'^O THEN N$="0“ 

REM T sKs CoP? of 1 sn siieniP t to check the null string 

fnp tv— t ci^if ju* 5 to i STEP -1 

Check.diSit2-Check.diSit%+VAL<MID$<N$»I%?1)) 

T r Check .disitX!>=9 THEN Check.disitZ=Check.disitZ-9 

NEXT ll 


•ill leave the check disit Modulo 9 in Check.disit%. 


But what is that funny line 

IF Check.digit%>= 9 THEN 
Check.digit%= Check.digit%-9 

Suppose, in the process of scanning 
N$ to calculate the check digit, we get a 
value in Check.digit % that is greater than 
9. This means that a + b + c is itself a 
number greater than 9, but the remainder 
on division by 9 cannot be greater than 8, 
so the extra 9’s in the remainder must be 
removed. 

Finally, it is obvious (hopefully) 
why a Modulo 9 check digit is also called 
a sum-of-the-digits check digit. 

The Modulo 11 Check Digit 

Refer to Figure 2. If we write 10 as 
(11-1), the proof is essentially the same 
as the proof given above for the Modulo 9 
check digit, and is left as an exercise. The 
Modulo 11 check digit is also called the 
alternating sum-of-digits check digit. 

The Modulo 7 Check Digit 

Airline tickets use a Modulo 7 check 
digit for every number that appears on 
the ticket. If you examine a ticket pur¬ 
chased from a ticket agent, you will find 
a check .digit Modulo 7 suffixed to at 
least the ticket number, the travel agent 
number, and the airline number. 

Years ago, in a telephone conversa¬ 
tion, when the world was less suspicious 
and more willing to answer questions, 
an airline representative suggested that 
a Modulo 7 check digit was used because 
it was easy to calculate, and at the same 
time not nearly as obvious as Modulo 9 or 
Modulo 11. 

What Kind of Errors 
Does a Modulus Catch? 

A Modulus check digit is, by defini¬ 
tion, the remainder after dividing the 
number by the modulus. Hence, a Modu¬ 
lus check digit will not catch an error 
such that the absolute value of the differ¬ 
ence between the correct number and the 
number in error has a remainder of 0 
when divided by the modulus. 

Another way of looking at this is to 
observe that since the check digit is the 
remainder after division by the modulus, 
adding any integer multiple of the modu¬ 
lus to the original number will make no 
change in the check digit. Hence a 
Modulo 9 check digit will not detect the 
interchange of any two digits in the ori¬ 
ginal number, since the absolute value of 


the difference of two numbers differing 
only by having two digits interchanged is 
necessarily divisible by 9 (the proof is 
left as an exercise). Also, it follows from 
the above discussion that if the modulus 
being used has a prime factor in common 
with the base of the number system, 
there is less information (possibly none) 
in the check digit than there would be 
otherwise. 

As an illustration, a Modulo 2 or 5 
check digit for a number base 10 depends 
only on the least significant digit of the 
number, a Modulo 8 check digit for a 
number base 10 depends only on the 
three least significant digits of the num¬ 
ber, and, in general, if b is the base of the 
number system, and k is the smallest inte¬ 
ger such that b t k is evenly divisible by r, 
then a check digit modulo r for a number 
base b will depend only on the least sig¬ 
nificant k digits of the number. 

By the same argument, a Modulo 6 
check digit has only a little more informa¬ 
tion in it than a Modulo 3 check digit. 


since the part of the result that depends 
on the factor of 2 in the modulus de¬ 
pends only on the least significant digit of 
the number. 

A Parenthetical Note 

If N$ is the number whose check 
digit Modulo X is to be calculated, there 
are two obvious ways of calculating the 
check digit for a number N$: 

T=VAL(N$)/X 

Check.digit%=X*(T-INT(T)) 

which may have a problem with rounding 
errors under some odd circumstances, 
but is, otherwise, very simple indeed, and 

T=VAL(N$) 

WHILE T>X 
T=T-X 
WEND 

Check.digit%=T 

which does not have any rounding error 
problems unless T is very large, but does 
require a loop whose time increases with 


Figure 2 

If N4 is the posher whose check digit is to be calculated, then! 


Check,disit%=0 

IF LEN< N$ )=0 THEN N$="00" 

REM Take care of an attempt to check the null string 
IF LENIN*) AND 1 THEN N$=“0“+Nt 

REM Make the length of N* even 
FOR I%=LEN< N* ) TO 1 STEP -2 

Check ,disitX=Check .diSit%K'AL< MID*< Nt.IZ.l >>- \ 
VAL<MID*< Nt.IZ-1.1 ) 

IF Check.disit%>=ll THEN Check.digit%=Check.digi iX-1 1 
IF Check .digi tKO THEN Check.digitX=Check.disit%+ll 

NEXT IX 

will leave the check digit Modulo 11 in Check.disit%. 


Dr. Dobb’s Journal, Number 66, April 1982 


37 

173 






Figure 3 

origins! number 
weight 

weighted disits 
sum of weighted digits 
76 Modulo 9 < e.S.) 


“12”, “21”, and “135” are not as good 
as the weights “13”, “31”, and “137”, 
assuming that you are working with deci¬ 
mal numbers. There is less checking if ad¬ 
jacent weight digits are the same than if 
they are different. Hence, “1337” is not 
as good as “1373”. 


digit we are inserting: 

17 2 3 5 
117 2 3 5 
11702 3 5 
1170223 5 
117022375 
1170223751 



the number whose check digit is being 
calculated. 

The programs given in the previous 
sections for calculating the check digits 
do not depend on the number of signifi¬ 
cant digits that can be represented in a 
number, since the numbers whose check 
digits are being calculated are treated as 
strings, and the only limitation is the 
maximum size of a string (which is 255 
bytes in CBASIC; obviously much greater 
than the precision of a real number in 
CBASIC!). Hence, in the most general 
case, it is advisable to treat the number 
whose check digit is being found as a 
string, but if additional information is 
available (e.g., all of the numbers are 
fewer than 7 digits), it may be reasonable 
to use a less general algorithm. 

Weighted Check Digits 

Another way of computing check 
digits is to “weight” the digits in the ori¬ 
ginal representation. An example is 
shown in Figure 3, where each digit is 
multiplied by its weight and then the 
weights are summed and a check digit 
computed from the sum of the weights. 
If N$ is the number whose check 
digit is to be calculated, W$ is one period 
of the weighting vector (for the example 
above, W$ would be “13”), and X is the 
modulus to which the check digit is to be 
computed, then the example in Figure 4 
will leave the Modulo X weighted-sum 
check digit in Check.digit%. 

Various weights have been used. 
Among the more common are: 

. 12 
. 21 
. 13 
.31 
. 135 
. 137 

Some Comments on the 
Weighted Check-Sum 

An analysis of the weighted check¬ 
sum is, frankly, more involved than 
makes sense to try to include in this 
paper. However, it is definitely worth 
making some observations about ways to 
improve the checking capability of the 
technique. 

First, the longer the period, the 
better the checking. In this sense, the 
three-character weights “135” and “137” 
are better than any of the two-character 
weights given above. Digits in the weight 
that are not factors of the base are better 
than digits that are. Hence the weights 

38 

174 


Multiple Check Digits 

Well, why not? But if you can af¬ 
ford to have multiple check digits, where 
should you put them, and how should 
they be calculated? 

One scheme is to put them, one at a 
time, at the end of the number, with the 
calculation for each check digit including 
all of the check digits that have already 
been added. If each check digit is calcu¬ 
lated with respect to a different modulus, 
this technique has about the same effect 
as calculating a single “check digit” to a 
modulus that is the product of all of the 
individual moduli used to calculate the 
individual check digits. 

On the other hand, if it is possible to 
distribute the check digits through the 
original number, it may be possible to 
identify the digit in the original number 
that is in error. As an example, consider 
the number 

1 7 2 3 5 

Suppose that we insert a check digit 
Modulo 9 after each digit of the original 
number, based on all of the digits (includ¬ 
ing check digits) to the left of the check 


and suppose that the 2 in the original 
number is changed to a 3. This would 
produce the number 1170333055. If this 
is compared with the previous number, 

1170223751 

1170333055 

XX X X 

it is clear that the left-most “x” marks 
the spot where there is a difference, and 
hence where the error occurred. 

A Closing, but Parenthetical, 
Comment 

In everything that has been discussed 
above, the assumption was made that the 
thing being examined was the representa¬ 
tion of a number. In the programming ex¬ 
amples, the number was represented as a 
string. 

An ASCII character has associated 
with it a numeric value between 0 and 
1 27. Hence, a string can be thought of as 
a representation of a number base 128. 
Exactly the same discussion applies to the 
creation of check characters for strings 
as applies to the creation of check digits 
for numbers. tkj 


Dr. Dobb’s Journal, Number 66, April 1982 


Figure 4 

T=0 

IF LEN(Nt >=0 THEM N$="0" 

REM Take cars GT on cjlt/cITir t to check the null string 

T$ = "» 

UHILE LEN< T$ KLEN(N$ ) 

T$=y$+T$ 

i.icun 

WL'U' 

REM This makes the weighting vector long enough 
FOR IX=LEN( N't) TO 1 STEF -1 

T=T+'v'AL< MID$< N$»IX?1) }*t'AL< MID$< T$?IX?1)) 

UCVT TV 

I ? C -A i J, /» 

T=UALt N$ )/X 

Check ,digitX=X*< T-INT< T)) 

REM This is a simplified computation? see above 




A Poor Person’s 
Spelling Checker 


T his is a very simple, stand-alone 
spelling checker that will proof¬ 
read any CP/M text file including 
those produced by most word processors. 
This program was intended to be the low- 
cost answer to early expensive spelling 
checkers, but recent announcements of 
a plethora of modestly priced spelling 
checkers have made marketing of the 
Speller impractical. I have decided to 
publish this version for non-commercial 
use by those interested in investigating 
the problems of spelling verification. 

The Speller is coded in Z80 assembly 
language rather than 8080 assembly lan¬ 
guage, because the Z80 instruction set is 
much closer to that of the large IBM 
systems I am used to. The techniques 
used in this program are adaptations of 
ones used with large IBM systems and, be¬ 
cause of the limitations of the Z80 in¬ 
struction set, may seem awkward to the 
Z80 programmer. 

The Speller first reads a text file, 
isolates words, and builds a list in 
memory of distinct words. Words are 
isolated using two tables, one of delimit¬ 
ers and one of letters. As each word is 
isolated, the word list is searched and if 
the word is not present it is added. Since 
only one list entry is built for each dis¬ 
tinct word, a great deal of text can be 
processed in a single pass. If there are 
more distinct words than will fit in the 
available memory, multiple passes are 
made until all the text is processed. 
Words longer than 30 characters are split 
into 30 character pieces and a console 
message is printed identifying the long 
word. 

After the words have been isolated 
from the text, lexicons are scanned and 
each word in each lexicon is compared 
with the words isolated from the text. 
Each correctly spelled word is flagged and 
after all lexicons have been scanned, the 
unflagged words are listed at the console 
in the order they appeared in the text. 
Lexicons are maintained with regular 
editors and need not be in alphabetical 
order. 

This is a slow process and may not be 
practical for documents with more than 
3000 distinct words. Such documents, 
however, are very rare because the num- 


by Alan Bomberger 

Alan Bomberger, 3721 Starr King Circle, 
Palo Alto, CA 94306. 


ber of distinct words used by any particu¬ 
lar writing style is usually less than 1000. 


Use 

The Speller is executed with the 
command 

[DSK:] SPELL [DSK:]FILE.TYP 

After the text has been completely 
scanned or when the available memory is 
full, the user is prompted to enter the 
names of lexicons to scan. After all the 
desired lexicons have been scanned, 
words not located in the lexicons are list¬ 
ed at the console in the order in which 
they were isolated in the text. If there 
was insufficient memory to process the 
entire file, additional isolation and lexi¬ 
con scan passes are made. There is no 
interactive interface with the Speller, 
and after all the possibly misspelled 
words are listed on the console, it is the 
responsibility of the user to make correc¬ 
tions in the text using whatever text edi¬ 
tor is preferred. 

All lexicon files are of the type LEX. 
If a <CR> is entered, then the list 
of possibly misspelled words will be 
printed on the console. 


Lexicons 

Lexicons are lists of words that are 
assumed to be correctly spelled. Each 
word is separated by <CR> or <CR- 
LF > with blanks ignored. A lexicon can 
be built by entering each word on a sepa¬ 
rate line of a text file. Lexicons that con¬ 
tain words with characters other than the 
26 letters of the alphabet must be care¬ 
fully coordinated with the word isolation 
tables described later. 

In this implementation, lexicons may 
be compacted using a technique based on 
the frequency of occurrence of the letters 
in the lexicon. The most common 15 
letters (including <CR>) are coded as 
4-bit numbers from 0 to 0E and the rest 
of the letters (including CNTL Z) are 
coded as 8-bit numbers from F0 to FC. 
The frequency of occurrence of each 
letter was determined by counting the 
letters in the lexicon I use (33,000 words 
of a general vocabulary) and the tables 
that describe the mapping of letters to 
numbers are labeled T1 and T2 in the 
code. These tables are easily changed to 
reflect the relative frequency of letters 


for particular lexicons provided that a 
corresponding compression program is 
written to compact the lexicon. The first 
byte of a compacted lexicon contains an 
FF so that compacted and non-compacted 
lexicons can be recognized automatically 
by the Speller. This compaction tech¬ 
nique cuts the size of a 33,000 word lexi¬ 
con by one half without introducing 
much overhead. Other schemes can be de¬ 
vised with much higher compaction but 
may rely on the order of the words. 

Since no analysis of words is per¬ 
formed by the Speller, all forms of words 
that might be used must appear in the 
lexicon. With this simple scheme, a lexi¬ 
con would have to be extremely large in 
order to achieve complete spelling veri¬ 
fication. However, including the most 
common forms of words makes it possi¬ 
ble for modest sized lexicons to signifi¬ 
cantly reduce the number of words that 
must be manually checked. 

The choice of a sequential lexicon 
is a tradeoff between coding complexity 
and speed. An indexed lexicon would 
allow lookup of each word as it is isolated 
from the text but would mean vastly 
more complex code and more difficult- 
to-maintain lexicons. 


Word Isolation 

Two tables in the Speller control the 
isolation of words. A character of text 
is classified as a delimiter if it is in the 
DELIMIT table or as a part of a word if it 
is in the ALPHA table. If the character is 
not in either table, it is ignored. When a 
delimiter byte is located the resulting 
word is added to the word list. 

This two-table arrangement allows 
considerable flexibility in determining the 
nature of words and special word proces¬ 
sor control characters are easily elimi¬ 
nated. 

The word list is built in the available 
memory so its size is dependent on the 
hardware configuration. There are 4 bytes 
of control information associated with 
each word. A flag byte indicates the 
status of the word (spelled correctly, 
printed, last word in the list) and a length 
byte gives the length of the word. A two- 
byte chain pointer is maintained to the 
next in the list. When the word list is built 
the chain pointer is to the next word in 
the list and is redundant. However, be¬ 
fore the lexicon is scanned, 27 separate 


42 


Dr. Dobb’s Journal, Number 66, April 1982 

T75 





chains are built in the word list. Each 
word is put on the chain associated with 
the first letter of the word (the 27th 
chain is for all non-alphabetic charac¬ 
ters). 

The word list can be printed in the 
order it was built using the length infor¬ 
mation associated with each word, and 
can be scanned as 27 separate chains, 
with the chosen chain being the one as¬ 
sociated with the first letter of a particu¬ 
lar lexicon word. This technique of parti¬ 
tioning the word list cuts the scan time 
considerably. For small text files the time 
required to proofread is limited by the 
time required to scan the lexicon. For 
larger text files, the building of the word 
list becomes the limiting factor. As long 
as the word list does not become too 
large there is no serious problem, but 
when the word list approaches 1000 
words (a very “full” vocabulary) the 
search time to determine if the word is 
already in the list can become rather 
lengthy. 


Timings 

Since the lexicons are scanned se¬ 
quentially from beginning to end, a long 
time is required to check the spelling of a 
small text file. However, the time increases 
slowly for larger text files. The times 
given in Table 1 are for a 4 megahertz 
Z80 NorthStar computer with floppy 
disks. Only a single lexicon (33,000 
words, 162,000 bytes compacted) was 
scanned for these timings. 

Since at the time the word list is 
scanned it is divided into chains for each 
letter of the alphabet, the time required 
to scan the word list is dependent on the 
number of chains. If most of the words 
begin with the same letter, the scan time 
will be longer than if the words are evenly 
distributed on 26 chains. 

When this Speller was directed to 
scan its own lexicon as a text file, the 
weakness of its simplicity became obvi¬ 
ous. Each of the 33,000 words is, of 
course, distinct and only 3500 of them fit 
in the memory available on my 64K 
North Star computer. Each pass required 
more than 40 minutes to complete and 9 
passes were required. Such an extreme 
case should not be the criterion for design 


File size in bytes 

Figure 1 

Number of words 

Time in Minutes 

7 

1 

2 

3600 

250 

2.6 

9200 

456 

2.6 

8200 

448 

2.7 

24000 

690 

4 


Summary 

This Speller is both functional and 
provides the basis for much more com¬ 
plex programs. With very few exceptions 
no information is carried around in regis¬ 
ters so the addition of new functions is 
easy. The addition of word-structure 
analysis routines would increase the effec¬ 
tiveness of small lexicons by making pos¬ 
sible the recognition of root words with 
standard suffixes and prefixes. Only the 
root words would be in the lexicon. The 
addition of an “indexed” lexicon would 
make possible the correction of words as 
the text is being read. Spelling correction 
is possible if a “nearness” function is sub¬ 
stituted for the simple exact match. 

It is clear there is no mystery associ¬ 
ated with the problem of proofreading a 
text file. There are as many ways to or¬ 
ganize the program and the lexicon files 
as there are programmers and this pro¬ 
gram illustrates only one of these organi¬ 
zations. The principles behind this pro¬ 
gram were those of simplicity, ease of 
programming, and flexibility. 

For those interested, I can supply 
machine-readable source on a North 
Star Double Density disk or on an 8-inch 
single density (IBM standard) disk for 
$10. A 33,000-word compacted lexicon 
is also availabe in the same formats for 
$30. 

(Listing begins on page 46) 


of a particular program. 


Dr. Dobb’s Journal, Number 66, April 1982 
T76 


43 



Spelling Checker (Text begins on page 42) 


. z 80 

; Poor Person's Spelling Checker 

; Released for NON COMMERCIAL USE ONLY 
i (c) 1981 Alan Boiberger 

; The input Tile is checked using the lexicon 
; files and aisspelled lords are printed in the 

; order they appear in the text. 

i 

; Each lexicon is scanned for each lord list 
; and lay be in any order. 

; The lord list lill fill all available leiory so 

; only very large docuients Mill require lore than 
; one pass of the lexicons. 


boot 

equ 

0 

bdos 

equ 

s 

pstring equ 

9 

rstring equ 

10 

conout 

equ 

2 

openf 

equ 

IS 

dosef 

equ 

16 

readf 

equ 

20 

setdia 

equ 

26 

cr 

equ 

Odh 

If 

equ 

Oah 

bell 

equ 

07h 

fcb 

equ 

05ch 

f cb2 

equ 

06c h 

buffi 

equ 

080h 


spelit: 



Id 

sp,stack ; 

a nei stack pointer 

Id 

de,copyr 


call 

print 


call 

openin ; 

open input files 

call 

zchn ; 

zap chains 

buildl: 



call 

giord ; 

get the next lord of text 

jr 

c,endin 

no lore left, check spelling 

call 

search 

see if in lord list 

jr 

nc,buildl 

yes it is 

call 

addi 

no, so add it in 

» 

j •lork" 

contains the address of the last lord 

; put into the lord list. 

See if this lord is passed the 

; threshold of leiory 


call 

coipare 


jr 

nc,buildl ; 

no so continue 

Id 

hl,nundc+2 

■ark as incoiplete 

Id 

thI),T 


call 

spell 

check the current list 

call 

ptable 

print the aisspelled lords 

Id 

ix,coiMdl 

the last of the canon lords 

set 

iflgsl,(ix+if1gs 

; lark this as the last 

Id 

c,6 


Id 

b, 0 


Id 

de,nund 


Id 

hi,zcount ; 

zero counter 

ldir 



call 

zchn ; 

zap chains 


jr 

endin: 

buildl 

; and get next lord 

call 

spell 

; check the spelling of lords in list 

call 

ptable 

; print the ones not in lexicon 

call 

dosein 

; close up input file 

jp 

boot 

j return 


I 

; coipare 


; coapare 

the value in 

lork lith 'endiei* 

coipare: 



Id 

hi, lor k 

; address of last lord 

Id 

a, (endiei) 

; end of leiory 

sub 

(hi) 


Id 

a, (endiei+1) 


inc 

hi 


sbc 

a,(hi) 

; double precision subtract 

ret 



! 

; openin 



> 

; open input Hit and 

locate end of mory 

i 

openin: 



Id 

de,fcb 

; input file 

call 

open 


Id 

de,ninput 

j in case not there 

inc 

a 


jr 

z, failed 

; no file 

Id 

a, 128 


Id 

(ibp),a 

; set so first call gets disk record 


! 

; find end of aeiory 


i 


Id 

hi,(6) 

; address of bdos 

Id 

be,64 

1 a targin 

or 

a 

; clear carry 

sbc 

hi,be 

; subtract largin 

Id 

(endaei),hl 


ret 



failed: 



call 

print 


jP 

boot 

; quit noi 

! 

; giord 

get next lord 

in text into ciord 

» 

; carry flag on leans end of input 


i 


giord: 


Id 

a, 128 


Id 

(cflags) ,a 

; set this lord as last 

Id 

de, 0 

; length of lord 

giordl: 



call 

gbyte 

j get next byte of text 

jr 

c,giorde 

; end of input 

Id 

be,(deliil) 

) length of deliiiter table 

Id 

hi,deliit 

; the table 

cpir 


i is it a deliiiter 

jr 

z,delii 

! yes 

Id 

be,(alphil) 


Id 

hi,alpha 

; is it alphabetic 

cpir 



jr 

nz,giordl 

; no skip it 

cp 

V 

1 is it loier case 

jr 

c.oiordu 

: no 


46 


Dr. Dobb’s Journal, Number 66, April 1 982 

177 







gwordus 


del it: 

gworde: 

gwordt: 


I 

gbyte: 


gbytel: 


gbyter: 


i 

i 


cp 

■{■ 

j lower 

; seard 

is the entry when 

searching on a chain 

jr 

nc,gwordu 


i 



and 

03fh 

; lake all upper case 

1 

search: 



Id 

hi,cword+4 

1 place to build word 

Id 

ix,words ; 

start of list 

add 

hi, de 


search 


entry if starting with chain 

Id 

(hi),a 

; put byte in word 

sloop: 



inc 

e 

; new length 

Id 

a, (den) ; 

length of current word 

Id 

a.e 


cp 

(ix+wlen) 

■ust be sale as list entry 

Id 

(den),a 

; update in word entry 

jr 

nz,nextw ; 

try next entry 

cp 

30 

; how long is word 

call 

dc 

coipare 

jr 

z,gwordt 

; too long a word 

jr 

z,latch ; 

it is a latch 

jr 

gwordl 

; loop 

nextw: 



Id 



bit 

wflgsl,(ix+wflgs) 

; is this last entry 

a,e 

i current length 

jr 

nz,match 

yes then no latch 

CP 

0 


Id 

a,(ix+wchn) j 

get chain pointer 

jr 

z,gwordl 

; skip leading delimiters 

Id 

(work),a 

or 

a 

; zero carry flag 

Id 

a,(ix+wchnl) j 

both parts 

ret 



Id 

(work+1),a 




cp 

0 1 

this is high order (never zero 

Id 

de,lngwdl 


jr 

z, match 

end of chain 

j first part of text 

Id 

ix,(work) 


call 

print 


jr 

sloop 


Id 

de,cword+4 


latch: 


call 

print 


or 

a ; 

clear carry 

Id 

de,lnglx2 

; second part 

jr 

sret 

call 

print 


match: 


or 

a 


scf 

. 

set carry 

jr 

gworde 


srit: 



getbyte 


ret 


get next byte of text 
carry flag on for end of file 


push 

de 


Id 

a,(ibp) 


cp 

128 

; do we need another buffer full 

jr 

nz,gbytel 

; no 

Id 

de,fcb 


call 

diskr 

; read a block 

cp 

0 

i did it ok? 

scf 


; in case not 

jr 

nz,gbyter 

; end of file return 

Id 

e,a 

i has current byte index to fetch 

Id 

d, 0 

; double precision 

Id 

hi,buffi 


add 

hi, de 


inc 

a 

; next index 

Id 

(ibp),a 


Id 

a, (hi) 

; get byte 

CP 

Olah 

; check for end 

scf 


; in case it is 

jr 

z,gbyter 

i y« 

or 

a 

I clear carry flag 


pop de 
ret 

search 

search word list for latch with cword 

on return ix will point to latched entry or last in list 


carry on if no latch 


cl c 


dc: 


del: 


dee: 


i 


addw: 


coipare logical character 

cword with list entry pointed to by ix 

a contains length 


push 

ix 


Id 

c,» 

; length for down count 

Id 

hi,cword+4 

j coipare here 

Id 

a, (ix+word) 

i first character 

cp 

(hi) 

i is it 

jr 

nz,dce 

; no stop 

inc 

hi 


inc 

ix 


dec 

c 


jr 

nz,clc 1 

; not end so continue 

pop 

ix 


ret 



addw 




add word to list 

word is in cword and ix points to last entry 


Id 

(work),ix 

; save 

Id 

iy,(work) 

; old position 

Id 

a,0 


Id 

(cchn) ,a 


Id 

(cchnl).a 

j 2 ero chain pointer 


res 

wflgsl,(ix+wflgs) 

; clear this is last entry flag 

Id 

b, 0 


Id 

a, (ix+wlen) 

; get length of last word 



(Continued on next pag 


Dr. Dobb’s Journal, Number 66, April 1982 
178 


47 







Spelling Checker (Listing continued, text begins on page 42) 


add 

a,4 


Id 

c.» 

; include chain and stuff 

add 

lx,be 

; skip over last entry 

Id 

(work), ix 


Id 

a,(work) 

; get low byte 

Id 

(iy+wchn),a 

; to chain 

Id 

a,(work+1) 


Id 

(iy+wchnl>,a 

; to chain 

Id 

a, (den) 


add 

M 


Id 

c,a 


Id 

hi,cword 

; source 

Id 

(work),iw 


Id 

de,(work) 

; cant get there froi here 

ldir 


; love it 

call 

countw 

; buap count 


ret 

spell 

check each lexicon word with list entries 
■ark correct (found) words in list 


Id 

a,(work+1) 


cp 

0 


jr 

z,spel 11 ; 

if zero no words this letter 

call 

seard ; 

look for word in chain 

jr 

c,spel 11 ; 

did not find it 

set 

wflgsc,(ix+wflgs! 

; lark spelled correctly 

jr 

spel11 ; 

and loop 

Id 

dr,1fcb j 

close 

call 

close 


jr 

nextlex g 

get another lexicon 

Id 

de,buffi ; 

reset d*a 

cal 1 

setbuf j 

in case lore input 

ret 



getlex 




pet a lexicon file froi the custoier 

if none requested (null input) return with carry flag on 


getlex: 


spell: 

Id de,nuiwd 

call print 

call setchn 

Id de,buff2 

call setbuf 

nextlex: 

call getlex 

jr c,spe!lr 

Id de,1fcb 

call open 

Id de,nolex 

inc a 

jp nz,gotlex 

call print 

jr nextlex 

gotlex: 

Id de.lfcb 

call diskr 

cp 0 

jr nz,endl 

Id de,check! 

call print 

Id a, 0 

Id (ibpl),a 

Id (coip),a 



Id 

de,asklex 



call 

print 

; type proipt 


call 

answer 

; get answer 

infori of nuiber of words 

jr 

c,getlxr 

; return . no lexicon 

set up chains 

call 

bldfcb 

; build a new feb 

switch buffers 

get a lexicon file 
none so return 
get lexicon file 

or 

getlxr: 

ret 

5 

; answer 

5 

a 

; clear carry flag 

in case not there 

; get answer to question 

J 

answer: 

in buff2 

it is a valid lexicon 

Id 

de,buff 2 


it is not a valid lexicon 

Id 

a,80 


try again 

Id 

(buff 2),a 


lexicon feb 

call 

input 

; get answer 

Id 

a,(buff 2+1 

; get length of answer 

read first record 

cp 

0 

; see if any 

did it 

scf 


; none 

quick exit 

jr 

z,answrt 

; quit now 

tell custoier 
that we begin 

say not compacted 

or 

answrt: 

ret 

a 

; clear carry flag 


Id 

CP 

a, (buff2) 

Offh 

g first of coipacted 

1 

; bldfcb 



jr 

Id 

nz,spel11 
a, 1 


1 

; build an feb froi information in buff2 

Id 

(coip), a 

; set coipacted 

; assuie 

file type of .LEX 


Id 

(ibpl) ,a 

; skip ff 




call 

lword 

; get a word in cword 

i 

bldfcb: 



jr 

c,endl 

; end of lexicon 

Id 

hi,deffcb g 

the default feb 

Id 

ix,cword 


Id 

de,Ifcb ; 

goes here 

call 

getchn 

; get correct chain for this word 

Id 

be,16 ; 

•ove this iuch 

Id 

e,(hi) 

; low order byte 

ldir 


love it 

inc 

hi 


xor 

a ; 

get a zero 

Id 

d, (hi) 

; hiqh order byte 

Id 

(lfcbcr),a ; 

zero this as well 




Id 

hi,buff2+2 


Id 

(work),de 

; get first word in list 

Id 

a,(buff2+1) g 

get nuiber of bytes in naie 

Id 

ix,(work) 

g place to start 

Id 

c.» ! 

b is zero froi block love 


48 


Dr. Dobb’s Journal, Number 66, April 1982 

T79 








bllcsp; 



Wordu: 


Id 

a,(hi) 

; get a byte 

Id 

hl,cnordM 

cp 

« . 

; is it a blank 

add 

hi, de 

jr 

nz,noblk 

; no 

Id 

(hi),a 

inc 

hi 


inc 

e 

dec 

C 


Id 

a,e 

jr 

nz, bl 1 oop 

; skip leading blanks 

Id 

(den),a 

jr 

bldret 

; return with bad fcb 

cp 

30 

noblk: 



jr 

z, Wordt 

inc 

hi 

; skip disk naee if present 

jr 

Wordl 

Id 

a, (hi) 

1 get suspected V 

Worde: 


dec 

hi 

j back to first character 

Id 

a.e 

cp 

• , ■ 

; is it a disk naee 

cp 

0 

jr 

nz,nodsk 

; no just a naee 

jr 

z, Wordl 

Id 

a,(hi) 

; get disk naee 

or 

a 

and 

Ofh 

; to cp/e standards 

Wordr; 


Id 

(lfcbdn) , a 

; to fcb 

ret 


inc 

hi 


Wordf: 


inc 

hi 

; skip naee and 

scf 


dec 

c 


jr 

Wordr 

jr 

z,bldret 

; quit ttith bad fcb 

Wordt: 


dec 

c 


Id 

de,1nglx 1 

jr 

z,bldret 

; quit Hith bad fcb 

call 

print 

nodsk: 



Id 

de,cnord+( 

Id 

de,lfcbfn 

; place for naae 

call 

print 

Id 

a,a 

; tax length at this point 

Id 

de,lng!x2 

cp 

c 

; are ne ok 

call 

print 

jr 

c,bldret 

i no so leave blank 

or 

a 

filelp: 



jr 

Wordr 

Id 

a,(hi) 




cp 

■ ■ 

; this is end We ignore) 

i lchar 


jr 

z,bldret 




cp 

a a 

; also end 

; get a 

character froe 

jr 

z,bldret 

; and this 

i 


cp 

"a" 

; loner case alpha 

lchar: 


jr 

c.filell 

; no 

Id 

a, (coep) 

and 

05fh 

; aake upper 

cp 

0 

filei 1 1 



jr 

nz,lcharc 

Id 

(da) , a 

; put in fcb 

call 

lbyte 

inc 

de 


ret 


inc 

hi 


1 


dec 

c 


lcharc: 


jr 

nz,filelp 

; loop 

call 

gnib 

bldreti 



jr 

c,lchare 

ret 



cp 

Ofh 

» 



jr 

z,lchars 

; 1 word 



Id 

c, 16 

J 



Id 

hi, 11 

; get a lexicon word 




; carry flag on if end of lexicon 

cp 

c 

1 



jr 

nc,lchare 

Word: 



Id 

b, 0 

Id 

de, 0 

; length of nord 

Id 

c, a 

Wordl: 



add 

hi,be 

call 

lchar 

; get char froi file 

jr 

lcharg 

jr 

c, Wordr 

i if end 

lchare: 


cp 

If 

; skip these if present 

Id 

de,badlex 

jr 

z,Wordl 


call 

print 

CP 



scf 


jr 

z, Wordl 

i skip blanks in lexicon 

ret 


cp 

cr 

; end of nord 

lchars: 


jr 

z, Worde 

; done 

call 

gnib 

CP 

Olah 

; end 

jr 

c,lchare 

jr 

z, Wordf 

i set carry and return 

Id 

c,U 

CP 

V 

j loner case? 



jr 

c, Wordu 

; no, upper 



CP 

■C 


Id 

hi ,t2 




jr 

lcharl 




lcharg: 


jr 

nc, Wordu 


Id 

a,(hi) 

and 

05fh 

; eake sure upper case 




Dr. Dobb’s Journal, Number 66, April 1982 

T80 


; place to put it 

; build nord 
; buep count 

; hon long 
; too long 
; get tore bytes 

; check for null nord 
; any so far 
; no so continue 
j clear carry 


i return 
S first part 


; second part 


lexicon (compacted or not) 

S is it compacted lexicon 
i uell? 
i yes 

; no get a byte 
i and return 


; get a nibble 
; end already 
; is it flag 

i yes second set of letters 
; size of table 
; in table one 

; too big 


; got it 


; say end of lexicon 


; search length 


; loop here 


(Continued on next page) 


49 




Spelling Checker (Listing continued, text begins on page 42) 



or 

a 

j clear carry 


ret 




gnib 




get a nibble froi coipacted lexicon 

gnib: 

Id 

a, (lrnib) 



cp 

1 

i left or right 


jr 

z,gnibr 

; right 


Id 

a, 1 



Id 

(lrnib),a 



call 

lbyte 

1 git a byte 


jr 

c, gnibr 

1 report carry 


Id 

(byte),a 



srl 

a 



srl 

a 



srl 

a 



srl 

a 

; put left in lower 


or 

a 

i clear carry 


ret 



gnibr: 

Id 

a, 0 



Id 

(lrnib),a 



Id 

a, (byte) 



and 

Of It 



ret 



i 

5 

lbyte 




I 

; get a byte froi lexicon tile 


i carry flag on for end of 

file 

i 

lbyte: 



push 

de 


Id 

a,(ibpl) ; 

! get buffer pointer 

cp 

128 

; at end 

jr 

nz,lbytel ; 

; no 

Id 

de,Ifcb 

; fcb for lexicon 

call 

diskr 


cp 

o 

; did it work 

scf 


i in case not 

jr 

nz,lbyter 

! return with carry if end 

lbytel: 



Id 

e,a 

; position in buffer 

Id 

d, 0 


Id 

hi,buff2 


add 

hi, de 

j correct byte 

inc 

a 

1 for next tiie 

Id 

(ibp 1), a 


Id 

a,(hi) 

; get the byte 

or 

a 

; clear carry flag 

lbyter: 



pop 

de 



ret 

; ptable 

; print aisspel 1 ed words tro* list 

I 

ptable: 


Id b,0 

Id ix,words ; start 


50 


ptloop: 



bit 

wflgsc,(ix+wflgs) j is this one correct 


jr 

nz,pnext j yes don’t print it 


call 

pword ; print the word 

pnext: 


bit 

wflgsl,(lx+wflgs) 


jr 

nz,ptabr 


Id 

a,(ix+wlen) ; get length this entry 


add 

a,4 


Id 

c,a 


add 

ix,be 


jr 

ptloop ; try again 

ptabr: 

1 

i 

ret 

pitord 


5 

J 

print word pointed to by ix 

pword: 


push 

ix 


Id 

b,(ix+Mlen) 

puloopi 


Id 

e,(ix+word) ; a character 


push 

be 


call 

pchar 


pop 

be 


dec 

b 


jr 

z,crlf 


inc 

ix j next character 


jr 

peloop 

crlf: 


Id 

e,cr 


call 

pchar 


Id 

e,H 


call 

pchar 


pop 

ix 


ret 


i 

5 

count 

words 


countw: 

Id 

hi,nuewdc 

; get lowest byte 


Id 

a,' 

j a test for too large 

countl: 

inc 

(hi) 



cp 

(hi) 

; see if too big 


ret 

nz 

; no 


Id 

(hi),"O' 

i yes set to 0 


dec 

hi 



jr 

countl 

; backup and try again 

» 

\ 

zchn 



» 

J 

zero 

chain headers 


) 

zchn: 

Id 

a, 0 

; get a zero 


Id 

c,054d 

; nuiber 


Id 

hi,alphe 

i place 

zchnl: 

Id 

(hi),0 



inc 

hi 



dec 

c 



Dr. Dobb’s Journal, Number 66, April 1982 

W 








jr nz,zchnl 
ret 

getchn 

get address of chain head of word pointed to by ix 


dosein: 

id de,fcb 
call close 
ret 


getchn: 


getcha: 


chnothi 


! 


open: 





Id 

c,openf 

Id 

a, (ix♦word) 

i first char 

jp 

bdos 

Id 

b, 0 




Id 

hi, alphc 

; first chain head 

close: 


cp 

’ft’ 

i first 

Id 

c, cl osef 

jr 

c,chnoth 

; lower use other 

jp 

bdos 

cp 

’[’ 


print: 


jr 

nc,chnoth 

j greater use other 

Id 

c,pstring 




jp 

bdos 

and 

Olfh 

; eask 



dec 

a 







diskr: 


sla 

a 

; double it 

Id 

c,readf 

Id 

add 

c,a 
hi,be 

; displacement 

jp 

bdos 

ret 



pchar: 





Id 

c,conout 

Id 



JP 

bdos 

jr 

getcha 

; use last chain 

setbuf: 





Id 

c,setdaa 

setchn 



jp 

bdos 




input: 


scans word list and rechains it by letter 

Id 

c,rstring 




jp 

bdos 


» 


setchn: 



Id 

ix,words 

; place to start 

setchO: 



call 

getchn 

; get the correct he. 

Id 

4.0 

; get a zero 

setchl: 



inc 

hi 

; to high order byte 

cp 

(hi) 


jr 

nz,nxtchn 

1 not this one 

Id 

(work),ix 

; goes here 

Id 

de,(work) 

; get it 

Id 

(hi),d 


dec 

hi 


Id 

(hi), e 


Id 

(ix+wchn),a 

; zero forward 

Id 

(ix+wchnl),a 


jr 

setchn 

; next word 


nxtehn: 



Id 

d, (hi) 


dec 

hi 


Id 

e, (hi) 


ex 

de,hl 


inc 

hi 


inc 

hi , 

to chain portion 

jr 

setchl 


setchw: 



bit 

wflgsl,(ix+wflgs) 


jr 

nz,setchr j 

return 

Id 

a,(ix+wlen) 


add 

».< 


Id 

C.4 


Id 

b, 0 


add 

ix,be 


jr 

setchO 


setchn 



ret 




ds &4 

stack: ds 1 

endiea: ds 2 

dtffcb: db 0," LEX 1 ,0,0,0,0 

lfcb: ds 33 

lfcbcr equ lfcb+32 

lfcbex equ lfcb+12 

Ifcbsl equ lfcb+13 

Ifcbs2 equ Ifcb+14 

lfcbrc equ Ifcb+15 

lfcbdn equ lfcb*0 

lfcbfn equ lfcb+1 

lfcbft equ lfcb+9 

ibp: ds 1 

ibpl: ds 1 

work: ds 2 

byte: ds 1 

lrnib: db 0 

coap: db 0 

buff 2: ds 128 

zcount: db "0000 " 

nuawd: db "0000 distinct words in text",cr,If,*** 
nuewdc equ nuawd+3 

lnglxl: db "lexicon word 

lnglx2: db *’ longer than 29 characters',cr,If,"4" 
lngwdl: db "text word 

badlex: db "error in compacted lexicon",cr,If 

ninput: db "input file not specified or non-existant",cr,1f,"♦" 
nolex: db cr,If,"lexicon file not specified or non-existant",cr,lf,"<" 
checks: db cr,If,"begin spelling check pass",cr,If,"I" 
asklex: db "enter lexicon file naee (.LEX assused) or ’return’* 

db bell,cr,If,"I" 

copyr: db cr,If,"Poor Person Speller (c) 1981, Alan Bosberger" 

db cr,lf,cr,lf,"»" 

cwords ds 34 

db "»" 

cflags equ cword 

(Listing continued on page 53) 


Dr. Dobb’s Journal, Number 66, April 1982 
182 


51 



Spelling Checker 


(Listing 

continued, text begins on page 42) 

den 

equ 

cword+1 

cchn 

equ 

CNord+2 

cchnl 

equ 

CMOrd+3 

Nilgs 

equ 

0 

Mien 

equ 

1 

Nchn 

equ 

2 

MChnl 

equ 

3 

Hord 

equ 

4 

Nflgsl 

equ 

7 

Hflgsc 

equ 

6 

Mflgsp 

equ 

5 

deliit; 

db 

!?[] /’{>-■,cr,H,34,9, 'V 


db 

0,0,0,0,0,0,0,0 

delill: 

db 

del ill-delilt-8,0 

alpha: 

db 

“ ABCDEFGHI JKLHHOPflRSTllVMXYZ' 


db 

'abcdefghijklinopqrstuvwxyz* 


db 

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 

alphal: 

db 

alphal-alpha-20,0 

tl: 




db 

’EISNATR’ 


db 

’0LDCU6P’,cr 

t2: 

db 

’HHBYFVK’ 


db 

’KZXBJ’,01ah 

alphc: 

ds 

54 

Nords: 



coiMdl: 




db 

192,1,0,0,“A 1 


end 

spent (End Listing) 


Dr. Dobb’s Journal, Number 66, April 1982 


53 

183 




Son of Runic 

Writing the Compiler 


I n my last article, “Runic: An Interac¬ 
tive, Extensible Compiler” (DDJ # 65), 

I described a FORTH-like program¬ 
ming language called Runic. It featured 
high-level data types, a dictionary that al¬ 
lowed forward-referencing definitions, 
and Pascal-like logic structures. I deliber¬ 
ately kept implementation details out of 
that article because when I set to work 
I did not have a specific computer in 
mind — all I knew was that I wanted a 
language very much like Runic for my 
own use. 

After laying out specifications for 
the language more or less as they ap¬ 
peared in my last article, I began to de¬ 
velop Runic in July of 1979 on my PET 
computer. After months of futilely trying 
to write the tools I needed — such as a 
text editor and assembler—I sold the 
PET and bought a CP/M-based system in¬ 
stead. The PET may be fine for some 
things, but language development isn’t 
one of them. 

CP/M, despite its expense, gave me 
the development environment I needed. 
With my choice of tools made, my next 
step was to write a BASIC model of the 
compiler. Doing so, I felt, would not only 
help make me more familiar with CP/M 
but would identify problems early on in 
my development effort. That it did, but 
before writing a model I had to settle 
on a design approach. Two were worth 
considering: 

1. I could make Runic a “pure inter¬ 
preter,” directly executing source 
code. This would be slow, but simple. 
There’s also no need for a decompiler 
to make listings, since the source code 
is always kept around. 

2. I could make Runic a “compiler/ 
interpreter,” like most BASIC’s, com¬ 
piling source lines into an intermediate 
object language first and then inter¬ 
preting that. This would make Runic 
run much faster, but the compiler 
would be more complicated. In addi¬ 
tion, you need a decompiler function 
to get the source code back again. 

It wasn’t until I tried to add struc¬ 
tured logic blocks to the pure interpreter 
that I realized I would have to use the 
other design instead — not only was re- 


by Marty Franz 


Copyright © 1981 by Marty Franz, 525 
W. Walnut St., Kalamazoo, MI 49007. 


peatedly executing blocks of source code 
quite slow, but just scanning them was 
expensive, since you had to find the end 
of the block each time you evaluated a 
conditional, independent of whether the 
block was executed or not. 

Once this decision was made, I set to 
work. I invested a weekend writing 
BASIC models of the compiler and inter¬ 
preter, and ran some test cases through 
them. The models provided useful infor¬ 
mation, especially in the area of compil¬ 
ing the “if” and “do” logic blocks. 

After I had written the “toy” version 
of the compiler, I was ready for the real 
one. I needed a good high-level imple¬ 
mentation language — assembler, I felt, 
would be too slow to develop in. At the 
urging of my friends I tried C, and was 
hooked. It was easy to use, efficient and, 
best of all, the source code was quite 
readable. 

From September, 1980, through 
April, 1981, I wrote Runic’s compiler, 
mostly on weekends and at night. At the 
Sixth West Coast Computer Faire I 
brought along (and more or less gave 
away) demo versions. A production ver¬ 
sion is now for sale from Starside Engi¬ 
neering. It runs on any 48 K or larger 
CP/M system and features over 100 
words, a demo package, and a manual. 

In its present form, the Runic com¬ 
piler has these major components: 

1. A small driver that reads source state¬ 
ments from either the CP/M console 
or an input file and calls, in turn, the 
compiler and executive described be¬ 
low. This is a fairly simple function 
and will not be covered further in this 
article. 

2. The compiler that builds a string of 
object codes out of the statement. 

3. The executive that performs the ac¬ 
tions specified by the opcodes. 

4. Kernel functions called by the execu¬ 
tive that control the stack, condition 
flag, and dictionary. 

Figure 1 shows how each piece re¬ 
lates to the other. Now we’ll look at each 
component in more detail. 

The compiler conducts the scan of 
a user’s statement, building a set of ob¬ 
ject codes which are then executed by the 
executive. 

The compiler first tokenizes the en¬ 
tire line of Runic source. A “token” is 
either a word in the dictionary, a numeric 
constant, or a quoted string. For the lat¬ 
ter two token types, codes are generated 
to push the data onto the stack, and the 


constant data is copied directly to the ob¬ 
ject line. 

Otherwise, the dictionary is searched. 
Every entry in the dictionary has these 
four fields: 

1. The word’s name, converted to lower 
case and no more than 8 characters 
long. 

2. A flag that tells what type of word it 
is: number, string, kernel, or user 
definition. 

3. An address pointer to a function 

called when the word is executed; or, 
for numbers, the value of the number 
itself, stored as a two-byte integer. 

4. An address pointer to a function 

called when the word is compiled. This 
pointer is used for words like “if” and 
“do” that require extensive processing 
at compile time. 

If the current word is found in the dic¬ 
tionary, then the compile-time function 
for it is called (if it exists) or else a one- 
byte index to the entry is placed in the 
object code. Allowing one byte for the 
index means that 255 entries can be 
present in the dictionary at one time. 

If the word wasn’t found, and the user 
was defining a new word, then a dummy 
entry is created. This scheme allows 
for forward references — at some later 
time a new execution address can be 
filled in and the original definition will 
remain unchanged. And this is the reason 
one-byte object indexes are used — they 
remove the object code a step from the 
dictionary’s structure, allowing words to 
be re-defined later. 

If an assignment operator (“A”) was 
in front of the word, then an extra code 
is generated to tell the executive to pop 
the top of the stack into the word during 
execution. 

Internal stacks are maintained by the 
compiler to keep track of the relative 
branch locations for “if” and “do” 
blocks. Relative branches are generated 
rather than address branches so that a 
definition can be moved around and 
copied in object form. This, and a dic¬ 
tionary index rather than a direct address 
being used as the object code, lets each 
dictionary entry be a separate entity that 
may be replaced or deleted independently 
of the others. 

After a line has been compiled, it’s 
marked with another index that tells its 
length. This is so that error tracebacks 
and listings can be built from just the ob¬ 
ject code and the name of the word kept 
in the dictionary. Since only a user defini- 


54 


Dr. Dobb’s Journal, Number 66, April 1982 




Console Driver 

1 




Compi1er 


Executive 






Kern 

Funct 

el 

i ons 


Figure 1. 


A Block Diagram o-f Runic 



Figure 2. Runic’s Memory Map 


tion’s object code is stored, this small 
code overhead is necessary to preserve a 
source line’s integrity. Comments, if used, 
are stripped off during compilation and 
not saved with the object, as they are in 
BASIC. If commented source is needed, it 
can be kept on disk, then read and re¬ 
compiled when the definition is needed. 

If compilation of a direct statement 
was successful, the object code is exe¬ 
cuted immediately. On the other hand, if 
the user was defining a new word with 
the code is saved as part of the 
word’s dictionary entry and linked via the 
execution-time function pointer. In defi¬ 
nition mode, lines are entered and com¬ 
piled until the user types at which 
point the complete entry is added to the 
dictionary as a new definition. 

The executive takes over from the 
compiler, executing the object line. It 
uses the object codes to locate and call 
successive execution-time functions. Exe¬ 
cution proceeds until a “return” word is 
reached (this has a special object code of 
zero) or until an error occurs. 

The executive is started only after 
a direct statement is entered, not a defini¬ 
tion. It is called recursively (an advantage 
to writing the compiler in C instead of 
Assembler) for each user definition called 
with that definition’s execution-time ad¬ 
dress as the new program counter. It runs 
through object codes until a flag is set 
telling it to stop. This flag is set in one of 
three ways: (a) by executing a “return” 
word; (b) by Runic’s error handler (such 
as on a stack overflow); or (c) by the user 
pressing ESC (the break-in key). After 
the executive is stopped, it decides 
whether a traceback is required. 

If a traceback is needed (all errors 
that occur at execution time produce 
one) then the exeuctive uses the marker 
at the end of the current line to deter¬ 
mine the start of the erroneous state¬ 
ment. It then calls the rebuilding function 
to display it at the user’s console. 

An example of an error traceback is 
shown in this example: 

> “hi” 2 + say . 

— Wrong type of data 

— At: “hi” 2 + say . 

Here, the user tried to add a number and 
a string together, hence the Wrong 
type of data” message. The rebuilding 
function is also used to display user defi¬ 
nitions through the “show” word, men¬ 
tioned in the last article. This capability 
is important in Runic, since it helps users 


Dr. Dobb’s Journal, Number 66, April 1982 


55 

185 















list and revise definitions without the 
need for a source editor. 

Providing a break-in key is another 
important function of the executive. 
After each opcode is executed it checks 
CP/M’s console input port to see if ESC 
has been pressed during the last instruc¬ 
tion. If so, the executive is halted and a 
trace message displayed. This lets the user 
interrupt a wayward program to check 
the stack or its variables. 

In order to perform the actions speci¬ 
fied by the user in his statement, the 
executive calls kernel functions. These 
alter the state of the Runic machine: they 
push and pop stack data, set the condi¬ 
tion flag, and control branching. Each 
kernel function, when called, is passed 
the current program counter. A kernel 
function’s single interface requirement is 
that it alter this program counter in some 
way prior to returning to the executive 
so that execution can continue. 

New kernel functions are added to 
the dictionary by the “kernel” word. 
This is actually a small loader called by 
the executive with the name of a CP/M 
file on top of the stack. The CP/M file 
contains the kernel function in relocat¬ 
able format. The “kernel” word reads this 
new function in, relocates it, and adds its 
name to the dictionary. Once loaded, the 
new kernel is available as part of the lan¬ 
guage and can be saved with the rest of 
the compiler. The kernel function makes 
procedure calls to push and pop stack 
data, and must correctly maintain the 
program counter in order to work 
properly. 

The stack itself is an array of three- 
byte entries. For numbers, the first byte 
contains a zero flag and the next two con¬ 
tain the actual integer value. For strings, 
the flag byte is non-zero and the next 
two bytes contain a pointer to the ad¬ 
dress where the string is stored. Stack 
limit- and data type-checking are done 
by the routines that directly push and 
pop data, with null values returned if an 
error is encountered. A local copy of a 
string is made whenever it is pushed on 
the stack - no attempt is made to lock 
or chain descriptors to cut down on 
copying. The stack (like the dictionary) is 
a fixed-size data structure allocated when 
the compiler is first generated. 

Free memory for strings and user 
definitions is managed in the compiler 
through the use of 32-byte “cells” 
maintained by a bit map. The technique 
is similar to that used to manage disk 


storage: requests for free memory are 
rounded to a multiple of the cell size and 
an area is allocated out of the bit map to 
meet the request. 

With this in mind, Runic’s memory 
map under CP/M looks like Figure 2: 
above the compiler’s resident code there 
is a fixed area containing the memory 
management bit maps, the dictionary, 
and the stack. On top of the fixed area up 
to the top of the TPA is a dynamic area 
used for user definitions, kernel func¬ 
tions, and strings. The size of this dyna¬ 
mic area is computed each time the com¬ 
piler is run, based on the amount of free 
memory available. 

What’s performance like? Runic pro¬ 
grams are about as fast as comparable 
ones written in BASIC. The compiler oc¬ 
cupies 24K bytes on CP/M. Another 4K 
bytes is used by the standard library, a set 
of frequently-used user definitions and 
utilities. 

To interface to the CP/M operating 
system, three I/O words, “read”, “write” 
and “close” have been included. They 
provide re-direction of console I/O to 
CP/M files. With them, a Runic user can 
develop programs interactively using the 
compiler, then save them on disk, where 
they can be accessed by any CP/M- 
compatible text editor. A “program” is a 
set of user definitions loaded or saved as a 
group. Development using Runic is 
particularly easy, since the user can code 
top-down or bottom-up as the problem 
demands. 

My present plan for Runic is to get 
the system to as many serious users as 
possible for their evaluation and feed¬ 
back. While not as efficient as FORTH, 
Runic does have features that make it 
attractive for teaching FORTH-like pro¬ 
gramming languages to novice users, such 
as its flexible dictionary structure, con¬ 
venient strings, break-in key, and error 
checking. A few sessions with Runic- 
might be a good learning experience for 
a hobbyist interested in going beyond 
BASIC programming but perhaps not 
quite up to tackling one of the excellent 
FORTH systems currently available. 

In addition to distributing the com¬ 
piler, I plan to enhance it with more error 
recovery, kernel words, and documenta¬ 
tion. I would appreciate suggestions on 
this from interested DDJ readers. At the 
very least, Runic shows that it is possible 
to develop serious software on today’s 


micros. I hope readers working on similar 
projects will take heart from this and con¬ 
tinue their own efforts. 


56 

186 


Dr. Dobb’s Journal, Number 66, April 1982 


SOFTWARE REVIEWS 


PIE 

Walt Bilofsky 
$29.95 from 
The Software Toolworks 
(Reader Service No. 451) 

Video Scribe 
Ron Rocheleau 
$39.95 from 
Newline Software 
(Reader Service No. 461) 

Reviewed by D. C. Shoemaker 


Today’s personal computer owner 
generally has at least one of three basic 
purposes in mind for his or her sys¬ 
tem. The primary one may be game 
playing (to which few will admit, but 
which is a powerful lure for me), data 
manipulation (keeping track of infor¬ 
mation for business or home use) or 
text processing of one kind or another. 

I don’t mean to exclude the systems en¬ 
thusiast, often referred to as a hacker, 
who may actually spend more time 
on implementation than on the use of 
a piece of software or hardware, but 
such folk frequently have something 
like these goals as their final objective. 
Regardless of your goal, one essential 
piece of applications software you 
need is an editor. Such programs are 
the subject of my comments, and 1 will 
compare two full-screen type editors 
currently available for the Heath H89 
computer (or H8 computer with H19 
terminal.) 

The editors are Walt Bilofsky’s PIE 
1.5 (The Software Toolworks #201 or 
Heath Softstuff SF-9000) and Ron 
Rocheleau’s Video Scribe Ver. 3.0. Both 
of these are termed full-screen editors, 
which means they give a “page” of text 
on the CRT’s screen with the ability to 
position the cursor anywhere on that page 
of text by using some form of cursor¬ 
positioning commands (usually generated 
by a special set of keys or a keypad on 
the terminal). Naturally, this feature may 
be implemented in a variety of ways, 
from the fairly clumsy and difficult to 
use (as with Heath’s distribution editor 
that comes with HDOS, or CP/M’s ED) 
to the smooth and logical, as in the case 
of PIE and Video Scribe (VS). 

In addition to a controllable cursor, 
a good editor should have an easy way to 
change the page being displayed. Both 
PIE and VS allow one to page ahead or 
backwards through the text (scrolling), 


either a line at a time or a page of 24 lines 
at a time. Both allow immediate return 
to the head of the file, but VS also allows 
one to drop to the end of the file with a 
single command. One can get there with 
PIE, but by entering an additional com¬ 
mand first. 

From this point on, we’re going to 
look at the special features one might 
consider “bells and whistles.” One could 
live and work without them, but they 
sure make the job easier. Both PIE and 
VS include the capability to insert a line 
or a character, and to delete a line or a 
character. Both allow moving blocks of 
text, selecting a paragraph to move from 
the middle of a file to the end, for in¬ 
stance. Both allow the destination disk to 
be replaced, thereby offering the chance 
to leave the original file intact as a back¬ 
up; and both will allow deletion of the 
old file should there not be enough room 
for both to be saved on the same disk, 
helpful for single-disk users. In both 
cases, if the disk has too little space, an 
error message is generated. Both display 
the amount of space remaining in RAM 
(but not on disk, as Auto-Scribe does). 

Both PIE and VS can be optimized 
for Z80 use — the former by virtue of 
providing two separate programs on the 
disk, one for the 8080 and one for the 
Z80; and the latter by a settable option. 
In the case of VS, another settable option 
is automatic word wrap-around (happi¬ 
ness is never having to hit RETURN). In 
PIE, you would enter CTRL-W to turn 
that feature on or off, but only in the 
Software Toolworks version 1.5b; Soft- 
stuff’s version and PIE 1.5 lack that en¬ 
hancement. 

PIE and VS both come with excel¬ 
lent written documentation; PIE requires 
about 11 pages, and VS about 13. In 
addition, the Softstuff version of PIE also 
comes with the printed documentation 
on disk as a test file, so the user can re¬ 
place the written copy or create an ab¬ 
breviated version for quick reference. 

Finally, what I consider the ultimate 
feature, essential to any editor, the ability 
to perform macro changes in the text file. 
This means that if Constantinople is 
spelled wrong in 87 places throughout 
the text, a one-line command will go 
through the file and replace the incorrect 
spelling with the correct one. Both PIE 
and VS allow one to look at each occur¬ 
rence to confirm the change. This is also 
useful for locating a particular place in a 
file. 


So far, both editors look about the 
same. They’re not, and here’s how they 
differ. With PIE, you will need to become 
familiar with the manual and the com¬ 
mands, and you may have to refer back 
to refresh you memory. With VS, there is 
a very comprehensive “help file” that 
may be kept on-line on the active (VS 
source) disk, available to be called up 
without interrupting the edit session 
when you forget a command. This takes a 
fair amount of disk space (57 sectors) but 
on a two-drive system this is no problem. 
And since you can replace the disk in a 
one-disk system when you’re ready to 
write out and save the file, single-drive 
users can keep their help file available, 
too. 

Another major difference is in the 
use of the H19/H89 special-function keys 
across the top of the keyboard. Both PIE 
and VS use them, but VS uses the CRT’s 
25th line to display the current meaning 
assigned to the keys. This is important, 
because while PIE’s functions remain the 
same throughout the session, VS changes 
the definitions depending on what you’re 
doing. For instance, keys F1-F5 each 
have a main function, but when one is 
pressed, say the Input/Output function 
key, all five are re-defined into Read, 
Write, Exit, Insert and Delete. This may 
not seem terribly clear in reading, but 
when displayed on the screen the effect 
is to dramatically simplify the operation 
of the editor. I never refer to the manual 
for VS, except to get the address of the 
manufacturer. And, as mentioned, if the 
name of the function isn’t sufficient to 
refresh your memory, the HELP func¬ 
tion key is available. There’s also an 
“oops” key that undoes the effect of a 
command typed by mistake (if you 
haven’t gone too far along with it). 

VS allows the user to set both the 
left and right margins, and allows for 
right justification, or filling, of the text. 
This is not so satisfactory as on more ex¬ 
pensive text processors like AutoScribe or 
Magic Wand, as the justification all seems 
to take place on the rightmost five or 
six words, leaving the left part of the text 
unchanged. As a result, I rarely use that 
feature. (It’s neat to watch it work on the 
screen, though.) 

Finally, VS will allow you to insert 
text from another file into the working 
file at the location of your choice. PIE 
will not, and while this may not be a 
crucial feature to you, it is often highly 
(Continued on next page) 


58 


Dr. Dobb’s Journal, Number 66, April 1 982 

187 





HARDWARE REVIEW—““ 

The Sinclair ZX81 

Small Review of a Small Computer 


T he ZX81 is the recent entry from 
Sinclair for lowest cost computers, 
and a very delightful entry it is. It 
retains the innovative features of the old¬ 
er ZX80 such as single-keystroke key¬ 
word entry and a very compact case. The 
new machine has an 8K ROM that con¬ 
tains the BASIC interpreter, the video dis¬ 
play firmware, and a floating-point cal¬ 
culator that offers about the same 
amount of power as an Apple but at 
about double the speed. The BASIC in¬ 
terpreter allows variable names of arbi¬ 
trary length, so you can write programs 
that are very nearly self-documenting. 

The basic system also includes PEEK, 
POKE, and USER functions to facilitate 
machine language programming for the 
Z-80A processor. There is no doubt that 
the software resident in the system comes 
from a very smart group . . . they describe 
themselves in the excellent BASIC pro¬ 
gramming manual as “a small firm of 
Cambridge mathematicians.” 

Sinclair is an English company and 
there is one English chip in the machine 
- a large universal logic array which exe¬ 
cutes the video, cassette tape and address 


by Jerry Chamkis 


Jerry Chamkis, P. O. Box 18093, Austin, 
TX 78760. 


decoder functions. The remaining four of 
the IC’s in my kit are of Japanese manu¬ 
facture. 

The small keyboard is not as hard 
to use as it might seem and is, in fact, just 
right for young fingers to practice the 
marvels of computing. If you should wish 
to add a larger keyboard, nothing more is 
required than a naked keyboard wired 
into the ZX81. About $ 1 in parts will add 
a direct video output, so you can use a 
composite monitor instead of a television 
set as your display device; another SOt) 
worth of parts will fully decode the ROM 
address space to allow for easy expansion 
of the control program. 

Sinclair and others offer RAM ex¬ 
tension boards that start at 16K bytes 
and $100. Don’t take seriously the rather 
disappointing article in the January issue 
of BYTE. . . it is neither impossible nor 
undesirable to add more than 16K of 
RAM to this machine. I am equally 
pleased with its performance as a BASIC 
learning machine as a smart process con¬ 
troller, for which I predict it has a glori¬ 
ous future. It costs $150 assembled or 
$100 in kit form, which includes a UHF 
TV modulator and a calculator-charger 
type power converter. All in all, a rare, 
excellent bargain! 

(Editor’s note: see our May issue for de¬ 
tails of the above-mentioned direct video 
output modification.) 


Software Reviews 

(Continued from page 58) 


desirable. 

So we come to the bottom line: 
what’s to choose between the two? I have 
owned PIE for over two years, and VS for 
about one. While I like them both, I 
prefer and use VS more. The feature I 
appreciate most is the margin setting, 
while my wife (who has her own H89) ap¬ 
preciates the help file. VS takes consider¬ 
ably more disk space, especially with the 
help file installed, and takes a bit longer 
to start up. With regard to the price, the 
Software Toolworks’ latest version of 
PIE, 1.5b, sells for $29.95 at most Heath 
retail stores and direct from the maker, 
while VS sells for $39.95, also from the 
Heath stores or the maker. Both are top- 
quality programs from highly reputable 


firms. I believe the price difference is due 
to the development cost; it probably cost 
more to create VS than PIE. 

These are by no means the only 
good, full-screen editors available to the 
Heath user; they’re just two of the best I 
have personally experienced. When com¬ 
bined with a text formatting program 
(like Runoff or Walt Bilofsky’s TEXT) 
comprise a text processing package for 
about $75.00 that can’t be beaten for 
hundreds of dollars. When used with a 
daisy-wheel printer, such a combination 
is fully capable of producing camera-ready 
copy for offset printing, with headers, 
footers, page numbering, strike-over, 
footnotes, full justification, line spacing 
and so forth. »*j 


Dr. Dobb’s Journal, Number 66, April 1982 
188 


59 



BOOK REVIEWS 


The Logical Design of 
Multiple-Microprocessor Systems 
by B. A. Bowen and R. J. A. Buhr 
Prentice-HaU, Inc. 

310 pages, $25.00 
Reviewed by George W. Jolly 

Concurrent programming is the man¬ 
aging of software in which more than 
one thing happens at the same time. With 
the current low price of microprocessors, 
the design of such a system can easily in¬ 
volve assembling modules of software and 
hardware in a custom configuration to 
solve a concurrent problem. Logical De¬ 
sign takes you through this design pro¬ 
cess, beginning with the concept of con¬ 
current systems. Whether your needs in¬ 
volve software on large timesharing sys¬ 
tems or in clusters of microprocessors, 
this book will serve as an excellent text. 

The concrete examples all assume the 
Intel 8080 microprocessor, and are usual¬ 
ly in PL/M or Pascal. However, the vast 
bulk of the illustrations are diagrams, not 
program excerpts. These diagrams are 
very helpful and are not specific to any 
particular computer. A packet-switching 
protocol provides a concrete example of 
design trade-offs in a working system. 

You should be warned that concur¬ 
rent systems involve advanced concepts. 
If one hasn’t mastered ordinary program¬ 
ming, he will have a bit of fun trying to 
debug a concurrent program. Logical De¬ 
sign assumes plenty of experience in non¬ 
concurrent work. One strong point to the 
book is that several approaches to a given 
problem are worked out to expose the 
limitations or failings of each before 
settling on a better approach. This can 
save considerable wasted trial-and-error 
in a first concurrent project. 

Logical Design explains concurrent 
systems in an onion-skin fashion, where 
an innermost kernel is surrounded by suc¬ 
cessively higher-level layers of software. 
Several types of monitor routines are 
shown, which logically protects access to 
some resource. Diagrams also explain 
methods of hardware handshaking be¬ 
tween devices. Examples of concurrent 
software implementation in both PL/M 
and Pascal show how these languages can 
be used, even though they were not de¬ 
signed as concurrent languages. 

Logical Design is a thorough text on 
an interesting subject. If you want to 
learn about concurrent systems in a 


variety of styles, then Logical Design is 
for you. 

Threaded Interpretive Languages 
By Ronald G. Loeliger 
BYTE Books 
251 pages, $18.95 
Reviewed by H. T. Gordon 

A subtitle for this fascinating work 
could be “How to Construct Your Per¬ 
sonal FORTH-like HLL.” It’s a unique, 
detailed description of the deep structure 
of this type of computer language, and 
anyone who wants to know how it works 
ought to read it. To understand it, one 
needs some familiarity with the architec¬ 
ture of microprocessor-based systems and 
a modicum of skill in assembly-language 
programming (though not necessarily that 
of the Z80 used in many of the specific 
examples). The underlying FORTH con¬ 
cepts are clearly explained in general, but 
the implementation is “non-standard” 
and is therefore named ZIP. It’s unlikely 
that many readers will emulate the author 
and create their own core-language. But 
the tutorial impact on microcomputer 
software design may be impressive, in¬ 
fluencing new ROM monitors, operating 
systems, assemblers, and even the HLLs 
that are not FORTH-like; especially in 
6809 systems, since this microprocessor 
is far more stack-oriented than the Z80. 

ZIP looks like a powerful variant of 
FORTH, stressing code-efficiency so that 
its core will “fit” into 4K bytes, of which 
3.2K are used for the 150-odd keywords 
(summary on pp. 175-179) and the rest 
for the outer and inner interpreters. The 
numerous trade-offs required by this high 
compaction are analyzed with admirable 
frankness. Only the first 3 characters of 
source-code keywords are retained (e.g., 
both DROP and DROX would have the 
same 4DRO dictionary header). The 
severe timing penalty of defining simple 
operations as : . . . ; “subroutines” in¬ 
stead of direct machine code is empha¬ 
sized. Many primitives transfer only one 
byte to and from the parameters stack, 
instead of the usual 2-byte “word.” Al¬ 
though an HLL is a system-independent 
virtual machine, its I/O must of course 
interconnect with system-dependent rou¬ 
tines (ideally via programmable vector 
locations). Loeliger says little of this 
(pp. 54, 74), seeing it as a distinct prob¬ 
lem. 

The plural “languages” of the title 


merely indicates that many other varia¬ 
tions of the FORTH theme could be con¬ 
structed. These are not explored. Al¬ 
though he also has UCSD Pascal, he does 
not hint at possible resemblances of its 
compiled “pseudo-code” to FORTH- 
type “threaded code,” nor does he refer 
to the general problems of compilation — 
invariably some way of linking prefabri¬ 
cated blocks of machine code. He does, 
however, implement a full Z80 assembler 
and sketch the outlines of an editor and 
lightly touch on disk-access and many 
other practical problems. Most commer¬ 
cial FORTH systems require the presence 
of an elaborate operating system such as 
CP/M (a massive tail waggable by quite a 
small dog!). 

The book is expensive for its size 
(30% of its thickness is in its hardcovers). 
It may be criticized for incompleteness 
and lack of generality, and its unortho¬ 
dox approach will displease many users of 
FORTH. But its primary task — explica¬ 
tion of the generalized FORTH virtual 
machine — is done very well, and it can 
be a take-off point for exploring the 
possibilities. 

Microsoft BASIC Decoded 
& Other Mysteries for the TRS-80 
by James Farvour 
IJG Computer Services 
310 pages, $29.95 
Reviewed by James Cardell 

With one major caveat, this book is 
a valuable resource for the experienced 
assembly language programmer who de¬ 
sires to get the most out of a system 
which runs Microsoft BASIC. Included in 
the book is a concise but complete de¬ 
scription of the system monitor and 
BASIC interpreter. Armed with this 
knowledge of how the BASIC runtime en¬ 
vironment works and what functions are 
available in the interpreter code, and 
guided by the many how-to-interface-it 
examples, programmers will achieve quan¬ 
tum increases in their programming abili¬ 
ties. 

Manuals of this sort have been avail¬ 
able for a few years now and as an at¬ 
tempt to fill the enormous need of docu¬ 
menting Microsoft BASIC and the TRS- 
80 system monitor (undoubtedly to the 
chagrin of those in Forth Worth who re¬ 
fuse to acknowledge the existence of any¬ 
thing but BASIC programmers). To their 
credit these earlier attempts shed much 


60 


Dr. Dobb’s Journal, Number 66, April 1 982 




light on this subject, but Farvour’s book 
is much more than an attempt. It may 
very well be a definitive work. 

In addition to providing an abstract 
description of the runtime environment, 
he has taken a disassembled output of the 
low memory in which the system resides 
and lucidly commented every line (over 
7500!!) of code. Thus, this book serves 
readers on many levels. It is a reference 
to the programmer attempting to inter¬ 
face the hardware. It is a guide to achiev¬ 
ing powerful, concise, modular code by 
using the available runtime routines. And 
it is also a detailed instructional manual 
for those interested in examining a pro¬ 
fessional systems program. In short, it is a 
wise addition to any serious TRS-80 
owner’s library. 

All entry points into the code are 
documented with interface examples con¬ 
sisting of a few lines of code showing how 
to call the routine and what results to ex¬ 
pect. The entry points are organized by 
functionality, but cross-references by 
name and address should also have been 
provided. In addition to these short ex¬ 
amples, some larger programs are also pre¬ 
sented. A SORT program is given to 
demonstrate the technique of adding re¬ 
served words to those that the interpreter 
already recognizes by taking control at an 
error entry point. An OVERLAY pro¬ 
gram is an example of a sophisticated sys¬ 
tem program for a disk system that pro¬ 
vides the facility to add statements to a 
running BASIC program while maintain¬ 
ing current variables. 

Now as for the caveat, the book is, 
out of legal necessity, incomplete. Be¬ 
cause of copyright restrictions, the disas¬ 
sembled code could not be reproduced in 
its entirety in the book. The alternative 
taken here was to excise parts of the code 
and give instructions to the reader as to 
how these parts may be reproduced. The 
“parts excised” is the disassembled in¬ 
struction operand field. The “reproduc¬ 
tion instructions” are to print a disassem¬ 
bled listing of low memory on your own 
system and collate its pages with those of 
the book, which is conveniently drilled 
for a three-ring binder. Of course, to 
carry out the reproduction you need a 
line printer. And further, the recommend¬ 
ed disassembler which formats its output 
to align with that of the book is the one 
provided with Apparat’s NEWDOS, so 
you also need a disk system to do the job 
right. 

Dr. Dobb’s Journal, Number 66, April 1982 
190 


For some reason, (be it legal or the 
desire to sell many books) this informa¬ 
tion is never completely presented in the 
book. In fact, it is buried in a few sen¬ 
tences at the beginning of Chapter Seven. 
This is no problem for those purchasers 
possessing the requisite system configura¬ 
tion, but there will probably be irate 
readers with minimal systems unable to 
complete the book. This situation does 
not render the book totally useless, rather 
it makes the examination of disassembled 
code more cumbersome. It is possible to 
run a disassembler and list the output on 
the video monitor. This may then be read 
along with the comments in the book. 
The missing code might even be written 
into the appropriate space in the book, 
but this is impractical for the entire book. 
Reliance on the video output eliminates 
the ability to easily refer to it when using 
the system for something else, editing an 
assembly program for example. 


$2.50 

($3.00 in Canada) 


For Users of Small Computer Systems Number 67 May 1982 



John S. James 


Jerry Chamkis 


Gene Head 

more features inside! 


Telecommun - 
ications... 

... Computer 
Bulletin 
Boards... 

How to Add a 
System Clock 



















Dr. Dobbs Journal 

For Users ol Small Computer Systems y 

May 1982 Volume 7, Issue 5 


Editor - Marlin Ouverson 
Contributing Editors - 

Dave Caulkins, Dave Cortesi 
Marketing Director - Craig Harper 
Marketing Assistant - Larry Brittain 
Advertising Sales — Laird Foshay 
Circulation - Gloria Romanoff, 

Theresa O’Rourke, Terri Marty 
Art Director — Clifford West 
Production Manager - Barbara Ruzgerian 
Production Assistant — Joneva Barry 
Typesetter - Renny Wiggins 
Proofreader — Nancy Heubach 
Cover Illustration - A1 McCahon 


© 1982 by People’s Computer Company 
unless otherwise noted on specific articles. 
All rights reserved. 

Subscription Rates: $25 per year within the 
United States; $40 for first class to Canada 
and Mexico; $58 for airmail to other coun¬ 
tries. Payment must be in U. S. Dollars, 
drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be 
typed, double-spaced on white paper. List¬ 
ings should be produced by the computer, 
using a fresh, dark ribbon on continuous 
white paper. Please avoid printing on perfo¬ 
rations. Payment is in contributor’s copies. 
Requests to review galleys must accompany 
the manuscript when it is first submitted. 
Authors may receive a copy of the complete 
writer’s guidelines by sending a self- 
addressed, stamped envelope. 

Donating Subscribers Contributing Sub¬ 
scriber: $50/year ($25 tax deductible). Re¬ 
taining Subscriber: $75/year ($50 tax de¬ 
ductible). Sustaining Subscriber: $100/year 
($75 tax deductible). Lifetime Subscriber: 
$1000 ($800 tax deductible). Corporate 
Subscriber: $ 500/year ($400 tax deductible, 
receives five one-year subscriptions). 


Contributing Subscribers: Thomas H. 
Grohne, G. V. Elkins, Robert M. Connors, 
William J. McEown, Robert C. Luckey, 
Robert N. Stabler, DeWitt S. Brown, John 
B. Palmer, Jack Miller, Burks A. Smith, 
Transdata Corporation, Mark Ketter, John 
W. Campbell, Friden Mailing Equipment, 
Howard E. Decker, Jim Wilson, Frank 
Lawyer, Chris Pettus, Paul Lutus, Ben 
Goldfarb, Rodney Black, Steven Weiss, Pat 
Phelan, John Brodie, James Fleming, Unison 
World, Christopher Sherbak, Thomas Davis. 
Sustaining Subscribers: Gordon Eubanks, Jr., 
Pete Roberts, Steven Fisher Enterprizes. 
Lifetime Subscriber: Michael S. Zick. 

Foreign Distributors UK & Europe: 

Hofacker-Verlag, Tegernseer Strass 18, D- 
8150 Holzkirchen, West Germany. Asia & 
Australia: ASCII Publishing Co., Ltd, 
Aoyama Building 5F, 5-16-1 Minami 

Aoyama, Minato-ku, Tokyo 107, Japan. 


Dr. Dobb’s Journal, Number 67, May 1982 

792 


CONTENTS 


18 Program for Modem: Forth Code From the Conference Tree 

by John S. James 

Programming a modem can be one of the trickier aspects of a telecommunications 
system. The article explains techniques used by the CommuniTree Group, and 
includes actual working code now placed in the public domain. 

26 North Star-to-Epson Connection: A Simpler Way 

by Larry Shoer 

DDJ has published articles and software in the past about using this popular paral¬ 
lel printer with a North Star. Author Shoer has come up with a simpler approach. 

30 Adding a System Clock 

by Michael Kan 

Despite the general usefulness of system clocks, many computer hobbyists do not 
use them. This feature shows how to implement a software-simulated clock in an 
independent processor external to the host. 

42 New USER for CP/M 

by Gene Head 

Anyone who does a lot of hard copy documentation may have found hand 
feeding single sheets to present a thorn in the side. Perhaps single sheet ejects and 
an operator controlled waiting period are the answer for you. 

48 Direct Video Output From the Sinclair ZX81 

by Jerry Chamkis 

This author tantalized Sinclair aficionados last month with his mention of using a 
a monitor as the display device for the ZX81. Read on, for jitter-free video! 

50 Using Computer Bulletin Boards 

by Marlin Ouverson 

A pack of people plead monthly for the how-to’s of computer conferencing and 
bulletin boards. Here lies a logon sequence to get you onto most CBBS’s. 


4 Letters 
4 Editorial 
10 Dr. Dobb's Clinic 
13 Of Interest 
53 Software Review 

A TRS-80 Smart Terminal Package 

56 Book Reviews 

58 Hardware Review 

Hayes’ Stack Smartmodem 

59 Guest Essay 

Prior Censorship 


Dr. Dobb’s Journal (USPS 307690) is published twelve times per year by People’s Computer 
Company, Box E, 1263 El Camino Real, Menlo Park, CA 94025. Second class postage paid at 
Menlo Park, California 94025 and additional entry points. Address correction requested. 
Postmaster: send form 3579 to Box E, Menlo Park, California 94025 • 415/323-3111 


3 





LETTERS 


Screen-Oriented Bugs 

Dear Marlin, 

I want to thank you and all the peo¬ 
ple at Dr. Dobb’s Journal for publishing 
my article, “A Portable, Screen-Oriented 
Editor” (DDJ #63). 

Your readers should know about 
several bugs and typos that have been 
found in that article. Mr. David Harper of 
Henrietta, New York gets my nomination 
as “exterminator of the month” for his 
work in finding bugs 1 through 8 below. 
So far, he is the only person who has 
written to tell me about any bugs in the 
editor. 

Bug 1 In the function search 1() on 
file ed3.c the code that reads: 
if (pat[ 0] ==EOS) { 
return; 


} 

should be changed to: 

if (pat[0] ==EOS) -{ 
return -1; 

y 

This bug has a small effect on the find 
and search command-mode commands. 

Bug 2 In the function pmtfile() on 
file ed7.c, change the line: 

pmtcol 1(); 
to: 

pmtcol l(x); 

This bug causes the prompt line to con¬ 
tain an erroneous column number follow¬ 
ing the load or name command-mode 
commands. 

Bugs 3, 4, 5, and 6 I managed to 


/* return-1 if no character is ready 
from the console. 

* otherwise, return the character. 
*1 

syscstatQ 

-l 

int c; 



botch the routine syscstat() on file ed8.c. 
The version of this routine for CP/M 2.2 
which was published in Dr. Dobb’s Jour¬ 
nal does work, but it doesn’t do what the 
comment says it should. In addition, the 
version of syscstatQ for CP/M 1.4 con¬ 
tains a separate bug. In the interest of 
clarity, I won’t print the erroneous ver¬ 
sions of syscstatQ here. 

The correct version of syscstatQ for 
CP/M 2.2 is: 


Editorial “ 

Electronic Graffiti 


Telecommunications is one of the most important uses 
for microcomputers. It can mean many things: locally 
linked machines in a separate-but-equal file sharing mode, 
or in a master-slave(s) relationship; hooking in to centrally 
controlled data bases; or networking remote micros as 
independent nodes, over telephone lines or through the 
airwaves. But it can mean only two things: power to 
control information, and power accrued by access to 
information. 

Commercial data bases like the Source, MicroNet, and 
DIALOG are among the telecommunications schemes 
which get the most press coverage, thanks to big financial 
interests. Decisions about which information to provide, 
how easily, at what price (usually between $5 and $100 per 
access hour), and to which audiences, are effectively made 
in the corporate boardroom. 

Local networks like Nestar, Ethernet and others grow 
out of “futuristic” office concepts. These are commercial 
services which link computer workstations under one roof. 
They allow inter-communication; shared access of files on, 
for example, hard disk; and monitoring of each operator’s 
actions, especially useful in supervisory or educational 
environments. Local networks are installed at prices which 
are low enough, relative to the computing power created, 
for most financially stable institutions. 

Of growing interest, and especially important for 
computer hobbyists, are the hundreds of no-charge Com¬ 
puter Bulletin Board Systems (CBBS is actually a trade- 
marked acronym). Around the world, microcomputer 
enthusiasts are putting up CBBS’s as a public service, for 
the interaction with others, and for the experience. They 
use telephone lines and their own one- and two-disk drive 


configurations to link users in active interchanges, to 
provide public notices, articles, and conferences. Some are 
operated for use by special interest groups in the sciences, 
computers, arts and politics. 

The importance of such homegrown networks should 
in no way be underestimated. They are quickly mastered, 
thanks to their ease of operation. Because they are free of 
charge, there is no stratification of users by economic 
range. An unwritten operator’s code of ethics severely 
restricts censorship or “editing” of messages, creating a 
forum for sometimes radical, sometimes ingenious thought. 

The foundation is already laid for scenarios from a 
science author’s imagination. At night, humans go to bed as 
their machines blink quietly, passing messages from one to 
the next. Disk drives store personal mail and any unpro¬ 
tected through-messages with embedded, pre-selected 
keywords. A chain of local transmissions travels electron¬ 
ically across several states, avoiding long-distance fees. 
Broadcast repeaters transmit cross- or inter-continental 
files, with stringent error checking at each node. CBBS’s 
unite periodically to share selected resources, giving each 
local user indirect access to an entire world of information. 

In our Information Age, those who control informa¬ 
tion are the ones with real power — personal and political. 
Given such a scenario, microcomputer-controlled message 
systems are like local power generators; anyone with a 
terminal or a micro can use the resultant energy free of 
charge. 

Editor 


4 


Dr. Dobb’s Journal, Number 67, May 1982 

193 




c= cpm(6,-l); 
if (c==0) -{ 

return -1; 

y 

else -{ 

return c; 

y 

The correct version for syscstatQ for 
CP/M 1.4 is: 

syscstatQ 

i 

if (bios(2,0)= = 0) -( 
return -1; 

h 

else -{ 

return syscinQ; 

y 

y 

Please note that I still have no way to 
test the CP/M 1.4 version of syscstatQ. 
Proceed with caution. 

Warning And again I say, warning. 
If you make these changes to syscstatQ, 
then you must also change the code in 
chkkeyQ on file ed3.c. The old code is: 
if(c==0H 

I* no character at keyboard */ 
return (NO); 

y 

The code should be: 
if (c == -1) -[ 

/* no character at keyboard */ 
return (NO); 
h 

Bug 7 In the function bufdelnQ on 
file edlO.c the code that reads: 
if (bufdn()==ERR) i 
bufline=oldline; 
oldbufp=bufp; 
return (ERR); 

y 

should be changed to: 

if (bufdn()==ERR) i 
bufline=oldline; 
bufp=oldbufp; /* bug fix */ 
return (ERR); 

} 

This bug fouls up error recovery. 

Bug 8 The following line of bufrepl() 
should be deleted: 

bufpmax=bufpmax+n- oldlen; 

The line already appears in the rou¬ 
tine bufextQ. This bug makes parts of the 
main memory buffer unusable as editing 
progresses. Do not change the bufextQ 
routine! 

Bug 9 I did manage to find one bug 


Figure 1 

Diskdoc Changes 


/ * 

* get character, no echo 

* upper case is converted to lower 

*/ 

conlowe r () 

{ char ch; 

ch=conin(); 

if ((ch>='A , )8(ch<='Z')) ch=ch+'a'-'A'; 
return ch; 

> 


/ * 

* select drive, drive name is 'a','b' etc. 

* set values for track, sector counts and first sector 

* return true if ok 

* to find out what this version does, 

* refer to the cp/m 2.0 alteration guide 
*/ 

seldrv(drv,pt,ps,pf) 
char drv; 

int *pt,*ps,*pf; /* where to put track, sector and firstsector */ 

< int *dph,*spt,*dsm,*off,ha l fsecs , trks; 
char *dpb,*bls; 

if ((dph=bios(9,drv-'a'))==0) return 0; 

xlt=dph[03; /* look at disk parameter header */ 

dpb=dphC5D; 
if (xlt) *pf = x It COD; 
else *pf=255&bios(16,0); 

Spt=8dpbC0]; *ps=*spt; /* and at disk parameter block too */ 
bls“6dpb C 2D; 

dsm=8dpbC5D; 
off=8dpbC13D; 

/* this is tricky since unsigned divide isn't supported */ 
halfsecs=(*dsm + 1X<(*bls-1); 

trks=((halfsecs/(* spt))* 2) + (((halfsecsX(*spt)) + (*spt-1))/(*spt)); 

*pt s t rks + *off; 
return 1; 

> 


/ * 

* bios call 

* will only work with the original small C 

* other C compilers will usually have the argument sequence reversed 
*/ 


bios(fun,arg) 

int fun,arg; 

{ char *ofs; 

ofs=(fun-1)*3; 

U asm 

pop d 

pop h 

pop b 

push b 

push h 

push d 

Ihld 1 

dad d 

Ixi d,retn1 

push d 

mov d,b 

mov e,c 

pch l 
r et nl : 

x chg 

mov l,a 

mvi h,0 

pop b 

push b 

mov a,c 

cpi (9-1)*? 

j z retn2 

cpi (16-1)*? 

jnz retn3 

retn2: 

x chg 
r et n3 : 

# enda sm 

> 


; of s 
; ret 
; arg 

; get pointer to bios 
;add offset 

;arg in de too 
;go 

;of s 

;select disk function? 
;sector translate? 

;value came in hi 


6 


Dr. Dobb’s Journal, Number 67, May 1982 



on my own. In the routine edjoinQ on 
file ed4.c change the lines: 

/* abort if the screen isn’t wide e- 
nough */ 

if (k>SCRNWl) { 
return; 

y 

to: 

/ * abort if the screen isn’t wide e- 
nough */ 

if (k>SCRNWl) -[ 

bufgetln(editbuf, MAXLEN); 
return; 

y 

The effect of this bug is striking 
when it happens and you should definite¬ 
ly fix it. You can see the effect of the 
bug as follows: 

1. Use the join key to join two lines 
whose combined length exceeds the 
width of the screen. Nothing (ap¬ 
parently) will happen. 

2. Move the cursor to the middle of the 
current line. 

3. Make some change to the line from 
edit mode. You will now see that the 
line you are editing isn’t the line that 
you should be editing. 

There are also several typos in the 
article that may be confusing: 

Typo 1 On page 20 of the article, 
in the paragraph about the split key, it 
says, 

“Both these keys also switch the 
editor to insert mode.” 

This sentence should be deleted. Some¬ 
how it was duplicated from a previous 
paragraph which concerned the insert 
up and insert down keys. 

Typo 2 In Figure 4 of the article, 
the function of the s command should be 
changed from: 

move cursor right to H char K 
to: 

move cursor right to < char> 

Typo 3 The comment for edattopQ 
on file ed4.c should be changed from: 

/* return true if the current edit 
line is being 

* displayed on the bottom of the 
screen. 

*/ 

to: 

/* return true if the current edit 
line is being 

* displayed on the top of the 
screen. 


*/ The second bug was caused by an 

Yours oversight of mine when interpreting the 

Edward K. Ream CP/M BIOS disk parameter information. 

1850 Summit Av$. On some double-density formats (mainly 

Madison, WI 53705 the Intellec MDS II), Diskdoc believed 

that the first sector was number zero, in- 
Doctoring Diskdoc stead of number one. The enclosed re- 

Dear Marlin Ouverson, vised versions of seldrvf) and bios (J will 

Since I submitted the Diskdoc listing perform correctly. 

(DDJ #66), two bugs have been found. Yours sincerely, 

The first one concerns compatability with Egil Kvaleberg 

other compilers. While Small-C evaluates Studpost 111 

expressions from left to right, the N-7034 Trondheim-NTH 

Kernighan/Ritchie C-language specifica- Norway 

tion leaves the order of evaluation unspe¬ 
cified. The previous version cjf the con- Sad About Sinclair 
lower //-function depended orj the order 1 am an owner of a Sinclair, ZX81 
of evaluation, the version shown as Figure computer and I am dissatisfied with its 
1 does not. operation. I experience frequent, unpre- 



Dr. Dobb’s Journal, Number 67, May 1982 


7 

195 




dictable system failures due to the power 
jack plug (the “on/off switch”) connec¬ 
tion, keyboard depressions and the edge 
connector contact for the 16K RAM 
pack. The system failures result in loss of 
time and effort in re-entering and re¬ 
running programs. My ZX81 sits on a 
shelf instead of being used because of the 
likelihood of its error prone operation. 

I would like to hear from other 
owners of the ZX81 who are experiencing 
these same failures and who are interested 
in sending a group message to Sinclair 
requesting a fix. Contact me at the ad¬ 
dress below. I will respond to your re¬ 
plies through the same publications which 
have published this message. 

Donald F. Shank 

POB 50301 

Palo Alto, CA 94303 

Editor's note: For the other side of the 
coin about Sinclair’s latest computer, see 
last month's DDJ Hardware Review and 
“Direct Video Output” in this issue. 

1 Can C Forever 

To the good doctor: 

Having read the glowing reports in 
DDJ about Small-C, 1 ordered the 
CP/M (tm) version from the CODE 
WORKS. First I would like to say that 
Ron Cain has provided a true service to 
computer hobbyists by placing this piece 
of software in the public domain. Also, 
the CODE WORKS is performing a 
service to hobbyists using CP/M systems 
by providing this compiler at the very 
reasonable price of seventeen dollars. 

One very easy way to implement 
code improvement to the compiler is in 
the routine for the declaration of local 
variables “declloc(typ)”. I have changed 
this routine so it will only modify the 
stack pointer after the entire declaration 
has been parsed. Before, the stack was 
modified for each variable in the declara¬ 
tion. The simplest statement to benefit 
from this is: 

char a,b ; 

This now generates a PUSH rather than 

2 DCX SP’s. For a statement like: 

int al(40),a2(40),a3(40),a4(40), 
a5(40) ; 

the savings in space and time are consider¬ 
able. 

I was not expecting the compiler 
to benefit from the changes, however it 
did (although not by much). In the pro¬ 
cess of bootstrapping this change, the 


code size changed by the following 
amount: 

13 bytes larger: new compiler 
compiled with old compiler 
121 bytes smaller: new compiler 
benefitting from compiler 
_ change 

108 bytes smaller: net change in 
size. 

I am enclosing a copy of “declloc” 
for those wanting to duplicate this code 
improvement (see Figure 2 on page 7). 
Sincerely, 

Dan Bates 
Rt. 8, Box 278 
Johnson City, TN 37601 

Pidgin Tracks 

Dear Doc: 

It looks as though a slight plaque 
buildup has occurred on the proofreader’s 
glasses, which manifested itself in DDJ 
#65. In the Editorial, it is stated that 
“as Heinlein noted in his great Founda¬ 
tion trilogy,. ..” My copies were au¬ 
thored by Asimov. Heinlein’s forte is 
more in the area of serendipity. 

In a more serious vein, I really ap¬ 
preciated the PIDGIN follow-up, and 
read and analyzed its approach with great 
interest. It appears from the article that 
a listing of PIDMATH.ASM, which in¬ 
cludes arithmetic routines 7ISUB, 7IMUL, 
and 7IDIV, among others was omitted. 
See page 28, rightmost column, seventh 
trhough ninth and 33rd throught 38th 
lines. I hope that you will run these as an 
errata in an upcoming issue. 

Personally, I have been implementing 
TINCMP and PIDGIN on my SOL-20 by 
a method of successive approximation, as 
follows: 

(1) Verbatim entry of W. A. Gale’s 
TINCMP, 

(2) Revision of (1) to wholly structured 
code without GOTO/LOC construct, 

(3) Translation of a complete pattern set 
from 6502ML to 8080AL using 
“Template Definition” coding form, 
and TINCMP syntax summary, 

(4) One-for-one replacement of (2) 
statements with (3) code as a purely 
mechanical process, using my text 
editor and my fingers and eyes as a 
TINCMP surrogate. 

Presently, I have only proceeded to 
this point. As the SOLOS operating sys¬ 
tem of my tape cassette-based machine is 


markedly different from CP/M and Gale’s 
basic disk operating systems, the going 
is slow. 

As my approach to an 8080 imple¬ 
mentation differs due to changes in oper¬ 
ating system and programming style (I 
formerly ran a service bureau in Washing¬ 
ton, DC, and went for two and a half 
years without writing a single “GOTO”), 

I will let you know of my progress. 

If you can convince Gale to send you 
his “seven Pidgin programs which test the 
Pidgin macro definitions fairly thorough¬ 
ly” (DDJ #65, page 25), and fuller de¬ 
scriptions of Maclod and Spartan, I am 
certain that they would be popular fea¬ 
tures. 

Keep up the good work. And watch 
out for those gremlins. 

Very truly yours, 

Russell P. Herrold III 
2834 Clifton Road 
Columbus, OH 43221 

Foundation Folly 

To Marlin Ouverson: 

I’m sure you will get many letters 
pointing out your glaring editorial error 
in your March issue of DDJ. 

I refer to your comment that 
Heinlein wrote The Foundation trilogy. 
Although a great author, I’m sure Issac 
Asimov does not want to lose credit for 
his greatest work. 

As a charter member of the Science 
Fiction Book Club back in 1960 my first 
book was the trilogy & after 20+ years I 
still have it — beat up — well read by 
many - but still the best. 

Frederick G. Volpicelli 
331 8th Ave. 

Pelham, NY 10803 

Dear Mr. Ouverson, 

In response to your editorial in the 
March issue which you conclude by ask¬ 
ing “I wonder what’ll happen next 
month?” . . . 

I think I know. You will probably 
get about 400 letters reminding you that 
Asimov, not Heinlein, wrote the Founda¬ 
tion trilogy. 

Sincerely, 

Michael W. Brown 
2212 Cloverleaf Place 
Ardmore, OK 73401 

Editor’s note: Thanks to those who (too 
eagerly, methinks) caught the gaffe. I’m 
sure Mr. Heinlein would’ve written 
“Foundation” if he’d thought of it. . . 


8 

196 


Dr. Dobb’s Journal, Number 67, May 1982 


DR DOBB’S CLINIC 


by D. E. Cortesi 


A CPU Transplant 

Bruce Komusin of Huntington, NY, 
sent us a brief description of two interest¬ 
ing pieces of work. First, he performed a 
brain transplant on his 8085-based sys¬ 
tem: 

“The 8085, running from a 
10 MHz crystal, was removed and re¬ 
placed with a small card containing 
an 8088, an 8284, a sprinkle of re¬ 
sistors and caps, and a 14.58 MHz 
crystal (giving a 206ns clock). All 
other components of the system 
were unchanged, including 64K dy¬ 
namic RAM, memory-mapped video, 
etc.” 

We’d no idea that an 8088 would 
slip in so easily. Of course, Komusin then 
had the problem of running all his exist¬ 
ing software. He elected to write an 8080 
emulator in 8088 machine language, and 

“I must say the results have been 
underwhelming. The emulator ran 
5.85 times slower than the 8085 
when executing a compute-bound 
RAM test. When it executed an I/O- 
bound full-screen editor, the response 
was acceptable but the prompts and 
error messages, as well as the scroll¬ 
ing, were noticeably slower. 

“The emulator itself fits in one 
2732 EPROM which resides outside 
the first 64K of address space. In¬ 
terrupts are not implemented. The 
mechanism used to emulate the 8080 
instructions could be described as 
Direct Threaded Code. The “inner in¬ 
terpreter,” to borrow a FORTH 
term, is three bytes long; it consists 
of two 8088 instructions, neither of 
which affects the condition flags. 
The 8088 can emulate all but two of 
the 8080 instructions (IN and OUT) 
in thirteen bytes of code or less.” 

If you’d like to know more about 
Komusin’s CPU transplant, bombard us 
with letters. We’ll pass them on, and may¬ 
be he’ll write us an article. 

Getting WiDIR 

Is anyone still using CP/M 1.4? You 
are? Are you tired of having the DIR 
command’s output roll off the top of the 
screen? Dusty Pulver, who lives in Amp- 
thill, Bedford, U.K., got tired of it, and 
decided to make DIR give a wider dis¬ 
play. Pulver describes the patch: 

“It formats each file name into a 


block 16 bytes long, and doesn’t 
output any CR or LF, so it will work 
on any screen that’s a multiple of 
16 columns wide, i.e., it puts four 
names across a 64-column screen and 
five on an 80-column screen. How¬ 
ever, output to a printer may cause 
problems — so use STAT for that. 

“After the names have been print¬ 
ed, the system performs a warm 
boot, because I’ve had to use the rou¬ 
tine that outputs ‘Bdos Err on x:,’ 
which then does a boot, and I can’t 
find a way around it. Also, due to 
space restrictions I had to use a rela¬ 
tive jump, so the patch will work 
only on a Z80 system. Finally, if 
there’s a file with a filetype of three 
blanks, the format will be messed up. 

“Here is the patch as it would ap¬ 
pear in a 16K system. You have to 
add an offset to the indicated in¬ 
structions for a larger system. The 
offset is the size of the system less 
4000h bytes, i.e., 8000h in a 48K 
system. 


0DFD 

CD 

B0 

2A 

call 2AB0h+offset 

0E00 

C6 

41 


add A,41h 

0E02 

32 

8F 

2D 

Id (2D8Fh+of fset),A 

0E05 

01 

8D 

2D 

Id be,2D8D+offset 

0E08 

CD 

5D 

32 

call 325D+offset 

OEOB 

18 

05 


jr 05h 

OEOD 

20 

20 

00 

db blank,blank,0 

0E10 

3A 

24 


db colon,dollar 


The Eccentric Type 

Here’s an item from the Pitfalls and 
Warnings file, Hardware Section. Our 
Diablo 1650 printer (an excellent ma¬ 
chine) recently broke a spoke on its type- 
wheel — the “y” flew off. “Why not,” we 
mused, “and at the worst possible time, 
too.” We had 150 pages of camera-ready 
copy to print. So we hustled out to pick a 
a new Titan 10 daisy. 

The new wheel was quickly installed, 
but there was something fishy about the 
output. Nothing specific, it just looked 
messy somehow. Examination with a 
magnifying glass revealed the problem: 
the letters weren’t printing on an even 
baseline. Some sat high, some low. It was 
only a matter of 64th of an inch, but the 
eye can detect a very small error in align¬ 
ment. 

Back we went to our suppliers, who 
stood by patiently while we tested all the 



Titan 10 wheels they had in stock. They 
all printed a wavy line. We don’t know 
what the problem was. The spokes might 
have been different lengths, but more 
likely the axlehole was not concentric 
with the ring of letters. Whatever, 
Diablo’s quality control had slipped. 

Fortunately, our dealer also carried 
Diablo-compatible typewheels from 
another company, AGT. The AGT ver¬ 
sion of the Titan 10 worked perfectly, 
and so we managed to meet another dead¬ 
line. Has anyone else had a problem with 
an eccentric daisy? What was the out¬ 
come? 

Bye-bye Files 

From Pitfalls and Warnings, Software 
Section, CP/M department: We’ve been 
building a series of CP/M utilities. They 
all use the same command syntax, namely 

program input.typ [ output.typ ] 

Now, the output.typ operand can name 
the same file as input.typ. In fact, if 
output.typ is omitted, the programs as¬ 
sume that the output file is to replace the 
input file — but not, of course, before the 
program is finished. 

All the programs use the same code 
to set up the files. It does several things: 

(1) open input.typ, 

(2) erase any file output.$$$, 

(3) create a file output.$$$. 

The program then writes to output .$$$. 
At the end of the run, it 

(4) erases any file output.typ, 

(5) and renames output.$$$ to 
output.typ. 

The procedure worked just fine until, in a 
fit of stupidity, we ran one of the pro¬ 
grams with an omitted output.typ and an 
input.typ that was an ambiguous file 
reference. Not fortunately, but 

“*.OUT,” and we had several files with 
the .OUT filetype. The events that fol¬ 
lowed were absolutely correct, given the 
file print of the CP/M documentation, 
but they were unexpected even so. The 
operand “*.OUT” became 

“???????? Out” 

in the default FCB in low storage. The 
program then 

(1) requested an open for 
“???????? OUT” 

which worked perfectly. It got the first 
file that matched that reference. Then it 


10 


Dr. Dobb’s Journal, Number 67, May 1982 

197 






(2) did an erase of “????????.$$$” 
— no problem here, either. Then it 

(3) “made” the file “????????.$$$.” 
That, too, worked fine. It created a direc¬ 
tory entry for a file of that name, and the 
program wrote its output under that 
name. Things got more dramatic when 
the program 

(4) did an erase for “????????.OUT” 
and neatly removed a half-dozen files. 
Following that, it 

(5) successfully renamed 

“????????.$$$” 

to “????????.OUT” and, having illustrat¬ 
ed the old saying about how the opera¬ 
tion was a success but the patient had 
died, terminated normally. 

There is now a check for ambiguous 
file references in our standard code for 
file-handling. Is there in yours? 


Department of Amplification 

Jim Howell of San Jose, CA, wants 
to correct one of our careless statements: 

“In the January 1982 Clinic you 
state that MP/M is the smallest 
multi-tasking operating system you 
know of. I would like to point out 
the existence of OS-9 for the 6809, 
available from Microware Systems 
Corporation (5835 Grand, Des 
Moines, IA 50312). Microware re¬ 
commends a minimum of 32K bytes 
of storage for running OS-9 level 1. 
OS-9 is available for most SS-50 
systems that use a 6809 processor.” 

According to the ad that Howell en¬ 
closed, OS-9 supports re-entrant com¬ 
mand code so that more than one user 
can run a single copy of a program, and it 
allows any command to be started for 
independent execution while the user 
carries on with another one. 


Submitting Is Not Giving In 

Jim Shaw of Indianapolis, IN, has a 
problem. He wants to drive the ED editor 
from a script of commands submitted to 
it via XSUB. That’s a sensible idea; the 
combination of ED and XSUB is a power¬ 
ful tool for manipulating files. Shaw’s 
problem is that he can’t see how to do it: 

“The Substitute command uses 
the control-z character for string de¬ 


lineation. When I tried to include the 
control-z in the command line of the 
input file, ED thought I wanted to 
stop entering text! There was just no 
way to include a control-z in the file 
produced by ED. My next step was 
to use a dummy character for the 
control-z, and use DDT to change 
the file. When I tried that, SUBMIT 
reported an illegal control character 
in the input file. How can I put com¬ 
mands that require control-z into 
submitted files?” 

PIP uses control-z as well, to delimit 
the string arguments of the Start and Quit 
options (anyone who doesn’t know what 
they do should check them out; they’re 
quite useful). Getting control-z into a 
submitted file is really easy, or would be 
except for a small bug in SUBMIT. 

The SUBMIT command should ac¬ 
cept the two-character sequence “ A Z” 
(that’s two ordinary ASCII bytes, “A” 
followed by “Z”) in its input. It is sup¬ 
posed to translate that two-byte sequence 
into a single control character, control-z. 
Any of the 31 control characters can be 
submitted that way; “AC” should put 
a control-c in the file, “A[” should re¬ 
sult in an ESCape, and so on. 

We say “should” and “is supposed 
to” because there is a bug in SUBMIT for 
CP/M 2.2. It tests the second character of 
the sequence incorrectly and rejects it. 
You will find that the sequence “A z ” 
and “ A c” will work but “AZ” or “AC” 
will not. The patch for this problem is to 
load SUBMIT.COM under DDT and list 
the instructions at 044 lh. You should 
see 

0441 SUI 61 
0443 ST A 0E7D 

Change the operand of SUI from 61 h to 
41h and save a new version of SUBMIT. 
It should accept “AZ” and other se¬ 
quences for control characters. You can 
then submit a script of ED (or PIP, or 
DDT) subcommands through XSUB with 
no trouble. 

Well, almost no trouble. Two more 
SUBMIT problems will cramp your style. 
One is a bug: SUBMIT absolutely cannot 
handle a submitted file that contains a 
null line. A line that consists solely of 
CR, LF makes it crash or go catatonic. 
That’s too bad, because you’d like to 
submit a null line at the end of a list of 
PIP subcommands. There’s no fix for this 
one, but maybe you can work around it 
by submitting a control-c instead. 


When driving ED, you might like to 
submit a line containing lowercase letters. 
Forget it; SUBMIT translates its input to 
uppercase (anyone know a patch for 
that?). Even so, there’s a lot you can do 
with submitted ED (PIP, DDT) scripts. 
And examples of that kind of thing 
would make good Clinic items. 

And, on the matter of Clinic items, 
we still have a very handsome, plastic 
reference card for the 6502 CPU from 
MicroLogic. The first sender of a 6502- 
related “sponse” gets it. 


12 


Dr. Dobb’s Journal, Number 67, May 1982 








OF INTEREST 


by Michael Wiesenberg 


Games Galore 

What? A computer game based on 
the stock market? The Avalon Hill Game 
Company sent us news about Computer 
Stocks & Bonds, a version of their educa¬ 
tional Stocks & Bonds board game for 
“all the major home computer systems.” 
Up to four people can play against each 
other, or one player can challenge the 
computer. “Now it’s possible,” says 
Avalon, “for one to lose his shirt and 
walk away smiling — knowing it only cost 
him $20 to find out what an awful specu¬ 
lator he really is.” Software is available 
on diskette for Apple II, Atari 800, and 
TRS-80 Models I and III (level II), and 
on cassette for Pet, CBM, TRS-80 Models 
I and III, Atari 400 and 800, and Apple 
II. (Reader Service No. 402) 

Avalon Hill also offers Dneiper River 
Line for the same machines, a fictional¬ 
ized World War II engagement between 
the Russians and German forces in the 
southern Ukraine. It is based on the actu¬ 
al Soviet thrust over the Dnieper in late 
1943. History buffs are challenged to 
take the role of the Germans in repulsing 
Russian efforts to breach the critical de¬ 
fensive position. Avalon Hill gives you 
game components (actual “men”), repre¬ 
senting infantry, artillery, armored units, 
to place on a color mounted mapboard so 
you can plot moves as they unfold on 
your screen. They claim the software is 
worthless without this additional “hard¬ 
ware,” making the game piracy-free. $25 
on cassette, and $30 for diskette. The 
company suggests writing first for 
memory and program specifics. (Reader 
Service No. 412) 

Atari, Inc., and DC Comics, Inc., 
jointly announced the pairing of electron¬ 
ic home video games and comic books. 
(Well, I can see some similarities.) This 
summer, certain Atari video game car¬ 
tridges will contain comic books featuring 
characters from the games. Defender is to 
come in June, with “defenseless human¬ 
oids kidnapped by aliens from the earthly 
city and only the Universal Ship Defender 
can protect them. The aliens are a 
dastardly lot — Landers, Mutants, Bomb¬ 
ers, Pods, Swarmers and Baiters. The De¬ 
fender must ward off these no-goodniks, 
firing laser missiles and detonating smart 
bombs. If Landers abduct humanoids, the 
heroic Defender must blast them from 
the sky, catch the falling humanoid and 
carry him safely to the earthly city.” 
(Please don’t think / wrote that deathless 


prose!) $37.95. Berserk, coming in Au¬ 
gust, offers “a courageous humanoid 
dodging through a maze shooting nasty 
robots before they zap him. Out of no¬ 
where appears grinning bouncing Evil 
Otto who loves to squash careless human¬ 
oids.” $31.95. And in September, Star 
Raiders, in a “galactic shoot-em-up . . . 
with the television your space ship. 
Armed with deadly photon torpedoes and 
protective shield, you steer through dis¬ 
tant galaxies searching for alien space 
craft. A special radar scope lets you anti¬ 
cipate enemy maneuvers.” $37.95. All 
that and comics too! (Do you think 
it’s a coincidence that Atari and DC are 
both subsidiaries of Warner Communica¬ 
tions, Inc.?) (Reader Service No. 422) 

While we’re on about Atari, Edu- 
Soft has announced the availability of 
their educational programs written origi¬ 
nally for TRS-80 and Apple II on Atari 
400/800. Used, they say, in “thousands 
of classrooms across the country,” these 
programs “feature mathematics instruc¬ 
tion, drill and games, and include con¬ 
cepts used in graphing, algebra and arith¬ 
metic, and computer simulation.” Well, 
this may be a good way to get the kids to 
learn something besides lightning reflexes 
on your home computer. Guess the Rule 
(recognize relative sizes of numbers) and 
Reverse (strategy) are in Package W-2. 
Plot (display and compare graphs) and a 
different Guess the Rule (algebraic guess¬ 
ing game in arcade format) in Package 
W-3. Simulated Computer (simulation of 
a small machine-language computer) in 
W-4. Fraction Recognition and Mixed 
Number Recognition in W-5. Cassette is 
$14.95; disk, $19.95. Add $2 per order 
for shipping and handling. Write for free 
catalog. (Reader Service No. 432) 


Fine Freebies 

After playing Computer Stocks & 
Bonds, you may want inside information 
on which stocks to invest in. For a free 
report on high technology companies and 
their performance in 1981 write to High 
Technology Growth Stocks (a newsletter; 
don’t be surprised if they send you a sub¬ 
scription pitch with their list). (402 
Border Rd., Concord, MA 01742; 617/ 
369-5382) 

Get a free reference sheet for the 
TRS-80, giving all the Z-80 mnemonics 
for opcodes 0-255 in decimal, hex, and 


octal, ASCII code identification of print¬ 
er control codes, keyboard characters, 
graphics codes, space compression (TAB) 
codes, BASIC’s reserved word token 
codes, four number base conversion 
tables (powers of 2, 16, 2-to-16 conver¬ 
sion, hex-to-decimal), a program that 
converts LSB-MSB to hex, and articles 
that clearly explain conversions in both 
directions. I’ve got one; it’s packed with 
information. Send a #10 SASE to ABS 
Suppliers, and specify Model I, II, or III. 
(3352 Chelsea Circle, Ann Arbor, MI 
48104;313/971-1404) 

CAVRI Systems Ink (really) is a free 
newsletter for interactive video users. 
CAVRI systems link video recorders and 
computers. (From the photos in their 
newsletter, it looks like they use Apples.) 
CAVRI systems are used to train helicop¬ 
ter pilots, by the Navy for engineering 
courses, by universities to develop inter¬ 
active video courses, etc. (26 Trumbull 
St., New Haven, CT 06511; 203/562- 
4999) 


Applications Areas 

We received notice of some applica¬ 
tions software for your HP-85. LIST/85 
is a mail list program by Tensegrity, Inc. 
It has a zip sort, random access search, 
and the ability to concatenate records in 
memory with any LIST/85 disc or tape 
data file without bringing that file into 
memory. Each complete address is a rec¬ 
ord of five fields; each field can have up 
to 32 characters. Up to 100 records (500 
fields) can be in memory at a time. $145 
includes data cartridge, disk, manual, 
holder, and 600 self-adhesive label 
samples. (Reader Service No. 442) 

How about a utility to duplicate 
BASIC or system tapes for your TRS-80 
Model I or III? How about paying only 
$1 1.95 ($9.95 plus $2 shipping and hand¬ 
ling) for it? On a Model III it also con¬ 
verts 500 baud to 1500 and vice versa. 
You could change Scripsit to 1500 for 
faster loading, for example. It’s called 
COPY-TAPE, and it can also scan 
through memory to see the ASCII of the 
program you duplicated, and has a veri¬ 
ly command. Use it on a Model I level II 
or Model III BASIC (both with 16K or 
more). David Modney guarantees his tape 
to load, or he’ll replace it. He ships with¬ 
in three working days. 

Here’s another inexpensive program 
for your TRS-80 from David Modney, 


Dr. Dobb’s Journal, Number 67, May 1982 


13 

199 





called Automatic Graphing of Functions. 
It plots formulas in the form Y=f(X) or 
Y=Y+f(X), graphs discontinuous func¬ 
tions, and plots simultaneous equations 
on one graph. The graph goes to a printer 
with just “the push of a key.” Modney 
claims his program is “Bug-Free!” It runs 
on the same machines as COPY-TAPE, 
and costs $19.95 plus $2 (s and h). 
(Reader Service No. 452) 

I can’t resist cute names, and who 
can resist a video text editor for $90? 
MR EDit doesn’t sound like it’s exactly 
a word processor, but it seems close. It’s 
fully screen oriented. The cursor moves 
by character, word, line and screen. Dele¬ 
tion is by character, word, or line in any 
direction. MR EDit has extensive search 
and replace. It has something called 
“paste buffer manipulation commands.” 
(Could that be for text movement?) User- 
defined command keys allow custom con¬ 
figuration to any non-memory-mapped 
CRT. Micro Resources Corporation sells 
MR EDit for CP/M and MP/M systems 
with 20K transient program area and a 
CRT with at least 12 lines of 64 or more 
characters. It’s available on 8-inch single 
density or 5!4-inch soft-sectored floppy. 
The manual alone is $12.50; that price is 
refundable on order of the editor. 
(Reader Service No. 462) 

Apple V.I.P. II from Micro-SPARC, 
Inc., outputs VisiCalc grids to a printer 
the way they are formatted on the screen, 
in columns and rows. To customize 
spreadsheet reference reports, you can 
select from seven different combinations 
of column width and number of columns. 
A fast machine-language disk read and 
sort routine does all this. It automatically 
compensates for long formulas by seg¬ 
menting and printing them in clear con¬ 
tinuous blocks, and does the same for 
very wide reports. It sells for $29.95. 
(But they forgot to tell us what form it 
comes in!) (Reader Service No. 482) 

Computer Camps 

Want to get the kiddies off your 
computer so you can use it, and still keep 
them happy? Send them to a computer 
camp! That seems to be the newest wrin¬ 
kle in specialized camps. There are tennis 
camps, art camps, music camps, and now 
Specialty Camps, Inc., will conduct Atari 
Computer Camps for 10- to 18-year-olds 
at four locations, two four-week sessions 
at each. The camps will be at the Univer¬ 
sity of San Diego, Asheville School, in 
Asheville, NC, Lakeland College in 


14 

200 


Sheboygan, WI, and E. Stroudsburg State 
College in E. Stroudsburg, PA. The cur¬ 
riculum has been designed by Atari’s 
education specialists. (Reader Service 
No.492) 

For 12- to 18-year-olds who want 
to have a week of intensive BASIC with 
one computer for each two campers, 
Lake Forest College, 30 miles north of 
Chicago, will have four computer camp 
sessions from June 20 to August 6. The 
camp director is Dr. Lowell Carmony, As¬ 
sociate Professor of Mathematics and 
Computer Studies. (Reader Service 
No.502) 

Computer Camps, at Santa Barbara 
and Lake Tahoe, offer two-week sessions 
for 100 10- to 18-year-old campers, and 
include such computer-related crafts as 
robot assembly. The counselors also in¬ 
sist that the kids see the light of day. Cost 
is $795. (Reader Service No. 512) 

Rancho Oso Summer Camp of Santa 
Barbara has been around since 1960. 
They offer 56 9- to 15-year-olds two- 
week sessions for $675. They recently ac¬ 
quired a bank of Atari 800s, and also 
stress horsemanship and riding. (Reader 
Service No. 522) 


Community Calendar 

Graphics Interface ’82 will be held in 
Ontario May 17-20. You’re too late for 
early registration, so it will cost anywhere 
from $75 for conference students only to 
$345 for general admission to all tutorials 
as well. It’s in coordination with the Uni¬ 
versity of Toronto, and sponsored by the 
National Computer Graphics Association 
of Canada (NCGA) and the Canadian 
Man-Computer Communications Society 
(CMCCS). Tutorial topics include com¬ 
puter graphics, digital image processing, 
raster graphics, computer-aided design, 
graphic design for computer graphics, 
user interface design, Videotex, manage¬ 
ment graphics. (961 Eglington Ave. E., 
Suite 200, Toronto, Ontario M4G 4B5; 
(416) 424-4758/3482) 

The First Regional Conference on 
Technology and Special Education is 

being presented by the New York State 
Association for Educational Data Systems 
on May 22. Computer Applications in 
special education for administrators, 
teachers, and parents will be discussed at 
the Mill Neck Manor Lutheran School for 
the Deaf, Frost Mill Rd., Mill Neck, LI, 


NY 1 1765. Contact Dr. Dolores Shanahan 
of Commack Public Schools (Indian Hol¬ 
low Computer Lab, Kings Park Rd., 
Commack, NY 1 1 725 ; 5 16/493-3431) 
or Jerry Burke of Half Hollow Hills High 
School (Dix Hills, NY 11746; 516/549- 
6792). 

A conference on Local Area Net¬ 
works will be held May 25 and 26 at the 
Halloran House, New York City, by Frost 
& Sullivan, Inc., who describe themselves 
as “a leader in communications, data pro¬ 
cessing, and office of the future market 
research.” (Future market research? Is 
that something like crystal-ball gazing?) 
Topics will include selecting the best 
LAN for your company, applications, 
LANs integrated into the office of the 
future, baseband vs. broadband, standards 
and protocols, voice integration and data 
tradeoffs, and prospects for PBX and CBX. 
Moderator will be D. R. MacNaughton, 
president of Business Development Inter¬ 
national, consultants in computers and 
data communications. MacNaughton is 
project director for Frost & Sullivan fac¬ 
simile, electronic mail, and computer 
maintenance studies. They list no price 
for attending, but you should contact 
Account Representative Carol Sapchin. 
(106 Fulton St, New York, NY 10038; 
212/233-1080) 

The Technical Education Research 
Centers (TERC) are giving workshops on 
Microcomputers in Education at Gutman 
Library in Cambridge, Massachusetts, 
May 18-20 and at the Taft School in 
Watertown, Connecticut, June 7-9 for 
“professional development for educators 
at all levels, elementary through college.” 
(Stuff like that is put in quotes because 
I don’t know what “professional develop¬ 
ment” means and you shouldn’t think 
that’s my terminology.) Workshops will 
“emphasize hands-on experience,” they 
say, on a “variety” of micros. Extensive 
workshop reference materials will be 
“given” to participants, and there will be 
evening symposia on current trends in 
microcomputer applications to educa¬ 
tion. Hotel accommodations will be 
“available.” (8 Eliot St, Cambridge, MA 
02138;617/547-3890) 

Virginia Polytechnical Institute and 
State University is offering a workshop 
on personal microcomputer interfacing 
and scientific instrument automation, 
May 31-June 4. Contact Dr. Linda Leffel. 
(Blacksburg, VA 24061,617/547-3890) 


Dr. Dobb’s Journal, Number 67, May 1982 



The MUMPS User’s Group are hold¬ 
ing their eleventh annual conference June 
7-11 at the Denver Hilton. (You’ll re¬ 
member them from last August’s Of In¬ 
terest. MUMPS is a microcomputer lan¬ 
guage used in medical and business en¬ 
vironments.) Hardware, software, and sys¬ 
tems vendors will be there. There will be 
presentations, tutorials, workshops, dis¬ 
cussions. (Box 37247, Washington, DC 
20013;301/779-6555) 

A workshop on the design and crea¬ 
tion of “‘user-friendly’ computer pro¬ 
grams for immediate use in classroom, 
office or home” will be conducted July 
6-23 at Fresno State University by Dr. 
Dan Isaacson, Editor/Publisher of Course- 
Ware Magazine. Price is $153, with addi¬ 
tional unspecified charges for “materials” 
and other university fees. The course is 
aimed at teachers and business persons 
who want to “design innovative programs 
as effective teaching or working tools,” 

. . develop effective computer-based 
learning experiences,” and produce “use¬ 
ful and marketable” software. The maga¬ 
zine offers a scholarship refund of tuition 
and fees to each participant who com¬ 
pletes the course and writes “a well- 
designed program accepted for publica¬ 
tion” by the magazine. (Caveat emptor.) 
(Reader Service No. 532) 

The National Conference on Artifi¬ 
cial Intelligence will be August 16-20 at 
Carnegie-Mellon University and the Uni¬ 
versity of Pittsburgh. Featured topics will 
be robotics and something called “expert 
systems.” Growing out of AI research, ex¬ 
pert systems are computer programs with 
large stores of specialized knowledge, to 
solve complex problems by imitating the 
decision-making processes of human ex¬ 
perts and, in some cases, outperforming 
humans. Expert systems are now used in 
medicine, geology, and business, and will 
soon be available on home computers to 
help with tax forms, automobile main¬ 
tenance and repair, etc. A two-day tu¬ 
torial will give a nontechnical look at Al 
August 16 and 17. Other topics include 
computational vision, programmable au¬ 
tomation, game playing, and knowledge 
representation (what?). Carnegie-Mellon’s 
new Robotics Institute will be a focal 
point of the conference. Further informa¬ 
tion is available from the American As¬ 
sociation for Artificial Intelligence. 
(Reader Service No. 542) 


Dr. Dobb’s Journal, Number 67, May 1982 


15 

201 




Program for a Modem 

Forth Code From the Conference Tree 


T he modem is your computer’s link 
to the telephone — a window to 
databases maintained by thousands 
of individuals and organizations. If you 
want to write your own program to con¬ 
trol a modem, there are several different 
ways to proceed. You may use calls to 
the manufacturer’s firmware supplied in 
the modem, you may ignore the firmware 
and program the modem hardware direct¬ 
ly, or, if you have a “smart modem” (one 
with its own built-in microprocessor), 
you would communicate with the modem 
by using control sequences of ASCII 
characters. 

This article concerns primarily the 
second alternative; programming a Hayes 
MicroModem II* for the Apple II** by 
directly accessing the modem chip, ig¬ 
noring the firmware. This writeup may be 
useful to several groups of programmers: 

(1) Those who want to program the 
MicroModem II directly, in any language, 
will find information here not readily 
available elsewhere. 

(2) Those interested in programming 
a computer to control other external de¬ 
vices may find this example useful. 

(3) The code shows various FORTH 
techniques in an application, not a teach¬ 
ing example. 

This code is used in The Conference 
Tree, a program for computer conferenc¬ 
ing. Anyone with an Apple II, 48K, one 
or more floppy disk drives, and a Hayes 
MicroModem II can sponsor computer 
conferences, which may be accessed by 
anyone with a 300 baud or 110 baud ter¬ 
minal (not necessarily an Apple). New 
messages are always attached to other 
messages already in the conference, form¬ 
ing a tree of messages structured by the 
users; any user’s entry may become the 
start of a new conference. Various other 
features such as public and private con¬ 
ferencing, seven levels of password 
protection, and a “turing test,” which 
allows the conference sponsor to make 
sure that only persons (not computers) 
log on, are provided. As far as is known, 
there is no way to crash the system or 


by John S. James 

John S. James, c/o CommuniTree Group, 
470 Castro St., Suite 207-3002, San 
Francisco, CA 94114. 

J_8 

202 


violate its security from a remote loca¬ 
tion. For more information on The Con¬ 
ference Tree, see “The Conference Tree” 
by this author, in Dr. Dobb's Journal 
#60, or write to The CommuniTree 
Group. 

One caveat — the code released here 
is from a working system, but is not a 
polished teaching example. It could use 
substantial improvements. For reliability, 
we chose to release the code as is and ex¬ 
plain how it should be improved, instead 
of giving it a facelift for publication. 

The code published here has been 
placed in the public domain by The Com¬ 
muniTree Group. It contains information 
not readily available elsewhere, thanks in 
large part to the excellent help we have 
received from Hayes Microcomputer 
Products in answering our questions and 
volunteering advice on matters we had 
overlooked. Remaining deficiencies are of 
course the sole responsibility of the 
author. 

How the Program Is Organized 

The Apple provides seven “slots” 
which the modem (or other peripheral 
device) may be plugged into. The slot 
numbers are 1 through 7. The modem has 
several one-byte control and status regis¬ 
ters, which are accessed through addresses 
in the 6502 address space; the addresses 
are functions of the slot number. 

The purpose of the modem control 
section of The Conference Tree program 
is to build up several operations which 
may be used later in the application code 
to do useful work. The most important 
of these operations are XKEY (read a 
character from the modem), XEMIT 
(write to the modem), GETCALL (do 
everything necessary to receive a phone 
call, matching the user’s terminal baud 
rate and parity if any), and XHANGUP 
(hang up the phone). 

A rudimentary knowledge of 
FORTH should be sufficient for reading 
most of this program. As we chose to im¬ 
plement The Conference Tree entirely in 
higher-level FORTH, there is no 6502 
code. 

Screen By Screen 

FORTH source code is traditionally 
organized as “screens” of 1024 bytes 
(16 lines by 64 chracters). Since the 
Apple II uses 40-character Ones, most 
Apple FORTH systems organize the 
screen as 24 40-column lines. 



Screen 32 

This “load screen” compiles the rest 
of the source code. 

Screen 33 

Two Apple-specific operations are 
defined. ?KEY tests whether a key has 
been pressed on the Apple, and returns a 
boolean, or truth value — “1” if a key has 
been pressed, “0” otherwise. On some 
(but not all) FORTH systems, 7TERMI- 
NAL does the same thing. 

KEYLOOK returns the value of a 
key that has been typed, like the FORTH 
word KEY. But unlike KEY, it does not 
wait in a busy loop if no key has been 
pressed, but returns zero instead. 

Because these definitions use address 
and mask values, it is best to define them 
in hexadecimal. Since we follow the con¬ 
vention that all references to screen num¬ 
bers should be in decimal, we return to 
decimal before finishing the screen; other¬ 
wise, some numbers on the load screen 
would have to be in hex. 

Screen 34 

This screen defines PARITYTABLE, 
which has 16 entries, each zero or one, 
corresponding to whether the binary 
numbers 0000-1111 have even or odd 
parity. This table will be used for faster 
determination of the parity of an input 
or output byte. 

Screen 35 

RAM BYTES, defined in this screen, 
is an alternative to the FORTH word 
VARIABLE for allocating memory. It de¬ 
fines address constants, putting the data 
at any address desired and keeping it out 
of the FORTH dictionary, which should 
be kept ROMable. The author prefers 
RAM BYTES to VARIABLE for almost 
all uses, except for tables of constants 
which should be kept in the dictionary 
so that they will be loaded automatically 
(e g.. PARITYTABLE). 

It is the author’s personal convention 
to give flags names which end in “F” and 
to allocate two bytes for each, even 
though one would be enough, to avoid 
the danger of using 16-bit operators by 
mistake. 

* MicroModem II is a registered trademark of 
Hayes Microcomputer Products, Inc. 

** Apple II is a registered trademark of Apple 

Computer, Inc. 

Dr. Dobb’s Journal, Number 67, May 1982 




Screen 35 — The Variables 

MODEMSLOT tells what slot num¬ 
ber the modem is plugged into. It must be 
set before the program is run. 

XSPEED keeps track of the pro¬ 
gram’s toggling between 300 and 110 
baud when a user is logging on. 

TEMP will be used for the original 
input character. The value returned by 
the input word has the high-order bit 
stripped off. The original value is needed 
for checking parity when a user first logs 
on. 

PARITY will indicate whether even 
or odd parity has been detected from the 
terminal. 

CHARINDEX gives the current posi¬ 
tion in the 80-character input line. It is 
here only because the modem must not 
echo a character typed past end-of-line. 

COUNT1 and COUNT2 are used for 
nested timeout loops, which automatical¬ 
ly hang up the phone if the user has done 
nothing for about ten minutes. 

CALL# counts the phone calls re¬ 
ceived since the system was last put 
online. 

LOCALF indicates local-mode oper¬ 
ation, i.e., using the system without the 
phone line as a local database. 

ABORTF is set if the session must be 
aborted due to timeout. 

NOLOGONF indicates that logons 
have been disabled, because the operator 
needs to take the system down at the end 
of the current session. 

HALFDUPLEXF indicates halfdu¬ 
plex vs. fullduplex operation. Full (pro¬ 
gram does echo characters typed by the 
user) is assumed unless a command 
(TERMINAL) is used to set to half. If 
you want to handle both modes, it is bet¬ 
ter to start with fullduplex, as users will 
be less confused if the characters they 
type print twice than if they don’t print 
at all. 

Screen 36 

Here the three registers used — the 
Ring, Status, and Data registers - are set 
up. These registers, on the ACIA chip 
used in the modem, are accessed through 
byte addresses in the 6502. Every refer¬ 
ence to a register computes its address as 
a function of the slot number where the 
modem is plugged in. It would be more 
efficient to compute the address only 
once, but there is no problem keeping up 
with 30 characters per second in either 
case, so we chose to simplify the code 
instead of optimizing its speed. 


For details on the registers, see the 
MicroModem II manual. 

XINIT initializes the modem. It first 
puts the byte “3” into the status register, 
as required by the ACIA chip. Then it 
checks the XSPEED variable to decide 
how to initialize the status and ring regis¬ 
ters — 300 or 110 baud. Later operations 
will reinitialize at each speed alternative¬ 
ly, while a new user is trying to get on, 
until a carriage return character is recog¬ 
nized. (The user is told to type two car¬ 
riage returns to start using the system.) 

Screen 37 

X7HUNGUP tests whether the user 
has hung up (or the carrier has otherwise 
been lost). 

First, the LOCALF flag is checked to 
see if the system is in local mode (operat¬ 
ing without the modem or phone at all). 
If so, we cannot be “hung up,” so a zero 
(boolean false) is returned. Otherwise we 
put a zero on the stack, then check the 
status register, doing a bitwise AND with 
binary 4 (00000100) to get the not- 
carrier-detect bit. If that bit is on, we 
reinitialize and test again in case it was 
only a momentary interruption (this may 
not be necessary); if it is still lost we drop 
the zero and replace it with a one (boole¬ 
an true) to indicate that the user has hung 
up. 

Screen 38 

7ESCAPE is a special operation used 
to allow the operator of the conference to 
gracefully shut it down without interrupt¬ 
ing a user online at the time. If a user is 
on when the operator needs to take down 
the system (e.g., to use the Apple for 
something else), the operator can press 
the ESC key, and the user will receive a 
message that the computer is needed in 
five minutes. Also, all further logons will 
be disabled. Alternatively, the operator 
may press Z, to silently disable further 
logons, allowing the current user to finish 
the session normally. 

Parts of this operation are a bit com¬ 
plicated, and not necessary for under¬ 
standing the modem software itself. The 
dummy operation is for allowing a for¬ 
ward reference to be patched in later; the 
operation which actually sends the “com¬ 
puter is needed” message to the user must 
be defined later in the program, after the 
modem operations are available. KEY- 
LOOK returns the value from the buffer 
where the Apple key input is stored. If it 


is ESC or Z, 7TERMINAL DROP clears 
the keyboard strobe, 07 EMIT beeps the 
Apple speaker, and the NOLOGONF flag 
is set to boolean true, to disable any later 
logons. The operator is informed that 
logons are disabled. If the key was ESC, 
the user is warned, and a boolean true is 
returned by 7ESCAPE, indicating that the 
user’s command has been interrupted and 
should be aborted. 

Screen 39 

Although the micromodem is able to 
set parity automatically, we chose to do 
all the work ourselves. EVENPARITY 
uses a table lookup of each four bits of 
the byte to set even parity quickly. SET- 
PARITY tests the carriage returns initial¬ 
ly typed by the user, and sets the 
PARITY variable to tell the program 
which parity to output. XKEYLOOK 
reads a key from the modem, except that 
if no key has been typed, it does not hang 
in a busy loop but returns “0”, and if the 
phone has been hung up, it returns 
“256”, an impossible value for any key to 
return, as an indicator. 

Screen 40 

XEMIT sends a character to the 
modem. XEMITP does the same, with 
even or odd parity applied. XHANGUP 
hangs up the phone. XWAITRING waits 
for the phone to ring; as explained below, 
this definition should be improved. 

Screen 41 

ECHO echos the character that the 
user typed back to the terminal, if the 
terminal is operating in fullduplex. Echo 
does not occur if the terminal is in half¬ 
duplex, or if a backspace was typed, or 
if the user was at end of line (column 80). 
Carriage returns also are not echoed, al¬ 
though the program should probably have 
been organized so that they would be, to 
make sure the user gets immediate feed¬ 
back. 

Screen 42 

TIMEOUT? automatically hangs up 
the phone if the system has been waiting 
for input for about ten minutes. The 
main purpose is to protect users against 
forgetting to log off (hang up) when they 
have called long distance. It also prevents 
malicious users from disabling a tree by 
calling up and leaving the phone connect¬ 
ed indefinitely. Incidentally, the timeout 
probably cannot be done through the 


Dr. Dobb’s Journal, Number 67, May 1982 


19 




firmware supplied with the modem — one 
of the reasons we bypassed it and con¬ 
trolled the chip directly. 

TIMEOUT? uses two nested loops to 
keep track of how long the system is in 
a busy loop waiting for a key to be 
pressed at the terminal (two loops were 
used since a single loop could not count 
high enough without using 32-bit num¬ 
bers, which are not available in older im¬ 
plementations of FORTH). If timeout 
does occur, the phone is hung up, and 
the number on top of the stack is re¬ 
placed with a non-zero value, which will 
terminate the busy loop in XKEY. 


Screen 43 

XKEY waits for a modem key to be 
typed. It must also check for timeout, for 
phone hung up (loss of carrier), and for 
the ESC or Z keys which may be pressed 
by the computer’s operator. XKEY masks 
off the high bit of the character (7F 
AND), but saves a copy of the original 
byte in TEMP where it may be used to 
detect parity. 


Screen 44 

GETRING is part of GETCALL, 
screen 45. This section of the code should 
be cleaned up and perhaps reorganized. 

GETRING prepares to wait fora call 
by making sure the phone is hung up and 
the modem is initialized. If logons have 
been disabled by the system operator (by 
using ESC or Z explained earlier), it in¬ 
forms the operator that the system is now 
clear, beeps (07 EMIT), and pauses 
(?KEY DROP KEY DROP); the ?KEY is 
to make sure no key struck earlier is wait¬ 
ing to be read. If the operator decides to 
allow further logons after all, any key 
may be pressed to continue. 

On the operator’s log (on the Apple 
Screen — it may also be directed to a 
printer) the program prints the call num¬ 
ber, and the system status of waiting for a 
call. When the phone rings, the log shows 
that fact. In addition, the log shows the 
ASCII values of all characters received 
until a correct carriage return is recog¬ 
nized. (The XCR operation which prints 
this value is poorly named and placed in 
the code, but we chose not to change it 
now.) 

Incidentally, for privacy reasons, the 
operator’s log does not show what mes¬ 
sages are read or written, only the com¬ 


20 

204 


mands used plus any erroneous com¬ 
mands or attempts to guess the password. 
The Conference Tree even allows private 
conferencing without the knowledge of 
the system operator, although the opera¬ 
tor can set a password requirement to 
prevent it. 

Screen 45 

GETCALL makes sure the local¬ 
mode flag is off, i.e., the system is being 
used over the telephone. Then it goes into 
a loop to receive calls, and only termi¬ 
nates when a proper carriage return is de¬ 
tected. In other words, GETCALL will 
ignore any number of erroneous calls that 
may occur (e.g., voice calls, 1200 baud 
which the micromodem cannot use, etc.), 
and terminate when it receives a good 
call. 

The loop does a GETRING, makes 
sure the keyboard strobe is clear, then 
toggles the speed between 300 and 110 
baud, initializing each time. The “0” 
(not-timeout boolean) makes the UNTIL 
stay in the BEGIN . . . UNTIL loop unless 
a carriage return is found and the zero 
is replaced (DROP 1), terminating the 
loop. Parity is set from the carriage return 
character at this time. 

Screen 46 

SLOTTEST provides an error mes¬ 
sage if there is no card at all in the desig¬ 
nated modem slot. The address of the 
slot’s instruction space is computed, and 
read twice (DUP @ SWAP @). If there is 
no card, random values will be returned; 
if the values are different, an error mes¬ 
sage is given. 

Testing 

If you want to test-run this code, be 
sure to initialize MODEMSLOT, CHAR- 
INDEX, CALL#, LOCALF, ABORTF, 
NOLOGONF, and HALFDUPLEXF. Rea¬ 
sonable values are zero for everything ex¬ 
cept MODEMSLOT. 

Execute GETCALL, then have some¬ 
one with a terminal dial in and type a 
couple of carriage returns. You should be 
able to send ASCII characters, using 
XKEY and XEMITP. 

Improvements 

Since the program was written, we 
have learned of two recommended im¬ 
provements in the modem control. 

When the ring is detected, the pro¬ 
gram should wait until the ring finishes 


before picking up the phone, in order to 
avoid putting ring current over the 
modem contacts. Presumably the change 
can be made in XWAITRING. We have 
not had any problem with the present 
version, however. 

Also, GETCALL should have a sepa¬ 
rate timeout, probably 30 seconds, to 
detect the carrier, and then timeout if no 
carriage return is received. The present 
timeout of approximately a minute leaves 
the system unavailable for that time in 
case of a voice call due to a wrong num¬ 
ber. The screen may even show several 
lines of garbage as the phone company’s 
message to please hang up comes on. No 
harm results, but future products should 
include this improvement. 

Smart Modems 

A smart modem is one which in¬ 
cludes its own microprocessor. Control is 
usually accomplished by ASCII sequences 
communicated between the modem and 
the computer. The advantage of a smart 
modem is that it doesn’t care what com¬ 
puter is used; it talks to a standard RS- 
232 interface. 

CommuniTree Group is using a smart 
modem from Hayes Microcomputer 
Products for converting The Conference 
Tree to run under CP/M. 

Anyone planning to use a smart 
modem should know that many serial 
cards use only three lines of the RS-232 
cable - data in, data out, and ground. 
With these serial cards, the modem has 
no way to tell the computer that the user 
has hung up the phone, except by ASCII 
sequences which may be hard to distin¬ 
guish from data typed by the user. Pro¬ 
grams like The Conference Tree, which 
must run unattended, require that any 
serial or communications card used with a 
smart modem support at least the ability 
to detect carrier, and possibly other fea¬ 
tures such as ring detect. 


(Listing begins next page) 


Dr. Dobb’s Journal, Number 67, May 1982 



Modem Program (Text begins on page 18) 


SCR tt 32 
( LOAD SCREEN) 

33 LOAD 34 LOAD 35 LOAD 36 LOAD 
37 LOAD 38 LOAD 39 LOAD 40 LOAD 
41 LOAD 42 LOAD 43 LOAD 44 LOAD 
45 LOAD 46 LOAD 


SCR tt 33 

( APPLE-SPECIFIC OPERATIONS) 

HEX 

: ?KEY (-300L. LIKE 7TERMINAL, BUT) 

( TESTS ANY KEY) 

C000 C@ 80 AND 

IF 1 CO10 CO DROP ELSE 0 THEN ; 

: KEYLOOK ( -CHAR-OR-O) 

?KEY 

IF C000 C@ 7F AND ELSE 0 THEN ; 
DECIMAL 


SCR tt 34 

( MISC. DATA STRUCTURES) 

( PARITY TABLE OF 16 O-OR-1 VALUES) 

HEX 

0 VARIABLE PARITYTABLE OE ALLOT ( 16) 

( THE FOLLOWING OPERATION 'T' IS A 
TEMPORARY COMPILE-TIME OPERATION 
WHICH IS DEFINED, USED TO LOAD THE 
TABLE CONVENIENTLY, AND THEN 
FORGOTTEN.) 

: T ( 16# - MOVE NIBBLE PARITIES IN) 

10 0 DO PARITYTABLE I + C! LOOP ; 
0110 1001 1001 0110 T 

FORGET T 
DECIMAL 


SCR tt 35 
( VARIABLES) 

: RAMBYTES ( ADDR N-ADDR. ALLOCATE) 

OVER CONSTANT + ; 


24000 ( ADDRESS TO START THE DATA AREA) 

2 RAMBYTES MODEMSLOT ( SLOT tt ) 
2 RAMBYTES XSPEED ( 300 OR 110 ) 
2 RAMBYTES TEMP ( INPUT CHAR ) 
2 RAMBYTES PARITY ( ODD OR EVEN ) 
2 RAMBYTES CHARINDEX ( INPUT LN INDEX) 
2 RAMBYTES C0UNT1 ( FOR TIMEOUT ) 
2 RAMBYTES COUNT2 ( FOR TIMEOUT ) 
2 RAMBYTES CALL# ( COUNT FOR LOG ) 
( FLAGS) 

2 RAMBYTES LOCALF ( TRUE=LOCAL OP ) 
2 RAMBYTES ABORTF ( T=KILL COMMAND) 
2 RAMBYTES NOLOGONF ( T=LOGONS DISAB) 
2 RAMBYTES HALFDUPLEXF ( T=HALF ) 
( DATA AREAS) 

81 RAMBYTES AREAS ( INPUT BUFFER ) 
CR ." NEXT AVAILABLE ADDRESS:" . CR 


SCR tt 36 

( MODEM REGISTERS; INITIALIZATION) 

HEX 

: MMRING ( ---ADDR. MODEM RING & CNTRL) 
C085 MODEMSLOT @ 10 * + ; 

: MMSTATUS ( ---ADDR. MODEM STATUS) 
MMRING 1+ ; 

: MMDATA ( ---ADDR. MODEM DATA) 

MMRING 2+ ; 

: XINIT ( - INITIALIZE) 

3 MMSTATUS C! ( MUST DO THIS FIRST ) 
XSPEED @ 

IF 8B 15 ( 300, NO PARITY ONE STOP) 
ELSE 8A 11 ( 110, TWO STOPS) 

THEN 

MMSTATUS C! MMRING C! ( SET SPEED) ; 
DECIMAL 


SCR tt 37 

( DETECT IF USER HANGS UP PHONE) 
HEX 

: X7HUNGUP ( ---BOOL. 1=HUNG UP) 
LOCALF @ 


(Continued on next page) 


Dr. Dobb’s Journal, Number 67, May 1982 


21 

205 





Modem Program (Listing continued, text begins on page 18) 


IF 0 ( NOT 'HUNG UP' IF LOCAL) 

ELSE 

0 ( FLAG) 

MMSTATUS C@ 4 AND ( CARRIER LOSS?) 
IF XINIT MMSTATUS C@ 4 AND 
( STILL NO CARRIER?) 

IF DROP 1 ( HUNG UP) THEN 
THEN 
THEN ; 

DECIMAL 


SCR tt 38 

( SESSION ESCAPE) 

HEX 

: DUMMY ; 

: ESCMSG ( - DUMMY - PATCHED LATER) 

( THIS WILL SAY COMPUTER IS NEEDED) 
DUMMY ; 

: ?ESCAPE ( BOOL. T=ABORT THE CMND) 

KEYLOOK DUP IB = OVER 5A = OR 
IF ( 'ESC' OR 'Z' KEY PRESSED) 
?TERMINAL DROP ( CLEAR STROBE) 
07 EMIT ( BEEP TO OPERATOR) 

1 NOLOGONF ! 

CR LOGONS DISABLED" CR 
IB = 

IF ( ESC KEY PRESSED) 

USER WARNED - 5 MINUTES" CR 
ESCMSG 1 ( ABORT) 

ELSE 0 ( NEEDN'T ABORT) 

THEN 

ELSE DROP 0 ( NEEDN'T ABORT) 

THEN ; 

DECIMAL 


SCR # 39 

( MODEM PARITY; CHARACTER LOOK) 

HEX 

: EVENPARITY ( N-->-N. SET EVEN PARITY) 
DUP 000F AND PARITYTABLE + C@ 

OVER 00F0 AND 10 / PARITYTABLE + C@ 
+ 1 = 


IF 80 + THEN ; 

: SETPARITY ( TEST FIRST C/R) 

TEMP C@ 80 AND 80 XOR PARITY ! ; 

: XKEYLOOK ( N;0;256 XKEY NO WAIT) 

MMSTATUS C@ 1 AND 

IF MMDATA CO 7F AND ELSE 0 THEN 

X7HUNGUP IF DROP 100 THEN ; 

DECIMAL 


scr n 40 

( MODEM WRITE; HANGUP PHONE; WAIT RING) 
HEX 

: XEMIT ( N---.) 

BEGIN MMSTATUS C@ 2 AND UNTIL 
MMDATA C! ; 

: XEMITP ( N---. HANDLE PARITY) 

EVENPARITY PARITY @ XOR ( ODD?) 
XEMIT ; 

: XHANGUP ( - HANG UP PHONE) 

9 MMRING C! ; 

: XWAITRING ( -WAIT FOR CALL) 

BEGIN ( WAIT FOR RING) 

XHANGUP MMRING C@ 80 AND 0= 

UNTIL ( PHONE RINGS) ; 

DECIMAL 


SCR U 41 
( ECHO, MI SC) 

: ECHO ( N-N. ECHO TO REMOTE) 

( DON'T ECHO IF: ) 

HALFDUPLEXF @ 

OVER 127 AND ( STRIP PARITY) 

DUP 8 = ( BACKSPACE) 

OVER 13 = OR ( CARRIAGE RETURN) 
SWAP 127 = OR ( ALSO BACKSPACE) 
OR ( HALFDUPLEX) 

CHARINDEX @ AREAS 79 + = OR 
( AT COL. 80) 

0= IF DUP XEMIT THEN ; 


SCR # 42 

( TIMEOUT IF USER DOES NOTHING) 


22 

206 


Dr. Dobb’s Journal, Number 67, May 1982 



HEX MMSTATUS C@ 4 AND 0= 

: TIMEOUT? ( FLAG-FLAG. TEST IF IDLE) if TEMP C@ . THEN ; 

1 COUNT1 +! COUNT1 @ 80 = 

IF 0 COUNT1 ! 1 COUNT2 + ! 

COUNT2 @ 384 ( SECONDS - HEX) = 

IF DROP 100 

XHANGUP 1 ABORTF ! 

THEN 

THEN ; -- 

DECIMAL SCR # 45 


SCR # 43 

( READ A CHARACTER FROM THE MODEM) 

HEX 

: XKEY ( -N. 256=HUNG UP) 

0 COUNT1 ! 0 COUNT2 ! 

0 ( INITIAL VALUE) 

BEGIN 

MMSTATUS C@ 1 AND 
IF 

DROP MMDATA C@ ECHO 
DUP TEMP C! 7F AND 
ELSE 

X?HUNGUP IF DROP 100 THEN 
7ESCAPE IF DROP OD ( C/R) THEN 
THEN 

TIMEOUT? 

DUP UNTIL ; 

DECIMAL 


SCR # 44 

( GETCALL - FIRST PART) 

HEX 

: GETRING ( -) 

XHANGUP 3 MMSTATUS C! 15 MMSTATUS C! 
NOLOGONF @ ( NO FURTHER USERS ON?) 

IF CR SYSTEM IS CLEAR" 07 EMIT 
?KEY DROP ( CLEAR STROBE) 

KEY DROP ( PAUSE FOR OPERATOR) 

0 NOLOGONF ! 

THEN 

1 CALL# +! ( INCREMENT CALL #) 

CR #" CALL# @ 3 .R 

WAITING FOR CALL.." 

XWAITRING ." RING" CR 6 SPACES ; 
DECIMAL 

: XCR ( ---. TYPE CHARACTER ON LOG) 


( GETCALL - RECEIVE A VALID CALL) 

HEX 

: GETCALL ( ---. RECEIVE PHONE CALL) 

0 LOCALF ! ( SET REMOTE MODE) 

BEGIN ( RECEIVING CALLS TILL OD) 
GETRING 

?KEY DROP ( CLEAR STROBE) 

0 XSPEED ! ( TOGGLE - 300 FIRST) 

( TOGGLE SPEED TILL GET C/R ) 

0 ( INIT NOT-TIMEOUT BOOL ) 

E00 0 

DO ( 60 SECOND TIMEOUT) 

XSPEED 1 TOGGLE XINIT 
XKEY OD = XCR 

IF DROP 1 SETPARITY LEAVE THEN 
LOOP ( TILL FIND CR OR TIME OUT) 
UNTIL ( NOT TIMED OUT) 

OD XEMITP ( RETURN THE C/R FOUND) 

." CONNECTED" ; 

DECIMAL 


SCR # 46 

( TEST TO MAKE SURE SLOT NOT EMPTY) 

HEX 

: SJ..OTTEST ( ---. ABORT IF NO CARD) 
C000 MODEMSLOT @ 100 * + 

DUP § SWAP @ - 
IF CR 

." ERROR, NO CARD IN MODEM SLOT " 
MODEMSLOT ? 

CR ." RESTART PROGRAM" 

7 EMIT 
BEGIN AGAIN 
THEN ; 

DECIMAL 


End Listing 


Dr. Dobb’s Journal, Number 67, May 1982 


23 

207 



This publication 
is available 
in microform. 


"Hu tu i in.11 

”oi 11:1 no 

■ matin hcmiur ■•••mmimai 



University Microfilms 
International 

Please send additional information 

for_ 

Name_ 

Institution_ 

Street_ 

City_ 

State_Zip_ 

300 North Zeeb Road 30-32 Mortimer Street 
Dept. PR. Dept. PR. 

Ann Arbor. Mi. 48106 London WIN 7RA 
U.S.A. England 


A Simpler Way 

North Star-to-Epson 


A recent article (A. Bomberger, 
“Connect a Parallel Printer to 
Northstar,” DDJ No. 62) describes 
the use of the Epson MX-80 with the 
North Star Horizon microcomputer. 
Several months ago 1 installed an Epson 
MX-80 F/T with Graftrax 80 on a North 
Star Horizon (11-Quad, 64K HRAM) and 
have been immensely satisfied with the 
results. 1 use the system with the latest 
release of North Star DOS (5.2) and 
with Lifeboat Associates’ CP/M version 
2.23a. One of the main functions of the 
system is to run Micropro’s WordStar 
version 3.00. I have found this to be a 
very powerful and cost-effective system. 

It should be pointed out that this 
configuration is more easily implemented 
than Bomberger indicates. I, like 
Bomberger, was at first concerned that 
the handshaking signals between the Hori¬ 
zon and the Epson were not directly com¬ 
patible. I compared the data transmission 
signals of the Epson printer with those of 
a Centronics printer that had been suc¬ 
cessfully connected to the Horizon paral¬ 
lel output port without any hardware 
modification. As these data transmission 
signals were identical (the Epson printer 
is indicated to have a Centronics Standard 
Parallel Interface) I had hopes that the 
implementation of the Epson printer 
would be straightforward. In fact, the 
only hardware tailoring I found to be 
necessary was in the wiring of the parallel 
cable to connect the North Star with the 
Epson. I wrote my own drivers for the 
North Star DOS, for CP/M, and for 
WordStar; however, the drivers were prac¬ 
tically identical and closely model those 
from an earlier release of the North Star 
DOS. The drivers permit the transfer of 
all 8 bits to the parallel port, and thus 
make full use of the graphics capability 
of the Epson printer. While I don’t know 
how my drivers will hold up under an 
interrupt request (this is a concern of 
Bomberger), I do know that in the fore¬ 
seeable future they will not be required 
to do so. The best comment I can make 
about this implementation is that it 
works. For other North Star Horizon/ 
Epson MX-80 users, this system may be 
an easier and entirely satisfactory system 
to install. 


by Larry Shoer 


Larry Shoer, Department of Chemistry, 
Lake Forest College, Sheridan & College 
Roads, Lake Forest, IL 60045. 


Table 1 is the pin-to-pin configura¬ 
tion of the parallel connector cable. The 
driver in Listing I is used for the North 
Star DOS. I also set the byte at location 
0ABC to C9 (RET) and the byte at loca¬ 
tion 0ABD to 00 (NOP). This prevents 
the printer from being initialized with a 
carriage return when the system is boot¬ 
ed. I prefer this arrangement; otherwise, 
the printer must be turned on for the 
system to complete its cold boot, whether 
or not the printer will actually be used. 

To use graphics from North Star 
BASIC it is necessary to first initialize the 
printer by outputting the reset command: 

PRINT #2, CHR$(27),CHR$(64) \ 
REM RESET PRINTER (ESC @) 

To prevent North Star BASIC from auto¬ 
matically inserting carriage returns in the 
middle of the graphics output, it is also 
a good idea to disable the automatic 
carriage return generation by outputting 
the following command: 

LINE #2,80,0 \ REM DO NOT 
SEND AUTO CR TO PRINTER 
(DOS 5.2) 

The driver in Listing II is used for 
CP/M, and requires the Epson ON LINE 
button to be cycled prior to printing a 
file. While some may find this an incon¬ 
venience, I prefer to leave this func¬ 
tion. The requirement of cycling the ON 
LINE button forces me to check the 
paper status prior to the actual print 
operation. The driver in Listing III is used 
for WordStar. It overwrites the WordStar 
port driver location. It supports status 
checking and, therefore, allows efficient 
simultaneous printing and editing. The 
North Star port driver can be installed 
with the WordStar Patcher, which may be 
invoked under the WordStar INSTALL 
program. The labels used in the above 
code will be recognized by the WordStar 
Patcher. To complete this phase of 
the installation, the WordStar Patcher 
should be instructed to set CSWTCH: 
equal to 01 (this selects the newly installed 
driver) and to set HAVBSY: to FF (this 
indicates that a busy test is available). 
This driver also requires the Epson 
ON LINE button be to cycled prior to 
each printing operation. The requirement 
of cycling the ON LINE button forces 
me to check the paper status prior to the 
actual print operation. This is especially 
useful since different forms will be used 
for different correspondence. 


26 


Dr. Dobb’s Journal, Number 67, May 1982 




Connection 


Table 1 

North Star Parallel Output Connector Egson HX;;80 F/T 


signal name* 

pin 


pin 

signal name 

data bit 7 

1 

— 

7 

data 8 

data bit 5 

n 

- 

7 

data b 

and 

T 

- 

17 

chassis gnd 

data bit 2 

4 

- 

4 

data 3 

data bit 0 

ST 

w l 

- 

2 

data 1 

PO-f1ag 

6 

- 

- 

— 

ack 

7 

- 

10 

acknlg 

spare 

s 

- 

i 

strobe 

data bit 6 

9 

- 

o 

u 

data 7 

data bit 4 

10 

- 

.£> 

data 5 

data bit 3 

1 1 

- 

5 

data 4 

data bit 1 

12 

- 

"T 

data 2 

gnd 

1 7 
i 

- 

- 

— 

gnd 

14 

- 

7,7 

gnd 

gnd 

15 

- 

1 6 

logic gnd 


* Confifuration as preset by North Star Computers. No user 
modification is necessary. For a description of these signals 
see Horizon Computer System Manual <2501 IB) pages 42 to 44. 

North StarlEpson 

Listing I 


0AC5 


;SPRINTER PARALLEL OUTPUT 

ROUTINE 

0AC5 


C0UT2 

EQU 

% 


0AC5 

DB06 


IN 

b ; 

READ MOTHERBOARD STATUS 

0AC7 

E601 


AN I 

1 

MASK Tn GET THF PO FI AG 

0AC9 

CAC50A 


JZ 

COU72 ; 

PRINTER NOT YET READY 

0ACC 

-7C3 


MOV 

A. B ; 

GET CHARACTER TO ACC 

0ACD 

D300 


OUT 

0 ; 

OUTPUT TO PRINTER 

0ACF 

3E20 


MV I 

A.20H ; 

LOAD PO RESET COMMAND 

0AD1 

D306 


OUT 

6 ; 

RESET PO FLAG 

0AD3 

78 


MOV 

. B t 

CHAR EXPECTED IN ACC 

0AD4 

C9 


RET 



0AD5 

00 


NOP 


NOP USED TO MAINTAIN 

0AD6 

00 


NOP 


ALIGNMENT WITH 

0AD7 

00 


NOP 


OTHER DOS 5.2 ROUTINES 


% RErERENCE: 

;HORIZON COMPUTER SYSTEM 
;MANUAL <25011B> PAGE 44 
; SYSTEM SOFTWARE MANUAL 
; < 25013B > PAGE H-2 
;SYSTEM SOFTWARE MANUAL 
;ADDENDUM <25501F) P. 11 
End Listing (Listings II &r III begin on next page) 


Dr. Dobb’s Journal, Number 67, May 1982 


27 

209 





North Star/Epson (Listing continued, text begins on page 26) 

Listing II 







S ihis USER AREA is for a Horizon computer 



;as used in a 

24K Lifeboat CP/M2 on North Star. 



;Change 

MSI ZE 

to the memory size desired 

0018 = 


MSI ZE 

EQU 

24 .Distribution system 



sCOUT2: 






3 F'arai 1 ei port output. 

5AE4 

DB06 


IN 

6 ;READ MOTHERBOARD STATUS 

5AE6 

E601 


AN I 

1 ;MASK TO GET PO FLAG 

5AE3 

CAE45A 


JZ 

CQUT2 ;PRINTER NOT YET READY 

5AEB 

79 


MOV 

A,C sGET CHAR TO ACC 

5AEC 

D300 


OUT 

0 ;OUTPUT TO PRINTER 

5AEE 

3E20 


MV I 

A.20H sLOAD PO RESET COMMAND 

5AF0 

D306 


OUT 

6 s RESET PO FLAG 

5AF2 

79 


MOV 

A,C ;CHAR EXPECTED IN ACC 

5AF3 

E57F 


AN I 

7FH ;MASK FOR ASCII CHAR 

5AF5 

C9 


RET 

;RETURN WITH CHAR IN ACC 

5AF S 

00 


NOP 

:NOP USED TO MAINTAIN 

5 AFT 

00 


NOP 

SALIGNMENT W/ HORUSER.ASM 

5AFS 

00 


NOP 

:<LIFEBOAT'S CP/M) 

5AF9 

00 


NOP 

;REFERENCES 

SAFA 

00 


NOP 

;HOR. COMPUTER SYS MANUAL 

5AFB 

00 


NOP 

;<2501 IB) PAGE 44 

5AFC 

00 


NOP 

:SYSTEM SOFTWARE MANUAL 

5AFB 

00 


NOP 

;(25013B) PAGE H-2 

5AFE 

00 


NOP 

;SYSTEM SOFTWARE MANUAL 





;ADDENDUM (25501F) P. 11 

5B49 

C9 


RET 

;CODE REMOVED TO OUTPUT 

5B4A 

00 


NOP 

;A CARRIAGE RETURN TO THE 

5B4B 

00 


NOP 

SPRINTER DURING COLD BOOT 

5B4C 

00 


NOP 

;NOP USED TO MAINTAIN 

5B4D 

00 


NOP 

;ALIGNMENT W/ HORUSER.ASM 





; (LIFEBOAT' S CP/M) End Listing 

Listing III 





0728 

DB06 

POBSY: 

IN 

6 ;INPUT MOTHERBOARD STATUS 

072A 

E601 


AN I 

1 ;STATUS 0 - NOT READY 





; 1 - READY 

072C 

2F 


CMA 

;REVERSE STATUS FLAG 

072D 

IF 


RAR 

;PUT FLAG IN CARRY 

072E 

C-9 


RET 

;STATUS CHECK COMPLETE 

072F 

00 


NOP 

SNOP 7 S MAINTAIN ALIGNMENT 

0730 

00 


NOP 

SWITH WORDSTAR PORT 

0731 

00 


NOP 

3 DRIVER 

0732 

00 


NOP 

m 

0733 

D300 

POSEND: 

OUT 

0 SOUTPUT CHAR FROM A REG 

0735 

3E20 


MV I 

A.20H sLOAD PO RESET COMMAND 

0737 

B306 


OUT 

6 SRESET PO FLAG 

0739 

C9 


RET 


073A 

00 


NOP 

S NOP 7 S MAINTAIN ALIGNMENT 

■ ■KB 



c * > 

SWITH WORDSTAR PORT 





SDRIVER 

0744 

00 


NOP 

End Listing 


28 

210 


Dr. Dobb’s Journal, Number 67, May 1982 


Add a System Clock 


F or a variety of applications, a system 
clock in a computer system is desir¬ 
able in order to keep track of the 
temporal sequence of events and their 
durations. Examples include records of 
computer usage and accounts, perfor¬ 
mance evaluation and time-slicing in a 
time-shared operating system. Frequent¬ 
ly, several clocks are required to monitor 
various events simultaneously. For exam¬ 
ple, in performance analysis of a comput¬ 
er system, we would like to have a sepa¬ 
rate clock to record the system elapse 
time, CPU-utilization time, disk seek and 
latency times, job mean queue time or 
printer I/O time, etc. 

Since the Cromemco computer does 
not provide any hardware clock, we have 
implemented a software simulated clock 
system in an independent, small Z80 or 
8080 microcomputer, external to the 
host Cromemco computer. 

Hardware 

The clock simulator is implemented 
in a microcomputer consisting of four 
boards: 

1. ZPU board 

2. TUART board (serial I/O board) 

3. BYTESAVER prom board 

4. Memory board (8K RAM from 
Industrial Micro Systems). 

The first three boards are from Cro¬ 
memco since we have some extra Cro¬ 
memco boards for backup purpose, but 
any other similar board can be used for 
the clock simulator instead. The BYTE- 
SAVER contains a Cromemco Z80 moni¬ 
tor (ZM-108) in a IK ROM at Hex ad¬ 
dress E000. The ZPU board is operated at 
2 MHz and is configured for power-on 
jump to Hex address E000, where the 
Z80 monitor resides. A CRT (9600 baud) 
is connected to the serial Port A of the 
TUART board as control during initializa¬ 
tion. The clock simulator program itself 
resides in a 2708 PROM at Hex address 
F000 on the BYTESAVER board. To 
enter the clock simulator program from 
the Z80 monitor, one simply executes the 
“G” or GOTO command by entering 
G F000 (Carriage return) 
on the CRT. 


by Michael Kan 


Michael K. Kan, c/o Scripps Memorial 
Hospital, 9888 Genesee Ave., La Jolla, 
CA 92037. 


30 


At this point, the CRT can be dis¬ 
connected and a 3-wire cable is used to 
connect serial Port A of the clock simula¬ 
tor to the clock serial port of the host 
computer. Pin 2 (send) and pin 3 (re¬ 
ceive) of the clock simulators’s serial port 
are connected to pin 3 (receive) and pin 2 
(send) respectively of the host computer’s 
serial port so that the clock simulator 
would act like a peripheral device to the 
host computer. Pin 7 of both serial ports 
are connected to signal ground. 

The host computer used to test the 
clock simulator and for performance 
analysis is a Cromemco Z-2 computer 
equipped with 32K bytes RAM, a 4 FDC 
disk controller, a Persi 277 disk drive and 
a TUART board. One of the two serial 
ports on the TUART (Port B at Hex 
address 50) is used as a printer port. The 
other serial port (Port A at Hex address 
F0) is used as an I/O port for communica¬ 
tion with the clock simulator. This port is 
operated at 9600 baud. 

Program 

The clock simulator program pro¬ 
vides two independent 32-bit clocks to 
keep track of the system elapse time and 
printer I/O time used in performance 
analysis. More clocks can be easily added 
if required. Each clock is implemented 
in 4 bytes of RAM in the low memory 
while the clock simulator program 
(SOFTCLKR) resides in a 2708 PROM at 
Hex address F000 (Figure 1 on page 34). 
The assembly program of SOFTCLKR 
is listed in Figure 2 on page 34. The 
SOFTCLKR program consists of a timer 
loop (timer subroutine) which provides 
the necessary time delay for each clock 
increment. The exact timer delay depends 
on a counter value which can be varied to 
meet a wide range of needs. A counter 
value of 23 Hex or 35 decimal is used in 
the clock simulator. The clock interval in 
this case is measured to be 0.1844 milli¬ 
second. 

The clock simulator is controlled by 
commands from the host computer sent 
over by way of the serial port and 3-wire 
cable. Command 0 resets both system and 
printer clocks, commands 1 and 2 start 
and stop the system clock while com¬ 
mands 3 and 4 start and stop the printer 
clock. Commands 5 and 6 retrieve the 
clock data from the system and printer 
clocks respectively. 

The clock simulator scans the serial 
port for commands between the timing 
loops. The first five commands (0-4) are 


carried out by turning on or turning off 
the appropriate software switches stored 
in the lower RAM of the clock simulator. 
The software switches are represented by 
INITFG, SYSSW and PRTSW on the 
SOFTCLKR program listing. The clock 
simulator responds to commands 5 and 6 
by sending 4 bytes of clock data (least- 
significant byte first) from the system 
and printer clocks respectively to the host 
computer. The maximum clock time de¬ 
pends on the clock interval. For a clock 
interval of 0.1 millisecond, the maximum 
clock time is 119 hours 18 minutes and 
16 seconds. 

Application 

As an example for applying the clock 
simulator, we are going to go through the 
various steps in order to find out the 
system elapse time and printer I/O time 
in a prime number generator program. We 
shall assume that a simple BASIC pro¬ 
gram (PRIME1.BAS) as shown in Figure 
3 on page 36 is used to generate the 
prime numbers. 

Apart from the prime number gene¬ 
rator program, two other programs are 
used to initialize the clock simulator and 
to print out the clock times at the end of 
the test program. These two programs 
and the test program (PRIME 1.BAS) are 
stored in a commmand file for batch 
operation. The first program in the com¬ 
mand file is a JOBBEG program imple¬ 
mented in FORTRAN (Figure 4 on page 
37). This sends commands to the clock 
simulator to reset all clocks and turn on 
the system clock just before loading the 
test program specified in the command 
file. Each test program has incorporated 
instructions to turn on the printer clock 
just before a prime number is printed on 
the printer and turn off the printer clock 
after completion of printing. 

The last program in the command 
file is a JOBEND program which sends a 
command to the clock simulator to stop 
the system clock and then gets the sys¬ 
tem and printer clock data and prints 
them out on the console. The listing of 
JOBEND program is given in Figure 5 on 
page 36. The host computer’s console 
outputs are given in Figure 6 on page 38. 

Discussion 

Although our host computer is a 
Cromemco Z-2 computer, the clock 

(Continued on page 57) 


Dr. Dobb’s Journal, Number 67, May 1982 

2TT 



> 

X 


) — x a. 

< LDX A (' a 

) xx a □ 

J iH h(k jot 

h IUJ 

'I x r-.j » uj uj 

• a. r Kuo. 

4- 1 w k □ □ □ 

J 'X iHihl- 

UJH 0 ) I/) CO 

: —j lu uj co u. uj uj 

• o> CO 


^ X 

CO □ UJ UJ 

a □ z _j 
z _j x a x 

LU X CO lu 

*> z > 

> □ □ UJ 

r-o 


-x 

lu a a. 
c h z a 

»-< UJ LU □ 

H ID CO -J 


H O' X IX' 

CO HQ 
> □ X X 
co \ A o. 


\ X «_■ jl 
u. a a j 

O -J 
X H 

E UJ U. 
□ H X Q 

CL CO I CO 


vj XI 
mUID I- 
Z X 

X H > O 
X X h 

e x — 

a a x a /-. 

•-'HU. uj x 

co z xx 

X UJ — X 
O Ot. A [Jj 

X X X □ 
H □ Di 
H X U'X 

X X CO 


X X 
CO -J X 
C’J — X CO . 
UJ X CO ' 
X > X UJ 
OX UJX I 
Cl X Ci l 
X X X Ci I. 

H Z X l 
H X * t 

x a h 
a h x 
X X — Q ■: 

> X X 
CO — CO ► 

jj x h ( 

H X X X C 
CO X H 1=1 >: 


>1 X N XX NX X CO CO — — X X N X X H Zi 

y £? y r ? ? r ??>XQXXPQXO 

w • ' f !XX X_J Qu “X X X 111 


H X 00 X XX i 

— 1 Cl OX X N 

□ or x o 

x _J » —- > ., « 

-J «H(6QiIO 
X — 

D 3 
X 

X X 

X Z _J 

□ H J W N H h i 

J H > I u I > J ! 

O E *J O "i I □ ' 


X- HO XX 
X X Q 

X i—i X LD L' 
— X X Q 
'/> H X jl 
A Z X O 

x x ci a 
x x a Z' _j 

XX CO O 

x z 


XXX 3 X 
x x r j a . 

- x - _i - 

h r _j x _j 

x. a x Du 

□ '-' - X JL 


xxxxxx XXX 

u- O © — X — OJ C 0 -t 
00 o CO CO CO CO CO 
o O -O O o o o o o 


i OO GO Q O Q> 

1 X X XX XXX 


ax x 

> 

.r ,r. □ 


X XCO CO X X 
; x h cold Dili □ 
i Ci X xx H x H 

I- M i* M «,-) 


OCU-lf'tt«C«OU.OO N O X — <U X Ct X X X 
O IT' o X fu OJ X - X N X O A 00 IT' c o C. Cu o x X 

(U o UjhOOOD X OC' 'Ll X o cu X O 0 *. Xi A X ‘£i X X 

x c x a. x x cu o x> x ci x o> x x ci co ci o x x x 

cu r- o c n oo cu oo cu ~ cu cu *oooxx — ®<ru.u. 
CO X O X 10 Cu O' CU (J o o CO CO O X O' x C 00 CO X X 

o Cu X r - Cu X •* — A A — o XXX CO J . CO '£i — X X 

O' CO X If' x O' CO — O Ci CO o x Ci O X Oi Ci X X X X 

X c x X * o X o O CO X X >7 — XX — c O vD X X 

CO O CO O' CO O cu o x O' X <r. O' X CO CO X C O CO X X 

O 'X' c O x X o x 00 o a o O A o CO J' X X X X 

O X X o CUXXOON^OiXCrCXXQXOOXX 

— cu rv x o o oo if> a so o — — cu x + o x - o x x 

X CO X X X o cu Ci Oi X •=■ x O' X X X 00 X 00 X X 

CU o A o N — CU IT' 00 o x CU cu If X X CU — CO XXX 

CO O (J O ID X Oi X O O X Oi CO CO X O' X X X X X X 


j id X QCuXfOXtt(U(ll-X-OXfuOG| 

:• x x x co co x ® x co •=• x ® oo co « o i 


o cu x x o x r- a- x x >J- cox ~ x oo x x x 

X CO X CO CO X CU 00 Oi X C' X CO O'XXXOiXXXX 

'M ® CU O X N ® 'O «-• r -- X $ • ® X •=• O C O X - X X 

CO •=• CO X CU X' X O' X 00 CO O' X ■=• ® ® •=• 00 CO O X X 

o * o a' ® in oj ® ^ co ® o o< « if • x x x *-« co x x 

X ® N X O' CU X P O' X x u x LL Q O' X X X X X 


j cu tf 'm r ■- x cu co x 

0 CO X If' X u CU X 


1 x •=• CU CU X ~ X X 
:• X X CO CO x CD X 


X — X X x 

© O Cu X CU f - ’t CU X 'O' CU CU CO • X >*0 <£> X X N J- X 

© © 00 X ID CO OJ N X O' CO CO x X mIUmUHUX 

© (») X (£| t CU C't CU N X^UJUJOlXX^OX^X 

UJ x x x CO •© CO (J X CO X X CO X X X x 00 CO x X 


»-« CU CD X 

CO CO X O' 


:• a. x x uj i 

:• x >’u x co i 


:• X + X Cu •£• — CO l 
_ X X UJ X i—I l 


• © © © © © © © © X X X X X X X 

■ OJ CO rt ID 'XI f - 0 C' a • X X X UJ X 

. o O X X X O O O X X X X X o o 

.xxxxxxxxxxxxxxx 


© © © © © X 
X — CU CO + ID 


a x h 

D _ X 

X 1-4 O' 

XX Q 

• Z. </f _l 


I □ If- X J 

' -r- □ x 

X O' > 

I D Ol X 

H D i/ t it 

■ H — X 

□ X JH 
X X _J X 
I —i Z' 

i x x a 

: I oo O' 

• H CU t 

+ X 

' H X 0 C' I 

i x a — h 


X 1-0 

Jx x z 

X Oj X 

x a cu 

-J «l CO (/■) 

HU X 

X X H 

> X I z 
X X H Z 

H 

X (/ ) • E 

U. > X 

■X (O' z X 

□ *H 

O’) UJ Oi 

X X X «| 
HH 

> -H Z 


x r <? ■ 

XX ~ 

Q _J « *H 
X • 

C/J X X X 

HZ □ 

►H X X 
X X _J 
Ahl 

CU JL z > 

CO Oi X Ql 


-J z 
□ a 
IE 4 ZOi 
X H X 
HZUM 
Z □ H 
►H O' I ~ 
Ql Oi 
X X H. ID 

X I z 

X X 3 Hi 
I H 


X(J H 
H H > 
M »-H _l X 
X 2 □ 

X i/i X I/O 
X X 
X ^ Z X 
X X u 
x a > h 


O X 

H X H jl 
X H x O' 
X X z □ 
H, X _J 
X X Oi 
JL X X 
Oi H X 

a ■* x x 

OI E ~ H 

X z ~ 
X H x X 


£ 

X 

Q 

X 

Z X A 

X > X H 

H > 

> X CO 

UJ 

Z 

eo 

□ 

'••• ' X 

X 

Z X > z 

□ CO X Z 

Z CO 

A _J X 

I 

X 

X 

X 

> 

□ Z' A CO 

W X — 

*-« 

A X 

H 

X 

oo 


> H 


i_i C/j 

o X 

X X 

> X > X 


3 

O 

u 


PL. 

X 

XXX 

Z JL X JL 

X H 

X CO x 

A 

H 

X 

Q 

X 

X X X X 

hOi Oi 

a 

X •- X C’j 

z 

X 

o_ 

w 

X Z 

H 

X Z X 

h a h a 

X A 

> A > — 

X 

A 

Ui 

X 

x *-• 

z 

r — ~ 

co x r _j 

I 





• 

H CO 

-J 

X CO X H 

h O' X O' 

H • 

H X H LD 

JL 

A 

X 

X Z 

Q X •- H 

CO X 

/v 

x a oi x 

Oi 

X 



X 

Oi 

O' AX 

Z X X _J 

CO 3 

Z XH 

□ 

C'j 

__ 1 

—1 

_l M 


a _j □ x 

a x x x 

*-< C' j 

XXX — 

-J 



Oi 

X z 

X 

XX H 

O' H O' X 

H 

X _l C’ J z 

o 


u 

H 

-- □ 

X 

X > X 

CO z ~ 

*. X 

H A X — 


CO 

|m 

X 

C-'j Oi 

H 

X A X 

I > — X 

O' X 

X X X 

X 


u. 

Q 

X 


H X Q 

Oi CO X 

a - 

X Z I 

X 


CO 

X CO 

> 

X H z 

X JL X 

-1 

X X Oi 

H 

JL 

o 


X - 

A 

X Z X X 

X CO Oi 

■_j I 

X X H 

CO 

Oi 



X _l 


X — Oj Z 

— a x 

Oi 

a > X — 

> 

X 

•X' 

LD _1 

X 

X X 

CO -1 

A H 

w -J 3 

CO 

H 


1 

□ 

X 

Z> * CO 

JL H Oi H 

Z — 

X X C'j 


CO 

<N 

00 

X X 

ZUU JUJ 

O) CO Z 

a 3 

X > □ 

X 


oj 

X 


□ X I 

□ X I X 

Oi C’j 

X — A 

I 

-J 

1 


X 

UJ _l > H 

_!•—'>_• v> 

X 

X H I X 

H 

X 

o> 


JL ^ 

X 

I Oi X 

Oi X X X 

C^i JL 

-s Oi — _ 


o 

X 


>_i X 

X 

H XX 

X X 

CJ 

H X X I 

I 

□ 

3 


Q — 

H 

X H X 

ax x 

x a 

X _J H 

H 

-J 

.£P 


_J • 

X Z I Z X 

HI X X 

i -j 

a x a 

a 


X 

Oi X 

M 

H Z 

H H •- X 

H o 

CO CO H X 

A 

X 

£ 

.. 

er ir 

■ r 


_ — .. .. . 

„ „ „ 


„ , 

, „ 


Dr. Dobb’s Journal, Number 67, May 1982 














hw X 

—t N 

(IhI •— 

z _j 

>r x 

Z GD - 

ll<I —CJ G 

KI L Z 

UJ G XCJ — 

x a 

G X_) G 

* UJ X'_ UJ 

K0 □ CO 

□ G 

Z » jlUI * 

CO COCO CO 

U UJ XUJ □ UJ 

ex z> 


it •/• Z > X CO Z> 


a. z 
a. — 
z x 

it G X 

k 

UJ G D UJ 

it CO Z CO 


it 

UJ it 

G UJ 

Z G 

- Z 

x - 

z a. <t 

it iL 

Zi X 

G □ G 

UJ G □ UJ 

X </) Z CO 


a it is 

a. uj •- 


it- * X 

OKuUJt- 
□ — X J ~ 
Z G 

I I- 1/1 G G 

I UJ Z X UJ z 

: s x □ s uj 

■ X □ CO 

• I- _J * 

CO * CO m 

I UJ CO □ UJ z 

: > ~ z > X 


I- (J IS 

LL G CJUJ X 
X XUI COZ G 
G XtO > □ «- 

x r--uj co z 

G '-'LL * x — 


k X it JLO it it it 3L □ 

u u Uj 2 CJ CJX 3 uuUJ 2 u JO: 3 

co co z i/j co gui i/p x g z co o. a uj / 

S > □ I/I □ IN I/J III IL □ H □ h N K 

UJ CO » > G X » > X X * X G x * X 

* 1..-1 X CO CO XX i/i * CO X X CO IS X X 


XI E G E ♦ G G 0J 

Eh iL h L X X G 

*—* X h- CO CJ X G CO 

G G X UJ G ./■ G X UJ G 

CO X G X X > X G A X 

'S IS i/i h- S CO X CO G S 


—— N — X 
NI ZX Z> G 
X I-H X«_I ~| Z CO 


hi— N«Xh-H N— Ih I- N « I h I- I 

x x z > »- x x z> gluxz>gujx; 

X CJ “>Z I/I X CJ “ E CO X -J ' 


X 

KGS 
H X X JL 
ZD JG 
— X D 
I CO X 
Z => * O 
□ h U 
Z X O G 


II X z 

SD □ * 
X U — 

X h- «-* 
X h- X II 
X N ~ 
.k. □ ~ G 
u X XX 

n x co 


XX ~ 
G X X Z 

k a lj s 
- □ - . 
-XXX CO ' 
Z co D x i 

J h- 

J it C Z </ i 

j U II X X 

O I h- X 

J X U C'l X I 

D G > I 


I OX 

a x 
x a> 
•=• z. •=• 

I X □ K 

x — — cu 

S X G 

x o x x 

o <_■ 

G O Z 
G X _l ~ 
X 

G G G 
G X X X 
X I- X 
h- x / :> a 

X CJ G G 

IX □ X CO 

a x x 

X h- CO 

CO I/I >- 

co 

~*U 

M. (J X X 
CJ G X S 
O — □ □ 
X 3 X X 

IX I/' X X 


x x x x 

> > Z z x : 

X UJ G l 

a □ i- z i 

x x z co — i 

x z ii > x : 

N □ •=■ co X ' 


XXIXXIXX 

O O - x O - (\J vs 

x o x X X X X 

® O O O O O O O 


Z GX X CO 
— X XX 
h J X* G X 
X XX X X 
Ih IllC) CO X 


J CO ExZI 

!' > X CO •— . 


Z X 
1 -iJl Jtx 

•X CJ X 

(- x X 
X I X u 

CO X CJ •— 


(j ^ CU CO ** CU 00 Jt 

x x □ a -f + -f 4-f-fSKS it. _ •J 

^ |^2 3XiiLtkitJilLXlL X X — Z Go 

O CO xi/' i/'XUULKJUGlUUhD h- UJ y> □ K > 

O » f\jc/i h- f v J CO CO iO CO h h h h m X X Z V' X X CO 

XX -> X . >>>>XXXXZGZZZ~>XK- 


h- co r-j xxzxxzxxzxizxo 


□ x x 

hXDX 
X X □ » 


Z Z G K 
— •-XX 

x x a a 

x x CO I/' 


s 

it II 3 3 jlx 

X □ hCOMXX 
I X X M CO h CO h 
G X Z Z > X > X 

• CO N □ •— CO X CO X ■ 


l r, H _ X X •— X X X X X X X X X X X •— X X •— •— X N X X N X X N X X N X 

>g g>GGGGGGGGGXOXNXgXNXZZOZ ZGZtGZZE 

□ j ECO CO Z CO CO CO CO CO CO CO CO CO CJ JG I G J G "| J H i i-i >— • • 1 *-1 •— 1 


Dr. Dobb’s Journal, Number 67, May 1982 

















□ 

f— 

X 


z: 

a 

z 


X 

□ 

'X 

— 1 

X 


£ 

eg 

lx 

oo 

o 


- > X 
' A a 
X 


□ CCiUi 
~ X 

H X (- 
X X 
X O X 

a a 

*- >- 
J Zlu 

x x r 



_l H- 

> > X Z 

x a o a 

z 


x z X 

< 

X o 
I □ 

1— A *-• A 

Z X z 

& 

1- _l 

— Z At W 

H 

o 

X 

x x a x 

DC 

a x 

E K J x 

O 

u. 

X 

jt (- 

o z 

~ A O- £ 
1- D ~ 

X K 

c 

a *- 

-1 X 

X W X 
Ih|-X 


o X 

i- X 

c 

<u 

E A 

W K 


• x t- 

u D X Z 
LODZ' 
l. Ui k a 


<u 

co 

\ 

N 


VO CU 

co co 


it o 

O D 
DO 
-JO 


Mn 
> X 

w x 

X X 

x □□ 
a x x 
►- x x 
x 

jii 
— > ►— H- 
XXX 
-<1=1 A 


CU X 

IT' -■ 
w K 
UJ X 
*- X 
X 
X D 
3 X 


CUX 

♦ K 
Ij 
►-a 
x - 


W 

H- 

H- 

cox 

♦K 

O 

NO 

a> 

K 

X 

H- 

»-+- 

ZX 

X 

X 

xz 

KJ 

X- 

K 

X 

XZ 

l-D 

X w 

xz 

ll£ 

X 

o 


□ H 

««•••) 

X 

xz 

X 

xz 

K 

z 

ii a 

h- 

XJ 

K 

X 

X 

II D 
h- 

X_J 

Ex 

x_. 

MU 

X 

-J 

i—_j 

z»r 

DO 

A 

l~_J 

zx 

DO. 

W_J 


V> K 

UJ «LL 

X ♦ K 

Z - x Z' 

» K D 

owe x ~ 

IT- X Z 
w >- II D 
UJX K 
HX X _J 
—X I- _j 

xa z. x 
3X D O 


tx 

in" 
'*■' K 

XX 
KX 
hhX 
XD 
3 X ' 


X 

K 

a 


Q 

Z 

w 

CQ 

o 


T3 

C 


X) 

o 


£ 

=5 

00 


- -- O D 
E Z _J 

«- O 
J * w 
-• f Z X 

=■ oo I 

k. — X H- 
■ D 

U •=• H IS> 

- X X 
- 1 l/> O -< 

: - z x- 

-• E X 
3 K h ,i * 

LIWI O 

- x o a 


w 


X X . 
--■CD — 

0 ~ X X I 
X 

- z x 
X D X 

* X K — 

- H _J 
X i—i _J 

. D X X 

: x x 


Z O A X 
— X H- 
Xl-I 
i I « J 
o h- Z Z 
D “ X 

J b. w h 

o □ x w 

<_* o o o o 


IT- O 

CO X 


\ ( 


X 

E 

X 


isi r j i 
\ \ ■ 
D D it • 
3 3 0' 

I- K C/j ■ 

» A 

XXX- 


* CD > > 

■g- _J X X 

X o 

r * ^ 

O X 

•=■ □ I- h- 

X X 

W X' X 
O (/ , 

•— •— X \ X D D 

sy ;m w ► oxhh 

D X X *• * X X A 

*"• X X X 
E X X X 

r * x 

EX 
^ EX 

x x a a 

•—Cl x t" ~ - 


l > > x : 

3 ~ - D . 
-XXXI 

J X X X I 
- *- K I- I 

: > ? x ' 

i X k-4 t_t | 


II II 


X > x 

D -H 
LL X W 


O 

CO 

01 

60 

CQ 

a 

c 

o 

V, 

,g 

'so 

0) 

J3 

* 

a> 


T3 

0) 

s 

.3 

o 

c 

o 

o 


Vi 

Si 

3 

.60 

E 

.* 

8 

o 

E 

aj 

w 

>i 

(0 


36 

214 


x 

□ 


□ 

X 


* 

o 

□ 


X 

X 

c- •-< 


M 

X 

X 

-I 

X 

X 


X 

z 

x 

w 


^3 

•S 

c 

0 

O 

.3, 

£ 


*- i 1 

WO X 


II- ~ X K 
NQZXXNQZ 
-)_ID«0C-)_JD 


♦ 

K 

W 


□ C* 
t > 

J X K 
] □ X 
J X X 


> 

A 

At 

o 

a 


x 

□ K 
O £ 


£ » 
£ ~K 

|aa 

H H 
XXX 
X Hi i— 


X x 
X X 

X 

® it x 

^ £ 


w 

Z c 

K • 

X 
H 

w 

K 

<«.«. 
0 A ID 
E -• 

• (/) X t/> 

X £ □ 

3 X □ K 
x X o \/> 
hk X 

» x 

x w a _i 


X 

x 


Jr ♦ h- 

X £ 

X h* X 

£ O 

K W O X 

•-< K 

X X K W K 

X 

H A X > X 

X X 

W K 0 W A 

0 z 


;fc& 


X 

K 

> 


X 

X 


CU 

■f H K 
CU At X X 
►“ OX K 


K - N 
X X Z £ 
X O “ h-. 


*-■ X h- *-1 th 
£ N A Z £ £ N A Z £ 
X .•_)□*-•£ “I _JD*-h 


X 

K 

(/> 


X 

X 

K 

£ 


O 

X 


X 

X 

* 


A 

A 

X 


i 

O 

W 

A 

i 

£ 

E 

□ 

O 

£ 

r 

□ 



K 

X 

A 

0 


X 

D 


CO 

£ 

£ 

X 

A 

A 


z 

£ 

K 

X 

X 

X 

w 

W 

X 

■* 




co At x x t k a. 

K o X I- H O X 

uj xkkxxxkk 
» l-XXKAKXX 
K WXAWKWXA 


I K «-< x h- K A 
i nb jr in o=.ui r 
■£ ua-ti jam 


CO 

< 

CQ 

.C 

E 

eg 

L- 

oo 

o 


U 

S 

5 

a. 


OJ 

c 

a> 

oo 

u» 

<U 

£ 

3 

C 

a> 

£ 


m 

QJ 


3 

W) 


A X 

* K 

Xi £ 

r 

w 

□ x 

A £ 

O -H 

- aL 

£ X 


W 

I £ 

X c 

Xi X 
□ I 
X *H 

X CO 

I 


A 

X 

X 

w 


A X 


w 

X 

X 

A 

E 

-J 

r 


x 

A 

£ 

Z 

£ 

X 


□ 

H 


X 

H 

D 

X 

X 

A 

E 

O 

£ 


X 

X 

X 

£ 

X 

Xi 

X 

A 

□ 


£ 

X 

£ 


X □ 

: X 

/ : i : i 

3 / / / / a 
•> CU CU CU CU £ 

aj / / / / ii 


X £ 

K 

$ 

K K 

K K 


£ £ 


X 

£ Z 

z z 



K 

~ a 


X 

X X 

X 

£ 

x z 

X X 



*-• 

X ~ 

X X 


A O 

o 

O 

o o 

o o 


« CU 

CO 

■* 

in x. 

N X 


Dr. Dobb’s Journal, Number 67, May 1982 





e i 
Cj to A h- 

x to z 

LL Lu □ X 
X □ 
'I MUJ 


□ K h- Z 

J U. Ii h UJ 

□ z z x 

LL LU 

Ll Z Z Z 

□ _J Z — 

•X - ID 

tO •— L-- LL 

UJ LL LL X (J 

I- X Z □ 

> tO □ UJ _J 

A X I |_| 


Z _J H 
•— Z X 
I/) Z xh 


Z _J 

□ X 

LL Z 


Z CU > X _l 
Z > X A I- >— 
I#l-iXX 


© » □ 
~ X LL w 
' □ H 

IT' - X X 
- h II □ 

mi t- 
►“ Z LL J 

Hill- J 

X □ X X 
3 X □ 


z o * 

LUX _| 
>Z Z I_l i/j 

xz x z z 
»» x uj a 

►-X OKU 
XX IW1U 
MX > tO 

_>I tO 


UJ X 
-J-l H- Z 
—1—J — X 
XX X □ 
OO X X 


X X X z 

x xi a 

□ x x- 1 - x — 

XXX Uh 
■ X □ tO •- X 

•:u x z x x 

X CU X X 3 X 


X X UJ X 

© □ _) Z □ X 

Oj X •— X □ 

I WZhiLlL 
Oj _• —% X 

oj' ' iff a X' %/t 

I X Z 1=1 


□ a -I _l I. 

i J X I X L 

Z I- , 


□ X X 
Ll X X 
□ X X 


I- X X X 
X K h- 
I- X X X 


K K -I X 
X X ■— t- 
I- X X X 
X H > A 
I- X X Z 


tO > X 

XX I— 

1L X 


If- 

Z X I X 

«t z 

X i-i D 
X X X I/J 
X 0 


X X □ X 


>— 



— 1 



X 

c 


to 


z 



x rsj 


X X 

A X K 


• A 



□ 



K 

c 

X 


X 

X X 

□ 


A \ 


X 

a xx 


□ E 


E 




X 

CO 

X 


X 

h- H 

h- 


* JL 


X CU 

X □ 1- X 


E X 



£ 



X 

fet 


to X 

a to 



jL 


•w LL 

K h- x 


to 



E 



X 

0U 

K 


-1 

A > 



t '.' to 



to oj E 


> 






E 

o 




to 



X X 


I/j X 

X E X 


E > 



A 



X 

ll 

z 

H 


1- 



Z X 


A ►— 

h- > LD 

© 

X A 



E 



LD 

a 


X 

X 

X X 

•—i 


— A 

N 

Z X 

jt © 

CO 




X 






z 


to I 

•—i 




X A 

X (J (0 

CO 

> E 



to 



CO 

r 

□ 

X 

K 

x ►— 





A 

A X X X 


A □ 






X 

W 

K 



X 

to 


X V! 


X 

XXX 

□ 




> 



X 

U 


to 

X 

to 

X 


to X 

CO 

© □ 

□ U A A 

H 

X Jt 



A 



A 

co 

Z 


1- 

□ H- 



X z 


© X 

K «— E 

□ 

-J (J 






E 

MJ 

X 

X 


1— X 

X 


X ►-* 

N 

X 

□ to 5 

LD 

a a 



X 


© 


CQ 

X 


□ 

X 

□ 

X 



cr «-■ 

X K *-« E 


«- X 



X 



E 

o 

ID 



X 1— 


□ 

X K 

A 

X 

X > 

© E 

to X 



□ 


CO 


w 

X □ 


□ 

D tM 


X 

h- X 

_i 

x - 

A A i-i X 

. X 







X 


□ X 


to 


O'* 


X iff 

X 

n 

E X A E 

r- /-v x 

> X 



X 


CD 

E 


X X 


1 

X z 


1 It 

□ X 

A 

X 1- 

Zi CO •- 

X' ~ K 

*-* X 00 


X 

♦ 

K 


c 



X 

-j X 

X 

X 

LL X 


X 

Z Z I- X 

N 1 

A K 

CO 


H 

CO 

□ 

X 


X z 

■X' 


Z X 

X 

A 

». w. 

(J 

x □ 

□ X 

CU Z E 

E © X' E 

© 


X 

*00 

X X 

or 

X 

E LD 

X 

A 

_ K X 

X 

H X 


H X Z 
Z □ X 

X tO </> □ 

is-., 

X -H E u 

(JO z 

H H X II 

r z ^ 

E E E E CU 

X X X X II 
X X X X 

o o o o o 
■Xi t'- X ffi © 
h h « « ro 


K — or«- 

□ X i\‘ H » 

Z X ► CO X 

.V X 

to r ~ / z 

E H X X OJ X 

X © / X 

I K Z h © h h 

X .V E 

. X E E I- ~ E 

< Z X X Z X X 

X X □ X X 


o © o © o o © © © 

-H (u m ♦ ir.i ••£> k x cr- 

!XI OJ OJ OJ CU CU OJ OJ OJ 


: z r r to 

|h««QUJ 
:xxx_j> 
x x x (J o 

© If) Xi © © 

I ■*■-*■*- IT' 'Xi 

I CO CO CO 00 CO 


* X _i □ 

Hi h II i-i 0 X 

a x a x x 

“J □ jL 

X X Z (J X 

© ►- X □ X 

00 Z X X _l I- 

I I— X U) IJ 

ld a > 


A □ X CJ 
X X X X 


X I- 

-• x a © 

X Zi z z 

X XXX 

CO X Z Z 

X z z 

I- H I- □ □ 

XX Z 

X X ~ 


□ XX—*-. 

if f tO i_i i_i 

to X CO to 

tO X A X X 


to X X X X 

X X X X X 

A I I I X 

II II II II II 

'IhluX 
I- X t o t o X 
X CO X LD X 


Dr. Dobb’s Journal, Number 67, May 1982 


37 

215 




38 

216 


Dr. Dobb’s Journal, Number 67, May 1982 





New USER for CPfM 


H ave you wanted to put computer 
listings on single sheets of paper to 
file in a note book or copy on a 
copying machine? The PIP utility in 
CP/M does this very well on continuous 
form, fan-folded paper but forget it with 
singe sheets! NEW USER will, among 
other things, allow you to print output 
on single sheets of paper that were pre¬ 
viously designed for form-feed controlled, 
tractor printers. 

The source listing, NEW USER, is 
a standard CP/M USER AREA assembled 
to operate on my computer. Like any 
USER AREA listing, it is unique to my 
computer. You will likely not be able to 
directly copy it unless you use an IMSAI 
MIO for device I/O, an IMSAI VIO-C for 
video display and an MX-80 F/T as the 
listing device. 

However, the main feature of trap¬ 
ping form feeds should be easily imple¬ 
mented on any other computer system in 
the CP/M environment. The warm- and 
cold-boot initialization section will only 
be helpful if you use the IMSAI VIO-C 
and haven’t yet figured how to keep the 
VIO-C out of “upper-case-only” mode 
or haven’t fixed the reverse video prob¬ 
lem found in early releases of this other¬ 
wise fine video board. 

Simply speaking (Doc told me to 
keep it short and simple), the console in¬ 
put routine checks each input character 
for a FORMKEY character. If a FORM- 
KEY character is found coming from the 
keyboard then the FORMBYT is toggled. 
That is, if it was an ASCII dollar-sign it 
becomes an ASCII space and vice-versa. 
This “switch” at FORMBYT selects and 
de-selects the form-feed trapping feature 
as well as directing the WARM BOOT 
message to either display a single line (no 
form feed trapping) or a second line 
(trapping form feeds). 

In the printer (or listing) output rou¬ 
tine, each character sent to the listing 
device is checked to see if it is a form 
feed. If it is not a form feed, control 
passes over the trapping routine and di¬ 
rectly to the output routine. If the out¬ 
put character is a form feed, then a 
second check is made to see if the form 
feed trap “switch” is ON. If the byte at 
location FORMBYT is an ASCII space, 
then the trap is indeed ACTIVE. If the 


byte at location FORMBYT is an ASCII 
dollar sign, then the trap is not active and 
control again passes over the trapping 
routine. 

In the trapping routine, printing out¬ 
put is suspended and a message is sent to 
the console notifying the operator that a 
form feed has been trapped and instruct¬ 
ing the operator to press the carriage- 
return key to continue printing. This is 
the time to load another single sheet of 
paper before pressing the carriage return 
key. 

Note: Select a FORMKEY value that 
doesn’t interfere with any of CP/M’s 
basic operations. I chose control-F. The 
integrity of the USER area is maintained 
except form feeds are cancelled and 
never reach the list device. 

I have used NEW USER for several 
months with solid results. Dot PRN files 
generated by MAC with embedded form 
feeds can be easily sent to the printer by 
activiating the form feed trap and using 
the TYPE command with a control-P to 
turn on the printer. PIPing files with the 
[P] option works well with the form feed 
trap option. 

If you run into any hidden problem 
with this that I overlooked, please let me 
and the readers of DDJ hear from you. 

(Listing begins on page 43) 


by Gene Head 


42 


Dr. Dobb’s Journal, Number 67, May 1 982 

2X7 





New USER for CPfM (Text begins on page 42) 


; Software from .> Head Quarters Cor vai 1 1 s, Oregon > 

» NEWUSLR» ASM for CP/M2 on North Star 

? UP.DATES AND REVISIONS 

; Version 3.4 of March 23, .1981 
5Ver sion 3.5 of Auqus t 22, 1981 

:MX—80 F/T DRIVER INSTALLED 8.22-81 

;FIX VIO.C HI-LITE PROBLEM 12-22-81 

;OPTIONALLY TRAP FORM FEEDS 1-1-82 

5 T r ap p i n g F/ F ’ s is d ynam i c a 11y set wit h t h e F 0R M KE Y k e y. 
5 Warrn bo a t message will reflect if F/F’ s are tr• apped 

; T h i s v ersion is for- CP/ M 2.2 x x 

5 Change M8IZE to the desired CF’/M memory size in K. 


* 

* 

* 

% 

* 

* 

* 

% 

* 

* 

* 

% 


MSIZE EQU 


; P u t y o u r s i z e h e i'¬ 


ll P r o c e d u r e i s a s f o 11 o w s :: 

!! On Assemble NEW USER. ASM but don’t LOA’O it 

5 1 * Run MOVCPM XX to the desired size (XX) 

; 2. SAVE 40 CPMXX.COM 

; 3. DDT CPMXX.COM 

", A. INEWUSER.HEX 

; B R (OFFSET) —> —> -.>.> .-> —> - 

5 C. C o n t r a 1 - C e i t f r o m D D T 

S -4. SYSGEN (DO NOT GET SYSTEM ONLY PUT SYSTEM) 

; 5. SAVE 40 CPMXX.COM 

? 

5 The -following equates are automatically changed by MSIZE. 


B IOS EQU 5300H+(MSIZE 24)* 1 024 ; 

BDOS EQU OSH ; 

USER E Q1J B10 S+700H 5 F o r d o u b 1 e / q u a d d e n s i t y 

; USER EQU BI0S+500H jiFor single densi ty 


OFFSET EQU 


2000H-BI OS 


To overlay SYSGEN IMAGE <• 


FALSE 

EQU 

0 


TRUE 

EQU 

NOT FALSE 


FORMKEY 

EQU 

’ F ’ -401-1 

;Key used to flip the trap 

FORMTRAF 


EQU TRUE 

; Condi. ti a na 11 y assemb 1 e TRAP 

IOBYT 

EQU 

t; 

;Store IOBYT 

VIDEO 

EQU 

OF803H 

5 V10 - C e n t r y p o i n t 

TTYDATA 

EQU 

02 

;Printer is the MX.80 F/T 

TTYMASK 

EQU 

10H 

5 Printer NOT BUSY if HIGH 

STATUS 

EQU 

03 

5 Status port on MIQ card 

KEYDATA 

EQU 

02 

;Parallel data port MIO card 

KEYMASK 

EQU 

02 

;Par a11e1 per t MASK M10 c a r d 

VIOFLAG 

EQU 

0F794H 

;U/L c ase b yt e on V10—C card 


(Continued on next page) 


Dr. Dobb’s Journal, Number 67, May 1982 
218 


43 




New USER for CP/M (Listing continued, text begins on page 42) 


VIOBYTE 

EQU 

2SH 

; Sets 0I0--C to U/L case mode 

CLEAR 

EQU 

0F800H 

;VI0-C clear and home cursor 

ASCMASK 

EQU 

07FIH 

; Mask out bi t 7 

BELL 

EQU 

07 

; ASCI I Bell 

NULL 

EQU 

00 

;ASCI I NULL 

CR 

EQU 

ODH 

;ASCII C/R 

FF 

EQU 

OCH 

;ASCI I F/F 

ESCAPE 

EQU 

1BH 

;ASCI I Escape key 

HIBYTE 

EQU 

0F7S2H 

;VIQ-C hi-lite byte 

HIMASK 

EQU 

80H 

;Hi~lite bit mask 


5 

MODE 

BYTE OPTIONS 



AUTOW 

EQU 

02 AND FALSE 

;Run AUTO on Warm 

Boot? 

AUTOC 

EQU 

01 AND FALSE 

;Run AUTO on Cold 

Boot? 

SINGLE 

EQU 

SOH AND FALSE 

;Single Drive system? 

WRITECK 

EQU 

40H AND FALSE 

;Read after Write 

check? 

ENINT 

EQU 

10H AND FALSE 

;Enable interupts 



ORG 

USER--1 



MODE 

DB 

AUTOW OR AUTOC 

OR SINGLE OR WRITECK OR E 


;80H sets printer to LPT: device, 0 sets to TTY:, 

;STAT.COM can modify IODYT in running CP/M. 

DEFI0B EQU 0 ;"I" Default I0BYT 

NULLS EQU 0 ;"J" Printer nulls 

HAND EQU 0 

ORG USER 




;JUMP 

CINIT 

TABLE - 
JMP 

Jumps MUST remain 
CINITR 

here in same order. 
;Cold boot init 

* 

* 

* 

WINIT 

JMP 

WINITR 

;Warm boot init 


* 

* 

CONST 

JMP 

UCONST 

;Console 

status 


* 

* 

* 

* 

CON IN 

JMP 

UCONIN 

;Console 

i nput 


CONOUT 

JMP 

UCONOUT 

;Console 

output 


* 

* 

LIST 

JMP 

ULIST 

;Printer 

output 


* 

* 

PUNCH 

JMP 

UF’UNCH 

;Punch output to 

'T 

console# 
* 

console* 

4 / 

READER 

JMP 

UCONIN 

;Reader 

input to 

LISTST 

JMP 

ULISTST 

;Printer 

status 


* 


5 


44 


Dr. Dobb’s Journal, Number 67, May 1982 

219 




;This 8 

byte data area used externally MUST remain. 

* 

* 

LENUA: 

DW 

USRLEN ;Length of USER AREA 

* 

USEIOB: 

DB 

DEFIOB ;"I" Initial I0BYT 

* 

HSTYF'E: 

DB 

HAND ;"H" Handshaking type 

* 

NULLQC: 

DB 

NULLS ;"J" Printer nulls 

* 


DB 

0,0,0 ;Reser ved 

* 

•J, 

5 

; * * * 

* * * 

****************** * •* 

* 

k * 

; This 

is the 

console status routine 


; When 

cal 1ed 

by CF'/M it will return with 


; Zero 

in the 

Accumulator if no data is waiting 


; and 

FF in ’ 

A’ if data is waiting. 



UCONST: 

IN 

STATUS 

j Get keyboard status 

AN I 

KEYMASK 

;Mask data waiting bit 

MV I 

A n 0 

j00 in ’A’ means no data 

RZ 


;Return from here if NO DATA 

CMA 


5’A’ = OFF IF data waiting 

RET 


;Return 


; This routine 

will return a 

character from the 

; keyboard in 

the ACC 


UCONIN: 

IN 

STATUS 

;Check keyboard status 

AN I 

KEYMASK 

;Mask parallel port bit 

JZ 

UCONIN 

;Wait until character typed 

IN 

KEYDATA 

;Get keyboard data 

AN I 

ASCMASK 

;Mask off bit 7 

CPI 

FORMKEY 

; Is this a F/F flip key? 

JNZ 

CONDONE 

;SINGLE EXIT POINT 

;Process a control-F to filp 

the? for ms-trap function 

LDA 

FORME* YT 


XRI 

4 

S —> 7 7 OR 7 7 —> 7 $ 7 

STA 

FORMSYT 


MV I 

A,FORMKEY 

;Restore FORMKEY character 

CONDONE RET 


;Exit with character in ACC 

; This is the 

console or Video output routine 

UC0N01JT: 

PUSH 

B 

;Save B,C 

MOV 

A, C 


AN I 

HIMASK 

;Get reverse video bit 

MOV 

B, A 

;Save reverse video bit 

LDA 

HIBYTE 


AN I 

7FH 

;Get reverse video control byte 

ORA 

B 

; Set or Reseat Bit in control byt 

STA 

HIBYTE 



(Continued on next page) 


Dt. Dobb’s Journal, Number 67, May 1982 
220 


45 



New USER for CP/M (Listing continued, text begins on page 42) 


UOUT 


ULIST: 


MOV 

A, C- 

CPI 

BELL 

JNZ 

UOUT 

OUT 

TTYDATA 

CALL 

VIDEO 

POP 

B 

MOV 

A, C 

RET 



li X - 8 0 F / T r o u t i n e 


MV I 

A, FF 

CMP 

C 

JNZ 

LISTOUT 

LDA 

FQRMBYT 


CP I ’ $ 

JZ LISTOUT 


; Force ail 1 bells to printer even 
;if printer is off line 
; Put c:bar acter on screen 
; Restore BC 

; RESTORE OUTPUT FOR CP/M 1.4 


;'Test for FORM FEEDS 
;Ignore all except form feeds 


; IF THEN FORM 

;...TRAP DISABLED 


; Get to here if F/F is being sent to 1isting 
;AND form feed trap is active. 

;Since we are already in a BDOS function call we 
5 should NOT loop back into another BDOS function call. 
;Do console I/O directly thru this USER area. 


; Operating program in TF'A should have at least 10 stack bytes 
; or else a new stack should be set up after saving 
; the cur rent stack. 



PUSH 

H! PUSH D! PUSH B! 



LX I 

H,WAITMSG 

;First show the wait message 

L.IST0 

MOV 

A, M 



CPI 

■ $■ 



JZ 

LIST1 



MOV 

C, M 



CALL 

UCONOUT 



I NX 

H 



JMP 

LISTO 


LIST 1 

CALL 

UC0N.IN 



CPI 

CR 

;Wait for a C/R from console 


JNZ 

LIST 1 



MV I 

C, 4 

; D e 1 e t e w a i t. m e? s sag e 


CALL 

UCONOUT 



POP 

B 1 POP D ! POP 

hi 

;Restore old 

stack if new stac k 

was assigned 


MV I 

C,NULL 

5 Send null to list device 


LISTOUT: 



IN 

STATUS 

5 Get TTY status 


46 


Dr. Dobb’s Journal, Number 67, May 1982 

22T 




Kl o 


TTYMASK 
ULIST 
A, C 

TTYDATA 


;Ch ec k for BUSY 
; W ai i t until n o t b u s v 


ULISTST: 


;fHIS FEATURE NOT IMPLEMENTED 


WINITR: 


CINITR: 


CALL 

LI ST 

5 First put it on the printer 

JMP 

UCONOUT 

5 NOW put it on the console 

; Any 

warm boot i n i t i a 1 .i 

2 ation goes h er e. 

PUSH 

D 


PUSH 

B 


MVI 

A,ESCAPE 

, F i r s t c h a r a c t e r f o r d i s a b 1 i i 

OUT 

TTYDATA 

;..OUT OF PAPER error 

MVI 

A,VIOBYTE 


STA 

VIDELAG 

;VI0—C to lower caxse 

LX I 

D,HITHERE 

;Point to warm boot message 

MVI 

C, 09 


CALL 

BDOS 

;Show warm boot message 

MVI 

A, 7 S’ 

;Disable OUT OF PAPER error 

OUT 

TTYDATA 


POP 

B 


POP 

D 


RET 




;Hardware initialization on cold boot qoes 
5 here if needed. Make sure it ends with a RET. 


CALL 

MV I 

STA 

XRA 

STA 

RET 


CLEAR 
A,VIOBYTE 
VIOFLAG 
A 

IOBYT 


;VI0—C is U/C mode now 
; Set the? VIG-C to U/L 
; case mode 

;and store. 


; Send a single line warm boot, message if form feed trap is OFF 
;Send two lines of warm boot message if form feed trap is ON 


HITHERE DB 

FORMSYT DB 
DB 
DB 


13,10,10,’HEAD QUARTERS - Corvallis, Oregon 97330’,13,10 

' (Trap all Form Feeds) J ,13,10 

10, 7 


;Form feed has been trapped message 

WAITMSG DB 13,10,’FORM FEED TRAPPED - PRESS RETURN TO CONTINUE %’ 


USRLEN EQU 


$ -C IN IT 


Length of USER AREA 


r. Dobb’s Journal, Number 67, May 1982 
22 


End Listing 
47 


Add Direct Video Output to 

Sinclair ZX81 


H ere’s a simple modification you can 
make to your Sinclair ZX80 or 81 
computer to add a direct video out¬ 
put. This allows you to use a composite 
input video monitor instead of a televi¬ 
sion set as your display device. If you 
have a ZX81 in the United States with a 
UHF modulator, you can mount all of 


by Jerry Chamkis 


Jerry Chamkis, Box 18093, Austin, TX 
78760. 


the parts in existing holes on the printed 
circuit board (provided for components 
used only with the European video stan¬ 
dards). 

None of the component values are 
critical. Transistors Q1 and Q2 may be 
any small signal high-frequency NPN de¬ 
vice, but it is preferable to use plastic- 
encased transistors since some of the 
leads must be bent alongside the case. 
The values of R1 and R2 may be varied 
to suit parts available or to adjust the 
video output level. I soldered a phono- 
type jack on the side of the modulator to 


serve as an output connector but the sig¬ 
nal could just as well be led out on a 
piece of cable. 

One interesting use of the direct 
video output is to separate out the sync 
signals and regenerate the horizontal sync 
with a phase locked loop. When the PLL 
detects a loss of horizontal sync (ZX8 1 
in the FAST mode or ZX80 always) it 
triggers a one-shot and holds the video 
blanked for a completely jitter-free dis¬ 
play in all modes. 



48 


Dr. Dobb’s Journal, Number 67, May 1 982 

223 









Using Computer 
Bulletin Boards 


I t has been brought to our attention at 
DDJ that a fair share of even our so¬ 
phisticated readers have no experience 
with electronic message systems. This 
article will help anyone get started — the 
many benefits which accrue will become 
apparent after only a few hours of ex¬ 
perimentation on various systems. 

How to Use Typical Systems 

Tapping into the current of readily 
available information is simple. The Peo¬ 
ple’s Message Service (PMS) software is 
exemplary. Originated by Bill Blue, there 
are now many PMS systems operated in¬ 
dependently. They are easy to learn to 
use, and each has a list of several hundred 
other systems across the United States. A 
list of telephone numbers which call up 
PMS systems is shown in Figure One. 

Any terminal can access PMS and 
similar systems, regardless of the “host” 
system’s configuration; as can any com¬ 
puter running terminal/communications 
software. Such software ranges from 
“dumb” to varying degrees of “smart.” 
The most rudimentary use your CRT as a 
display; keystrokes go through the RS232 
port to the CBBS, which echoes them 
back to your CRT. More powerful com¬ 
munications programs enable better use 
of your own computer’s resources, such 
as scrolling through several pages of text, 
file saving, and transmission of pre¬ 
formatted files. 

Step One 

Make certain a modem is connected 
to your computer. Acoustic couplers are 
the type with rubber receptables into 
which the telephone handset fits snugly. 
Direct-connect modems use the modular 
phone jack to plug directly into the 
phone, eliminating possible room noise. 

Step Two 

Dial the phone number of a com¬ 
puter bulletin board. If not busy, the sys¬ 
tem should answer within two or three 
rings and begin sending a carrier signal. 
When you hear that tone, place the hand¬ 
set into the coupler (or if using a direct- 
connect modem, depress the DATA 
switch). 


by Marlin Ouverson 


Step Three 

If nothing appears on your CRT after 
Step Two, then hit your Return or Enter 
key a couple of times. Some computer 
bulletin boards require you to know 
this, while others will send a prompt to 
the screen telling you to do so. It is used 
to determine your baud rate. 

Step Four 

You are now communicating with 
the host software. You may be asked to 
enter a password; or if you are a new user 
your name and location will be requested. 
New users are usually given special 
prompts and help messages. At some 
point, you will encounter a menu of com¬ 
mands available to you. They enable you 
to use the system’s data base; the value of 
what you retrieve from it can be seen as a 
function of (1) the information on that 
particular system, and (2) how well you 
learn to use the commands for entering, 
manipulating and retrieving the informa- 
tion. 

Step Five 

Have at it! Try using commands to 
scan message “headers” for items of in¬ 
terest to you. Then retrieve those mes¬ 
sages to read them. Can’t get at one? It is 
probably encoded with a password for a 
particular individual’s eyes only. Try en¬ 
tering a message of your own — tell other 
users you have been online, where you 
are from, anything you’d like to share. 
It could generate responses, which will be 
on file the next time you logon. 


Step Six 

It’s easy to spend hours experiment¬ 
ing, getting to know a system. If it is a 
good one, chances are that many others 
are waiting to use it. Some CBBS’s limit 
the number of minutes per day for each 
caller, while for others it is an honor 
system. For most systems you should 
type G (for goodbye) to logoff, or some¬ 
thing similar listed in the Command Sum¬ 
mary. 

When you logoff, most systems will 
ask if you have any comments for the 
Sys(tem)Op(erator). If not, you are dis¬ 
connected — but remember to hang up 
the telephone, in case Ma Bell thinks you 
are still using her services! It doesn’t hurt 
to be sure. . . 


Step Seven 

Get used to these simple steps; use 
several different systems. Discover how 
the hierarchical structure of Conference 
Tree systems differs from more linear 
CBBS’s. Find out how to use electronic 
bulletin boards with electronic mail fea¬ 
tures, try logging on to systems main¬ 
tained by special interest groups. You can 
experiment at beginning an ongoing dia¬ 
log with users who may share some con¬ 
cerns you have — perhaps it will spin off 
into a CBBS of its own. 

When you have a mild proficiency 
on one of these systems, find out if it 
has an expert user mode. Not only will it 
be faster to operate, there may be addi¬ 
tional commands which will increase the 
power of the system for you and multi¬ 
ply the uses you find for telecommuni¬ 
cations. 


Conclusion 

This has been an intentionally sim¬ 
plistic approach to computer bulletin 
boards, written to help those who feel 
they have been left behind in the dust, or 
to inspire any who haven’t understood 
the importance of the underlying con¬ 
cepts. DDJ has always had a strong inter¬ 
est in telecommunications; our company 
sponsors research and development by 
PCNET (Personal Computing NETwork) 
into communications protocols. For elec¬ 
tronic discussion of the subject, they 
maintain a CBBS at 415-863-4703. 

We highly encourage any and all to 
investigate what electronic communica¬ 
tions has to offer. Watch DDJ for arti¬ 
cles about readers’ experiences and ideas. 
Possibly more than any other applica¬ 
tion of computer technology, this field is 
open to innovators to shape how comput¬ 
ers will serve our world. The technical 
and social implications are many and far- 
reaching; we hope every reader will parti¬ 
cipate. 


50 

224 


Dr. Dobb’s Journal, Number 67, May 1982 



Figure One 

Numbers of selected People’s Message Service systems. These systems are rela¬ 
tively easy for newcomers to master, and contain a list of other bulletin board 
systems. If none of those listed are in your area code, call the nearest one and 
use its “O” (for Other CBBS’s) function to locate one within your local calling 
area. 


213-334-7614 

213-346-1849 

216-867-7463 

312-295-6926 

312-373-8057 


317-787-5486 

408-370-0874 

415-493-7691 

415-851-3453 


509-943-6502 

612-929-6699 

617-767-1303 

713-233-7943 


714-561-7277 

714-582-9557 

714-772-8868 

913-341-3502 


Figure 2. 

A sample session on a PMS system. 


PliS - PALO ALTO, CA. 

USERID <N=NONE> : 

LOGGING CALLER #25328 AT 11:36:29 PST 

Type "N" for system news. 

Type "?" -for commands. 

command ?? «-user typed “?” 


->> System Commands 

E = Enter a message into system. 

F = Features, articles, excerpts. 

G = Goodbye. Leave system (hangup). 

H = Help with various functions. 

I = Information about system. 

K = Kill a message from the files. 

M = Message alert. Messages for you? 

N = News — System news. 

0 = Other systems current summary. 

Q = Quickscan of message headers. 

R = Retrieve a message from the files 

(may be used during a scan to flag msgs). 
S = Scan of message headers (add - to end of 
number for a reverse scan). 

SR » Selective message retrieval 
(X aborts, # resumes). 

T = Time, date and connect time. 

U = User modifiable system function. 

X = eXpert user mode (toggles on/off). 

Z = Continue message entry after abort 
= Prints list of commands. 

# = Retrieve messages flagged during scan. 

TEST = Modem continuous test loop. 

NEWCALL. = Information for new callers. 


command ?s user chooses “S” 

Start at msg# (5605/9225) 79000 <- Start Scan at # 9000 


Msg# 9003 on 02/24/82 316:22 (2) <Pvt> 
Subj: HAHA!!, To: MARTY TERMAN 
From: Danny Wells 

Msg# 9005 on 02/24/82 317:27 (16) «Pvt> 
Subj: R/ DECODER, To: Danny Wells 
From: DAN DRUKER 

Msg# 9006 on 02/24/82 317:43 (8) <Pvt> 
Subj: MISC..., To: SYSOP 
From: DAN DRUKER 


Msg# 9008 on 02/25/82 311:42 (11) 

Subj: r/hmb, etc.... To: ken stuart 
From: Ron Carpenter 

Msg# 9020 on 02/25/82 322:10 (16) 

Subj: for sale. To: all 
From: Chuck George 

Msg# 9035 on 02/27/82 301:12 (4) 

Subj: HP 2000 MANUALS FOR SALE, To: ALL 
From: John Feibusch 

Msg# 9042 on 02/27/82 315:34 (4) 

Subj: MODEM MAN NEEDED, To: ALL 
From: HOWARD H SMITH 

Msg# 9044 on 02/27/82 319:28 (6) 

Subj: CP/M ON MICOM WP — QUESTION, To: ALL 
From: Philip Casella 

Command 7R 4- USer chooses “R” 

Msg# (5605/9225) ?9006 4- want to read # 9006 

Msg# 9006 on 02/24/82 317:43 (8) <Pvt> 4- paSSWOrd protected 

Subj: MISC..., To: SYSOP 

From: DAN DRUKER, LOS ALTOS,CA 

Password ?I don't know it... 

Msg# (5605/9225) ?9042 «- user selects another msg. 

Msg# 9042 on 02/27/82 315:34 (4) 

Subj: MODEM MAN NEEDED, To: ALL 
From: HOWARD H SMITH, PALO ALTO 

GTE LENKURT,SAN CARLOS,(WHERE I WORK) NEEDS AN ENGINEER 
INTERESTED IN HIGH SPEED MODEMS. CALL ME 415-595-3000 X2747 
(WORK) OR 415-494-2915 (HOME) ANYTIME, IF YOUR INTERESTED. 
THANKS 

Command ?g •«- logging off 

Comments/suggestions (y/n/r) 7n 

Connect time 03:01 

It’s 11:39:30 Goodbye.. 


End 


Dr. Dobb’s Journal, Number 67, May 1982 


51 

225 





Software Review ' 

COMMWHIZ 

A Smart Terminal Program for TRS-80’s 


COMMWHIZ 

Smart Terminal Program for TRS-80 

Models I and III 

(one disk drive required) 

$79.95 from 

VolksMicro Computer Systems, Inc. 

Circle No. 302 on Reader Service Card 

Reviewed by PCC Staff 

Everyone and his brother who sells 
communications software these days calls 
it “smart” — even if the only thing with 
smarts is the price. Thankfully, there are 
a few exceptions to the rule, one of 
which is COMMWHIZ. When the Creator 
was handing out software IQ’s, this 
package received nearly Mensa-class in¬ 
telligence. 

In this instance, “intelligence” ac¬ 
tually means there are many options. If 
you are used to dumb terminal software, 
you know the feeling of scribbling madly 
to copy a piece of data before it scrolls 
off the screen. Slightly less dumb pro¬ 
grams allow one to freeze the action for 
more leisurely note taking — at a stiff 
price if you are on a commercial time¬ 
sharing system. 

The folks who designed COMM¬ 
WHIZ themselves spend a lot of time on 
private and public data base/CBBS sys¬ 
tems. The have written a software 
package which allows the user to enter a 
more powerful command mode. This pro¬ 
vides features (see Figure 1) proven valu¬ 
able by experience, not just in theory. 
Additionally, it is menu driven, practical¬ 
ly eliminating the need to refer to the ref¬ 
erence card. 

Here are a few of the things it allows 
one to do: 

• Send one or two pre-defined user 
messages (such as a logon code and a pass¬ 
word) with only two keystrokes. This 
handy feature helps ensure error-free, 
first-try logon. 

• Call up the directory of disk files, 
useful for locating a file to be transmitted 
and for avoiding duplication of file 
names. 

• Create a buffer in RAM for stor¬ 
age of material received or to be transmit¬ 
ted. 48K systems will have about 30K of 
buffer space, a generous amount for text 
messages, and adequate for uploading/ 
downloading of software. 

• Fast command to toggle the buf¬ 
fer open or closed, or the printer on or 


off. This helps reduce clutter caused by 
saving unneeded information or filling 
disks to overflow with unedited material. 

• Execute certain DOS commands 
without leaving terminal mode. This is a 
handy function, but must be used with 
care — see comments below. 

• Auto open and close of the buf¬ 
fer. This permits other computer hobby¬ 
ists using COMMWHIZ, or some comput¬ 
er bulletin board system (CBBS) with 
downloading features like those of 
FORUM-80, to open your buffer before 
commencing with file transfer and to 
close it afterward. Used properly, this will 
help prevent programs from becoming 
contaminated with direct statements 
from the host communications software. 

• View buffer and check remaining 
memory. You can look to see if the buf¬ 
fer has contents, whether you captured 
all the desired data, and how much space 
is left in the buffer or on disk. 

• Use Scripsit, Electric Pencil or 
other word processing software to pre¬ 
pare text in advance of logon, or to edit 
files received. This can save valuable on¬ 
line time and, of course, utilize the best 
tools for text preparation, partly bypass¬ 
ing the need to use any host system’s 
less-sophisticated editor. 

• Other commands include open 
and close buffer, format screen width, 
initialize serial port, load file to buffer or 
buffer to disk, modify source file 
(EDTASM to ASCII and vice versa), re¬ 
turn to DOS without reset, transmit buf¬ 
fer and toggle between half- and full- 
duplex mode. 

Additionally, entering a special mode 
by simply pressing the up-arrow key en¬ 
ables one to generate the characters 
shown in Figure 2. These are particularly 
helpful when using remote systems which 
may require one of these symbols in 
order to logon or to use sub-menus of 
commands; or for just getting fancy. Our 
copy of COMMWHIZ interpreted the 
underline option as a backspace, although 
the maker assures us this glitch must be 
unique to us. . . 


The Program in Action 

The user is first presented the op¬ 
portunity to input up to two pre-defined 
messages. Following that, a status line ap¬ 
pears at the top of the screen (as in Fig¬ 
ure 3). The user could then, if he chose, 


access a CBBS without learning any more 
about the software. Anyone can use the 
program immediately and explore its 
more powerful features while in use. 

If he has dialed a remote system over 
the telephone and is required to enter a 
password or other code, he could have 
pre-defined this when booting the 
COMMWHIZ disk. When prompted for it 
by the host, he may enter Command 
mode by pressing Shift-Up-arrow and 
then pressing 1. His pre-defined message 
is sent, but not displayed on the screen 
(protecting his password from onlookers). 

Whenever the user executes an 
option from the Command menu, he is 
returned to terminal mode. It is possible 
to miss transmissions from the host if 
Command mode was entered during 
incoming data instead of waiting for a 
prompt, but unless the user is hesitant or 
unsure, he is returned to terminal status 
within two or three seconds. 

CBBS’s have different methods for 
entering text messages, so COMMWHIZ 
allows for different methods of transmit¬ 
ting text (see Figure 4). Usually, one 
inputs a single line at a time, followed by 
a carriage-return line-feed. This means 
that although one may have prepared text 
in advance with a word processor, he 
must transmit it a line at a time, waiting 
for the host’s prompts at the beginning of 
each line. COMMWHIZ allows one to 
define such prompts before transmission; 
it will then relay the entire message, wait¬ 
ing after each line for the proper prompt 
before proceeding. 

While in our office test mode (echo¬ 
ing our messages to the CRT without 
going through a host) we discovered a 
possible sore point. A small portion of 
the sub-menu related to Transmit options 
is spliced into very short (2- to 3-line) 
text messages. Evidently an unspecified 
minimum of space on the display is sent 
— longer messages must write over that 
area and so do not include the system in¬ 
formation therein. This small bug never 
once interfered in our actual on-line 
tests. 

A feature has since been added (not 
available on our review disk) which uses a 
timing loop to pause between lines. This 
circumvents the need to know the specif¬ 
ic system’s prompts in advance. It may 
also be useful when the prompts for 
message headers are different from those 
for the text. There are possible draw- 


Dr. Dobb’s Journal, Number 67, May 1982 
226 


53 



backs if this feature relies solely on a 
time factor, so it should be used dis- 
criminately until it proves reliable. 

DOS commands can be used while in 
COMMWHIZ. If you have an important 
buffer-full of information which needs to 
be saved, but your diskette is full and no 
spares are at hand, you can KILL an 
existing file to make room. RENAME is 
occasionally handy, as well. Although the 
the documentation advises strongly 
against use of FORMAT or BACKUP in 
its mode, it says “most DOS commands 
are useable. . .” Our experience did 
not show this to be true; or perhaps too 
literally true. 

In several instance, attempts to use a 
DOS command returned us to TRSDOS, 
folding up the buffer and crashing the 
program. We were able to re-boot and 
catch our connection to the remote 
CBBS’s without having to logon again, a 
minor consolation. The fault is not en¬ 
tirely with the terminal software: such 
crashes usually resulted from improper 
use of DOS commands which required 
system error messages. Some, however, 
should be forgivable errors, especially 
accidental use of lower-case letters. 

Once a session has ended and the 
telephone is back in its cradle, the user is 
still in terminal mode. If he has material 
in the buffer to store on disk, he enters 
Command mode and presses the letter S. 
This dumps the entire buffer contents 
onto disk: line feeds, control codes, and 
errata ad nauseum. Most conservationist 
users will then want to edit those files of 
extranea. Any good editor or word pro¬ 
cessor should make relatively short work 
of this task. 

A small irritation appeared during 
preparation of this review. Each text line 
stored ends with a carriage return. Scrip- 
sit interprets that code correctly and dis¬ 
plays it as a small block. Each line begins 
with a right square bracket; that is pro¬ 
bably the host system’s code for a line 
feed. Now, in Scripsit a right bracket 
means “end-of-text-block.” But the 
global delete function won’t remove 
either of the little buggers, so every single 
One (that must be cosmetically perfect) 
must have those symbols manually de¬ 
leted, instead of using the convenient re¬ 
peat command otherwise available in 
Scripsit. 

The makers of COMMWHIZ tell us 
this crops up occasionally. Such embed- 


54 


ded characters are evidently a function of 
the host system from which text was 
received. Scripsit doesn’t print such text 
markers unless specifically commanded, 
and other editors or word processors 
might easily search through and strip off 
the first character of each line, so this is a 
minor quibble at best. 

An interesting note: since one can 
leave COMMWHIZ, enter DOS and load 
programs without re-booting, we ^ften 
do just that to load Scripsit for the above 
purposes. At odd times like subsequent 
disk I/O, though, the COMMWHIZ cursor 
will mysteriously appear, putting an un- 
correctable hole in the document being 
prepared. 


Documentation 

COMMWHIZ is supplied with a 60- 
page manual. The first half is a tutorial, 
the final chapter of which deals with ad¬ 
vanced features of the system. The last 
half of the manual consists of sample ses¬ 
sions on various CBBS and commercial 
data base systems, showing logon, 
prompts and command summaries. There 
are also fairly extensive lists of CBBS tele¬ 
phone numbers. This last section will be 
particularly helpful to people completely 
new to telecommunications or to the pri¬ 
vate, no-cost systems mentioned else¬ 
where in this issue of DDJ. 

The manual is to the point, contains 
all the information needed, and is never 
condescending. It should have more care¬ 
fully emphasized the danger of opening a 
closed buffer - its contents are lost. This 
is mentioned once, but is easy to over¬ 
look until it has happened more than 
once; and once is too often. The last 
section on sample sessions should have 
used a different typeface for author com¬ 
ments, which are interspersed closely 
with the actual printout of the sessions. 


Summary 

We recommend COMMWHIZ as a 
communications package which is both 
powerful and easy to learn. It is useful 
from the first session. Its creators are re¬ 
sponsive, helpful and available. They have 
included free on the same disk with this 
program a utility which “permits rapid 
error-free file transfers between TRS- 
80’s ... or from the TRS-80’s to CP/M 
systems running . :. XFRCPM80.COM.” 


Many of the suggestions we would make 
are more deficiencies caused by a lack of 
standards among CBBS’s than by this 
software. 

When entering the Command mode, 
it would be helpful if the program gener¬ 
ated a Control-S (a common pause com¬ 
mand) so the user wouldn’t miss any in¬ 
coming data. If the user attempts to 
toggle on the printer and it is not con¬ 
nected, the “Printer not available” 
message flashes on and off the screen too 
quickly to be noticeable, not to say 
legible. And there should be a safeguard 
on that buffer: trying to open it when it 
has contents should prompt a verifying 
query; trying to toggle it open when it 
hasn’t been “turned on” by the Com¬ 
mand mode should show an error message 
rather than allowing the user to assume 
he is capturing anything in RAM. The 
status line should differentiate between a 
buffer that is actually closed and one that 
has been temporarily toggled shut. 

We have concluded this is a fine and 
truly “smart” terminal program which we 
will continue to use. Our experience with 
the company and people who make it 
lead us to believe they will continue to 
improve an already fine product. 


Dr. Dobb’s Journal, Number 67, May 1 982 

227 




MODE=Cmd 


BUFFER—Clsd AUTO=OFF PRTR=OFF COMM- 300 N81F 


(A)uto open &. close 
(C)lose buffer 
<D)irectory 

(E) xecute DOS command 

(F) ormat screen 
(Dnitial ize Serial Port. 

(L) oad file to buffer 

(M) odify Source file 


(Q) pen buffer for input 

(R) eturn to DOS 

(S) ave buffer to file 

(T) ransmit buffer 

(U) se of memory 

(V) iew buffer 
duple(X) 

COMMAND ==> . 


Figure 1. Command mode menu. Not shown are (P)rinter toggle on/off, (1) to send an optional user-defined 
message, and (2) to send the second user message. 


MODE-Spcl BUFFER-Clsd AUTO=OFF PRTR-OFF C0MM= 300 NO IF 
0-NULL 1-Escape 2=C 3=1 4=! 5=~ 6=\ 7=5) 8=C 9=3 -* 

Figure 2 . Special character mode options, available by pressing the up-arrow. 


MQDE=Term BUFFER=Clsd AUT0=0FF PRTR=0FF C0MM= 300 NS IF 


Figure 3. The status line at top of screen always displays the current status of the user’s system. Any of the in¬ 
formation can be changed by using Command mode options. 


S e 1 e c t. t r a n s m i t o p t i a n 

1. Send with no control characters 

2. Send with Auto Open and Close 

3. Transmit in Prompt mode 

4. Return to terminal mode 

Figure 4. The sub-menu of choices for transmitting text. 


Dr. Dobb’s Journal, Number 67, May 1982 
228 






BOOK REVIEWS 


Interfacing to S-100/IEEE 696 

Microcomputers 
by Sol Libes and Mark Garetz 
OSBORNE/McGraw-Hill 
321 pages, $15.00 

Circle No. 312 on Reader Service Card 

Reviewed by George W. Jolly 

A draft of the proposed standard 
definition of the S-100 bus was published 
in the July 1979 issue of Computer maga¬ 
zine. Interfacing, based on that draft, ex¬ 
plains how S-100 bus computers work. 
To understand this book, you need to be 
familiar with digital logic and schematic 
diagrams. If you intend to build any 
of the circuits described, you need ex¬ 
perience building circuits. The software 
examples presented are in 8080 assembly 
language, but are also generally flowchart¬ 
ed for you. 

An S-100 board must do certain 
things: it must decode address lines to 
determine whether or not to do some¬ 
thing; control lines tell it what to do; 
data lines pass the information being pro¬ 
cessed. If the total computer system is to 
function correctly, all boards must handle 
these bus wires the same way. The IEEE 
definition, reprinted as an appendix to 
the book, attempts to ensure this by 
spelling out the meaning of the lines in 
exact language. The authors augment this 
definition with actual circuit examples. 

Although Interfacing deals primarily 
with the S-100 bus interface, it also ex¬ 
plains a variety of outside-world applica¬ 
tions. For example, Chapter 10 includes 
several circuits for controlling AC power 
with on/off signals from an output port 
of a computer. The circuits shown are 
simple, making Interfacing a good source- 
book in addition to its main function. 
The authors give simple programs to illus¬ 
trate the driver software necessary. 

Later chapters explain more ad¬ 
vanced system concepts. The authors 
give a concise, plain-language explanation 
of interrupt processing, and explain the 
specific methods used by 8080 and Z80 
microprocessors. Temporary bus masters 
(DMA devices) occupy a chapter thick 
with timing explanations and example 
circuits. However, the design of the CPU 
board itself is not included; dynamic 
memory is also excluded. Debugging cir¬ 
cuits such as a breakpoint and a single¬ 
stepper are given, as well as a jump-on- 
reset circuit. 


Although Interfacing is overall a very 
good book, it was not as easy to read as 
most magazine articles. The explanations 
are good, but more concise than conver¬ 
sational. Interfacing is more suited to seri¬ 
ous study than for recreational reading. 
As a sourcebook of specific circuits, or 
as a text for S-100 concepts, it is 
excellent. 

Lecture Notes in Computer Science 
by G. Goos and J. Hartmanis, Eds. 

Springer-Verlag 
190 pages, $11.80 

Circle No. 332 on Reader Service Card 

Reviewed by Robert Irving 

This paperback is aimed at the pro¬ 
fessional writer of interactive programs, 
with two fundamental messages: (1) try 
to be a little less “professional,” get in¬ 
side the head of the non-programmer 
who will be using your interactive system 
and make it understandable to him; and 
(2) make both documentation and com¬ 
mand structure of the interactive system 
as close to the “natural” language (i.e., 
English) as is practicable within the sys¬ 
tem constraints. 

A text editor is used as the vehicle 
for the discussion, both for representing 
development of an interactive system and 
a set of user instructions, and as the basis 
of an experiment in determining those 
factors which lead to the best understand¬ 
ing (quickest use) and greatest efficiency 
(fewest errors). Some of the conclusions 
are reasonably obvious: if you allow ab¬ 
breviated commands, be consistent. Don’t 
sometimes use the initial letter, other 
times two letters, and still other times 
three, without some discemable rule for 
application. Easy to say, but not so easy 
to do! 

The authors’ “Assistant” program 
uses initial letters for any keyword ex¬ 
cept three which must be spelled out 
completely, presumably because these are 
potentially destructive commands — but 
one of them is PRESERVE which puts 
the text into file. One really unique item 
is a command called UNDO which does 
just that — it undoes the undesired result 
of the last executed command. How 
many times have you wished that you 
hadn’t just deleted everything to the 
bottom of the text file, having forgotten 
that you had just referred to the title of 
the article to check its wording — and 


consequently dumped the whole text into 
Limbo? Of course, such a function could 
use a lot of memory, as in my extreme 
example — but memory continually be¬ 
comes cheaper, and human time more 
expensive. 

One last item is worth mentioning: 
the book ends with a chapter on how to 
design experiments to ensure that your 
“improvements” really improve the pro¬ 
gram. 


Introduction to Computer Organization 
by Ivan Tomek 
Computer Science Press 
456 pages 

Circle No. 322 on Reader Service Card 

Reviewed by George W. Jolly 

Introduction to Computer Organiza¬ 
tion is really two books in one. The first 
half deals with structure and design of 
digital circuits; the remainder of the book 
covers computer architecture on a larger 
scale. Intended as a college text for a one- 
semester course, Introduction avoids elec¬ 
trical details, focusing on organizational 
structures common in computer systems. 
The material is designed to give program¬ 
mers, who may only know a high-level 
language like Fortran, an understanding 
of how computer hardware works. As 
a survey of important topics, the book is 
excellent. 

The first five chapters explain the 
basic of digital circuitry. Electrical de¬ 
tails are not at issue here, but rather the 
behavior of functional units such as gates, 
flip-flops, multiplexors and the like. One 
section does explain TTL voltage levels 
and the effect of noise on the circuit, so 
this subject is not neglected. State dia¬ 
grams are used to illustrate the function 
of sequential circuits. These diagrams are 
explained at the outset. 

Chapters five and six form a bridge 
between the circuit design and the com¬ 
puter architecture sections of the book. 
These chapters deal with coding, where 
numbers stand for things, and with arith¬ 
metic as used in computers. Considera¬ 
tions for the design of a character code 
are discussed, and the ASCII and EBCDIC 
codes serve as illustration. A brief sec¬ 
tion on error detection explains the use 
of parity bits, but the more powerful 
Hamming codes are only mentioned. The 
treatment of arithmetic is good, and even 


56 


Dr. Dobb’s Journal, Number 67, May 1982 

229 



includes a discussion of decimal arithme¬ 
tic in hardware. 

The remainder of Introduction ex¬ 
plains computers. This is a hardware view, 
full of program counters, memory address 
registers, and data busses. A tiny CPU is 
outlined, capable of only a few instruc¬ 
tions, and a driving microcode program is 
developed. Most of the truly nasty prob¬ 
lems of real microcode are removed, and 
the result is a fascinating insight into the 
workings of a computer. Introduction 
gives an overview of common instruc¬ 
tions found in real computers, and ex¬ 
plains the stack found on most micro¬ 
processors. 

Introduction also gives an excellent 
overview of memory and peripheral de¬ 


vices. Terminals, printers, disks, drums 
are all explained in basic terms. Good 
coverage is given to basic methods of 
handling peripherals with software. The 
treatment is based on plain English and 
simple diagrams, so the reader need not 
know any particular computer language. 

To put the subject into better per¬ 
spective, Introduction covers several real 
computers. The Heathkit Microcomputer 
Trainer ET-3400 provides an example 
microprocessor system. The author uses 
the Motorola 6800 chip for an in-depth 
explanation of subroutine linkages, inter¬ 
rupts, I/O, and instruction timing. Mini¬ 
computers and large computers are out¬ 
lined for insight into other architectures. 
The PDP-11 family, the Univac 1100/60, 
and the CDC Cyber 170 series provide a 


diverse view. A final section on future 
trends rounds out the picture nicely. 

A workbook is available to accom¬ 
pany this textbook. Throughout the text 
the reader is referred to the workbook for 
more examples; however, the text stands 
well on its own. The preface to the text 
warns that some problems in the work¬ 
book contain important material not 
covered in the text, and recommends 
using the two books in parallel. Unfor¬ 
tunately, this reviewer has not seen the 
workbook, but it should be worth a look 
or two. Overall, Introduction is an ex¬ 
cellent text. 




(Continued from page 30) 

simulator is completely independent and 
can be used with any computer with a 
serial port for communication with the 
clock simulator. The advantage of an in¬ 
dependent clock is the lack of interfer¬ 
ence with the host computer and the 
capacity to implement multiple clocks 
with little burden on the host’s CPU 
speed. This would not be true if the 
clocks were implemented on the host 
computer itself, since the host computer 
will be slowed down considerably by the 
extra CPU cycles consumed by the clock 
simulation. We have found the clock 
simulator most helpful in performance 
analysis when we compare the relative 
efficiency of various computer algo¬ 
rithms and evaluate the relative speeds of 
commercial interpreters and compilers. 
The application of the clock simulator in 
computer performance analysis will be 
the topic of a future paper. SBj 


(Figures 1 -6 begin on page 34) 


Dr. Dobb’s Journal, Number 67, May 1982 
230 


57 



HARDWARE REVIEWS 


Hayes Stack Smartmodem 

Hayes Microcomputer Products, Inc. 

Circle No 322 on Reader Service Card 

Reviewed by Rich Henderson-Gragg 

The Hayes Stack Smartmodem is a 
300 baud, auto-answer/auto-dial origi¬ 
nate, FCC part 68 certified modem with 
standard RS-232 computer interface. As 
an FCC certified device this modem can 
be directly connected to the phone line 
via a standard modular jack. The direct 
connection facilitates the auto-answer/ 
auto-dial capabilities as well as eliminat¬ 
ing the noise problems inherent in acous¬ 
tic coupling. 12 VAC power for the 
modem is provided by a UL listed power 
pack similar to those used by calculators. 

The unit is approximately 1.5” x 
5.5” x 9.6” which allows it to fit conveni¬ 
ently on or near your computer (fits fine 
on top of Apple disk drives). The case is 
part of the Hayes design which allows dif¬ 
ferent products of this series to “stack” 
together. There is a ridge on the top of 
each case to provide stability and a stan¬ 
dard desk phone can sit firmly on top of 
the complete stack. The front Panel has 7 
indicator leds that provide the user with 
information on the state of the modem. 
These lamps are: 

MR - modem ready (power on) 

TR — terminal ready (DTR from 
terminal or internal switch) 

SD — send data (flashes when data 
is received by modem from 
local terminal) 

RD — receive data (flashes when 
data is sent by modem to 
local terminal) 

OH - off hook (modem has“picked 
up” the phone) 

CD — carrier detect (modem has re¬ 
cognized a carrier from the 
line) 

AA — auto-answer (auto answer 
mode is enabled) 

Installation is quick and easy. Con¬ 
nect your terminal or computer (we used 
an Apple 3) to the RS-232 connector on 
the back, plug the modular cable provid¬ 
ed into the jack in back and into the telco 
line jack, plug in the power pack, switch 
on and you’re ready to go. 

As this is a “smart” device, you com¬ 
municate with it through your terminal. 
When the power is first applied, the 
modem initializes itself, lights the MR 


lamp and awaits a <CR> from the ter¬ 
minal to establish the baud rate between 
it and the terminal. You can now com¬ 
mand the modem to originate/answer a 
call or enter an auto-answer mode with 
simple command strings such as 

ATDT 408,555-1212 

This command string is AT (Atten¬ 
tion) DT (Dial touchtone) 408 (dial 408) 

, (wait 2 seconds) dial the rest of the 
number (the - is ignored). When the string 
is entered (terminated by a <CR>), the 
modem will execute the command. Then, 
if the internal software switch is set, it 
will activate the monitor speaker so you 
can hear the progress of the call (very 
handy if you get a busy signal) and de¬ 
activate the speaker when it detects the 
carrier from the other device. (With the 
software switch you can control this fea¬ 
ture to allow the speaker to come on and 
stay on, or not to come on at all.) The 
speaker is listen only, not a speaker¬ 
phone, therefore if you get a person 
(“what number did you dial”) you will 
need to pick up the telephone to answer. 
If the modem doesn’t receive carrier in 
about 30 seconds (this can also be 
changed) it will hang up and send a "NO 
CARRIER” message back to your termi¬ 
nal. Also if you hear a busy, sending any 
character to the modem while it is wait¬ 
ing for the carrier will abort the call with 
a “NO CARRIER” sent back to you. 

A further interesting feature is the 
ability to deal with older office pbx-type 
equipment which may require pulse dial 
to get the telco trunk lines. This com¬ 
mand string would handle such a prob¬ 
lem, 

ATDP9, T555-1 21 2 

The DP, would pulse dial the 9 access and 
wait 2 seconds before going into the 
touchtone number. 

With this system a wide range of 
commands is possible to handle about 
every conceivable condition including ori¬ 
ginate a call but using answer mode tones 
if calling a friend who has an originate- 
only modem, return to command state at 
end-of-line so additional commands can 
be input for a phone order or bank ser¬ 
vice. All 12 touchtone keys are provided 
including * and #. Other commands are 
used to set internal software/hardware 
conditions such as redial last number 
without having to type it in again, auto¬ 
answer on nth ring of phone, carrier on/ 


off, monitor speaker on/off, reset and a 
group of parameters including: character 
used as<CR>, character used as < Back- 
Space >, how long to wait on loss of car¬ 
rier. 

The manual is detailed, well-organized 
and well-written. The introduction tells 
you which parts of the manual to read to 
get on the air and which to read to learn 
more later. The appendices cover RS-232 
connections, modular phone wiring dia¬ 
grams, dial pulse and touchtone frequen¬ 
cies, specifications, use with amateur 
radio and return for repair procedures (in 
the very unlikely event you need it). In the 
back of the manual they have thought¬ 
fully provided a tearout summary card of 
the commands and functions. 

The only real problems we experi¬ 
enced with the system were getting used 
to the idea that the Smartmodem could 
take care of the line management and 
that programs didn’t need to worry about 
answering the phone, checking for carrier 
or how long to wait on loss of carrier. 
All the program really needed to do was 
watch the RS-232 Carrier Detect line to 
determine if it connected to another de¬ 
vice. The only annoyance we discovered 
was that the commands sent to the 
Smartmodem had to be uppercase. We 
spent 10-15 worried minutes trying to 
figure out why the modem wouldn’t 
acknowledge a command before noticing 
that the terminal was in lower-case mode. 
This requirement was implied in the 
manual as all examples were bold, upper¬ 
case characters, but we could find no 
specific statement to this effect. 

We’ve used the Smartmodem to talk 
to a variety of computer systems with no 
trouble at all. While we haven’t had the 
opportunity to test the “banking” fea¬ 
tures we have no doubt that they will 
work as described. The system installed 
easily and worked with no fuss other than 
remembering to send upper-case com¬ 
mands. The two programs we wrote in 
Apple 3 Pascal had no problem sending 
instructions to the modem and function¬ 
ing with the auto-answer feature. It is an 
attractive package and design, and should 
work well with almost any terminal or 
computer where the RS-232 port is wired 
as DTE (data terminal equipment). In 
the event that your computer’s RS-232 
port is wired as DCE (data communica¬ 
tions equipment) the manual describes 
how to allow correct operation. 


58 


Dr. Dobb’s Journal, Number 67, May 1 982 

231 




uuesr assay 

Prior Censorship 


T he Deputy Director of the CIA, 
Admiral Bobby Inman, announced 
on January 8* that the Admini¬ 
stration would seek passage of technical 
censorship laws unless the scientific com¬ 
munity submits to “voluntary censor¬ 
ship.” In recent years the government has 
attempted to censor cryptographic re¬ 
search and nuclear physics. This new at¬ 
tempt includes the fields of computer 
hardware and software, among others. 

What the CIA wants is called prior 
censorship. It means that the CIA reads 
any article submitted for publication, and 
decides whether it should be printed. The 
readers of the technical journals never 
know which articles have been rejected; 
they simply disappear. 

Our Constitution and legal system 
were designed to make it hard to impose 
this kind of tyranny without public con¬ 
sent, so the CIA is attempting to get 
cooperation through threats like the one 
cited above rather than through legal 
means. Our best defense against this is to 
immediately make a strong public stand 
against the attempt. 

Buy why should we care? The Na¬ 
tional Security Agency’s voluntary review 
system for cryptographic papers has 
reviewed 25 papers so far, and passed 


John Gilmore 


John Gilmore works as an independent 
consultant in the San Francisco Bay Area. 


them all (or so they say). And there is 
some risk that American advances in tech¬ 
nology can be used “against us” by other 
governments. 

I think we should care because infor¬ 
mation is a valuable resource to us. When 
the CIA censors reports on new research 
and development because they might 
reach foreign ears, they also withhold 
the information from us, the American 
technical community. Imagine where 
microcomputers would be today if the 
knowledge gained by the large-computer 
field had been withheld from publication 
— we’d still be diddling bits in 4004’s, 
if indeed LSI had ever been invented. The 
explosive growth of the computer indus¬ 
try has been fueled by the rapid dissemi¬ 
nation of new information; we censor 
that information at our peril. 

Besides, our best defense against 
foreign domination in technical fields is 
to do a lot of research here in the U. S. If 
the prerequisite information is not avail¬ 
able, and if the results of the research 
cannot be released, much of the incen¬ 
tive for individuals and companies to do 
new research simply disappears. 

There is also the argument that we, 
the public, should have at least as much 
information as our government has, to 
protect us against abuses of power. The 
Federal Data Encryption Standard is a 
good example. The original standard 
specified a 128-bit key, but the National 
Security Agency intervened and had it 
shortened to 56 bits. The original length 
provided security against anyone, includ¬ 


ing the NSA; the new length allows the 
NSA (and anyone else with Cray-sized 
computers dedicated to decryption) to 
read anything sent in the code. This de¬ 
ception was revealed in computer trade 
journals, and the DES has been widely 
discounted because of it; but how much 
of this would have been revealed if the 
CIA was in charge of censoring technical 
publications? 

What can you do about this? First, 
look in your White Pages under “United 
States Government” for the nearest 
Federal Information Center. Call them 
and they’ll tell who your Representative 
and Senators are, and their addresses. 
Then, write a letter briefly explaining the 
situation and your viewpoint. Send 
copies to your Congresspeople, and to 
your favorite technical publications. In¬ 
dicate on the letter who is getting copies. 
Put messages into computer bulletin 
boards and electronic mail systems — let 
your friends and co-workers know. Xerox 
this page and post it at work. If you’re 
active in a technical society, introduce a 
resolution that prohibits external censor¬ 
ship of its publications. Get it incorporat- 
into the by-laws if possible; make it hard 
for any individual or agency to pressure 
your organization’s management, by mak¬ 
ing the will of the membership clear. 

If you value your right to know the 
latest technical information — act now. 
Next month may be too late. 


*San Jose Mercury News, 1/8/1982, 
page FI. 


Dr. Dobb’s Journal, Number 67, May 1982 
232 


59 



Dr. Dobbs Journal 














Dr. Dobbs Journal 

For Users ol Small Computer Systems / 

May 1982 Volume 7, Issue 5 


Editor — Marlin Ouverson 
Assistant Editor - Fritzi Lareau 
Contributing Editors - 

Dave Caulkins, Dave Cortesi 
Marketing Director - Craig Harper 
Advertising Sales - Laird Foshay 
Circulation Manager - Gloria Romanoff 
Circulation Assistants - 

Theresa O’Rourke, Terri Marty 
Research Assistant - Cynthia Winograd 
Art Director — Clifford West 
Production Manager - Barbara Ruzgerian 
Production Assistant - Joneva Barry 
Typesetter - Renny Wiggins 
Cover Illustration - A1 McCahon 


© 1982 by People’s Computer Company 
unless otherwise noted on specific articles. 
All rights reserved. 


Subscription Rates: $25 per year within the 
United States; $40 for first class to Canada 
and Mexico; $58 for airmail to other coun¬ 
tries. Payment must be in U. S. Dollars, 
drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be 
typed, double-spaced on white paper. List¬ 
ings should be produced by the computer, 
using a fresh, dark ribbon on continuous 
white paper. Please avoid printing on perfo¬ 
rations. Payment is in contributor’s copies. 
Requests to review galleys must accompany 
the manuscript when it is first submitted. 
Authors may receive a copy of the complete 
writer’s guidelines by sending a self- 
addressed, stamped envelope. 

Donating Subscribers Contributing Sub¬ 
scriber: $ 50/year ($25 tax deductible). Re¬ 
taining Subscriber: $75/year ($50 tax de¬ 
ductible). Sustaining Subscriber: $100/year 
($75 tax deductible). Lifetime Subscriber: 
$1000 ($800 tax deductible). Corporate 
Subscriber: $ 500/year ($400 tax deductible, 
receives five one-year subscriptions). 
Contributing Subscribers: Thomas H. 
Grohne, G. V. Elkins, Robert M. Connors, 
William J. McEown, Robert C. Luckey, 
Robert N. Stabler, DeWitt S. Brown, John 
B. Palmer, Jack Miller, Burks A. Smith, 
Transdata Corporation, Mark Ketter, John 
W. Campbell, Friden Mailing Equipment, 
Howard E. Decker, Jim Wilson, Frank 
Lawyer, Chris Pettus, Paul Lutus, Ben 
Goldfarb, Rodney Black, Steven Weiss, Pat 
Phelan, John Brodie, James Fleming, Unison 
World, Christopher Sherbak, Thomas Davis, 
Jan Steinman. Sustaining Subscribers: 
Gordon Eubanks, Jr., Pete Roberts, Steven 
Fisher Enterprizes. Lifetime Subscriber: 
Michael S. Zick. 

Foreign Distributors UK & Europe: 
Hofacker-Verlag, Tegernseer Strass 18, D- 
8150 Holzkirchen, West Germany. Asia & 
Australia: ASCII Publishing Co., Ltd, 
Aoyama Building 5F, 5-16-1 Minami 

Aoyama, Minato-ku, Tokyo 107, Japan. 


CONTENTS 


Articles 


15 PDP-1802 — Hardware Simulator in Assembly Language 

by Christopher L. Hamlin 

This author chose to execute PDP-8 machine-language programs on a COSMAC 
1802. This first of two articles describes the PDP-8 instruction set and front panel 
functions, and an octal console monitor for the 1802. 

22 Multi-68000s in a Personal System 

by At Kossow 

If real-time rotation of graphic images sounds good to you then this project, 
which also supports multi-tasking and several kinds of mass storage, should 
appeal. Long live homebrew! 

26 An Improved LET Processor for LLL Basic 

by Norman E. Thagard and George Glenn 

The version of Basic widely distributed in earlier years by Lawrence Livermore 
Lab has an assignment statement which is quite limited. The authors applied 
compiler theory loosely to this interpreter to come up with a much better LET. 

36 A Print Utility for CP/M 

by Dan Daetwyler 

Tired of seeing wasted printer paper? Would you rather batch your printing jobs 
than set up SUBMIT files? How about another good use of the ambiguous file 
name? This utility addresses all these; perhaps you will find ways to make it even 
more useful. 

50 A Cross-Reference Generator in C 

by Jeffrey L. Taylor 

Software conversion is one process which makes you wish you had a cross- 
reference listing. This one is written for Whitesmith’s C compiler and Portable 
C library, but the author has included aids for adapting it to other compilers and 
libraries. 


Departments 

4 Editorial 
4 Letters 

9 Dr. Dobb's Clinic 
12 Of Interest 
56 Book Reviews 


Dr. Dobb’s Journal (USPS 307690) is published twelve times per year by People’s Computer 
Company, Box E, 1263 El Camino Real, Menlo Park, CA 94025. Second class postage paid at 
Menlo Park, California 94025 and additional entry points. Address correction requested. 
Postmaster: send form 3579 to Box E, Menlo Park, California 94025 • 415/323-3111 


Dr. Dobb’s Journal, Number 68, June 1982 
234 


3 






LETTERS 


In Sync With Sinclair 

Dear DDJ: 

This letter is a response to the article 
on the ZX81 which appeared in the April 
issue of DDJ. 

I have been using microcomputers 
for many years and recently purchased a 
ZX81 with the 16K RAM pack. Let me 
say that I am extremely impressed with 
this machine. For $250 one gets a com¬ 
plete computer system capable of being 
programmed in BASIC or machine lan¬ 
guage. The 16K memory is quite suf¬ 
ficient for many serious applications in¬ 
cluding solutions of non-linear equations 
and other problems which are too big for 


most handheld calculators/computers. It 
is certainly a good alternative to a pro¬ 
grammable calculator as long as portabili¬ 
ty is not required. 

There are a wide variety of compa¬ 
nies producing hardware and software for 
this machine. While most of the software 
consists of game programs, the hardware 
being produced includes additional mem¬ 
ory, serial interfaces, modems, sound 
boards and other interfaces to permit the 
ZX81 to communicate with the world. 
Most of the modules are priced under 
$ 100 (e.g., a serial interface advertised by 
BYTE-BACK Co. is $60). Finally, a 
magazine (SYNC) and a newsletter (SYN¬ 



TAX ZX80) are devoted solely to provid¬ 
ing information/programs for the ZX81 
and its predecessor, the ZX80. 

This machine is certainly going to 
bring a lot of people into the micro 
world. I recommend it for educational 
purposes as well. 

Sincerely, 

Anthony Skjellum 
1695 Shenandoah Road 
San Marino, CA 91108 

PET Project 

Dear Sirs, 

I am a student at the University of 
New Brunswick, Canada, in the senior 


Editorial ~ 

Improving Reader Interface 


Great things are happening at Dr. Dobb’s Journal these 
days. With the beginning of summer we have re-dedicated 
ourselves to publishing more pages, with more articles and 
more services for our readers. We have always been people- 
oriented - machines serving humanity rather than the re¬ 
verse. This has set us aside from the ever more commercial 
elements, and has spurred us to stay on the cutting edge, a 
razor-blade position that has earned DDJ much respect. 

Improving our “reader interface” is something to 
which we are committed. When you get your next issue, 
take a close look at the Reader Service card. Beginning in 
the July issue, you will be able to use it to vote for the 
most interesting article of the month, as well as to request 
information about advertisements. The author who (aside 
from our full-time staff) receives the most positive reader 
response will get a cash honorarium as a token of reader 
appreciation. In this manner you will be able to voice your 
preference in each issue and encourage favorite authors to 
contribute again. 

* » * 

Have a look at the DDJ announcement on page 61. The 
first annual Great DDJ T-Shirt Contest is on! Long-time 
friends have been reminding us for quite a while that the 
three-headed dragon which for years emblazoned the chests 
of the microcomputing world, has grown a bit tattered. 
Time has come, they tell us, to bring a new design to life. 
All readers are invited to quickly submit their ideas, phrases 
or sketches. The winning entry will be announced in our 
September issue. 

* » * 

Now, a note for all of you who have been asking for 
more of Jonathan Mills’ 8080/8086 Cross-Assembler. As 
you read in his article, the size of the listing is enough to 
deter all but the most masochistic from attempting to type 
it in by hand. The author has since arranged for RD Soft¬ 
ware to distribute the software on disk. It should be avail¬ 


able soon; write to them at 1290 Monument Street in 
Pacific Palisades, CA 90272 and they will hold your letter 
until specific details are available. Then they will get in 
touch with you. 

* * * 

We don’t know the American Enterprise Institute, and 
can’t vouch for their ideas or policies. Bruce Schuman re¬ 
cently sent us their motto, though. Whoever they are, their 
words reproduced below express some things that work 
well for all of us in microcomputing, and in publishing. 

Competition of Ideas 

Competition of ideas 
is fundamental to a free society. 

A free society, 

if it is to remain free, 

cannot permit itself to be dominated 

by one strain of thought. 

Public policy derives from the ideas, 
speculation and theories of 
thoughtful men and women. 

Policy makers themselves 
rarely originate the concepts 
underlying the laws by which 
people are governed. 

They choose among practical options 
to formulate legislation, 
governmental directives, regulations 
and programs. 

If there is no testing 

of ideas by competition, 

public policy decision may undermine 

rather than bolster 

the foundations of a free society. 

MDO 


4 


Dr. Dobb’s Journal, Number 68, June 1982 

235 





year and I am taking a thesis project with 
the Bio-Engineering Institute of the uni¬ 
versity. The title of my thesis is: “Per¬ 
sonal computers adapted for young 
disabled patients and voice output inter¬ 
face for non-verbal handicapped (text 
to speech synthesis).” 

What I’m intending to do is work 
with the PET computer and change 
its normal keyboard to an expanded key¬ 
board (used to accommodate people with 
motor or limb dysfunctions). Also I will 
be investigating the possibility of inter¬ 
facing the PET computer, if possible, 
with printers other than those compatible 
with the PET, and also with a speech syn¬ 
thesizer for non-verbal, disabled persons. 
Lastly, if everything goes as planned, 
writing some programs for young persons 
in their first steps of learning. 

The reason I am writing to you now 
is to inquire if you have any relevant 
material on this subject. If so could you 
be kind enough to send me information 
on how I may obtain this. 

Thanking you in anticipation. 
Constantinos Pattichis 
780 Montgomery St., Apt 10A 
Fredericton, NB 
E3B 2Y1 
CANADA 

Packing It In 

The Editor, 

I enjoyed the notes (in “Clinic,” DDJ 
#60) on how to convert binary to BCD — 
without division — by adding hexadeci¬ 
mal “A”. About a year ago I was thinking 
along the same lines, and noted that “A” 
was part of the opcodes for 8086 instruc¬ 
tions AAM and AAD (opcodes D4 OA and 
D50A). These instructions convert be¬ 
tween decimal (BCD) and binary while 
at the same time packing a word into a 
byte/unpacking a byte into a word. 

“Is the ‘A’ in the opcode used as 
immediate data?” I wondered. I soon 
discovered that the unspecified machine 
instructions D410 and D510 convert 
between an unpacked hex or decimal 
word (four nibbles OxOy) and a packed 
byte xy (i.e., no change in base). 

Yours sincerely, 

Keith S. Wilkinson 
CPO Box 1748 
Tokyo, JAPAN 100-91 

Doubly-Dense Pascal 

Dear Dr. Dobbs, 

Subject : Difficulties on getting appro¬ 
priate hardware & software to run appli¬ 


6 

236 


cation written in Pascal needing more 
disk space than 8” single-density. 

I have run into the following dilem¬ 
ma in choosing an appropriate machine 
for a potential client: 

1. get machine already having UCSD 
Pascal for double-density, etc. (such as 
Altos), but wind up having only 2 serial 
ports (insufficient for console, printer 
and modem); also, one Altos user told me 
the company won’t let him have the 
BIOS source, saying it’s “proprietary,” 
making it difficult to customize the print¬ 
er routine; or 

2. get machine (such as S-100) for 
which hardware can be added at will and 
wind up having to do considerable pro¬ 
gramming to make d.d. work for Pascal 
under a CP/M version of UCSD by modi¬ 
fying the BIOS to handle double-density 
— must be redone for every disk control¬ 
ler; 

3. I have considered rewriting the in¬ 
terpreter to use the disk tables in a CP/M 
2 BIOS, effectively making a “ready-to- 
run” system for d.d. on all CP/M-type 
machines, but it appears such a system 
couldn’t be legally sold to a customer; or 

4. even make UCSD work at all if 
only one of the so-called adaptable sys¬ 
tems which are not CP/M-compatible can 
be obtained for the customer - which, I 
believe requires rewriting the entire 
BIOS for the JMP vectors needed for that 
“adaptable Pascal.” 

Other problems: A local computer 
store didn’t know of any backup for the 
hard disk on Apple (other than 35 mini¬ 
diskettes or another hard disk!), and I 
don’t know what the story is with other 
machines — I consider lack of backup to 
be totally unsatisfactory. 

It appears that it will take consider¬ 
able letter writing and/or phone calls to 
get the needed facts in order to determine 
the best solution, and I may have diffi¬ 
culty getting people to understand the 
dilemma and give me the needed informa¬ 
tion. 

Several so-called data-base systems 
for micros I’ve had experience with have 
limitations that hamper “relatively” 
sophisticated applications: DBASE2 
doesn’t delete entries from an index when 
records are deleted and makes indexing 
of more than one field in a record ex¬ 
tremely difficult; MDBS requires you to 
write your own editor; SELECTOR-3 
takes 15 minutes to delete one record 
from a 1000-record file. However, I’ve 
been able to write such an application 


from scratch purely in Pascal by using 
very good and imaginative organization to 
make it configurable — but the above 
hardware problems get in the way. All 
of this may be an argument for dropping 
UCSD in favor of a CP/M Pascal — losing 
UCSD’s portability advantage. 

Sincerely, 

Thomas R. Amoth 
2215 NW 16th 
Corvallis, OR 97330 

In Search Of . . . 

Dear Sirs: 

I have recently come up against cer¬ 
tain shortcomings in the packages that I 
currently use for professional Z-80 soft¬ 
ware development, and hope that one or 
more of your readers will be able to offer 
a solution. Failing that, perhaps one of 
the software houses will be prompted to 
respond to my need, which certainly may 
be a common one. 

The applications program which I am 
developing is composed of 23 relocatable 
modules, plus a definitions module com¬ 
posed of EQUates, and a COMMON data 
area. This comes to about 19,000 lines 
of code and comments. The definitions 
module and the COMMON area are 
INCLUDEd with each module assembly, 
for reasons I will describe later. The total 
program occupies about 32K code, with 
another 28K of tables and buffers, and 
there are 123 globally defined symbols. 

Each module is written in Z80 assem¬ 
bly language, for assembly by the 
CROMEMCO Z80 Macro Assembler, Ver¬ 
sion 3.07, under CP/M 2.2. The Assem¬ 
bler interfaces to CP/M through a small 
routine attached to the Assembler, caus¬ 
ing CDOS System Calls to be translated 
to CP/M BDOS Calls. The Assembler gen¬ 
erates relocatable code in Microsoft REL 
format, of course. I greatly prefer the 
CROMEMCO Assembler over Microsoft’s 
Macro-80 when it comes to appearance 
of assembly and cross-reference listings. 
The CROMEMCO Assembler also pro¬ 
vides the STRUCT and GLOBAL pseudo¬ 
ops which Macro-80 lacks. 

The modules are linked together by 
the Digital Research PL/1 linker, LINK- 
80 Version 1.3, which produces a .COM 
file quickly and easily in about 4 minutes. 
It is not possible to use Microsoft’s Link- 
80 Version 3.43 without running out of 
memory in my 53K transient area. 

For debugging, I use the CROMEM- 

(Continued on page 55) 


Dr. Dobb’s Journal, Number 68, June 1982 



DR. DOBB’S CLINIC 


by D.E. Cortesi 


The Answer, We Submit.. . 

We’ve had our hands on an IBM Personal Computer for a 
few days now. It’s just a computer, after all. However, it has 
a couple of nice touches in its batch facility (the equivalent of 
CP/M Submit processing). One is the PAUSE command, 
which waits for any character to be typed. If the character 
received is a control-Break (control-c), the batch file is 
cancelled; otherwise it continues. 

That’s a handy little function. You can stick a PAUSE 
command at the point in a batch file where the operator is 
supposed to change diskettes. Or you could put one between a 
compile and a link so the job could be killed if there were 
compile errors. 

In fact, it’s so handy that we wrote one for use on our 
CP/M system (Listing 1). One little-known sentence in the 
CP/M documentation explains that the proper way of aborting 
a submitted job is to erase the file $$$.SUB. That’s what 
our PAUSE does if the character typed is a control-c. 

Of course, you might be deep in a DDJ article when the 
job gets to the PAUSE and so not notice that the system 
was waiting. For those occasions, it’s nice to have the BEEP 
command in Listing 2. Then you can build submitted jobs 
along these lines: 

. .. lengthy commands . . . 

BEEP HEADS UP, DUMMY! 

PAUSE OK TO GO ON? CHANGE DISKS IF SO. 

. .. rest of job . .. 

With a couple of changes, BEEP becomes FORMFEED, a 
command to eject the printer forms during the batch job. 

Submit We Must 

We continue our campaign to raise the world’s submit- 
consciousness with an example. Lots of people use the disk 
cataloging system written by Ward Christiansen and distribut¬ 
ed on the CP/M User Group’s disk number 40. In order to 
use it, you have to give each diskette a permanent, three-digit 
number, and a name that is descriptive of its present use. 

Disks change their uses a lot. Often, we retire one of ours 
back to the box of free diskettes to await re-use. At that 
time, all entries for files on that disk should be pulled out of 
the master catalog, and the diskette should be re-entered 
to the catalog as “-FREE.nnn.” The submit file in Listing 3 
will do exactly that. 

The first thing it does is to list the catalog entry for the 
disk under its present name. Then it pauses, in case the user 
has second thoughts. If not, it uses ED as a utility to expunge 
every catalog entry that refers to the disk. ED is called again to 
build a one-entry file of catalog transactions to enter the disk 
under its new name of “FREE.” The UCAT utility updates the 
master catalog. 

. . . But IF We Submit . . . 

One of the great oversights in Dr. Kildall’s little system 
design was the omission of any convention for command re¬ 
turn codes. A command should be able to terminate with a 
success/failure flag, and it should be possible to test the last 
code in a submitted job. (The IBM DOS has the same glaring 
omission, by the way.) 

But there are other things that we’d like to test during the 
course of a batch job. We’ve seen cases where it would be 





useful to test (1) whether a file exists, and abort if it doesn’t, 
(2) whether an operand is an ambiguous file reference, and 
abort if it is, and (3) whether an operand was omitted, and 
abort the job if it was. 

The PAUSE command above demonstrates a general 
pattern on which such tests could be built. Does anyone feel 
like writing the IFEXISTS, IFAMBIG, and IFNULL com¬ 
mands for use in submitted files? Please do! Send them in, 
along with any similar sort of submit utilities you can think of. 
We’ve heard there is a simple way of chaining to another 
command. How about a command that will execute another 
command only on a certain condition? 

A Faster Warm Start 

We now have a 96KB CP/M system. The extra 32KB is 
accessed by setting the extended address lines of the S-100 
bus through a Godbout Memory Manager board. When active, 
it replaces the middle 32KB of the address space, from 4000h 
to BFFFh. What can you do with an extra 32KB of storage? 
Well, the only thing we’ve done with it so far is to cut the time 
our system takes to do a warm start. 

At the end of almost every CP/M command, the system 
selects the A-drive, seeks to track zero, and reads two tracks 
worth of CCP and BDOS. That refreshes the code of those 
programs in case the previous command had overlaid them. 
Then the BDOS causes a seek to track two and reads the disk 
directory. 

On our system, a warm start used to take just over two 
seconds — but not any more. Now, when the system comes up 
in a cold start, the BIOS switches in the extra 32K board and 
does a block copy of the BDOS and CCP. The extra board 
is then switched out and the regular storage switched in. 

On a warm start, the system no longer loads the monitor 
from disk. It just switches in the extra RAM and does a 
block copy from it to refresh the BDOS and CCP. That low¬ 
ered the warm start time by six-tenths of a second. It also 
produced two bonuses. First, the BIOS got smaller, since it 
took quite a bit of code to handle the warm-start I/O. Second, 
we can now put any disk at all in the A-drive. The A-disk no 
longer has to be “bootable,” except when the power is first 
switched on. 

One other change cut another seven-tenths of a second, 
but it is specific to our system. It uses the California Com¬ 
puter Systems BIOS, and that code supports all sorts of disk 
densities. When it selects any drive for the first time after 
a warm start, it has to feel out the density of the disk. It used 
to start by reading at single density. Most of our disks are 
double-density. The disk controller chip would try valiantly to 
read the disk at single density, not giving up until it had 
seen the index hole pass five times. Then the BIOS would try 
again at double density and succeed. We changed the logic so 
that the BIOS tries all disks first at double density. That cut 
five disk rotation times from every select of a new drive, 
including the select of the A-drive that follows a warm start. 

The effect of these two changes was to bring the warm 
start time below one second. The subjective effect is of a much 
snappier system. 

A Neater CCP 

We have in hand a copy of NEWCCP, a replacement for 
the Console Command Processor of CP/M 2.2 from MRZ Data 


Dr. Dobb’s Journal, Number 68, June 1982 


9 

237 




Systems (POB 2571, Warminster, PA 18974). NEWCCP comes 
as assembly source code for both the MAC and MACRO-80 
assemblers. It contains a number of added built-in commands, 
and improvements on the standard ones. We haven’t actually 
installed it yet, but just reading it and thinking about all the 
other improvements that we could stick into our very own 
CCP is almost enough to justify the $25 price. If it works 
when we try it — and it looks as if it should — it will be a real 
bargain. 

Cheap Thrills 

That brings up the subject of good, cheap, software. There 
are a number of really useful, really cheap programs on the 
market. All too often, the companies that sell these bargains 
can’t afford the price of mass-market advertising, so the 
products go unnoticed in the general hullaballoo. 

If you have discovered a software bargain, send us a 
one-paragraph review and description (like the one of 
NEWCCP, above). We’ll print it under the “Cheap Thrills” 
heading. A genuine cheap thrill would be a reliable piece of 
software that performed a generally useful function, and 
which came at a remarkably good price. 

On the Fast Track 

The idea of doing whole-track buffering of diskette I/O 
has been around for a while. The notion is that, whenever 
a program requests a read or write of a single sector, the 
system should in fact read the whole track that contains that 
sector. The advantage is that reading a whole track at once 
takes at most two revolutions of the diskette, and usually 
less. Reading one sector at a time can take two revolutions per 
sector in the worst case. 

There was an early implementation of this idea, for CP/M 
1.4 and limited to a Tarbell disk controller, on one of the 
early CP/M User Group diskettes. Nowadays there are several 
commercial implementations of the idea that go under vari¬ 
ous trademarks. 

If you want a good, practical discussion of how whole- 
track buffering is done, you can find it in an addendum 
being distributed with the CP/M-86 manual set from Digital 
Research. It’s a paper written by John Pierce which gives 
the theory and contains the skeletal code of a CP/M-86 BIOS 
to implement the idea. We don’t know if DR will send you 
the paper alone as an application note, or whether you have to 
order the whole manual set to get it. 

Intel Needs Help 

From the January-February issue of Solutions, a public- 
relations magazine put out by Intel Corp., we learn that Intel 
has prepared a Support Library for their 8087 numeric co¬ 
processor. It “consists of the function library, a decimal 
conversion module,.. . and a full 8087 software emulator for 
debugging without the 8087 component. The library ... 
supports the proposed IEEE Floating Point Standard.” 

Well, that’s a lot of software (even if the 8087 does do 
most of the work), so we suppose that Intel’s asking price of 
$1250 (gulp!) is justified. But is the 8087 so hard to work 
with that you need twelve hundred dollars worth of interface 
code? Surely not! Obviously, Intel doesn’t know how to sell 
chips. Let’s show them how it’s done: let’s put some 8087 
knowledge into the public domain so that experimenters can 


use the device. Any readers working with it? What kind 
of programming does it take? 

Promises, Promises 

Next month we will return to the problem of making a 
BASIC interpreter branch faster. Several readers have con¬ 
tributed to the discussion, but none has reported actual 
measurements or traces of operating programs. It ought to be 
especially easy to get an execution trace from any Microsoft 
BASIC; all you have to do is find a way to direct the output of 
TRON to a file for later analysis. Still, the important question 
of the dynamic behavior of practical BASIC programs re¬ 
mains open. Computer science is one of the few sciences that 
can be truly exact, you know. But without measurement and 
experiment, it isn’t a science at all! PBj 

Listing 1 

TPA equ OlOOh 

Boot equ OOOOh 


Bdos 

equ 

0005h 


CharIn 

equ 

1 


Erase 

equ 

19 


ControlC equ 

03h 


Pause 

org 

TPA 



mvi 

c,Char In 



call 

Bdos ; 

get one character 


cpi 

controlC 



jnz 

Boot ; 

just warm-start, 


mvi 

c, Erase ; 

..unless control-c 


lx i 

d, SubFile 



call 

Bdos ; 

..then erase ?$$.SUB 


jmp 

Boot 


SubFile 

db 

1,'$$$ 

SUB',0,0,0,0 

; 


rest of FCB is irrelevant 


end 

Pause 

_ 




Listing 2 


TPA 

equ 

OlOOh 


Boot 

equ 

OOOOh 


Bdos 

equ 

0005h 


CharOut equ 

2 


Bell 

equ 

07h 


Beep 

org 

TPA 



mvi 

c, CharOut 



mvi 

e,Bell 



call 

Bdos 



jmp 

Boot 



end 

Beep 


Listing 3 

A>type freedisk.sub 

; going to make the disk -$1.$2 a free disk 
cat -*.* $1.$2 

pause — does that look right? 
xsub 

ed mast.cat 
#a 

#ms,$1.$2* Z0L1K-1L 
e 

era names.sub 
ed names.sub 
I-FREE.$2 
e 

ucat 


10 

238 


Dr. Dobb’s Journal, Number 68, June 1982 



OF INTEREST 


by Michael Wiesenberg 


For further information on any of the 
items mentioned in this column, circle 
the designated number on the Reader 
Service card and return it to us. Your 
request will be processed promptly. 

Communication Is What Computers 
Do With Each Other 

LogOn, from Ferox Microsystems is 
a software package that turns your desk¬ 
top computer into an auto-dial, auto¬ 
answer, intelligent terminal that inter¬ 
communicates with other computers. 
With menus, users send and receive text 
or binary files, exchanging messages, 
electronic mail, programs, graphic im¬ 
ages, etc., at 30 to 120 cps. A per¬ 
manent directory of frequently-called 
numbers and computer configurations 
can be constructed. Then the user se¬ 
lects a computer from a menu, and 
LogOn dials, redials automatically if 
necessary, transmits data, and retrans¬ 
mits blocks when necessary (based on 
CRC checking). LogOn is written in 
UCSD Pascal, and can be ported to any 
other UCSD Pascal-based micro, mini, 
or mainframe, making it upward- 
compatible. Cost is $150 on 5'A- or 8- 
inch disk for most systems. (Reader Ser¬ 
vice No. 303) 

Tickerscreen, a computerized stock 
market bulletin board, is a free service for 
investors with personal computers. Of¬ 
fered by Max Ule & Company of New 
York, Tickerscreen can be accessed for 
the cost of a local call in over 150 cities. 
The service provides closing New York 
Stock Exchange prices, closing market 
indexes, commission computation on 


any stock or option transaction, di¬ 
rect order entry for Ule’s clients, and 
(here’s the pitch) a demonstration of 
Tickertec, a service that displays the 
NYSE or AMEX tickertape without a 
fifteen-minute delay. (Reader Service 
No. 313). 

Hardware Not Sold in 
Hardware Stores . . . 

The Rockwell AIM-65 is a true 
microcomputer-in-a-briefcase. It has its 
own 120-line-per-minute, 20-column 
thermal printer, a 20-column alphanu¬ 
meric display, a keyboard, 1 or 4K RAM 
and 4 or 16K ROM. Memory expan¬ 
sion to 32K is possible. Applications are 
installed in ROMs or EPROMs. Software 
options include BASIC, an assembler, a 
compiler, Forth, a math package, and Pas¬ 
cal. The stripped-down, fully-expandable 
machine costs $419, while the complete 
AIM-65 in a thin briefcase, with power 
supply, is $518. (Reader Service No. 
323) 

The Micro-Professor is a computer- 
in-a-book, a Z-80-based single-board 
computer with 2 to 4K bytes of RAM, 
and 2 to 8K of ROM. It has a built-in 
six-digit LED, and a 36-key keyboard. A 
3.5-by-1.3-inch wire-wrap area is used 
for breadboarding. It comes with a built- 
in speaker and cassette tape interface, 
and costs $149. (Reader Service No. 333) 

Your basic inexpensive tiny comput¬ 
er is the Super Elf, $106.95 for kit and 
$156.65 assembled (including high and 
low address options, speaker, transform¬ 
er). Tiny BASIC for the 1802 processor, 
Super BASIC, S-100 expansion, color 


video, memory expansion to 64K, an edi¬ 
tor and assembler, and suchlike are all 
options. (Reader Service No. 343) 

The Kaycomp II comes in a solid- 
looking metal case. It has a nine-inch 
green display with 80 columns of 24 
lines, eliminating, they say, the need for 
horizontal scrolling. Two 514-inch disk 
drives are included. The Z-80-based 
system software includes CP/M, a menu- 
driven operating system, a full-blown 
word processor, BASIC, Forth, an elec¬ 
tronic spreadsheet, and a math program. 
All this costs $1795 (even the price is 
familiar). (Reader Service No. 353) 

Hewlett-Packard has introduced a 
color pen-plotter, the HP 7470, compati¬ 
ble with most personal computers and 
many oscilloscopes and spectrum analyz¬ 
ers, and priced at a reasonable $1550. 
The 7470 uses a micro-grip drive system 
that obviates heavy moving arms and 
paper-transport drums and belts, elimi¬ 
nating some of the problems of conven¬ 
tional plotters. Two rotating “grit 
wheels” cause grit particles to penetrate 
the drawing medium at thousands of 
points, causing microscopic indentations 
indetectable to the naked eye. This 
machine weighs only 12.5 pounds! 
(Reader Service No. 363) 

How would you like to instantly 
double the capacity of all your floppies, 
for only $9.39? The Flip-Jig is a gadget 
to mark and punch the jackets of disk¬ 
ettes so that you can use both sides. After 
all, both sides of a diskette are coated 
with magnetic material, but when the 
manufacturer puts it into its jacket, 
only one side is usable (we know there 



The HP7470 color pen 
plotter (at left) is com¬ 
patible with most per¬ 
sonal computers. 


The Match-Box from 
ICO-Rally (at right) 
provides a programma¬ 
ble pin and socket con¬ 
figuration for device 
compatibility. 



12 


Dr. Dobb’s Journal, Number 68, June 1982 

239 




are potential hazards, but if backups are 
used, the potential savings are at least as 
great. . .). (Reader Service No. 373) 

Program it yourself on the PROM-IT 
EDS EPROM development system for 
the Apple II. Burn 8, 16, and 32K 
EPROMs, and down-load hex files from 
any computer or development system 
with an RS-232 port, for $129.50. 

—(Reader Service No. 383) 

Connect anything to anything with 
Ico-Rally Corp.’s Match-Box, a two- 
component computer cabling system with 
programmable pin and socket configura¬ 
tion for device compatibility. Users no 
longer need to unsolder leads and move 
pins. With Match-Box, they can neatly 
adjust the cables in a few minutes. 
Prices range from $19 to $53, depending 
on the number of conductors in the 
cable. (Reader Service No. 393) 

Expanded disk storage for IBM per¬ 
sonal computers provides up to 672K 
bytes in SVi-inch floppy-disk drives. 
Interface prices range from $470 for one 
single-sided drive internal to the IBM 
cabinet, or $670 for one double-sided 
(336K) external drive with cabinet and 
power supply (Reader Service No. 403) 

Plexa-Lok is a clear cover to protect 
your Apple keyboard. It locks into place, 
and can be used while the computer is 
running. Your $19.95 includes a 30-day 
money-back guarantee. (Reader Service 
No.413) 

. . . and Software Not Sold in 
Dress Shoppes 

MicroMUMPS, ANSI MUMPS for 
most micros, is available from the Univer¬ 
sity of California at Davis. Since the code 
is in the public domain, it costs only $33, 
including object code, applications, utili¬ 
ties and documentation. Source code is 
also available at extra cost, as are a year 
of updates. Additional packages include 
File Manager and Quest. You need CP/M 
or equivalent and 56K of memory. Write 
for an order form on which you can 
specify your configuration. (Reader Ser¬ 
vice No. 379) 

Everything you ever wanted to know 
about APL on your micro but were afraid 
to ask? APL Press in Palo Alto can give 
you more information. (Reader Service 
No. 423) 

Logo is a graphics-oriented language 
primarily for young users. Krell Software 
offers what they claim is the only real 
thing, M.I.T. Logo, for $179.95 (and they 


ask you not to buy anybody else’s). Re¬ 
quires 64K (Reader Service No. 433) 

Terrapin is an anybody else that of¬ 
fers a version of Logo called Terrapin Lo¬ 
go Language. (The language features a 
turtle.) This one costs $149.95 and is 
only for Apple II (also 64K). (Reader 
Service No. 443) 

If you’re going to sell software to the 
Department of Defense, you need Ada. 
Ada is primarily a process-control lan¬ 
guage, but it is also useful for business, 
finance, education, and mathematics, ac¬ 
cording to Supersoft, who sell Supersoft 
Ada, which they claim is the first true 
Ada compiler for microcomputers (every¬ 
thing for micros so far has been a subset). 
(Remember, this is a “true” compiler for 
a language for which the standard has not 
yet been validated.) It sells for $250, and 
requires 48K of memory on a Z80, 8080, 
or 8086/8088 system with CP/M. (Read¬ 
er Service No. 453) 

MicroPILOT is a command-oriented 
authoring language for educators. Teach¬ 
ers with no previous computer experience 
can create their own computer-assisted 
instruction materials. It costs $79.95 
from Radio Shack, and requires a TRS- 
80 Model I or III with at least 32K of 
memory. (Reader Service No. 463) 

A real native code hardware- 
independent BASIC compiler for CP/M? 
That’s the claim for BASIC/Z. Input/ 
output is supported at the source code 
level. All floating-point math is done in 
binary-coded decimal (BCD), to avoid 
round-off errors. Records can be blocked 
and deblocked. A SORT verb, part of the 
language, sorts 2000 elements in two 
seconds. Structured programming is sup¬ 
ported with nested DO/UNTIL, WHILE/ 
WEND, FOR/NEXT, IF/THEN/ELSE. 
User-defined functions are fully recur¬ 
sive, and can contain an unlimited num¬ 
ber of statements. Error trapping routines 
can even handle BDOS errors, and PUSH/ 
POP permits subroutine stack manipula¬ 
tion. BASIC/Z includes an interactive 
editor with global search and replace and 
complete syntax testing during entry. A 
debugger offers line tracing, error line re¬ 
tention, and “stepping” one line at a time 
through a compiled program while con¬ 
tinuously displaying the values of selected 
variables. Sounds good. BASIC/Z runs on 
CP/M systems with addressable cursor, 
and costs $345. (Reader Service No. 473) 

SMAL/80 (Structured Macro Assem¬ 
bly Language) “combines the logical 
power, versatility, and convenience of a 


compiled, structured high-level language 
like Pascal, Ada, or C with the efficiency 
and flexibility of an assembly language.” 
In addition to assembly language state¬ 
ments, SMAL/80 uses constructs like 
BEGIN . . . END, IF . . . THEN . . . ELSE 
. . ., and LOOP . . . REPEAT, and is not 
field-fixed, permitting indented state¬ 
ments for easier reading. It also uses sym¬ 
bolic notation to reflect what the proces¬ 
sor is actually doing, such as A = B instead 
of MOV A.B and A = NOT A instead of 
CMA. It’s a compiler, not an assembler, 
an extension by Dr. Charles Popper of 
SMAL, the language he developed in 
1974 at Bell Telephone Labs. The pack¬ 
age includes compiler, linker, macro pro¬ 
cessor, and macros that translate 8080 
into SMAL/80. Chromod Associates sell 
SMAL/80 on CP/M disks for $150. 
(Reader Service No. 483) 

Printers Not Found in Printshops 

How about a letter-quality daisy 
wheel printer for $1195? The DTC 381 
merges new technology with a refur¬ 
bished Diablo HiType I print mechanism. 
Serial RS-232 interface, baud rates from 
50 to 19,200, plastic printwheels, propor¬ 
tional and incremental printing, bidirec¬ 
tional printing, optional Centronics- 
compatibility, a mobile wheeled stand 
with paper tray and side shelves, etc., etc. 
(Reader Service No. 493) 

The Transtar 140 Diablo-compatible 
40-cps serial daisy wheel printer lists at 
$1695. (Reader Service No. 309) 

If you have an IBM 50, 60, or 75 
electronic typewriter, you can get a 
“smart” parallel printer interface for 
$499.95, or serial for $649.95. The Tlec 
Mark II or III features software indepen¬ 
dence, and text formatting capabilities, 
such as proportional spacing, right justi¬ 
fication, mixed pitches, page titling and 
numbering, hanging indents, centering, 
underscoring, intelligent margins and 
tabs, boldface, etc., and 17 cps through¬ 
put. (Reader Service No. 319) 

MicroFazer is a 64K printer buffer 
for all popular micros and parallel print¬ 
ers. It receives and stores up to 64K of 
data at 4000 cps, and then transfers the 
data to the printer as rapidly as the print¬ 
er can handle it, meanwhile freeing the 
computer for other processing. Prices 
range from $159 for an 8K buffer to 
$299 for 64K. (Reader Service No. 329) 

(Continued on page 25) 


Dr. Dobb’s Journal, Number 68, June 1982 
240 


13 


PDP-1802 

A Hardware Simulator in Assembly Language 


T he program presented in this article 
permits the execution on COSMAC 
1802 systems of programs written 
in the machine language of the Digital 
Equipment Corporation PDP-8 minicom¬ 
puter. The article is in two parts; part 1 
describes the PDP-8 instruction set and 
front panel functions, as well as an octal 
console monitor program for the 1802 
which allows loading, examining and 
changing 12-bit memory locations using 
octal notation. Part 2, to be published 
soon in DDJ, presents the PDP-8 instruc¬ 
tion interpreter for the 1802, and the I/O 
and interrupt facility. 

The original PDP-8 was the first 
minicomputer to be widely adopted, and 
in many respects it heralded the minicom¬ 
puter revolution; it was the 8008 of 
minis, and brought computer power to a 
far broader spectrum of users than had 
previously been the case. Partly as a re¬ 
sult, an immense amount of free or low- 
cost software exists for the PDP-8, much 
of which can be executed using the emu¬ 
lator described here. Many of the soft¬ 
ware and systems concepts first devel¬ 
oped for the PDP-8 have since gone on to 
find application elsewhere in the DEC 
line, and by extension in the computer 
field at large. 

The first PDP-8 was made up of dis¬ 
crete devices, with a massive power sup¬ 
ply and fan system to match. Later 
models used integrated circuits, and both 
size and power requirements were greatly 
reduced. The emulator described here, 
which I call the PDP-1802, is based on 
the first PDP-8 (the “straight eight”), 
with certain modifications closer in 
operation to the behavior of the PDP-8/1 
and PDP-8/L, which were later models. 
These modifications are described in part 
2 . 

The emulator maps a virtual 12-bit 
word address space onto the 8-bit word 
space of the microcomputer system, and 
performs the necessary address conver¬ 
sion and data packing and unpacking. 
Thus 4096x0 twelve-bit words (a PDP-8 
“field”) map into 6K of eight-bit bytes. 
Since the emulator requires only about 
D/ 2 K bytes, including the octal console 
monitor, a PDP-8 with a single field can 


Christopher L. Hamlin 


Copyright © 1982 by Christopher Hamlin. 
All Rights Reserved. 

2202 Hindle Lane, Bowie, MD 20716. 


be emulated on an 1802 with fewer than 
8K bytes. Of course, it is possible to write 
and run small PDP-8 programs on 1802 
systems with as few as 2K bytes. 

Hardware requirements are minimal. 
Most 1802 systems use either a toggle- 
switch front panel, or (more commonly) 
a hexadecimal keypad. In either case, this 
is the minimum needed to enter and run 
programs. Certain PDP-8 switch-register 
functions (described below) cannot be 
supported on systems using only a 
software-scanned hex keyboard such as 
that on the RCA VIP; such users will 
need to provide software or hardware al¬ 
ternatives. 

The PDP-8 

The front panel of the PDP-8 has 
twelve toggle switches for setting addresses 
or data into the switch register. These 
permit one to address 4096i O twelve-bit 
words directly. Three more switches al¬ 
low manual selection of any of eight 
such 4096io word fields. The PDP-1802 
emulator assumes there is one field whose 
first address is 0000 8 , though it could 
readily support multiple field operation. 

The remaining switches are: 

Load Address: Causes the address set 
in the twelve switches to be placed in the 
address register. 

Deposit: Causes the word set in the 
twelve switches to be placed in the mem¬ 
ory location pointed to by the address 
register. The address register is then incre¬ 
mented, allowing loading of successive 
memory locations from the panel switches. 

Examine: Causes the value in the 
memory location pointed to by the ad¬ 
dress register to be placed in the accumu¬ 
lator and displayed on the front panel, 
in the twelve lamps showing the accumu¬ 
lator content. 

Start: Causes execution to begin at 
the address in the address register (usually 
placed there by using the Load Address 
switch). Various registers and flags are 
initialized in so doing. 

Continue: Same as Start, but without 
the initialization step. 

Single Cycle: When on, this switch 
permits stepping through a program 
machine-cycle by machine-cycle by 
repeatedly pressing the Continue switch. 

Single Instruction: Same as Single 
Cycle, but executes a complete instruc¬ 
tion. 

In addition to the accumulator, the 
states of the memory buffer, program 
counter, and memory address register are 


displayed by sets of twelve lamps, and 
one lamp shows the state of the link bit 
(similar to a carry bit for the 1802 DF). 

For PDP-8 models equipped with 
hardware-extended arithmetic elements, 
an additional set of lamps shows the state 
of the multiply register (not included in 
the PDP-1802 emulator). 

Finally, a set of lamps shows the 
current machine cycle, and the type of 
instruction or machine state. 


PDP-8 Instructions 

The PDP-8 instructions are simple 
and are easy to learn quickly. 

All instructions are twelve bits long. 
The left-most (most significant) three 
bits (called bits 0, 1, and 2) form the 
operation code; there are eight of these. 
The instructions with op codes 0 8 through 
5 8 treat the remaining nine bits identical¬ 
ly, and are called memory reference in¬ 
structions. The memory reference instruc¬ 
tion op codes and their mnemonics are 
given below. 

Here is how the low nine bits of 
the memory reference instructions are 
treated: 

The lowest seven bits form the low 
part of the address with which the 
instruction is concerned, and can address 
any word on one page (a page is 128 x 0 
twelve-bit words). 

Bit 4 (fifth from the left) controls 
where the other five bits of the full ad¬ 
dress with which the instruction is con¬ 
cerned will come from; in other words, 
bit 4 determines which page contains the 
address the instruction refers to. If bit 4 
is zero, then the address is a location in 
page 0, specified by the low seven bits. 
If bit 4 is one, then the address is on the 
current page (the page on which the 
instruction itself resides). 

Bit 3 (fourth from the left) controls 
direct and indirect addressing. If it is 
zero, direct addressing is used, and the 
instruction is carried out using the loca¬ 
tion specified by bits 4 through 11 as the 
effective address. If bit 3 is one, indirect 
addressing is used. The effective address 
for the instruction is that pointed to by 
the content of the location specified by 
bits 4 through 11. Indirect addressing per¬ 
mits operations to be carried out over the 
whole field addressed by twelve bits. 

To summarize, memory-reference in¬ 
structions operate on locations selected 
directly or indirectly through page 0 or 


Dr. Dobb’s Journal, Number 68, June 1982 


15 

241 




the current page. 

The actions of the memory reference 
instructions are as follows: 

(0) — AND: perform logical AND be¬ 
tween the content of the location 
specified and the content of the ac¬ 
cumulator, leaving the result in the 
accumulator. The memory loca¬ 
tion’s content is unchanged. 

(1) —TAD: perform two’s complement 

addition between the specified loca¬ 
tion’s content and the accumulator 
content; the result is left in the ac¬ 
cumulator. Any carry complements 
the link bit. In two’s complement 
notation, the values 0000 8 through 
3777 g are positive; 4000 8 through 
7777 8 are negative, with 7777 g re¬ 
presenting -1. 

(2) — ISZ: increment the content of the 

specified location; if the result is 
zero, skip the next instruction (that 
is, the instruction following the 
ISZ). 

(3) — DC A: deposit the content of the ac¬ 

cumulator in the specified location, 
then clear the accumulator by plac¬ 
ing 0000 8 in it. 

(4) - JMS: jump to a subroutine. The ad¬ 

dress of the location following the 
JMS instruction is automatically 
placed in the specified location, and 
execution proceeds with the in¬ 
struction immediately following the 
specified location. (A return is thus 
simply a jump indirect to the first 
word of the subroutine). 

(5) -JMP: jump; transfer execution to 

the location specified. 

The remaining op codes are 6 and 7. 

Op code 6 is reserved for input and 
output instructions. Since these are hard¬ 
ware dependent, only the I/O instructions 
governing operation of the teletype and 
paper tape reader/punch are implemented 
in the PDP-1802 emulator. They are de¬ 
scribed in the next part of this article. 

Op code 7 covers operations on the 
accumulator, link, and switch register, as 
well as conditional jumps. It also governs 
operation of the extended arithmetic ele¬ 
ment if this is used; El A instructions are 
not implemented in this emulator. 

The op code 7 instructions are called 
the “operate microinstructions.” There 
are two groups of operate microinstruc¬ 
tions, called Group 1 and Group 2. Bit 3 
governs the choice of group; if bit 3 is 0, 
the Group 1 operate microinstructions 


are selected. If bit 3 is 1, the Group 2 
operate microinstructions are selected so 
long as bit 11 (the rightmost) is a 0 (if it 
is a 1, then the extended arithmetic ele¬ 
ment is invoked). 

The function(s) to be performed by 
the instruction are determined by setting 
one or more bits to 1. The bit assign¬ 
ments for Group 1 are as follows: 

Bit 4: Clear the accumulator (set it to 
0000 8 ); 

Bit 5: Clear the link (set it to 0); 

Bit 6: Complement the accumulator 

(change 0’s to 1 ’s and vice versa); 
Bit 7: Complement the link; 

Bit 8: Rotate the accumulator right 
(through the link); 

Bit 9: Rotate the accumulator left 
(through the link); 

Bit 10: Perform a rotate operation select¬ 
ed by bit 8 or 9 once if 0, or 
twice if 1; 

Bit 11: Increment the accumulator. 

More than one of the function selec¬ 
tion bits may be set to 1 in a single oper¬ 
ate instruction; that is why these are 
called microinstructions. By setting bit 4 
and bit 6 in a Group 1 microinstruction,' 
for example, the accumulator would be 
cleared and complemented, leaving it 
filled with l’s. Any logically admissable 
combination of microinstructions may be 
used (it would not, for instance, be logi¬ 
cal to specify both a rotate left and a ro¬ 
tate right). The precise sequence in which 
combined microinstructions are executed 
is described in part 2 of this article. 

The Group 2 operate microinstruc¬ 
tions include conditional skips based 
upon the state of the accumulator and 
link. These conditional skips work in 
an ingenious way which requires special 
discussion. The other Group 2 micro¬ 
instructions are therefore presented first: 

Bit 4: Clear the accumulator (same as 
Group 1); 

Bit 9: Perform logical OR between the 
switch register and the accumu¬ 
lator contents, leaving result in 
the accumulator; 

Bit 10: Halt; stops processor operation. 

The conditional skip microinstruc¬ 
tions test the accumulator or the link or 
both. If the specified condition is met, 
the instruction following the operate 
microinstruction is skipped. There are 
two distinct sets of tests which are 


16 

242 


performed to determine whether a skip 
will occur. Bit 8 (called the reverse sens¬ 
ing bit) determines which set of tests is 
to be performed. These two sets of tests 
are treated separately: 

Bit 8 is 0 

Bit 5 set to 1: perform skip if accumula¬ 
tor is minus; 

Bit 6 set to 1: perform skip if accumula¬ 
tor is zero; 

Bit 7 set to 1: perform skip if link is non¬ 
zero. 

If more than one condition is being 
tested (i.e., more than one bit is set), only 
one of the tests called for need be true 
for the skip to occur. In other words, 
the results of the tests called for are 
logically ORed together, and if the result 
is 1 (true) the skip takes place. 

Bit 8 is 1 

Bit 5 set to 1: perform skip if accumula¬ 
tor is positive (zero is 
positive); 

Bit 6 set to 1: perform skip if accumula¬ 
tor is non-zero; 

Bit 7 set to 1: perform skip if link is zero. 

Notice that the conditions are re¬ 
versed if bit 8 is 1. In addition, when the 
reverse sensing bit (bit 8) is set, the re¬ 
sults of the conditions tested are logically 
ANDed together, instead of being ORed. 
Thus all conditions for which tests are 
called must be met for the skip to occur. 
For example, if bit 8 is 1, and bits 5 and 
7 are set to 1, the skip will occur if and 
only if the accumulator is positive (which 
includes zero) and the link is zero. 

The final Group 2 operate micro¬ 
instruction is a special case: if bit 8 is 1 
and bits 5, 6 and 7 are 0, an uncondition¬ 
al skip is forced. 

The manner of combining Group 2 
conditional skip microinstructions makes 
it possible to perform in a single instruc¬ 
tion many kinds of tests which are impor¬ 
tant in efficient logical and arithmetic 
data processing. 

The final PDP-8 op code, 6, will be 
treated in part 2 along with the discus¬ 
sion of PDP-8 interrupt servicing. 


The Autoincrement Registers 

Many computations involve the need 
to step through long tables of data one 
word at a time. In order to simplify (and 
speed up) operations of this kind, the 


Dr. Dobb’s Journal, Number 68, June 1982 


PDP-8 architecture provides a set of auto- 
increment registers. These aren’t really 
separate registers; they are simply mem¬ 
ory locations 0010 8 through 0017 8 in¬ 
clusive. Here is how the autoincrement 
operation works: 

If, and only if, one of the locations 
0010 8 through 0017 g is addressed in¬ 
directly by a memory reference instruc¬ 
tion, then the content of that location is 
incremented by one before it is used to 
form the effective address (of the oper¬ 
and) of the instruction. The incremented 
content remains in the location; the con¬ 
tent will be incremented again the next 
time the location is addressed indirectly. 
This is known as autoindexing. The tech¬ 
nique allows for rapid stepping through 
tables without having to use ISZ instruc¬ 
tions to update the address (notice that 
no separate instruction is needed to im¬ 
plement this function). Bear in mind that 
you must be careful not to address one 
of these locations indirectly if you do not 
wish its contents to be incremented. 
Autoindexing is fully supported on the 
PDP-1802. 

The Octal Console Monitor 

The front panel functions of the 
PDP-8 are emulated by a monitor using 
an ASCII keyboard and CRT display. 
(Provisions for substituting a hex key¬ 
board and LED display are described 
too). On entry to the emulator, the moni¬ 
tor issues a carriage return/line feed and 
awaits imput. At this point, only two 
types of input are recognized: a “C”, 
or an octal digit. If a “C” (for Continue) 
is typed, execution of an already entered 
PDP-8 program continues with values 
which have been set up in the registers 
and buffers. This can be used to resume 
execution after a Halt, for instance. If 
anything but a “C” is entered, the 
monitor will take the first four octal 
digits entered (ignoring any other charac¬ 
ters) as an address. The content at that 
address is immediately displayed in octal 
digits, and the cursor halts on the same 
line. At this point the monitor will ac¬ 
cept only a space, an octal digit, “C”, 
“S”, or “L” as input. Pressing the space 
bar causes successive locations and their 
content to be displayed. If an octal digit 
is entered instead, then the first four oc¬ 
tal digits entered will replace the old con¬ 
tent at that location. Entering “L” (for 
Load) causes issuance of a CR/LF; the 
monitor then waits for four octal digits, 
forming a new (virtual) memory address 


18 


to be examined or modified. “S” causes 
execution to start from the location cur¬ 
rently displayed by the monitor, after 
initialization of the PDP-8 registers. “C” 
causes execution to continue from the 
currently displayed address without 
initializing the registers. 

Other Panel Functions 

The PDP-8 single-step function and 
switch register are implemented in the 
PDP-1802 by closely related methods, 
and so are described together. It is as¬ 
sumed that the 1802 system has either a 
hex keypad or a set of eight toggle 
switches for entering data and addresses, 
and that an additional switch connected 
to one of the 1802 EF lines is used to sig¬ 
nal the presence of data in the switches 
or keypad latch. 

Closing the switch on the EF line 
causes execution to be suspended upon 
completion of the current PDP-8 instruc¬ 
tion. The content of the program count¬ 
er, the memory address buffer, and the 
accumulator are shown on the CRT 
screen in octal. After the EF line switch is 
released (opened), the emulator is ready 
to set up the pseudo switch register. The 
high four bits of the twelve-bit switch 
register content are placed in the low half 
of the hex keypad latch or panel switches. 
The most significant bit of this byte will 
determine whether single-stepping mode 
is to be entered. If that bit (which is not 
one of the twelve-switch register bits) is 
a 1, a single instruction will be executed. 
If it is a 0, normal execution is enabled. 

Pressing (closing) the EF line switch 
and holding it pressed loads the byte, set¬ 
ting the most significant four bits of the 
pseudo switch register and also setting or 
resetting the single-step flag. While the 
EF line switch is still held closed, the low 
eight bits of the pseudo switch register 
are now set up on the keypad or panel 
toggles. When the EF line switch is re¬ 
leased, the pseudo switch register will 
have been set up, and single stepping will 
have been enabled or disabled. Execution 
will continue accordingly. 

Notice that this procedure, although 
it permits carrying out any operation of 
which the PDP-8 switch register func¬ 
tions would be capable, does not work in 
the same way it does on the actual PDP- 
8. In effect, the EF line switch results in 
actions like those obtained by successive¬ 
ly pressing Halt and Continue on the 
PDP-8 (when the emulator’s single-step 
bit is 0) or like the single instruction 


switch (when the single-step flag bit is 1). 
The major difference is that computer 
operation is halted whenever the switch 
register setting is changed. 

It is important to observe that the 
procedure just described only sets up the 
pseudo switch register. In order to make 
use of its content in a program, the 
normal PDP-8 microinstruction for 
ORing the switch register into the ac¬ 
cumulator must be used. The emulator 
does not allow for the single cycle func¬ 
tion, because the structure of operations 
by which instructions are executed does 
not resemble the states of the PDP-8 
cycles. 

It should now be possible for readers 
to experiment with writing and entering 
PDP-8 programs, using the octal monitor. 
In the concluding part of this article, the 
input and output functions for the tele¬ 
type and paper tape reader/punch are de¬ 
scribed, along with the procedure for 
emulating interrupts. The operation of a 
software UART (universal asynchronous 
receiver/transmitter) for the teletype, in¬ 
cluded as part of the emulator, is also ex¬ 
plained. The implementation of the PDP- 
8 instruction interpreter is outlined, and 
considerations affecting adaptation of the 
emulator to different hardware configura¬ 
tions, as well as relocation of the program 
(perhaps for installation in an EPROM) 
are discussed. 


Dr. Dobb’s Journal, Number 68, June 1982 

243 


Homebrew Lives: 

Multi-68000s in a 
Personal System 


T he computer system described in 
the following paragraphs is an at¬ 
tempt on the part of myself, Darryl 
Uchitil, and Jim Hannas to design and 
build a home computer at the current 
state of the art in microprocessor-based 
computers. It has a simple bus design, 
supports a very sophisticated color raster 
display, a number of different types of 
mass-storage devices, and a sophisticated 
multi-tasking operating system. 

The first design session for the graph¬ 
ics display began in the early spring of 
1979. I was, at that time, working for the 
University of Wisconsin at Milwaukee as 
the graphics consultant for the univer¬ 
sity computer center. In addition to the 
usual collection of Tektronix graphics de¬ 
vices, the computer center had a DEC 
GT-46 vector interactive graphics system. 
The GT-46 is a PDP-11/34 computer 
with a 16”vector display capable of draw¬ 
ing vectors with 10 bits of X and Y reso¬ 
lution. If you have ever seen a vector dis¬ 
play rotating an image in real-time you 
would know why Jim, Darryl and I all 
sensed a need for such a device on our 
own computers. 

The initial design meetings we had 
centered on the idea of getting a vector 
display running on the S-100 systems we 
had at home, with at least the resolution 
of the GT-46. A prototype for the 
1024 x 1024 vector display was finished 
in late spring by Jim but presented all of 
us with a problem. While the vector 
display did work, it was limited in the 
number of lines that it could draw before 
the entire screen began to flicker. There 
was no way to speed up the drawing rate 
of the vectors without going to an analog 
vector generator, something which we 
really didn’t want to do. In addition, 
there was no practical way to ever build a 
high-resolution vector display capable of 
displaying color. As a result, it was 
decided that the graphics display would 
have to be a raster rather than a vector 
display system. 

The decision to abandon the design 
of a vector graphics display in favor of a 
raster system represented a real problem 
in generating images via the computer. 


by Al Kossow 


Al Kossow, Medical College of Wisconsin, 
Department of Physiology, 8701 Water- 
town Plank Road, Milwaukee, WI 53226. 


A vector display requires only the end 
points of a line segment to be computed 
to draw a line, whereas every point within 
a line must be computed and drawn a dot 
at a time on a raster display. There was 
no way a Z-80 would ever be able to per¬ 
form the calculations fast enough for up¬ 
dating a raster display. Since a Z-80 
wouldn’t be fast enough, we would have 
to build faster computers. 

The processor we decided upon at 
that time for the graphics computer was 
the Motorola 68000. Although very little 
information was available on it in the 
summer of 1979, we felt that the 24-bit 
address space and 32-bit registers would 
be very useful for manipulating all of the 
memory required for a high-resolution 
color display. 

The idea of multiple 68000s within 
the computer evolved because of our de¬ 
sire to maximize performance of the 
graphics display while also being able to 
support a multi-tasking operating system. 

I was able to get enough information on 
the 68000 processor by early fall to begin 
the slow and painful process of boot¬ 
strapping the software needed to get the 
processor going. A FORTRAN cross- 
assembler was a byproduct of the initial 
work done to write a small debugger for 
the 68000. 

At the same time, work had begun 
on defining the hardware required to im¬ 
plement the computer. The first decision 
was the system bus. We all felt the S-100 
was not an acceptable bus for a multiple 
processor system. The final size and con¬ 
figuration of the boards used ended up to 
be a somewhat arbitrary decision based 
on the availability of a large number of 
wire-wrap boards I was able to locate 
from a bankrupt electronics company. 
Since we knew that a “de facto” standard 
for 68000s was still a long way away, 
there was little we could lose by not using 
a defined bus. 

We have called the bus which we are 
using for our computers the PUNIBUS. 
The signal definitions for the bus are 
shown in Figure One. The PUNIBUS is 
in fact two distinct busses. The first bus is 
used between 68000 processors and de¬ 
vices such as RAM and the graphics con¬ 
trol board which the 68000 processor 
board can access. The second bus is a 
high-speed, 16-bit bi-directional data 
path between processors and peripherals. 
The details of the peripheral bus (PBUS) 
appear in a later section. 


The timing specifications for the 
PUNIBUS are similar to those of the 
M68000 microprocessor. Most of the sig¬ 
nals on the bus are buffered versions of 
the signals coming from the- processor 
or memory management unit. There are a 
few signals which were left off the bus 
that are available for the control of 
68000 peripherals, and a few special sig¬ 
nals were added that provide byte-wide 
parity and multi-level, daisy-chained 
interrupts. 

We are currently using dual-width (2 
connectors) and a triple-width (3 con¬ 
nectors) cards in implementing the sys¬ 
tem. Dual-width cards are used wherever 
no PBUS communications are needed, or 
where the PBUS connector is not used 
as an inter-card jumper between PC 
boards. 

Computer Hardware 
Implementation 

The 68000 multiprocessor system is 
made up of two 68000 processor cards, 
a two-card raster graphic display control¬ 
ler, a system memory board capable of 
holding up to one megabyte of memory, 
and a collection of special-purpose in¬ 
telligent I/O boards for operation of serial 
interfaces, cartridge and floppy disks, 
and 9-track magnetic tape. The intercon¬ 
nection of the boards in the system is 
shown in Figure Two. 

M68000 Processor Card 

Each processor card has an 8MHz 
68000 processor, 68451 memory manage¬ 
ment unit, an interrupt generator which 
provides a programmable interval clock 
used by the operating system as the 
event sequencer, and 8 sockets for a rudi¬ 
mentary EPROM monitor and bootstrap 
program. In addition, one processor has 
a CMOS time-of-year clock used to main¬ 
tain the system’s time and date. 

Raster Graphics Controller 

The graphics display in the multi¬ 
processor is a device capable of display¬ 
ing 256 unique colors from combinations 
of 256 shades of red, green, and blue 
upon a 640 x 480 pixel color video dis¬ 
play. A block diagram of the graphics 
controller is shown in Figure Three. The 
image as displayed on the screen is stored 
in the display memory as a series of 8-bit 
pixels. Display memory is fetched eight 
pixels (64 bits) at a time to increase the 


22 

244 


Dr. Dobb’s Journal, Number 68, June 1982 




apparent access speed of the dynamic 
memories and to allow the 68000 
processor to interleave memory accesses. 
These eight-bit values are used as the ad- 
ress of a IK by 24-bit high-speed color 
mapping memory. The output of the 
color map is used as the 8-bit input to 
three Intech high-speed video DACS 
which output to a 19” RGB color moni¬ 
tor. Additional features of the graphics 
controller are the ability to pan and zoom 
within the display memory. 

Dynamic Memory Cards 

The original memory board we de¬ 
veloped was a dual-width card which 
used 16K dynamic RAMs and was capa¬ 
ble of a maximum of 128K bytes of RAM 
per card. Because of the rapid decrease in 
price of 64K RAM devices, and because 
of the need for a massive amount of 
memory for the graphics display memory, 
we have switched to a triple-width card 
capable of holding twice as many chips 
per board. Our graphics display memory 
boards and the system memory boards 
are built on the same printed circuit 
board which provides a bussed memory 
array with gridded power and common 
lines on the top of the board, and a 
wrapped-wire prototype area on the 
lower half of the board. Doing the mem¬ 
ory boards this way provided a well-bussed 
memory array which is essential for cor¬ 
rect operation of dynamic memories, 
while also allowing us the ability to 
prototype the refresh and control logic. 

Intelligent I/O Control and 
the PBUS 

One of the biggest problems with a 
multiple CPU computer is the allocation 
and sharing of resources between CPUs. 
Normally, peripherals are connected to 
one processor, with other processors ac¬ 
cessing the peripherals via shared memory 
or a special dual-porting arrangement on 
the peripheral. We have chosen to con¬ 
sider commonly used peripherals (such as 
mass storage devices and terminal lines) 
as being universally sharable resources 
and have connected those commonly 
used devices on a special high-speed 
parallel peripheral controller bus called 
the PBUS. CPUs within the system have 
th ability to request peripheral controllers 
to perform operations via PBUS “chan¬ 
nel” command packets. In addition, pro¬ 
cessors can issue requests to other proces¬ 
sors to allow inter-processor data trans¬ 
fers. 


Figure One 

PUNIBUS Signal Definition 



Pin 

Name 

Pin 

Name 


A 

Common 

1 

Common 


B 

DATAO 

2 

DATA1 

c 

C 

DATA2 

3 

DATA3 

o 

D 

DATA4 

4 

DATA5 

n 

E 

DATA6 

5 

DATA7 

n 

F 

DATA8 

6 

DATA9 

e 

H 

DATA 10 

7 

DATA 11 

c 

J 

DATA 12 

8 

DATA 13 

t 

K 

DATA 14 

9 

DATA 15 

o 

L 

PARITY 1 

10 

PARITY2 

r 

M 

+5 V 

11 

+ 5 V 


N 

Upper DATA Strobe 

12 

Lower DATA Strobe 

A 

P 

DATA Transfer ACK 

13 

Bus Error 


R 

VALID Peripheral ADR 

14 

Write 


S 

+12 V 

15 

+12 V 


T 

INT ACK Out 

16 

— 


U 

INT ACK In 

17 

Non Maskable INT 


V 

-12V 

18 

-12V 


W 

Interrupt 1 

19 

Interrupt2 


X 

Interrupts 

20 

Interrupt4 


Y 

Interrupts 

21 

Interrupt6 


Z 

Common 

22 

Common 



Pin 

Name 

Pin 

Name 


A 

Common 

1 

Common 


B 

ADR1 

2 

ADR2 

c 

C 

ADR3 

3 

ADR4 

0 

D 

ADR5 

4 

ADR6 

n 

E 

ADR7 

5 

ADR8 

n 

F 

ADR9 

6 

ADR10 

e 

H 

ADR11 

7 

ADR12 

c 

J 

ADR13 

8 

ADR14 

t 

K 

ADR15 

9 

ADR16 

o 

L 

ADR17 

10 

ADR 18 

r 

M 

+5 V 

11 

+5 V 


N 

ADR19 

12 

ADR20 

B 

P 

ADR21 

13 

ADR22 


R 

ADR23 

14 

ADR Strobe 


S 

+5 V Battery 

15 

+ 5V Battery 


T 

Bus Grant Out 

16 

Bus ACK 


U 

Bus Grant In 

17 

Bus Request 


V 

-5 V 

18 

-5 V 


w 

IOSEL 

19 

Memory Disable 


X 

- 

20 

Reset 


Y 

- 

21 

Clock 


z 

Common 

22 

Common 


(Figures 2 and 3 on next page) 


Dr. Dobb’s Journal, Number 68, June 1982 


23 



There are a few devices (such as the 
graphics controller) which require such a 
high amount of processor interaction that 
they are connected directly to a M68000 
processor via the PUNIBUS. Currently, 
the graphics display is the only device 
which requires such tight coupling to a 
processor. 

An intelligent I/O card normally 
consists of a PBUS interface, the interface 
hardware required of the peripheral (s) be¬ 
ing controlled by that board, and either a 
Z-80 or a bipolar bit-slice microproces¬ 
sor. Currently, all I/O cards are using 
Z-80s as the control computer but we 
suspect that we will need the extra speed 
of the bit-slice devices for some of the 
fancier interfaces we would like to do 
(such as the network link). 

System Software 

The major component of the soft¬ 
ware for the multiprocessor is the BERT 
multi-tasking operating system. BERT 
is based on ideas from UNIX, VAX/VMS 
and RSX-11M. The majority of the sys¬ 
tem is being written in C. The operating 
system is currently being bootstrapped 
via a C cross-compiler developed on the 
RSX system at work. Once the opsys 
kernel, the file system, and the command 
processor are running on the multiproces¬ 
sor, the C cross-compiler, assembler, and 
linker (which were all written in C) will 
be cross-compiled, linked and moved to 
the 68000 where the balance of the devel¬ 
opment will be done. 

Software for the graphics hardware 
will be developed as a parallel effort with 
the operating system, by adapting CLICS 
(C Language Implementation of the Core 
Standard, which was developed by the 
Department of Defense) to the graphics 
hardware on the multiprocessor. 



The FORTRAN Cross-Assembler 

When this project was first started, I 
was totally ignorant of UNIX or the C 
language. Since that time, I have become 
hooked on the use of C for systems pro¬ 
gramming and operating systems develop¬ 
ment. Prior to this change, however, I 
wrote a cross-assembler for the 68000 
which was writen in FORTRAN to run 
on either RT-11 or RSX -11. It is of little 
use to me now, and I thought that some¬ 
one else might have use for such a pro¬ 
gram. The DDJ editor tells me he will 
publish the listing (it is quite long) only 


t.+ 

i i 

I Display Meaory \ - 

I tin ins and ctl +-+ 

I I I 

+.F-+ 1 

I 1 

+.+-.+ 1 

l I I 

I IK by 24 bit map I I 

I 1 I 

+--+ 1 

III I 


+-+—+-+ I 

IdacIdacIdacI I 

+—+—+—+ + 

I I +- 

1 + - 

+- 


+—.+ 

I I 

+ Graphics Display I 
I (IMb/card) I 
I (4 cards box) I 

+- + -+ 

I 

+-+-+ 

I I 

I FUNIBUS intf + - M68000 

I I 

+.+ 

--+ 


I I 
+Sync RGB I 
-+Red Monitor I 
•+Grn I 
-IBlu I 
+-+ 


24 

246 


Dr. Dobb’s Journal, Number 68, June 1982 


















































if a considerable number of readers 
clamor for it. The program currently re¬ 
quires a few assembly-language subrou¬ 
tines to perform 32-bit arithmetic and 
binary operations. They would have to be 
rewritten to be of use on a microsystem. I 
also do not know if the program will 
compile using Microsoft FORTRAN. 
Since I do not have the compiler, I have 
no way of knowing if the program will 
compile or not. 




Dr. Dobb’s Journal, Number 68, June 1982 


Of Interest 

(Continued from page 13) 


Operating Systems Are Not 
Phone Companies 

CP/M-86, for 8086 systems, from 
Digital Research is completely compati¬ 
ble with all Z-80 and 8080 CP/M pro¬ 
grams, in addition to its own 8086 8-bit 
cross-assembler and 16-bit assembler, 
DDT-86 debugging tool and assembler/ 
disassembler, and availability of compilers 
that need more than 64K to run efficient¬ 
ly (FORTRAN 77, etc.). The 8086 Dual 
Processor Option (DPO) is a single board 
from Veritas that adds CP/M-86 to your 
IBM Displaywriter or TRS-80 Mod II. 
It costs $1500, including CP/M-86. 
(Reader Service No. 339) 

MicroShell from New Generation 
| Systems is a Unix-like operating system 
| that relocates itself under CP/M and re- 
] mains compatible with CP/M. MicroShell 
automatically searches multiple user- 
specified disks for programs and files, 
redirects or appends output to a file with 
optional screen echo, sends console out¬ 
put of one program to console input of 
the next (“pipes”), supports multiple 
commands on one line, directly reads and 
executes commands from a file without 
the necessity of Submit processing, re- 
1 tains all CP/M CCP functions, has user- 
definable prompts, and can be cus¬ 
tomized to the user’s environment. Micro- 
Shell is available on disk for 8080/8085/ 
j Z-80 CP/M systems at a cost of $150. 
(Reader Service No. 349) 

Computer Coverage Is More Than 
Dust Covers 

Protect your equipment with person¬ 
al computer insurance coverage from 
(who else?) Personal Computer Insurance. 
No-deductible insurance that covers 
everything except data costs $50 a year, 
with extended business coverage for $60. 
(Reader Service No. 359) 

All-risk computer insurance coverage 
for businesses that includes data is 
offered by Kemper. They call it BEEP 
j (Business Electronic Equipment Policy) 
and offer protection with various deduc¬ 
tibles from $100 up. Each policy is dif¬ 
ferent, so you’ll have to call for prices. 
You might also ask them about home 
computer coverage, particularly if you’re 
self-employed. (Reader Service No. 369) 

•»J 


25 

247 


An Improved LET Processor 
for LLL Basic 


L awrence Livermore Lab Basic has a 
restricted assignment (LET) state¬ 
ment. LLL Basic expressions can be 
no more complex than 

<LLL Basic Expression > -> 

operand operator operand 

where operand may be a constant or a 
variable, and operator is one of the arith¬ 
metic operators *, /, +, or Borrowing 
from compiler theory, we overcame these 
limitations with a patch routine which 
incorporates certain principles of a form 
of shift-reduce parser known as operator- 
precedence. 

Because LLL Basic is an interpreter 
rather than a compiler, the patch is writ¬ 
ten a bit differently than textbook ex¬ 
amples but the idea is similar. A parser 
recognizes sentences in a language and 
this is true for natural languages as for 


by Norman E. Thagard 
and George Glenn 


Norman E. Thagard, M.D., 528 E. Castle- 
harbour Drive, Friendswood, TX 77546. 


Norman Thagard is a mission spe¬ 
cialist astronaut with NASA. He writes, 
“Ownership of personal computers a- 
mong employees at Johnson Space 
Center is common. Given the prepon¬ 
derance of scientists and engineers 
here, that is expected., . . There are 
a number of desktop machines at 
the center devoted to system simula¬ 
tions ...” 

Of himself, Thagard says, “Cur¬ 
rently, I am the astronaut office point- 
of-contact (along with female astro¬ 
naut Shannon Lucid) for STS-7, 
which is scheduled for launch next 
April. Unfortunately, that does not 
mean that I am flying on the mission 
but I am learning a lot about proximi¬ 
ty operations. This is because this is 
the first shuttle misssion where we will 
deploy a payload, fly around it, then 
pick it back up.” 

George Glenn is an engineer under 
contract to NASA who is currently 
working on the software for the Re¬ 
mote Manipulator System which flies 
on the space shuttle. 


programming languages. In the Basic lan¬ 
guage sentences are statements of which 
LET statements are particular examples. 
Our patch, then is merely a recognizer 
for LLL Basic LET statement right sides. 
LET statement right sides are merely 
arithmetic expression which satisfy the 
following rules (called productions): 

Expression -*■ Expression + Term 
or 

Expression - Term 
or 

Term 

where 

Term -*■ Term * Factor 
or 

Term / Factor 
or 

Factor 

and 

Factor -* Variable 

or 

Constant 

or 

Expression 

or 

GET(LLL Basic 
Expression) 

The means the right side is an ex¬ 
ample of the left side. Variable and 
Constant are the allowable LLL Basic 
variables and constants. 

It follows from the above rules that 
complex right sides are permitted and are 
evaluated as dictated by parentheses if 
present, according to the operator pre¬ 
cedence *, /, +, - if no parentheses are 
present, and left-associatively if operators 
are of equal precedence. This means that 
if A= 1, B=2, and C=3, then (A+B)*C=9, 
and A+B*C=7. Arithmetic operators are 
associative, i.e., (A+B)+C = A+(B+C). 
However, the patch would evaluate 
A+B+C as though written (A + B)+C 
(left-associatively). 

A shift-reduce parser takes the input 
one item (usually called a token) at a 
time and either shifts (pushes) that item 
to a stack, reduces (pops) an item(s) from 
the stack, or flags a syntactical error. It 
terminates its operation when end-of- 
line is detected. The decision about which 
action should occur is based on the re¬ 
sults of a comparison between the relative 
precedence of the item at the top of the 


stack and the item just read. In theory, 
only one stack need be maintained. How¬ 
ever, since LLL Basic is an interactive in¬ 
terpreter, it was easier to determine 
operand values and store them on a 
separate (operand) stack to implement 
this patch. The shift-reduce decisions are 
based on the operators and therefore only 
the operator stack is involved in such de¬ 
cisions so the operand stack does not 
complicate the operation of the patch. 

To briefly explain how an operator- 
precedence parser works, we can take the 
expression A+B*C used earlier. Operand 
A is read and its value determined and 
stored. Often, a token is chosen to repre¬ 
sent A. This token, really just a place¬ 
holder, is then pushed onto the stack on 
top of another token used to mark the 
bottom of the stack. As mentioned 
before, this is not done in this patch. 
Rather, the value of A is pushed onto a 
separate operand stack. Next, the opera¬ 
tor “ + ” is read and, as it has higher pre¬ 
cedence than the bottom of stack marker, 
it is pushed onto the operand stack im¬ 
mediately. Next, B is read and its value 
is placed onto the operand stack above 
the value for A already there. The 
operator is read and its precedence com¬ 
pared to that of the “+” at the top of the 
operator stack. Since has higher 

precedence than “+”, we know that the 
operation A + B should not be performed 
yet so is pushed on top of the “+”. 
Now C is read and its value pushed onto 
the operand stack on top of A and B. Our 
two stacks now appear as 

operand stack operator stack 

C * 

B + 

A $ 

(bottom of stack) 

The end-of-line marker is read next. This 
forces the parser to pop one operator 
from the operator stack and two oper¬ 
ands from the operand stack to perform 
the operation B*C, placing the result 
back on the operand stack. The stacks 
now appear as 

operand stack operator stack 

(result of B*C) + 

A $ 

The end-of-line marker forces us to con¬ 
tinue to pop the stacks until empty, so 
now the “+” is popped along with the 
result of B*C, and A. The indicated 
operation is carried out to yield A+(B*C) 
which is the expected result. 


26 


Dr. Dobb’s Journal, Number 68, June 1982 




The left parenthesis, if it appears in 
the input expression, is automatically 
pushed onto the operator stack but is as¬ 
signed the lowest precedence so that the 
next operator will always be pushed on 
top of a left parenthesis. On the other 
hand, when popping operators off the 
stack, the left parenthesis signals that the 
necessary reductions have been carried 
out and reading the input can resume. In 
compiler lingo, the left parenthesis is said 
to define the left side of a “handle.” In 
this case, the handle is of the form (E) 
where E denotes an arbitrary (arithmetic) 
expression. The fundamental operation of 
the recognizer is identifying such “han¬ 
dles” in the input and replacing them by 
their value. Whatever the form of E in 
(E), upon encountering a right parenthe¬ 
sis, the stack will be popped, the ap¬ 
propriate operations performed, and the 
process repeated until the matching left 
parenthesis is popped. If no left parenthe¬ 
sis is found an error message is generated. 
The recognizer permits the use of a unary 
minus. As with the left parenthesis, a 
unary minus, when read, is automatically 
placed on the operator stack. In contrast 
to the left parenthesis, however, the 
unary minus is assigned the highest pre¬ 
cedence of all. As a result, an expression 
such as A+-B+C is evaluated as though 
written (A+(-B))+C. The expression 
A+-(B+C) is evaluated as A+(-(B+C)) 
because of the rule that the left paren¬ 
thesis is automatically pushed onto the 
operator stack. 

To use the new expression processor, 
called EXEVAL, requires a patch in the 
LET processor of LLL Basic. The patch 
involves the six consecutive bytes at 
016117-016124 octal. In the first three 
bytes we “no op” the call to ICP8. In 
the second three bytes we call EXEVAL 
rather than EVAL. We have located EXE¬ 
VAL at 020004Q but it is likely that 
there is a great deal of variation among 
LLL Basic memory maps from user to 
user. So, if you need to relocate the patch 
the only critical feature is that the least 
significant address byte of table VALTAB 
must be 000Q. Shown below is the re¬ 
quired change to the LET processor. 

Change: 

0161 17 315 373 025 CALL ICP8 

016122 315 335 031 CALL EVAL 


LET Processor 

Listing 1 

FUNCTION Expression— Evaluator (EXPRESSION—VALUE) 

PERFORM Initialization 

DO UNTIL End of source line is reached or a syntax error is detected 
PERFORM Get —Next—Operand—Value 
IF No syntax error was detected THEN 

Store the operand value obtained on the operand stack and 
increment the operand stack pointer 

DO UNTIL End of source line is reached, a syntax error is de¬ 
tected, or an arithmetic operator is encountered 

PERFORM Get —Next—Operator 
IF A syntax error has been detected THEN 
Setup syntax error annunciation 

ERROR EXIT 

ELSE PERFORM Cleanup —Processing 

EXIT 

END 


PROCEDURE Initialization 

Set the left parenthesis counter to zero 

Set the operand stack pointer to the first position of the operand stack 
Set the operator stack pointer to the first position of the operator stack 
Store the empty stack identifier on the operator stack 

END 


PROCEDURE Get—Next—Operand—Value 

CALL ICP8 to get the next character of the source line; syntax error is 
indicated if end of line is reached 

IF The end of line was not reached THEN 

IF The character is a left parenthesis THEN 
PERFORM Process —Left —Parenthesis 
ELSE IF The character is a minus sign THEN 
PERFORM Process —Unary_Minus 

ELSE CALL VALUE to get the operand value; syntax error is 
indicated if the line item is not an operand 


END 


To: 

016117 000 000 000 NOP NOP NOP 
016122 315 004 040 CALL EXEVAL 
(Continued on page 28) 


PROCEDURE Get —Next—Operator 

IF More characters remain in the source line THEN 

(Continued on next page) 


Dr. Dobb’s Journal, Number 68, June 1982 


27 

249 




LET Processor 


Note that this patch affects only the 
right side of LET statements. Other calls 
to the EVAL subroutine are left in place. 

This means, for example, that an expres¬ 
sion in a PUT function must have the old, 
simple syntax. That is, we must have 

LET PUT( LLL Basic Expression) 

= Expression 

before the new parser will be called. 

The patch itself is shown in Listing 2 
(page 30). For more details of the opera¬ 
tion of this patch refer to the pseudocode 
outline in Listing 1 (page 27). We hope 
this patch makes LLL Basic more useful 
for you. 

... end 


SVMSRT to search the operator symbol table and re¬ 
turn the operator index. The index is set to negative 
one if the character is not found in the symbol table. 

IF The operator index returned does not indicate addition, 
subtraction, multiplication, or division THEN 

Syntax error is indicated 
ELSE PERFORM Process_Operator_Index 


(Listing 1 continued, text begins on page 26) 

IF The next character is a right parenthesis THEN 
PERFORM Process — Right— Parenthesis 

ELSE CALL 


(Listing begins on page 27) 


PROCEDURE Process —Left —Parenthesis 
The operator stack pointer is incremented. 

The left parenthesis identifier is stored on the operator stack 
The left parenthesis counter is incremented 

END 


PROCEDURE Process —Unary_Minus 

IF The most recent operator stored on the operator stack is the unary 
minus THEN 

Syntax error is indicated 
ELSE The operator stack is incremented 

The unary minus identifier is stored on the operator stack 

END 

PROCEDURE Process-Right-Parenthesis 
The left parenthesis counter is decremented. 

IF The left parenthesis counter is less than zero THEN 
Syntax error is indicated 

E LSE DO WHILE The operator identifier on top of the operator stack 
is not the left parenthesis identifier 

CALL Unstack-Perform _Op 
The operator stack pointer is decremented 
The source line character pointer is incremented 
The source line character count is decremented 

END 


(Continued on top of page 29) 


28 

250 


Dr. Dobb’s Journal, Number 68, June 1982 


PROCEDURE Process_Operator_lndex 

Determine the new operator identifier from the operator index 

DO WHILE The precedence value of the operator identifier on top of 

the operator stack is greater than or equal to the precedence 
value of the new operator identifier 

CALL Unstack_Perform_Op 
The operator stack pointer is incremented 
The new operator identifier is stored on the operator stack 

END 


SUBROUTINE Unstack_Perform_Op 

Get the operator identifier on top of the operator stack 
The operator stack pointer is decremented 
IF The operator identifier is the unary minus identifier THEN 
The sign of the operand on top of the operand stack is inverted 

ELSE The second floating point register is set equal to the operand on 
top of the operand stack 

The operand stack pointer is decremented 

The first floating point register is set equal to the operand on top of 
the operand stack 

The required operation is determined from the operator identifier 

CALL BINOP to perform the indicated operation on the two 
floating point registers 

Store the result of the operation back on the operand stack 

END 


PROCEDURE Cleanup—Processing 

IF The left parenthesis counter is not equal to zero THEN 
Syntax error is indicated 

E LSE DO UNTIL The operator identifier on top of the operator stack 
is the empty stack identifier 

CALL Unstack_Perform_Op 

The EXPRESSION—VALUE is set equal to the operand value on 
top of the operand stack 

END 


Dr. Dobb’s Journal, Number 68, June 1982 


End Listing 1. 

(Listing 2 begins on page 30) 


29 

251 



LET Processor 

(Listing continued, text begins on page 26) 


Listing 2. 




TABMSB 

EQU 

040Q 

MSB of VALTAB start address 



LPCNTR 

EQU 

20404Q 

Left parenthesis counter register 



OPRSP 

EQU 

2041 IQ 

Operator stack pointer 



OPRPTR 

EQU 

20405Q 

Operator stack pointer register 



OPDSP 

EQU 

2043 IQ 

Operand stack pointer 



OPDPTR 

EQU 

20407Q 

Operand stack pointer register 



LPREC 

EQU 

060Q 

Left parenthesis precedence value 



; Operator precedence processor for LLL Basic LET statement right sides. 




ORG 

20000Q 


20000 

020 

VALTAB: 

DB 

020Q 


20001 

021 


DB 

02 IQ 


20002 

042 


DB 

042Q 


20003 

043 


DB 

043Q 


20004 

257 

EXEVAL: 

XRA 

A 

Initialize the 

20005 

062 004 041 


STA 

LPCNTR 

left parenthesis counter to zero. 

20010 

345 


PUSH 

H 

Save the source line character pointer 

20011 

075 


DCR 

A 

Let -1 be the operator stack bottom marker 

20012 

041 011 041 


LXI 

H,OPRSP 

Get the operator stack pointer and place 

20015 

167 


MOV 

M,A 

the bottom marker on the stack 

20016 

042 005 041 


SHLD 

OPRPTR 

Store the pointer in the operator SP register 

20021 

056 031 


MVI 

L.OPDSP AND 377Q 

Initialize the operand stack pointer 

20023 

042 007 041 


SHLD 

OPDPTR 

Store the pointer in the operand SP register 



; Fetches next source line character. Tests to see if it is left parenthesis. 

20026 

341 

LI: 

POP 

H 

Restore source line character pointer 

20027 

315 373 025 


CALL 

ICP8 

Bump pointer. If EOL, annunciate illegal expr. 

20032 

076 250 


MVI 

A,250Q 

Is new source line character 

20034 

276 


CMP 

M 

a left parenthesis? 

20035 

302 055 040 


JNZ 

NOPAR 

If not, go see what it is 

20040 

345 


PUSH 

H 

It is a left parenthesis. Save character pointer 

20041 

076 060 


MVI 

A,LPREC 

Assign it ID = 060, hence precedence value = 3 

20043 041 004 041 


LXI 

H,LPCNTR 

Bump the left 

20046 064 


INR 

M 

parenthesis counter. 

20047 

052 005 041 


LHLD 

OPRPTR 

Fetch the operator stack pointer 

20052 

303 166 040 


JMP 

PUSHOP 

Go push the left paren. to the OPR stack 



; Tests to see if character is a unary minus. If operand, it pushes value. 

20055 

076 255 

NOPAR: 

MVI 

A,255Q 

Is new source line character 

20057 

276 


CMP 

M 

a unary minus? 

20060 

312 276 040 


JZ 

UMIN 

If it is, go process it. 

20063 

315 324 027 


CALL 

VALUE 

If operand, fetch value. If not, annunciate error. 

20066 

345 


PUSH 

H 

Save source line character pointer 

20067 

052 007 041 


LHLD 

OPDPTR 

Fetch operand stack pointer and 

20072 

315 271 027 


CALL 

COPDH 

go push operand value to stack. 

20075 

076 004 


MVI 

A,4 

Bump the 

20077 

205 


ADD 

L 

operand stack 

20100 

157 


MOV 

L,A 

pointer and 

20101 

042 007 041 


SHLD 

OPDPTR 

store pointer in operand SP register. 

20104 

341 


POP 

H 

Restore source line character pointer 


30 

252 


Dr. Dobb’s Journal, Number 68, June 1982 





; Tests to see if character is a right parenthesis or an operator. 


20105 

171 

L2: 

MOV 

A,C 

Get the source 'line remaining' counter and 

20106 

267 


ORA 

A 

test for EOL. If at EOL, 

20107 

312 353 040 


JZ 

FINI 

go finish up the subroutine. 

20112 

076 251 


MVI 

A,251Q 

Is present source line character 

20114 

276 


CMP 

M 

a right parenthesis? 

20115 

312 312 040 


JZ 

RPAR 

If so, go compute value of parenthetical expr. 

20120 

076 002 


MVI 

A,2 

Not right paren. Set A = 2 and 

20122 

014 


INR 

C 

bump C prior to calling SYMSRT so 

20123 

315 367 022 


CALL 

SVMSRT 

SYMSRT will search KDAT3 for operator. 

20126 

326 011 


SUI 

9 

Did SYMSRT find an operator? 

20130 

372 070 032 


JM 

ER8 

If not, annunciate illegal expression 



; Compares operator precedence against top stack operator. 

20133 

345 

OPR: 

PUSH 

H 

Save the source line character pointer 

20134 

046 040 


MVI 

H,TABMSB 

The operator value from KDAT3 will index 

20136 

157 


MOV 

L,A 

VALTAB to obtain operator precedence I.D. 

20137 

176 


MOV 

A,M 

Fetch operator precedence I.D. 

20140 

107 


MOV 

B,A 

Save it in B 

20141 

052 005 041 


LHLD 

OPRPTR 

Fetch operator stack pointer 

20144 

176 

OPR1: 

MOV 

A,M 

Fetch precedence I.D. of top stack operator 

20145 

346 360 


ANI 

360Q 

Compute precedence value of top stack opr. 

30147 

137 


MOV 

E,A 

Save it in E 

20150 

170 


MOV 

A,B 

Restore new operators precedence I.D. 

20151 

346 360 


ANI 

360Q 

and compute its precedence value 

20153 

273 


CMP 

E 

Compare its precedence to stack operators. 

20154 

170 


MOV 

A,B 

Restore precedence I.D. of new operator 

20155 

332 166 040 


JC 

PUSHOP 

If new prec. > stack prec., go push it to stack 

20160 

315 176 040 


CALL 

USTAK 

New prec.< stack prec. so go POP stack operator 

20163 

303 144 040 


JMP 

OPR1 

Go back and test new opr. against next stack opr. 



; Pushes new operator to stack 


20166 

043 

PUSHOP: 

INX 

H 

Bump operator stack pointer 

20167 

167 


MOV 

M,A 

Push new operator precedence I.D. 

20170 

042 005 041 


SHLD 

OPRPTR 

Save operator stack pointer 

20173 

303 026 040 


JMP 

LI 

Go deal with next source line character 



; Pops operator at top of operator stack 


20176 

107 

USTAK: 

MOV 

B,A 

Save accumulator 

20177 

257 


XRA 

A 

Is top stack operator 

20200 

276 


CMP 

M 

a unary minus? 

20201 

302 220 040 


JNZ 

TUOPDS 

If not, go do binary operation 



; Handles unary minus 


20204 

052 007 041 

WUNOPD 

LHLD 

OPDPTR 

; Fetch the operand stack pointer 

20207 

053 


DCX 

H 

; Point to characteristic of top stack operand 

20210 

176 


MOV 

A,M 

; Fetch characteristic 

20211 

027 


RAL 


; Fetch its sign bit 

20212 

077 


CMC 


; Complement (negate) it 

20213 

037 


RAR 


; Restore sign bit (negate operand) 

20214 

167 


MOV 

M,A 

; Restore characteristic 

20215 

303 265 040 


JMP 

OPOVER 

; Go wrap up the subroutine 


(Continued on page 34) 


Dr. Dobb’s Journal, Number 68, June 1982 


31 

253 







LET Processor 




(Listing 2 continued, text begins on page 26) 



; Perform binary operation on two operands at top of stack. 

20220 353 

TUOPDS: 

XCHG 


Save operator stack pointer in DE 

20221 052 007 041 


LHLD 

OPDPTR 

Fetch operand stack pointer 

20224 175 


MOV 

A,L 

Two operands will be popped 

20225 326 004 


SUI 

4 

during the binary operation 

20227 157 


MOV 

L,A 

to follow so adjust the 

20230 042 007 041 


SHLD 

OPDPTR 

operand SP accordingly. 

20233 353 


XCHG 


Restore operator SP to H L 

20234 176 


MOV 

A,M 

Top stack operator to A 

20235 041 200 060 


LXI 

H,FREG2 

Copy the top stack operand 

20240 315 271 027 


CALL 

COPDH 

into floating point register 2. 

20243 056 174 


MVI 

L.FREG1 AND 377Q 

Copy the second 

20245 033 


DCX 

D 

stack 

20246 033 


DCX 

D 

operand 

20247 033 


DCX 

D 

into 

20250 033 


DCX 

D 

floating 

20251 315 271 027 


CALL 

COPDH 

point register 1. 

20254 353 


XCHG 


Save adjusted operand SP in HL 

20255 346 017 


ANI 

17Q 

Compute operator value prior to BINOP 

20257 315 121 032 


CALL 

BINOP 

Go compute FREG1 operator FREG2 

20262 315 271 027 


CALL 

COPDH 

Push the result to the operand stack 


; Cleans up after unary or binary operation. Adjusts operator stack pointer. 

20265 170 

OPOVER: 

MOV 

A.B 

Operation is complete so restore A 

20266 052 005 041 


LHLD 

OPRPTR ; 

The operator stack was 

20271 053 


DCX 

H ; 

popped so adjust 

20272 042 005 041 


SHLD 

OPRPTR ; 

the operator SP 

20275 311 


RET 


and return. 


; Makes sure that two consecutive unary minuses do not occur. Pushes minus to stack. 

20276 345 

UMIN: 

PUSH 

H 

Save source line character pointer 

20277 052 005 041 


LHLD 

OPRPTR 

Fetch the operator stack pointer 

20302 257 


XRA 

A 

Test the top stack operator 

20303 276 


CMP 

M 

Is it also a unary minus? 

20304 312 070 032 


JZ 

ER8 

If it is, go annunciate illegal expression 

20307 303 166 040 


JMP 

PUSHOP 

Go push the unary minus to the operator stack 


; Computes value of parenthetical expression. 


20312 345 

RPAR: 

PUSH 

H 

Save the source line character pointer 

20313 041 004 041 


LXI 

H,LPCNTR 

Fetch the left parenthesis counter 

20316 065 


DCR 

M 

A left paren. is being popped 

20317 372 070 032 


JM 

ER8 

If no matching left paren., go annunciate error 

20322 052 005 041 


LHLD 

OPRPTR 

Fetch the operator SP 

20325 076 060 


MVI 

A,LPREC 

Is the top stack operator 

20327 276 

RPAR1: 

CMP 

M 

a left parenthesis? 

20330 312 341 040 


JZ 

LPAR 

If so, go process it 

20333 315 176 040 


CALL 

USTAK 

Left paren. not yet exposed. Go perform operation 

20336 303 327 040 


JMP 

RPAR1 

Go back for next stack operator 

34 




Dr. Dobb’s Journal, Number 68, June 1982 

254 









; Cleans up after evaluation of parenthetical expression. 


20341 053 


LPAR: 

DCX 

H 

; Left paren. popped so adjust operator SP 

20342 042 

005 041 


SHLD 

OPRPTR 

; Restore adjusted SP to operator SP register 

20345 341 



POP 

H 

; Restore source line character pointer to HL 

20346 043 



INX 

H 

; Bump it to point past the right paren. 

20347 015 



DCR 

C 

; Decrement the 'source line remaining' counter 

20350 303 

105 040 


JMP 

L2 

; Go deal with rest of source line 



; Completes processing of expression after EOL (source line) encountered. 

20353 041 

004 041 

FINI: 

LXI 

H.LPCNTR 

; Fetch left parenthesis counter 

20356 276 



CMP 

M 

; Is it zero? 

20357 302 

070 032 


JNZ 

ER8 

; If not, too many left parentheses. Illegal 

20362 075 



DCR 

A 

; Routine will terminate when OPR stack empty 

20363 052 

005 041 


LHLD 

OPRPTR 

; so fetch operator SP and 

20366 276 


FINI1: 

CMP 

M 

; test for bottom of stack marker. 

20367 312 

000 041 


JZ 

FINIT 

; If found, go terminate routine 

20372 315 

176 040 


CALL 

USTAK 

; Not empty, so go perform next operation 

20375 303 

366 040 


JMP 

FINI1 

; Go back and look again for bottom marker 


; Finishes up routine. 

20400 041 031 041 FINIT: LXI D,OPDSP ; DE to point to expression value 

20403 311 RET ; upon exiting this routine. 


End Listing 2. 



Dr. Dobb’s Journal, Number 68, June 1982 35 

255 



A Print Utility for CP/M 


I believe the only program that out- 
proliferates YALE (Yet Another Line 
Editor) is a print utility. So why this 
one? Well, I like trees. In actual fact, I'm 
cheap. Paper, particularly printer paper, 
costs money. I find that I’m constantly 
listing and relisting the source of modules 
under development; having a printer that 
prints 132 columns, I got awfully an¬ 
noyed at seeing half the page left blank. 
Hence a simple, double-column print 
utility. But like most “hackers” I 
couldn’t leave well enough alone. I got 
tired of re-running the utility when I 
finally had a program cleaned up and 
wanted a final print. Setting up submit 
files was too much “busy work,” etc., so 
I added a batching capability. Then, the 
CP/M ambiguous file name is useful, so 
why not include that too? 

In short, a nice, simple little program 
turned into a 4K monster, but it has 
proven to be very handy for me. Hope¬ 
fully, it will help you. Memory require¬ 
ments are the 4K mentioned plus a page 
buffer for your size printer. This could be 
another whopping 7800 bytes, so if 
you’re memory short, this isn’t the pro¬ 
gram for you! If you’re equipped with 
one of those nice printers (and exploiting 
software) that uses forms control, you 
need read further only from academic 
interest. This simple-minded beast is de¬ 
signed to work with dumb equipment. It 
ignores forms controls, handles its own 
pagination, and generally does things in 
a brute-force manner. My printer is a 
KSR-43 Teletype, which I might add is 
one fine machine. I’ve had it for several 
years and have never had a minute’s prob¬ 
lem with it. And that includes more cases 
of printer paper than I want my wife to 
find out about! This printer is a 132- 
character line, 51-line page machine, and 
that’s what the utility is currently assem¬ 
bled to work with. If your page format is 
different, keep the faith. The program is 
“patchable,” or may be re-assembled 
changing two constants (equates) and it 
will handle any reasonable format. I’ll 
talk about installation a little later, so 
keep reading. 


by Dan Daetwyler 


Dan Daetwyler, Route 5, Box 518A, 
Springdale, AZ 72764. 


Listing Format 

Hopefully, the listings accompanying 
this article are adequately commented. 
Rather than discuss the details of the 
code, this section will discuss some things 
that aren’t included in the listings. I 
use one of the last versions of the defunct 
TDL (nee ZITAN) assembler and linker, 
which I love. Fortunately, those tools are 
still available, since I believe they are one 
of the finest offerings available for the 
Z-80. Using this assembler/linker lets me 
break up my source into more manageable, 
kernels and helps limit the re-assembly 
listing volume, so “DPRINT” is broken 
into 6 source files: DPRINT, DPR01, 
DPR02, DPR03, DPR04, DPRWS. I 
won’t go into the functioning of .ENTRY 
and .EXTERN, which bring all of these 
pieces back together with addressability, 
but I will describe each of the macros and 
common I/O modules used by the print 
utility. Like many hackers I’ve quit re¬ 
inventing the wheel every time I write a 
program. I have a set of common libraries 
that contain most of my primitives, and a 
set of macro libraries which simplify the 
calls to those modules. Since many of 
you will not have access to the TDL 
assembler/linker, and because of volume, 

I have chosen not to include the source 
listings of these materials. Rather, I will 
describe, in a very few words, each of the 
functions, and you may have the pleasure 
of mapping this thing into your I/O en¬ 
vironment. First, I’ll describe the limited 
set of macros used. 

FCB Macro 

This is a structure that defines a File 
Control Block (FCB) in CP/M’s standard 
format, but with a four-byte header. The 
header contains a pointer to a file buffer 
for this file in the first two bytes, a buffer 
use count (current character offset) in the 
next byte, and the mode (input=l, out- 
put=2) in the fourth byte. Initially the 
use count is set to -1. All FCB’s used by 
DPRINT are of this format. 

SEARCH Macro 

Sets up a call to the directory search 
module (common library), passing the 
type of search (first,next) and the address 
of the FCB. Returns with carry set if a 
“no find” condition occurs. Returns the 
standard CP/M offset (0-3) in the A regis¬ 
ter if a match is made. 

OPEN Macro 

Sets up a call to the common library 
open routine. Passes the FCB pointer and 


mode. An error exit is specified and taken 
if the file cannot be opened. The expan¬ 
sion used in this utility assumes the FCB 
is external to the macro and has been 
filled with name and type. Another ex¬ 
pansion will generate an “in-line” FCB 
with name and type specified, but that is 
not used in this utility. 

FGET Macro 

Entry with a register pair containing 
the FCB address simply sets up the call 
to the module that will provide the next 
sequential character from an input file. 
Return is made with the character in the 
A register. An end-of-file exit is specified 
in the macro and taken if either a 1AH 
character is encountered or the CP/M 
read returns an end-of-file condition. 

Common Library Modules Used 

Although this list appears extensive, 
in actual practice the code for most of 
these modules is extremely primitive, 
simply providing the register save and re¬ 
store necessary before invoking the usual 
CP/M function. The save and restore 
functions embedded in these calls restores 
all registers to their entry state except the 
A register. 

$LO Module 

Outputs the character contained in 
the A register to the system list device. 

SCO Module 

Same thing to the system console. 

SLCRLF Module 

Outputs a carriage retum/line feed to 
the system list device. 

SCRLF Module 

Same thing to the system console. 

SLBLK.SLBLKS Modules 

SLBLK outputs a single blank to the 
system list device, while SLBLKS outputs 
as many blanks as the count in the A 
register specifies. 

$BLK,$BLKS Modules 

Same thing to the system console. 

$MCI Module 

Performs the CP/M function #10 
(get input string). Expects the HL register 
pair to contain the address of a buffer, 
the A register to contain the maximum 


36 

256 


Dr. Dobb’s Journal, Number 68, June 1982 



length of permitted input plus two, and 
returns with the buffer filled and set up 
as described in your handy-dandy CP/M 
manual. 

$MCPM Module 

Performs the CP/M stringout function 
(function #9). Expects entry with the 
HL register pair pointing to a console 
message that is terminated with a $ and 
outputs this message to the system 
console. 

$CIDR Module 

Performs CP/M function #6 for 
input. Returns the result in the A register. 
This function reads the console input 
port without waiting and does not echo 
the key stroke. 

SCI Module 

Performs CP/M function #1, which 
is a simple read of the console input port. 
This function waits and echos. Return is 
made with the character in the A register. 

SSERCH Module 

Performs CP/M functions 17 and 18 
(first,next) which search the file direc¬ 
tory for the name specified in the FCB 
pointed to by the call. Returns with carry 
set if a “no find” condition occurs. 
Otherwise returns the A register content 
provided by CP/M. 

SFGET Module 

Simply provides the next sequential 
character from the file defined by the 
FCB on input. Return is made in the A 
register. Carry is set if either a 1 AH char¬ 
acter or a CP/M end-of-file condition is 
detected. 

SOPEN Module 

Open the file pointed to by the FCB 
pointer provided in the call. Sets the FCB 
prefix with the mode provided in the call, 
initializes the FCB (except for the drive, 
name and type fields, and sets the buffer- 
use byte to -1. 


As you can see, these are all primi¬ 
tives that most of you who use CP/M 
have already developed to fit your own 
conventions. You can either substitute 
your macros and calls in this source 
material, or write simple primitives that 
are called directly by modifications you 
make in this code. 


Installation 

The assembled and linked program 
is a standard .COM file that may be easi¬ 
ly patched for variations in printers. 
Locations 11 OH through 116H contain 
the following: 


110H-111H 

112H-113H 
114H 

115H-116H 


line length, least significant 
byte first 

half of the line length, LSB 
size of paper (number of 
lines) minus 7 
(line length) * (size of pa¬ 
per - 7), LSB 


Location 117H, currently containing a 
RET (C9H), starts a 100H area that may 
be used for any special initialization code 
your configuration may require. This 
code will be entered once per invocation 
of DPRINT. 


Operation 

To run the utility you may initiate 
it by either of two forms of CP/M run 
commands. You may either enter: 

DPRINT B:ANYF1LE.TYP 

(where B: is optional 
for the default disk) 

or simply: 

DPRINT 

In either case, after load, the system will 
permit you to enter a constant to be 
printed on the heading line of each page 
of the listing produced. This can be any¬ 
thing you wish (not to exceed 40 charac¬ 
ters), but was primarily intended for a 
date. If you do not wish a constant in the 
header, a null response is acceptable. 

In case of the second form of the run 
command, the system will immediately 
start printing your file. If the file cannot 
be found, an open error message will be 
produced on the console. Paper position¬ 
ing should be such that the first printable 
line on the page is positioned under the 
print head. 

In the first form, the system will en¬ 
ter into interactive mode with you, 
prompting for the entry of the file 
names you wish to print. As you enter 
each name, the system will look it up in 
the file directory appropriate, display the 
result (either “can’t find” or “print” 
followed by the file name), and wait for 
a key stroke. Any key other than N will 
cause the file to be stacked for printing. 

Since ambiguous names are permit¬ 
ted, entries such as *.ASM or DPR???.- 
ASM may produce several possible file 
names for stacking, and each is presented 


to you for inclusion or discard. When all 
matching names have been found, the 
prompt for another file name is issued. 
To terminate this process, make a null 
entry. The system will stack up to 64 files 
for print, and then will automatically exit 
the interactive dialog. 

Upon exit from the interactive dia¬ 
log, the system will immediately begin 
to print the first file in the stack. During 
the printing process, you may interrupt 
the print by any of the following keys: 

Control-S Pauses print — any key will 
resume printing. 

Control-C Cancels total job and returns 
to CP/M. 

Escape Cancels print of the current 
file and proceeds to the next 
file (assuming stack is still oc¬ 
cupied). 

This interruption will occur at the current 
line. When a file or job cancellation oc¬ 
curs, the form is advanced to the top of a 
new page. 

When the stack is exhausted, the pro¬ 
gram will prompt to see if you have 
further printing or not. If you respond Y 
to the prompt, the system will re-enter 
the interactive dialog phase, and the pro¬ 
cess iterates. 

For those of you who do not want to 
poke all of this into a terminal, I’ll make 
the standard offer. ... If you send me a 
disk and $20, or $30 without a disk, I’ll 
format it to single-density single-surface, 
and load it with the source, relocatable, 
and executable materials for DPRINT and 
my common libraries and macros. The 
latter probably won’t do you much good 
unless you have the TDL (or equivalent) 
assembler and linker, but for those who 
do, it will save some code. Incidentally, 
the fee is to cover copying, shipping, and 
handling. I’m like Dr. Dobbs . . . I’m non¬ 
profit, but in my case it probably wasn’t 
intentional! From previous experience, 
I’m a bit “gun shy.” I use a Morrow En¬ 
gineering 2D disk interface with Shugart 
800 series disks. By going to single-density, 
single-surface, I’ve always been able to 
migrate materials, but because of those of 
you with “odd” interfaces, etc., this offer 
is without warranty. Incidentally, I’m on 
CP/M Version 2.x, but that should not 
cause problems. 

Good luck, and happy printing!! 

(Listing begins on page 39) 


Dr. Dobb’s Journal, Number 68, June 1982 


37 

257 




CP/M Print Utility (Text begins on page 36) 


Listing 1 

Listing of DPRINT.ASH March IB, 1982 

.TITLE "DOUBLE COLUMN PRINT OF DISK ASCII FILE - MAIN 
MODULE" 

.S8TTL "VERSION 2.0 - MARCH 1982 - DD SYSTEMS" 

.IDENT DPRINT 


•EXTERN SETSTK ;DPR01 

■EXTERN PRELD,LDFCB ;DPR02 

.EXTERN CLEAR,PRINT ;DPR03 

.EXTERN FILL ;DPR04 

•EXTERN .FREE. ;SYSTEM 


******* ************************** 


* * 

* COPYRIGHT 1982 - DD SYSTEMS * 

* ALL RIGHTS RESERVED * 

* * 

********************************* 
* * 

* D. U. DAETUYLER * 

* ROUTE 5, BOX 518A * 

* SPRINGDALE, ARK. 72764 * 

* 501-756-0212 * 

* t 


********************************* 

NOTE: THIS COLLECTION OF MODULES IS RELEASED FOR 
INDIVIDUAL, PRIVATE, USE. ANY COMMERCIAL 
USE OR EXPLOITATION IS EXPRESSLY FORBIDDEN. 
“CP/M" IS A COPYRIGHTED DEVELOPMENT OF 
DIGITAL RESEARCH. "KSR-43" IS COPYRIGHTED 
BY THE TELETYPE CORPORATION. 

THIS PROGRAM PROVIDES A DOUBLE COLUMN PRINT OF TYPICAL 
SOURCE (ASCII) FILES FOR ANY LANGUAGE. IT IS DESIGNED 
TO USE ANY REASONABLE PAGE SIZE (MAX 132 X 66) AND IS 
CURRENTLY ASSEMBLED TO RUN UITH A KSR-43 TELETYPE. IT 
HANDLES ITS OUN PAGINATION AND IGNORES FORMS CONTROLS. 
PAGES ARE TITLED AND NUMBERED. LINES TOO LONG (OVER 
HALF PAGE - 2) TO FIT ARE BROKEN ON "TEXT UORD" 
BOUNDARIES, AND THE CONTINUATION IS INDENTED 20 
POSITIONS ON THE FOLLOUING LINE. 

INPUT TO THE PROGRAM MAY BE IN THE CP/M COMMAND LINE 
AS IS USUAL FOR UTILITIES (EG: DPRINT B:DUMMY.ASM!. 


ADDITIONAL OPTIONS ARE OFFERED, HOUEVER. SIMPLY 
ENTERING THE RUN COMMAND (EG: DPRINT) ALONE, HILL 
CAUSE THE PROGRAM TO INTERROGATE THE CONSOLE FOR ITS 
INPUT FILE OR FILES. UP TO 64 FILES MAY BE SPECIFIED 
DURING THIS INPUT SESSION. END OF SESSION IS 
SIGNIFIED BY A NULL RESPONSE (IMMEDIATE RETURN). 

UHEN ENTERING FILES IN THIS MODE, THE CP/M CONVENTIONS 
PERMITTING THE USE OF ???? OR * AS UNIVERSAL MATCH 
CHARACTERS IS ALLOUED. 

AS EACH FILE IS REQUESTED (MULTIPLE RESPONSE UITH 
(???? OR *), IT IS LOOKED UP IN THE DISK DIRECTORY, 

AND THE USER IS ASKED IF THIS FILE IS TO BE PRINTED. 

ANY RESPONSE OTHER THAN "H" UILL PERMIT THE FILE TO 
BE STACKED FOR PRINT. "N" UILL BYPASS THAT FILE 
AND CONTINUE THE PROCESS. BY ENTERING *.ASM, THE 
PROGRAM UILL PERMIT YOU TO SELECT FROM ALL OF THE 
.ASM FILES ON THE DISK...SAVES A FEU KEY STROKES. 

UHEN MULTIPLE FILES ARE PRINTED, THE HEADINGS AND PAGE 
NUMBERING IS RE-INITIALIEB FOR EACH FILE. DURING 
PRINTING, THE PROCESS MAY BE INTERUPTED AT THE END OF 
ANY LINE. A "CONTROL-S" UILL PAUSE PRINTING UNTIL 
ANY KEY IS DEPRESSED. AN "ESCAPE" UILL CAUSE THE FILE 


CURRENTLY BEING PRINTED TO BE TERMINATED, THE PAGE 
EJECTED, AND THE NEXT FILE (ASSUMING ONE AUAITS! TO BE 
STARTED. A "CONTROL-C" ABORTS THE JOB AND RETURNS TO 
THE SUPPORTING SYSTEM. 

INITIAL ENTRY UILL REQUEST A "TITLE" THAT UILL APPEAR 
ON THE HEADING LINE OF EACH PRINT OUT (ALONG UITH THE 
FILE NAME AND PAGE NUMBER). THIS "TITLE" DOES NOI 
CHANGE DURING THE ENTIRE RUN, AND IS REALLY INTENDED 
FOR INCLUSION OF A DATE. A NULL ENTRY IS ACCEPTED. 

FINALLY, THE PROGRAM, BEFORE TERMINATION, UILL ALLOU YOU 
TO RE-ENTER THE FILE SELECTION DIALOG IF YOU DESIRE. 

CHARACTERS LESS THAN BLANK, AND OTHER THAN CARRIAGE 
RETURN, LINE FEED, BACK SPACE, AND TAB UILL PRINT AS THE 
"UNPRINTABLE" CHARACTER SYMBOL ON THE PRINTER. 


; SYSTEM EQUATES 

r 

PCB == 5CH ; DEFAULT SYSTEM FCB 

BUF1 == 80H ;CP/M DEFAULT BUFFER 

» 

; AREA FOR PAGE CONSTANTS 

L.L == 132 

P.L ” 51 

I..LEN:: .UORD L.L JLINE LENGTH 

HLEN:: .UORD L.L/2 ;HALF LINE LENGTH 

LINES:: .BYTE P.L-7 ;PAGE LENGTH - HEADER AND TRAILER 

PROD:: .UORD (P.L-7)*L.L-1 ;PAGE MATRIX SIZE 

t 

; USER "PATCH" FOR INITIALIZATION 

DUMMY: RET 

•BLKB 127 

; ACTUAL START OF PROGRAM 

START: XRA A 

STA STKCNTtt ;INITIALIZE UORKING STORAGE 


STA PGCNT# 

LHLD .FREE. ;LOAD TOP OF PROGRAM 

LDED PROD ;LOAD PAGE SIZE-1 

DAD D 

INX H ;HL POINTS TO LAST CELL USED 

LDED 6 ;LOAD BOTTOM OF OPERATING SYSTEM 

DCR Ii ;REDUCE FOR STACK 

XCHG 

ORA A 

DSBC D ;SEE IF ENOUGH SPACE 

JRNC ..XX 

LXI H,PRM6 

CALL SMCPM ;ANNOUNCE MEMORY SHORTAGE 

JMP 0 ;AND SCRUB 

..XX: CALL TITLE ;GET HEADING FIELD 

LXI H,STACK# 

SHLD STKPTR# 

LDA FCB+1 ;SEE IF FILE NAME UAS INPUT UITH COMMAND 

CPI ' ' 

JRZ ..RPT JNO, SO ENTER CONSOLE DIAGLOG 


FILE NAME ON COHMAND LINE 
LXI H.FCB 

LXI D,F$INF'#+4 ;INPUT FCB 

LXI B, 32 

(Continued on next page) 


Dr. Dobb’s Journal, Number 68, June 1982 
258 


39 









CP/M Print Utility (Listing continued, text begins on page 36) 



LDIR 


SINCE CP/M SET IT UP, USE IT! 


CALL 

PRELD 

GO TO PRELOAD ENTRY POINT 


JRC 

..DNE 

OPEN FAILURE 


JMPR 

..GO 

AND REENTER PROCESS 


CONSOLE 

DIALOG FOR FILE ENTRY 

RFT: 

CALL 

*CRLF# 



LX I 

H,PRM1 

PROMPT FOR DATA 


CALL 

$MCPM# 



JMPR 

..B 


A: 

LXI 

H,BUF1 

;USE DEFAULT BUFFER FOR INPUT 


MV I 

A,20 

JMAX INPUT = 20 CHARACTERS 


CALL 

$MCI# 

;GET INPUT STRING 


I NX 

H 



XRA 

A 



CMP 

M 

JCHECK FOR NULL INPUT 


JRZ 

..SDN 

;YEP, SO ALL DONE BUT THE PROCESS 


CALL 

SETSTK 

;ADD ENTRY TO STACK 


JRC 

..SDN 

J20 ENTRIES, SO PUNT 

8: 

CALL 

$ CRL F # 



LXI 

H,PRM2 

;CONTINUE PROMPTING 


CALL 

SMCPM# 



JMPR 

. .A 



HAVING 

THE INPUT 

LIST, NOLI PROCESS 

SDH: 

CALL 

SCRLF# 



LXI 

H,PRM4 



CALL 

$HCPM# 

;PROMPT FOR PRINT PHASE 


LXI 

H,STACK# 



SHLD 

STKPTR# 

;RESET THE STACK POINTER TO START 

CHK: 

CALL 

LDFCB 

;SET UP THE FCB AND OPEN 


JRC 

. .DNE 

;STACK IS EXHAUSTED 

GO: 

XRA 

A 



STA 

PGCNT# 

;RESET PAGE NUMBER 


LXI 

Y.LINSX# 



MV I 

0 ( Y ), 0 

;INITIALIZE LINE CONTROL SUITCH 

G1: 

CALL 

CLEAR 

;CLEAR THE PAGE PRINT AREA 



CALL 

FILL 

;FILL IT UITH DATA 



JRC 

..EOF 

;END OF FILE 



CALL 

PRINT 

;nou LIST IT 



JRC 

..TST 

;SOMEONE IS TALKING TO US 



JMPR 

.. G1 

JLQOP THROUGH FILE 


..EOF: 

CALL 

PRINT 

ISTILL HAVE TO PRINT THAT 

LAST PAGE 


JRC 

..TST 




JMPR 

. .CHK 

;NO, SO GO FOR NEXT STACK 

ENTRY 


THE STACK IS EXHAUSTED (AND SO AM I) 


..DNE: 

LXI 

H,PRM3 

|SEE IF HE UANTS TO PRINT 

THE PHONE 


CALL 

$CRLF# 




CALL 

$MCPM# 




CALL 

SCIN 

;JUST ONE CHARACTER IS ENOUGH 


CPI 

'Y' 

;IF HE FUMBLES THIS, HE'S 

OFF 


JNZ 

0 




XRA 

A 




STA 

STKCNTN 




LXI 

H,STACK# 



SHLD 

STKPTR# 




JMPR 

. .RPT 

THERE UE GO AGAIN!! 



USER 

ENTERED A 

CANCEL BATCH OR CANCEL FILE COMMAND 

!.TST: 

DCR 

A 




JRZ 

..CHK 

;ABORTED THIS FILE 



JMP 

0 

;ABORTED THE BATCH 



HEADER LINE CONSTANT ENTRY 



CALL 

DUMMY 

;DUMMY (RET) PATCH 1 


INITIALIZATION 

LXI 

H,PRM5 


CALL 

JMCPM# 

;PROHPT FOR HEADING 

LXI 

H, BUF2# 


MVI 

A,42 


CALL 

»MCI# 

;GET USER INPUT 

INX 

H 


LXI 

B, 0 


MVI 

C, 40 

JMAX ACCEPTED 

MOV 

A, H 


CPI 

4! 


JRNC 

..A 


MOV 

C,A 

;LESS, SO USE HIS LI 

INR 

C 

J BUMP EITHER BY ONE 


L XI B.TILSAV# 


;SAUE TITLE 


LOCAL MESSAGES 


PRM1 : 

.BYTE 

1BH, E' ; CLEARS SCREEN ON SOME TERMINALS 


.ASCII 

" FILE ENTRY" 


■ BYTE 

13,10,13,10 


• ASCII 

"ENTER FILE NAMES IN CONVENTIONAL FORH:" 


■ BYTE 

13,10 


•ASCII 

" [DRIVE:1NAME.TYPE" 


• BYTE 

13,10 


• ASCII 

"AMBIGUOUS REFERENCES (????? OR *> ARE 

SUPPORTED. LIMIT IS" 


• BYTE 

13,10 


■ASCII 

"44 FILES FOR PRINT. ENTER A NULL (ZERO LENGTH) 
ENTRY TO" 


• BYTE 

13,10 


•ASCII 

"TERMINATE THE SELECTION PROCESS." 


• BYTE 

13,10, '$ 

PRM2: 

.ASCII 

"FILE? (NULL TO QUIT): $" 

PRM3: 

•ASCII 

"MORE (Y OR N>? 1” 

PRM4: 

.ASCII 

"'ESCAPE' TERMINATES PRINT OF FILE CURRENTLY 
PRINTING" 


• BYTE 

13,10 


•ASCII 

" CONTRQL-S PAUSES PRINTING - ANY KEY RESUMES” 


.BYTE 

13,10 


■ASCII 

"'CONTROL-C TERMINATES AND RETURNS CONTROL TO 
THE SYSTEM" 


■ BYTE 

13,10,'$' 

PRM5: 

•ASCII 

"ENTER HEADING: $" 

PRM4: 

•ASCII 

"SORRY - NOT ENOUGH MEMORY FOR THIS PAGE 



SIZE! !$" 

f 

• END 

START 

Listing 2 


Listing 

of DPR01.ASM March 18, 1932 


.TITLE 

"DOUBLE COLUMN PRINT - SEARCH STACK MODULES" 


. SBTTL 

"VERSION 2.0 - MARCH 1982 - DD SYSTEMS" 


. I DENT 

DPR01 

’ 

■ENTRY 

SETSTK 

Y 

•EXTERN 

LOGFIL 

y 

.INSERT 

MACF1 


THIS SET OF HOBULES ACCEPTS THE INPUT STRING FROM THE 
USER AND FORMS IT INTO "FCB" FORM. AND '????" ARE 
HANDLED AS ARE "DRIVE" SPECIFICATIONS. 


Dr. Dobb’s Journal, Number 68, June 1 982 

259 





SETSTK: 


..ft: 


..C: 


. ,B: 


SETDRV: 


..A: 


..X: 


AS EACH 

NAHE IS 

ACCEPTED, IT IS USED FOR A DIRECTORY 

* 



SEARCH. 

EACH SATISFIED SEARCH IS DISPLATED, AND THE 




USER IS 

PERHITTED TO ACCEPT/DISCARD THE ENTRY. IF 




THE ???? OR * HATCH CHARACTERS ARE USED, THEN ALL OF 




THE FILES HEETI 

NG THESE CRITERIA ARE DISPLAYED FOR 

SETNAH 

PUSH 

D 

USER SELECTION. 

ACCEPTED FILES ARE STACKED FOR LATER 


XRA 

A 

PROCESSING. IF 

A NAHE CANNOT BE FOUND, THEN THAT 


CHF 

B 

INCIDENT IS LOGGED. AND THE PROCESS CONTINUES. 


JRZ 

..RET ;NO NAME - UELL OPEN WILL GET HIM 




..A: 

HOV 

A , M 

LXI 

D,F$SRCH#+4 :POINT TO SEARCH FCB 


INX 

H 

HOV 

B,H 

;GET STRING LENGTH 


CPI 

*• 

INX 

H 

JSTEP TO DATA 


JRZ 

..UN ;UNIVERSAL HATCH - UOU! 

CALL 

SETDRV 

;TRY TO FILL IN THE DRIVE SPEC 


CPI 


CALL 

SETNAH 

;MOVE IN THE FILE NAHE 


JRZ 

..END ;FOUND END OF NAHE 

CALL 

SETTYP 

I MOVE IN THE FILE TYPE 


STAX 

D 

SEARCH 

SRCH,FIRST 


INX 

D 

JRC 

..B 

;not FOUND 


DJNZ 

. .A 

CALL 

DSPFND 

;DISPLAY FILE FOUND 

-.RET: 

POP 

D 

JRC 

..C 

;USER BYPASSED 


XCHG 


CALL 

ADSTAK 

;ADD ENTRY TO STACK 


PUSH 

B 

RC 




LXI 

B , 8 

SEARCH 

SRCH,NEXT 


DAD 

B 

JRNC 

..A 

,-GOOD HIT 


POP 

B 

XRA 

A 

;no find, but secondary 


XCHG 

;de stepped over nahe field 

RET 




RET 


CALL 

NOFND 

JPRIMARY SEARCH NOT FOUND 




XRA 

A 





RET 



f 

'*•' HUST BE CONVERTED TO ?YT»ttT? 

SEE IF 

A DRIVE 

UAS SPECIFIED, OR IF IT IS A "DEFAULTED" 

..UN: 

POP 

D ;RESTORE PTR TO START OF FIELD 





PUSH 

D 





XCHG 






PUSH 

B 





HVI 

B, 8 




. .B: 

HVI 

M , ?' 


FILE 


INX 

H 





DJNZ 

..B 

PUSH 

H 





PUSH 

D 



POP 

B 

PUSH 

B 



XCHG 


PUSH 

D 



INX 

H 

POP 

H 



DCR 

B 

INX 

D 


..END: 

DCR 

E 

MV I 

M,' ' 



JHPR 

..RET 

LXI 

B , 11 





LDIR 


JBLANK THE STACK ENTRY AREA 


NOU SET 

THE FILE TYPE 

LXI 

B ,24 





M/I 

H.0 

JCLEAR THE REMAINDER OF THE FCB 

SETTYP: 

PUSH 

D 

LDIR 




XRA 

A 

POP 

B 



CHP 

B 

POP 

D 





POP 

H 





XRA 

A 





STAX 

D 

;SET AS "DEFAULT" 




INX 

D 



JRZ 

..RET 

MOV 

A,H 


. .A: 

MOV 

A ,M 

INX 

H 



INX 

H 

CPI 

✓ ✓ 



CPI 

' *•' 

JRNZ 

. .X 

;STRIP LEADING BLANKS IF ANY 


JRZ 

..UN ;UNIVERSAL HATCH AGAIN 

DJNZ 

..A 



STAX 

II 

HOV 

A, H 



INX 

D 

CPI 

/ J / 

;CHECK FOR DRIVE FLAG 


DJNZ 

. .A 

DCX 

H 


..RET: 

POP 

D 

RNZ 


;DEFAULT DRIVE 


RET 


MOV 

A,H 


..UN: 

POP 

H 

SUI 

A ' 



HVI 

B,3 

RC 


;bad drive, so default 

..B: 

HVI 

H ,' ? ' 

INR 

A 



INX 

H 

DCX 

D 



DJNZ 

. .B 

STAX 

D 

;SET IN DRIVE CODE 


RET 


INX 

D 


r 



INX 

H 


T 

DISPLAY 

THE FILE NAHE FOUND AND GET ACCEPTANCE 

INX 

H 


r 



OCR 

B 


DSPFND: 

CALL 

SETRD ;SET UP NAHE FROM DIRECTORY 





CALL 

iCRLF# 





LXI 

H.FHSG ;PROMPT FOR ACCEPTANCE 

BCR 

B 



CALL 

iMCPMH 

RET 




LXI 

H.SAVFIL 

NOW FIT 

THE NAHE INTO THE FCB 



(Continued on next page) 


Di. Dobb’s Journal, Number 68, June 1982 

M 


41 







CPIM Print Utility (Listing continued, text begins on page 36) 


CALL L06FIL 

MVI A,'?' 

CALL SCO# 

CALL JBLKS 

CALL *CI« ;GET INPUT RESPONSE 

CPI •'N / ; ONLY N' REJECTS 

STC 
RZ 

XRA A 

RET 

; SET DIRECTORY ENTRY AND WOVE TO SAVE AREA 

SETRD: ADD A 

ADD A 

ADD A 

ADD A 

ADD A 

LXI B,0 

MOD C,A 


LXI H, BUF2B 

DAD B JHL POINTS TO DIRECTORY ENTRY 

LXI D.SAVFIL 

LXI B,12 

LOIR ;SAVE NAME 

LDA FJSRCHSf4 ;GET DRIVE 

STA SAVFIL 

RET 

; ADD SAVE ENTRY TO STACK 

» 

ADSTAK: LDED STKPTRS 

LXI H,SAVFIL 

LXI D, 12 

LDIR 

SDED STKPTRN ;SAVE UPDATED POINTER 
LDA STKCNTS 

INR A ;INCREMENT STACK COUNT 

STA STKCNT # 

CPI 64 

CMC 

RET 

; PRIMARY ENTRY NOT FOUND, SO LOG IT 

NOFND: CALL SCRLFS 
LXI H.NFMSG 

CALL SMCPMS 
LXI H,FSSRCHS+4 

CALL LOGFIL 
RET 

J LOCAL MESSAGES 

FRSG: .ASCII “Print i" 

NFMSG: .ASCII "Can't find S" 

; LOCAL UORK AREA 

SAVFIL: .BLKB 12 

• END 


Listing 3 

Listing of DPRtL’.ASM March IB, 1982 

.TITLE "DOUBLE COLUMN PRINT - SET UP FOB'S AND OPEN" 


42 


•SBTTL "VERSION 2.0 - MARCH 1982 - DD SYSTEMS" 

.I DENT DPR02 

.ENTRY LDFCB.PRELD,LOGFIL 

* 

.INSERT MACF1 

J THIS MODULE PULLS FILE NAMES FROM THE STACK AND OPENS 

; THEM. "PRELD" IS AN ENTRY USED UHEN THE FILE IS 

J SPECIFIED ON THE CP/M COMMAND LINE. FILE NAMES 

; ARE PLACED IN THE INPUT FCB FOR OPEN. IN THE RARE 

: CASE OF AN OPEN FAILURE, THE INCIDENT IS LOGGED, AND 

; THE RUN CONTINUES. 

J SYSTEM EQUATES 

BUF1 == 80H ;CP/M DEFAULT BUFFER 

; PULL NAME FROM STACK, DO INITIAL DIRECTORY SEARCH, AND 

OPEN 

LDFCB: LDA STKCNTS 

ORA A ;CHECK THE STACK COUNT 

STC 

RZ JSTACK EXHAUSTED 

DCR A 

STA STKCNTS 

LHLD STKPTRS ;GET NAME ADDRESS 

LXI D, F4INPS + 4 ;POINT TO SEARCH FCB 

LXI B,12 

LDIR JMQVE IN NAME (AND DRIVE) 

SHLD STKPTRS ;SAVE THE UPDATED STACK PTR 
PRELD: OPEN INP,INPUT,,,,BUF1,OPERR 

XRA A 

RET 

,• OPEN ERROR LOGGING 

OPERR: CALL 4CRLFS 

LXI H,OMSG 

CALL SMCPMS JSTART MESSAGE 

LXI H,F$INPB+4 

CALL LOGFIL JOUTPUT FILE NAME 



JMPR 

LDFCB 



OUTPUT 

FILE NAME 

TO CONSOLE 

LOGFIL: 

MOV 

A, M 



ORA 

A 

;CHECK DRIVE 


JRZ 

. .A 

; DEFAULTED 


ADI 

' A ' - 1 



CALL 

SCOH 

;OUTPUT DRIVE 


MVI 

A,':' 



CALL 

SCON 

;and FLAG 


A: 

INX 

H 



MVI 

B,8 


C: 

MOV 

A,H 



INX 

H 



CPI 

/ / 



JRZ 

..B 

;SKIP BLANKS 


CALL 

SCON 


B: 

DJNZ 

..C 

;LOOP THROUGH NAME 


MOV 

A,H 



CPI 

' ' 

;SEE IF THERE'S A TYPE 


RZ 


;no, SO GET OUT 


MVI 

A,'.' 



CALL 

SCOS 



MVI 

B ,3 


D: 

MOV 

A,M 



Dr. Dobb’s Journal, Number 68, June 1 982 

261 











{CONTROL'S 


I NX H 

CALL $C0# 

DJNZ ..D 

RET 


CPI 13H 

JRNZ ..A 

CALL $C1# JUAIT FOR KEY PRESS 


; LOCAL MESSAGE 

OHSG: .ASCII “CAN'T OPEN i" 


JMPR 

..XX 

;NOU SEE IF 

IT UAS A CONTROL KEY 

DJNZ 

..LP 



CALL 

SLCRLF* 

JFINISH THE 

PAGE 

CALL 

iLCRLF# 



XRA 

A 



RET 





Listing 4 

Listing of DfR03.ASM Harch IB, 1982 


PNT1: 

MVI 

A»1 


PNT2: 

PUSH 

PSU 

;SAVE RETURN CODE 


INR 

B 


PNT3: 

CALL 

iLCRLF# 

ISPACE OUT PAGE 


DJNZ 

..PNT3 



POP 

PSU 



STC 




RET 




.TITLE "DOUBLE COLUMN PRINT - CLEAR AND PRINT MODULES" 
.SBTTL “VERSION 2.0 - MARCH 1982 - DD SYSTEMS" 

.IDENT DPR03 


•ENTRY CLEAR,PRINT 


PRINT A PAGE LINE 


•EXTERN .FREE. 


THIS MODULE CLEARS THE PAGE BUFFER AREA AND THEN PRINTS 
IT AFTER IT HAS BEEN SET UP BY "FILL". IT SAHFLES THE 
KEY BOARD DURING PRINTING FOR POSSIBLE INTERRUPTIONS, 
AND TAKES APPROPRIATE ACTION ON VALID INPUT. 


PRTLNE: PUSH H 

..LP: MOV A,H 

CPI 13 

JRZ ..CR JQUIT ON CR 

CALL *L0M 

INX H 

JMPR ..LP 






..CR: 

CALL 

ILCRLF# {END LINE 






POP 

H 






RET 


CLEAR.- 

LHLD 

.FREE. 

,-USES MEMORY ABOVE PROGRAM 





PUSH 

H 






POP 

D 






INX 

D 


a 

y 

PRINT 

THE PAGE HEADING 


LBCD 

PROD# 

|PAGE SIZE 





MVI 

M,' ' 


HEAD: 

LXI 

H,HMS1 


LDIR 


!CLEARED TO BLANKS 


CALL 

LMSG 


RET 




LXI 

H,F$INP#+A 






MVI 

B, 8 






MOV 

A,H 






INX 

H 


PRINTS 

THE PAGE 

BUFFER 


ORA 

A 






JRZ 

..A {CHECK DRIVE 






ADI 

' A' -1 






CALL 

$LO# 

PRINT: 

CALL 

iLCRLF# 



MVI 

A,':' 


CALL 

SLCRLF N 

ISPACE DOUN FROM TOP 





CALL 

iLCRLF# 






CALL 

HEAD 

,-PRINT THE HEADING 









CALL 

ILO# {DRIVE FLAG 


LHLD 

• FREE. 


..A: 

MOV 

A,M 


LDED 

LLEN# 

JLOAD LINE LENGTH 


INX 

H 


LDA 

LINES# 

;LOAD LINE COUNT 





MOV 

B, A 





..LP: 

CALL 

PRTLNE 

;PRINT A LINE 





DAD 

D 






CALL 

SC I DR H 

{CHECK FOR KEY PRESS 




..XX: 

ORA 

A 






JRZ 

..A 






CPI 

1BH 



CPI 

/ / 


JRZ 

..PNT1 

{PUNT THIS FILE 


JRZ 

..B {SKIP BLANKS 


CPI 

3 



CALL 

SLO# 


JRZ 

..PNT2 

;PUNT THE JOB 





(Continued on next page) 


Dr. Dobb’s Journal, Number 68, June 1982 
262 


43 







CP/M Print Utility (Listing continued, text begins on page 36) 


.B: 

DJNZ 

..A 



MOV 

A,M 



CPI 

/ / i 

1 

ICHECK FOR TYPE 


JRZ 

..C 



MVI 

A/.' 



CALL 

slon ; 

PUNCTUATE 

.C: 

MVI 

B, 3 


.D: 

MOV 

A, M 



INX 

H 



CALL 

$LON ; 

OUTPUT TYPE 


DJNZ 

..D 



MVI 

A,6 



CALL 

SLBLKSN ; 

OUTPUT 93 SPACES 


LXI 

H,TILSAV+1 


CALL 

LMSG 

(OUTPUT USER HEADER 


LDA 

LLENN 

;get line length 


SUI 

78 



CALL 

SLBLKSN ; 

JSPACE OVER TO PAGE 


LXI 

H,HMS2 



CALL 

LMSG 



LDA 

PGCNTN 

|GET PAGE COUNT 


INR 

A 



STA 

PGCNTN 



MVI 

B, 0 


..F: 

5UI 

10 



JRC 

..E 



INR 

B 



JMPR 

..F 


..E: 

ADI 

10 



MOV 

C,A 



XRA 

A 



CMP 

B 



MVI 

A.' ' 



JRZ 

..G 



MVI 

A, '0' 


..G: 

ORA 

B 



CALL 

SLON 

(OUTPUT PAGE NUMBER 


MVI 

A, 0' 



ORA 

C 



CALL 

SLON 



CALL 

SLCRLFN 



CALL 

SLCRLFN 



RET 




DUMB LIST MESSAGE ROUTINE 

LMSG: 

MOV 

A,M 



ORA 

A 



RZ 




INX 

H 



CALL 

SLON 



JMPR 

LMSG 



LOCAL MESSAGES 


HMS1: 

.ASCIZ 

"Listing 

of " 

HMS2: 

.ASCIZ 

"Page " 


TILSAV: 

:.ASCIZ 

H 


» 

.END 




Listing 5 


.TITLE "DOUBLE COLUMN PRINT - PAGE FILLER MODULES" 
.SBTTL "VERSION 2.0 - MARCH 1982 - DD SYSTEMS" 

.IDENT DPR04 

•ENTRY FILL 

■EXTERN .FREE. 

■INSERT MACF1 


THESE MODULES PROVIDE THE FUNCTION OF BUILDING THE TUO 
COLUMN SPREAD IN A PAGE SIZE BUFFER. THE "FILL" 

MODULE IS SIMPLE OVERHEAD THAT ITERATES THROUGH THE 
"COL" ROUTINE TUICE. THE ”C0L" ROUTINE, AGAIN, IS 
OVERHEAD THAT CYCLES THROUGH THE "LINE" ROUTINE "LINES" 
TIMES. "LINE" IS THE REAL PROCESSOR, UHICH FORMS THE 
LINE IN A BUFFER BY USE OF "GETLIN" AND THEN MOVES 
APPROPRIATE PARTS (LONG LINES) OF THE LINE TO THE PAGE 
AREA. "GETLIN" READS THE DISK AND BUILDS A FULL LINE 
(UP TO 255 BYTES) IN THE BUFFER AREA. IT READS UNTIL 
A CR IS SENSED. FINALLY, "SCAN" (CALLED BY "FILL") 
SCANS THE PAGE BUFFER AND ESTABLISHES CARRIAGE RETURN/ 
LINE FEEDS AT THE APPROPRIATE POINTS IN THE LINE. 

NOTE: THIS ROUTINE WILL NOT HANDLE PAGES OF UIDTHS 
OF 5)0 COLUMNS OR GREATER (NOT THAT ANY ONE USES SUCH 
A PRINTER). 


PAGE FILL 


LIXD .FREE. 


;FORM FIRST COLUMN 
; EOF 


;OFFSET HALF PAGE 
;FORM SECOND COLUMN 
; SAVE FLAGS 
;SET CR/LF 
;RESTORE FLAGS 


BUILD ONE COLUMN 


LDA 

LINESN 


MOV 

B, A 

(LINE COUNT 

LDED 

LLENN 

(LINE LENGTH 

CALL 

LINE 

(BUILD A LINE 

RC 


(EOF RETURN 

DADX 

D 


DJNZ 

..A 


XRA 

RET 

A 


BUILD 

A LINE 


PUSH 

D 


PUSH 

B 


BIT 

0,0 (Y) 

(CHECK OVERFLOW FLAG 

JNZ 

. .UGH 

(OVER FLOW WAITING 

CALL 

GETLIN 

(GET THE NEXT LINE 

ORA 

A 


JRZ 

..XX 

(ZERO LENGTH LINE (USUALLY 1 

MOV 

C, A 



Dr. Dobb’s Journal, Number 68, June 1982 

263 










LDA 

HLENN 

JLOAD HALF LENGTH 


DCR 

A 



DCR 

A 



CNP 

C 



JRC 

..LNG 

; LIHE TOO LONG 


RES 

0,0(Y) 

JCLEAR OVERFLOU FLAG 

NVE: 

PUSH 

X 



POP 

D 

;BE POINTS TO LINE/COL IN PAGE 


LXI 

H,LINBUFN 


HVI 

M 



LOIR 


;move in line 

X 

X 

XRA 

A 



BIT 

1,0(Y> 

JCHECK FOR EOF 


JRZ 

..RET 

;no so nornal return 


BIT 

M<Y> 

;SEE IF OVERFLOU PENDING 


JRNZ 

..RET 

; YES SO NORNAL RETURN 


STC 



RET: 

POP 

B 



POP 

D 



RET 




HANDLE 

OVERFLOU 



! .UGH: LXI H,LINBUFN 


NVI 

C,20 


NOV 

8,C 


HVI 


JCLEAR OFFSET IN LINE 

INX 

H 


DJNZ 

..U1 


NOV 

E,1(Y) 

;LOAD OVERFLOU PTR 

NOV 

D,2(Y) 


NOV 

B , 3 ( Y ) 

(LOAD OVERFLOU COUNT 

LDAX 

D 


NOV 

H,A 

;MOVE IN OVERFLOU 

INX 

D 


INX 

H 


INR 

C 


DJNZ 

.. U2 


NOV 

A ,C 


JNPR 

..GO 

;nou handle as nornal 


’..LNG: 
. .LLI: 


.. L L 2: 


..OUT: 


HANDLE LONG LINE 

HVI B,0 

NOV A,N 

CPI ' ' ;BACK SCAN 

JRZ ..OUT 

CPI 

JRZ ..OUT 

DCX H 

INR G 

OCR C 

JHPR ..LLI 
LDA HLENN 

DCR A 

DCR A 

CNP C 

JRC ..LL2 ;STILL TOO LONG 

INX H 

INR C 

DCR B 

NOV 1(Y),L 

NOV 2 (Y >, H 

NOV 3(Y),B 

SET 0,0(Y> JSET OVERFLOU FLAG 

JNPR ..NVE 


9 



9 

6ET NEXT FILE LINE 

GETLIN: 

NVI 

C,B 


LXI 

H.LINBUFN 

..LP: 

FGET 

INP,EOF 


CPI 

1 AH 


JRZ 

EOF ;END OF FILE FOUND 


CPI 

13 


JZ 

CR ;END OF LINE 


CPI 

ID 


JRZ 

..LP ;SKIP LINE FEEDS 


CPI 

9 


JRZ 

..TB ;EXPAND TABS 

.. T B 2: 

NOV 

H,A ;SAVE IN BUFFER 


CPI 

8 


JRZ 

..OK ;IS OK 


CPI 

' '-1 


JRNC 

..OK 


NVI 

H,1FH ;"UNPRINTABLE" CHARACTER 

..OK: 

INX 

H 


INR 

C 


NVI 

A,0FFH 


CNP 

C 


JZ 

CR JFORCE END OF LINE 


JNPR 

..LP ;LOOP TILL END OF LINE 

» 

» 

9 

HANDLE 

(EXPAND) TABS 

..TB: 

NOV 

A,C 


ADI 

S 


AN I 

0F8H 


SUB 

C 


MOV 

B, A 


HVI 

A, ' ' 

.. TB1: 

HVI 

H,' ' JSET BLANKS 


INX 

H 


INR 

C ;COUNT 


DJNZ 

..TB1 


JNPR 

..LP ;AND KEEP GOING 

9 

9 

END OF 

LINE 

9 

CR: 

NOV 

A,C JLOAD COUNT 

* 

RET 


* 

END OF 

FILE 

EOF: 

SET 

1,I(Y) JSET EOF FLAG 


JNPR 

CR 

1 


(Continued on next page) 


Dr. Dobb’s Journal, Number 68, June 1982 
264 


45 






CP/M Print Utility 

(Listing continued, text begins on page 36) 


SCAN PAGE MATRIX AND SET CR/IF 


SCAN: 

LHLD 

.FREE. 

;POINT TO END OF LINE 


LDED 

LLENtt 

LOAD LINE LENGTH 


DAD 

D 



DCX 

H 

,HL POINTS TO END OF LINE 


LDA 

LINES# 



MOV 

B,A 

;line count 

..LP: 

CALL 

REVRS 

00 REVERSE SCAN 


DAD 

D 



DJNZ 

..LP 



RET 



y 

y 

REVERSE 

SCAN FOR 

NON BLANK 

REVRS: 

PUSH 

H 



PUSH 

B 



LGCD 

LLEN# 

;line length 


MVI 

A/ ' 


..LP: 

CCD 




JNO 

..GO 



JRZ 

..LP 


..GO: 

INX 

H 



INX 

H 



MVI 

M, 13 

JSET CR 


INX 

H 



MVI 

M, 1 0 

JSET LF 


POP 

B 



POP 

H 



RET 

.END 


Listing 6 

Listing of DPRUS.ASM March 18, 1982 

.TITLE "DOUBLE COLUMN PRINT - WORKING STORAGE" 

•SBTTL “VERSION 2.« - MARCH 1982 - DD SYSTEMS" 

. IDENT DPRUS 

.INSERT MACF1 

• THE MODULE CONTAINS THE PRIMARY UORKING STORAGE FOR THE 

PROGRAM 


* 

SYSTEM 

EQUATES 


BUF1 

s: 

80H 

;CP/M DEFAULT BUFFER 

* 

y 

DUMMY 

FCB'S 


y 

FCB 

INF,,,, 

, BUF1 


FCB 

SRCH,,, 

, ,BUF2 

STKPTR: 

:.BLKU 

1 

;CURRENT STACK ENTRY 

STKCNT: 

: .BLKB 

1 

JSTACK COUNT 

STACK:: 

. BLKB 

788 

;64 ENTRY STACK 

LINSX:: 

.BLKB 

4 

JUNE CONTROL POINTERS AND SUITCH 

LINBUF: 

:. BLKB 

255 

;line input buffer 

P6CNT:: 

.BLKB 

1 

;PAGE COUNTER 

BUF2:: 

.BLKB 

128 

;SEARCH FILE BUFFER 

y 

.END 




End Listing 


46 


Dr. Dobb’s Journal, Number 68, June 


<n m 

00 CD 
Ox CM 








Cross-Reference 
Generator in C 

A Program Conversion Aid 


C ross-reference listings are of little 
use to the person who originally 
wrote the program, so most such 
programs just gather dust on the back 
shelf. But those of us who don’t own 
Apples or TRS-80s get much of our soft¬ 
ware by converting programs written for 
some other computer. Cross-reference 
listings save hours of debugging on con¬ 
version efforts. When I started to convert 
Ron Cain’s Small-C compiler to the LSI- 
11,1 hauled XREF, a cross-reference pro¬ 
gram I had written years before, off the 
shelf where it had been resting. Ron’s dif¬ 
ferent coding style revealed a few addi¬ 
tional errors. However, the biggest prob¬ 
lem was the symbol table, for the compil¬ 
er would not fit in memory. CREF, the 
program described in this article, is a test 
bed for a different symbol table imple¬ 
mentation that is more compact. Even¬ 
tually, the more compact symbol table 
implementation will get folded back into 
XREF. 

CREF is written for Whitesmith’s C 
compiler and Portable C library. The lan¬ 
guage is compatible with Unix Version 7, 
but the library functions are not. For 
those with different compilers and li¬ 
braries, Figure 2 shows a cross-reference 
listing of the library routines. CREF 
accepts a list of file names from the com¬ 
mand line; if there are no file names, 
input is taken from the standard input. 
The cross-reference listing is printed on 
the standard output. The listing consists 
of all file names in “#include” state¬ 
ments, and all function, variable, and 


by Jeffrey L. Taylor 


Jeffrey L. Taylor, The Toolsmith, 139 G 
Street, Box 151, Davis, CA 95616. 


macro names in alphabetical order. Un¬ 
der each name is a list of files it appears 
in. To the right of each file name is a 
list of occurrences by line number. 

The three-level hierarchy in the list¬ 
ing is reflected in the symbol table organi¬ 
zation as shown in Figure 1. At the top is 
the name table, next a file table for each 
name, and at the bottom a list of line 
numbers for each file and name. While 
each name entry is unique, there is a file 
entry for each name in the file. This is 
where the symbol table was reorganized; 
how it was changed is explained later. 

Binary trees are used for the name- 
and file-search trees. Each entry contains 
text for a symbol and pointers, possibly 
NULL, to the left and right decendents. 
A binary tree grows from the “root” 
down, with new entries added at the tips 
or “leaves.” The function lookup finds 
the entry for a symbol, or if it is not 
present, where it should go. To search a 
binary tree, start at the root and compare 
the symbol against that stored in the 
entry. If it matches, stop, this is it. If it is 
before the entry in the alphabet, move to 
the left branch. Otherwise, it is after the 
entry and move to the right branch. Re¬ 
peat until it is found or there is no 
branch; i.e., the NULL pointer is encoun¬ 
tered. If the name is not found, that last 
NULL branch is where it should be add¬ 
ed. The tree is always kept in alphabetical 
order. The function “tree_walk” tra¬ 
verses a binary tree in what is known as 
in-order or symmetric order. It calls itself 
to visit all entries in the left subtree, then 
the original entry, and then all entries 
in the right subtree. Short, simple code, 
it uses lots of stack space. 

The list of line numbers is kept in a 
linked list. Each entry contains a line 


number and a pointer or link to the next 
line number. The pointer for the last line 
number is NULL. If a name occurs twice 
in the same line, then the line number is 
only recorded once. As each line number 
is added to the list, it is inserted at the 
top. Any duplicates are on top, so each 
line number is compared to the top of the 
list before adding. The function reverse is 

called by “list_file” to flip the order just 

before the list is printed. 

This symbol table structure as given 
works fine. However, for large programs 
there is considerable redundancy. There is 
a file entry for every name in it. If the 
text for that file name is stored separate 
form the rest of the entry, all entries for 
that file can use the same text. A point to 
the text is stored in each entry. To keep 
the code simple, this separate text entry 
is used for all trees. A tree rooted at 
“file_root” keeps track of the text for all 
file names to avoid duplicates. Name 
entries are looked up and added in a 
straightforward manner. File entries are 
looked up similarly, but adding a new 
entry is more complicated. The entry is 
added as usual, but “file_root” is 
searched and possibly added to for the 
text of the file name. 

CREF is intended for cross- 
referencing C programs. By changing the 
reserved word list and the code that ig¬ 
nores comments, it can be adapted to 
most other languages. I don’t currently 
have any programs too large for CREF, 
but sooner or later they will come along. 
When that happens, I must learn about 
some new data structure to store part of 
the symbol table on disk. It looks like a 
good way to learn about B-trees. »»j 

(Listing begins on page 51) 


"symbol _root" 



Figure 1 - Symbol Table Organization 


alloc 


cref .c 

61 

64 

linked, c 

26 

28 

string.c 

55 

61 

btoi 

cref.c 

231 

258 

fclose 

cref .c 

316 

326 

fopen 

cref .c 

316 

322 

getlin 

cref .c 

138 

142 

it ob 

cref.c 

280 

292 

putlin 
cref .c 

272 


stdin 

cref.c 

316 

322 

write 

diagn.c 

9 

14 


Figure 2 - Library Cross Reference 


50 


Dr. Dobb’s Journal, Number 68, June 1982 





Cross-Reference Generator 

(Text begins on page 50) 


cref.c 
crtf .c 
cref .c 
cr»f.c 
cref.c 
cref.c 
cref.c 
crtf .c 
cref.c 
cref.c 
cref.c 
lexcnp.c 
lexcnp.c 
lexcnp.c 
lexcnp.c 
lexcnp.c 
lexcnp.c 
lexcnp.c 

lfXCMp.C 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

lcxcnp.c 

crcf.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

diagn.c 

crcf .c 

esc .c 

esc .c 

esc.c 

esc.c 

esc .c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

esc.c 

cref.c 

linked.c 

linked.c 

linked.c 

linked.c 

linked.c 

linked.c 

linked.c 

linked.c 

1 inked.c 

linked.c 

linked.c 


1: 

Hinclude <std.h> 

linked.c 

2: 

Ninclude <local.h> 

linked.c 

3: 


linked.c 

4: 

• C cross reference utility * 


5: 


linked.c 




7: 

/• (c) 1982 by The Toolsnith +/ 

linked.c 




9: 

typedef short boolean; 

linked.c 


Ninclude "lexcnp.c" 

linked, c 

11: 

1: 

linked.c 

2: 

3: 

/• copyright (c) 1982 by The Toolsnith •/ 

1 inked.c 
linked.c 

41 

5: 

/• lexcnp - lexical conparison, -1 ("a" < "b"), 0 ("a" ** "b") 
int lexcnp(aa, bb, nn) 

or ’1 */ 

6: 

char ’aa, *bb; 

linked, c 

7: 

unsigned nn; 

linked.c 

8: 

< 

linked.c 

9: 

register char ’a, *b; 

linked, c 

10: 

register unsigned n; 

linked.c 

11: 


cref .c 

12: 

for(a * aa, b B bb, n * nn; ;a**, b+O < 

string.c 

13: 

if(tolouer(’a) !* tolower(’b)) 

string.c 

14: 

return tolower(’a) - tolower(*b); /• unequal •/ 

string.c 

15: 

if(’a =* 'NO' S l —n ** 0) 

string.c 

16: 

break; 

string.c 

17: 

> 

string.c 

18: 

for(a * aa, b * bb, n * nn; ; a**, b*+) { 

string.c 

19: 

if(*a !* *b) 

string.c 

20: 

return *a - ’b; /• unequal •/ 

string.c 

21: 

if (’a ** 'NO' ! 1 —n sa 0) 

string.c 

22: 

break; 

string.c 

23: 

> 

string.c 

24: 

return 0; /• equal */ 

string.c 

25: 

> 

string.c 

12: 

Ninclude "diagn.c" 

string.c 

1: 

string.c 

2: 

/* (c) copyright 1982 by The Toolsnith •/ 

string.c 

3: 

string.c 

4: 

/* diagnostic - spit out error nessage */ 

string.c 

5: 

diagnostic(fatal, args) 

string.c 

6: 

boolean fatal; 

string.c 

7: 

char ’args; 

string.c 

8: 

< 

string.c 

9: 

extern unsigned lenstrO, writeO; 

string.c 
string, c 

10: 

extern exitO; 

string.c 

11: 

register char **a; 

string.c 

12: 


string.c 

13: 

if(fatal) 

string.c 

14: 

urite(STDERR, "PANIC!!! ", 9); 

string.c 

15: 

for(a ■ largs; ’a !* HULL; +’a) 


16: 

urite(STDERR, ’a, lenstr(*a))J 

string.c 

17: 

urite(STDERR, "Nn", 1); 

string.c 

18: 

if(fatal) 

string.c 

19: 

exit(HO); /* error exit to OS •/ 

string.c 

20: 

> 

string.c 

13: 

Ninclude "esc.c" 

string.c 

1: 


string.c 

2: 

/• (c) copyright 1982 by The Toolsnith •/ 

string.c 

3: 


string.c 

4: 

/• esc - nap string into escaped character if appropriate •/ 

string.c 

5: 

char esc(s) 

string.c 

6: 

register char ”s; 

string.c 

7i 

< 

string.c 

8: 

extern unsigned scnstrO; 

string.c 

9: 

static char realt] ■ "NbNtNvNfNnNrN(N!N)N' s "; 

string.c 

10: 

static char synbCl * "btvfnri!)*"; 

string.c 

11: 


string.c 

12: 

if(”s !■ 'W) 

string.c 

13s 

return ”s; 

string.c 

14: 

if(’(’s’1) ** 'NO') /• not special at end */ 

string.c 

15: 

return 'NN'; 

string.c 

16: 

♦ ♦•s; 

string.c 

17: 

realCsizeof(real)-13 » ”s; 

string.c 

18: 

return realCscnstr(synb, ”s)3; 

string.c 

19: 

> 

string.c 

14: 

Ninclude "linked.c" 

string.c 

1: 


string.c 

2: 

/• (c) copyright 1982 by The Toolsnith •/ 

string.c 

3: 


string.c 

4: 

struct linked_list < 

string.c 

5: 

struct linked_list ’link; 

string.c 

6: 

); 

string.c 

7: 


string.c 

8: 

/• reverse - invert order of a linked list •/ 

string.c 

9: 

struct linked list *reverse(this) 

string.c 

10: 

register struct linked list ’this; 

11: 

< 



12: register struct linked list ’next, ’previous; 

13: 

14: for(previous * HULL; this !» HULL; previous * this, this * next) -C 

15: next = this->link; 

16: this->link * previous; 

17: > 

18: return previous; 

19: > 

20 : 

21: /• insert - add an M n M byte elenent to front of "list" */ 

22: struct linked_list ’inserUn, list) 

23: unsigned n; 

24: struct linked_list ’list; 


25: < 

26: extern char •allocO; 

27: 

28: return (struct linked list *) alloc(n, list); 

29: > 

15: Ninclude "string.c" 

1: 

2: /• (c) copyright 1982 by The Toolsnith */ 

3: 

4: /’ cnpstr - conpare strings •/ 

5: boolean cnpstHa, b) 

6: register char *a, «b; 

7: < 

8: for( ; «a == *b*+; ’+a) 

9: if(*a «« 'NO') 

10: return YES; 

11: return HO; 

12 : > 

13: 

14: /• cpybuf - copy buffer "s" to "d" for bytes •/ 

15: unsigned cpybuf(d, s, n) 

16: register char *d, *s; 

17: unsigned n; 

18: < 

19: register unsigned i; 

20: 

21: for(i * n; i !* 0; —i) 

22: *d+* * *s; 

23: return n; 

24: > 

25: 

26: /• instr - find first occurrence in string of nenber of set */ 

27: unsigned instr(p, s) 

28: register char *p, ’s; 

29: < 

30: register char *c; 

31: 

32: for( ; • *; *♦♦) 

33: for(c * p; ’c; c’+) 

34: if(’c =* • *) 

35: goto out; 

36: out: 

37: return c - p; 

38: > 

39: 

40: /• lenstr - returns length of string "s" •/ 

41: unsigned lenstr(s) 

42: register char *s; 

43: < 

44: register unsigned n; 

45: 

46: for(n * 0; ’*♦♦ !* '\0'J ♦+») 

47: ; 

48: return n; 

49: > 

50: 

51: /• nevcpy - copy a string into newly allocated space •/ 

52: char ’newcpy(s) 

53: char •»; 

54: < 

55: extern char ’allocO; 

56: extern unsigned lenstrO; 

57: register char ’t; 

58: register unsigned n; 

59: 

60: n * lenstr(s) ♦ 1; /* include terminating HUL */ 

61: t = alloc(n); 

62: cpybuf(t, s, n); 

63: return t; 

64: > 

65: 

(Continued on next page) 


Dr. Dobb’s Journal, Number 68, June 1982 


51 








Cross-Reference Generator (Listing continued, text begins on page 50) 


string, c 

66: 

/• scnstr - scan "s M for first occurrence of "c" 

•/ 

string.c 

67: 

unsigned scnstr(s, c) 


string.c 

68: 

register char »s, c; 


string.c 

69: 

< 


string.c 

70s 

register char *t; 


string.c 

71: 



string.c 

72: 

for(t = s; *t xx *t !* e; ♦♦t) 


string.c 

73: 

t 


string.c 

74: 

return t - s; 


string.c 

75: 

> 


cref.c 

16: 



cref.c 

17: 

struct instance < 


cref.c 

18: 

struct instance *link; 


cref,c 

19: 

int line; 


cref.c 

20: 

>; 


cref.c 

21: 

union ptr { 


cref.c 

22: 

struct node *files; 


cref.c 

23: 

struct instance +lines; 


cref.c 

24: 

>; 


cref.c 

25: 

struct node { 


cref.c 

26: 

struct node *right, *left; 


cref.c 

27: 

union ptr p; 


cref,c 

28: 

char *nane; 


cref .c 

29: 

>; 


cref .c 

30: 



cref.c 

31: 

struct node nsynOol root = NULL; 


cref.c 

32: 

struct node rfile root = MULL; 


cref,c 

33: 

Ndefine ID 'a" /• identifier •/ 


cref.c 

34: 

Ndefine INTEGER '0' /• integer • / 


cref.c 

35: 



cref.c 

36: 



cref,c 

37: 

• Synbol Table handling routines * 


cref.c 

38: 

*•••*•*•••*•*••**********«****«**+•/ 


cref.c 

39: 



cref.c 

40: 

/• lookup - install nane at or belou root */ 


cref ,c 

41: 

struct node ••lookup(root, nane) 


cref .c 

42: 

register struct node ••root; 


cref ,c 

43: 

register char *nane; 


cref.c 

44: 

< 


cref,c 

45: 

register int cond; 


cref.c 

46: 



cref ,c 

47: 

if(«root !* NULL) < 


cref .c 

48: 

if((cond 3 lexcnp(nane, (*root)->nane, O)) < 

O) 

cref.c 

49: 

root = lookup(I(*root)->l*ft, nane); 


cref.c 

50: 

else if(cond > 0) 


cref.c 

51: 

root 3 lookup*J(*root)->right, nane); 


cref.c 

52: 

> 


cref.c 

53: 

return root; 


cref.c 

54: 

> 


cref.c 

55: 



cref.c 

56: 

/• add - insert entry for "nane" in tree at "root" •/ 

cref.c 

57: 

add(root, nane) 


cref .c 

58: 

struct node ••root; 


cref.c 

59: 

char •nane; 


cref.c 

60: 

< 


cref .c 

61: 

extern char •allocO; 


cref.c 

62: 

register struct node *r; 


cref.c 

63: 



cref,c 

64: 

r 3 (struct node *) alloc(sizeof(struct node), 

NULL); 

cref.c 

65: 

r->left 3 r->p.lines * NULL; 


cref.c 

66: 

r->nane 3 nane; 


cref,c 

67: 

•root 3 r; 


cref .c 

68: 

> 


cref.c 

69: 



cref.c 

70: 

/• tree_walk - walk a binary tree, doing ftn to each node 

cref.c 

71: 

tree waiktroot, ftn) 


cref.c 

72: 

register struct node •root; 


cref .c 

73: 

register (•ftn)(); 


cref .c 

74: 

< 


cref ,c 

75: 

if(root ! 3 NULL) < 


cref,c 

76: 

tree walk(root->left, ftn); 


cref.c 

77: 

(•ftn)(root); 


cref .c 

78: 

tree walk(root->right, ftn); 


cref.c 

79: 

> 


cref.c 

80: 

> 


cref.c 

81: 



cref.c 

82: 

/« use - log an occurrence of "nine" in "file" at "line" 

cref.c 

83: 

use(nane, file, line) 


cref .c 

84: 

char »nane, efile; 


cref .c 

85: 

int line; 


cref ,c 

86: 

< 


cref .c 

87: 

register struct instance »«it; 


cref .c 

88: 

register struct node ••ft, ••nt; 


cref ,c 

89: 



cref .c 

90: 

if(s(nt 3 lookup(4synbol_root, nane)) == NULL) 


cref.c 

91: 

add(nt, newcpy(nane)); 


cref.c 

92: 

if(<(nt 3 lookup(i((*nt)->p.files), file)) == 

NULL) { 

cref ,c 

93: 

if(•(ft 3 lookup*Xfile root, file)) 33 NULL) 


cref .c 

94: 

add(ft, newcpytfile)); 


cref ,c 

95: 

add(nt, (*ft)->nane); 


cref,c 

98: 

> 



97: it 3 &((«nt)->p.lines); 

98: if(»it == NULL !! (*it)->line !- line) < 

99: eit = (struct instance *) insert(sizeof(struct instance) 

100: (*it)->line = line; 

101 : > 

102: } 

103: 

104: /• get_nane - extract file nane fron line • / 

105: unsigned get_nane(line, file) 

106: register char *line; 

107: char •file; 

108: < 

109: register unsigned n; 

110: register char *delin; 

111: 

112: while (Mine == ' ' !! eline == '\t') 

113: ♦♦line; 

114: if (*1 me == '\n') 

115: n = lenstr(file); 

116: else < 

117: if(»line **'“•') < 

118: delin = M \"\n"; 

119: ♦♦line; 

120 : > 

121: else if(*line == '<') -C 

122: delin 3 ">\n M ; 

123: ♦♦line; 

124: > 

125: else 

126: deli* = " \t\n"; 

127: n = cpybuf(file, line, instrdine, delin)); 

128: filetnl = '\0'; 

129: > 

130: return n; 

131: > 

132: 

133: unsigned line count = 0; 

134: 

135: /• newline - return pointer to the next line */ 

136: char *new line() 

137* < 

138: extern unsigned getlinO; 

139i static char 1inetMAXLINE♦1]; 

140: 

141: ♦♦line_count; 

142: linetgetlintiine, NAXLINE)3 * '\0'; 


143: return line; 

144: > 

145: 

146: 

147: /• white_space - tests for blanks, tabs and consents */ 

148: boolean white_space(s) 

149: register char »<s; 

150: < 

151: if(• *s ==''!! **s == '\t') 

152: return YES; 

153: if(••s 33 '/' XX •(*s♦1) 33 '*') { /• connent •/ 

154: while(*++*s != '/') 

155: while(**+*s l= '•') 

156: if<••s 33 '\0') 

157: if(*(*s = new lineO)) 

158: —*s; 

159: else < 

140: diagnostic(N0, "unexpected EOF", NULL); 

161: return NO; 

162: > 

163: return YES; 

164: } 

165: return NO; 

166: > 

167: 

168: /• gettoken - strip leading token fron s */ 

169: char get_token(s, t) 

170: register char ms, at; 

171: < 

172: register char class; 

173: Ndefine ishex(c) ( / 0'< 3 (c>U<c)< 3 '9'H , a / < 3 (c)U(c)<«'f'i 

S'A'<»(C)1*(C)<*'F') 

174: 

175: while(white_space(s)) 

176: ♦ ♦•$; 

177: if(isalphaUM) IS **s 33 '_') < /* identifier */ 

178: class = ID; 

179: do 

180: *(t+0 * *((**)♦♦); 

181: while(i*digit(e«s) I! isalpha(**s) I! •♦• =* '.•'); 

182: > 


52 

268 


Dr. Dobb’s Journal, Number 68, June 1982 




crtf .c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
cr#f.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
cref.c 
crtf.c 
crtf.c 
crtf.c 


cref.c 

crtf.c 

crtf.c 
crtf.c 
crtf.c 
crtf .c 
crtf.c 
crtf ,c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf .c 


crtf .c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 

crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 
crtf.c 


183: else if(ees ** '"' Si •*« ** 'N") { /• string or literal •/ 

184: class * ttsj 

183: do < 

186: tsc(s); 

187: ♦ 

188: if(**s ** 'NO') 

189: if(*(*s * ntw_lint()) «* 'NO') 

190: goto out; 

191: } whllt(t*s class); 

192: ♦♦•s; 

193: ) 

194: tlst if<isdigit(*»s)) < 

195: do < 

196: class * ♦♦♦•»; 

197: class * tolower(class); 

198: > whilt(ifhtxUlass) IS class ** 'x' I! class ** 'V ! 

S class ** '.'); 

199: class * INTEGER; 

200 : > 


crtf.c 

274: 


crtf.c 

275: 


cref.c 

276: 

/• list_file - print lints within a file +/ 

cref.c 

277: 

list.f ile(ft) 

cref.c 

278: 

register struct node *ft; 

crtf.c 

279: 

< 

crtf.c 

280: 

extern unsigned itobO; 

crtf.c 

281: 

register unsigned b; 

crtf.c 

282: 

register struct instance nit; 

crtf.c 

283: 

char bufC53; 

crtf.c 

284: 


cref.c 

285: 

b * puts(" "); 


crtf.c 

286: 

b ♦* puts(ft->na«e); 

crtf.c 

287: 

/* print lint numbers */ 

crtf.c 

288: 

for(it = rtvtrse(ft->p.lines); it !* NULL; it * it->link) < 

crtf.c 

289: 

if(b == 0) 

crtf.c 

290: 

b * puts(" "); /* this and 2nd to last line 


mist agree */ 


201: tlst < 

202: class * ••»; 

203: ♦♦•s; 

204: > 

205: out: 

206: *t = '\0'; 

207: return class; 

208: > 

209: 

210: /* keyword - is M s" a reserved word in C *f 
211: boolean ktyuord(s) 

212: register char *s; 

213: < 

214: register char *»k; 

215: register int c; 

216: static char •reservedC] * ("auto", "break", “cast", "char", "continue" 

217: "default", "do", "double", "else", "extern", "float", "for", "goto", 

"if", 

218: "int", "long", "register", "return", "short", "sizeof", "static", 

219: "struct", "switch", "typedef", "union", "unsigned", "while", NULL); 

220: 

221: for(k * reserved; *k !* NULL; **k) /• reserved nust be sorted */ 

222: if((c ■ ltxcnpd, *k>) <■ 0) 

223: break; 

224: return c ■■ 0; /• equality •/ 

225: > 

226: 

227: /• xrtf - cross reference •/ 

228: xref(filt) 

229: register char *filt; 

230: < 

231: extern unsigned btoiO; 

232: register char c; 

233: char *s, tokenCHAXLINEH 3; 

234: 

233: lint.count « 0; 

236: while(*(s * neu_line())) < 

237: if<(c * get.tokends, token)) '»') 

238: whilt(c !■ '\n') < 

239: if(c ■■ ID 11 1 keyword(token)) 

240: ust(token, file, lint.count); 

241: c * get.tokends, token); 

242: > 

243: tlst if (get.tokends, token) *■ ID) < 

244: if(cnpstrttoken, "include”)) < 

245: get_na«t(s, token); 

246: ust(toktn, file, lint.count); 

247: > 

248: tlst if(cnpstr(token, "define")) < 

249: gtt.toktnds, token); 

250: ustdoktn, file, line.count); 

251: ) 

252: tlst if(cnpstr(token, "ifdtf") It cnpstr(token, "ifndtf")) < 

253: get.tokends, token); 

254: ustdoktn, file, lint.count); 

255: > 

256: tlst if(cnpstr(token, "lint")) < 

237: if (get.tokends, token) ** INTEGER) 

258: btoiltoken, HAXLINE, llint.count, 10); 

259: tlst 

260: diagnostic(NO, "Hint ", token, NULL); 

261: > 

262: tlst 

263: diagnostic(NO, "R", token, *s, NULL); 

264: > 

265: > 

266: > 

267: 

268: /* puts - output s string to STDOUT */ 

269: unsigned puts(s) 

270: char *s; 

271: < 

272: return putlind, ltnstr(s)); 

273 : > (Continued on next page) 


crtf.c 291: b ♦= puts(" "); 

crtf.c 292: bufCitob(buf, it->1int, 0)3 * '\0'J 

crtf.c 293: b ♦= puts(buf); 

crtf.c 294: if<b > HARD.UIDTH-10) < 

crtf.c 295: puts("Nn"); 

crtf.c 296: b * 0; 

cref.c 297: } 

cref.c 298: > 

cref.c 299: if(b > 6) /• non-blank line */ 

crtf.c 300: puts("Nn"); 

cref.c 301: ) 

cref.c 302: 


cref.c 303: /* print.xref - dunp cross reference table to stdout */ 

cref.c 304: print.xref(nt) 

crtf.c 305: struct node *nt; 

cref.c 306: < 

cref.c 307: puts(nt->na«e); 

crtf.c 308: puts("Nn"); 

cref.c 309: tree.walk(nt->p.fiIts, llist.file); 

crtf.c 310: > 

crtf.c 311: 


crtf.c 312: boolean naintac, av) 
crtf.c 313: register int ac; 

crtf.c 314: register char **av; 

cref.c 315: t 


crtf.c 316: extern FI0 tfcloseO, *fopen(), stdin; 

crtf.c 317: 

cref.c 318: if(ac <= 1) 

crtf.c 319: xref("<stdin>"); 

crtf.c 320: else 


crtf.c 321: while(--ac > 0) 

crtf.c 322: if(fopendstdin, *-f*av, READ) ** NULL) 

cref.c 323: diagnostic(N0, "can't open ", *av, NULL); 

cref.c 324: else { 

cref.c 325: xrefdav); 

cref.c 326: fclosedstdin); 

crtf.c 327: > 


crtf.c 328: tree.walk(synbol.root, Iprint.xref); 

cref.c 329: return YES; 

cref.c 330: > 


End Listing 


Dr. Dobb’s Journal, Number 68, June 1982 


53 

269 


Letters (Continued from page 6) 


CO Debugger (ZDT?), Version 00.16. Its 
capabilities exceed those of DDT in many 
ways, so I suspect it is better than ZSID 
in all but its lack of symbol handling. 

By using these packages, I encounter 
the following problems: 

1) The definitions module and the 
COMMON area must be INCLUDEd 
with each module assembly, signifi¬ 
cantly increasing the length of time it 
takes to assemble, and increasing the 
size of the cross-reference listing pro¬ 
duced by each module assembly. As 
well, any change affecting the relative 
positions of symbols in the COMMON 
area necessitates the reassembly of all 
23 modules. 

2) No program-wide cross-reference list¬ 
ing is possible. (At an earlier stage of 
program development, all the modules 
were coded absolute, and were 
INCLUDE files in a single module 
which was assembled absolute, produc¬ 
ing a .HEX file. This made it possible 
to generate a cross-reference listing of 
all symbol usages in all modules. As 
the program size increased, this be¬ 
came no longer possible, due to the 
Assembler running out of memory.) 

3) The debugger, although excellent in all 
other respects, lacks the ability to use 
symbol names and values from a .SYM 
file. 

Problem (1) is created to some ex¬ 
tent by the linker’s inability to perform 
more than simple addition and subtrac¬ 
tion of constants to externals. More sig¬ 
nificant, however, is the assembler’s in¬ 
ability to handle 8-bit and 3-bit exter¬ 
nals. For example, it would be desirable 
to assemble the following instruction: 

BIT FLAG,(IX + LOCN) 
where both FLAG and LOCN are exter¬ 
nals. The value of FLAG ultimately 
should appear in object code as bits 5,4,3 
of the 4th byte of' the instruction, and 
the value of LOCN should appear as the 
3rd byte of the instruction. (Microsoft’s 
Macro-80 and Link-80 3.43 seem to have 
an undocumented 8-bit capability, but 
Macro-80 always assembles the 3-bit 
reference as absolute zeroes, with no er¬ 
ror message.) 

Problem (2) is given only a very weak 
solution by the Microsoft Link-80’s /L 
option, applied to a .LIB file composed 
of the 23 .REL files. The problem with 
the /L listing is that the symbols are 


ordered as they are referenced by mod¬ 
ules, and not alphabetically. Also, multiple 
references by a module to an external 
symbol are not enumerated. What is real¬ 
ly needed is a listing of each global sym¬ 
bol, in alphabetical order, giving its defin¬ 
ing module and relative value, together 
with the name of each module referenc¬ 
ing that symbol, and the relative locations 
within that module that contain the refer¬ 
ences. 

As for problem (3), I know of no 
symbolic debugger that offers the ability 
to edit instructions (displaying each 
instruction before asking for input under 
the A command), general arithmetic ex¬ 
pression evaluation, and specification of a 
relocation constant specifying the base 
address of a module, so that relative 
addresses can be used in commands. (The 
CROMEMCO Debugger does all but 
handle symbols.) 

In summary, I seek the “ideal” 
assembly-link-debug package for Z80 de¬ 
velopment under CP/M. It should have 
the following features: 

a. Zilog/Mostek Z80 mnemonics, of 
course. 

b. Internal symbol names of at least 8 
characters. 

c. External symbol names of at least 7 
characters. 

d. 16-bit, 8-bit, and 3-bit externals. 

e. IF-THEN-ELSE conditional. 

f. Macros with string operators. 

g. STRUCT and GLOBAL features of the 
CROMEMCO Assembler. 

h. The ability to link 123 global symbols 
and 32K of object code under a 53K 
transient area. 

i. Local cross-reference within modules 
for all internal and external symbols, 
listing lower-case symbol names in 
lower-case. 

j. Global cross-reference among all 
modules for all external symbols, list¬ 
ing their values and locations of refer¬ 
ence. 

Should readers attempt to partially 
beg the question by suggesting a high- 
level language be used instead of assem¬ 
bly language, I ask that they be sure that 
it can generate the optimized high speed, 
small size, interrupt-driven code demand¬ 
ed by a Z80 real-time control applica¬ 
tion. The language should be able to be 
compiled by any CP/M system, run stand¬ 
alone without CP/M, be self-documenting 
and very readable, support data structures 
and string operations, and be available for 
purchase without restrictions regarding 


the hardware it is used with, or licensing 
fees regarding the distribution of pro¬ 
grams created under it. 

I’m even willing to consider operat¬ 
ing systems other than CP/M, provided 
they support its extensive customization 
capabilities; i.e., run on the same custom 
computer, and read the same custom- 
formatted disks (at least once). 

Hopefully the publication of this 
letter and any responses will help others 
like myself who find that their system 
programming tools fall short of the tasks 
required of them, if you have a favorite 
assembler, linker, debugger, language, or 
system that meets the above require¬ 
ments, please be so kind as to share it 
with us. 

Yours for better software, 
Wayne Farmer 
R.A. Gray, Inc. 

9181 Chesapeake Drive 
San Diego, CA 92123 

Centrifugal Forth 

Dear Marlin, 

The article on “Runic” in DDJ #65 
is one of many fulfillments of my rueful 
prophecy in DDJ #51-52 that the limi¬ 
tations of Forth would inspire creation of 
incompatible look-alikes. Others are Ron 
Loeliger’s ZIP (in his Threaded Interpre¬ 
tive Languages, BYTE Books, 1981), 
Samurai Software’s RPL (March 1982 
BYTE), and Motalygo’s PS (October 
1981 BYTE). It’s likely that in the in¬ 
creasing number of versions of “stan¬ 
dard" Forth there will be minor tinkering 
enhancements that may cause subtle in¬ 
compatibilities. Every commercial version 
tries to be “better” than its rivals, and 
this often involves optimizations to “fit” 
one of the major hardware systems or in¬ 
novations to appeal to special user 
groups. I wonder if any “virtual machine” 
concept is stong and flexible enough to 
withstand these centrifugal forces! 
Sincerely, 

H. T. Gordon 

College of Natural Resources 
University of California 
Berkeley, CA 94720 


Di. Dobb’s Journal, Number 68, June 1982 
270 


55 


BOOK REVIEWS 


Elementary Pascal 

by Henry Ledgard & Andrew Singer 

Vintage Books 

266 pages, $12.95 

Circle No. 379 on Reader Service Card 
Reviewed by D. C. Shoemaker 

Judging from the number of books 
appearing on the market these days, 
Pascal is still the language with the 
fastest-growing following. It seems that 
at least one or two introductory texts 
reach my bookseller’s shelves each 
month, and no sign of letting up. Natural¬ 
ly, some are better than others, and some 
are more advanced than others, and some 
are more specialized than others. Ele¬ 
mentary Pascal is somewhat difficult to 
classify, so let me tell you about it, and 
let you decide where it fits. 

Henry Ledgard is no stranger to com¬ 
puter programmers, or to users of Pascal. 
Responsible in part or in total for the 
“Programming Proverbs” series, including 
Pascal with Style, he is one of the better 
writers who take it upon themselves to 
get the novice programmer off on the 
right foot, and perform a valuable service 
thereby. His latest book is no exception. 

Ledgard chose to combine an 
introductory-level discussion of Pascal 
with a whimsical touch of humor, nostal¬ 
gia and mystery by setting his work in the 
late Victorian English environs so well 
known to fans of Conan Doyle’s Sherlock 
Holmes. His medium is a newly discov¬ 
ered trunkful of manuscripts by Holmes’ 
biographer, Dr. Watson, with Ledgard and 
Singer the modern-day “editors.” When I 
first picked up the book, I was rather 
skeptical that this approach would work 
at all, but work it does, and well. 

It develops that Holmes was aware 
of the work of Charles Babbage on the 
Analytical Engine, and that he has access 
to a much-improved version. It turns out 
that this improved version speaks Pascal, 
and Holmes, with his logical mind, is an 
ace programmer. Much of the book deals 
with Holmes’ introduction of Watson to 
the Engine, and to Pascal. In passing, 
Holmes is able to develop the concept of 
logical structure and problem-solving 
techniques, with the eternal Watson as 
the student and foil. 

A large number of people other than 
the authors worked very hard to insure 
the success of this approach, and they are 
given full credit in an interesting post¬ 
script at the conclusion of the book. 
A Holmes fan myself, I must admit that I 


was at least as interested in the authors’ 
approach and how they did what they 
did, as I was in the results themselves. 
They manage to capture the flavor of Sir 
Arthur’s characters quite well, partly by 
the time-honored approach of lifting 
short passages from other Holmes tales 
and recombining them into new stories. 
They are not the first to do this, but they 
have done a better job than most, partly- 
because they don’t push too hard to 
make a full-length story. 

The book consists of fourteen chap¬ 
ters, each of which develops a lesson on 
the use or application of some feature of 
Pascal in the solution of a mystery. Chap¬ 
ters are divided into two parts, the first 
being the discussion between Holmes and 
Watson about the mystery itself, stressing 
the logic of the approach to a solution, 
and the second being a more detailed 
examination of the program techniques 
used. Topics range from a discussion of 
algorithms to structure to punctuation 
to statements. Arrays, procedures and 
functions, input and output, record struc¬ 
tures and subprograms are all covered by 
means of examples. In short, all the major 
aspects of Pascal are dealt with by the 
end of the book, and an appendix called 
“Pascal at a Glance” summarizes the lan¬ 
guage. The version of Pascal used is 
almost identical to X3J9/81-003, the 
draft, proposed ISO Standard Pascal, and 
I would judge that most Pascal users will 
find the examples close enough to their 
particular versions to be useful. 

Intended as an introduction, to be 
read and used in conjunction with the 
manual for a specific implementation of 
the language, Elementary Pascal makes a 
very effective first book on programming, 
one that will help keep the beginner on 
the path to good programming practices 
and help prevent him or her from falling 
into the most common errors. Taken in 
this respect, the book is excellent, and 
even more experienced programmers, es¬ 
pecially those not familiar with Pascal, 
can benefit from it. The authors say they 
will be following up with similar books 
on other languages, and the BASIC ver¬ 
sion is already in print. It appears identi¬ 
cal to the Pascal version, with the only 
discemable differences due to variations 
in the languages themselves. A unique 
approach, and a unique book, highly 
recommended. 


Pascal Programs for Scientists 

and Engineers 
by Alan R. Miller 
Sybex 

374 pages, $16.95 

Circle No. 389 on Reader Service Card 
Reviewed by William G. Hutchison, Jr. 

Do you know some Pascal and some 
math, but have difficulty putting the two 
together? If so, Alan Miller’s new book 
Pascal Programs for Scientists and En¬ 
gineers will help. Miller is a Professor of 
Metallurgy at the New Mexico Institute 
of Mining and Technology. He has also 
written several books and numerous arti¬ 
cles on microcomputers and program¬ 
ming. 

Miller’s practical orientation is evi¬ 
dent throughout the book. Unlike some 
authors, he doesn’t begin with an axio¬ 
matic definition of Pascal or with abstract 
principles of program design. He starts 
with examples of “correct” Pascal pro¬ 
grams which produce incorrect answers 
with some current small-computer Pascal 
compilers. The examples mostly relate to 
floating-point exceptions and trig func¬ 
tions, which the example compilers do 
not handle correctly. 

The remainder of the book covers 
the usual material found in most intro¬ 
ductory numerical analysis books: ele¬ 
mentary statistics, matrices, linear alge¬ 
bra, curve fitting, integration, etc. The ex¬ 
amples are in fact appropriate for scien¬ 
tists or engineers. One thing this book 
does not do is teach why these methods 
are used. You must know a bit about 
what these techniques are used for before 
reading this book. 

Likewise, Miller does not teach 
Pascal programming here. Since there are 
so many good introductory Pascal texts 
available, that is not a serious problem. 
Since this book is not suitable for a first 
book, who would use it? It seems most 
useful either for self-study for the pro¬ 
fessional who wants to keep up to date, 
or as supplementary reading for a second 
programming course for technically ori¬ 
ented students. It might not be suitable 
as a primary text, because there are no 
formal exercises and solutions. However, 
there are many suggestions for further 
experimentation in the text. You should 
have access to a Pascal system to get the 
maximum value from the book. 

The format of the book is very at¬ 
tractive and readable. The programs are 
presented complete in boxes, with the 
reserved words in bold face type. The 


56 


Dr. Dobb’s Journal, Number 68, June 1982 

27T 




author understands that built-in func¬ 
tions like TRUNC or EXP are not re¬ 
served words and should not be printed 
bold face. That puts him ahead of some 
Pascal writers for accuracy! I found no 
typographical errors in the programs 
themselves. 

Miller uses a good structured pro¬ 
gramming style, with consistent indenting 
for readability, and sufficient comment¬ 
ing. He does not use many advanced fea¬ 
tures of Pascal like defined scalar types, 
subranges, records, pointer types, pack¬ 
ing, or recursion (except for a recursive 
version of Quicksort). Could this be be¬ 
cause the programs are very similar to 
those in the author’s BASIC Programs for 
Scientists and Engineers ? As a result of 
the author’s simple programming style, 
these programs will be useful for people 
who want to get started without spending 
a lot of time on details of Pascal, but it 
may not be suited for someone who 
wants to learn Pascal thoroughly. 

The real strength of this book is the 
appeal to the intuition of the reader. 
There is a minimum of abstract math, and 
a maximum of applications. For example, 
most numerical analysis books tell the 
reader to beware of matrices with zero 
values on the main diagonal: simple 
Gaussian elimination won’t work to in¬ 
vert them. Miller goes beyond merely 
recommending the method of pivots, he 
actually gives a complete, usable example. 
All of the programs are usable as is, and 
they are clear enough to serve as bases for 
more complex programs. The biblio¬ 
graphy at the end includes most of the 
best works in programming and numerical 
analysis for those who want to go further. 
To sum up, this is a fine book for some¬ 
one who wants to get a job done without 
a major investment in learning advanced 
techniques. 

Intuitive IC Electronics 

A Sophisticated Primer for Engineers 

and Technicians 
by Thomas M. Frederiksen 
McGraw-Hill 
183 pages, $18.50 

Circle No. 399 on Reader Service Card 
Reviewed by George W. Jolly 

A book that truly reveals mysteries 
to the uninitiated is a rare gem. Intuitive 
IC Electronics begins with the basic defi¬ 
nition of an electric current, and takes 
you through the history of diodes, tran¬ 
sistors, and integrated circuits. Mr. 
Frederiksen assumes no prior knowledge 


of semiconductors, and throughout the 
book he emphasizes pictures and plain 
English, not mathematics (thus the “in¬ 
tuitive” in the title). The mathematics in 
the book, if gathered together, would 
fill about six pages. 

Intuitive begins with the physical 
nature of electricity. If terms like “ther¬ 
mal noise,” “energy-band theory,” and 
“avalanche breakdown” seem over your 
head, you probably should read this 
book. Mr. Frederiksen makes them seem 
simple, and sprinkles information about 
the physical construction of integrated 
circuits here and there to keep things 
interesting. 

Intuitive uses the junction diode to 
explain many concepts used in other 
semiconductor devices. Bipolar transis¬ 
tors, JFETs, and MOSFETs also receive 
excellent treatment. The actual internal 
workings of these devices is fascinating. 
Mr. Frederiksen shows many small details 
to round out his presentation. Problems 
faced by the manufacturer of semicon¬ 
ductor devices are shown, some of which 
are not yet fully understood. 

Mr. Frederiksen does not leave you 
with old information. Newer devices such 
as charge-coupled devices, large dynamic 
memory chips, and electrically erasable 
read-only memory receive excellent treat¬ 
ment. The book concludes with a short 
look at the future of the semiconductor 
industry. 

Intuitive is a delightful book. Mr. 
Frederiksen has the rare ability to explain 
engineering concepts to non-engineers 
without boring us to sleep. 




Dr. Dobb’s Journal, Number 68, June 1982 
272 




For Users of Small Computer Systems 



$2.50 

($3.00 in Canada) 


OBBS IOURNAL 


Number 69 July 1982 



Video Graphics 
on the IBM-PC 

Approximation 

Algorithms 

Software Reviews : 

Word 

Processors for 
IBM’s Micro 

and even 
more! 


CP M-86 vs MSDOS 
a technical comparison 







Dr. Dobbs Journal 

For Users ot Small Computer Systems f 

July 1982 Volume 7, Issue 7 


Editor - Marlin Ouverson 
Assistant Editor - Fritzi Lareau 
Contributing Editors - 

Dave Caulkins, Dave Cortesi, 

Ray Duncan, Gene Head, 

Michael Wiesenberg 
Marketing Director - Craig Harper 
Advertising Manager - Laird Foshay 
Circulation Manager — Gloria Romanoff 
Circulation Assistants - 

Theresa O’Rourke, Terri Marty 
Art Director — Clifford West 
Production Manager — Barbara Ruzgerian 
Production Assistant — Margaret Tsai 
Typesetter - Renny Wiggins 
Cover Illustration - Non Tolson 


© 1982 by People’s Computer Company 
unless otherwise noted on specific articles. 
All rights reserved. 


Subscription Rates: $2 5 per year within the 
United States; $40 for first class to Canada 
and Mexico; $58 for airmail to other coun¬ 
tries. Payment must be in U. S. Dollars, 
drawn on a U. S. Bank. 

Writer’s Guidelines: All items should be 
typed, double-spaced on white paper. List¬ 
ings should be produced by the computer, 
using a fresh, dark ribbon on continuous 
white paper. Please avoid printing on perfo¬ 
rations. Payment is in contributor’s copies. 
Requests to review galleys must accompany 
the manuscript when it is first submitted. 
Authors may receive a copy of the complete 
writer’s guidelines by sending a self- 
addressed, stamped envelope. 

Donating Subscribers Contributing Sub¬ 
scriber: $50/year ($25 tax deductible). Re¬ 
taining Subscriber: $75/year ($50 tax de¬ 
ductible). Sustaining Subscriber: $l00/year 
($75 tax deductible). Lifetime Subscriber: 
$1000 ($800 tax deductible). Corporate 
Subscriber: $ 500/year ($400 tax deductible, 
receives five one-year subscriptions). 
Contributing Subscribers: Thomas H. 
Grohne, G. V. Elkins, Robert M. Connors, 
William J. McEown, Robert C. Luckey, 
Robert N. Stabler, DeWitt S. Brown, John 
B. Palmer, Burks A. Smith, Transdata Cor¬ 
poration, Mark Ketter, John W. Campbell, 
Friden Mailing Equipment, Howard E. 
Decker, Jim Wilson, Frank Lawyer, Chris 
Pettus, Paul Lutus, Ben Goldfarb, Rodney 
Black, Steven Weiss, Pat Phelan, John 
Brodie, James Fleming, Unison World, 
Thomas Davis, Jan Steinman. Sustaining 
Subscribers: Pete Roberts, Steven Fisher 
Enterprizes. Lifetime Subscriber: Michael 
S. Zick. 


Foreign Distributors UK & Europe: 

Hofacker-Verlag, Tegernseer Strass 18, D- 
8150 Holzkirchen, West Germany. Asia & 
Australia: ASCII Publishing Co., Ltd, 
Aoyama Building 5F, 5-16-1 Minami 

Aoyama, Minato-ku, Tokyo 107, Japan. 


CONTENTS 


Articles 

14 CP/M-86 vs. MSDOS — A Technical Comparison 

by Dave Cortesi 

Author Cortesi sets two operating systems for the IBM Personal Computer head- 
to-head. They are measured against each other, as well as compared to CP/M-80. 
Amplifications, rebuttals, amendments and corrections sent by readers will be 
part of a follow-up article later this year. 

32 Graphics on IBM's Personal Computer 

by Ray Duncan 

Not all details of the PC’s high-resolution graphics are clearly documented in the 
official manuals. This article is confined to discussion of the color/graphics inter¬ 
face in hi-res text and graphics modes. Included are a memory map, line generator 
subroutine, graphics dump routine and more. 

44 More on Checksums 

by Robert Blum 

DDJ #66 presented an article covering a number of commonly used check digit 
systems. This short piece serves as an addendum to the original, and may help 
readers perform a self-check for possible dubious conclusions they may have 
formed. 

46 PDP-1802, Part II — Hardware Simulator 

by Chris Hamlin 

Last month saw a description of this simulator. The current installment presents 
all the code needed to allow a COSMAC 1802 to run PDP-8 code. Get it running 
— the author will be contributing some useful applications software as well. 

54 Rough Approximation Numerical Algorithms 

by H. T. Gordon 

Underground lore reveals how an approximation algorithm can be designed to 
yield a value with either an absolute or relative error less than a pre-set value, over 
a defined interval of the numerical input. . . . 

66 Small -C for the 9900 

by Matthew Halfant 

This powerful language puts down roots in the 9900, thanks to author Halfant. 
Follow him down the trail to his implementation on this 16-bit machine. 


Departments — 

6 Editorial 

"Dueling DOS'" 

6 Letters 

9 CP/M Exchange 

10 Dr. Dobb's Clinic 


57 Of Interest 

61 Software Reviews 

Word Processors for the IBM PC 

76 Book Reviews 


Dr. Dobb’s Journal (USPS 307690) is published twelve times per year by People’s Computer 
Company, Box E, 1263 El Camino Real, Menlo Park, CA 94025. Second class postage paid at 
Menlo Park, California 94025 and additional entry points. Address correction requested. 
Postmaster: send form 3579 to Box E, Menlo Park, California 94025 • 415/323-3111 


4 


Dr. Dobb’s Journal, Number 69, July 1982 




LETTERS 


IBM PC — No Nits is Good Nits 

Dear Doctor: 

Robert Baer’s letter (He Picks IBM’s 
Nits, March) really did surprise me with 
his nitpicking of the IBM Personal Com¬ 
puter. I just bought one myself for soft¬ 
ware development and am quite im¬ 
pressed with it. Some observations: 

Few micros come with clock/calen¬ 
dars at all, especially as standard equip¬ 
ment. Mr. Baer doesn’t like to tell his 
what day it is, but I don’t mind. You 
have to tell a System/34 what day it is, 
too, so this must just be what IBM is 
used to. A particularly nice feature is the 
fact that the IBM PC dates each file in 
the directory with the date you saved it. 

Yes, the FORMAT program is in¬ 
credibly simple-minded. It must not veri¬ 
fy since it seems to happily format just 
about anything. I agree it needs to be im¬ 


proved. There is a format function on the 
diagnostics disk provided with the system 
that can detect a bad disk quite well. It 
even reports track and sector where an 
error is found. The format this program 
writes is just for testing, but at least it 
will test a diskette. 

I found some errors and omissions in 
the documentation too, but IBM’s docu¬ 
mentation is better than the competition. 
At least they can spell. They thoughtfully 
provide a couple of postage-paid “prod¬ 
uct comment” forms in the back of each 
manual so they must want users to tell 
them about any errors they find. 

With a processor able to address 
1000K of memory, one can be extrava¬ 
gant with it! Who cares if they want to 
reserve a mere 40K for system ROM? 
This computer uses more memory for sys¬ 
tem, DOS, and memory-mapped video 



than most “personal computers” have al¬ 
together with ten times more left over. I 
can’t imagine what a single-user applica¬ 
tion would do with all that memory any¬ 
way. 

The big disappointment is the totally 
inadequate 160K per drive disk storage, 
especially when you consider that reliable 
quad density 5” drives have been available 
for years. However, Tecmar has come out 
with a bus expansion unit and I know of 
at least one Winchester that is available 
now. I imagine the after market industry 
will soon jump in to fill the void with 
plenty of plug-in goodies. 

Sincerely, 

Burks A. Smith, President 

Datasmith 

Box 8036 

Shawnee Mission, KS 66208 


Editorial 

Dueling DOS’ 


Not long ago, individuals who had thought of writing 
software for the new IBM microcomputer threw up their 
hands in disgust. The corporation had offered royalty terms 
insulting to prime developers, including a ceiling on the total 
amount of royalties that would be paid on any single piece 
of software, regardless of its sales. A combination, I sup¬ 
pose, of angry letters and deathly silence from the people 
they had counted on awakened IBM to their error. They 
had thrown open the door to third-party vendors with 
good compensation schemes. 

Since then, IBM has sent notice that royalties will now 
be negotiated on an individual basis. This will give an edge 
to software sources experienced in negotiation and pricing, 
and allows the company to offer less attractive terms to 
novice authors with little or no track record. Such people 
may still find third-party agreements to be the most reason¬ 
able. 

The moral, if any, is that even napping giants can be 
aroused by enough Lilliputian pinpricks. 

* * * 

Owners of IBM’s Personal Computer have before them 
a short-lived dearth of software. It is a brief silence before 
the inevitable hurricane wall of products roars onto the 
scene. This is the moment of decision for many owners 
of (and most vendors for) that machine: which operating 
system will they support? 

IBM’s promotion of MSDOS will no doubt create an 
installed base of many thousands of users of that soft¬ 
ware. It fits well within Microsoft’s ongoing strategy to 
become known as more than just the world’s largest 


supplier of ROM Basic. As MSDOS’ reputation evolves, it 
will surely establish public prejudice for or against then- 
future offerings. Judging from the voracity of their market¬ 
ing campaign, this fact has not escaped Microsoft manage¬ 
ment, either. 

Meanwhile, back in Pacific Grove, Digital Research 
spent a few extra months developing CP/M-86, giving their 
competitor an unexpected lead time. Most predicted then- 
finished product would be a logical extension of the 
pervasive CP/M-80, with enhancements or changes to take 
advantage of the 8088 processor but still compatible with 
existing software. Their development work had to take 
place at a time of internal reorganization, significant staff 
growth, and marketing strategies which struggled to accom¬ 
modate their newest corporate acquisitions. 

Finally, both systems are available; it remains to be 
seen how software vendors will react to them. Because 
neither product will ultimately be confined to one machine, 
the comparison contained in this month’s DDJ carries con¬ 
siderably more weight than would otherwise be true. We 
have given a good deal of space to a topic which will be¬ 
come of even greater relevance with the passage of time. 

We have tried to keep our comparison on an objec¬ 
tive, technical level by simply lining up similarities and dif¬ 
ferences side by side. The reader may draw his own conclu¬ 
sions. By all current indicators, if a clearcut winner emerges 
from the confrontation of the two operating systems, it will 
be a winner by decision and not by knockout. 

— Marlin Ouverson 


6 


Dr. Dobb’s Journal, Number 69, July 1982 



Dear Dr. Dobb, 

I have several comments on the 
March 1982 issue of DDJ. Perhaps the 
most important of these comments con¬ 
cerns the Editorial (page 3). The Founda¬ 
tion trilogy was written by Isaac Asimov, 
not Heinlein. 

Regarding the letter from Robert 
Baer on page 4, I would agree with Nit 
#1 (DOS demands a date upon power- 
up) only if the date is not used for any¬ 
thing. If this date (and time?) is, for 
example, put on listings by a list utility 
and/or if the date/time of the last modifi¬ 
cation to a file is stored on diskette along 
with the file, then I see little reason to 
object. 

On Dr. Dobb’s Clinic (page 6), I 
believe that Microsoft BASIC for the 
TRS-80 (Level 2) uses Method 1, not 
Method 0, for searching for the target of 
a GOTO command. (Method 0 is always 
start at the beginning of the BASIC pro¬ 
gram; Method 1 modifies this to start at 
the current position if the target line 
number is higher than the current line 
number.) 

Finally, regarding 8080 Pidgin (page 
24), since Mr. Bender asks “How about 
an 8086 version? I will ask “How about a 
6809 version?” 

Sincerely, 

Jim Howell 
5472 Playa Del Rey 
San Jose, CA 95123 

A BIOS for Epson 

Dear Marlin, 

Gary Novosielski’s December article 
“For CP/M BIOS An Improved MX-80 
Printer Driver” was very commendable 
with respect to the depth of his obser¬ 
vations and the clarity of his reporting. In 
particular I think he did an outstanding 
job of documenting his driver program. 

This letter is printed on my MX- 
80F/T. When I read the article I had re¬ 
cently acquired the printer, and since 
a major reason for its purchase was my 
need for a high performance unit, I found 
his findings to be somewhat on the 
discouraging side. While I can follow his 
program with some effort, I am not yet in 
a position, assembly-language-wise to 
tackle a major modification on my H89’s 
BIOS. 

I am using The Software Toolworks 
PIE editor and TEXT formatter. I had ob¬ 
served in the manual that instructions for 
underlining and emboldening were pro¬ 
vided, also references to backspacing. 


Having Gary’s article in mind, and a feel¬ 
ing that word processors were really 
meant for Diablos or the like anyway, I 
didn’t give the possibility a whole lot of 
attention. Then a few days ago a situa¬ 
tion came up for which I required the use 
of both these features. So what the heck, 

I figured, I’ll give it a try and see if Gary 
is really right. 

He is, in spite of the appearance of 
this letter. I am delighted, because my 
less than seventy dollar word processing 
software is able to cope. TEXT lays down 
the underline and/or the text to be em¬ 
boldened at the required position (s) in 
the line on a first pass without a line feed, 
then returns to lay down the line in its 
entirety. Backspacing is available as a 
secondary procedure when for some rea¬ 
son the primary is unsuitable. 

The approach taken by PIE and 
TEXT is not, I think, the real thing in 
utilizing the Epson’s control features. But 
an enhancement is provided that I could 
have been enjoying much sooner had I 
but looked more closely at what I had. 
Which is the point of my writing. Don’t 
make assumptions. 

Regards, 

Clem Pepper 

3270-96 Caminito East Bluff 
La Jolla, CA 92037 

All in Favor . . . 

Dear Doc, 

Thank you for the interesting articles 
on TINCMP and PIDGIN. Allow me to 
second Mr. Herrold’s request (Letters, 
DDJ #67) that you publish the programs 
to test the PIDGIN macro definitions. 

I am currently implementing TINCMP 
and PIDGIN for a cassette-based H8. If, 
by any chance, any of your readers are 
interested, I would be glad to pass the 
results of my work along to them. 

Thanking your for your considera¬ 
tion, I am, 

Yours truly, 

Terrence Enger 

150 Graydon Hall Drive, #1207 
Don Mills, Ontario M3A 3B2 

P-Code vs. CP/M 

Dear DDJ and readers: 

Following SofTech’s recent an¬ 
nouncement of an 8086 version of the 
p-System, I contacted them for informa¬ 
tion on upgrade conversion from my pre¬ 
sent 8080 copy of version IV. I was in¬ 
formed that the p-System for the 8086 


was a separate product, and that a com¬ 
plete system would have to be purchased 
under a new license. 

When I originally purchased the 
UCSD system, I was under the impres¬ 
sion that by committing to an interpreted 
system I was trading execution speed for 
portability, thus protecting myself against 
obsolescence as newer processors became 
available. The literature of the time 
(1979) indicated that only an interpreter 
change would be needed when changing 
CPUs. Since then, new p-machines have 
replaced old more rapidly than new pro¬ 
cessors have appeared, and each new ver¬ 
sion entails another charge to keep li¬ 
censes current. 

Now I find that although my hard¬ 
ware is processor-independent, and in 
fact currently employs three coproces¬ 
sors, and although SofTech now supports 
native code generation for them (al¬ 
though crudely), it is practically infeasi¬ 
ble to port my existing system software 
from the 8080 which presently executes 
the p-System to the 8086 which per¬ 
forms only background I/O. To use my 
8086, I am looking at an even $1000 to 
SofTech alone in converting my operating 
system, compiler, and utilities. A kilo- 
buck, to gain minor execution-speed im¬ 
provements on a minority of my pro¬ 
grams, is rather steep. I’d get more by 
keeping the 8080 interpreter, but with 
added support for my 9511 math chip. 
Unfortunately, SofTech doesn’t want us 
doing that, either. 

At present, no other vendors support 
version IV with anything useful, so I use 
version II for everything except my own 
reinventions of the wheel. The widely 
proclaimed source compatability is, of 
course, useless to those of us without 
source licenses, and merely gives us the 
option of scrapping our software invest¬ 
ments every year or two in order to use 
functionally identical programs. 

By comparison, I have a CP/M-86 
program which interprets CP/M-80 pro¬ 
grams quite nicely, even though they are 
object-only native code. Normally I have 
no need to interpret, since I can run 
CP/M-80 in the 8080 processor, just as I 
do the p-System, but it is convenient not 
having to shuffle systems. My CP/M pro¬ 
grams written for version 1.3 prior to 
1978 are therefore alive and running on 
an 8086 in 1982, but my p-code programs 

(Continued on page 72) 


Dr. Dobb’s Journal, Number 69, July 1982 
276 


CP/M EXCHANGE 


by Gene Head 


Many DDJ readers go back at least 
as far as ALTAIR and IMSAI front 
panels, with recollections of toggling 
binary bits to enter a boot loader and 
then loading the operating system from 
a Tarbell cassette interface. Without 
a simple keyboard monitor in ROM, 
debugging in those early days took 
a very long time. One slipped bit usually 
meant reloading by hand the boot loader 
followed by reloading the operating sys¬ 
tem cassette followed by the editor or 
BASIC program, etc., etc. 

Before long, PROM and EPROM key¬ 
board monitors were available costing 
about $200. After a crash or on power- 
up, keyboard commands could be used 
to load a cassette program, examine and 
fill memory and a few other less exotic 
functions. We geared ourselves to the Tar¬ 
bell cassette and there were actually pub¬ 
lished programs for business applications 
using cassette. Hard to imagine running 
a payroll program using three or four 
passes on a cassette! Floppy disks were 
being used by a few of the hardware 
experts (sometimes amateurs but still 
experts) but most of us only dreamed 
about the affordable floppy. 

Time passed. It seemed like forever. 
The cost of the floppy remained out of 
reach of most hackers. Then the break¬ 
through — a cut-down version of the 
floppy disk called a mini-floppy appeared 
in magazine ads. The corner was turned. 
High-speed loading, with storage in the 
kilobytes was a reality. Technology has 
continued improving until today we have 
several megabyte hard disks and virtual 
disks (lots of RAM that is accessed like 
a disk one “track” and “sector” at a 
time) that cost just a little more than the 
original mini-floppies. 

Digital Research gave us CP/M with 
the main advantage of device I/O inde¬ 
pendence. It doesn’t matter to the CP/M 
programmer if the printer is a 110 baud 
TTY or a 9600 baud parallel printer. Pro¬ 
grams became transportable! But what 
about the actual transportation? 

The technology that brought us out 
of the dark ages of cassette interfaces 
also created a problem that has never 
been overcome. No standard for mini¬ 
disk recording was adopted. Exchanging 
disks to pass data from one computer to 
another is quite impractical. With soft- 
and hard-sectored disks, single- and 
double-density disks, single- and double¬ 
sided formats available, exchanging data 
between non-identical systems is impossi¬ 


Dr. Dobb’s Journal, Number 69, July 1982 


ble. One vendor of software lists no fewer 
than twenty different formats for mini¬ 
disk distribution. 

Digital Research and Lifeboat Associ¬ 
ates have done their best to keep the 
CP/M defacto standard just that, the stan¬ 
dard. CP/M formatted data can still be 
exchanged from my North Star computer 
to my friend’s Superbrain computer if we 
can find the method of transporting the 
data. Once I have the CP/M-formatted 
file of data I can access it through a simi¬ 
lar CP/M program. But how do I get it 
from the Superbrain to the North Star? 

Computer-to-computer communica¬ 
tion is one answer. 

The modem, and future telecommu¬ 
nication devices, will bring us out of the 
non-compatible “boxed information” 
dilemma and into the realm of instant in¬ 
formation access and rapid information 
exchange. Floppies gave us mass storage 
with rapid access. Telecommunications 
will broaden the field of access and give 
us rapid exchange of data. 

The Pioneers 

Like a lot of hackers, I started out in 
Ham radio. After thousands of radio con¬ 
tacts I couldn’t see much thrill in leaving 
a message on a Computer Bulletin Board. 
However, when I found a disassembler 
that provided a much-needed utility to 
my software library, and that I could 
transfer for the cost of a phone call, I 
knew there was more to modem commu¬ 
nications than creating digital graffiti. 

Ward Christensen has given us the 
CP/M modem program, MODEM. This 
program allows for the transfer of CP/M 
files between users connected via phone 
line and modem. XMODEM, as it is 
named on most every remote CP/ M sys¬ 
tem, is clearly the standard for modem 
information exchange. A simple system 
of sending data followed by a check-sum 
assures accurate and efficient data ex¬ 
change. XMODEM is very friendly and 
even a novice will be able to transfer files 
with very little head scratching. If you 
don’t own a modem, figure out a way to 
get one. Buy one cooperatively with 
friends or build one or borrow one. There 
are literally hundreds of remote CP/M 
systems with programs and data available 
for the cost of a phone call! 

Kelly Smith in Simi Valley, Califor¬ 
nia, has the largest library of public do¬ 
main software available to modem users 
I have seen. On my last connect I counted 
1628 separate CP/M files, in just under 


10 megabytes of disk space. These files 
included BASIC business programs from 
Adam Osborne, MACRO Libraries for 
programmers, utilities to test memory 
and disks and CPUs, and source code for 
languages like FORTH and STOIC, not 
to mention games and graphics. 

Information exchange is happening. 
You’re missing out if you don’t get in on 
it! 

About This Column 

Dr. Dobb’s will dedicate space regu¬ 
larly to the CP/M user, the novice as well 
as the veteran. There should be enough 
room to address many levels of expertise. 
We have a unique opportunity to really 
communicate effectively. Thanks to the 
narrow scope of interest here, we will all 
be speaking the same terms and jargon. 
I know some of the readers of this 
column can get their hands on a modem, 
if only to borrow one for the weekend. 
This will allow practical exchange of 
solutions to common problems. Finally, I 
think I will be able to handle individual 
communications. Your questions and 
comments will be serviced in one of two 
ways. 

1. Your SASE will get you the name 
of another person who can solve 
your problem or share informa¬ 
tion. 

2. Your comments and/or questions 
published here should bring a di¬ 
rect response from fellow readers. 

I realize I could be biting off more 
than I can chew, so if this gets out of 
hand I reserve the right to cancel the 
one-to-one stuff and go on to editing 
your comments and contributions. 

You will determine the content of 
this column, not me. I’ll collect your 
ideas, edit your contributions and maybe 
throw in some thoughts of my own. How¬ 
ever, this is not my column, it is our 
column. If there is not enough interest on 
your part to maintain it, we will scuttle 
the whole thing very quickly. 

What Exactly Is “Interest”? 

If you were writing this column and I 
was reading it, I would make the follow¬ 
ing contribution in the form of a letter: 

Dear Gene: 

Every time I boot my CP/M 
system it hangs up if the printer is 
not “ON” and “ON-LINE”. How 
can I fix this? Sometimes I have 

(Continued on page 67) 


9 

277 





DR DOBB’S CLINIC 




by D.E. Cortesi 


Old Business 

We continue to get a trickle of letters 
on calendar matters. Who is Gregory, 
when and why did he change the calen¬ 
dar, and by how much; who is Julius and 
what kind of dates does he get? Readers 
who are interested in these things can 
now refer to two good survey articles in 
other journals. 

The first appeared in that excellent 
British publication, New Scientist. In 
the issue dated March 25, 1982 (Volume 
93, Number 1298, page 770), Geoffrey 
Thomas nicely summarizes the astronomi¬ 
cal basis of the calendar, the problems 
Pope Gregory XIII addressed, and the 
present state of things. If you aren’t 
familiar with New Scientist, you have a 
pleasant discovery in store. Among other 
things, it carries frequent (if superficial) 
coverage of European developments in 
personal computing. Ask your library to 
stock it. 

The May, 1982 issue of Scientific 
American contains an article by Gordon 
Moyer that covers much the same ground, 
but with more detail and in greater his¬ 
torical depth (and with the heavier writ¬ 
ing style typical of SciAm). 

A BASIC Misunderstanding 

David Levy of Blacksburg, VA, 
writes to tell us of what he regards as an 
error in IBM Personal Computer BASIC. 
“There is a confusion in the boolean 
operations when lines are broken by 
colons,” he says, and demonstrates it 
with this complete program: 

FOR 1=0 TO 99:IF I MOD 2 THEN 
?I:NEXT 

which prints exactly nothing, while this 
apparently identical program — 

10 FOR 1=0 TO 99 

20 IF I MOD 2 THEN ?I 

30 NEXT 

- prints 50 odd digits as you would ex¬ 
pect. The same “bug” can be displayed 
using WHILE-WEND instead of FOR- 
NEXT. Has Levy found a glaring error 
in PC BASIC? Think about it. 

We think not. Two obscure, poorly 
documented, effects are operating in 
Levy’s program. Their interaction makes 
the program’s behavior seem very strange, 
but it isn’t wrong. 

The first thing is that, in all Micro¬ 
soft BASICS, the scope of an IF is de¬ 
limited only by the keywords THEN and 


ELSE and by the end of the line. Note, 
line, not statement. Colon delimiters and 
other keywords do not delimit the parts 
of an IF. This is spelled out in the IBM 
manual (page 4-100), implied in the TRS- 
80 Level II manual, and not said at all in 
the BASIC-80 5.0 manual. 

The second thing is that an END 
statement (or the end of the program 
text, which has the same effect) discards 
all open loops without an error message. 
One would expect that omitting line 30 
of the second example would result in 
a “FOR without NEXT” error, but it 
doesn’t. This is not stated in any of the 
three manuals we checked. 

What happens in Levy’s program is 
that a FOR loop is begun; the value of 
I MOD 2 is tested; it is zero and so the 
true-scope of the IF is skipped entirely. 
That takes the interpreter to the end of 
the line ( not to the colon!). It proceeds 
to the next line, but there isn’t one. So it 
tosses the open loop into the bit bucket 
and, with an innocent smile, says “Ok.” 

It’s just one of the little things that 
makes it such a delight to teach begin¬ 
ners to program in BASIC. Or, as Dr. 
Edsger Dijkstra says in the May issue of 
SIGPLAN Notices, “It is practically im¬ 
possible to teach good programming to 
students that have had a prior exposure 
to BASIC; as potential programmers 
they are mentally mutilated beyond hope 
of regeneration.” 

Root And Branch 

In the March issue we published a 
long discussion of the possible ways that 
a BASIC interpreter could execute a 
branch. A number of readers responded. 

Some commented on programming 
style. In general, two attitudes emerged: 
one was that there are always programs 
that need, and programmers that will use, 
whatever quirks a language allows - and 
so what? The other was that, BASIC 
being such a poor language for building 
large programs, it’s pointless to worry 
about subroutine placement. 

Well, yes, but our comments were a 
reaction to quite a number of naive write¬ 
ups in computer magazines which would 
be read by even more naive programmers. 
Here’s a recent example, typical of many: 
“Thus the second lesson is to place sub¬ 
routines as close as possible to the begin¬ 
ning of the program. Some of your pro¬ 
grams that heretofor seemed to drag on 
unmercifully could now have more zip” 
(from “Considering Space And Time In 



The Atari,” C. M. Levy and G. Levy, 
Compute!, May, 1982). Our point was 
that such advice is terribly ephemeral. 
Levy and Levy are correct, for the Atari 
of 1982. But programs, and ideas, live 
much longer than the systems that spawn 
them. How many readers of Compute! 
will still carry that “lesson” three years 
from now when they are using their 
256KB, 32-bit-CPU, Atari 9000s? 

Two readers noted that the TRS-80, 
at least, searches forward from the pre¬ 
sent line when the target line number is 
greater. This is almost our Method 1, but 
it appears that the TRS-80 starts from 
the top of the program when the target 
line is less than or equal to the present 
line number. This is surprising; it seems 
obvious that a branch to the present line, 
as in 

1000 IF INKEY$=“” THEN 1000 

should execute in minimum time, but 
Microsoft didn’t see it that way. 

Several readers pointed out a method 
that we didn’t consider. Tom Lane of 
Pittsburg, PA, describes it best. 

“When a line is tokenized, replace 
line numbers with the sequence: 

(1) The line-number-follows token 
(a byte), 

(2) Two zero bytes (a pointer to the 
target line will be placed here, 
later), 

(3) The line number itself, converted 
to binary. 

At RUN time, scan the text looking for 
line number tokens. For each one found, 
pick up the line number value, find the 
referenced line (using Method 0 or 1), 
and install a pointer to that line in the 
reserved space. If the line is nonexistent, 
put in a zero. 

“To execute a branch, just pick up 
the pointer from the token, with a check 
for zero. Aside from eliminating the com¬ 
putation and search costs, this method 
also eliminates the need to convert the 
text form of the line number to binary 
during each execution of a branch. It 
should be at least a factor of 10 quicker 
than your methods.” 

We assumed that line numbers would 
be stored as binary tokens; sorry if that 
wasn’t clear. Lane also corrected our 
analysis of Method 2. The expected num¬ 
ber of iterations should have been 3n/16, 
not n/6. 

This is certainly a workable method. 
A line-number token must contain both 


10 

278 


Dr. Dobb’s Journal, Number 69, July 1982 


a number and an address, as Lane sug¬ 
gests, not just an address as suggested by 
several other readers. The reason is that 
the interpreter must have some way of 
telling when the target line does not exist. 
An interpreter has to be able to tolerate 
the presence of such branches, diagnosing 
them when they are executed. 

That method allows only static line 
references. Dynamic references (naming 
line numbers as variables rather than con¬ 
stants) can be quite useful. When the line 
search is driven by line numbers, the 
interpreter can handle a branch to a vari¬ 
able. When the search relies on addresses, 
the interpreter has to require every 
branch target to be given as a constant. 
The Microsoft interpreters require static 
references, but take no advantage of the 
predictability that results. 

A Designer’s Experience 

The best response came from Bill 
Wilkinson of Cupertino, CA, a fellow 
columnist and the designer of several 
BASIC interpreters. All that follows is 
extracted from his letter. 

I don’t believe anyone still uses 
Method 0, the straight linear search 
through memory. Certainly even simple- 
minded Atari BASIC uses a scheme simi¬ 
lar to Method 3. [An Atari line is: 

NNNN LL SS tokens SS tokens . . . 

where NNNN is the line number in 
binary, LL the line length, SS a statement 
length.] The line length is a single byte 
which means that lines can’t be longer 
than 255 bytes. Big deal. 

Note the use of statement-length 
bytes. Most BASICS find these unneces¬ 
sary, but when we designed Atari BASIC 
we wanted to make it as flexible as possi¬ 
ble. So we allowed the user to STOP, 
change his program (!), and GOTO or 
CONTinue without losing track of 
FOR . . . NEXT loops, GOSUBs, or vari¬ 
ables. The consequence: the run-time 
stack can’t contain absolute addresses, 
since the process of changing the program 
may very well change a line’s address. In¬ 
stead the stack contains a line number 
and a statement offset within the line. 
Hence the statement length bytes allow 
us to scan to the appropriate statement 
quickly. 

Cromemco 32K Structured BASIC 

The user types in a source line. 
BASIC scans it for correct syntax, con¬ 


verts it to internal token form, and 
checks to see if it was preceded by a line 
number. For now, assume that this is a 
new line number. The tokenized line, 
with statement length bytes but without 
its line number, is simply added to the 
end of the program space. Its line number 
is added to a line number table where it 
is linked [in line number sequence] into 
a singly-linked list of all line numbers 
entered so far. 

You might presume that having a line 
number table is equivalent to Method 8, 
a hash table built when the word RUN is 
given. Not so. With Structured BASIC, 
the tokenized version of GOTO 100 looks 
something like this: 

GO L# TTTT 

[where GO is the GOTO-token, L# is 
the line-number token, and TTTT is an 
address in the line number table]. The 
•address is actually the relative address 
within the line number table for line 100. 
The line number table need not be 
searched at all, except when the line is 
first entered. Within the line number 
table [each entry appears thus: 

AAAA LLLL FFFF 

where AAAA is the address of a line in 
the program space, LLLL is its line num¬ 
ber in binary, and FFFF is the relative 
address of the next line number table 
entry in sequence]. The execution sce¬ 
nario of 100 GOSUB 200 follows: 

This is a GOSUB token. Push the cur¬ 
rent line number table address ( not the 
line number, not the line address) and 
statement offset on the run-time stack. 
Now pretend we are a GOTO instead. 

Is the next token a line-number- 
follows or a line-label-follows? It has to 
be one or the other; the syntax checker 
(which is also the tokenizer) won’t let 
anything else through. Aha; it’s a line- 
number-follows. 

Use the next two bytes as a relative 
address pointing to an entry within the 
line number table. Get the two bytes 
[AAAA, above] thus pointed to. These 
two bytes are the address of line 200 in 
the program space. Start execution there. 
That’s it! No scans, no hashing, just two 
indirect address loads. 

[There are several consequences of 
using a line number table.] Line labels: 
Structured BASIC allows code like this: 

100 Goto Totalpay 

1370 Totalpay : ... 


Labels are treated much like variables and 
are placed in the variable table (which is 
also built at entry time, not at run time). 
A special flag in the table says “this is a 
label,” and the value of a label is the ad¬ 
dress of its corresponding line within the 
line number table. So a label costs only 
one extra indirect address load. (Variables 
are tokenized as addresses within the vari¬ 
able table, and can be used with no space 
or speed penalty.) 

Renumbering: To renumber a pro¬ 
gram we have to change all references to 
each line number as well as the line num¬ 
ber in the line itself. Wait a minute; what 
references? What line number in the line? 
We simply resequence the line number 
table and all is done! 

Deleting lines: At last, some over¬ 
head. When a line is actually deleted, its 
space must be recovered from the pro¬ 
gram table. So all succeeding lines must 
be moved “down” in memory. Then we 
must go traipsing through the line num¬ 
ber table changing the addresses of lines 
which were higher in memory than the 
deleted line. But we do not have to go in 
linked-list order, so the process is reason¬ 
ably fast. Replacing an existing line is 
done by first deleting it and then adding 
it to the end of the program space as if it 
were a new line. 

Unfortunately, deleted lines remain 
in the table (they must, or we would have 
to do drastic patching on the table). But 
there’s a workable solution to this 
problem: LIST the program to disk and 
reENTER it (from disk), a not too time- 
consuming process. [Bill, why couldn’t 
you link the freed table entries into a 
chain and reuse them as new lines are 
entered? DEC] 

Relocation: Each program consists of 
five parts: the Program Space (tokenized 
lines), Variable Table, Line Number 
Table, String/Array Space, and Run¬ 
Time Stack. Any reference to an element 
in one of these spaces is nearly always by 
address. But since the various spaces 
might grow, shrink, or relocate, all ad¬ 
dresses are relative to the start of the ap¬ 
propriate space. 

For more details, see my paper in the 
proceedings of the Second West Coast 
Computer Faire. That paper discusses 
Cromemco 16K BASIC, but the princi¬ 
ples are identical. 

»»J 


12 


Dr. Dobb’s Journal, Number 69, July 1982 

279 



CP/M-86 vs. MSDOS 

A Technical Comparison 


Editor’s Note: We think that this article may stir some contro¬ 
versy among our readers. If a significant number of readers are 
moved to respond to it, we will publish a follow-up article in 
a later edition. The follow-up will air the corrections, amend¬ 
ments, amplifications, and rebuttals of respondents. 

U sers of personal computers based on the Intel 8086 (or 
8088) have a wide choice of operating systems, but re¬ 
markably little technical information on which to base 
a choice among them. In this article I intend to present a de¬ 
tailed technical comparison between the two best-known 
operating systems for these machines: CP/M-86 from Digital 
Research, and MSDOS (or IBM DOS, or SB-86) from Micro¬ 
soft. There are other operating systems for the 8086 — the 
UCSD P-system from Softech, and Oasis from Phase One Sys¬ 
tems, to name two — but I am not competent to review them. 

Sources 

I got information on the systems from several sources. My 
primary sources were vendor manuals. The IBM Disk Operat¬ 
ing System and Technical Information manuals were my pri¬ 
mary sources of information about MSDOS. These manuals are 
well-written and handsomely presented, but I found them to 
be somewhat stingy with detailed technical information on 
MSDOS. 

I supplemented my reading with two weeks of full-time 
use of an IBM Personal Computer equipped with MSDOS ver¬ 
sion 1.0, on which I wrote several programs both in assembly 
language and in BASIC. I also had access to the proceedings of 
a Microsoft seminar on MSDOS. This material mentioned 
several MSDOS utilities which were not in fact present on the 
IBM distribution disk. This article is based on MSDOS as dis¬ 
tributed for the IBM machine. 

The CP/M-86 User’s Guide, CP/M-86 Programmer's 
Guide, and CP/M-86 System Guide from Digital Research 
were my sources for that system; I also had a brief look at the 
IBM version of the CP/M-86 manual. These manuals bear no 
resemblance to the old CP/M-80 books. They are clearly the 
work of professional writers and are very good indeed. If 
Digital Research would spring for professional typesetting and 
layout, their new books would bear comparison to any. 

Information on the 8086 came from Intel’s 8086 Family 
User Manual and from Steven Morse’s excellent 8086 Primer 
(Hayden Book Company, 1980). 

CompuView Products, Inc. generously provided an evalua¬ 
tion copy of their version of CP/M-86 for the Personal Com¬ 
puter. I spent several hours with that system as well. Unfor¬ 
tunately it was a preliminary version which had not been com¬ 
pletely shaken down. Except for a few special features, I 
didn’t factor the CompuView experience into this article. 

Objectivity 

Many people equate the term “technical” with the word 
“objective,” and that with “fair” and “unbiased.” It would be 


by Dave Cortesi 

Copyright © People’s Computer Company 1982. All rights re¬ 
served. Permission is hereby granted to reproduce this article 
for any non-commercial purpose. Reproduction, in whole or 
in part, for commercial advantage is prohibited. 


14 

280 


nice if a technical comparison could automatically be an ob¬ 
jective one, but there is really no such thing as a value-free 
judgment. I have attempted to present facts in an objective 
way, and all apparent statements of fact that follow are based 
either on vendor literature or on actual machine experience. 

Whenever I draw an inference from the facts, or compare 
two sets of facts, you may assume that my conclusions are 
affected by my tastes and interests and so are not value-free. 

I have marked such extra-factual assertions with qualifiers 
like “I think,” or “it seems likely,” so you can tell the points 
at which you may want to reach a different conclusion. 

Overview 

It seems clear that both systems were modeled on CP/M- 
80. They offer the same command language, support the same 
file services, and have the same general structure, as that well- 
known system. 

CP/M-86 

CP/M-86 is a product (and trademark) of Digital Re¬ 
search, Incorporated, the company that produced CP/M-80. 
Like its parent system, CP/M-86 is composed of four parts: a 
Basic I/O System (BIOS), a Basic Disk Operating System 
(BDOS), a Console Command Processor (CCP), and a set of 
commands. 

The BIOS masks hardware dependencies from the rest of 
the system. It must be provided by the system integrator — 
the vendor or hobbyist — and is usually written in 8086 
assembly language. The BIOS provides a low-level, hardware- 
independent, interface to the disk system, and byte-level ac¬ 
cess to four logical serial devices. The mapping of the logical 
devices onto physical ports may be fixed, or the BIOS’s author 
may choose to support redirection of serial I/O through the 
IOBYTE mechansim. 

The BDOS provides I/O services to applications programs 
and to the CCP. It provides file access services, and it manages 
file directories and disk space allocation. It also offers services 
for the allocation of transient storage, and contains the logic 
needed to load a program from a disk file. 

The CCP creates the user interface to the system. It reads 
command lines from the logical terminal or from a command 
file, parses them, and carries them out. It contains the logic 
of a few commands and executes others by loading programs 
from disk. 

MSDOS 

MSDOS was commissioned by IBM and produced by the 
Microsoft Corporation from a base written by Seattle Comput¬ 
er Products, Inc. Lifeboat Associates, an important software 
vendor, has undertaken to market the system for other 8086- 
based machines, and to encourage the development of appli¬ 
cation programs for it. 

MSDOS is composed of a BIOS, a BDOS, a command 
processor, and a set of commands. The BIOS has much the 
same purpose as that of CP/M-86. In the IBM Personal Com¬ 
puter, the BIOS is in ROM. On other hardware, it will pre¬ 
sumably have to be supplied by the system integrator. 

The BDOS provides I/O services to application programs 
and to the command processor. It manages file directories and 
disk space allocation. It does not contain the logic to load pro- 


Dr. Dobb’s Journal, Number 69, July 1982 



grams from disk, nor does it provide services to allocate transi¬ 
ent storage. 

The COMMAND program creates the user interface to the 
system. It reads command lines from the terminal or from 
a command file, parses them, and carries them out. It contains 
the logic of a few commands and executes others by loading 
them from disk. 

The User Interface 

A user interface is composed of many things: the syntax 
rules of the commands; the methods of entering and editing 
command lines; the conventions used to name files and de¬ 
vices; the commands supplied with the systems; and the meth¬ 
od of executing commands in batch mode. 


Table 1 


Line-Editing Control Characters 


Edit Function 

CP/M-86 

MSDOS 

Destructive backspace 

backspace 

backspace 

Tab to next 8th column 

tab 

tab 

Mark end of line, type clean 
line, continue 

ctrl-R 

F5then F3 

Mark end of line, discard 
input, start over on next 
screen line 

ctrl-U 

ESC 

Continue input on next 
screen line 

ctrl-E 

LF 

Terminate line, deliver to 
program 

CR or LF 

CR 

Clear current screen line, 
discard input, start over 
on current screen line 

ctrl-X 

none 


Table 2 


MSDOS “Template” Editing Keys 

Edit Function 

Key 

Copy down next character of prior 
input line 

FI or -> 

Copy characters of prior line up to “x” 

F2 then x 

Copy all remaining characters of prior line 

F3 

Skip one character of prior line 

DEL 

Skip characters of prior line up to “x” 

F4 then x 

Make current input the “prior” line, 
mark end of line, start over on 
next screen line 

F5 

Toggle “insert mode,” in which invisible 
pointer to prior line does not advance 
with the visible cursor 

INS 


Command Syntax 

Both systems use the syntax of the CP/M-80 command 
language. Tokens are sequences of nonblanks delimited by 
blanks and other characters. The first token on the line is the 
command verb, either the name of a routine internal to the 
command processor or else the name of a file. The systems 
have identical rules for the formation of file references. Both 
manage the file system on a disk-drive basis; both use single 
letters to name the drives; and both assume a default drive 
which qualifies all file references where the user fails to over¬ 
ride it. Both prompt for a command with “ d >” where d is 
the drive-letter of the default drive. 

MSDOS improves on CP/M-80 in one minor respect. It 
accepts the tab and the comma, as well as the blank, as a token 
delimiter. It also accepts the semicolon as a general delimiter; 
that introduces an incompatibility with MP/M II, in which the 
semicolon delimits a file password. 

Command Entry and Editing 

The systems have similar rules for entry and editing of 
command lines. The keys used for editing are summarized in 
Table 1. MSDOS has more elaborate support for console line 
input than does CP/M-86. It retains the last input line as a 
“template.” Function keys let the user draw down parts of 
this template for use in the current line of input (see Table 2). 
It remains to be seen how these keys will be implemented on 
a non-IBM keyboard. 

In my opinion the “template” is an excellent idea, but I 
found it difficult to use in practice. The problem is that you 
have to manage two different cursors: the one you can see in 
the current line, which moves in response to ordinary key¬ 
strokes, and an invisible cursor that moves over the prior input 
line under the control of the function keys. The function keys 
that move the invisible cursor have different uses when BASIC 
is in control. 

The CompuView version of CP/M-86 for the IBM P.C. 
goes well beyond this feature. It lets you edit any line visible 
on the screen, much as you can do when working with IBM 
(or Atari, or PET) BASIC. Not only the prior command but 
any line — even a line of program output — may be edited and 
re-entered. I found this feature a delight to use. 

Conventional Names 

Table 3a shows the conventional names used for serial de¬ 
vices in CP/M-86. These names are used only as operands of 
the STAT and PIP commands. The MSDOS device names 
(Table 3b) may be used anywhere a filespec is permitted. An 
MSDOS program may open the “file” named CON: and so do 
console I/O using the BDOS services for file access. I will re¬ 
turn to this important point. 

Table 4 shows the conventional filetypes used in the two 
systems, in so far as I could determine them. Table 4 may be 
incomplete, and of course each software package brings an¬ 
other convention with it. 

Command Invocation 

In both systems, the first token of a command line be¬ 
comes the argument of a search for the code that implements 
that command. Both systems improve on CP/M-80 in the way 
this search is conducted, but in different ways. 


Dr. Dobb’s Journal, Number 69, July 1982 


15 

281 



In CP/M-86, the CCP searches its list of built-in com¬ 
mands first. If that search fails, it looks for an executable file 
on the default drive under the current user (i.e. sublibrary) 
number. CP/M-80 gave up when that search failed. CP/M- 
86 tries once more, this time searching the default drive under 
user number zero for a file with the SYS attribute. This last 
search makes the user number feature, introduced with CP/M- 
80 2.2, useful at last. You can store common commands under 
user number zero, yet still invoke them when working under 
another user number. 

The MSDOS search procedure is similar for the first two 
steps. COMMAND checks first for a built-in command. Then 
it searches the default drive for a file of type .COM. When that 
fails, it searches the default drive again, but for a file of type 
.EXE (relocatable object code). If the command still hasn’t 
been found, COMMAND searches once more, this time for a 
file of type .BAT — a text file of command lines. If that is 
found, the commands in the file are executed in batch mode. I 
think this is a great convenience. You can write a .BAT file 
and then use it like any other command. It’s not a new idea 
(mainframe systems have used it for years) but it’s a welcome 
one. 

Incidentally, I had to verify the MSDOS search hierarchy 
by experiment. The IBM documentation does not state which 
filetype has priority. The point is significant because, since 
.BAT files are last in search order, it is impossible to enhance a 
command by encapsulating it in a batch command file of the 
same name. Nor is there any point in creating a .EXE program 
with the same name as a .COM program; the latter will always 
be found first. 


Table 3a 

Logical Device Names in CP/M-86 

Name 

Designated Device 

CON: 

assigned console device 

LST: 

assigned printer device 

AXI: 

assigned auxiliary serial input 

AXO: 

assigned auxiliary serial output 


Table 3b 

Logical Device Names in MSDOS 


Name 

Designated Device 

CON: 

terminal device 

PRN:, 

LPT1. 

printer device 

AUX:, 

COM1. 

first serial port 


1 The corresponding xxx2: device is not recognized as a filespec. 


Table 4 



Standard Filetypes 


File Contents 

CP/M-86 

MSDOS 

Backup file created by an editor 

.BAK 

.BAK 

BASIC program 

.BAS 

.BAS 

Batch job (file of commands) 

.SUB 

.BAT 

Loadable machine-code program 

.CMD 

.EXE 1 

Printable file (assembler output) 

.LST 

.LST 

Object program (assembler 
output) 

.H86 2 

.OBJ 3 

Assembler symbol table 

.SYM 

.CRF 

Temporary file 

.$$$ 

.TMP 4 

1 .COM files also exist, but there seems 
them (perhaps with DEBUG?). 

to be no way to create 

2 Non-relocatable. 

3 Relocatable. 



4 Inferred from a single example (LINK). 



The Command Sets 

Each system comes with a set of commands. Some are 
built into the command program; the rest are executable pro¬ 
grams loaded from disk. When comparing the two command 
sets, keep in mind that in both systems the command sets are 
open-ended. A missing command is simply an opportunity for 
an independent software vendor. 

The CP/M-86 commands are summarized in Table 5. In 
the Type column, “B” stands for “built-in” and “T” means 
“transient.” Commands marked with an asterisk are docu¬ 
mented only in the IBM manual for the system. They support 
unique P.C. features (CompuView supplies some similar func¬ 
tions, but as part of a general configurator command). 

There are several changes from CP/M-80. The DIRS, 
COPYDISK, and HELP commands are especially welcome. 
The PIP command will now copy to, as well as from, a user 
number other than the active one — another step toward mak¬ 
ing the user-number concept useful. 

I have doubts about the TOD command. It is described in 
the User’s Guide with no mention of hardware requirements. 
It definitely exists in the IBM version of the system. But the 
System Manual says nothing about its support requirements; 
there is no BIOS entry for clock operations; and there are no 
BDOS functions to set and read the time. I infer that the TOD 
command and the system clock/calendar are not device¬ 
independent functions of the system. Rather, TOD must be an 
optional nicety supplied by the system integrator to the pat¬ 
tern of the documentation. 

The MSDOS commands are summarized in Table 6. There 
are a number of differences from CP/M-80; some are improve¬ 
ments. The DIR command, in my opinion, is not one. It dis¬ 
plays the creation date and size of each file, but it shows files 


16 

282 


Dr. Dobb’s Journal, Number 69, July 1982 





only one per line. It took me only a few days to collect more 
than 24 files on one diskette; from then on I had to hold the 
screen when I used DIR. The CP/M-80 approach of separate 
summary (DIR) and detail (STAT) displays seems better to 
me. 

The RENAME command does improve on CP/M’s REN. 
Even after two years, I still get the operands of REN back¬ 
wards. RENAME takes operands of oldname, newname, and 
where a letter of newname is ambiguous, the corresponding 
letter of oldname is copied. Thus the command “rename 
alpha.bas *.asc” renames “alpha.bas” to “alpha.asc” with 
minimal keying. 

Note that COPY, the general file-transfer utility, is a 
built-in command. This is an improvement; it makes that 
frequently-used command faster, and removes the need to 
have a copy on every disk. Unfortunately, COPY is not as 
capable as PIP. It lacks the functions of PIP’s options D, E, 

F, L, N, P, Q, S, T, U, V, and Z (the functions of PIP options 

G, H, I, O, R, and W are, for one reason or another, irrelevant 
in MSDOS). Nor can COPY concatenate files. Its lack of a 
verified-copy option is partly compensated by the presence of 


the COMP utility (but note that COMP is a transient). Similar¬ 
ly, DISKCOPY does not verify, but the DISKCOMP utility can 
be used to verify its work afterward. 

After living with them, it is my opinion that some MSDOS 
commands are unduly chatty. The COMP, DATE, DISKCOMP, 
DISKCOPY, and TIME commands all require a user response 
even when all their operands are given on the command line. 
Some of these responses are needed to support single-disk 
systems (but are required in a two-disk system regardless); 
others just seem officious. Because they demand keyboard 
input, those commands cannot be used in an unattended batch 
file. This limits the utility of MSDOS’s fine batch facility. 

Batch Command Files 

CP/M-86 provides exactly the same facility for batch exe¬ 
cution of commands as do CP/M-80 and MP/M. The SUBMIT 
command converts an editable file of command lines into an 
internal form. Before prompting the user for a command, the 
CCP looks to see if the file $$$.SUB exists on the A: drive; if 
so, the CCP takes the next command from it rather than from 


Command 

Type 

Table S 

CP/M-86 Command Functions 

CP/M-80 

Function equivalent MSDOS equivalent (comment) 

DIR 

B 

display summary of directory 

DIR 

DIR (detailed info, one file/line) 

DIRS 

B 

display summary of system files 

none 

none (can’t display hidden files) 

ERA 

B 

erase directory entries 

ERA 

ERASE 

REN 

B 

rename a file 

REN 

RENAME (easier syntax) 

TYPE 

B 

display file at console 

TYPE 

TYPE 

USER 

B 

set/display sublibrary number 

USER 

none (no sublibrary concept) 

ASM86 

T 

assemble 8086 code 

ASM (8080) 

none (assembler is separate product) 

•ASSIGN 

T 

assign logical:physical devices 

STAT 

none (logical:physical mapping fixed) 

COPYDISK 

T 

verified track-level diskcopy 

none 

DISKCOPY (does not verify) 

DDT86 

T 

debug at machine-code level 

DDT 

DEBUG (no assemble command, but disk I/O) 

ED 

T 

line-oriented editor 

ED 

EDLIN (many fewer commands) 

•FUNCTION 

T 

assign strings to Fn keys 

none 

none (DOS uses keys for template edit) 

GENCMD 

T 

make .H86 file executable 

LOAD 

LINK (a full relocating linker) 

HELP 

T 

on-line command hints 

none 

none 

LDCOPY 

T 

copy bootstrap tracks 

SYSGEN 

SYS, FORMAT 

•NEWDISK 

T 

format a diskette 

(vendor) 

FORMAT 

PIP 

T 

general file transfer 

PIP 

COPY (many fewer options) 

•PROTOCOL 

T 

set asynch-port protocol 

none 

none (with asynch support code?) 

•SPEED 

T 

set asynch-port bit rate 

none 

none (with asynch support code?) 

STAT 

T 

detailed file info, sorted 

STAT 

DIR (but not sorted) 

STAT 

T 

report disk space free 

STAT 

CHKDSK 

STAT 

T 

make drive read-only 

STAT 

none (can’t make drives r/o) 

STAT 

T 

make files read-only, hidden 

STAT 

none (no file r/o attribute) 

STAT 

T 

verify directory integrity 

none 

CHKDSK 

SUBMIT 

T 

initiate batch job 

SUBMIT 

automatic effect of command-search 

TOD 

T 

set/view date, time (see text) 

none 

DATE, TIME 

* These commands are unique to the IBM PC version of the system as supplied by Digital Research. 


18 Dr. Dobb’s Journal, Number 69, July 1982 

283 




... the XSUB feature of 
CP/M-80 was omitted from 
CP/M-86! 


the console. Only one batch file may be active at a time. The 
last line of a batch file may be another SUBMIT command. In 
this way batch files may be chained, but they cannot be 
nested. 

I was first dismayed, then profoundly disappointed, to 
find that the XSUB feature of CP/M-80 was omitted from 
CP/M-86! I cannot comprehend why this very useful facility 
was left out (nor do I understand why MSDOS didn’t imple¬ 
ment something like it). It should be very easy to create an 
XSUB for CP/M-86;its absence presents a golden opportunity 
for software vendors. 

The MSDOS command processor invokes a file of batch 
commands automatically when it cannot turn up a command 
program. The text-substitution facility of the CP/M-80 
SUBMIT utility has been incorporated into the command pro¬ 
cessor. Operands from the original user command are substi¬ 
tuted at marked points in the command lines taken from the 
file. The user marks these points with “%n” rather than with 
“$n” as in CP/M, but otherwise the facility is exactly the 
same. As in CP/M, batch files can be chained but not nested. 

Putting this function in the command processor improves 
performance, but only slightly. MSDOS avoids having to load 
a SUBMIT command, and avoids having to write the command 
file out in internal format. I expected that COMMAND would 
not have to return to the disk directory before each line, as 
CP/M does. However, it appears not to be that clever; the disk 
makes two seeks for every line of the file, just as in CP/M. 


MSDOS does not have a facility like XSUB. All requests 
for console line input must be satisfied from the console. In 
my opinion, this is an important omission. Many of the 
MSDOS commands call for stereotyped keyboard responses. 
Since there is no way to automate these responses, there will 
be fewer MSDOS batch files that can be left to run 
unattended. 

Object Program Structure 

In both systems, new commands are implemented as pro¬ 
gram files on disk. The systems take different approaches to 
the preparation of object modules. The 8086 offers many 
more features for program structure than the 8080, and both 
systems provide support for them. 

8086 Addressing 

At any moment, an 8086 object program has access to 
four different areas of transient storage. The base address of 
each area is held in a segment register. Storage operands are 
specified by naming or implying a segment register and giving 
a byte offset within the segment. The CPU computes the effec¬ 
tive address of an operand by adding the offset to the con¬ 
tents of the segment register. The four accessible segments are 
the Code segment, the Stack segment, the Data segment, and 
the Extra segment. The segments may overlap. The segment 
registers can be loaded from storage. 


Command 

Type 

Table 6 

MSDOS Command Functions 

CP/M-80 

Function equivalent CP/M-86 equivalent (comment) 

(batch) 

B 

initiate batch execution 

SUBMIT 

SUBMIT (see text) 

COPY 

B 

general file transfer 

PIP 

PIP (has more options, stiffer syntax) 

ERASE 

B 

erase directory entries 

ERA 

ERA 

PAUSE 

B 

pause in batch execution 

none 

none (but see DDJ Clinic, June 1982) 

REM 

B 

remark in batch file 

semicolon 

semicolon 

RENAME 

B 

rename a file 

REN 

REN (awkward syntax) 

TYPE 

B 

display file at console 

TYPE 

TYPE 

CHKDSK 

T 

validate directory integrity 

none 

STAT 

CHKDSK 

T 

report disk space free 

STAT 

STAT 

CHKDSK 

T 

report transient space free 

none 

none 

COMP 

T 

byte-level file compare 

none 

none 

DATE 

T 

view, set system date 

none 

TOD 

DEBUG 

T 

debug at machine-code level 

DDT 

DDT86 (no disk I/O, but assemble command) 

DISKCOMP 

T 

track-level disk compare 

none 

none (but COPYDISK does a verified copy) 

DISKCOPY 

T 

track-level disk copy 

none 

COPY DISK 

EDLIN 

T 

line-oriented editor 

ED 

ED (many more commands) 

FORMAT 

T 

format diskette 

(vendor) 

(NEWDISK in IBM; vendor in others) 

LINK 

T 

relocating linker 

none 

none (non-relocating assembler) 

MODE 

T 

set Epson printer options 

none 

none 

SYS 

T 

copy system programs 

SYSGEN 

LDCOPY 

TIME 

T 

view, set system time 

none 

TOD 


20 


Dr. Dobb’s Journal, Number 69, July 1982 




MASM cannot be 
loaded... with less than 96KB 
of storage. 


It’s difficult to avoid confusion in the use of the word 
“segment” when writing about the 8086. As I have used it so 
far, a “segment” is an area of storage whose base address is 
held in a segment register. Such a segment is always 64KB 
long, because the program can access any offset from 0 to 
64KB beyond a segment register. Usually, segments are meant 
to be much smaller. Although there are no hardware con¬ 
straints, the programmer will usually think of the Code seg¬ 
ment as being only as long as the program code, of the Data 
segment as being only the size occupied by the defined vari¬ 
ables, etc. 

Such a logical segment is referred to as a “group” in the 
documentation of both systems (although neither set of manu¬ 
als uses very consistent terminology in this area). In an object 
program, the code group is the concatenation of all code units 
in the program, the data group is the concatenation of all data 
units, and so on. In either system, a group may exceed the 
64KB that the machine can address at any moment; in that 
case it is up to the programmer (or compiler) to arrange that 
the needed part of a group falls within the addressing range of 
a segment register. 

An 8086 program can have a much richer structure than 
one for the 8080. It may consist of many different groups, 
and the groups need not be contiguous in storage. On the 
other hand, an 8086 program may be almost as simple as one 
for the 8080. If all four segment registers are set to the same 
base address, the program consists of a single segment of no 
more than 64KB. If the first 256 bytes of that segment are 
formatted like the base page of CP/M-80 storage, a very close 
emulation of the CP/M-80 environment results. 

Both operating systems provide a means of putting the 
parts of a program together into groups in an executable 
file. Both distinguish between simple one-segment programs 
and those that have a more complex organization, and both 
provide an emulation of the CP/M-80 base page. 

Program Structure in CP/M-86 

CP/M-86 programs are, at present, built with ASM86, 
the assembler distributed with the system (at the 1982 Com¬ 
puter Faire, Gary Kildall promised that a relocating macro 
assembler, Pascal, CBASIC, and PL/I would all be available this 
year). ASM86 is a minimal assembler; it supports IF (but not 
ELSE), a single-level INCLUDE, and a limited “code-macro” 
feature that allows the creation of special-purpose op codes 
(the CompuView system comes with “code-macros” defining 
the opcodes of the 8087 numerical co-processor). 

ASM86 allows code to be assembled into a single code 
group, and allows the assembly of storage definitions and con¬ 
stants into single data, stack, and extra groups. The groups 
may be given absolute addresses, or their bases may be left to 
be defined at load time. No group may exceed 64KB (note 
that this doesn’t restrict the amount of storage that a program 
can access when running; it limits the amount of code and data 
that can be defined at assembly time). 

ASM86 is not a relocating assembler. This means that 
programs cannot be assembled as modules to be linked to¬ 
gether later. It also means that, except for special-purpose 
programs that will load at a known address, all programs must 
be written to be position-independent. This is not difficult to 
do in the 8086, provided that no group exceeds 64KB. The 
segment registers are set up on entry to the program; since all 


operands are addressed relative to the segment registers, it is 
hard to avoid creating position-independent code. Only static 
inter-group references are position-dependent, because they 
must contain group base addresses. 

ASM86 produces object code in Intel Hex format as an 
.H86 file. This is made into a loadable .CMD file by the 
GENCMD utility. A .CMD file contains the binary image of 
the code, data, stack, and extra groups. It begins with a header 
record that tells the size of each group and its absolute load 
address if one was defined. The header also gives a minimum 
and a maximum allocation size for each group, so that space 
can be allocated when the group is loaded (the run-time size of 
a group may exceed its assembled size). Four additional groups 
can be defined in the .CMD header; these are allocated when 
the program is loaded, but are not initialized. 

If a .CMD file defines only a single group, the program is 
said to be built on the “8080 Model.” Such programs get spe¬ 
cial treatment when they are loaded. 

Program Structure in MSDOS 

MSDOS programs are, at present, built with BASIC or 
with a relocating assembler (other languages are promised from 
many vendors). BASIC programs are stored in the usual Micro¬ 
soft tokenized form; they need concern us no further. The 
MSDOS assembler comes as a separate product ($100 at Com¬ 
puterLand stores). Two versions are supplied, macro and non¬ 
macro. Both produce relocatable object code. 

The assemblers are large: a 53KB object file for ASM, the 
non-macro version, and a 67KB file for MASM. The smaller 
assembler fills 35% of a diskette. MASM cannot be loaded in a 
system with less than 96KB of storage. ASM loads in a 64KB 
machine but produces an “out of memory” error when given a 
source file much over 100 statements. I had to buy an expan¬ 
sion RAM card before I could assemble useful programs. In 
my opinion, this kind of bloat is inexcusable. ASM86, which is 
functionally comparable to ASM, occupies only 27KB. Since 
an overlarge program is often underfast as well, I timed ASM. 
When producing only an object file, it assembles 6.7 lines per 
second; 4 lines/sec when a listing is requested. I did not have 
a chance to time ASM86, but on my Z80 system MAC runs at 
nearly 20 lines per second. 

The MSDOS assemblers allow any number of “segments” 
(units of code or data) to be defined and given public names. 
They allow external references to code entries assembled in 
other modules. The assemblers produce a .OBJ file of relocata¬ 
ble code. The .OBJ format is said to be compatible with an 
Intel standard;it is not documented in the IBM manual. 

The output of one or more assemblies is combined into 
loadable form by LINK. LINK seems to be a very competent 
linker (it’s hard to be sure; the IBM manual tries to explain it 
to novices and ends up saying nothing much to anyone). It 
organizes the assembled “segments” into groups, of which 
there can be many. It converts offsets within “segments” into 
offsets within groups, and corrects static references to group 
base addresses so they are relative to the start of the program 
image. It resolves inter-program references. It can apparently 
search a library of object code to find missing groups, but no 
documentation is provided on the library format, nor are any 
library management utilities supplied. 

The output of LINK is a .EXE file, a relocatable program 


Dr. Dobb’s Journal, Number 69, July 1982 


21 

285 


ASM86 is not a relocating 
assembler. 


image. The image may contain static references to group 
base addresses, which must be relocated to account for the 
load address of the program. 

The Execution Environment 

Both systems contain a means of loading a program and 
setting up its execution environment: its segment registers, its 
allocated storage, and its means of communication with the 
rest of the system. In both systems, the execution environ¬ 
ment is centered on a 256-byte base page. 

The CP/M-86 Environment 

The CP/M-86 BDOS contains the logic required to load 
a .CMD file. The file header describes the groups that make up 
the program. The BDOS allocates storage for each group, and 
then loads the program image into its various group-areas. All 
the groups are put into a contiguous area if one exists, but if 
not, the BDOS will put each group where it fits. Only four 
groups are loaded from the file, but the file can specify up to 
four additional areas to be allocated for working storage. The 
size of any group will have been set by GENCMD from its 
command operands, and may be from 16 bytes up to 1MB. 

The BDOS does not relocate static base addresses in the 
code. It does place the base address and length of each allocat¬ 
ed group within the base page, which occupies the first 256 
bytes of the Data group. The length of the Data group falls at 
offset 0006 in the base page. 

The BDOS load function is available to any program, but 
its most frequent user is the CCP. After the BDOS has loaded a 
program, the CCP sets up the command operands in its base 
page in the CP/M-80 format. It sets the segment registers and 
enters the program. A program on the “8080 model,” with a 
single group, has all its segment registers set equal, so as to 
simulate the 8080 environment. Other programs receive their 
segment registers set to the base of the four basic groups; to 
address other groups, or to access beyond 64K in a group, the 
program must load its own segment registers via the base page. 

A program communicates with the BDOS by loading a 
function number into the CL register, an address into the DX 
register, and issuing an INT 224 (not by calling a vector in the 
base page; except for single-group programs, the base page is 
not part of the Code segment and so can’t be called). The 
BIOS can be called by requesting a BDOS function. The 
BIOS functions are identical to those of CP/M-80. 

A program terminates by requesting BDOS function 0 
(not by jumping to the base page offset 0000). Two kinds of 
termination are allowed. Normally a terminating program is 
removed; all its allocated storage is released. But a program 
may request that it not be removed from storage. Such a pro¬ 
gram loses control of the CPU, except as it is reentered by an 
interrupt. Ordinary programs have no use for this feature, but 
it offers a number of opportunities to systems programmers. 
The 8086 has 256 different interrupt codes, most of them 
available to software calls via the INT instruction. A device 
driver, a spooler, an XSUB, a numerical processor, or any 
other kind of software resource could be built with this 
mechanism. It would load as a command, and stay around 
permanently after “terminating” to service its particular 
interrupts. MSDOS has a similar feature, as we’ll see. 


22 

286 


The MSDOS Environment 

In MSDOS the program load function is entirely in the 
COMMAND program. MSDOS distinguishes two kinds of load¬ 
able files, .COM and .EXE. The former are single-group, non- 
relocatable programs - programs built on the 8080 model. 
They are loaded without relocation (so must be position- 
independent), and are entered with all segment registers point¬ 
ing to the base page. The IBM system provides no command 
for creating a .COM program (one could be built with the 
DEBUG program, but this is not specifically documented). A 
.COM program can be loaded by another program and then 
called. 

When a .EXE program is loaded, header information in 
the file guides COMMAND in relocating all static group-base 
addresses to account for the load address of the program. 
The entire program image is loaded contiguously at the low¬ 
est available address (there is a LINK option that will cause 
COMMAND to load one group of the program at the highest 
possible address). On entry to a .EXE program, the Code seg¬ 
ment register bases the first code group and the Data segment 
register addresses the first data group. Other groups can be ac¬ 
cessed by loading the segment registers with immediate 
operands which have been relocated. The .EXE file format is 
not documented, so a .EXE program can’t be loaded by 
another program. 

The CP/M-like base page is addressed through the Extra 
segment register. In it, the size of storage is available at offset 
0006, and the command operands are available in the usual 
places. I found two small mistakes in this emulated base 
page. The command tail at offset 008lh is not translated to 
upper case as was done in CP/M-80. This could be regarded as 
improvement, but it is a change. And the last character in the 
tail is a CR character, not an OOh byte. 

Once loaded, a program communicates with the BDOS by 
loading a function number into the AH register, an offset into 
the DX register, and issuing an INT 33 (a .COM program may 
CALL 0005h instead; there is a “far call” to the BDOS at 
that address). The BIOS can be called by issuing one of several 
interrupt codes. However, not only are these BIOS functions 
quite different from those of CP/M-80, they will probably 
differ from vendor to vendor. Use of the BIOS should be 
avoided in MSDOS (as it should be avoided in CP/M-86 as 
well, but for other reasons). 

The program terminates by setting the Code segment 
register to address the base page and issuing an INT 32 (it may 
jump to offset OOOOh in the base page; there is a INT 32 
there). The program has the option of setting DX to its end- 
offset and issuing an INT 39; this returns control to MSDOS 
but the program will be preserved in storage where it may re¬ 
spond to hardware and software interrupts. MSDOS adjusts its 
program load point upward to avoid overlaying the program. 

The MSDOS environment has one unique feature: it is 
possible for a program to trap both control-break interrupts 
and permanent disk errors. The program can defeat a user’s 
attempt to abort it, or can provide a graceful termination 
when control-break is hit. It can gain control when a disk 
error occurs and either take some action or notify the user in 
terms relevant to the application. Both of these features strike 
me as useful. They are available only at the assembly-language 
level, of course. 


Dr. Dobb’s Journal, Number 69, July 1982 


The BDOS Services 

Table 7 summarizes the BDOS functions available in the 
two systems as they compare to their model, the CP/M-80 
functions. Certain functions have been marked as having a 
“significant” incompatibility with CP/M-80. By “significant” 
I mean that some programs will require logic changes to 
operate with these BDOS requests. I think that only a mi¬ 
nority of programs will be affected, and the required changes 
will be minor — but study Table 7 and form your own 
opinion. The MSDOS file services will be discussed later. The 
only real difficulty that I see is that MSDOS does not provide 
function 12, Get Version Number. This seems a silly oversight; 
if MSDOS supported it (returning some unique value) then we 
could write programs that would run in either system. (On 
second thought, maybe that wasn’t an oversight.) 

Function 11 is an interesting case. The CP/M-80 manual 
claimed that if a byte was available, register A would be re¬ 
turned with FFh. In fact, CP/M-80 returned Olh. The MSDOS 
designers chose to implement the CP/M-80 interface as docu¬ 
mented. The CP/M-86 designers implemented the CP/M-86 
interface as it was, but documented it accurately. Which is 
more “compatible”? 

MSDOS function 41, Parse Filespec Into FCB, is a wel¬ 
come addition; it should be a great convenience to programs 
that take a filespec from a user input. It is also nice to find 
services 42-44 for operating on a system clock and calendar 
without hardware dependency. 

CP/M-86 functions 53-58 mark a major enhancement 
over CP/M-80. The BDOS controls all storage allocation. If a 
program needs more storage, it can call on a variety of BDOS 
functions to allocate or release space. This, in my opinion, is 
an important feature. Since the BDOS manages storage alloca¬ 
tion, programs are protected from each other. A program can 
acquire the storage it needs without any consideration of the 
presence of other programs. Storage can be acquired in blocks 
of any size, and the blocks need to be contiguous - the BDOS 
will allocate around any hardware holes and the program need 
not be aware of them. This feature is related to the program- 
load BDOS function. The calling program does not have to 
sub-allocate its own space to hold the loaded program; the 
BDOS allocates whatever space the loaded program needs. In 
MSDOS, storage allocation is handled in the same ad hoc way 
that it was in CP/M-80 (with the single exception that an 
interrupt server is protected from programs loaded after it). 

The File Systems 

The file system is the heart of any operating system. The 
CP/M-86 system is quickly dealt with: it is identical to that 
of CP/M-80. FCBs, directory entries, the Disk Parameter 
Block, the Allocation Vector — all are identical in layout and 
use. Your un-erasers, disk zappers, and catalog programs will 
need no logic changes when ported to CP/M-86. 

Nor will they find any improved function. This disap¬ 
points me. MP/M II and MP/M-86 both contain major im¬ 
provements in the file system. They support file passwords, 
multirecord transfers, creation and access timestamps, error 
trapping, and disk label identifiers. I don’t see why these 
things weren’t made available in CP/M-86. 

The MSDOS designers attempted to improve on the 


CP/M-80 file system while maintaining compatibility for the 
majority of programs. The changes they made fall into three 
categories: file access to serial devices, record I/O, and a 
different method of allocating disk space. (The information 
that follows is based on the IBM DOS manual only; I did not 
have time to verify it by experiment. I found IBM’s manual a 
skimpy, cryptic, and ambiguous guide in these matters. Some 
of what follows is therefore based on inference and extra¬ 
polation which I believe to be sound but which may be wrong 
in detail.) 


File Access to Serial Devices 

If one of the device names shown in Table 3b is used as a 
filename in an FCB, the BDOS will direct all operations on 
that FCB, not to a disk file, but to the device named. If the 
FCB filename is “CON:” then a request for a sequential read 
will bring keyboard data to the file buffer while a request for 
sequential output will write to the screen. This seems to me a 
most useful concept. For example, it allows a utility like COPY 
to transfer data from a file to the printer without special pro¬ 
gramming and without special command syntax. This flexi¬ 
bility is available to any utility that takes a filespec in its com¬ 
mand operands. 

The feature does not, in my opinion, replace the IOBYTE 
feature of CP/M-86; it is a different thing entirely. In MSDOS 
the user can cause a file-access program to use a serial device 
instead. In CP/M-86, the user can cause a serial access program 
to use a different serial device. In both cases the redirection is 
transparent to the program. In MSDOS, the user cannot re¬ 
assign printer output to a different port. In CP/M-86 the user 
cannot make a disk utility write to the printer instead. And in 
neither system can the user make a program that uses the serial 
I/O functions use disk data instead. 


Record I/O 

MSDOS eliminated the CP/M-80 restriction that all file 
access must be in units of 128 bytes (do keep in mind that this 
restriction affected only those who programmed in assembly 
language; all but the simplest language translator masked it). 
The BDOS will transfer a record of any size, and it will trans¬ 
fer a block of many records (up to 64KB total) on a single 
request. 

In order to access a file in units of, say, 439 bytes, you 
would set that record size in a field of the FCB after opening 
the file. When the FCB is first opened, the record size is ini¬ 
tialized to 128 bytes. As long as it is left so, the file functions 
will behave like the CP/M-80 services. The current-record 
and random-address fields will have the same meanings. 

If a file is written in 128-byte units, it can be read back 
in 128-byte units without difficulty. If a file is written in units 
that are not multiples of 128, and is then read back in 
128-byte units, the last record may be a short one (that is true 
whenever the writing and reading units differ). The BDOS 
returns a code of Olh to signal end of file, and a code of 03h 
to signal a short last record. A program ported from CP/M-80 
will treat both codes as end of file. That is why function 20 is 
marked as incompatible in Table 7. 


Dr. Dobb’s Journal, Number 69, July 1982 


23 

287 



Your un-erasers, disk zappers, and 
catalog programs will need no 
logic changes when ported to 
CP/M-86. 


If the record size is set to 1, function 35 will return the 
file size in bytes. Functions 39 and 40 allow the program to 
read or write as much as 64K bytes in one operation, a 
convenience for some applications. 

The fact that MSDOS will transfer data in other units 
than 128 bytes does not necessarily make its I/O more effi¬ 
cient than that of CP/M-86. The CP/M-80 record size is an 
artifact of its BDOS-to-program interface. Many CP/M-80 
systems, and most CP/M-86 systems, transfer data between 
computer and disk drive in larger units. My Z80 system, for 
example, usually transfers data in 1024-byte.sectors. Some 
systems read and write whole tracks; others, like the Intersys¬ 
tems “Cache BIOS” machines, buffer multiple tracks in 
storage. The transfer blocksize, channel bandwidth, and disk 
seek time govern the I/O performance, not the record size at 
the BDOS interface. By using the MSDOS multirecord read 
and write functions the programmer can ensure that it won’t 
take more than two revolutions to write a track’s worth of 
data — an effect that isn’t difficult to achieve under CP/M- 
80, either. 

Disk Space Allocation 

The MSDOS method of space allocation is completely dif¬ 
ferent from that of CP/M-80 (see box below). Disk space is 
allocated in units which the IBM manual calls “sectors” 
(I’m not sure that these units now, or will always, corre¬ 
spond to physical sectors; hence the quotes). Each sector 
is 512 bytes long. There are 313 sectors on a diskette in the 
IBM system, of which the first 8 are reserved for system 
purposes. The rest are numbered from 2 up to 304. A File 
Allocation Table (FAT) is kept in a reserved sector. It is a 
vector of 305, 12-bit entries. Each entry represents the 
status of the corresponding sector, with an entry of OOOh 
standing for a free sector and FFFh meaning the last sector 
of a file. 

MSDOS maintains a directory of 32-byte entries, just as 
CP/M does. However, an MSDOS entry contains no data map; 
it holds only the number of the first sector assigned to the file. 
Call that number F\ then the number of the following sector is 
in FAT[5), and so on through the FAT to the last sector of 
the file, for which FAT[F] =FFFh. In order to allocate a sec¬ 
tor, the BDOS finds the first FAT[A] =000h, and adds sector 


N to the file. Duplicate copies of the FAT are stored in re¬ 
served sectors; a copy of the FAT is kept in storage at all 
times. 

Because the FAT is in storage, the BDOS can always find 
the number of the next sector of a file without reading the 
directory. Because most allocation data is in the FAT, a file 
never requires more than one directory entry, and that entry 
has room for a creation date and a file size. An entry also has 
room for the eleven file attribute bits supported by CP/M 
and MP/M, but MSDOS does not implement these. An MSDOS 
file can be “hidden,” equivalent to the SYS file attribute, but 
not by any command available to the user. So far as I could 
determine, the read-only, archive, and application-defined at¬ 
tributes of CP/M-80 are not supported. Because the directory 
entry differs from CP/M-80, any CP/M-80 program that looks 
at the attributes, extent number, record count, or data map of 
an FCB will have to be redesigned for MSDOS. 

It is interesting to calculate maxima for the MSDOS 
allocation scheme. A FAT element is a 12-bit integer. There 
can be at most 4,093 unique sector numbers (002h-FFEh). A 
maximum FAT would occupy 6,144 bytes in storage and 
12,288 bytes on disk (two copies). Such a FAT could track 
the allocation of 4,093 sectors, or 2,095,616 bytes of data if 
a sector is 512 bytes. Unless some parameter changes, the larg¬ 
est possible MSDOS file will contain only 2MB of data, one- 
fourth the maximum size allowed by CP/M-86! 

This is strange, for the record-size field in an MSDOS 
directory entry is a 4-byte integer. In order to allocate a file 
of 2 31 (2.1 billion) bytes, MSDOS would have to use either a 
FAT with 4,194,304 elements or a sector size of 524,672 
bytes. Or it could compromise on a FAT of 65,533 entries 
tracking “sectors” of 32KB each. 

Mind you, the IBM manual says nothing to suggest that 
the FAT could have more than 305 entries, or that a FAT ele¬ 
ment might be other than 12 bits wide, or that a “sector” 
would ever be other than 512 bytes. It is my inference that 
one or more of these things must be a system parameter. For 
instance, to control a double-sided, double-density, 8-inch 
diskette (1.26MB), the FAT must have 2,464 entries. To con¬ 
trol a SMB hard disk, either the FAT entries must be 16 bits or 
the sector size must rise to 2 KB. 


For readers who don’t know how CP/M-80 allo¬ 
cates space, here is a summary. CP/M divides a disk into 
a number of blocks B, each of a size S. The blocks are 
numbered from 0 to 5-1. The first D blocks are assigned 
to be a directory. On a single-density 8-inch diskette, 
5=243, 5=1024, and D= 2. The numbers vary with the 
disk hardware; they are chosen by the author of the 
BIOS. 

A file is represented by one or more directory 
entries. An entry contains a data map, which is simply a 
list of the numbers of the blocks that hold data for that 
file. One data map accounts for one extent of data - 
usually 16KB, but the size depends on 5 and 5. A file 


24 

288 


that exceeds one extent has more than one directory en¬ 
try; each entry has a unique extent number so the file 
can be retrieved in order. When the program reads past 
an extent boundary the BDOS must return to the direc¬ 
tory for another data map. 

When it first accesses a disk, CP/M builds a vector of 
5 bits, setting the first D bits to 1 and the rest to 0. Then 
it reads all directory entries. For every block number in 
a data map, the corresponding bit is set to 1. The zero 
bits that are left represent free blocks; the index of the first 
0-bit is the number of the first free block. That number is 
put in the data map of the next file that needs a block of 
space. 


Dr. Dobb’s Journal, Number 69, July 1982 



Table 7 


nbr 

CP/M-80 Function 

MSDOS Differences 

CP/M-86 Differences 

0 

terminate program 

CS must address base-page prefix 

*DL must contain a parameter 

1 

CON: byte input, tab expand., no 




A C check 

tabs returned, ctl-break tested 


2 

CON: byte output, tabs expanded 

* tabs written, bkspce is destructive 


3 

RDR: byte input 

input from asynch port # 1 

input from AXI: (name change only) 

4 

PUN: byte output 

output to asynch port # 1 

output to AXO: (name change only) 

5 

LST: byte output 



6 

CON: unedited output/input 




without echo 


also supports kbd-status test 

7 

get IOBYTE 

* direct console input 


8 

set IOBYTE 

* direct console input 


9 

CON: strings output, tabs expanded 

tabs not expanded 


10 

CON: line input with editing controls 

* returned line ends in CR, not OOh 


11 

CON: input status, returns 00/01 

returns FF/00 (see text) 

returns 01/00 (see text) 

12 

get system, version numbers 

* clear template and do kbd input 


13 

reset all drives 

"“also resets file transfer address 


14 

select a drive 

also returns number of drives 


15 

open (an extent of) a file 

* extent number not relevant 


16 

close (last extent of) a file 



17 

search for first matching FCB 

* full-search option not supported 


18 

search for next matching FCB 

*full-search option not supported 


19 

delete file 



20 

sequential read of 128 bytes 

* partial-record return code possible 


21 

sequential write of 128 bytes 

other record sizes supported 


22 

create (first extent of) a file 

system prevents duplicate filenames 


23 

rename file 

“?” in new name copies old name 




byte 


24 

get bit map of active drives 

*not supported 


25 

get default drive’s number 



26 

set file transfer address 

sets both segment base and offset 

sets offset only; see #51 

27 

get address of disk allocation vector 

returns address of F.A.T. 


28 

make the current drive read-only 

* not supported 


29 

get bit map of read-only drives 

*not supported 


30 

set file attributes 

*not supported 


31 

get address of disk parameter block 

*not supported 


32 

get/set user (sublibrary) number 

*not supported 


33 

direct-access read of 128 bytes 

other record sizes supported 


34 

direct-access write of 128 bytes 

other record sizes supported 


35 

get size of file in 128-byte units 



36 

get direct-access file position 



37 

reset selected drives 

*set an 8086 interrupt vector 


38 

n.a. 

create a program base page 

n.a. 

39 

n.a. 

direct read multiple records 

n.a. 

40 

as #34, but fill new blocks with zero 

* direct write multiple records 


41 

n.a. 

parse filespec string into FCB 

n.a. 

42 

n.a. 

return system date 

n.a. 

43 

n.a. 

set system date 

n.a. 

44 

n.a. 

return system time 

n.a. 

45 

n.a. 

set system time 

n.a. 

50 

n.a. 

n.a. 

call BIOS function 

51 

n.a. 

n.a. 

set file tranfer segment base 

52 

n.a. 

n.a. 

get file transfer base and offset 

53- 

58 inclusive: n.a. 

n.a. 

calls to get, free transient storage 

59 

n.a. 

n.a. 

load a program from a .CMD file 


*a significant difference from CP/M-80 function which might require logic changes in more sophisticated programs. 


Dr. Dobb’s Journal, Number 69, July 1982 






... claims that it could cope 
with files of 2 31 bytes are, in my 
opinion, absurd. 


I draw three conclusions from these calculations. First, 
as distributed and documented by IBM, MSDOS has a maxi¬ 
mum file (and disk) size of 2MB, less than that of CP/M-86. 
Second, it could be modified to support much larger files, but 
the interface to do that is not documented (unlike the BDOS- 
BIOS interface of CP/M-86). Third, MSDOS cannot practical¬ 
ly support files very much larger than those ot CP/M-86; 
claims that it could cope with files of 2 31 bytes are, in my 
opinion, absurd. 


Table 8 

Extensions to CP/M-80 That Do NOT Appear 

Volume label support; volume-id verification; use of 
volume-id in place of a drive-letter in commands. 

Multi-volume disk files. 

System-supported archival storage; catalog of archived 
files; archive command to back up only changed files. 

Clock-based job scheduling; commands executed at pre¬ 
selected times and dates (such as archive backup runs). 

Multiple directories; cross-volume directories; directory 
as a standard filetype with creation and update utilities; 
archival backup of groups of files as named in a sub¬ 
directory. 

True I/O redirection (transparent redirection of serial 
I/O requests to a disk); serial output redirection to 
another program’s input; DOS-supported spooling of 
serial I/O; asynchronous printing scheduled without con¬ 
stant user intervention. 

BDOS functions for device-independent control of cur¬ 
sor and screen; BDOS function to return screen dimen¬ 
sions (1 x 80 when screen output redirected). 

Support of (1) default operand values, (2) conditional 
tests, (3) iteration, in batch command language; nested 
batch files. 



Table 9 

Significant Regressions from CP/M-80 Function 

CP/M-86 

MSDOS 


no serial I/O redirection 


no command to make a 
file r/o 

XSUB facility omitted!!! media incompatible with 

other systems 


no archive attribute in 
files 


no XSUB facility 


Summary 

Thus far in this paper I have laid the systems out for you 
side-by-side. Now let’s look at them head-to-head. I invite 
you to participate in this: feel free to add or delete entries 
from the tables I’ll present, or even to switch entries from one 
column to another. 

CP/M-80 was a sturdy little tyke, but by no means was it 
a complete operating system. After examining these descend¬ 
ants of CP/M-80, my strongest feeling is one of disappoint¬ 
ment. It disappoints me that two high-powered software 
houses have worked so hard to produce only . . . two more 
CP/Ms. Consider Table 8, a very incomplete list of things, all 
needed, all feasible, that do not appear in either system. 

Now consider Table 9, which summarizes the points in 
each system that (I think) represent significant regressions 
from the capabilities of CP/M-80. 

For a more cheerful view, see Table 10, which lists what I 
feel are the significant improvements on CP/M-80. It only 
bothers me that the two columns of Table 10 are so different 
from each other. 

Finally, let us compare the systems directly. Table 11 lists 
what I feel are the significant advantages of CP/M-86 over 
MSDOS — wait for it! - while Table 12 lists what I see as the 
significant advantages MSDOS has over CP/M-86. Ok, now 
look. 


Table 10 

Significant Improvements on 

CP/M-80 Functions 

CP/M-86 

MSDOS 

Documentation vastly 

Command documenta- 

improved. 

tion clear, handsomely 

Searches for commands 

presented. 

under user code zero. 

Automatic batch execu- 

No I/O on warm start; 

tion. 

A-disk need not be boot- 

No I/O on a warm start; 

able. 

A-disk need not be boot- 

DIRS to display system 

able. 

files. 

Liberal rules for disk 

HELP command pro- 

change. 

vided. 

Consistent support for 

PIP copies to other user 

1 -drive systems; COPY 

codes. 

is a built-in command. 

ST AT validates the direc- 

RENAME syntax much 

tory. 

better. 

Coherent storage- 
management scheme 
handled by BDOS. 

Print-screen function 
(may be specific to IBM 
hardware). 

Easy to implement 

Multi-record I/O requests. 

interrupt-servers. 

Serial device may be 
treated as files through 

FCB. 


26 

290 


Dr. Dobb’s Journal, Number 69, July 1982 





The Last Word 

I am not going to present a recommendation as to which 
system you should prefer. This has been a technical compari¬ 
son. Your choice of an operating system will be determined by 
a lot of considerations, only a few of them technical. I’m not 
even going to tell you which I would prefer to have in my own 
machine, because I don’t want that taken as a recommenda¬ 
tion by someone in different circumstances than mine. 

I will make these recommendations. Software developers: 
these systems are similar enough that your products can run 
on both with only minor changes. Modularize your programs 
so as to encyst every system call in a subroutine of your own. 
Include those units from a library (cystem.lib?). Then with a 
single library change you can port between systems, and you 
will not be dependent on the choices of the OEMs that built 
the systems. Hackers and homebrewers: consider which sys¬ 
tem is the most up-front with information on its internals. 
That’s the one you can most easily adapt to your peculiar 
hardware. 

And to ordinary users: you really don’t care, do you? You 
should be looking at the applications that are available. Choose 
your applications first, then get the system that runs all of 
them. If possible, wait at least another twelve months; the ap¬ 
plications market for all 8086-based systems is just about to 
explode. BSj 


Table 12 

Significant Advantages of MSDOS 
Over CP/M-86 

1. Automatic invocation of batch command files. 

2. Liberal rules for changing diskettes. 

3. File-transfer utility is a built-in command. 

4. Consistent support for single-drive systems. 

5. Prior command can be recalled, re-entered. 

6. Serial device names can be used as command oper¬ 
ands where the program expects a filespec. 

7. Full relocating linker supplied with system; system 
contains a relocating loader. 

8. File system supports various record sizes and multi¬ 
record access requests. 

9. Lower overhead on random file access. 

10. Control-break and disk error trapping. 

11. BDOS functions for system clock/calendar. 

12. Upgrade path to XENIX promised. 



Table 11 


Significant Advantages of CP/M-86 

Over MSDOS 

1 . 

I/O redirection through IOBYTE. 

2. 

R/O protection for files and drives, via user com¬ 
mands. 

3. 

File-transfer utility much more capable (PIP vs. 
COPY). 

4. 

Consistent, extensible scheme of file attributes. 

5. 

More options for directory display (DIR, DIRS, 
STAT). 

6. 

Coherent storage-management scheme built into 
system. 

7. 

Assembler (non-macro, non-relocating) supplied 
with system; compiles sizable programs in 64KB 
machine. 

8. 

8-inch diskettes interchangeable with CP/M-80, 
MP/M-80, MP/M-86 systems and some others; 

5 -inch diskettes interchangeable with some systems, 
hardware permitting. 

9. 

Interrupt servers (spoolers, device drivers, XSUB?) 
easy to implement. 

10. 

Adaptable to all disk hardware via well-documented 
interface. 

11. 

Upgrade path to MP/M-86 available now. 


Dr. Dobb’s Journal, Number 69, July 1982 


27 

291 





Graphics on IBM’s 
Personal Computer 


T he IBM Personal Computer is available with two types of 
video output: a monochrome 80 column by 25 line text- 
only display, and a color/graphics display with text and 
bit-mapped graphics capabilities. Both are memory mapped; 
software drives the displays by simply writing character codes 
or bit patterns directly into a designated area of RAM. The 
memory is dual ported and is accessed “from the back” by the 
Motorola 6845 chip which controls the monitor. 

Referring to the memory map in Figure 1, you will notice 
that the monochrome display occupies 4Kbytes starting at 
B0000H, and the color/graphics display is assigned 16Kbytes 
starting at B8000H. In addition, IBM has reserved a total of 
112 Kbytes of address space as “graphics/ display buffer” 
which implies plans for release of video displays with much 
higher resolution at some later date. 

The discussion in this article will be confined to use of the 
color/graphics interface in high resolution text and graphics 


by Ray Duncan 


FE000 

ROM "BIOS" 

F4000 

System ROM 

Standalone BASIC etc. 


Reserved 

B8000 

Color/graphics display buffer, 16Kbytes 


Reserved 

B0000 

Monochrome display buffer, 4Kbytes 

AOOOO 

Reserved 

40000 

"Future expansion" 

Currently available user 
memory area, 256 Kbytes 

00000 


Figure 1 

Memory map of the IBM Personal Computer. 


modes. Although the version of BASIC supplied with the 
Personal Computer contains powerful high-level commands 
for both text formatting and creation of graphic images, this is 
hardly a suitable language for the many utilities, editors, and 
games that all of you ambitious programmers are thinking 
about. 

Color/graphics Board High-Res Text Mode 

In this mode an 80 column by 25 line text area is dis¬ 
played. Characters are 5 by 7 dot patterns defined in an 8 by 8 
box with one line of descender for lower case. The cursor 
home position, (X,Y)=(0,0), is considered to be the upper left 
corner of the screen (see Figure 2). 

Each character display position is allotted two bytes in 
the RAM buffer. The first byte (even address) is the ASCII 
code of the character, which is translated by a character 
generator into a dot matrix pattern for the screen. The con¬ 
tents of the odd address is called the attribute byte. Several bit 
fields in this byte control such features as blinking, highlight¬ 
ing, and reverse video (see Figure 4). 

A hex and ASCII dump of part of the video map in text 
mode is shown in Figure 5. Since each screenful of text 
takes (80 columns * 25 lines * 2 bytes per character) = 4000 
bytes, and the color/graphics interface has 16Kbytes of 
on-board memory, the video map is divided into 4 Kbyte 
“pages.” The portion of memory currently being displayed is 
called the “active page.” While the user is viewing one portion 
of text, a program can be building up a new text image in 
another part of the buffer and then cause a new image to 
appear instantaneously by simply selecting a new active page. 

The memory address of any character in the display may 
be calculated as the base address of the RAM buffer, plus the 
current active page number times the size of the page, plus the 
line number (Y coordinate) times 80 characters per line times 
2 bytes per character, plus the column number (X coordinate) 
times 2 bytes per character, i.e.: 

address = B8000H + (page * 1000H) + ((Y * 50H + X) * 2) 

High-Res Graphics 

There are two levels of graphics available to the program¬ 
mer: 320 x 200 black and white or color and 640 x 200 black 
and white. Only the latter has sufficient resolution for any 
sophisticated graphing and design work, although the color 
capabilities will undoubtedly be very popular for sales demon¬ 
strations, games, and flashy business programs. 

In high resolution black-and-white mode, each bit of the 
memory map is a “pixel” which is either on or off and cor¬ 
responds directly to a dot on the screen. When addressing the 
display, the “X” coordinate giving the horizontal displacement 
must be in the range 0 to 639, and the “Y” coordinate giving 
the vertical displacement must be in the range 0 to 199. The 
home position, (X,Y)=(0,0), is the upper left corner of the 
screen (see Figure 3). 

Translating an (X,Y) coordinate into a physical memory 
address is more complex in graphics mode than in text mode. 
Each successive 80 bytes, or 640 bits, consists of one horizon¬ 
tal scan line. Within each byte, the bits map one-for-one 
onto points, with the most significant bit corresponding to the 
leftmost displayed dot of a set of 8 dots, and the least signifi¬ 
cant bit corresponding to the rightmost displayed dot of a set 


32 

292 


Dr. Dobb’s Journal, Number 69, July 1982 




of 8 dots. The memory map is set up so all the even Y coordi¬ 
nates are scanned as a set alternating with all of the odd Y 
coordinates. 

The byte address containing a particular (X,Y) coordinate 
may thus be calculated as: 

address = B8000H + ((Y AND 1) * 2000H)+ 

(Y/2 * 50H) + (X/8) 

Once the correct byte is extracted, the bit number may be 
calculated as: 

bit number = 7 - (X MOD 8) 

where bit #7 is the most significant bit, and bit #0 is the least 
significant bit. It is easiest to build an eight-byte table or 
array of bit masks, and use (X AND 7) to extract the appro¬ 
priate entry from the table. 


IBM Video Drivers 

A complete set of text and graphics drivers are present as 
part of the machine’s ROM software. These routines are 
accessed through a software interrupt trap and provide display 
mode selection, cursor addressing, display of text, scrolling, 
and point plotting. Documentation of these services is virtually 
nonexistent in the IBM manuals except for the ROM BIOS 
program listing itself in the back of the Technical Reference. 

The most elegant feature of the video support routines is 
that most of them may be called by user software without 
regard for the display controller or video mode in use. The 
subroutines determine the current type of display and perform 
all necessary address translation, also fetching bit patterns for 
characters from a resident table if the program wishes to 
display text in graphics mode. Naturally one must pay for this 
flexibility in speed; the user can readily write much faster 
drivers for dedicated application programs where the video 
display mode is known in advance. 



Cursor addressing, color/graphics interface in high-resolution 
text mode (mode 3). 


The common calling format for the video routines is as 
follows: 

MOV AH,function-number ; AH always determines call type 

;load other 
; registers with 
; call-specific parameters 

INT 1 OH ; trap to service routine 

Although each function call has different arguments and 
returns different results, some general rules can be applied: 

• The BX, CX, and DX registers and all of the segment regis¬ 
ters are preserved across video driver calls; the contents of 
all other registers may be destroyed. 

• The X coordinate or column number is passed in register 
CX or DL. 

• The Y coordinate or row number is passed in register DX or 
DH. 

• The display page, if any, is passed in register BH. 

• The character or pixel value to be written is usually passed 
in register AL. 

Details of Video Driver Services 

Function 0 set video mode 
CALL with: 

AH = 0 

AL = 0 40 x 25 black and white text 

1 40 x 25 color text 

2 80 x 25 black and white text 

3 80 x 25 color text 

4 320 x 200 color graphics 

5 320 x 200 black and white graphics 

6 640 x 200 black and white graphics 

7 monochrome text display 



Point addressing, color/graphics interface in high-resolution 
graphics mode (mode 6). Black and white display, 640 x 200 
resolution. 


Dr. Dobb’s Journal, Number 69, July 1982 


33 

293 





(Continued from page 33) 

Function 1 — sfet cursor type 
Call with: 

AH = 1 

CH = bits 0-4 starting line for cursor 
CL = bits 0-4 ending line for cursor 

Note: Hardware will always cause blink. Setting bit 5 or 6 in 
CH will have unpredictable effect on cursor. 


Function 2 — set cursor position 
Call with: 

AH = 2 

BH = page number (must be zero for graphics modes) 
DH = row (Y coordinate) 

DL = column (X coordinate) 

Note: (X,Y)=(0,0) is upper left corner of screen. 

Function 3 — read cursor position 
Call with: 

AH = 3 

BH = page number (must be zero for graphics modes) 
Returns: 

DH = row (Y coordinate) 

DL = column (X coordinate) 

CH = starting line for cursor 
CL = ending line for cursor 

Function 4 — read light pen position 
Call with: 

AH = 4 
Returns: 

AH = 0 if light pen not down / not triggered 
1 if light pen down and triggered 
DH = character row (Y coordinate, 0-24) 


7 

6 5 4 

3 

2 1 0 

BL 

Background 

I 

Foreground 


Background Foreground 
000 000 

000 001 

000 111 

111 000 

BL = blink 
I = Intensity or “highlight” 


Figure 4 

Attribute byte for each displayable character in text mode. 
Blink, intensity, and foreground/background attributes may 
be used in any combination. In reverse video, the intensity bit 
has the opposite effect from what you would expect: the con¬ 
trast of the character is halved instead of doubled. 


No display 
Underline 
Normal video 
Reverse video 


DL = character column (X coordinate, 0-79) 

CH = pixel row (Y coordinate, 0-199) 

BX = pixel column (X coordinate, 0-319 or 0-639 de¬ 
pending on mode) 


Function 5 — select active display page 
Call with: 

AH = 5 

AL = page value 

Note: This function is legal only in text display modes. The 
page number may be in the range 0-7 for modes 0 to 1, in the 
range 0-3 for modes 2 and 3. 

Function 6 — scroll window of active page up 
Call with: 

AH = 6 

AL = number of lines to scroll, new lines are blanked at 
bottom of window. If AL=zero, entire window is 
blanked. 

CH = Y coordinate, upper left corner of window 
CL = X coordinate, upper left corner of window 
DH = Y coordinate, lower right comer of window 
DL = X coordinate, lower right comer of window 
BH = attribute to be used for blanked area. 

Note: Function 6 and 7 have tremendous potential for sup¬ 
port of object-oriented editors and languages. 


Function 7 — scroll window of active page down 
Call with: 

AH = 7 

AL = number of lines to scroll, new lines are blanked at 
top of window. If AL=zero, entire window is 
blanked. 

CH = Y coordinate, upper left corner of window 
CL = X coordinate, upper left corner of window 
DH = Y coordinate, lower right corner of window 
DL = X coordinate, lower right corner of window 
BH = attribute to be used for blanked area. 


Function 8 — read attribute and character at cursor 
Call with: 

AH = 8 

BH = display page 
Returns: 

AL = character 

AH = attribute byte (text modes only) 

Function 9 - write attribute and character(s) at cursor 
Call with: 

AH = 9 

AL = character to write 
BH = display page 
BL = attribute 

CX = count of characters to write 

Notes for functions 9 and 10: writing multiple characters by 
setting the replication factor in CX will only produce a valid 
result for the current row. All values of AL result in some sort 


34 


Dr. Dobb’s Journal, Number 69, July 1982 




of text or graphic character appearing on the screen; i.e., the 
codes normally thought of as line feeds or carriage returns do 
not have any effect on the cursor. After a character is written, 
the cursor must be moved explicitly to the next desired posi¬ 
tion using function 2. The user is responsible for detecting 
end-of-row or end-of-screen and for taking the appropriate 
action. 

Function 10 — write character only at cursor 
Call with: 

AH = 10 

AL = character 

BH = display page 

CX = count of characters to write 

Function 11 — set color palette 
Call with: 

AH = 11 

BH = color palette ID being set (0-127) 

BL = color value to be used with that color ID 
Note: Color ID=0 selects the background color (0-15 in 
graphics mode, and 0-31 in text mode). 

Function 12 - write dot 
Call with: 

AH = 12 

AL = color value. If bit 7 of AL is set, the color value is 
exclusive OR’d with the current contents of the 
pixel. 

DX = row number (Y coordinate) 

CX = column number (X coordinate) 

Function 13 — read dot 
Call with: 

AH = 13 

DX = row number (Y coordinate) 

CX = column number (X coordinate) 

Returns: 

AL = pixel contents 

Function 14 — write text in teletype mode 
Call with: 

AH = 14 
AL = character 

BH = display page in alpha mode 

BL = foreground color in graphics mode 

Note: If the character is line feed, carriage return, or back¬ 
space, the appropriate cursor movement is executed. If the 
character is a bell code, a tone is sounded. Otherwise, the char¬ 
acter is placed on the display at the current cursor position 
and the cursor is moved to the next position. If the cursor is at 
end-of-line, it is moved to the start of the next line. If the cur¬ 
sor is on the last line of the screen, the screen is scrolled up 
and the cursor is placed on a new line. Beware! When scroll¬ 
ing, the entire new line is set to the attribute of the last charac¬ 
ter that was written on the preceding line. This can produce 
some alarming and visually rather distasteful results when 
using reverse video. 


Function 15 — get current video state 
Call with: 

AH= 15 
Returns: 

AL = mode (see function 0 for explanation) 

AH = number of character columns on screen 
BH = active display page 

A Line Generator 

To further the cause of independence from BASIC for 
graphics support, 1 am including two logically equivalent 

(Continued on page 36) 



0 

1 

2 

3 

4 

3 

6 

7 

8 

9 

A 

B 

C 

D 

E 

F 

BBOOiOOOO 

34 

07 

68 

07 

69 

07 

73 

07 

20 

07 

64 

07 

65 

07 

6D 

07 

B800iOOIO 

6F 

07 

6E 

07 

73 

07 

74 

07 

72 

07 

61 

07 

74 

07 

63 

07 

BBOOi0020 

73 

07 

20 

07 

74 

07 

68 

07 

63 

07 

20 

07 

63 

07 

6F 

07 

B80010030 

6E 

07 

74 

07 

63 

07 

6E 

07 

74 

07 

73 

07 

20 

07 

6F 

07 

BBOOi0040 

66 

07 

20 

07 

74 

07 

66 

07 

63 

07 

20 

07 

63 

07 

6F 

07 

BBOOi0030 

6C 

07 

6F 

07 

72 

07 

2F 

07 

67 

07 

72 

07 

61 

07 

70 

07 

BBOOi0060 

68 

07 

69 

07 

63 

07 

73 

07 

20 

07 

20 

07 

20 

07 

20 

07 

B80010070 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

BBOOi0080 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

B80010090 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 

20 

07 


Figure 5 

Dump of first 160 bytes of color/graphics interface memory 
buffer in 80 x 24 text mode. Note that ASCII character codes 
are stored in even bytes and their respective attributes in odd 
bytes. 



0 

1 

2 

3 

4 

3 

6 

7 

B 

9 

A 

B 

c 

D 

E 

F 

BBOOiOOOO 

FF 

FF 

FF 

FF 

FF 

FF 

FF 

FB 

00 

00 

00 

00 

00 

78 

FC 

C6 

BBOOi0010 

00 

FC 

00 

00 

00 

00 

00 

00 

70 

00 

3C 

00 

00 

00 

00 

10 

BBOOi0020 

00 

00 

00 

00 

00 

06 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

BBOOi0030 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

B800i0040 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

BBOOi0030 

80 

00 

00 

00 

00 

00 

00 

OB 

00 

00 

00 

00 

00 

30 

66 

FE 

B80010060 

00 

66 

78 

DC 

7C 

78 

FB 

78 

30 

00 

CO 

78 

CC 

DC 

CC 

7C 

BBOOi0070 

78 

DC 

00 

00 

00 

22 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

BBOOi0080 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

BBOOi0090 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 


0 

1 

2 

3 

4 

3 

6 

7 

8 

9 

A 

B 

c 

D 

E 

F 

BAOOl0000 

80 

00 

00 

00 

00 

00 

00 

OB 

00 

00 

00 

00 

00 

30 

66 

EE 

BAOOl0010 

00 

66 

00 

00 

00 

00 

00 

00 

30 

00 

66 

00 

00 

00 

00 

30 

BAOOl0020 

00 

00 

00 

00 

00 

14 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

BAOOl0030 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

BAOOl0040 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

BAOOl0050 

80 

00 

00 

00 

00 

00 

00 

08 

00 

00 

00 

00 

00 

30 

7C 

FE 

BAOOl0060 

00 

7C 

CC 

76 

CO 

CC 

CC 

OC 

30 

00 

CO 

CC 

FE 

66 

CC 

30 

BAOOl0070 

CC 

76 

00 

00 

00 

41 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

BAOOl0080 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

BAOOl0090 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 


Figure 6 

Dump of selected portions of the color/graphics display buffer 
in high-resolution graphics mode. Each 80 bytes corresponds 
to one horizontal scan line of the display. The buffer is inter¬ 
laced: B800:0000 corresponds to Y = 0, BA00:0000 to Y = l, 
B800:0050 to Y=2, BA00:0050 to Y = 3, etc. 


Dr. Dobb’s Journal, Number 69, July 1982 


35 

295 





(Continued from page 35) 



Figure 7 

Demonstration of high-resolution graphic image transferred to 
Epson MX-80 printer with Graftrax option, using the program 
in Listing 3. [Reduced for publication.] 


line-generator subroutines. This algorithm is fairly simple but 
accurate, and requires as input arguments only the two end¬ 
points of the desired line. It uses the axis with the farthest dis¬ 
placement as the independent variable, stepping through the 
plot in single units of resolution. Working values of the depen¬ 
dent variable and the slope, along the axis of shorter displace¬ 
ment, are maintained in registers scaled up by a factor of 
1000. This ensures that any rounding errors will be less than 
the resolution of the display. 

Listing 1 is in standard Intel 8086 assembly language; 
those of you who must use the corrupted mnemonics of the 
Microsoft assembler have my sympathy. To keep the subrou¬ 
tine relatively short I have used the ROM video service routine 
to plot dots — the user may improve the execution speed sig¬ 
nificantly by writing a short assembly language sequence to 
write the bits directly into the memory map. Changing the 
scaling factor from 1000 to 1024 will allow replacement of the 
integer multiply and divide instructions with a sequence of 
arithmetic shifts, which will yield an additional speed advan¬ 
tage. 

Listing 2 is the equivalent line-drawing algorithm coded in 
“high-level” Forth. Note that the subroutine named “!DOT” 
plots points into the memory map direcly. The two operators 
“C@L” and C!L” will be unfamiliar to Forth programmers — 
they are “long” fetch and store operators which require a 
double-word address consisting of the 16-bit segment or para¬ 
graph and the 16-bit offset. 


Printing Graphic Displays 

The IBM dot matrix printer, which is actually built by 
Epson, can be enhanced with a special ROM set called “Graf¬ 
trax” (tm) which gives the device a bit-plot graphics capability. 
The option costs about $75.00, is available from many com¬ 
puter stores and mail order dealers, and may be installed by 
the user with a screwdriver in about ten minutes. 

I have included as Listing 3 a short program written in 
Forth which will translate a high-resolution video graphic 
display into hard copy on any printer equipped with Graftrax. 
An example of an image printed by this program is shown in 
Figure 7. 

Due to the slight difference in dot spacing, the hard copy 
image is distorted by a magnification in the vertical axis of 
about ten percent. The printer is used in the 480-dot mode, 
thus the right one-fourth of the video display will be omitted. 
The program may readily be modified to dump the right and 
left halves of the image separately, they may then be pasted 
up for further reproduction. 


Future Topics 

If enough readers express interest, I will be happy to con¬ 
tribute further columns on video graphics, using the IBM PC as 
th example machine. Possible topics include assembly language 
and high-level language routines for translation and rotation of 
figures, use of the color modes, and subroutines for generation 
of more complex shapes such as cubes, ellipses, and parabolas. 


(Listing begins on page 37) 


36 


Dr. Dobb’s Journal, Number 69, July 1982 













IBM Video Graphics (Text begins on page 32) 

Listing 1 title 'Hi-Res Graphic* Line Draw' 

pagewidth 80 

pagesize 66 

cseg 


Line drawing routine -for 
high re*olution graphic* 
display on IBM Personal Computer. 

Ray Duncan April 1, 1982 
Laboratory Microsystem* 






1 i nei 



1 cal ling argumentsi 








(dx*»Xl, cx"Yl 








jbx=»X2, ax«Y2 

0000 

8B 

FO 



mov 

si , ax 

1 

l*i " copy of Y2 

0002 

8B 

FB 



mov 

d i , b x 

jdi ■ copy of X2 

0004 

2B 

Cl 



sub 

ax , cx 

fax - Y2-Y1 

0006 

OB 

CO 



or 

ax, ax 

|i f delta Y-0 

0008 

75 

03 



Jnz 

1ine04 

1 go to 

000A 

E9 

AC 

00 


jmp 

1 i n*6 

1 -fast draw routine 

000D 

2B 

DA 


1ine04i 

sub 

bx , dx 

)bx - X2-X1 

000F 

OB 

DB 



or 

bx, bx 

| i f delta X-0 

0011 

75 

03 



jnz 

1ine05 

( go to 

0013 

E9 

BE 

00 


jmp 

1 i ne7 

1 -Fast draw routine 

0016 

50 



lineOSi 

push 

ax 

1 save actual delta X 

0017 

53 




push 

bx 

1 and delta Y 

0018 

79 

02 



Jns 

1ine06 

|if delta x negative 

001A 

F7 

DB 



neg 

bx 

) make it positive 

001C 

OB 

CO 


1in*06i 

or 

ax, ax 

1 ± -F delta y negative 

00 IE 

79 

02 



jns 

1ine07 

1 make it positive 

0020 

F7 

D8 



neg 

ax 


0022 

3B 

C3 


1ine07i 

cmp 

ax, bx 

1 abs <Y2-Y1) > abs<X2-Xl)7 

0024 

5B 




pop 

bx 

(restore original 

0025 

58 




pop 

ax 

1 delta y and delta x 

0026 

7F 

48 



Jg 

1 i ne3 

1 jump i-f delta y larger 

0028 

3B 

D7 



cmp 

dx, di 

»if X2 < XI then 

002A 

7C 

04 



jl 

1ineOB 

1 interchange X1,Y1 

002C 

87 

D7 



xchg 

dx, di 

1 with X2,Y2 

002E 

87 

CE 



xchg 

cx , si 


0030 

52 



1ineOBi 

push 

dx 

1 save XI 

0031 

53 




push 

bx 

1 save delta X 

0032 

BB 

E8 

03 


mov 

bx,1000 

(scale up delta Y 

0035 

F7 

EB 



i mul 

bx 

( by 1000 

0037 

5B 




pop 

bx 

(then divide by delta X 

0038 

F7 

FB 



idi v 

bx 

( to get Y increment*1000 

003A 

5E 




pop 

si 

(per unit of X 

003B 

50 




push 

ax 


003C 

B8 

E8 

03 


mov 

ax,1000 

(also get YltlOOO 

003F 

F7 

E9 



imul 

cx 


0041 

59 




pop 

cx 

(Continued on next page) 


Dr. Dobb’s Journal, Number 69, July 1982 


37 

297 






IBM Video Graphics (Listing continued, text begins on page 32) 


0042 

50 



1 ineli 

push 

ax 

(save registers 

0043 

51 




push 

cx 

»cx - V incr # 1000 

0044 

52 




push 

dx 

Idxiax* Y * 1000 

0045 

56 




push 

si 

»si - XI 

0046 

57 




push 

di 

1di - X2 

0047 

BB 

E8 

03 


mov 

bx,1000 

1 scale Y back down 

004A 

F7 

FB 



i di v 

bx 

1 to graphable range 

004C 

8B 

DO 



mov 

dx , ax 


004E 

8B 

CE 



mov 

cx, si 

|now dx-Y cx-X 

0050 

B8 

01 

0 C 


mov 

ax,OcOlh 

1 set -function 12 code 

0053 

CD 

10 



i nt 

lOh 

jcall ROM to plot point 

0055 

5F 




pop 

di 

irestore registers 

0056 

5E 




pop 

si 


0057 

5A 




pop 

dx 


0058 

59 




pop 

cx 


0059 

58 




pop 

ax 


005A 

3B 

F7 



cmp 

si p di 

p whole range o-f X plotted? 

005C 

74 

11 



jz 

1 i ne2 

|yes,exit 

005E 

46 




i nc 

si 

pincrement X 

005F 

33 

DB 



xor 

bx, bx 

psign extend Y increment 

0061 

OB 

C9 



or 

cx, cx 


0063 

79 

03 



jns 

1 inelS 


0065 

BB 

FF 

FF 


mov 

bx, -1 


0068 

03 

Cl 


1inelSi 

add 

ax f cx 

land calculate new Y value 

006A 

13 

D3 



adc 

dx, bx 


006C 

E9 

D3 

FF 


jmp 

1 i nel 

igo plot next point 

006F 

C3 



11ns2i 

rst 


1 

pcommon exit point 
■ 








f 

icome here i-f delta Y 








1 greater than delta X 

0070 

3B 

FI 


1ine3i 

cmp 

si p cx 

1 

|make sure Y1 < Y2 

0072 

7F 

04 



JQ 

1 in*4 

I i -f not, interchange 

0074 

87 

FI 



xchg 

si , cx 

p XI,Y1 with X2,Y2 

0076 

87 

FA 



xchg 

di pdx 


0078 

52 



1ine4i 

push 

dx 

icalculate X increment 

0079 

50 




push 

ax 


007A 

B8 

E8 

03 


mov 

ax,1000 

iscale up delta X 

007D 

F7 

EB 



i mul 

bx 


007F 

SB 




pop 

bx 

pdivide delta X * 1000 

0080 

F7 

FB 



i di v 

bx 

p by delta Y 

0082 

8B 

F9 



mov 

di , cx 

p to get X increment 

0084 

8B 

CB 



mov 

cx, ax 

I * 1000 per unit Y 

0086 

58 




pop 

ax 


0087 

BB 

E8 

03 


mov 

bx,1000 

pal so calc XI * 1000 

008A 

F7 

EB 



imul 

bx 


008C 

50 



1ine5i 

push 

ax 

1 save registersi 

008D 

51 




push 

cx 

jcx * X incr # 1000 

OOBE 

52 




push 

dx 

|axidx« X * 1000 

008F 

56 




push 

si 

1 si - Y2 

0090 

57 




push 

di 

pdi - Y1 

0091 

BB 

E8 

03 


mov 

bx,1000 

1 scale down current X 

0094 

F7 

FB 



i di v 

bx 

p value to graphable value 

0096 

8B 

CB 



mov 

cx, ax 



38 

298 


Dr. Dobb’s Journal, Number 69, July 1982 



0098 

8B 

D7 


mov 

dx, di 

jnow dx»Y cx«X 

009A 

B8 

01 

OC 

mov 

ax,0c01hjset -function 12 

009D 

CD 

10 


int 

lOh 

inow plot point 

009F 

5F 



pop 

di 

irsstors rsgistsrs 

00A0 

5E 



pop 

si 


00 A1 

5A 



pop 

dx 


00A2 

59 



pop 

cx 


00A3 

56 



pop 

ax 


00A4 

3B 

F7 


cmp 

si , di 

jwhol# rang# o-f Y dons? 

OOAfe 

74 

C7 


jz 

1 i n*2 

1 ysspsxi t 

00A8 

47 



inc 

di 

jincrsmsnt Y 

00A9 

33 

DB 


xor 

bx , bx 

(sign sxtsnd X incrsmsnt 

OOAB 

OB 

C9 


or 

cx , cx 


OOAD 

79 

03 


jns 

1 i na55 


OOAF 

BB 

FF 

FF 

mov 

bx, -1 


00B2 

03 

Cl 


lin#55i add 

ax' cx 

1 now calculat* nsw X val' 

00B4 

13 

D3 


adc 

dx p bx 


00B6 

E9 

D3 

FF 

jmp 

1 in*5 








1 

j-fast plot routins -for 







|Y2"Y1 i.s. horizontal 1 

00B9 

87 

D1 


lin*6i xchg 

dx, cx 


OOBB 

3B 

D9 


cmp 

bx, cx 


OOBD 

7D 

02 


Jge 

lin#65 

1 -fore# XI < X2 

OOBF 

87 

CB 


xchg 

cx p bx 






1in*65i 


|sav# r#gist#rsi 

00C1 

53 



push 

bx 

1 bx - X2 

00C2 

51 



push 

cx 

|cx ■ XI 

00C3 

52 



push 

dx 

1 dx - Y 

00C4 

B8 

01 

OC 

mov 

axp0c01h|s*t -function 12 cods 

00C7 

CD 

10 


i nt 

lOh 

iplot point 

00C9 

5A 



pop 

dx 

jr#stor# r#gist#rs 

OOCA 

59 



pop 

cx 


OOCB 

5B 



pop 

bx 


OOCC 

41 



inc 

cx 

|incr#m#nt X 

OOCD 

3B 

D9 


cmp 

bx f cx 

iwhol# rang# o-f X don#? 

OOCF 

7D 

FO 


jg« 

1in#65 

1 no 

00D1 

E9 

9B 

FF 

jmp 

1 i n*2 

1y#*p #xit 


-fast draw rout in* -for 
X2-X1 i.#. vertical lini 


00D4 

87 

CA 

1 in#7i 

xchg 

cx, dx 


00D6 

SB 

DE 


mov 

bx, si 


OODB 

3B 

DA 


cmp 

bx p dx 


OODA 

7D 

02 


Jg« 

11 n#75 

1 -fore# Y1 < Y2 

OODC 

87 

DA 

1in#75i 

xchg 

bx p dx 

1 sav# r#gist#rs 

OODE 

53 



push 

bx 

Ibx - Y2 

OODF 

51 



push 

cx 

jcx - X 

00E0 

52 



push 

dx 

|dx - Y1 

00E1 

B8 

01 OC 


mov 

axp0c01h|s#t -function 12 cod# 

00E4 

CD 

10 


int 

lOh 

iplot point 

00E6 

5A 



pop 

dx 

)r#stor# r#gist#rs 

00E7 

59 



pop 

cx 


00E8 

5B 



pop 

bx 


00E9 

42 



inc 

dx 

|incr#m#nt Y 

OOEA 

3B 

DA 


cmp 

bx p dx 

jwhol* rang# o-f Y don#? 


(Continued on page 42) 


Dr. Dobb’s Journal, Number 69, July 1982 


39 

299 



IBM Video Graphics (Listing continued, text begins on page 32) 


OOEC 7D FO 
OOEE E9 7E FF 


jge 

jmp 


•nd 

END OF AS 8 EMBLY. NUMBER OF ERROR 81 0 


1ine75 
1 i ns 2 


I not yet 
I yes,exit 


B800 C0N8TANT MAP 
0 VARIABLE BIT-TABLE -2 ALLOT 
80 C f 40 C, 20 C, 10 C, 


Listing 2 

8 creen # 39 

0 < Plot dot x,y 

1 FORTH DEFINITIONS HEX 

2 

3 

4 

5 

6 

7 

8 
9 

10 
11 
12 

13 

14 

15 DECIMAL 


04/23/82 ) 


8 C, 4 C f 


< addr o-f memory map/16 

< bit masks -for dot ) 

2 C, 1C, 


< 


Plot 
! DOT 


dot at coordinate 


x,y. 


OVER 7 AND BIT-TABLE + 
C 8 >R 
DUP 1 AND 

IF 2000 ELSE 0 ENDIF 
SWAP 2/ 50 * + SWAP 8 
MAP SWAP 2DUP C 8 L 
R> OR ROT ROT C!L | 

— > 


Stack effect* x y-) 

( extract bit mask ) 
and save it ) 
calc byte addr, if y odd) 
then offset by 2000 h ) 
each dot row«80 bytes ) 
extract byte from memory 
map, turn on bit and > 
put byte back in map ) 


< 

< 

< 

/ + < 
< 
< 
< 


Screen # 40 


0 

1 

2 

3 

4 

5 

6 

7 

8 
9 

10 

11 

12 

13 

14 

15 


( Draw line from xl,yl to x2,y2 


0 VARIABLE INCR 2 ALLOT 
1 4DUP 4 PICK 4 PICK 4 PICK 


( 


4 PICK | < 4 


»ve 

wd 


04/08/82 ) 

x or y increment) 
analogue of DUP) 


Draw 

LINE 


line. 8 tack effect* xl yl x 2 y 2 - ) 

4DUP ROT - ABB ROT ROT SWAP - ABS < 

IF ( delta x > delta y, so plot xl 

4 PICK 3 PICK > IF 2SWAP THEN ( 

4DUP ROT - ROT ROT SWAP - < 

SWAP 1000 M* ROT M/ < 

8 ->D INCR 2! DROP 
DROP SWAP 1000 M* 

4 ROLL 4 ROLL SWAP 


( y 2 -yl x 2 -xl ) 
to x 2 ) 

force xl < x 2 ) 
y 2 -yl x 2 -xl ) 
save incr* 1000 ) 


— > 


( discard y 2 , take yltlOOO > 
< bring up x 1 and x 2 ) 


Screen # 41 


0 

1 

2 

3 

4 

5 

6 

7 

8 
9 

10 

11 


( Draw line from xl,yl to x2,y2 continued 


04/08/82 ) 


DO 2DUP 1000 M/ SWAP DROP I < now plot points) 

SWAP .'DOT INCR 28 D+ LOOP 
ELSE ( delta y > delta x, so plot yl to y2 ) 

3 PICK 2 PICK > IF 28WAP THEN < force yl < y2 ) 

4DUP ROT - ROT ROT SWAP - < y2-yl x2-xl ) 

1000 M* ROT M/ < save incr*1000 ) 

B->D INCR 2! DROP 

SWAP DROP ROT 1000 M* < discard x2, take xl*1000 ) 

4 ROLL 4 ROLL SWAP ( bring up yl and y2 ) 

< now plot points > 


42 

300 


Dr. Dobb’s Journal, Number 69, July 1982 



DO 2DUP 1000 M/ SWAP DROP I !DOT 
INCR 2® D+ LOOP 
THEN 2DR0P | 


Listing 3 

Screen # 48 

0 ( Dump hi-res graphic image to Epson printer 

1 FORTH DEFINITIONS HEX 

2 B800 CONSTANT MAP < addr of 


04/23/82 ) 


4 0 VARIABLE BIT-TABLE -2 ALLOT ( bit mai 

5 80 C, 40 C, 20 C, 10 C, 6 C, 4 C, 2 C, 1 C, 


( addr of memory map/16 ) 

( bit masks -for dot testing) 


6 0 VARIABLE BIT-BUFFER IDE ALLOT 

7 

8 < Fetch dot value -from memory map. 

9 i ®D0T DUP 1 AND 

10 IF 2000 ELSE 0 ENDIF 

11 SWAP 2/ 30 * + OVER 8 / + 

12 MAP SWAP C®L SWAP 7 AND 

13 BIT-TABLE + C® AND 

14 IF 1 ELSE 0 THEN | 


( build printer output here) 

Stack effecti x y-> 

< calc byte addr, if y odd) 

< then offset by 2000h ) 

( each dot row-80 bytes ) 

( get mask from table to ) 

( test dot position ) 

< return 1 if dot on,else 0) 


Bcreen # 49 

0 < Dump hi-res graphic image to Epson printer 
1 

2 < after a pattern has been built into BIT-BUFFER ) 

3 < corresponding to x-0 to 479 S< y-y to y+3 by ) 

4 < DUMP-MAP, this routine sends it to the printer ) 


04/23/82 ) 


6 i BEND-LINE 

7 


0A EMIT ( line 

IB EMIT 4B EMIT ( selec 

8 E0 EMIT 01 EMIT ( 480 byte 

9 1E0 0 DO 

10 BIT-BUFFER I + C® EMIT < 

11 LOOP | < loop thr 

12 —> 

13 

14 

15 

Screen # 50 

0 < Dump hi-res graphic image to Epson printer 
1 

2 i DUMP-MAP C8 0 DO (for y-0 t 

3 1E0 0 DO 0 < for x-0 t 


( line feed ) 

( select graphics mode ) 

( 480 bytes will be sent ) 


:® EMIT < send this byte ) 
< loop through bit buffer ) 


04/23/82 ) 


2 i DUMP-MAP 

3 


< for y-0 to 199 step 4 > 

< for x-0 to 479 > 


4 

5 

6 

7 

8 
9 

10 

11 

12 i DUMP 

13 

14 

15 DECIMAL |S 


I J ®D0T IF 80 OR THEN 

I J 1+ ®D0T IF 20 OR THEN 

I J 2+ ®D0T IF 08 OR THEN 

I J 3 + ®D0T IF 02 OR THEN 
BIT-BUFFER I + C! 

LOOP < next x ) 8END- 

4 +L00P | < next y ) 


N < get x,y ) 

THEN < get x,y+l > 

THEN < get x,y+2 ) 

THEN < get x,y+3 ) 

( save pattern) 
SEND-LINE 


PRINTER 

IB EMIT 41 EMIT 08 EMIT 
DUMP-MAP CONSOLE | 


( select parallel port) 
( set vertical spacing) 
( send graphics image) 


End Listing 


Dr. Dobb’s Journal, Number 69, July 1982 


43 

301 


More on Checksums 


As a follow-up to our recent article on 
checksums, DDJ April 1982, here is a 
discussion of some additional examples. 

A personal check is probably the 
most common example of a 
document that contains informa¬ 
tion which must be accurately repro¬ 
duced several times through mechanical 
or electronic means on its journey from, 
for example, the receiving bank through 
the Federal Reserve System, and finally 
to the bank on which it is drawn. At each 
of these processing steps the accuracy of 
the routing information must be verified 
or the chances of it being falsely routed 
are increased. 

Certainly the most reasonable meth¬ 
od of verification in this example is the 
check digit. Examine a blank check for 
a moment. Along the bottom are a series 
of pre-encoded fields. The third from the 
right is normally the routing and transit 
number. In the U.S. it will always be in 
one of two formats. Either nine digits 
long or two groups of four digits separat¬ 
ed by a dash. In the latter case, no check 
digit is built in and the only absolute veri¬ 
fication method available would be com¬ 
parison to all known number series. 

Referring to Figure 1, the check digit 
calculation example can be used to veri¬ 
fy the routing number on any check 
drawn on a U.S. bank. Try it on yours! 

Another common example of infor¬ 
mation verification through check digits 
is oil company credit cards. The oil 
industry is faced with problems similar 
to the banking industry, rapid verifica¬ 
tion of information produced through 
mechanical or electronic means. If you 
have an oil company credit card with an 
account number grouped in a 3-3-3-1 

pattern, refer to Figure 2 for an example 
of a check digit calculation which will 
probably work with your card. 

Figure 3 will be helpful in categoriz¬ 
ing the type of error each check digit 
type is most proficient at discerning. 

Finally, check digits are the most 
common form of verification of decimal 
numbers in existence today. Proceeding 
one step further, it is possible to recon¬ 
struct any single digit of a number string 




Figure 1 




Modulus: 


10 




Weights: 


3,7,1,3,7,1,3,7 




Bank number including 
a check digit in the 9th 
position: 


061000010 






Example 





0 

6 10 0 0 

0 

1 



3 

7 13 7 1 

3 

7 



0 

42 1 0 0 0 

0 

7 

Sum = 50 

Add to units position to produce zero results 

0 



0 = Check Digit 







Figure 2 







Basic account number 

4 

0 7 

5 

5 

0 

5 

6 

1 

2 

Multiply units position 
and every alternate 
position by two 

2 

1 2 

1 

2 

1 

2 

1 

2 


8 

0 14 

5 

10 

0 

10 

6 

2 


Cross add all digits 

8+0+1+4+ 

5 + 1 

+0+0+ 

1+0+6+2 

= 28 

Subtract units position 
of result from 10 

10 

-8 = 2 










Check Digit is 2 








providing the check digit is present and 
all other digits of the original number are 
correct. Considering the obvious advan¬ 
tage of human interface inherent in the 
decimal numbering system, one of the 
best encoding systems is bar-coded 
binary data with error correction built 
in which can easily correct many missing 
digits. Five or six digits of correction is 
not uncommon. »*j 


by Robert Blum 


Robert Blum, 5536 Colbert Trail, Nor- 
cross, GA 30092. 


44 


Dr.' Dobb’s Journal, Number 69, July 1982 






Figure 3 


Type of Check Digit 
Numbering System 

Type of Error Detected 

Type of Error 

Not Detected 

Modulus 11 

100% of all transcription 
errors. 

Approximately 

10% of random 
errors. 

Geometric Weights 

90% of random errors, 

100% single and double 
transposition errors. 


Arithmetic Weights 

All single and double trans¬ 
position errors, 90% of ran¬ 
dom errors. 

Certain random 
errors from errone¬ 
ous recording. 

Modulus 10 

All transcription errors 

Certain types of 
random errors. 

1-3-7 

88% of transposition errors. 
88% of double transposition 
errors. 90% of random errors. 
High percentage of alternate 
column transpositions. 


Double ADD Double 

100% transcription error. 

97% transposition error. 

90% random error. 

Transpositions in 
adjacent positions 
between 09 and 90. 



Alternate column 
transposition of in¬ 
terchanged digits. 

Random error 
caused by substitu¬ 
tion of a valid 
check digit with an 
erroneous basic 
account number. 


Dr. Dobb’s Journal, Number 69, July 1982 


45 

303 




Part II 

PDP-1802 


P art I of this article (DDJ #68) de¬ 
scribed the instruction set of the 
PDP-8 minicomputer, and present¬ 
ed a program which emulates the front 
panel functions of the PDP-8 on micro¬ 
computers using the RCA COSMAC 1802 
microprocessor. In this concluding part, 
the emulator’s instruction interpreter is 
described, together with the input/output 
facility. 

Input/Output on the PDP-8 

I/O instructions on the PDP-8 have 
the op code 6. DEC has designated a large 
number of codes for the remaining bits 
of the I/O instructions corresponding 
to the selection codes and operating re¬ 
quirements of peripheral devices of all 
kinds, including terminals, disk drives, 
tape drives, oscilloscope displays, paper 
tape reader/punches, and so on. The most 
elementary I/O instruction group is con¬ 
cerned with the Teletype unit used as a 
console on PDP-8s, and these are the 
only instructions explicitly realized in 
the emulation. 

Like the Operate instructions de¬ 
scribed in Part I, the I/O instructions 
can be microprogrammed to combine 
multiple actions in single instructions. 
The Teletype I/O instructions allow for a 
total of three actions for input and three 
actions for output which may be com¬ 
bined. 

The PDP-8 used as its console a 
modified Teletype Model 33 ASR. This 
Teletype unit has a keyboard, a printer, 
a paper tape reader, and a paper tape 
punch. The printer and the punch are, so 
far as the computer is concerned, one de¬ 
vice; the punch is turned on and off 
manually, and identical data are acted on 
by the printer and punch. The paper tape 
reader and the keyboard are similarly 
seen by the computer as one source of 
data. There are, however, important dif¬ 
ferences in operation which the emulator 
must take into account if standard PDP-8 
software is to be executed correctly. 
First, the keyboard is set up to make the 
eighth most significant bit of the ASCII 
code always marking (that is, always a 1). 
The paper tape reader, however, does not 
do this, and must correctly sense and 


by Chris Hamlin 

Chris Hamlin, 2202 Hindle Ln., Bowie, 
MD 20716. 


transmit whatever actually is present on 
the tape in the eighth position. If you 
plan to use a Teletype in conjunction 
with this emulator, you must be sure that 
it works this way, or modify it accord¬ 
ingly. 

Second, the paper tape reader on 
the Teletypes supplied by DEC for use 
with PDP-8s are equipped with a relay 
which is opened or closed as a function of 
a flag in the computer. The relay permits 
or inhibits advance of the paper tape 
reader; since the flag controlling the relay 
may be sensed or cleared under program 
control, this allows the computer to read 
some data, then stop the tape reader 
while taking an action, then read more 
data when ready. This capability is used, 
for example, when assembling a program: 
source code is read a line at a time from 
the reader, which is then stopped while 
the line is assembled and the output 
printed or punched or both. 

In the emulator, a similar signal must 
be supplied to provide control over the 
paper tape reader. Although it is common 
to use the Q line for such purposes in 
1802 systems, a more general solution is 
preferable, and in any case the Q line is 
used for displaying the link bit. Accord¬ 
ingly, one bit in an output port is chosen 
as the relay control flag. 

Keyboard Instructions 

The general form of the keyboard/ 
reader instructions is 603X 8 where the 
least significant three bits represented by 
“X” control the instruction’s three 
actions. 

KSF-6031: Skip on keyboard flag. The 
next instruction is skipped 
if the keyboard flag is raised, 
indicating that an ASCII 
character has been loaded 
into the keyboard buffer 
(the buffer content could be 
binary data too, of course). 
KCC-6032: Clear the accumulator, and 
clear the keyboard flag. 
KRS-6034: Move the content of the 
keyboard buffer into the ac¬ 
cumulator. 

The usual microprogrammed combi¬ 
nation of these is: 

KRB-6036: Clear the keyboard flag, and 
move the content of the 
keyboard buffer into the 
accumulator. 

A common use of these instructions 


is to set up a loop (using KSF) which the 
program exits when a character has been 
assembled in the buffer (raising the flag); 
the program then obtains the character 
for processing, and clears the flag (with 
a KRB). 


Printer/punch Instructions 

The three printer/punch microin¬ 
structions resemble those for the key¬ 
board and reader; their general form is 
604X 8 . 

TSF-6041: Skip on printer flag. The 
next instruction is skipped 
if the printer flag is raised. 
The flag is raised upon com¬ 
pletion of printing or punch¬ 
ing a character from the 
printer buffer. 

TCF-6042: Clear the printer flag. 
TPC-6044: Move the content of the ac¬ 
cumulator to the printer 
buffer, then transmit the 
character to the printer/ 
punch. The printer flag is 
raised when the action has 
been completed. 

Again, these actions may be com¬ 
bined, as follows: 

TLS-6046: Clear the printer flag; trans¬ 
fer the content of the ac¬ 
cumulator to the printer 
buffer; transmit the charac¬ 
ter to the printer, and raise 
the printer flag upon com¬ 
pletion of the action. 

As with the keyboard/reader instruc¬ 
tions, a common use of the printer in¬ 
structions is to create loops in which the 
program remains until the printer has 
completed processing of a character. This 
can be used to ensure that the printer is 
given something to do only when it is 
ready. 

It is important to note that the ac¬ 
tivities of the keyboard/reader and the 
printer/punch are wholly independent of 
one another. With appropriate program¬ 
ming, one character may be received for 
processing while another is being printed 
or punched. 

Interrupt Processing 

The approach to servicing Teletype 
input and output described above de¬ 
pends upon having the computer sit in 
loops while it waits for the very slow 
(Continued on page 50) 


46 

304 


Dr. Dobb’s Journal, Number 69, July 1982 


(Continued from page 46) 
devices to complete actions in progress. 
To avoid such wastes of time (during 
which the computer could be doing use¬ 
ful work) an interrupt facility is used. In 
the PDP-8 peripheral devices may raise 
interrupt requests at any time; program¬ 
ming must then determine the source of 
the request and, if necessary, resolve com¬ 
petition between interrupting devices for 
system resources. In the PDP-1802 emu¬ 
lator, the interrupt action is provided for 
only in the case of the keyboard and 
printer I/O devices in the Teletype (and 
thus the reader and punch, too). First, 
the interrupt action in the PDP-8 is de¬ 
scribed. Then ways of emulating it are 
discussed and presented. 

Interrupts are issued whenever the 
keyboard flag or the printer flag are 
raised. When the interrupt has been re¬ 
quested, the computer finishes executing 
the current instruction. Then, instead of 
proceeding to the instruction it would 
normally have executed next, it automa¬ 
tically executes a “JMS 0000” instruc¬ 
tion. Remember that this will place the 
address of the next instruction in the in¬ 
terrupted program in location 0000, 
which is the normal action of a JMS in¬ 
struction. After the JMS 0000 has been 
performed, the instruction in location 
0001 will be executed, and this is, as a 
rule, a jump to the interrupt service rou¬ 
tine you have provided. To return to the 
interrupted program after the completion 
of the service routine, you need merely 
issue a “JMP I 0000” (indirect jump via 
location 0000) instruction. 

When an interrupt occurs, all further 
interrupts are disabled until the program 
(generally the interrupt service routine) 
enables them again. This ensures that an 
orderly progression in service for time- 
critical applications may be guaranteed. 
Two instructions are provided to control 
the interrupt facility: 

ION-6001: The interrupt facility is en¬ 
abled, but only following 
execution of the next in¬ 
struction (after the ION); 
this allows exit from the in¬ 
terrupt service routine to 
occur before another inter¬ 
rupt is received for pro¬ 
cessing. 

IOF-6002: The interrupt facility is dis¬ 
abled. Interrupt requests are 
ignored. 


Note that the occurrence of an inter¬ 
rupt automatically disables the facility; 
the program need not issue an IOF. 

The interrupt facility of the PDP-8 
could be emulated in either of two ways. 
One approach would be to use the actual 
interrupt apparatus on the 1802; then the 
interrupt service routine handling 1802 
interrupts could be set up so as to carry 
out exactly the same actions taken by a 
PDP-8. Another approach would be to 
simulate interrupts using the input flags 
(the so-called EF lines) on the 1802. The 
emulator software could then simply 
check the state of the flags after execut¬ 
ing each PDP-8 instruction, and take 
appropriate action. 

The simulated interrupts have the 
disadvantage of requiring additional code 
and therefore additional overhead on 
every emulated PDP-8 instruction cycle. 
For many 1802 users, however, this is 
preferable, because in order to use the 
true interrupts of the 1802 to emulate 
the PDP-8 facility some additional hard¬ 
ware is required. To make the emulator 
usable on unmodified 1802 systems, 
therefore, the simulated interrupt ap¬ 
proach is adopted here for the printer 
and the keyboard/reader. 

Serial Communications Facility 

Standard PDP-8 computers were sup¬ 
plied with a hardware facility for convert¬ 
ing eight-bit characters to a Teletype- 
compatible serial stream, and for receiv¬ 
ing serial Teletype characters and con¬ 
verting them to eight parallel bits. Today 
the devices for carrying out this parallel- 
to-serial and serial-to-parallel conversion 
are called UARTs (for Universal Asyn¬ 
chronous Receiver Transmitter). In the 
PDP-1802, the action of the PDP-8 serial 
communications facility is emulated by a 
software UART (that is, a program pro¬ 
viding the necessary conversion and 
timing). This is provided so that users 
without their own UARTs (hardware, 
that is) can still use the emulator. 

A major shortcoming of the software 
UART approach should be pointed out, 
however. The whole point of the PDP- 
8 interrupt architecture and of the serial 
communications facility was to make the 
very slow Teletype operations able to 
proceed while the CPU did a great deal of 
useful work on other matters; the atten¬ 
tion of the CPU is thus only required at 
the beginning or end of a slow I/O opera¬ 
tion, but not during it. The software 
UART implemented in the 1802 emula¬ 


tion, on the other hand, ties up the 1802 
CPU during character reception and trans¬ 
mission, with the result that no other 
business can be taking place at the same 
time. Many readers may find that it is 
preferable, for this reason, to go to the 
slight additional expense of adding a 
hardware UART (such as RCA’s CMOS 
1854, which is made for use with the 
1802) so that true interrupt benefits are 
realized. 

Other PDP-8 Capabilities 

The PDP-1802 does not emulate all 
of the PDP-8 capabilities. The most im¬ 
portant one which is not emulated is the 
DMA facility. DMA (direct memory ac¬ 
cess) is a means whereby extremely rapid, 
controlled data transfer can be provided 
without having to execute instructions in 
the CPU. The PDP-8 was unusually 
powerful for its time and cost, in large 
part because of the flexible DMA facili¬ 
ties it provided. Disk drives and real-time 
laboratory instrumentation can be at¬ 
tached quite easily to the DMA facility, 
and this made the PDP-8 attractive for 
many applications previously requiring 
larger, more costly computers. Although 
the 1802 also has a data channel which 
closely resembles DMA in its operation, 
the hardware complexity required to 
emulate 12-bit DMA on an 8-bit device is 
excessive, and is unnecessary for execut¬ 
ing the basic PDP-8 instruction set on the 
emulator. 

Later models of the PDP-8 incorpo¬ 
rated a number of enhancements, and 
also introduced subtle changes in the ac¬ 
tions occurring within the computer 
when certain instructions were executed. 
The most important extension to the in¬ 
struction set, which is not included in the 
PDP-1802 (although it could easily be 
added) was the PDP-8/E instruction 
BSW (70028 ), which swaps the upper and 
lower halves of the accumulator (a byte 
swap). The PDP-8/E also included addi¬ 
tional interrupt control, teletype/punch 
and keyboard/reader instructions. If you 
obtain PDP-8 software to run on the 
emulator, be sure to ascertain whether it 
contains any of these unsupported in¬ 
structions, and provide patches to replace 
them. 


Running the Emulator 

When a program is loaded, type “L” 
and the starting address; then press “S”, 
and program execution commences. You 


50 


Dr. Dobb’s Journal, Number 69, July 1982 

305 



may at any time begin to single step I would be most interested to hear 
through it as described in Part I (DDJ from readers who implement the PDP- 
#68). When you single step, the program 1802, and will answer any questions or 
counter, memory buffer, accumulator, try to help with problems others may 
and instruction buffer are displayed as encounter as best I can. 
each instruction is executed. A patch is 
given allowing display of these registers 

on the console device as normal execu- (Listing begins on page 52) 
tion proceeds. 

The Q line is used to show the state 
of the link bit at the conclusion of each 
instruction; the low eight bits of the ac¬ 
cumulator are also shown in hex on two 
seven-segment LEDs (or eight single 
LEDs if you use them). If you do not 
have a CRT to devote to use as the con¬ 
sole for the monitor, you may use your 
hex keypad or toggle-switch panel, plus 
the LED displays, to supply the octal 
console monitor functions instead. 

Notes on the Implementation 

The octal console monitor is made 
up almost entirely of subroutine calls 
using the RCA standard call-and-return 
technique. The emulator for the PDP-8 
instructions, on the other hand, is almost 
entirely in-line code, the only subrou¬ 
tines being those for moving between the 
eight-bit and twelve-bit address spaces. 

The 1802 architecture, whose most im¬ 
portant feature is a complement of six¬ 
teen registers of sixteen bits each, is very 
well suited to emulating the twelve-bit 
architecture, since most of the internal 
registers of the PDP-8 can simply be re¬ 
presented directly by 1802 registers. 

Many points of the emulation are greatly 
simplified, too, by the ability of 1802 
registers to change function (pointer, 
counter, data storage, and so on) as 
needed. 

Needless to say, this is not a high¬ 
speed approach to computation. It seems 
fair to say that for most applications, the 
emulator will operate between several 
hundred and several thousand times slow¬ 
er than would the slowest PDP-8 (the 
serial architecture PDP-8/S). However, 
it can be used to gain real insight into the 
operation of the PDP-8 instructions, and 
will provide faithful execution of correct 
PDP-8 software composed of the sup¬ 
ported instructions. The most complex 
piece of software I have run using the 
emulator has been a floating-point pack¬ 
age adapted from one distributed by 
DECUS (the DEC Users’ Society) which 
processes five-word numbers with 51-bit 
mantissas. This package works flawlessly, 
albeit a trifle sluggishly. 

Dr. Dobb’s Journal, Number 69, July 1982 

306 



PDP-1802 (Text begins on page 46) 


(Note: The entry point is 1400H. The program assumes the program counter is in Register 0.) 


I/O and Console Routines 11 90 12 F8 18 F2 

11 AO 18 F8 02 F2 
11 BO BC F8 04 F2 
11 CO 20 F2 32 BC 
11 DO 02 F2 32 D8 
11 E0 12 B2 8F F9 

11 F0 00 00 00 00 

Monitor Driver 12 00 3E 00 6A FA 

12 10 3A 0E 67 22 
12 20 A5 A0 20 90 
12 30 8D 3E 35 FF 
12 40 90 3A 3F D5 
12 50 3A 4E 8D 76 
12 60 04 B0 F8 42 
12 70 93 B6 83 A6 
12 80 12 72 A6 FO 
12 90 3E 9A 8F F9 
12 AO 00 00 00 00 
12 BO 46 AD 8D 52 
12 CO D3 E2 96 73 
12 DO D3 96 B3 86 
12 EO 00 00 00 00 

12 FO 00 00 00 00 

13 00 D4 13 BA D4 
13 10 9B B9 8B A9 
13 20 D4 16 1A D4 
13 30 00 8D FB 20 
13 40 CB 15 ED D4 
13 50 D4 16 35 19 
13 60 72 FF 08 33 
13 70 77 BD D4 12 

'13 80 FI AB 12 02 
1 3 90 9B F6 F9 30 
13 AO AD D4 12 09 
13 BO 8B FA 07 F9 
13 CO 07 OA D5 46 
13 DO C8 FF 00 D5 
13 EO 32 E6 FF 00 

13 FO 3E FO 6A FA 

Initialization 14 00 90 B3 F8 06 

Single Step 14 10 E2 F8 18 B2 

14 20 C4 C4 12 9 F 
14 30 BE FA 80 BF 
14 40 22 88 AB 98 
14 50 D4 13 90 D4 
14 60 D4 12 07 20 
14 70 64 22 9 C FA 


32 

BF 

F8 

01 

F 2 

32 

A 1 

8F 

FA 

80 

32 

A 1 

32 

B 1 

F8 

00 

AC 

8F 

FA 

7F 

AF 

9C 

FA 

1 0 

32 

BC 

8D 

AC 

9C 

FA 

10 

BC 

CO 

1 4 

23 

F 8 

F8 

01 

F 2 

32 

CF 

8F 

FA 

08 

32 

CF 

18 

F 8 

8F 

FA 

F7 

AF 

F8 

04 

F 2 

32 

E6 

8 C 

AD 

D4 

OC 

AF 

CO 

1 4 

23 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

7 F 

AD 

D5 

46 

AD 

8 D 

52 

F8 

04 

BO 

20 

90 

D5 

FC 

00 

F8 

80 

AD 

36 

1 A 

F8 

01 

BO 

F8 

3 A 

22 

F8 

02 

BO 

F8 

47 

AO 

20 

90 

3 A 

2 C 

00 

76 

AD 

3 B 

26 

F8 

03 

BO 

F8 

41 

AO 

20 

F8 

80 

BD 

7 B 

F8 

02 

BO 

F8 

47 

AO 

20 

90 

AD 

CF 

7 B 

38 

7A 

9D 

F 6 

BD 

3 B 

48 

7 A 

F8 

AO 

20 

90 

3A 

65 

D5 

D3 

E2 

96 

73 

86 

73 

46 

B3 

46 

A3 

30 

6 A 

D3 

96 

B3 

86 

A3 

E2 

B6 

30 

7 A 

00 

00 

00 

00 

00 

00 

00 

00 

00 

84 

AF 

6 A 

F9 

80 

AD 

CO 

15 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

67 

22 

F8 

04 

BO 

20 

90 

3A 

B9 

D5 

00 

00 

86 

73 

93 

B6 

83 

A6 

46 

B3 

46 

A3 

30 

CO 

A3 

E2 

12 

72 

A6 

FO 

B6 

30 

DO 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

00 

E2 

22 

12 

00 

D4 

13 

C 3 

43 

CB 

13 

03 

D4 

13 

59 

30 

1 D 

99 

BB 

89 

AB 

D4 

13 

90 

D4 

16 

00 

12 

07 

20 

D4 

13 

90 

D4 

12 

07 

20 

D4 

12 

32 

53 

D4 

13 

C3 

4 C 

3B 

OD 

D4 

13 

C3 

53 

13 

C3 

43 

CB 

13 

03 

D4 

13 

59 

D4 

16 

00 

D4 

13 

BA 

30 

16 

F8 

04 

BD 

8D 

FF 

30 

3 B 

72 

8D 

52 

67 

22 

FA 

07 

73 

9D 

FF 

0 1 

32 

00 

30 

5 C 

12 

72 

AB 

02 

FE 

FE 

FE 

52 

8 B 

76 

76 

76 

52 

8B 

FI 

AB 

12 

02 

7 E 

BB 

D5 

AD 

D4 

12 

09 

8 B 

7 E 

7 E 

7 E 

FA 

07 

F9 

30 

8B 

F6 

F 6 

F 6 

FA 

07 

F9 

30 

AD 

D4 

12 

09 

30 

AD 

D4 

12 

09 

D5 

D4 

12 

07 

OD 

D4 

12 

52 

8D 

F3 

3 A 

D1 

F 6 

D4 

12 

09 

D4 

13 

BA 

AD 

D4 

12 

B2 

D5 

00 

00 

00 

46 

52 

8D 

F3 

30 

EC 

F6 

67 

22 

D4 

13 

F7 

D5 

00 

00 

00 

7F 

AD 

D5 

D4 

12 

BO 

OD 

D4 

12 

BO 

OA 

D5 

A3 

D3 

F8 

12 

B4 

B5 

F8 

6 B 

A4 

F8 

7B 

A5 

F 8 

FF 

A2 

F8 

14 

B1 

F8 

00 

A 1 

CO 

13 

00 

FA 

80 

C6 

3F 

6 E 

37 

29 

3F 

2 B 

6 C 

64 

22 

C4 

C4 

C4 

37 

37 

6 C 

64 

22 

AE 

8 C 

52 

64 

BB 

D4 

13 

90 

D4 

12 

07 

20 

89 

AB 

99 

BB 

12 

07 

20 

8 C 

AB 

9 C 

FA 

OF 

BB 

D4 

13 

90 

8A 

AB 

9 A 

BB 

D4 

13 

90 

D4 

13 

BA 

8 C 

52 

1 0 

CE 

7 B 

38 

7 A 

CO 

12 

90 

99 

B8 

30 

23 


52 


Dr. Dobb’s Journal, Number 69, July 1982 

307 


Interpreter 


14 80 F8 01 F2 CA 
14 90 CB 9 C FA 08 
14 AO FA OF 3A A8 
14 BO AF 02 FA 08 
14 CO 70 52 8F FA 
14 DO 12 F8 80 F2 
14 EO 32 FI 8E 22 

14 FO AC 8F FA 8F 

15 00 98 B9 88 A9 
15 10 AA 9B BA FA 
15 20 00 B9 8A A9 
15 30 AF 30 3C 8A 
15 40 5F D4 16 00 
15 50 BB 9 B B9 8B 
15 60 FA FD AF 9A 
15 70 93 B1 01 A3 
15 80 8B 73 9B F9 
15 90 D4 16 00 D4 
15 AO 18 D4 16 35 
15 BO 52 8 C F4 12 
15 CO 9 C BB 8 C AB 
15 DO 23 D4 16 00 
15 EO B8 89 A8 CO 

15 FO BC AF BF 89 

16 00 22 FC 00 89 
16 10 99 74 52 72 
16 20 FO F9 08 AB 
16 30 9 B FA OF BB 
16 40 9B 7E BB 3B 
16 50 07 FA FO FI 
16 60 F2 C2 11 90 
16 70 9C FA 10 BC 
16 80 F8 20 F2 32 
16 90 32 96 9C FB 
16 AO 1C 9C FA OF 
16 BO 9C F6 BC 8C 
16 CO 14 23 F3 52 
16 DO 8C FE AC 9C 
16 EO IF BC 02 C2 

16 FO 5D 5D 3E Cl 

Checksum Code* 17 10 F8 06 B5 F8 

17 20 90 A2 E2 F8 
17 30 3A 29 F8 10 

17 40 F8 00 30 2A 

Checksum Values** '8 00 9F E8 22 8E 

18 10 F8 00 7F FB 
18 20 85 CF 06 8F 
18 30 92 67 17 86 
18 40 15 B5 56 87 
18 50 09 AA FC 81 


14 

F 4 

F 8 

78 

F 2 

32 

D 1 

22 

52 

FB 

08 

32 

32 

9 C 

8F 

FB 

40 

AF 

30 

A8 

8 C 

3 A 

A8 

9 C 

8F 

FB 

20 

AF 

9 C 

FA 

10 

32 

B1 

8F 

FB 

10 

3A 

BE 

8F 

FA 

70 

F2 

32 

DO 

30 

CB 

8 A 

FA 

70 

FB 

70 

F 2 

F3 

3 A 

DO 

18 

98 

FA 

OF 

B8 

32 

DD 

9 C 

FA 

1 0 

BC 

F8 

00 

AC 

F8 

04 

F2 

73 

9 E 

FA 

OF 

52 

9 C 

FI 

12 

BC 

8 C 

FI 

1 2 

AF 

F8 

02 

F2 

C2 

14 

23 

7 B 

00 

00 

22 

AA 

18 

98 

FA 

OF 

B8 

D4 

16 

00 

D4 

16 

1 A 

8 B 

OC 

FB 

OC 

C2 

16 

5 A 

8A 

FA 

80 

3 A 

33 

F8 

FA 

FO 

3A 

3 C 

89 

FA 

08 

32 

3C 

8 F 

F9 

02 

FA 

7 F 

52 

89 

FA 

80 

FI 

A9 

9 A 

FA 

01 

32 

D4 

16 

1 A 

8F 

FA 

02 

32 

5 B 

1 B 

9 B 

FA 

OF 

A9 

27 

D4 

16 

35 

30 

5 F 

9 B 

B9 

8 B 

A9 

8F 

F 6 

FC 

74 

A1 

93 

B 1 

01 

A3 

F6 

FC 

74 

A 1 

7 A 

A7 

90 

BD 

D 1 

E6 

D4 

16 

00 

D4 

16 

1 A 

10 

52 

9 C 

F 2 

12 

BC 

8 C 

F2 

AC 

CO 

1 4 

23 

16 

1 A 

1 B 

27 

8 B 

3A 

A 1 

9 B 

FA 

OF 

3A 

A 1 

CO 

14 

23 

D4 

16 

00 

D4 

16 

1 A 

9 B 

73 

8 B 

AC 

9 C 

74 

FA 

1 F 

BC 

CO 

14 

23 

D4 

16 

00 

D4 

16 

35 

9 C 

FA 

1 0 

BC 

F8 

00 

AC 

CO 

14 

98 

BB 

88 

AB 

D4 

16 

35 

19 

99 

FA 

OF 

B9 

14 

23 

99 

B8 

89 

A8 

CO 

1 4 

23 

F8 

00 

AC 

A8 

99 

B8 

CO 

1 4 

23 

82 

92 

21 

22 

22 

92 

FE 

73 

99 

FA 

OF 

7 E 

73 

12 

1 2 

89 

F 4 

73 

F6 

B7 

72 

76 

A7 

D5 

47 

BB 

07 

33 

2F 

FA 

9B 

F6 

BB 

8B 

76 

AB 

3 B 

24 

FC 

00 

D5 

AB 

D5 

9B 

FA 

OF 

33 

4F 

F9 

10 

BB 

8 B 

FE 

AB 

3D 

57 

17 

8 B 

52 

07 

FA 

OF 

FI 

57 

D5 

52 

57 

17 

8 B 

57 

D5 

F8 

8 A 

73 

9 A 

52 

F8 

02 

F8 

01 

F2 

12 

CA 

1 4 

80 

F8 

80 

F2 

32 

77 

F8 

00 

AC 

F8 

40 

F 2 

32 

80 

9C 

FA 

OF 

BC 

8D 

8 C 

FB 

FF 

AC 

9 C 

FB 

OF 

BC 

F8 

1 0 

F2 

10 

BC 

F8 

01 

F 2 

32 

A7 

22 

9 C 

FA 

1 0 

52 

F3 

BC 

1 2 

F8 

08 

F2 

32 

C6 

F8 

02 

F2 

52 

76 

AC 

33 

BA 

30 

BE 

9 C 

F9 

10 

BC 

02 

C2 

30 

BO 

F8 

04 

F2 

C2 

1 4 

23 

F8 

02 

F2 

52 

7 E 

BC 

FA 

20 

32 

E2 

8 C 

F9 

01 

AC 

9 C 

FA 

14 

23 

F3 

52 

30 

DO 

DC 

Cl 

10 

8F 

D8 

6 D 

58 

02 

2 B 

72 

08 

67 

B6 

37 

1 1 

B2 

67 

60 

6F 

A5 

F 8 

1 0 

A7 

F 8 

1 1 

B2 

F 8 

18 

B4 

F8 

00 

A4 

B6 

A6 

A8 

88 

F 4 

A8 

12 

27 

87 

25 

A7 

88 

54 

E 4 

86 

F 4 

1 4 

A6 

E2 

95 

32 

44 

86 

E4 

54 

64 

24 

00 

00 

00 

00 

FF 

00 

FF 

40 

FE 

00 

D 1 

B8 

FO 

27 

C7 

79 

69 

15 

7 A 

F7 

00 

04 

95 

BE 

7B 

68 

C5 

CF 

C9 

AE 

AD 

CE 

65 

AB 

49 

66 

E2 

93 

B 4 

92 

8D 

2D 

CB 

7F 

29 

9F 

6C 

A7 

CF 

D4 

24 

2F 

36 

FB 

71 

26 

FD 

AE 

BF 

47 

6F 

52 

16 

E2 

C3 

43 

57 

02 

9C 

96 

DE 










* Execute this code to generate checksum values. 

**One checksum for every line (16 values) of code from 1190H to 16FFH; value at 18S7H is checksum for the whole interpreter. 

End Listing 


Dr. Dobb’s Journal, Number 69, July 1982 
308 


53 



Rough Approximation 

Numerical Algorithms 


W hen a numerical calculation is 
done by a computer, few users 
know how the numbers are be¬ 
ing stored or what algorithms are being 
applied. This is part of the underground 
lore of binary digital computation, itself 
derived from the even more abstruse tech¬ 
niques of higher mathematics. Many users 
are aware that the result will often be a 
rounded-off approximation. Few will 
know anything of approximation theory, 
that optimizes the trade-off between al¬ 
gorithmic simplification and loss of pre¬ 
cision. Some elements of it are intelligibly 
discussed in Numerical Methods, by G. 
Dahlquist and A. Bjorck (1974, Prentice- 
Hall, 573 pp.), computer-oriented Swed¬ 
ish mathematicians. An approximation al¬ 
gorithm can be designed to yield a nu¬ 
merical value with either an absolute or 
a relative error less than some pre-set 
value, over a defined interval of the 
numerical input. It is not unusual, when 
the range of input is very wide, to have 
several different approximation algo¬ 
rithms, each one valid for a different 
interval. This note will consider only one 
simple example, the calculation of the 
natural logarithm of a real binary num¬ 
ber, N. The term “rough” approximation 
means that the relative error, in the in¬ 
terval over which the algorithm is valid, 
does not exceed 0.1%. However, a simi¬ 
lar approach could be used to design al¬ 
gorithms with any desired degree of pre¬ 
cision. 

Any real binary number N can be 
most compactly stored in exponential 
form, 2 n (l + m), where n is a signed inte¬ 
ger and m is a binary fraction; (1 +m) 
must be positive for calculation of the 
natural log, ln(N), that is 

ln(N) = n ln(2) + ln(l + m) 

The first term is easily calculated by mul¬ 
tiplying a look-up table value of ln(2) by 
n. The second term can be evaluated to 
any desired precision by the infinite- 
series algorithm 

ln(l + m) = m(l - m/2 + m 2 /3 - 
m 3 /4. ..) 

but this converges extremely slowly as 
the fraction m approaches 1. As succes- 


by H.T. Gordon 


H. T. Gordon, College of Natural Re¬ 
sources, University of California, Berke¬ 
ley, CA. 


sive terms are calculated, the error alter¬ 
nates between positive and negative. E.g., 
if one wishes to simplify calculation by 
not going beyond the m 2 /3 term, the 
error is always positive and worsens as m 
becomes larger. This can be mitigated by 
replacing m 2 /3 by a term that will be 
numerically less. One computationally - 
simple algorithm is 

In(1 + m) m[ 1 - m/2 + (m/2) 2 + 

(m/2) 2 /16 ] 

Since all the divisions are by multiples of 
two, they can be quickly done as right- 
shifts of m. The only complex operations 
are two binary multiplications. The first 
calculates (m/2) 2 and the second multi¬ 
plies the term in brackets by m. 

The performance of this algorithm 
was tested on a pocket calculator. The re¬ 
lative error is low and negative for values 
of m less than 0.1. At 0.1 it is-0.05%, at 
0.2 it is -0.11%, at 0.25 also -0.11%, 
then declines to -0.07% at 0.3, to -0.01% 
at 0.34, changes sign to +0.01% at 0.35, 
+0.06% at 0.37, and +0.16% at 0.40. This 
limited working interval (here from 0 to 
0.37) is typical for approximation algo¬ 
rithms. It is obvious that replacing the 
(m/2) 2 /16 term by a slightly larger term 
would narrow the working interval and 
lower the maximum negative error. 

A different algorithm must be used 
for values of m greater than 0.37. Again 
there are very many possible ones. One 
approach is to calculate y = (1 - m), so 
that (1 + m) = (2 - y). An approximation 
algorithm for In(2 - y) is 

ln(2) - (y/2) [ 1 + y/4 + (y/4) 2 + 
(y/4) 2 /2 + (y/4) 2 /4] 

Although more complex, the real work 
still involves only two binary multiplica¬ 
tions. The relative error is low and nega¬ 
tive for values of m larger than 0.7. At 
0.7 it is -0.04%, at 0.6 it is -0.08%, at 
0.5 it is -0.1%, at .45 it is -0.9%, at 0.4 it 
is -0.04%, then changes sign to +0.07% at 
0.35. The working interval is twice as 
wide as that of the first algorithm, be¬ 
cause the approximation is in effect a 
function of m/2. Both algorithms show a 
negative-error plateau as the difference 
from their respective “reference points” 
(.ln(l) or ln(2)) increases, and this shifts 
to a positive error near the limit of the 
working interval, that is close to the loga¬ 
rithmic mean of the reference points. 
Near the reference points, where m or 


(1 - m) becomes very small, even simpler 
algorithms will do. E.g., 

In(1 + m) » m(l - m/2 + m/32) 

has a working interval from zero to 0.12. 
The problem becomes the relative com¬ 
plexity of selecting one of many simple 
operations versus one of two more com¬ 
plex ones. It’s unlikely that algorithms as 
“rough” as these have ever been pro¬ 
grammed, but more complex approxima¬ 
tions are the hallmark of high-speed com¬ 
puter math. Like most fascinating algo¬ 
rithms, they tend to be deeply buried in a 
mass of machine code, protected by anti¬ 
copying tricks. Competition breeds 
secrecy. PBj 


54 


Dr. Dobb’s Journal, Number 69, July 1982 

309 




OF INTEREST 


by Michael Wiesenberg 


For Your IBM PC 

How about the C language for your 
IBM Personal Computer? Lifeboat Associ¬ 
ates, those wizards who have implement¬ 
ed CP/M on virtually every microcomput¬ 
er, have announced their Lattice C Com¬ 
piler for the IBM PC with DOS. For those 
who have just returned after ten years of 
COBOL programming in Ulan Bator, C 
was developed at Bell Laboratories con¬ 
currently with the UNIX operating sys¬ 
tem. C is both a high- and low-level 
language that offers control over the com¬ 
puter typically found only in assembly 
languages. (And did you know that be¬ 
fore their successful C language, Bell 
Labs had A and B?) Lifeboat’s C compiler 
is a full implementation of Kernighan 
and Ritchie’s specification of C as de¬ 
scribed in their standard text. Lattice C is 
compatible with UNIX Version 7 and BD 
Software C Compiler. It produces relo¬ 
catable machine code in Intel’s 8086 ob¬ 
ject module format. A compile-time op¬ 
tion controls whether this code is gener¬ 
ated for the 8087 floating-point proces¬ 
sor directly or for library functions that 
simulate its operation. The Lattice C 
Compiler includes a library, and I/O sub¬ 
routines for IBM PC DOS and MS-DOS. 
(Reader Service No. 314) 

IBM sells programs for the PC writ¬ 
ten by outside software companies. In¬ 
ventory Control, by Peachtree software, 
assists a small business to improve mer¬ 
chandise control, reduce inventory invest¬ 
ment, and improve customer service and 
response. It can be used alone, or with 
Peachtree’s General Ledger, Accounts Re¬ 
ceivable, and Accounts Payable, and is 
easily customized. $595. (Reader Service 
No. 399) Time Manager Program, by 
Microsoft, is a personal calendar that 
automatically sorts appointments and dis¬ 
plays them chronologically, and a “to- 
do” list that reminds the user of impor¬ 
tant commitments, organized by priority, 
with high-priority items not completed 
on their day heading the list tomorrow. 
Time Manager totals and accounts income 
received, hours worked, and money and 
time expended, giving account totals for 
specified time periods. It produces, for 
example, year-to-date totals for all busi¬ 
ness expenses charged to credit cards or 
paid by cash or check. $100. (Reader Ser¬ 
vice No. 409) Microsoft has also written 
a COBOL compiler for the PC, ANSI 74 
level standard, with extension for color 
and screen formatting. It chains to other 


Dr. Dobb’s Journal, Number 69, July 1982 
310 


programs, can combine object modules 
with those from the IBM PC Macro As¬ 
sembler, and offers segmentation to run 
programs larger than memory. $700. 
(Reader Service No. 419) CP/M-86, 

by Digital Research, is now available, sup¬ 
porting up to two physical or four logical 
drives, with disk formatting, file copying 
to other devices, dynamic memory man¬ 
agement, and offering an editor, assem¬ 
bler, debugger (DDT86), and a program 
that produces command files. CP/M-86 
is not compatible with IBM PC DOS or 
the UCSD p-System, and existing CP/M- 
86 programs running on other computers 
must be converted to run on the IBM PC, 
but, they say, “This is normally per¬ 
formed by the program author as part of 
the development activity.” $240. (Reader 
Service No. 429) IBM offers its own Dow 
Jones Reporter, which accesses the Dow 
Jones News/Retrieval Service, with head¬ 
lines and news stories for the Wall Street 
Journal, Barrons, and the Dow Jones 
News Wire Service, current day market 
quotes, historical stock quotes, and com¬ 
pany profiles and extracts and financial 
statistics on thousands of companies and 
180 industries. This is a software product; 
users supply modems and cables. (Reader 
Service No. 439) An updated VisiCalc 
(1.1), by VisiCorp, that accomodates 
256K and supports additional parallel and 
serial printers, will be provided free to 
warranty registrants. (Reader Service 
No. 445) All programs are available from 
authorized dealers: IBM Product Centers, 
ComputerLand Stores, and Sears Business 
Systems Centers, and in volumes of twen¬ 
ty or more through the IBM National 
Accounts Division. 

Baby Blue CPU Plus is a circuit board 
and software from Xedex that makes the 
IBM PC compatible with CP/M-80-based 
programs and supports serial printers. 
Xedex has acquired OEM (original equip¬ 
ment manufacture) rights to MicroPro 
software, including WordStar and Mail- 
Merge, configured to recognize the IBM 
keyboard’s special keys. Normally Word¬ 
Star requires user modification and can¬ 
not take advantage of the IBM PC’s key¬ 
board. The two software products, nor¬ 
mally sold together for $575, are made 
available with Baby Blue as a $980 pack¬ 
age. The Baby by itself is $600. (Reader 
Service No. 324) 

The FinalWord is a word processor, 
written in C, for the IBM PC, from Mark 
of the Unicom. It can be customized by 
users, supports (they claim) any printer, 


has a table of contents program, indexing, 
footnoting, numbering by chapter/section, 
deletes/moves letter, word, sentence, 
paragraph or page, has multiple buffers 
and windows, deletion recovery, crash 
recovery, state ‘save, true proportional 
spacing, and everything else you’d expect 
from a good WP. The FinalWord is also 
available on most other micros, and costs 
$300. (Reader Service No. 334) 

PHONE SUPPORT, by Information 
Unlimited Software, for the IBM PC, puts 
users of IUS’s Easy Writer on line (during 
normal business hours, Pacific Time, with 
a toll-free 800 number) with service 
representatives who also help with PC 
configuration and simple testing proce¬ 
dures. Single users pay $100 a year, and 
corporations $175. A newsletter is includ¬ 
ed in the price. (Reader Service No 344) 

For Your CP/M DOS 

FNB Software offers several CP/M 
utilities on disk for most computers. 
SMARTKEY adds intelligent keyboard 
facilities to a terminal by intercepting 
calls to the BIOS, so that individual keys 
can be redefined to different character 
codes from that produced by the hard¬ 
ware. For example, cursor control keys 
can be redefined to suit the cursor com¬ 
mands of word processors. Keys can be 
defined to represent strings of any length, 
giving a terminal without them function 
key capabilities. The current set of defi¬ 
nitions can be saved in a disk file or a new 
set loaded without removing SMART- 
KEY from memory. $39. SMARTPRINT 
uses definition tables generated by 
SMARTKEY to translate characters sent 
to the system printer, permitting use of 
non-standard printwheels without manu¬ 
al character translation, use of non-ASCII 
printers or those that cannot generate the 
full ASCII character set, and substitution 
of a character sequence for an unavailable 
character (for example, “.GT.” for “>”). 
$19. FAST speeds up systems with slow 
disk drives, automatically relocating itself 
to the top of available memory, where it 
modifies the linkages to the driver rou¬ 
tines. Once installed, it is transparent to 
the user, except for reduced disk activity 
and throughput, they say, “comparable 
to that of a hard disk system.” WordStar, 
for example, runs three times as fast. The 
only penalty is a reduction in memory of 
7.25K. Since FAST loads below CP/M, 
it can be removed without changing 
disks or SYSGENing a new system. $49. 
The Extension Utility Package includes 


57 



SPOOL, to redirect program output from 
printer, punch, or console to a disk file or 
both, UNSPOOL, to print as a back¬ 
ground activity, QSUB, to “quick sub¬ 
mit” in one line of input several CP/M 
commands, and RESTORE, to recover 
files inadvertently ERAsed, perform con¬ 
sistency checks on the directory, and sort 
a directory by name or type while remov¬ 
ing erased files. $39. UNPROTECT de¬ 
crypts Microsoft BASIC programs saved 
in protected format (preventing LISTing 
or EDITing). $39. FNB will supply up¬ 
dates for the cost of media and a “nomi¬ 
nal handling charge.” (Reader Service 
No.354) 

What? You don’t know how to use 
CP/M? TEACH/M (“teach ’em,” get it?), 
from Select, “helps frustrated users learn 
CP/M in ninety minutes.” This disk for 
noncomputer professionals costs $75. 
(Reader Service No. 364) 

Cheaper, and certainly more com¬ 
prehensive, is a book, Inside CP/M , A 
Guide for Users and Programmers , pub¬ 
lished by Holt, Rinehart and Winston, 
and written by DDJ contributing editor 
Dave Cortesi. The $20, 575-page paper¬ 
back contains two independent parts. The 
first is a comprehensive tutorial on the 
purchase, use, management and program¬ 
ming of a computer system with CP/M. 
The second part is a large reference sec¬ 
tion in which, according to the preface, 
“the answer to any question about 
the day-to-day use of CP/M can be 
found in seconds.” (Reader Service 
No.449) 

UNERA, from Elliam Associates, un¬ 
erases ERAsed CP/M files. UNE2 recovers 
the files, one at a time, or selectively 
from all erased files on a disk, and CON2 
gives the status of erased files that are 
using the same disk space as active files 
(causing a space conflict). Recovering 
such files can clobber active files. The 
manual suggests steps for file recovery in 
this case. UNERA is available for $76.50 
for all CP/M 2.2 systems, single- and 
double-density, floppy and hard disk 
with standard CP/M directories, and for 
single-density 1.4 systems, and can be 
patched to 1.4 double density. “Recover¬ 
ing the results of just one mistake,” they 
tell us, “such as ‘ERA *.BAS’ when you 
meant ‘ERA *.BAK,’ can easily pay for 
the cost of these two programs.” Sounds 
good. (Reader Service No. 374) 

CPMPOWER, from Computing! (I 
love names with !’s in them), is a set of 
45 (!) CP/M housekeeping commands. 


58 


It recovers erased files, calculates check¬ 
sums, tests disk and reserve files for bad 
blocks, lists file size in sector and kilo¬ 
bytes, loads disk files to any memory 
location, reads/writes any track and sec¬ 
tor from/to memory, displays/substitutes 
hex, ASCII, and binary, dumps memory 
in formatted hex/ASCII, searches mem¬ 
ory for ASCII or hex using wildcards, fills 
memory with hex, moves blocks of mem¬ 
ory, lists disk parameters, copies files 
readily by assigning them numbers and 
permitting a copy over a range, as, files 
7-23, 27-33, etc., chains to other .COM 
files, and has four user-configurable cus¬ 
tom commands. All this, and a 60-page 
manual, too for $149! (Reader Service 
No.384) 

Another disk utility package for 
CP/M 2.x comes from ELEKTROKON- 
SULT in Norway. They claim the product 
is unique because it automatically adapts 
to any diskette format. DDUMP examines 
and patches any byte on any sector, to 
study how CP/M allocates disk storage 
and to examine or repair a damaged disk 
and recover lost data. DTEST tests a disk 
for bad spots, locking bad sectors out 
from later use by CP/M by automatically 
collecting them in a “garbage” file. This 
reduces the likelihood of later disk 
crashes. DUSER permits access from one 
user area to programs/files on other user 
areas, without having to keep duplicate 
copies of files on the disk. DDUP dupli¬ 
cates disks independent of disk control¬ 
ler, drive, disk size, and format, and re¬ 
places bad sectors on the source disk with 
blank sectors on the destination, permit¬ 
ting recovery from damaged files. Now 
here’s an anomaly. They too have an 
UNERA that recovers accidentally e- 
rased files (they even spell it the same, 
“ERAsed”). These utilities cost $29.95 
each, or all five for $ 125. All five manuals 
alone, $20. Add $8 handling and shipping 
for each order, and specify format. 
(Reader Service No. 394) 

For those doing development for the 
TI TMS7000 series microprocessors, 
Allen Ashley claims that his SYSTEM- 
TMS7 is the only CP/M cross-assembler 
for these processors. The software system 
features a macroassembler with full 
macro and conditional assembly as well as 
the ability to chain a series of source files 
together during a single assembly, an in¬ 
teractive editor/assembler, a text edi¬ 
tor, and offloading facilities. He also 
sells cross-assemblers for the National 


COP400 and 70-series, Intel 8048 and 
8051, Zilog Z8, RCA 1802, AMI S2000, 
and Fairchild/Mostek F8/3870 proces¬ 
sors. SYSTEM-TMS7 costs $150, includ¬ 
ing complete documentation and full user 
support by mail or phone. (Reader Ser¬ 
vice No. 404) 

A 60K CP/M System Upgrade Kit for 
IMSAI costs $255 with CP/M, or $175 
for just CP/M and $75 for just the kit. 
(Reader Service No. 414) 

The Catalog of Public Domain Soft¬ 
ware for CP/M, Book 2, consisting of 
tables of contents and abstracts of files, 
and document files contained on diskette 
volumes published by the CP/M Users 
(sic, sans apostrophe) Group and the 
SIG/M (Special Interest Group/ Micro¬ 
computers), is available from the New 
York Amateur Computer Club for $10. 
There is also, naturally enough, a Book 1. 
(Reader Service No. 424) 

Here’s a freebie from Digital Re¬ 
search: the Technical Support Group of¬ 
fers a set of CP/M 2.2 patches and ap¬ 
plication notes, “Using PIP with XSUB,” 
“Auto Loading Programs,” “Making De¬ 
lete (Rubout) Work Like Backspace,” 
“Improving the Control-S Function,” 
and “Nested Submit Files.” Request must 
be written and include the user’s CP/M 
license number. CP/M users who have not 
sent in their registration cards can include 
them. Write to: CP/M 2.2 Application 
Notes, Technical Support, Digital Re¬ 
search, Box 579, Pacific Grove, CA 
93950. 

Buy Some Hardware 

The TI LCD Programmer converts 
floating-point numbers between hexa¬ 
decimal, decimal, and octal. There is a 
two’s complement key, bit-by-bit logical 
operations, and fifteen sets of parentheses 
at each of four processing levels. Inmac 
sells it for $75 on a 45-day free trial 
basis, with one-year warranty against 
material defect and workmanship. How 
can you go wrong? (Reader Service 
426) 

Anyone who’s had a crash from a 
spike on the line will appreciate Ico- 
Rally’s Surge Protector. Sporting a 25 
nanosecond response time, it can dissi¬ 
pate 950,000 watts at 100 microseconds, 
at its rated 15 amps and 120 volts AC, 
and costs a mere $39.95. (Reader Service 
No.434) 

If your only IBM product is a Selec- 
tric, Electric Typing Fingers (ETF-80), 


Dr. Dobb’s Journal, Number 69, July 1982 

3iT 


from Personal Micro Computers, can turn 
it into a printer. The unit sits atop the 
typewriter keyboard, which needs no 
modification (and thus the manufactur¬ 
er’s warranty remains in force), and 
plastic-tipped solenoids press the keys 
just as would a typist. Electric Typing Fin¬ 
gers runs on many popular computers, in¬ 
cluding the IBM PC, and operates the Se- 
lectric and other compatible typewriters. 
It needs no additional software, and costs 
$595. (Reader Service No. 444) 

Osborne announced a Double Den¬ 
sity Upgrade kit for the Osborne 1. It 
doubles storage to 184K, and reads and 
writes other formats, such as the Xerox 
820. The system automatically recog¬ 
nizes different densities when diskettes 
are changed. Consisting of a printed cir¬ 
cuit board, 2732A ROM, double-density 
system diskette, and user’s manual, the 
kit costs $185 and is available at Osborne 
dealers. (Reader Service No. 454) 

The Fox is Digital Microsystem’s new 
DSC-3/F CP/M desktop computer, a 30- 
pound portable unit incorporating a nine- 
inch CRT, two 5-1/4-inch single- or 
double-density double-sided floppies 
(with a formatted capacity of 307.2K per 
drive), twelve programmable function 
keys, an interface for the company’s local 
area network (HiNet) that can support 32 
users and address up to 255, four RS- 
232C serial ports, two eight-bit bidirec¬ 
tional parallel ports with status lines, 64K 
of RAM and IK of ROM. The processor 
is a Z-80A, providing an access speed of 
250 nanoseconds, with no wait states. 
Programmable CRT control codes provide 
compatibility with other software drivers, 
so that the Fox can emulate any other 
terminal. The package includes business 
application software. Two word proces¬ 
sors are offered, two data base manage¬ 
ment systems, budget and finance pro¬ 
grams, and several programming lan¬ 
guages, including BASIC, COBOL, PL/1, 
FORTRAN, and Pascal. It sounds like 
quite a system for $3995. (Reader Ser¬ 
vice No. 459) 


Sell Some Software 

Lifeboat Associates is offering a free 
publication, Guidelines for Software 
Authors. It addresses, among others, 
these questions'. How should you prepare 
a software package for evaluation? What 
kind of documentation should you in¬ 
clude with a submission? What about 
your legal rights? If your program is 


accepted, what next? (Reader Service No. 
464) 

Peachtree Software seeks quality, 
well-documented applications software 
for micros. (Reader Service No. 474) 

Pocketlnfo asks authors of quality 
applications software for hand-held com¬ 
puters (TRS-80 pocket computer, Sharp 
PC -1211, and Casio FX - 702P) to contact 
them for a copy of procedures and a non¬ 
disclosure agreement prior to submis¬ 
sion. (Reader Service No. 484) 

Atari has opened a regional center for 
the development and acquisition of soft¬ 
ware programs for home computers in 
the Boston area, at the Crimson Galleria, 
in Cambridge. This center is the second 
of its kind — the first is at corporate 
headquarters in Sunnyvale, California - 
and will “provide a place where qualified 
software developers can work with Atari 
computers, have access to our technical 
reference materials, and be able to work 
with our staff . .. who can answer their 
questions about our computers.” The 
center will also house a facility for con¬ 
verting programs written for other com¬ 
puters to Atari format. Atari wishes to ac¬ 
quire software in the fields of entertain¬ 
ment, self-improvement, home manage¬ 
ment, education, and system software. In 
addition to developing their own soft¬ 
ware, marketing user-written software 
through the Atari Program Exchange, and 
working with other established software 
publishing houses, especially in the edu¬ 
cational area, Atari encourages third- 
party developers. They plan other such 
centers in areas with high concentrations 
of programmers and users. (Reader Ser¬ 
vice No. 494) 

... Well, at Least Join a User Group 

CP/M user groups include the New 
York Amateur Computer Club, Box 106, 
Church Street Station, New York, NY 
10008; the CP/M Users Group, 1651 
Third Avenue, New York, NY 10028, 
and SIG/M (Special Interest Group/ 
Microcomputers), Box 97, Iselin, NJ 
08830. 

CP/M users will also be interested in 
PicoNet, which meets monthly in Dysan 
in Santa Clara, CA. $20 a year gains 
access to a large library of member- 
contributed software and a newsletter. 
Box 2070, Sunnyvale, CA 94087. 

For those who thought the Sorcerer 
had died (including me; I have one), the 
Sorcerer’s Apprentice Users Group pub¬ 
lishes a fact-filled 24-page newsletter 


with information about Exidy machines 
that can be found nowhere else, main¬ 
tains a Sorcerer CBBS system in the 
Detroit area (313-535-9186 ringback), 
and makes a lot of wonderful software 
available. Membership is $18 a year, or 
$24 for the newsletter sent first class. 
Sorcerer’s Apprentice, Box 33, Madison 
Heights, MI 48071; (313) 286-9265. 

North Star owners can join the In¬ 
ternational North Star Users Association 
for $20 a year. Box 1318, Antioch, CA 
94509. 

Membership dues in the MUMPS 
Users’ Group of North America (MUG), 
are $40 a year, and include a subscription 
to MUG-Quarterly, discounts on MUG 
publications, and voting privileges. 
MUMPS Users’ Groups, Box 37247, 
Washington, DC 20013. (301) 779-6555. 
(They must be very professional. They 
seem to be the only ones who know 
where the apostrophe belongs!) 




Dr. Dobb’s Journal, Number 69, July 1982 
312 


59 



SOFTWARE REVIEWS 


Volks writer 

Lifetree Software 
$195 

Circle No. 489 on Reader Service Card 

Reviewed by Robert K. Funkhouser 

VOLKSWRITER, a product of Life- 
tree Software, is designed specifically for 
the IBM Personal Computer. It makes ex¬ 
tensive use of the cursor control keys, 
function keys and other special keys of 
the PC keyboard to make word process¬ 
ing an easy task. VOLKSWRITER is writ¬ 
ten in IBM Pascal and runs under the 
DOS operating system. 

The software was tested on a single¬ 
drive system with 64K RAM. Using a 
single drive posed no problems, just the 
usual hassle of switching diskettes to save 
and retrieve files. The amount of RAM, 
however, proved a serious limitation. 

VOLKSWRITER is advertised as a 
high-performance word processor. In¬ 
deed, most commands and functions are 
performed extremely fast. However, on a 
64K machine you are left with just 1 OK 
memory for editing. This is a serious limi¬ 
tation, as 10K is just too small. The 
VOLKSWRITER documentation states 
that up to 128K can be used, and strong¬ 
ly recommends you have that much mem¬ 
ory. On a 128K machine, you will have 
60K available to hold edited data. 

The documentation is good. It is easy 
to read and is structured for quick refer¬ 
ence. Three tutorial files come on the 
program diskette. These guide you 
through the use of function keys and 
other special keyboard keys used in edit¬ 
ing. It requires only a couple of hours, 
using the tutorials and the manual, to de¬ 
velop proficiency with all of VOLKS- 
WRITER’s features. Learning to use it 
was quick, easy and fun. 

There are two main menus: an Edi¬ 
tor menu and a Printer menu. The Editor 
menu contains the full range of editing 
functions and minor printing capabilities. 
The Printer menu is used to print docu¬ 
ments but also has minor editing func¬ 
tions. Thus, you would normally start 
with the Editor menu, edit and save a file, 
then call the Printer menu to create a 
print format and print the file. 

Editing 

Under the Editor menu the follow¬ 
ing can be done: 

Display files on diskette 
Retrieve a file for editing 
Edit a file 


Store a file on diskette 
Select a print format for use 
Clear memory for editing a new file 
Rename files 
Delete files 

Select the Printer Menu 
Display HELP text 
Exit VOLKSWRITER 

The main purpose of a word proces¬ 
sor is to manipulate text, and the VOLKS- 
'WRITER is up to the task. The editing 
functions make extensive use of the spe¬ 
cial keys on the keyboard. The following 
shows the editing functions and the key¬ 
board keys associated with them: 

Cursor and text movement: 


Home 

moves cursor to the upper 
left corner of the screen 

End 

moves cursor to the lower 
left corner of the screen 

->■ 

moves cursor to the right 

«- 

moves cursor to the left 

t 

moves cursor up; if the cur¬ 
sor is at the top of the screen 
it forces upward scrolling 

4 

moves cursor down; if the 
cursor is at the bottom of 
the screen it forces down¬ 
ward scrolling 

Ctrl + -*• 

moves cursor to the next 
word 

Ctrl + <- 

moves cursor to the previ¬ 
ous word 

Tab 

tabs to preset columns 

Ctrl + Home 

moves the cursor to the first 
character of text 

Ctrl + End 

moves the cursor to the last 
character of text 

Pg Up 

scrolls upward one-half 
screen 

Pg Dn 

scrolls downward one-half 
screen 

Ctrl + Pg Up scrolls upward one screen 

Ctrl + Pg Dn scrolls downward one screen 

Inserting text: 

Ins 

inserts characters; if inser¬ 
tion pushes the line past the 
right margin, a new line is 
started 

F3 

inserts a new line 

Alt + F3 

inserts a section symbol 
marking the end of a page 
(used in printing) 

Alt + F2 

inserts text from another file 


Deleting text: 

Del deletes characters 

F4 deletes a word: if the cursor 

is in the middle of a word 


only the text to the right of 
the cursor is deleted 

Alt + F4 deletes characters from the 
cursor position to the end 
of the line; if the cursor is 
in column 1 then the en¬ 
tire line is deleted 

Alt + F8 deletes a block of text 
All other functions: 


F5 

defines the beginning of a 
block 

F6 

defines the end of a block 

Alt + F5 

moves a block of text 

Alt + F6 

copies a block of text 

Alt + F8 

deletes a block of text 

FI 

Help; displays function key 
settings 

Alt + FI 

Prints text from cursor posi¬ 
tion to the end of the file 

F2 

writes the entire text or por¬ 
tions of the text to a file 

F7 

Find; finds a specified string 
and places the cursor at the 
string 

Alt + F7 

Replace; replaces one string 
with another. This may be 
done for one, several or all 
occurrences of the string. 

F8 

Reformat; reformats text 
until an end of paragraph or 
end of page symbol is found. 

F9 

used to set tab positions and 
the right margin 

Alt + F9 

centers line of text within 
margins 

FI 0 

Reset; cancels block defini¬ 
tions, stops printer, resets 
F7 strings, etc. 

Alt + FI 0 

Exit; return to main menu. 


All of the above functions proved 
easy to use. Perhaps as significant, these 
functions are easy to remember. The uses 
of the cursor control keys relate well to 
the names of the keys. After using 
VOLKSWRITER for about thirty min¬ 
utes, the uses of those keys were well 
in mind. Recalling the purposes of the 
function keys is a snap, simply enter FI 
to see the settings. 

Throughout all menus, VOLKS¬ 
WRITER displays a status line at the bot¬ 
tom of the screen. This line shows the 
name of the file being edited, and the 
status of a Retrieve, Store, Print, etc., 
activity. The status line also has a “gas 
gauge” which shows what percentage of 
memory (left after VOLKSWRITER was 
loaded) is available for use. When this per¬ 
centage falls below 10, the percentage 
display begins to flash. It’s meant to get 


Dr. Dobb’s Journal, Number 69, July 1982 


61 

313 




your attention and it works. When the 
percentage gets to zero (or near zero) the 
speaker is beeped ten times in a shrill 
tone and you are instructed to immedi¬ 
ately save the file. This feature, coupled 
with VOLKSWRITER’s insistence (almost 
to the point of being annoying) that you 
respond to a Yes/No prompt before tak¬ 
ing any action that would erase memory, 
makes it very hard to accidentally lose 
what you have edited. 

Printing 

VOLKSWRITER uses “print for¬ 
mats” which define the characteristics of 
the printout. How many lines per page, 
what line to put page numbers (if- any) 
on, what page number to begin with, 
margin specifications, number of extra 
spaces (if any) between lines, along with 
several other options. Formats are also 
used to specify left and right justification. 
Left and right justification is performed 
on the screen by using the F8 (paragraph 
reformat) key. 

Some of the options pertain strictly 
to the IBM (or Epson) dot matrix printer, 
such as dark printing, double strike print¬ 
ing, 40, 66, 80 or 132 characters per line. 
When used with the NEC Spinwriter 
printer, VOLKSWRITER issues codes for 
inter-line spacing and horizontal motion 
index at the start of executing the Print 
command. 

A format may be set for a single use 
or you may save the format as a file for 
later use. This technique makes it easy to 
set up standard formats for particular 
kinds of documents as well as the crea¬ 
tion of custom formats for a single use. 

The Printer menu is like the Editor 
menu except it allows you to set up a 
new format, print, and return to the Edi¬ 
tor menu. While you may do editing 
through this menu, not all of the editing 
functions are available In particular, the 
block functions, block moves, copies, 
etc. are not available. Thus, editing 
through this menu would normally be 
done for minor changes only, such as last 
minute changes before printing. 

Printing may also be done by placing 
. .PRINT and . .FORMAT commands in 
the text. Here’s an example: 

. . FORMATCONTENTS.FMT 

. . PRINTCONTENTS.TEX 

. .PAUSEInsert new forms 

The first line will call in the print 
format CONTENTS.FMT and the second 
line will cause CONTENTS.TEX to be 


printed using the CONTENTS.FMT for¬ 
mat. The . .PAUSE will print the message 
“Insert new forms” and cause a system 
wait until any key is pressed. By using 
this technique you can print several files 
at one time or call in “boilerplate” text 
files at specific points. This is also the 
way to print a file or files that are too 
large to fit into memory. 

Shortcomings 

The only problem encountered was 
when doing a reformat of a paragraph 
(the F8 key) which contained a continu¬ 
ous string of characters longer than one 
line. I was playing with the command 
(one would normally not have such a 
character string in a paragraph) when the 
problem occurred. An “Lstring too 
long. . .” error was displayed, and 
VOLKSWRITER went down. I restarted 
it by entering VW (normal startup) and, 
as expected, the file I was editing was 
gone. Although this situation might never 
occur in “real use,” It’s always disap¬ 
pointing when software fails and informa¬ 
tion is lost. 

Another complaint regards the mes¬ 
sages displayed when it is necessary to 
switch diskettes. These are really DOS 
messages and they are often placed in the 
middle of menu displays, making them 
difficult to read and often confusing. 
Once you get used to this, however, it 
presents no functional problems, just 
some messy messages. Two-drive systems 
should not have this distractive situation. 

If you replace all occurrences of a 
given string with a longer string you wil 
find that all paragraphs which have been 
changed will need reformatting (F8). You 
have to page through your text and press 
F8 for each paragraph that needs refor¬ 
matting. It would nice if there were a 
“global reformat” function to speed the 
process. 

Summary 

Performance was very good, albeit 
at the expense of‘memory. VOLKSWRIT¬ 
ER sells for $195, but if you have just 
64K you should add the price of another 
64K. I had not planned to expand the 
memory on my machine, but after using 
VOLKSWRITER, and seeing the dramatic 
increase in my writing speed, I’m not 
complaining too loudly about having to 
get more memory. I would probably need 
it or want it sooner or later, anyway. 
VOLKSWRITER itself will use 14K more 


if you have 128K, which leads me to be¬ 
lieve it will require even fewer trips to 
disk, thus improving response time when 
moving between menus. 

My overall impression of VOLKS¬ 
WRITER is very positive. It allows for 
excellent control of the printout, has ex¬ 
cellent protection against data loss (dis¬ 
counting the odd reformat crash) and 
fully uses the IBM-PC keyboard. It also 
allows the fonts and darkness options 
of the IBM matrix printer to be easily 
used. It is a good piece of software 
tailored to match a good machine. 


Wrlte-On 

Spiecher Systems 
Published by Datamost 
$129.95 

Circle No. 499 on Reader Service Card 
Reviewed by Jerry C rim mins 

Write-On! is a converted Applesoft 
program from Speicher Systems. Being 
written in Microsoft Basic for the Apple 
Computer probably made this program 
easy to convert to Microsoft for the IBM. 
It also could be why Ctrl-C is used as an 
imbedded character to center a line (this 
can cause an unintentional break, but 
text is not lost). This may explain why 
the editor in the program runs slower 
than other word processors. But the ex¬ 
perience gained from Betsy Speicher’s 
previous Apple adventure obviously 
carried over to this program. 

Unlike another widely advertised 
word processor for the IBM Personal 
Computer, Write-On! will read, write, or 
merge any standard IBM Personal Com¬ 
puter ASCII file. For some people, that 
alone may be reason enough to buy 
Write-On! There are many good things 
about this word processing package. It 
has an impressive array of formatting and 
printer commands that allow the user to 
easily re-arrange text, and to add num¬ 
bers and titles to pages or entire chapters 
with only a few keystrokes. All margins 
are adjustable, 20 pre-set headers are 
available that can be cleared and re¬ 
defined during an edit session, and 9 tab 
settings can be cleared and reset. Block 
transfers in the editor are easy to learn 
and do, global changes are easy, and text 
can be formatted and previewed on the 
screen before printing. In short Write- 
On! does anything that those other word 
processors do. 


62 

314 


Dr. Dobb’s Journal, Number 69, July 1982 


In one instance, a form letter can be 
created that will prompt a typist to enter 
the appropriate text in the appropriate 
place. Similarly, a form letter will read a 
data file containing the appropriate kinds 
of data input, while it prints. Combine 
this capability with disk image files (text 
stored on disk in a formatted version) to 
store form letters, then make a mailing 
list data file by using the included data 
file writer, and print form letters automa¬ 
tically. One of the on-disk examples is a 
form letter (and another is an invoice 
billing) set to read data files. 

Write-On! is good, but it is not per¬ 
fect. It doesn’t support the underlining or 
overstrike capability of the IBM printer 
(Epson). 

A touch-typist might never realize 
that there are better editors than the one 
provided with Write-On! But a non¬ 
typist (like myself) may find the current 
line pointer a little difficult to manipu¬ 
late. It is done by entering commands 
U (up) or D (down) followed by the num¬ 
ber of the lines you wish to move. Per¬ 
haps a scrolled pointer, or the addition of 
line numbers to the text would be suffi¬ 
cient. With neither option, it is difficult 
to place the pointer on the right line, 
especially when seeking text that is off 
the screen. 

There are some good parts to the edi¬ 
tor. It does make use of the cursor con¬ 
trol keys on the number keypad (within 
one 255 character line). The “Ins” and 
“Del” keys, the “End” and “Ctrl End” 
(delete line from cursor to end) keys 
work in the edit command mode by push¬ 
ing the return key. This editor is quite 
sufficient and will do the job for anyone. 
All the commonly used control characters 
are in the typewriter area of the key¬ 
board, which is good for the touch-typist. 

The documentation that comes with 
Write-On! is slow and easy, but it does 
contain everything. The biggest need is 
for more examples of unformatted text 
in the manual, where it can be referred to 
while typing in a file. The manual does 
contain all the necessary information to 
teach a beginner how to use the pro¬ 
grams, which is more than most manuals. 

There is an error message index in 
the back and a handy reference card 
(prompter) with commands, defaults, and 
syntax. 

The best part of the documentation 
is the files on the Write-On! diskette that 


illustrate the unformatted, versus the for¬ 
matted text. These are excellent exam¬ 
ples. In addition to the previously men¬ 
tioned form letter is a billing invoice, a 
meat loaf recipe, and an outline of the 
entire history of Middle Earth. 

Write-On! is as powerful as other 
microcomputer word processors, and it 
costs less. Compared to Word Star or 
Easy Writer 1.11, Write-On! is better 
prepared to be all things for all users. 
True, the editor is not a machine lan¬ 
guage routine with fast vertical and 
horizontal scroll; but it does work and 
doesn’t introduce lots of new keys to 
touch-typists. 

The power of the imbedded printer 
commands, and the disk file commands 
allows Write-On! to fill commercial uses 
right away. 

After using this software to write 
some letters (and of course this review), I 
had some questions for Datamost and 
Betsy Spiecher — I had trouble getting 
files to and from drive b. No problem, I 
was told, use b:File.Spc (no space be¬ 
tween and “File”). 

Another subject we discussed was 
backup copies; everyone talks about 
copying. If a program is not backed up 
an investment may be wasted, or a cus¬ 
tomer may experience an unacceptable 
delay. Write-On! is copyable, and this 
recommends the product over those pro¬ 
grams that can’t be backed up. Another 
good thing about Basic is that it is easy to 
modify. The company says that an im¬ 
proved editor is on the way, with an even 
better manual (the entire manual was set 
using Write-On!). Datamost was very 
helpful, and it was a pleasure to talk with 
the author of the program. 

I obviously appreciate this software. 
It is a writing utility, it handles files and 
records, it handles the printer, and it 
handles the editing. It is not fast and it 
doesn’t scroll. But there is no other one 
package I could find which does every¬ 
thing that Write-On! does, and especial¬ 
ly not for the IBM Personal computer. 
After a quick update to support underlin¬ 
ing on the IBM/Epson printers (yes, the 
Epson 100 also), and a little souping up 
on the editor, it will be difficult to find 
a better word processor for any micro. 




Dr. Dobb’s Journal, Number 69, July 1982 


63 

315 




Small-C for the 9900 


I n number 54 of Dr. Dobb’s, Ron Cain 
published his subset C compiler, writ¬ 
ten in its own language. For $15 1 ob¬ 
tained from The Code Works a working 
version (CP/M Version N - April 1, 1981) 
of this compiler, complete with a runtime 
interface to CP/M. I proceeded to rewrite 
the code generator part to produce assem¬ 
bly code for my 9900, an earlier acquisi¬ 
tion without disks of its own but having 
access to disks via an interface to my 
CP/M machine. Thus I now write C pro¬ 
grams which I cross-compile to run on 
the 9900. 

The model of the machine addressed 
by Ron’s compiler involves 16-bit pri¬ 
mary and secondary registers, and a stack. 
Since the 9900 is a 16-bit machine, I 
thought at first that the conversion would 
be straightforward. It was not. One very 
minor problem is that the 9900 does not 
use a stack for return addresses in making 
subroutine calls. More serious is the fact 
that it does not want to access word 
(i.e., 16-bit) operands unless they are 
aligned on word boundaries. 

The solution to the first problem is 
to create a stack: I used general register 
0 (denoted R0 in what follows) as the 


by Matthew Halfant 


Matthew Halfant, Bedford Computer 
Corp., Tirrell Hill Rd., Bedford, NH 
03102. 


stack pointer. The 8080 instruction 
CALL SUBR 
is replaced here by 

BL @SUBCAL 
DATA SUBR 

where SUBCAL is a single routine posted 
in the preamble of the generated code, 
which branches to SUBR after saving the 
return address on the stack. The code for 
SUBCAL is 

SUBCAL MOV *R1 1+,R3 
DECT R0 
MOV R11 ,*R0 
B *R3 

The return from a subroutine is effected 
by B @SUBRET, where SUBRET is sim¬ 
ply 

SUBRET MOV *R0+,R3, 

B *R3 

As mentioned above, a far more 
serious problem concerned operand align¬ 
ment. Global variables are given reserved 
space in RAM, so that, for example, a 
program beginning 
int x; 
char c; 
int z; 
main() 

{ ... 

would produce, in the assembly listing 

ZX BSS 2 
ZC BSS 1 


ZZ BSS 2 

(the prefix z — Code Works uses qz — 
prevents conflict with assembler key¬ 
words). Since c is a char, it will be ac¬ 
cessed with a MOVB instruction (MOVe 
Byte), not sensitive to alignment. But z 
will be accessed as a word, and we see 
that it may not be aligned as things stand. 

A similar thing occurs with local 
variables, for which space is reserved on 
the stack. In my first pass at rewriting 
the code generator, I compromised the 
9900 by forcing byte moves, rather than 
risk word moves that could not be 
guaranteed to work. Except for some 
register-to-register operations, I was cut¬ 
ting a poor figure compared to the 8080 
for which the original was written. The 
size of the generated code was excessive. 
For example, the 8080 pushes its primary 
register (HL) on the stack with 

PUSH H 

and I was achieving the same thing with: 
DEC R0 
MOVB R1 ,*R0 
SWPB R1 
DEC R0 
MOVB R1,*R0 
SWPB R1 

Not ideal. 

The correct approach, which I subse¬ 
quently adopted and advocate here, is to 
modify the compiler itself so that align¬ 
ment is preserved. This is done very sim¬ 
ply as follows. The routine dumpglbsQ, 
from ccl, generates the storage definition 
statements illustrated above (see Figure 
1). A test is made to see if an odd number 
of bytes is being reserved; if so, that num¬ 
ber is incremented by 1. The inserted line 
if Cj&l) j++; does the job. 

For the situation with local variables, 
the identical approach is applied, this 
time to declloc(typ), which is the last 
function in ccl. The inserted line is as 
before, here using k in place of j (see 
Figure 2). 

With these changes, I was able to 
rewrite the code generator cc8 as shown 
in Listing I. In adapting cc8 to other 
16-bit machines, it may be well to in¬ 
corporate the above changes even if the 
machine will allow unaligned accesses; the 
code is bound to run faster and the cost 
in additional storage is small. 

By the way, some minor additional 
alterations were needed for the case of 
the 9900, and I mention them here for 


Figure 1 

dumpglbs() 

( 

int j; 

if(glbflag==0)return; /* don't if user said no */ 

cptr=startglb; 

while(cptr<glbptr) 

{if(cptrlident][“function) 

/* do if anything but function */ 

{outname(cptr);col(); 

/* output name as label... */ 
defstorageO; /* define storage */ 
j=((cptr[offset]&255)+ 

((cptr [of f set+1] &255)«8) ); 

/* calc # bytes */ 
if((cptr[type]==cint)| 

(cptr [ident]==pointer)) 

if(j&1) j++; /* 9900 addition: reserve even */ 

outdec(j); /* number of bytes */ 

nl(); 

} 

cptr=cptr+symsiz; 

> 

> 


66 

316 


Dr. Dobb’s Journal, Number 69, July 1982 




those who want to make use of what I’ve 

done. 

1. Change # define litabsz 2000 before 
attempting any additions to the com¬ 
piler. I use 4000. 

2. In main(), I invert the order of calling 
dumplits() and dumpglbs(). Thus the 
string literals are dumped last, using 
the BYTE pseudo-op. Doing it the 
other way would require insertion of 
an EVEN pseudo-op between the two. 

3. The function col(), which, prints a 
colon, is rendered a no-op. This is used 
only to add a colon following state¬ 
ment labels, which the 9900 assembler 
does not want. 

4. The statements #define asmpref 7, 
#define asmsuff 7, are modified to 
use constants 5 and 0, respectively. 
The routine outname(sname), from 
cc8, prefixes only “z” instead of“qz” 
as in the original, which results in 
maximum symbolic name lengths of 6. 


This unfortunate restriction is imposed 
by the 9900 assembler. 

In addition to the code generator, 
it is necessary to write a runtime library 
containing the functions getcharQ, 
putchar(c), gets(buff), puts(string), 
fopen(name,mode), fclose(ptr), getc(ptr), 
putc(c,ptr), and cpm(bc,de). These are 
described in the 11-page manual supplied 
by The Code Works with their diskette. 
Adherence to their definitions guarantees 
that the compiler can be bootstrapped to 
the target machine. 

(The function cpm() is used only 
once in The Code Works version, and the 
reference can be eliminated. That makes 
it unnecessary to include the function 
with the run-time library.) »»j 

(Listing begins on page 68) 


Figure 2 

declloc(typ) /* typ is cchar or cint */ 

int typ; 

{ 

int k,j;char sname[namesize]; 
while(l) 

{while(l) 

{if(endst())return; 
if(match("*")) 
j-pointer; 
else j-variable; 
if (symname(sname)--O) 
illname(); 
if(findloc(sname)) 

multldef(sname); 
if (match("[")) 

{k=needsub(); 
if (k) 

{j=array; 

if(typ-=cint)k-k+k; 

} 

else 

{j-pointer; 

k-2; 

> 

} 

else 

if ( (typ==cchar) 

&(j!-pointer)) 
k=l;else k=2; 

if(k&l) k++; /* for 9900: keep stack word-aligned */ 
/* change machine stack */ 

Zsp-modstk(Zsp-k); 
addloc(sname,j,typ.Zsp); 
break; 

} 

if (match(",")-=0) return; 

} 

} 


CP/M Exchange 

(Continued from page 9) 


work to do that does not require any 
printer output and I’d like to keep it 
“OFF”. 

Sincerely, 

A Dedicated Reader 

Without your input this feature will 
not continue. Figure out what you have 
learned that will benefit others and/or 
problems you have yet to solve. Send 
them to the CP/M Exchange. I think I 
can safely say that whatever interests you 
will also interest other readers of this 
column. Information exchange ends when 
the data is acknowledged as received cor¬ 
rectly. Information exchange begins when 
you ask a question or share an idea. 


Dr. Dobb’s Journal, Number 69, July 1982 


67 

317 




Small-C for 9900 (Text begins on page 66) 


CODE GENERATOR FOR THE 9900 

/* »»» start of cc8 «««< */ 

/* Begin a comment line for the assembler */ 
comment() • 

{ outbyte('*'); 

> 

/* Put out assembler info before any code is generated */ 
header() 

{ comment(); 

outstr(BANNER); 
nl(); 

comment(); 
outstr(AUTHOR); 
nl(); 

comment(); 
outstr(VERSION); 
nl(); 

comment(); 

nl()i 

if(mainflg){ /* do stuff needed for first */ 

outstr("TOPMEM EQU >8800"); /* initial stack pointer */ 
nl(); 

ol("DREG"); 

ol("A0RG >100"); 

ol("JMP START"); 

outstr("SUBCAL MOV *R11+,R3"); 

nl(); 

ol("DECT R0"); 

ol("M0V R11,*R0"); /* push return address on stack */ 

olf'B *R3"); 

outstr("SUBRET MOV *R0+,R3"); /* pop address from stack */ 

nl(); 

ol("B *R3"); 

outstr("START LI RO.TOPMEM"); /* R0=stack pointer */ 
nl(); 

zcall("main"); /* call the code generated by small-c */ 
zcall("exit"); /* do an exit gtf 7/16/80 */ 

> 

> 

/* Print any assembler stuff needed after all code */ 
trailer() 

{ 

ol("EVEN"); 

ol("DATA -1"); /* 9900 assembler seems to need this */ 

ol("END"); 
comment(); 

outstr(" - End of Compilation -"); 

nl(); 

> 

/* Print out a name such that it won't annoy the assembler */ 

/* (by matching anything reserved, like opcodes.) */ 

/* gtf 4/7/80 */ 
outname(sname) 
char *sname; 

{ int len, i,j; 

outasm("z"); 
len = strlen(sname); 
if(len>(asmpref+asmsuff)){ 
i = asmpref; 

len = len-asrapref-asmsuff; 
while(i— > 0) 

outby te(raise (*sname-H-)); 
while(len— > 0) 
sname++; 
while(*sname) 

outbyte(raise(*sname++)); 

> 

else outasra(snarae); 

/* end outname */} 

/* Fetch a static memory cell into the primary register */ 
getmem(sym) 

char *sym; 

{ if((sym[ident]I=pointer)&(sym[type]==cchar)) 

{ot("MOVB @"); 

outname(sym+name); 

outstr(",R1 ;getmem(),char"); 

nl(); 


ol("SRA R1,8"); 

> 

else 

{ot("MOV @"); 
outname(sym+name); 
outstr(",Rl ;getmem(),int"); 
nl(); 

> 

> 

/* Fetch the address of the specified symbol */ 

/* into the primary register */ 
getloc(sym) 

char *syra; 

{ immed(); 

outdec(((sym[offset]&255)+ 

( (sym[of fset+1] &255)«8))- 
Zsp); 

outstr(" ;getloc"); 
nl(); 

ol("A R0,R1"); /* add stack pointer to primary */ 

> 

/* Store the primary register into the specified */ 

/* static memory cell */ 
putmem(sym) 

char *sym; 

{ if((sym[ident]!=pointer)&(sym[type]==cchar)) 

{ol("SWPB Rl"); 
ot("MOVB Rl,@"); 
outname(sym+name); 
outstr(" ;putmem(),char"); 
nl(); 

ol("SWPB Rl"); 

> 

else {ot("M0V Rl,@"); 
outname(sym+name); 
outstr (" j*putmem() , int"); 
nl(); 

> 

> 

/* Store the specified object type in the primary register */ 
/* at the address on the top of the stack */ 
putstk(typeobj) 
char typeobj; 

{ zpop(); 

if(typeobj==cint) 

{olf'MOV Rl,*R2 ;putstk(),int"); 

/* primary stored indirect through sec */ 

> 

else { ol("SWPB Rl ;putstk(),char"); 
ol("MOVB Rl,*R2"); 
ol("SWPB Rl"); 

> 

> 

/* Fetch the specified object type indirect through the */ 

/* primary register into the primary register */ 
indirect(typeobj) 
char typeobj; 

{ if(typeobj==cchar) 

{ol("M0VB *R1,R1 ;indirect(),char"); 

ol("SRA Rl,8"); 

> 

else {ol("M0V *R1,R1 ;indirect(),int"); 

> 

> 

/* Swap the primary and secondary registers */ 
swap() 

{ ol("M0V Rl,R3 ;swap()"); 

ol("MOV R2,R1"); 
ol("M0V R3,R2"); 

> 

/* Print partial instruction to get an immediate value */ 

/* into the primary register */ 
immed() 

{ ot("LI Rl,"); 

> 

/* Push the primary register onto the stack */ 
zpushQ 

{ ol("DECT R0 ;zpush()"); 


68 

318 


Dr. Dobb’s Journal, Number 69, July 1982 


ol("MOV R1,*R0"); 

Zsp=Zsp-2; 

> 

/* Pop the top of the stack into the secondary register */ 
zpop() 

{ ol("MOV *R0+,R2 ;zpop()"); 

Zsp=Zsp+2; 

> 

/* Swap the primary register and the top of the stack */ 
swapstk() 

{ ol("MOV R1,R3 ;swapstk()"); 

ol("MOV *R0,R1"); 
ol("MOV R3,*R0"); 

> 


/* Call the specified subroutine name */ 
zcall(snarae) 

char *sname; 

{ ol("BL @SUBCAL"); 

defword(); 
outname(sname); 
nl(); 

> 

/* Call a run-time library routine */ 
callrts(sname) 
char *sname; 

< 

ot("BL @"); /* runtime routines save Rll if need be */ 

outasm(sname); 

nl(); 

/*end callrts*/) 

/* Return from subroutine */ 
zret() 

{ ol("B 0SUBRET"); 

> 


/* Perform subroutine call to value on top of stack */ 
callstk() 

{ ol("MOV *R0,R3 ;callstk()"); 


ol("MOV *R0,R3 
ol("LI R1,$+6"); 

ol("MOV R1,*R0"); 
ol ("B *R3"); 

Zsp“Zsp+2; /* corrected 5 May 81 rj 

> 


*/ 


/* Jump to specified internal label number */ 
jump(label) 

int label; 

< ot("B @"); 

printlabel(label); 
outstr(" ijurnpO"); 
nl(); 

> 


/* Test the primary register and jump if false to label */ 
testjump(label) 
int label; 

{ ol("MOV R1,R1 ;testjump()"); 

ol("JNE $+4"); 
ot("B ); 

printlabel(label); 
nl(); 

> 

/* Print pseudo-op to define a byte */ 
defbyte() 

{ ot("BYTE "); 

> 


/*Print pseudo-op to define storage */ 
defstorage() 

< ot("BSS "); 

> 

/* Print pseudo-op to define a word */ 
defword() 

< ot("DATA "); 

> 


/* Modify the stack pointer to the new value indicated */ 
modstk(newsp) 

int newsp; 

{ int k; 

k=newsp-Zsp; 
if(k==0)return newsp; 
ot("AI RO,"); 
outdec(k); 

outstr(" JmodstkO"); 
nl(); 


return newsp; 

) 

/* Double the primary register */ 
doubleregO 

{ ol("SLA R1,1 ;doublereg()"); 

> 

/* Add the primary and secondary registers */ 

/* (results in primary) */ 
zadd() 

{ ol("A R2,R1 ;zadd()"); 

> 

/* Subtract the primary register from the secondary */ 

/* (results in primary) */ 

zsub() 

{ ol("S R2,R1 ;zsub()"); 

ol("NEG Rl"); 

> 


/* Multiply the primary and secondary 
/* (results in primary */ 
mult() 


ol("CLR 

R5 ;mu! 

ol("MOV 

R2,R3"); 

olC'JGT 

$+4"); 

ol("NEG 

R3"); 

ol("INC 

R5"); 

ol("MOV 

R1,R1"); 

olC'JGT 

$+4"); 

ol("NEG 

Rl"); 

olC'INC 

R5"); 

ol("MPY 

Rl,R3"); 

ol("MOV 

R4,R1"); 

ol("ANDI 

R5,1"); 

olC'JEQ 

$+2"); 

ol("NEG 

Rl"); 


registers */ 


/* signed multiply 


*/ 


/* Divide the secondary register by the primary */ 

/* (quotient in primary, remainder in secondary) */ 


div() 

{ ol("CLR 
ol("MOV 
olC'JGT 
ol("NEG 
ol("INC 
ol("CLR 
ol("MOV 
olC'JGT 
ol("NEG 
ol("INC 
olC'DIV 
ol("MOV 
ol("MOV 
ol("ANDI 
ol("JEQ 
ol("NEG 
ol("NEG 

> 


R5 ;div()"); 
R2,R4"); 

$+4"); 

R4"); 

R5"); 

R3"); 

Rl,R1"); 

$+4"); 

Rl"); 

R5"); 

Rl,R3"); 
R3,R1"); 
R4,R2"); 

R5,1"); 

$+4"); 

Rl"); 

R2"); 


/* signed divide */ 


/* Compute remainder (mod) of secondary register divided */ 
/* by the primary */ 

/* (remainder in primary, quotient in secondary) */ 
zmod() 

< div(); 
swap () J 
> 


(Continued on next page ) 


Dr. Dobb’s Journal, Number 69, July 1982 


cd| 'O 




Small-C for 9900 

(Listing continued, text begins on page 66) 


/* Inclusive 'or' the primary and the secondary registers */ 

/* (results in primary) */ 

zorO 

{ol("S0C R2,R1 ;zor()");} 

/* Exclusive 'or' the primary and seconday registers */ 

/* (results in primary) */ 
zxor() 

(ol("X0R R2,R1 ;zxor()");} 

/* 'And' the primary and secondary registers */ 

/* (results in primary) */ 
zand() 

(ol("M0V R2,R3 jzandO"); 

olC'INV R3"); 

ol("SZC R3,R1"); 

} 

/* Arithmetic shift right the secondary register number of */ 
/* times in primary (results in primary) */ 
asr () 

(olC'MOV R0,R3 ;asr()"); 

ol("M0V R1,R0"); 
olC'MOV R2,R4"); 

ol("SRA R2,0"); /* shift count in RO */ 

olC’MOV R2,R1"); 

ol("M0V R4,R2"); /* restore secondary */ 

olC'MOV R3,R0"); 

> 

/* Arithmetic left shift the secondary register number of */ 
/* times in primary (results in primary) */ 
asl () 

(olC'MOV R0.R3 ;asl()")j 

olC’MOV R1.R0"); 
olC'MOV R2,R4"); 

ol("SLA R2,0"); /* shift count in RO */ 

olC'MOV R2,Rl")j 

olC'MOV R4,R2"); /* restore secondary */ 

olC'MOV R3,R0"); 

> 

/* Form two's complement of primary register */ 
neg() 

(ol("NEG R1 ;neg()");> 

/* Form one's complement of primary register */ 
com() 

(olC’INV R1 ;com()"); > 

/* Increment the primary register by one */ 
inc() 

(ol("INC R1 ;inc()");} 

/* Decrement the primary register by one */ 
dec () 

(olC’DEC R1 ;dec()");} 

/* Following are the conditional operators */ 

/* They compare the secondary register against the primary */ 
/* and put a literal 1 in the primary if the condition is */ 
1 * true, otherwise they clear the primary register */ 

/* Test for equal */ 
zeq() 

(olC'MOV R1,R3 ;zeq()")j 

olC'CLR Rl"); 
ol("C R2.R3"); 
olC'JNE $+2"); 
ol("INC Rl"); 

} 


/* Test for not equal */ 
zne () 

(olC'MOV Rl ,R3 ;zne()"); 

olC'CLR Rl"); 
ol("C R2,R3"); 

ol("JEQ $+2"); 
ol("INC Rl"); 

> 

/* Test for less than (signed) */ 
zlt() 

(olC'MOV Rl,R3 ;zlt()") ; 


ol("LI Rl,1") ; 

ol("C R2.R3"); 

olC'JLT $+2"); 

olC'CLR Rl"); 

} 

/* Test for less than or equal to (signed) */ 
zle() 

(olC'MOV Rl,R3 ;zle()") ; 

olC'CLR Rl"); 

ol("C R2,R3"); 

olC'JGT $+2"); 

ol("INC Rl"); 

} 

/* Test for greater than (signed) */ 
zgt() 

(olC'MOV Rl ,R3 ;zgt()"); 

ol("LI Rl,1"); 

ol("C R2,R3"); 

olC'JGT $+2"); 

olC'CLR Rl"); 

> 

/* Test for greater than or equal to (signed) */ 
zge() 

(olC'MOV R1.R3 ;zge ()") ; 

OlC'CLR Rl"); 

ol("C R2,R3"); 

olC'JLT $+2"); 

ol("INC Rl"); 

) 

/* Test for less than (unsigned) */ 
ult() 

(olC'MOV Rl ,R3 ;ult ()"); 

ol("LI Rl,1"); 

ol("C R2,R3"); 

ol("JL $+2"); 

olC'CLR Rl"); 

} 


/* Test for less than or equal to (unsigned) */ 
ule() 

(olC'MOV R1.R3 ;ule()"); 

olC'CLR Rl"); 

ol("C R2,R3"); 

ol("JH $+2"); 

olC'INC Rl"); 

> 

/* Test for greater than (unsigned) */ 
ugt() 

(olC'MOV R1.R3 ;ugt ()"); 

ol("LI Rl,1"); 

ol("C R2,R3"); 

ol("JH $+2"); 

OlC'CLR Rl"); 

> 

/* Test for greater than or equal to (unsigned) */ 
uge() 

(olC'MOV Rl,R3 ;uge ()"); 

olC'CLR Rl"); 

ol("C R2,R3"); 

ol("JL $+2"); 

olC'INC Rl"); 

} 

/* <«<< End of small—c compiler >>>>> */ 


(End Listing) 


70 

320 


Dr. Dobb’s Journal, Number 69, July 1982 


(Letters) 

(Continued from page 7) 

from 1981 won’t run on my 1982 p- 
machine, which in turn is reluctant to 
accept a new CPU. Neither p-machine 
will run programs written for the Apple, 
in spite of a great deal of hype about 
machine-independence. There must be a 
lesson here somewhere. 

Sincerely, 

D. C. Sessions 
4649 E. Pueblo Avenue 
Phoenix, AZ 85040 

EPROM for Epson 

Dear Marlin, 

Thank you for publishing a number 
of comments and a printer driver for the 
Epson MX-80 printer in the November 
and December 1982 issues. I would like 
to make a few comments, and also de¬ 
scribe some features which have not been 
discussed. 

In the Clinic in November, there is 
some confusion as to the code used to 
switch off double-width printing. The 
code given in the Epson manual is DC4, 
or ctrl-T, and not SI or SO. 

There is a feature in the printer 
which has not been mentioned, namely 
the possibility of printing Japanese char¬ 
acters instead of the TRS-80 graphics set. 
Presumably, not many users need this 
character set, and this is probably the 
reason why the escape codes 4 and 5 are 
not documented in the manual. If the 
Japanese characters are selected with 
DIP switch 1, pin 7, then ESC 5 can be 
used to switch to graphics characters, and 
ESC 4 to switch back to Japanese. These 
codes are ignored if DIP switch 1 selects 
graphics. 

For those users who have access to 
an EPROM programmer, the Japanese 
characters can be substituted by 63 other 
characters; in my printer I have chosen to 
implement all the Greek lower-case char¬ 
acters (for mathematical and electronics 
texts), and a number of other useful spe¬ 
cial characters. Since I use graphics most, 
I have also changed ESC 4 and ESC 5 so 
they can be used irrespective of DIP 
switch 1. 

To implement these features and a 
number of others, I have manually dis¬ 
assembled all the 4K of Intel 8049 in¬ 
structions controlling the printer. In Den¬ 
mark, for example, 12-inch paper is stan¬ 
dard rather than the 11 -inch kind found 


in the U.S. It was therefore logical to pre¬ 
set the forms length to 72 lines instead 
of 66 lines, and to allow page lengths up 
to 127 lines. 

If Gary Novosielski has a printer 
which can be set to more than 66 lines 
per page, then there must be several ver¬ 
sions of the ROM. The one I have (from 
about October ’80) has the restriction 
mentioned in the manual, that the maxi¬ 
mum is 66 lines per page. This limit seems 
ridiculous since it apparently serves no 
practical purpose to limit page size ar¬ 
bitrarily. 

The graphics capabilities of the print¬ 
er have not been mentioned at all, and 
obviously they are not as impressive as 
those available with the Graftrax ROMs 
or the MX-100. However, I have found 
them adequate for most of my needs, es¬ 
pecially when printed in condensed form. 
In this format, each pixel is almost exact¬ 
ly twice as high as it is wide (the ratio is 
actually 18:34), and thus a square pixel 
can be obtained by using two adjacent 
horizontal pixels. 

Unfortunately, in condensed mode 
two extra dot positions are inserted be¬ 
tween each character, and therefore there 
is a noticeable space between every sec¬ 
ond pixel. This makes the graphics seem 
discontinuous. The alternative would be 
to remove these dot positions in the ROM, 
but this would change the pitch for con¬ 
densed print as well. Actually, the con¬ 
densed mode does not print 16.5 charac¬ 
ters per inch, but 17 characters per inch. 
Try measuring a line of 132 characters; 
it should be almost exactly 7.7 inches 
rather than 8 inches long. Perhaps the 
original intention was to print 136 char¬ 
acters in compressed mode. Removing the 
two dots would give 20 pitch, or 160 
characters per line, with the same charac¬ 
ter size as now, but with less space 
between the characters. 

Another possibility would be to 
make one of the two horizontal pixels per 
character wider than the other one, but 
this may give some unbalanced graphics. 
Someday when I have the time I will try 
to implement this option. 

From the above it should be obvious 
that Gary Novosielski is not quite correct 
when he states that the print head speed 
is reduced by a factor of 1.65 in com¬ 
pressed mode. It is reduced to half speed, 
the same as for emphasized printing. Dot 
spacing in emphasized mode is the same 
as in compressed mode, and the print 


head has only two speeds rather than 
three. 

A useful feature which has not been 
incorporated into the printer is a reset 
switch. On the parallel interface there is 
an INIT line which does a hardware reset 
of the processor, but this is not imple¬ 
mented on my computer. It is annoying 
having to power off the printer to reset 
all the internal memory, and quite often 
it seems to disturb the computer as well 
when switching on or off. 


Actually, it is simple to install a reset 
switch. I have chosen to install a push¬ 
button reset switch just behind the power 
switch. One lead is connected to the INIT 
line in the interface, the other is connect¬ 
ed to ground. The easiest position to find 
these may be on resistor R15 and zener 
diode ZD5. These are located to the right 
of the IC 3E looking from the back of the 
printer. They can be seen in the bottom 
center of the diagram showing the DIP 
switch locations, and the ends to use are 
the ones closest to the DIP switches. 
With a bit of dexterity the leads can be 
soldered in place without removing the 
circuit board. 


There are at least two versions of the 
printer with the original ROM. One of 
them has three 2716 EPROMs mounted 
in sockets IB, 2B and 3B, and the jumper 
J1 alongside the 8049 has been cut (mak¬ 
ing the 8049 into an 8039). This gives 6K 
of ROM, 4K for the program and 2K for 
the character sets. The other version uses 
the 2K ROM in the 8049 and has 4K of 
external ROM in a single 2332 ROM 
mounted in socket IB. The jumper J1 is 
left intact. The second version can easily 
be converted into an EPROM version, 
simply by cutting the jumper J1, and in¬ 
stalling three 2716 EPROMs in the sup¬ 
plied sockets. The 8049 code is replaced 
by the code in socket 3B, the character 
set is in socket 2B, and the remaining 
program code is in socket IB. 


Incidentally, if anyone is interested 
in my alternative character set instead of 
the Japanese set I can provide a set of 
3 EPROMs for $70, including air-mail 
postage. This will also allow ESC4 and 

(Continued on page 74) 


72 


Dr. Dobb’s Journal, Number 69, July 1 982 

321 


(Continued from page 72) 

ESC5. A sample of the character set is 
given below. 


0123456783 + 


0123456 ' 


3 CX [i x S € 0 v f| *- V K A U V O T) e /> <3 7 


V Ain t V CrEf)n$©r£int- f + 4 . </± ^ 


Special requests for other characters 
can also be filled, but at a higher price. 
If there is sufficient demand for an A PL 
or other standard set, they may be pro¬ 
vided later at the above price. 

Incidentally, I have written to Epson 
America some time ago asking whether 
sale of the modified ROMs was allowed, 
since presumably their program is copy¬ 
righted; they have not bothered to answer 
me. However, since the ROMs are of little 
use without an MX-80 printer, there 
should be no conflicts. 

Sincerely 
Arne Rohde 
Pilevej 31,7600 Struer 
DENMARK 


74 

322 


Dr. Dobb’s Journal, Number 69, July 1982 


BOOK REVIEWS 


Ciarcia’s Circuit Cellar Volume II 
By Steve Ciarcia 
Byte Books/McGraw-Hill 
$12.95, 220 pages 

Circle No. 459 on Reader Service Card 

Reviewed by George W. Jolly 

This is a collection of nineteen arti¬ 
cles published in Byte magazine between 
December, 1978, and June, 1980. Four¬ 
teen of them were voted by Byte readers 
as the best article of the month. This col¬ 
lection receives a similar vote from me. 
Several times in the book letters from 
Byte readers are reprinted after the 
article to which they pertain. This adds 
an interactive touch to the book which is 
difficult to enjoy from the original maga¬ 
zine alone. 

Interfacing microcomputers to the 
outside world is the main theme of this 
collection. A three-part series on Steve’s 
home security system provides many 
ideas on the use of microcomputers for 
intruder detection. Flowcharts and block 
diagrams easily explain the design of such 
systems. Another article shows the use of 
the BSR X-10 home control system to 
automate lamps and appliances. One of 
the letters reprinted with this article de¬ 
scribes an alternative method to that 
shown in the article. 

Other articles deal with a variety of 
microcomputer topics. Steve explains 
how to use sound generation chips, joy¬ 
sticks, real-time clocks, and LED dis¬ 
plays. Even a simple biofeedback monitor 
is described. Most articles are construc¬ 
tion articles written in plain language and 
well-illustrated. Steve is very good about 
explaining why his circuits were designed 
the way they were. As a result you can 
learn a lot just reading the articles. 

One interesting article describes 
Steve’s home heating system. He has 
added a wood stove to his hot-water 
distribution system to supplement the oil 
burner. The article describes the problems 
involved in protecting the system from 
excessive heat, and how he used a micro¬ 
computer to automate the system. Cir¬ 
cuits given in the article allow remote 
temperature sensing and electric motor 
control. Reading how Steve handled a 
practical design problem in the real world 
really helps in understanding the con¬ 
cepts. 

Experimenters will find many cir¬ 
cuits to play with in this collection. Fiber 
optic communication methods are ex¬ 
plained, and the Intel 8086 microproces¬ 
sor is described. Two articles show how 


to connect I/O devices to the TRS-80 
Model I without the expansion inter¬ 
face. You may be interested in these arti¬ 
cles even if you do not have the TRS-80 
Model I because they provide examples of 
interfacing from which you can learn. 

Ciarcia’s Circuit Cellar Volume Two 
is a collection of excellent articles 
brought together in a convenient form. If 
you want to experiment with microcom¬ 
puter interfacing, or want to read some 
entertaining design articles, give it a try. 

Using Structured Design 
By Wayne P. Stevens 
John Wiley & Sons 
$24.95, 231 pages 

Circle No. 469 on Reader Service Card 
Reviewed by Chuck Ballinger 

This book, unlike others in the field 
of structured design, deals with the prac¬ 
tical approach. When you finish this book 
you will have practical ideas and solution? 
to how you might make use of the struc¬ 
tured techniques. 

While written for the beginner to in¬ 
termediate level programmer it is also full 
of information and ideas that encompass 
most of the available information on struc¬ 
tured design. Managers, business people 
and long-time programmers stand to gain 
substantially from this book. 

“Structured” is the concept of sepa¬ 
rating functions within a program or sys¬ 
tem into relatively independent modules. 

This concept, while relatively new to 
the programming environment, has exist¬ 
ed in industry for years. The component 
parts of a plane, a car, or a house and the 
necessary interface between their func¬ 
tional components is so well defined that 
they can be (and typically are) designed, 
manufactured, and improved by different 
companies or people. Moreover most 
parts are interchangeable among like de¬ 
signs. Structured Design teaches you to 
use comparable concepts in designing and 
writing your programs. Remember, the 
overall goal of structured anything is to 
reduce the cost of developing and main¬ 
taining that system or program. This 
book takes you through the realm of 
structured design admirably. The set of 
topics (structured design concepts, struc¬ 
ture charts, coupling, binding, etc.) all 
relate to one another and do not create 
any large gaps that must be filled in later. 

One of the strong points in this book 
is the section on Tips and Techniques. 
Most of us prefer the “show me” method 
whereby an idea or concept is explained 


and then demonstrated. This serves to 
enhance what you’ve just read as well as 
allowing you to test visually if this is 
what you had in mind. This book does 
this in an easy to understand fashion, 
while not being so simple that someone 
with some pre-existing exposure to struc¬ 
tured design would not benefit from the 
text material. 

In addition you are given the oppor¬ 
tunity to improve an existing Structure 
Chart in chapter 8 which gives you an 
idea of what it is and then the steps you 
may want to take to improve your end 
product. You are also involved in generat¬ 
ing an initial chart, since the hardest place 
to start is getting that first attempt down 
on paper. This approach should help you 
over that initial hurdle. 

In short this book covers the many 
topics that make up the sometimes giant 
word “structured,” and breaks them 
down to a level where you can feel com¬ 
fortable about learning and using a really 
excellent technique. Even if you only 
write programs for yourself you should 
consider using this method. Your time is 
valuable also and structured design can 
lend itself to reducing your development 
time and thus freeing you for more proj¬ 
ects that you just don’t have time for 
now. This book is a very fine example of 
how to do it and should be read by all. 

Computer Simulation in Business 
By Hugh J. Watson 
John Wiley & Sons 
$22.95, 358 pages 

Circle No. 479 on Reader Service Card 
Reviewed by Robert Ashworth 

Did you ever wonder how a business, 
firm or person might change over time? 
This book is for the college student or 
others who want to learn more about the 
art and science of simulation. It is based 
on the author’s dissertation and 12 years 
of research in financial planning systems 
and human decision making. Simulation 
is defined as a mathematical model that 
describes the behavior of a system over 
time. 

The text begins by identifying dif¬ 
ferent models, either physical or symbol¬ 
ic. These in turn are divided into their 
purpose, mode of analysis, the way in 
which randomness is employed and the 
use of specific applications. A balanced 
approach is also evident as the author 
cites reasons when simulation is not use¬ 
ful. 

Chapter II illustrates ten real busi- 


76 


Dr. Dobb’s Journal, Number 69, July 1982 

323 




ness applications covering such areas as 
finance, production, marketing, personnel 
and economics. A Monte Carlo or random 
simulation is used when variables like 
demand and delivery of a product are ex¬ 
pressed as the frequency of occurrence. 
In another example a manual step-by- 
step method is applied to an inventory 
control problem. 

One of the strengths of this book is 
its treatment of financial planning genera¬ 
tions. The author shows how traditional 
line item budgeting can be incorporated 
into the desired simulation. Simple ex¬ 
amples of both analytical and numeric 
methods are provided. 

Probability distributions with their 
many variations are well developed. Sup¬ 
porting FORTRAN code is also helpful in 
specific cases. Several statistical tests are 
called upon as required to test assump¬ 
tions about the real world. 

The chapter on random numbers de¬ 
scribes clearly what they are, how you 
can generate them, and what tests they 


must pass for acceptance. The midsquare 
and congruential methods are shown for 
both manual and computer applications. 

The problem of waiting lines is well 
described; three pages of FORTRAN with 
comments describes the single channel, 
single phase case. The discussion is 
thoughtful and clearly shows how to han¬ 
dle the more difficult situations. 

The next chapter deals with special- 
purpose simulation languages such as 
GPSS. Short discussions of DYNAMO, 
GASP, SIMSCRIPT and IFPS are helpful 
but could be longer. 

The problem of human decision¬ 
making is illustrated with trust invest¬ 
ment, vendor selection, personnel man¬ 
agement and processing of overdrafts. 
Perhaps later editions will expand this dif¬ 
ficult topic. Possibly a whole book would 
be helpful. 

No book on simulation would be 
complete without a portion devoted to 
management games. Not only were sev¬ 
eral types of games presented, but the 


purpose, advantages, limitation and ad¬ 
ministration were candidly discussed. The 
chapter concludes with a detailed look at 
the Credit Union Management Game. 

Corporate simulation models may be 
financial, marketing or production in 
structure. A telecommunications model is 
used for detail illustration. When it is re¬ 
lated to the organization’s planning pro¬ 
cess it becomes an effective tool to sup¬ 
port the decision-making process. 

The last two chapters deal with ad¬ 
vanced techniques and procedures for the 
development of successful simulation 
models. 

In summary, this is a very readable 
book on a rather technical subject. The 
chapters have a number of good problems 
and extensive references. To assist in 
understanding the many illustrations 
found in the text, the author has included 
an appendix of eight useful statistical 
tables. If you want to simulate part of the 
world, here’s your opportunity. 


Dr. Dobb’s Journal, Number 69, July 1982 
324 


77 




R. 



For Users of Small Computer Systems 



$2.50 

($3.00 in Canada) 


OBB'S lOURNAL 


Number 70 August 1982 



A “C” Command Line Processor 

Anthony Skjellum 

Performance Evaluation in 
Small Computers 

Michael K. Kan 

Intel’s 8087: 

Numeric Data Processor 

Ray Duncan 

and more! 


File Transfer 
Utilities... 

... Elliptical 
Answers... 

... IBM-PC 
Benchmarks 


325 










Dr. Dobbs Journal 

For Users of Small Computer Systems / 

August 1982 Volume 7, Issue 8 


Editor - Marlin Ouverson 
Assistant Editor - Fritzi Lareau 
Contributing Editors - 

Dave Caulkins, Dave Cortesi, 

Ray Duncan, Michael Wiesenberg 
Marketing Director - Craig Harper 
Marketing Assistant - Beatrice Blatteis 
Advertising Director - Laird Foshay 
Circulation Manager - Gloria Romanoff 
Circulation Assistants - 

Theresa O’Rourke, Terri Marty 
Art Director - Clifford West 
Production Manager - Barbara Ruzgerian 
Production Assistant — Margaret Tsai 
Typesetter - Renny Wiggins 
Cover Illustration - Margaret Tsai 


© 1982 by People’s Computer Company 
unless otherwise noted on specific articles. 
All rights reserved. 


Subscription Rates: $25 per year within the 
United States; $40 for first class to Canada 
and Mexico; $5 8 for airmail to other coun¬ 
tries. Payment must be in U. S. Dollars, 
drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be 
typed, double-spaced on white paper. List¬ 
ings should be produced by the computer, 
using a fresh, dark ribbon on continuous 
white paper. Please avoid printing on perfo¬ 
rations. Payment is in contributor’s copies. 
Requests to review galleys must accompany 
the manuscript when it is first submitted. 
Authors may receive a copy of the complete 
writer’s guidelines by sending a self- 
addressed, stamped envelope. 

Donating Subscribers Contributing Sub¬ 
scriber: $ 50/year ($25 tax deductible). Re¬ 
taining Subscriber: $75/year ($50 tax de¬ 
ductible). Sustaining Subscriber: $100/year 
($75 tax deductible). Lifetime Subscriber: 
$1000 ($800 tax deductible). Corporate 
Subscriber: $ 500/year ($400 tax deductible, 
receives five one-year subscriptions). 

Contributing Subscribers: Thomas H. 
Grohne, G. V. Elkins, Robert M. Connors, 
William J. McEown, Robert C. Luckey, 
Robert N. Stabler, DeWitt S. Brown, John 
B. Palmer, Burks A. Smith, Transdata Cor¬ 
poration, Mark Ketter, John W. Campbell, 
Friden Mailing Equipment, Howard E. 
Decker, Jim Wilson, Frank Lawyer, Chris 
Pettus, Paul Lutus, Ben Goldfarb, Rodney 
Black, Steven Weiss, Pat Phelan, John 
Brodie, James Fleming, Unison World, 
Thomas Davis, Jan Steinman, Ronald E. 
Johnson, G. Hunter. Sustaining Subscribers: 
Pete Roberts, Steven Fisher Enterprizes. 
Lifetime Subscriber: Michael S. Zick. 


Foreign Distributors UK & Europe: 
Hofacker-Verlag, Tegemseer Strass 18, D- 
8150 Holzkirchen, West Germany. Asia & 
Australia: ASCII Publishing Co., Ltd, 
Aoyama Building 5F, 5-16-1 Minami 

Aoyama, Minato-ku, Tokyo 107, Japan. 


CONTENTS 


Articles 

10 Argum — A "C" Command Line Processor 

by Anthony Skjellum 

This program provides sophisticated command line parsing in order to help pro¬ 
grammers produce more powerful and consistent code. It is portable, easily modi¬ 
fiable, and of interest to both 8- and 16-bit users. 

34 Performance Evaluation in Small Computers 

by Michael Kan 

Performance evaluation is essential to any business; when it comes to squeezing 
the most from your micro, proper evaluation is critical. 

41 SEND/RECEIVE File Transfer Utilities 

by Lawrence Hughes 

These utilities allow the user to transfer files from adjacent CP/M systems; source 
code is included. 

47 Intel's 8087 Numeric Data Processor 

by Ray Duncan 

A comprehensive look into the architecture and capabilities of the 8087 co¬ 
processor; or what to do with the empty space on your IBM-PC motherboard. 


Departments “ 

6 Letters 

7 Editorial 

8 Dr. Dobb's Clinic 
51 Of Interest 


Dr. Dobb’s Journal (USPS 307690) is published twelve times per year by People’s Computer 
Company, Box E, 1263 El Camino Real, Menlo Park, CA 94025. Second class postage paid at 
Menlo Park, California 94025 and additional entry points. Address correction requested. 
Postmaster: send form 3579 to Box E, Menlo Park, California 94025 • 415/323-3111 


4 


Dr. Dobb’s Journal, Number 70, August 1982 





LETTERS 


More C Notes 

Dear Mr. Ouverson: 

The May 1980 issue devoted to the 
language C was fantastic. The compiler 
written by Ron Cain was an excellent 
means of immersing oneself into the C 
language, along with the other articles. 
As Ron mentioned in closing, other peo¬ 
ple might have a problem getting the 
compiler operational. I was one of those 
people, and I thought my experience 
might be of interest to others. 

First some background. 1 have access 
to a large CDC Cyber-172 but not any 
compiler for C, although a variety of 
other languages are available. Thus, the 
question of how to use the compiler as 
written quickly arose. It was as quickly 
realized that it would have to be rewrit¬ 
ten into a different language. I chose to 
recode the program in Pascal, and get it 
operational. However, if the compiler was 
going to be running on the Cyber in 
Pascal, it would be useful to generate 
Cyber assembly language, Compass. I had 
considered leaving the code generation in 
8080 mnemonics, yet the time delay in 
using a cross-compiler and then cross- 
assembler was not appealing. In imple¬ 
menting the compiler, some simplifica¬ 
tions were possible. On current micro¬ 
computers, one has to be concerned with 
8- and 16-bit items. Yet the Cyber-172 
has 60-bit words, posing no problem for 
address items. At the same time, I chose 
to waste memory space, and only store 
one character in a word, wasting 54 bits 
per word. The rationale for this is to con¬ 
tinue to interchange the role of integers 
and characters. At code generation, fur¬ 
ther simplifications were possible by us¬ 
ing macros instead of calling runtime rou¬ 
tines. 

Recently, I completed teaching a 
course on Alternative Programming Lan¬ 
guages, using APL, Ada and C. The exper¬ 
ience in the classroom gave me and my 
students an opportunity to thoroughly 
test the compiler. As a result of student 
reactions, the compiler has been modified 
to handle the FLOAT data type. Again, 
with 60-bit words, FLOAT and DOUBLE 
can be considered the same. 

In summary, the compiler has been 
recoded into Pascal, about 2200 lines, 
modified for floating point, and produces 
Cyber assembly language. Most of the 
runtime software is written in C, although 
the I/O, and error-handling routines are 
in Compass. The article by Chris Kern in 
Byte, May 1981, provided a version of 


PRINTF to use. My class developed our 
own version of SCANF. 

Well, as Ron asked in the last part of 
the article, I thought he might like to 
know that a form of his compiler is alive 
and running well on a CDC Cyber-172. 
Sincerely, 

Freeman L. Moore 
Computer Science Department 
Central Michigan University 
Mount Pleasant, MI 48859 

Dear Dr. Dobb’s, 

I have adapted the small-c compiler 
by Ron Cain to generate code for the 
6809. The adapted compiler is running on 
a South West Technical Products S/09 
computer with 56K of RAM, running 
FLEX version 9.0. It generates assembly 
language acceptable to the SWTPC 
ASM09 assembler. 

In addition to the features found on 
the original compiler, the following 
things have been added: 

The type unsigned. 

The operators “J J”, 

<< i» 

> • • 

The control structures “for”, “do — 
while”, “switch — case — default”. 
Octal and hexadecimal constants. 

I also have a function library which 
implements the following: 

• Command line arguments passed to 
main() through the argc, argv mechan¬ 
ism. 

• I/O redirection using the “<” and 

command line operators. 

• The functions fopen, fclose, putc, getc, 
ungetc, getchar, putchar, iswhite, 
isdigit, isalpha, tolower, toupper, fgets, 
gets, fputs, puts, strlen, strcpy, strcmp, 
itoa, atoi, all of which match their 
definitions under UNIX. The I/O rou¬ 
tines talk transparently to disk files or 
devices. They contain code for using 
ACIA’s or PIA’s, and they understand 
filenames like “/dev/tty”, “/dev/ 
modem”, and “/dev/lp”. 

• The functions printf, fprintf, sprint, 
which are not quite as powerful as 
their UNIX counterparts. 

The compiler does not prompt for 
source file names, nor compilation op¬ 
tions but instead takes the source file 
names as command arguments and the 
options as UNIX-style command line 
flags. A sample command line might be: 

cc -ps filel.c file2.c file.3c >xyz.asm 



My main goal while making modifi¬ 
cations was to make the system look as 
much like UNIX as possible. If all hobby¬ 
ist implementations of C make themselves 
compatible with UNIX, then we will 
have a much easier time sharing software. 

I can provide for $20 either all 
sources, executables, and documentation 
on a 5-%-inch disk (not including the as¬ 
sembler, of course); or, listings of all 
source and documentation. 

Anyone interested in forming a 6809 
C user’s group? 

Dan Everhart 

5823 202nd St. SW, Apt. #5 
Lynnwood, WA 98036 

He Wants the Whole Thing 

Dear Marlin: 

I just received my DDJ #68 this 
morning and read with great interest, the 
article on the multi-68000 system by A1 
Kossow. I urge you to please publish the 
listing in its entirety. 

Yours truly, 

E. E. Mullins 
Box 73027 
Houston, TX 77273 

Is That You? 

Dear DDJ: 

We are interested in voice recogni¬ 
tion hardware and software for an 8080 
S-100 non-CP/M system for data entry. 

Several years ago we saw 
ads for and articles about such items 
but can’t find any now. 

Can you list sources for them? In¬ 
formation from other readers will be ap¬ 
preciated. 

Sincerely, 

T. B. Finn 
P. O. Box 2336 
Goleta, CA 93118 

Venus Rising 

The Editor, 

I am responding to Wayne Farmer’s 
letter in DDJ #68, who lists a number of 
guidelines for a truly useful macro¬ 
assembler, and wonders whether one such 
exists. My own macro-assembler VENUS, 
which I have just completed, would seem 
to fit the bill. 

VENUS is a structured macro¬ 
assembler, editor, symbolic debugger, 
linker, loader, and disassembler with a 
full complement of algebraic, string, and 
I/O facilities. It allows internal and ex¬ 
ternal symbol names of eight characters, 


6 


Dr. Dobb’s Journal, Number 70, August 1982 

327 



and supports 16-, 8- and 3-bit externals 
(so that, for instance, the instruction 
BIT FLAG, (IX+LOCN) 

can be assembled, where both FLAG and 
LOCN are externals). It allows macros 
with string operators, can link up to 512 
global symbols, will link programs of 
any size at all, and produces global cross- 
references among all modules. In addition 
to an IF-ELSE-ENDIF construction, 
it supports WHILE-ENDWH and DO- 
UNTIL control structures, and has a 
BREAK facility. Moreover, all of these 
control structures use the Z80 flags as 
condition tests, so that total control over 
register use is maintained. 

Mr. Farmer also notes the problem 
of the awkwardness of needing to IN¬ 
CLUDE a large COMMON area along with 
each program module — thus increasing 
assembly time and requiring the reassem¬ 
bly of all segments when the COMMON is 
changed. VENUS has several facilities for 
handling this problem. First, it has an 


EXECUTE statement which allows a 
series of commands (get files, assemble 
them, link them, load them, list them, 
print them, etc.) to be executed without 
operator intervention. Thus if a program 
has 23 modules, a file may be created 
which, when EXECUTED, will leave the 
programmer free to do other things while 
the operations take place. 

Second, the design philosophy of 
VENUS incorporates the notion that pro¬ 
gram development occurs normally in an 
accretionary fashion. Some parts of the 
program will be completed before others 
are developed. The completed modules 
can be separately linked and their symbol 
table of externals saved to disk. The mod¬ 
ules under construction can be separately 
linked, and the linker knows the absolute 
locations of all declared ENTRY variables 
of the completed modules. Thus, if a 
program has 23 modules and 21 are 
completed, only the other two need to be 
reassembled and relinked during program 


development. When they are done, they 
may be added to the already completed 
programs, if desired. 

The third VENUS facility for dealing 
with the problem of the COMMON area 
requires a bit of programmer discretion. 
VENUS allows the interleaving of normal 
code, data areas, common areas, and 
blank common areas, within program 
modules. Thus, there is normally no 
reason to INCLUDE a COMMON source 
file. However, like other assemblers, 
VENUS can perform only addition and 
subtraction on externals. If more compli¬ 
cated algebraic operations are required, 
they must be collected in one or more 
separate modules along with the EQUs 
that define the variables, and the results 
can be declared externals, to be drawn 
upon by other program modules. If the 
algebra needs to be changed, only the 
module involved need be reassembled 
before relinking the whole program. 

(Continued on page 33) 


Editorial “ 

Thanks To Our Readers 


Thanks go to the many readers who responded to our 
recent survey. Such questionnaires are some of the methods 
we use to get to know you a little better, to more precisely 
define what is looked for in DDJ. It is interesting to see 
how the tabulated results change from year to year as the 
industry presumably moves ahead and as different issues — 
telecommunications, software portability, new languages, 
etc. - ebb and flow in public opinion, if not in importance. 

We were amazed, for instance, at how rapidly many of 
our readers have acquired IBM’s Personal Computer. Equal¬ 
ly interesting was that the 68000 chip has a greater follow¬ 
ing among our readers than the 8086/8088, although the 
margin is not overwhelming. Among topics eliciting very 
favorable response were CP/M, algorithms, assembly lan¬ 
guage, compilers and the Z80/8080. Pascal and Small-C/C 
were among the languages of evident enthusiasm, and multi¬ 
user operating systems are becoming worthy of more edi¬ 
torial attention. 

This is a small and possibly predictable sample of the 
results we pulled from the survey. It helps to confirm what 
our mail, conversations and instincts tell us. As a token of 
our appreciation, three respondees were chosen at random 
to receive complete sets of Dr. Dobb’s Journal bound vol¬ 


umes. They were T. E. Toews, Michael J. Young and 
Charles R. Rogers. The sets include the latest, volume num¬ 
ber five, which was due to be released in mid-July. 

* * * 

For our newsstand buyers, a special note: Last year’s 
Forth theme issue will be followed by another one next 
month. Since the first was nearly an immediate sellout, 
keep your eyes open for the September 1982 issue to 
appear. There are a number of features which are certain 
to be valuable not solely because of their use of Forth, but 
because of the solid design and programming technique 
they represent. 

* * * 

One last message for those of you who have been frus¬ 
trated by the inaccuracy of your system clocks. If you 
aren’t quite in step with solar time, it’s because a leap 
second was added to our calendar on the last split-moment 
before midnight, June 30th. If it’s not one thing, it’s 
another ... 

— Marlin Ouverson 
Editor 


Dr. Dobb’s Journal, Number 70, August 1982 
328 


7 



DR. DOBB’S CLINIC 




by D.E. Cortesi 


The Lazy Pinky and the H19 

Our Heathkit H19 terminal has 
served us well for two years now, but re¬ 
cently we began to notice that, once in a 
while, when we typed the word “pascal” 
it came out on the screen as “pa[seal.” 
Then stranger things began to happen. 
Once or twice a day we would type the 
word “photograph” or “graphics” - 
something with “aph” in it — and as the 
H key went down our full-screen editor 
would jump to the top of the file. Our 
editor has been patched to take the H19’s 
FI key as a signal to go to the top of the 
file. 

Very strange. Why would “aph” look 
like “aph,Fl”? With some experimenta¬ 
tion we found that if we held down the A 
and P keys and pressed H, the computer 
would receive an “h” followed by the FI 
escape sequence. And if we held down A 
and P and pressed S, the computer would 
get “s” followed by “[”. More experi¬ 
ments revealed other combinations: hold¬ 
ing down 1 and K and pressing L pro¬ 
duced both “1” and “o”. 

We got out the schematic of the HI9. 
The keyboard is encoded as a matrix of 
switches; the matrix is scanned and de¬ 
coded by a single IC, a 5740. This chip 
sends pulses down the matrix columns; 
where a key is closed the pulse shows up 
on one of the matrix row lines. The chip 
converts the key address to a key number 
which is eventually decoded to ASCII. 

When we mapped out all the four- 
letter combinations we had found (PA[S, 
OILK, etc.) on the keyboard matrix, it 
was quite noticeable that each combina¬ 
tion was formed of keys that were at 
the comers of a rectangular subsection of 
the switch array. And then the light 
dawned. If any three key-switches at cor¬ 
ners of a rectangle are closed, the key- 
switch at the fourth corner of the rec¬ 
tangle will also appear to be closed (see 
Figure 1 for an example). It is a classic 
example of what we used to call a “back- 
circuit” in the days when we repaired 
electrical accounting machines. This back- 
circuit is an inevitable feature of the 
H19’s keyboard matrix; it could only be 
eliminated by putting a diode in series 
with every single key-switch. 

So “pas[cal” was not a symptom of 
an intermittent failure in the HI9; it had 
been there right along. How come it took 
18 months to show up? That became 
clear after some thought. Your Intern is a 
touch-typist, and the P and A keys fall 
under his right and left pinky fingers, re- 



COL UMN LINES FROM 
KEYBOARD ENCODER 



Figure 1. 

Part of the key matrix of the H19 terminal. Holding I and K keys, pressing L key, 
produces spurious O-key output. 


Listing 1. 

100 REM Floating-point exercise 
110 DEFDBL K,S 
120 DEFINT I 
130 DIM S(999,1) 

140 PRINT CHR$(7) : REM signal to start the watch 

150 FOR 1=0 TO 999 

160 K=K+.001 

170 S(I,0)=SIN(K) 

180 S(I,l)=COS(K) 

190 NEXT I 

200 PRINT CHR$(7) : REM stop the watch 


Listing 2. 

100 REM Sieve of Eratosthenes, after 

101 REM Creative Computing, May, 1982 
110 DEFINT A-Z : DIM X(5000) 

120 PRINT "2"; CHR$(7); :REM start the watch 

130 FOR P=3 TO 67 STEP 2 

140 IF X(P) THEN 160 ELSE PRINT P; 

150 FOR J=P*P TO 4999 STEP P+P : X(J)=1 : NEXT J 
160 NEXT P 

170 FOR P=71 TO 4999 STEP 2 

180 IF X(P) THEN 190 ELSE PRINT P; 

190 NEXT P 

200 PRINT CHR$(7) : END 


8 


Dr. Dobb’s Journal, Number 70, August 1 982 

329 












spectively. Clearly, our typing habits have 
grown sloppy over the past year. When 
typing a familiar word like “pascal,” the 
pinky fingers are not coming off the keys 
fast enough. The P and A are staying 
down long enough so that, sometimes, 
when the ring-finger comes down on the 
S, there are a few milliseconds when all 
three keys are closed. The encoder chip 
then sees new closures of both the S and 
the [ keys (or both the H and FI keys, in 
“aph”). It’s an interesting example of 
how a slow change in the habits of the 
operator can give the appearance of a 
developing bug in the machine. 

Improvements SUBMITted 

Robert Pasky of Newton Center, 
MA, has sent us fixes for the irritating 
problems that plague the SUBMIT com¬ 
mand of CP/M. He worked out patches 
for both version 1.4 and 2.2 that cause 
SUBMIT to (a) retain lowercase letters 
from its input file, (b) pass all 32 control 
characters, and (c) accept empty input 
lines and pass them through to the out¬ 
put. 

The last fix is particularly impressive, 
since we are told by Digital Research that 
that problem required too extensive a 
patch, and it would have to wait for a 
later version of the system. 

We have combined all three of 
Pasky’s patches with the one given in the 
May Clinic. Starting with a fresh, stock 
SUBMIT.COM file, use the L command 
of DDT to verify the instructions shown 
in Table 1, then change them as indicat¬ 
ed. Save the resulting program as 
DDJ.COM. Then test it carefully before 
putting it into service. 

Intern Benchmarks Machine 

It seems to be all the rage these days 
to run benchmarks on the IBM Personal 
Computer. Since we’ve had a PC sitting 
next to our 4MHz Z80 system for some 
time now, we thought we’d join in the 
fun. Listings 2 and 3 show two programs 
that we ran on each machine. The Z80 
system used Microsoft Disk BASIC ver¬ 
sion 5.0. Times were measured to the 
nearest second with a stopwatch, and 
averaged over several trials. 

The floating-point exercise in Listing 
1 ran in 32 seconds on the Z80 system; 
it took 40 seconds on the IBM PC. The 
program in Listing 2 is a good test of inte¬ 
ger arithmetic and of array indexing. The 
Z80 did it in 18 seconds; the IBM in 24. 

Tsk, tsk, tsk. The 8086 machine 
architecture is ever so much better suited 


to both these tasks than the Z80. It 
should be possible to write floating-point 
subroutines and array-indexing subrou¬ 
tines for the 8086 that would just run 
rings around the Z80. Judging by the 
CPU alone, IBM BASIC ought to be quite 
a bit faster; instead it is significantly 
slower. Why? The obvious guess is that 
the IBM interpreter was mechanically 
translated from 8080 to 8086 code, but 
we have seen absolutely nothing to verify 
that. It would be nice if some reader 
would disassemble the IBM ROMs and 
tell us if they look like translated code. 

Elliptical Answers 

Now we move from the mundane to 
the sublime, more or less. In a recent 
Clinic we published a call for help from 
Don Taylor of Corvallis, OR. He wanted, 
he said, a formula that would let him 
rotate the image of an ellipsoid (an ellip¬ 
tical solid) on all three axes. We received 
eight replies, each detailed, each full of 
(to us) daunting derivations. We pan¬ 
icked, packed up the lot of them, and 
sent them off to Don Taylor himself to 
analyze for us. What follows is his: 

The Intern asked me to summarize 
the responses to the question that I posed 
in the April Clinic. What follows is, I 
hope, a better description of what I was 
trying to find, the solution that several 
readers found, and what it might be used 
for. 

If you attempt to display three- 
dimensional objects on a monitor, you 
quickly discover the massive amount of 
calculation needed to model a complex 
object. Even relatively simple objects may 
need dozens of points for a rough repre¬ 
sentation. To attempt to manipulate one 


of these objects in real tim is no small 
task. Every point displayed is the result 
of at least one matrix multiplication, 
needing upwards of sixteen multiplies. 
Think of thirty or so points, updated five 
or ten times a second, and it becomes ob¬ 
vious why real-time, 3-d graphics are 
uncommon. 

I began searching for another method 
of representing objects, one that would 
be flexible and yet give an order of mag¬ 
nitude increase in speed. It seemed that 
single points did not supply enough infor¬ 
mation about an object, given the amount 
of effort needed to find their apparent 
position. If we could model part of the 
object as a geometric solid, and find 
the perspective view of that whole subsec¬ 
tion at once, some speed might be gained. 
The sphere seemed a likely candidate 
since its outline is easy to find and it is 
simple to draw. The only drawback is 
that the sphere just does not model many 
objects well. Then I hit upon the ellip¬ 
soid. It seemed the perfect solution; it 
can model a large class of objects with 
low resolution, needing only a few ellip¬ 
soids for any given object. 

Two problems remained: how to find 
the perspective view of an arbitrary ellip¬ 
soid from an arbitrary point, and how to 
draw that view at high speed. The general 
feeling was that the view of an ellipsoid 
must be an ellipse, but there did not seem 
to be an easy way of proving that, nor of 
finding the formula that described the re¬ 
sulting ellipse. 

A solution to the second problem, 
how to draw an arbitrary ellipse at high 
speed, was discovered by Pitteway (M. L. 

(Continued on page 58) 


Table 1. 


- Addresses - - Instructions - 


vers 1.4 

vers 2.2 

Verify 

Change to 

Purpose 

0362 

036F 

AN I 

5F 

AN I 

FF 

retain lowercase 

0380 

038D 

MV I 

M, 00 

MV I 

M, FF 

allow empty lines 

0434 

0441 

SUI 

61 

AN I 

IF 

allow both A Z and *z 

043A 

0447 

MV I 

A, 19 

MV I 

A, IF 

allow A [ for ESCape 

044C 

0459 

INR 

A 

NOP 


ii n ii M 

0516 

0523 

CPI 

00 

CPI 

FF 

allow empty lines 


Changes to SUBMIT. Using DDT, verify the instructions at the addresses shown, 
then change them as indicated. Save the changed file under a different name and 
test it. 


Dr. Dobb’s Journal, Number 70, August 1982 
330 


9 




Argum — A “C” Command 
Line Processor 


T he Argum package is designed to simplify the process of 
command line argument interpretation. The package sup¬ 
ports handling of dash options as well as command line 
arguments not part of a dash option sequence. 

The job of processing command line sequences can be quite 
formidable if a reasonable number of dash arguments and 
other options are required of program operation. In general, 
each program has its own parser for handling these arguments. 
Not only does this lead to repetition of effort, but also spawns 
syntactical inconsistencies between programs. Such inconsis¬ 
tencies are often hard to remember and tend to frustrate users. 
In order to alleviate these problems, this package was de¬ 
veloped. 

Description 

The Argum package is designed to handle dash options of the 
form 

<-[|+] ><i> [ <[:[|=] ]suf»>] [ <arg > ] 

where s is a single letter or a string beginning with a letter. (See 
more on string format below after A_vset.) As illustrated, the 
dash option may be invoked by a dash (*-’) or, optionally, 
with a plus (*+’) sign. Furthermore, the dash option may take 
two optional fields denoted the sub-option and argument 
fields. Considerable flexibility is afforded since each dash argu¬ 
ment may use zero or more of these options. Furthermore, 
comand line arguments independent of dash options are made 
accessible separately. 

Full error checking includes descriptive error messages and 
numerical return values which exactly describe the nature of 
the illegal specification. 

A_ini: general initialization. The subroutine A_ini must 
be called to prepare the argument processing environment. 
A_ini takes several arguments which will be described in 
turn: 

ARGUM base[ ]; 
unsigned dymax; 

base must be an array of a size sufficiently large to 
handle the dash arguments possible for a given pro¬ 
gram. Each dash option requires one entry in the 
array. The unsigned quantity dmax is the number of 
elements in the array base[ ]. 

char *nop[ ]; 
unsigned nmax; 

nop is an array of pointers to strings. It is filled with 
pointers to arguments on the command line which are 
not associated with any dash option. The unsigned 


by Anthony Skjellum 


This documentation and software package Copyright 1981 © 
Anthony Skjellum. All rights reserved. This software and 
documentation may be distributed for non-commercial uses 
only. Any commercial use, without the author’s written per¬ 
mission, is prohibited. 

Anthony Skjellum, 1695 Shenandoah Rd., San Marino, CA 
91108. 


integer nmax is the size of the nop array, and hence 
is the maximum number of non-associated arguments 
permitted on the command line. If no non-associated 
arguments are expected, pass nop as NULL and 
nmax equal to zero. This will prohibit these argu¬ 
ments from being used. 

nb: The user program may consult the global un¬ 
signed integer A_ntyped which is the number of argu¬ 
ments currently in the nop[ ] array. See Example #3. 

A_set: initialize dash options. The subroutine A_set 
must be called for each dash option to be initialized. It 
returns a dash descriptor (type DASH which is a pointer 
to type ARGUM) for the dash argument initialized by the 
call. A description of A_set’s calling arguments follows: 

char ch; 

ch is the character for the dash option. Both upper 
and lower case letters are permitted and are consid¬ 
ered distinct. Dash options using characters other 
than letters are prohibited (sequences of the form 
-< digit >? . . . ? are returned unchanged since they 
are presumed to be negative numbers). 

unsigned opts; 

The variable opts is the logical OR of one or more of 
the following option selectors: 

A_NONE 

This dash argument uses no options. 

A_ARG 

The dash option takes an argument. 

A_SUB 

The dash option takes a sub-option. 

A_PLUS 

Plus invocation permitted. 

A_COLOP 

Colon in sub-option is optional. 

A_NOCOL 

Colon not allowed to begin sub-option. 

A_COLEQ 

Colon character is an equal sign. 

A program may not declare more than dmax dash options. 
A_set writes an error message and aborts execution if 
such an error occurs. 

nb: A_set is used exclusively to define single character 
dash options. Use A_vset (see below) for setting dash op¬ 
tions longer than one letter. 

A_vset: Initialize variable length dash option. This sub¬ 
routine operates similarly to A_set but with the follow¬ 
ing exceptions. While A_set takes a character as its 
first argument, A_vset takes a pointer to a null terminat¬ 
ed string which is the dash option name. Furthermore, 
the options A_COLOP and A_NOCOL are not available. 

char *str; 

Pointer to the matching string containing the name of 
the dash option. No copy of the string is made. 


10 


Dr. Dobb’s Journal, Number 70, August 1 982 

331 




Therefore, the user program should either use a con¬ 
stant string argument when calling A_vset or at least 
assure that the string contents will not change. 

Matching Strings. When using multi-character dash op¬ 
tions, it is often convenient to permit abbreviations. This 
is facilitated through the matching strings which contain 
the characters of the dash option name and optional ab¬ 
breviation delimiters (the character ‘|’). These characters 
may occur after each character in the string except the 
last. 

Matching strings are of the form 

<char[ T] Xchar[ ‘|’] >. . ,<char> 

The abbreviation delimiters permit a long dash name to be 
specified by one or more abbreviations. Therefore, the 
string “modiule” defines a dash option name “module” 
which may be specified by the whole name or by “mod.” 

nb: The character ‘|’ may not be part of a dash option 
name. 

nb: During parsing, dash options are scanned in order of 
definition. When permitting abbreviations, the program 
should be careful to define dash options in such an order 
that ambiguity will not occur. 

A_pars: command line processor. This subroutine is the 
general purpose command line processor which will be 
employed by most programs using this package. Its argu¬ 
ments are as follows: 

int argc: 
char *argv[ ]; 

The integer argc indicates the number of arguments in 
the array argv[ ] as per the C language command line 
convention. 

int *i; 

A_pars begins interpreting the command line starting 
at the element pointed to by argv[*i]. If *i is set to 
one, the whole command line is parsed. However, if 
fixed arguments are required by the program, it 
should first check for them and then call A_pars with 
the appropriate value for *i. Note that a pointer (as 
opposed to a value) is passed. This is done so that *i 
can be returned with the index of the offending argu¬ 
ment when A_pars returns an error condition (a re¬ 
turn value of less than zero). 

nb: A_pars cannot be used with programs which ex¬ 
pect dash option repetition. To produce command 
line parsing of this form, use A_next (described 
below). 

A_argerr: parse and exit on error. This subroutine calls 
A_pars and then checks for an error condition returned 
from A_pars. If an error did occur, it calls the subroutine 
A_err described below. The result is a descriptive error 
message and an exit with a value of one. 


Arguments same as A_pars. 

A_next: process next argument. A_next contains the 
command line parser for the Argum package and is used 
by A_pars which does the complete parse. However, as 
noted above, A_pars is not designed to handle dash op¬ 
tion repetition. When a program requires repetition, it 
must use A_next directly. Typically, a do .. while loop is 
used. After each execution of A_next, a check is made 
for the occurrence of a repetition. Appropriate action 
may then be taken by the program. The description of 
A_next’s arguments illustrate the mechanism by which 
repetition is handled. See also the second tutorial ex¬ 
ample. 

int argc; 
char *argv[ ]; 

These are the same as for A_pars and A_argerr. 
int *i; 

*i is the element of argv[ ] to be parsed. 

*i is returned with its new value. The do . while loop 
should continue while *i is less than argc. 

char *mode; 
char flag; 

These two variables are used to provide the capability 
to process option repetition. The flag variable must 
be OR’d with A_REP in order for option repetition 
to be permitted. When repetition occurs, the variable 
*mode is returned OR’d with A_REP. This is an indi¬ 
cator for the calling program to handle the repetition. 
Typically, the element of base[ ] will have to be 
moved to a safe place since a further repetition of this 
option will overwrite the contents of the specific ele¬ 
ment in this array. 

The index of the array which was repeated is the return 
value of A_next. 

nb: *mode is returned OR’d with A_NOASC if a non- 
associated argument was encountered. 

nb: See also the function A_copy which provides a 
straightforward way to copy elements of the type 

ARGUM. 

A_until: process until non-associated argument. This sub¬ 
routine processes command line arguments until a non¬ 
dash argument is found. When repetition is permitted, it 
will return to the caller any time a repetition occurs. In 
case of repetition, A_until returns the index of the array 
base[] referenced. 

int argc; 
char *argv[ ]; 
int *i; 

char *mode; 
char flag; 

Same as for A_next. 


12 

332 


Dr. Dobb’s Journal, Number 70, August 1982 



int *count; 

Returns number of dash arguments processed. 

A_while: process while non-associated argument. This 
subroutine is used to process a sequence of non-dash argu¬ 
ments. It stops when it encounters the first dash argu¬ 
ment or when no more arguments are available. If this 
dash argument was a repetition, A_while returns the 

index of the array base[ ] referenced. 

nb: The first dash option encountered by A_while is 
parsed. 

int argc; 
char *argv[ ]; 
int *i; 

char *mode 4 
char flag; 
int *count; 

Same as for A_until. 

A_err: Error handling. The subroutine A_err is called in 
order to display a message based on an error value generat¬ 
ed by A_pars, A_argerr, or A_next. 

int argc; 
char *argv[ ]; 

As above. 

int i; 

Index of argv[ ] containing the offending argument. 
This is a value. 

char error; 

The error variable must contain a valid error number 
returned by one of the command line processors. In¬ 
valid error numbers result in the message Bad syntax. 

char mode; 

The mode variable instructs the subroutine on its fur¬ 
ther action after displaying the error message. If 
mode is zero, it returns to the calling subroutine. 
Otherwise it performs an exit function calling with 
parameter mode. 

A_typed: tests is dash option typed. This function is 
used to determine if a dash argument was typed. For use 
after a successful command line parse. 

DASH name; 

The argument name is the dash descriptor for the 
dash option to be interrogated. 

nb: A_typed and the functions A_t_arg, A_t_sub and 
A_t_plus (the latter three described next) are not sub¬ 
routine calls but instead generate inline code for greater 
efficiency. 

A_t_arg: tests if dash argument typed. This function 
tests for the presence of an argument associated with 


dash descriptor specified. 

DASH name; 

As above. 

A_t_sub: tests if dash sub-option typed. This function 
tests for the presences of a sub-option associated with 
dash descriptor specified. 

DASH name; 

As above. 

A_t_plus: tests for plus invocation. This function tests 
for the plus invocation of the dash argument associated 
with the dash descriptor specified. 

DASH name; 

As above. 

A_copy: Copy element of type ARGUM. This utility is 
provided to aid in processing repetitious command line 
options. When a repetition occurs, this routine will be 
used to move the entry in the base[ ] array to a location 
setup by the program. A_copy provides the subroutine 
to do the actual operation of copying. 

DASH dest; 

The pointer to the destination. 

DASH sourc; 

The pointer to the source. 

A_namexit: descriptive error message utility. This error 
utility is used by A_err to provide descriptive error 
messages. It prints the program name followed by the 
message. 

char *str; 

Null terminated string to be printed, 
char *argv[ ]; 

As above. Used to extract the program name (ad¬ 
dressed by argv[0]). 

After displaying the error message, A_namexit interro¬ 
gates the external variable A_mode for further action. 
A_mode is an integer variable defined by the Argum 
package for handling error exits. If the variable is non- 
zerO, A_namexit will perform an exit function with argu¬ 
ment A_mode. Otherwise it will return to the calling sub¬ 
routine. The function A_desexit performs an identical 
check. 

A_desexit: another descriptive message utility. This sub¬ 
routine is designed specifically for displaying a specific 
command line element as well as an error message. The 
output is of the form: 

program name: message: element 
After printing, it performs its exit check as described for 


14 


Dr. Dobb’s Journal, Number 70, August 1982 

333 


A_namexit. 
char *str; 

Pointer to string containing the error message. 

int indx; 

Element of argv[ ] containing offending element. 

char *argv[ ]; 

As above. 

A_isarg: Check for dash option. This is a utility subrou¬ 
tine used by A_next to check for a dash option. 

char *ele 

ele should point to the argument to be tested. 

char *chr; 

char *chr; is returned with the dash character, if the 
test was successful. 

char *pflag; 

*pflag is returned with a value of two if the dash op¬ 
tion was invoked with a plus. 

Notes On Use 

Loading. The Argum processor requires the include file 
/usr/include/argum.h which is specified by the following: 

#include <argum.h> 

It is also necessary to link the subroutine library for the pack¬ 
age. This is done via a -largum at the loading stage. 


Names used by Argum. The following is a list of names used 
by the Argum subroutine package. Use these names only in 
conjunction with this package. 


ARGUM 

A_argerr 

A_isalpha 

A 

_set 

A ARG 

A_argum 

A_isarg 

A 

_t_arg 

A COLEQ 

A_base 

A_match 

A 

_t_plus 

A COLOP 

A_coln 

A_max 

A 

_t_sub 

A NOASC 

A_copy 

A_mode 

A 

_typed 

A NOCOL 

A_desexit 

A_namexit 

A 

_until 

A_NONE 

A_digit 

A_next 

A 

_while 

A PLUS 

A_err 

A_nmax 

DASH 

A REP 

A_indx 

A_nop 



A_SUB 

A_ini 

A_ntyped 



A_act 

A_init 

A_pars 




Tutorial Examples 

Example #1: Standard parse with A_argerr. Assume we have 
a program which requires an input file and two mutually ex¬ 
clusive dash options to specify program action on the input 
file. We require that the program read the standard input if the 
input file is omitted, and that is write to the standard output. 


Furthermore, in the case that the two mutually exclusive dash 
options are both typed, we want to abort execution. 

The C example in Listing One fulfills the above specifications. 

Listing 1 

#include <stdio.h> /• standard library •/ 

. any other libraries ... 

^include <argum h> /* Argum library V 
main(argc.argv) 

int argc; /* argument count */ 

char *argv[], /• pointer of array of pointers to arguments V 

/• 

declare any externals required by the program 

V 

/• 

declare any variables specific to the main 
program 

•/ 

FILE ’input; 

/• 

this program requires a file desciptor 
for its input file 

V 

ARGUM base[3]; /• space for three dash options V 

/* now define dash descriptors */ 

DASH i_fil, /• input file dash descriptor •/ 

DASH f_dash; /* descriptor for first of two command dashs •/ 

DASH g_dash, /• descriptor for second command dash */ 

/* 

we must also have an integer set to where 
parsing shall begin 

*/ 

int pos = 1; 


/• start at first argument V 

/• 

This program uses no non-associated 
command line arguments so requires 
no nop[] array 

•/ 

Ajni(base.3.NULL,0); /• call initializer */ 

/• 

Initialized for four dash options, 
no non-associated arguments 
V 

Lfil = Ajet(Y,(AJtRG)); 

/• input file -l takes an argument •/ 

f_jlash = A_set('f .(A^NONE)); 

/* first command dash -f takes no arguments •/ 

g_dash = A_set('g',(A_NONE)); 

/• second command dash -g takes no arguments •/ 

/• 

We have now initialized the argument processor 
and can now parse the command line 
V 


18 

334 


Dr. Dobb’s Journal, Number 70, August 1982 


A^jirgerr(argc.argv,&pos); /’parse*/ 

/• A^argerr exits on error */ 


/* 

We have had a successful parse, now 
deal with command line typed: 

•/ 

/• 

Check if neither -f nor -g was typed 
If so. abort. 

•/ 

ifO(A k _typed(f_dash) | A^typed(g_dash))) 

\ 

fprintf(stderr,"\nneither -f nor -g specified\n"); 
exit(l); 

i 

/• 

Check if both -f and -g were typed. 

If so. abort. 

•/ 

if((A k J.yped(f_jdash) + A_typed(g_dash)) > 1) 

\ 

fprintf(stderr,”\n-f. -g are mutually exclusive\n"); 
exit(l); 

i 

/• 

First check if an input file was 
specified. If not. select standard input 
for reading. 

•/ 


if(A u J.yped(iJil)) /*-i*/ 

\ 

if(A_kjarg(i_fll)) /• name also specified •/ 
input = fopen(ufil->a_addr,"r"). 

else 

I 

fprintf(stderr,”\nno -i arg, assumed stdin\n”); 
input = stdin; /• standard input •/ 

i 

else 

input = stdin. /• select standard input */ 


/• 

Now act on -f or -g 

•/ 

if(A^yped(f_dash)) /* -f typed •/ 

I 

... action for -f... 


i 

else 

i 

i 


/• -g typed •/ 

... action for -g option ... 


i 

/• end of program •/ 


Example #2: Repetition processing with A_next. Assume 
that we need a program which is to perform operations on its 
input file in a given order. Such operations will be specified by 
dash options. Since a given operation could be specified more 
than once, repetition capability will be required. 


The C example in Listing Two implements these specifications. 

Listing 2 

^include <stdio h> /• standard library •/ 

/* any other required libraries •/ 

^include <argum h> /• Argum library •/ 

main( argc. arg v) 

int argc; /• argument count •/ 

char *argv[], /• pointer to array of pointers to arguments •/ 


/• 

declare any externals required by the program 

•/ 

/• 

declare any variables specific to the main program 

•/ 

FILE ’input, 

char mode. /• mode variable for A_next use */ 
int retn; /• variable used in do while loop •/ 


this program requires a file descriptor 
for its input file 


ARGUM base[6]; /• space for six dash options */ 

/* 

Make repitition areas for -a. -b 

which are the dash options which will be 

allowed to be used more than once. */ 

ARGUM eL.rep[3],b_rep[4]; 

char eL_cnt = 0. /• repitition count for -a •/ 
char b_pnt = 0; /* repitition count for -b •/ 

/• now define dash descriptors •/ 


DASH Lfil. /• input file dash descriptor */ 
DASH ajash, /• function a •/ 

DASH b_dash. /• function b •/ 

DASH c_dash, /• function c •/ 

DASH cLdash, '* function d */ 

DASH e_dash; /• function e */ 


/• we must also have an integer set to where 

parsing is to begin 

•/ 


int pos = 1. 

/• start at first argument */ 

/• 

This program uses no non-associated arguments 
and therefore requires no nop[] array. 

Initialize for six dash options 

•/ 

A_im(base.6.NULL,0); /* initialize •/ 


/• 

Now set the dash options individually: 

*/ 

Lfil = A w yset( ,, iinput".(.A - ARG)); /• form: -i fil or -input fil •/ 
ajash = A_set( a‘.(Aj^RG)). /• function a arg •/ 


Dr. Dobb’s Journal, Number 70, August 1982 


11 

335 



b_dash = A_set('b',(A_ARG)), /* function b arg V 
c_dash = A_5et(’c , ,(A^NONE)); /• function c •/ 

cUash = A_set('d'.(A-NONE)); /• function d •/ 

e_dash = A_5et('e‘.(AJ s J0NE)); /* function e V 

/• 

We have now initialized everything and 
can now begin processing the command line 

*/ 

do /* begin loop V 


retn = A_next(argc,argv,&pos.&mode,A k J^EP). 

/* permit repitition V 

if(retn < 0) /* fated error occurred V 
A^prr(argc,argv,pos.retn. 1 ); 


/• indicate error and exit V 

/• 

Now check for repitition: 

*/ 

if(mode & A^_REP) /• repitition occurred */ 


switch(base[retn] ch) /• act based on dash typed */ 
case 'a': 

/• valid repitition •/ 

if( 0 L_pnt >= 3) /• overflow */ 
repexit(argc.argv.pos), 

A^copy(&aa*ep[eL£nt ■+•+],&base[retn]); 

/• perform copy V 

break; 
case 'b': 

/• valid repitition •/ 

if(b_pnt >= 4) /• overflow •/ 
repexit(argc.argv.pos); 

A-popy(&b_rep[b_cnt++].&base[retn]). 

/* perform copy V 

break. 

default. /• all others illegal */ 

fprintf(stderr, M \nIllegal repititionNn"); 
exit(l); /* leave •/ 

$ /* end switch V 

{ /* end if */ 

{ while(pos < argc). /• continue while arguments V 

/• 

We now have arguments. Program would now act 
on them . 

•/ 


ilOAJLfrrg(Lfll)) /• file name not specified V 

I 

fprintf(stderr, M \nNo input file name specified\n"); 
exit(l); 


else 

I 

input = fopen(Liil->a_addr.''r"); /• open file for input V 
if (input == NULL) 

I 

fpnntf(stderr."\nCannot open %s\n*'.i_fil->a_addr); 
exit(l); 

I 

I 

/• 

Program would now handle arguments 
in a meaningful way. 

•/ 


{ /• end program V 


/• 

Subroutine repexit 

•/ 

repexit(argc.argv.i) 
int argc; 
char •argv[], 
int i; 

( 

fprintf(stderr."\n5Ss Repitition overflow at %s\n".argvfO],argv r i]); 
exit(l); 

i 

/• end subroutine •/ 


Example #3: Using non-dash arguments. Assume that we 
have a program which requires two non-dash arguments as 
well as three dash arguments which direct program execution. 
The program takes its input from a file. 

The C example in Listing Three demonstrates such a case. 


Listing 3 

^include <stdio.h> /* standard library •/ 

/• any other libraries */ 

^include <argum h> /• Argum library V 

main(argc.argv) 
int argc; 
char *argv[]; 

\ 


/* 

declare any externals required by the program 

*/ 

extern int Aj^typed; /• number of non-associated args •/ 

/* 

declare any variables specific to the main program 

•/ 


FILE ’input; /• file descriptor for input */ 
char mode. /* mode variable for A^jiext use */ 
int retn; /* variable used in do while loop •/ 


20 


Dr. Dobb’s Journal, Number 70, August 1982 



ARGUM base[3]; /* space for six dash options */ 

char *nop[2], /• make space for two non-associated arguments V 

/* 

we must also have an integer set to where 
parsing is to begin 
V 

int pos = 1; 

/• start at first argument •/ 

/• now define dash descriptors V 

DASH Lfll; /* input file dash descriptor V 
DASH f_dash; /* function f •/ 

DASH g_dash, /• function g V 


/• 

Initialize: 

*/ 

AJn^base.S.nop^). /• call initializer •/ 

/• 

Now set dash options individually 
V 

Lfil = A_yset("i!nput".(A_ARG)). /* form: -1 file or -input fil */ 
f_dash = A^et(T,(A > JJONE)); /• f function •/ 
g_dash = A k _set( g'.(A k _NONE)); /• g function */ 

/• 

We have now initialized can now 
call A^argerr 

•/ 

A^argerr(argc,argv,&pos). /• parse, exit or error */ 

/• 

Successful parse: 

•/ 

if(A_ntyped < 2) /• two non-associated args not typed •/ 

I 

fprintf(stderr."\nTwo string args required\n”); 
exit(l). 

{ 

/• 

Progreim may now process input file specification 
and the elements of the *nop[] array 

•/ 


j /• end of program •/ 


Error message numbers and their meanings. These are the error 
numbers returned by A_next, A_pars, etc. 

NUM Meaning 

-1 No arguments on command line (i.e. argc = 1) 

-2 Illegal dash option 

-3 Option repetition error 

-4 No arguments available (i.e. starting position >= argc) 

-5 Too many non-dash arguments 

-20 Argument processing not initialized (no call to A_ini) 

-21 Illegal plus invocation of dash argument 

-22 Illegal sub-option use on a dash argument 

-23 Colon character not allowed to start sub-option 

-24 Colon required to begin sub-option 

-25 Illegal character in matching string (i.e. ‘ |’) 

-26 Null matching string 

(Listing begins on page 24) 


Dr. Dobb’s Journal, Number 70, August 1982 


21 

337 



3t 

£1 


t- a c 
*T> \ o O 

# l_ ~ 

cr> q. v 
c > 

- O' C P 

e e o - 


w a. o 
' in c ti l 

' l_ - C V 

o» c 

♦'♦'CO 

c l_ o o 

- <TJ « 

O V V £ 

a i/i a u 

o — 

H- O £ 

O V C 3 

3 Qi in 

* o a CP 

1 C_ * 0/ <v 

c — in ~ 

* a. 3 «♦ 


l_ E 
3» C "9 

£ *0 C. 

at 

a E o 

Oi 3 c 

in o a 

a fc 

<r 


— *#### 

- v s \ \ \ 

3 


o> 3 a; in 

t- •* cn o o> 

o c o * 

~ a» * •- fi¬ 
ve #-.# <«. 

x * * 

On C C C 

C V n> v * n» 

I C £ C C £ 

<! -• O — U O 


xv a» 

* u c 

E * I 

<z 

* * 

\ \ Of 


xv in 

* o c 

6| * 

<i <c a 


3 C. | 
o in <r 


•* c c 

C V 3 

£ a o 

•* O # <♦ 

•“1 

t_ (_ £ 

V nj OJ 

C £ £ £ 

— o o o 


a###*######*# 


#****«#** 


o 

(0 

(0 

0) 

o 

o 

k 

0. - 
Q 2 

<t> 

C oo 

.= 5 


E a 

3 & 

0) ■“ 

k X 

< 4> 

H 



V. 

& 

Cj 

•2 

k 

O 3 
C 3 

V 

CD 

g 

s 

4> 

^ -C 

\ 

<*> 


,o «*. 

V 

G> 

&C 

<3 



\ 

N 

sj 


"3 o 

8 



^ -s: 


§. 

<X> 

<x> 

3 



*> 

•Q £ 


El 


3 ^ 


S3 

cn 

£ ^ 


c ■ a 
■2 S S 
atg 

~ 1> c 

S IS? .2 - 

S ^ ^ 

C . 

*§ § I 

•a | S 
S 


a*######**##*# 


o c 
in v Hi 
v E • 
c in id c 
0j l — - 
E 0* 0) O) 
3 v ib 

o> c v a 
L — W 
* O U O 
a - v 
«♦ <♦ 

oh- in 

o o — 

L. v 

ai 31 at 
a * i_ c 
6 t_ o* — 
3 c v in 
c *» c in 
— 0) 
o 3 O O 
at a» a. o 
c c t_ 
nj as - a 


- * # # 

* \ \ \ 
3 


a##*##**# 


Q, V * V 
I c £ C 
<X - O — » 


Dr. Dobb’s Journal, Number 70, August 1982 



Argum Line Processor 

(Listing continued, text begins on page 10) 


IP 

c 

o 


* 

ip 


73 

c 

o 

a 

c \ 

o * 


73 

(u 

i 

j!i 


l~> c 4-» • w 

u 01 — o 

3 E «-» c 

o' 3 — ai u 

i_ cp \ a. <5 

<v L. * Qj C 3 

* * LOO 
n \ « L 

C Oiu TJtJ *0 

- C 3 QJ - 

- o<p V ^ 

O (_ C. - O 

Qj JO •«- Q. 

(_ IP U Qj l_ 

O Oi O L H 

** O T3 IP fi 

i/i ^ - ui — e 

~ IP * O 3 

+> IP IP C I i. c 

C Q» i_ — C 

3 L Hi O C «*- 

o <V +> +> COO 

a c l. o 

in o o «-»<*£ 3 

cr a. ip — o — 

<V +> - t3 

— C O £3 

<*-30^03 
- O «-> C 

0i O 3» OK (PC 

"O * o r» cp 3 

O CPL <0 Oj <0 4-» 

G L L « III - li 

* ui n a 3 f l 


# 

\ 


* 

\ 


* * 

\ \ 


O r-1 

CP ij 

l_ 3 

w u t_ 

— CP * 

- (- * — 

<• * 


3, * 

I C £ 

<r - u 


qj ip *■* 
n cp c 
0*3 

e - o 
* o 
* 

l_ C. 

m m +> 

£ c. c 

O O — M 


ip 3 a 

L. O 
Qj £ 

*» U £ 
C - IP 
- £ * 
0 3 0 

a. 

~ 31 


— IP 
O - 
O £ 


£ 

D 

O 

a 


E a. 
- o 
x c 


o 

CL 

<r 


6 | "l 
<r <r 


I L. 


****** \ 


\ ***** * 


* ^ 

I IP 


£ £3 

! I 

<r <i 


~ \ 

— * 

o 

O TJ 
o qj 
C 3 
• O 


■a 

a» 

ip 

o 

u 

c 

Qj 

73 

C 

QJ 


Qj 

IP 

* 

a 

I 

-I 

»♦- 


* 73 

\ C 

Qj 

**» 

* m 

\ ip 


°\ o 
<1 u 


— \ 
o 

°l~ 
<r ro 
w 

it i 
II W 


a 

qj a i 

* c 


Is 


00 C 
00 O 

~ O 

a a 
o 

— * 

o \ 
o 


-1 ’T 
k-i (VI 
<U I 
IP w 
* £ 

^1 3 
<L 4-> 
w a, 


\ \ 

* * 


— 3 0 


IP ~ 
• (VJ 
n (VI 


I 0/ 


L H (-11 

73 T3 

o a -o a 

V ", 3 

I IP I IP 

IP *+■ IP «*■ 



QJ Oi 


IP IP 
10 *0 
a a 

I I 


<E <1 


Qj 

IP 



Qj Qj 
IP IP 
* «0 


Pdi V 


<*> <-s 


\ 

* 

H- 


c 

qj 

* 

\ 


o 

Qj 

IP 

O 


u 

c 

Qj 


73 

C 

Qj 



26 

340 


Dr. Dobb’s Journal, Number 70, August 1982 


if <n_isarg(ptr,8.chr,&pf lag)) 





Dr. Dobb’s Journal, Number 70, August 1982 


27 

341 


Argum Line Processor 

(Listing continued, text begins on page 10) 


\ 

<1 


\ 

* 


oi 

c 

* 


• I 
II 


y 

* 

s 


* 0/ 
£ l. 
Q. 


Ul 






01 £ 

** o c 
c — ui 
- £ * 


1 L. ♦-> 
4-> — 
Ul B 


W \ I 


w o» 

f 41 C 
O £ — 
Ul — 


3 

O it «. 

M A A 


13 Ul 
O O 


C Ot \ 
0» ft 
6 C 

0i — Q. 

— o o 

oi a c 

*4- H- C 

~ o o- 


t* 4. 

E * 


E 

D 

e> 

o: 

<r 


I 


E 

D 

O 

a 

<r 


L 0» - 
Oi E U 
+• 3 O 
C Oi Ul 


E a 
* 


E *4- 
3 O 


6 n Qj 
-30 
X C 
* U — 
E * 

ft 

ft ft \ 

\ \ 


— 6 <v — 

III 
<i <t <r 
c 

o o o 


Ul Ul Ul 

c c c 

3 3 3 


-J a 
D o 
z c 


D 03 
Z 


a 4 
O E 

35 


On*..,* 

* »-* E n 6 

4i 4i O u C 

ui ui a. 

t * o o o 

■Q X3 Oi C Oi 

w _ C ft C 

- E OI OI 
CD-u- 

- O Ul * Ul 

Joe. c c c 

« « 3 O 3 S 


v <r 


I I 


* ^ 

W .* O' 

L O L. 
l_ O' ^ 

a. t- ft - 

O' 'O ft 

t- L 

* * 4-> 

I C £ C 

<r - u - ^ 



\ 

ft 


X 

Oi 


Oi 

O 

O 

E 



Oi 

O 

O 




* 

£ 

O 


c 

c 


' .% 4-> 

o > c .* X 

O'** O' o Oi Oi 

L O L CO 

* O’ 'U L. O 

w C ft Oi 6 

c n 


i- L C C 

01, 4-» * 4-» * * 

I C £ C £ r 

<z — a - o o 


v 


43 

Oi 

Ul 

ft 

\ 




Dr. Dobb’s Journal, Number 70, August 1982 




Dr. Dobb’s Journal, Number 70, August 1982 


29 

343 




IIo Argum Line Processor 

(Listing continued, text begins on page 10) 


********** 


<S 

\ 


CO CD 
\ \ 
N * 
*1 O 
\ \ 
GD cn 

G> S 


* 

* 

* 

* 

****** 


* Q. £ 
O ^ 


O O +* \ o 

l — a * - 

Ol «-* o *-> 

NO. O Q. 
O £ Ol O 

in in 

c £ * 3 in . 

-WO - 

- o oi « c < 

c n 

3 3i 
n c 

»4- CD 

O C 2* 


Ol D 

3lJC 


3 «■* C o in 


-O — ■ 


in o 

I 3 — 

I — o 
i a. u 


Q (\j tj CD 


lO W 

m 


a. -j o 
u in o o u 
z o m d j <j j 
o a: d _j o o o 

l <C | W | ^l°l Z |°i 

<z <r « <i <x <x <r 


U fli tl Qj Hi 4i 1) 

t> TJ tMJ O O t) 
************** 


cn c 
- 

£ 6 


-* - O — 


o in - - 


^ rvj 

u 
u ) 
o. <r 
u o 

*1 Z | 

<r <r 


Ql Qj Hi Qj Qj CL, Qj a, q, 

ccccccc cc 


tJ in a u a - 


* o c «■* Q. 

\ a si a a 

* c oi e o o c 


+> — in o* a n — 


OL.\C*»Cl_33o 

♦>*aia-'duiiflu 


E 

Ol 3 I 
^ Ufl 


a. c \ 

m o * 

L. — 

o cn 
ai a * 
a — 
a* «*- 

31 

•n 19 c 

e c ** 

L Ol 
£ 01 C 


U Ol O O o 
^ ^ Ol Hi oi 
LC—— — 

£ O-- 

u af <i- 4. 


a. «-» 4 -* ^ 

to Ol I 

* in in i 

n cr cn i 

oi m m » 


*■ **■ in ♦> a* 

- — * 

O n» 


• C 
O 

+* — 

C ♦■> 

qj a 

6 O 
3 I 
oi n 

£ 3 

* in 


n oi oi - 
» 3 3 U 
* c. L. 


********* 


_ L C 

!L P tJ o 

oiai in o. — o’ c o o 

c — Ol £ 3 o o in m - HI 

L-L 3-Oifl-o 3- L || 

♦■>-n>inai_ 3 oo— o* 4 in 
j4.«f4.^«inocao)#» 

OOOOOOOOOOO 

OlQiOlOiOlOiOlOiOiaiOi 

ccccccccccc 

OIO*OIOIOIOIOIOIOIOIOI 

£ ' — — •— •— -M l_ l_ 

*ininwinininininininin mm 

£CCCCCCCCCCC££ 

0333333333 3:j0u 


3 3 
t- L *♦- 
♦* ♦* — 


•* O X 
Ol C m 
in - 6, 
m I I 
n <i <E 

I 

« D D 
* Ol Oi 

c c 

E Ol Ol 
D - - 
O in in 
a c c 
... <13 3 


in 


c c c 


Ol *. 

in i. 

:> ♦* ■ 
I in 
<r * 

I L 

tf) m 

<i r 


<+■ ^ 
*■> ri 

c w 


L L * Oi Oi 


(J C QJ *> +* 

m ~ — 

t. O — «■> ♦* 

m a - o o 


*• in o L. 3 


* * 

\ \ 


^ ® 

l. in «... 

*-> n (S (9 

in ii 

* O H II 

cn qj 

II c — Ol £ 
L — L 3 

£«-» -* in 

o in «*- <«><«- 


* * 

\ \ 


— o 


.. .. <3 re 

n 

o n j d « 

a □ o _i \ 

V. U M 

« <E <1 <1 
o» oO o« oft 
in in in in 

a a a a 
o o o o 


x x x x x 

T3 o o o u 

c c c c c 


o o o o 
c c c c 


I I I I I 

<r <i <l <r <l 

Ol Ol Ol Ol Ol 

in in in in in 

m * 

a a a a a 

I I I I I 

<L<L<1<L<Z 


Mil 

<L <L <L <1 


anna 
I I I I 

<L <L <L G 


C 

3 V 


Q. 

O 

-J 

o 


£ 

Oi <c 

o c 
+> / 
in : 


<L O v 


E 

D 

0 

a 

€ 


lc 


Dr. Dobb’s Journal, Number 70, August 1982 










z 

D 

O 

a. 

<X 




3» 

a 

T3 

QJ 

W 

3 

Qi 

£ 



4-» O • 

C ♦> g 

Oj <9 

e l. i_ 

3 m oi 

o» ►» o 

e cl. 

* - Q. 

o 

3» Q. 

£ 

* 

■a \ 

Of 

in 

3 


O 


♦-> \ 
o # 
c 

c 
0 J o 


a> +> 
in 3 a 

L- O 

Cj £ 

►j u £ 
C — U1 
- £ * 
0 3 0 

a 

3> 
Ifl C 
O CT -Tj 

c 

3 * — £ 

"0 t- *-> 

u 

- in 3 

-0 w 

■D 

O M QJ 


c 


o 

a 


c «• 

Oj - 

e o 

3 O 

O' in 

L. I/I 

>9 * 


g 

CD \ 
g * 

g 

3 • 

g a 
— o 
X c 
* I 
g <r 


\ 

* 

a. 

o 

c 

I 

<r 

* 

c 


in 

L. 

Oj 

a 

g 

Qj 

g 



♦J 

<« 

N 


C 

* 

\ 


"l 

<1 


<9 

£ 

o 


o> 

\ c 

# — 


— \ 

♦j # 


c £ \ 

£03* 
in - 

D *->*-> Oj 

o a. qj in 

o in <* 

o £ <1 I 


g 

3 ~ 


* 

C 

o 


X3 

c 

o 

u 


Qj 

TJ 

* 


c. o» 
o c 



g <9 — 

I I I 
<r <i <t 


in in in 

c c c 

3 3 3 



X 

Qj 


O 

c 

Qj 


O 

Qj in 

- om 3 

- L. 3 — 

- <9 in a. 

*+• «♦- <*• 

A A A A 

till 
<1 <t <1 <1 


~ ~ ~ <1 
<1 <r <1 w 
w w m 
T3 CPX3 3 
QJ t_ 3 — 
a ^ in q. 
3> I II 

I I I I 

<1 <z <z <z 


Qj Qj Qj Qi 
C C C C 


Qj Qj Qj Qj 


*«4*4»*4*»*****##**#\ 


00 

C 


T3 

C 

W 


CD GD 
\ \ 
OJ 'T 


g C 
g o 


31 C 
— Qj 
C «-> 
O «-» 


* — w . 


c ♦» - 
OOfl 
C O — 
£ £ 
l_ ♦-> O 

O — L 

U. 3 Q. 


«-* Qj 
Qj in 

^l *1 

<E <E 

I I 
in in 
<r <e 
a a 


*******444***4444444 


Z 3 
D O 
O w 

a * 

w II 



U TJ 

O QJ \ 

sue# 

* Q. L. 

3 CT> 
3* OI U 
C Qj >9 
t- — 4. W 
t_ qi 

* £ Qi | 

£ <E 

Qj *-> 

in C O 3» 
<9 Qj ►> £ 

A 6 

I 3 L t> 
<X C7> Qi C 
l_ 4-» 3 
‘►'•CO 


m c • l 
£ — £ «• 
3 O CL £ 

w a o o 

0**44 

£ \ \ \ \ 


l a •» 

► Qj L 

a. * c 


*• t. o o 

g +j >9 <9 <9 

I C £ £ £ 

<X — U (J (J V 


N 

* 



* 

Qj 


O' 


a. 

o 

•* o 

Qj — 

in •* •% 
•* * L. C 
£ \ ♦-» — 

I in o 
C. * o 
* - I 

L <1 

z +> * 

D C £ l_ 
O — O <9 

a. £ 

COL.O 
Qj Qj 

C C 

l in in l 
Qj - - Qj 
«■» O' O' +> 
X Qj Qj X 
QJ O O Qj 


O 

a 


Qj 

in 

* 

\ 


\ 

* 


<• 

£ 

u 


■ II 

O’ - 
Qj 

— II 

O 

u c 


LJ I 


Qj 

in 


ii 


c 


o 

u 

I 

<r 


\ 

* 


Qj 

C 


O 

a 


in 


Qj 

in 

•9 

£ 

I 


in 



* 

O' 


a 

Qi 

Q. 

in 


Qj 

in 


A Qi V 


in 

3 


Q- 


in 

•9 

o 


o 

a 

* 


v 


— V 


■- \ 

a * 


rS 



•- V 


I 

cx 

o 

ex 

© 

c 

o 


3 

•S 

5j 


Dr. Dobb’s Journal, Number 70, August 1982 


11 

345 


Summary of Argum Definitions 


Major Subroutines 

A_ini: Initializer 

A_ini(base,dmax,nop,nmax) 

ARGUM base[ ] 
unsigned dmax; 
char *nop[ ]; 
unsigned nmax; 

A_set: Dash option initializer 

DASH A_set(ch,opts) 
char ch; 
unsigned opts; 

A_vset: Alternate dash option initializer 

DASH A_vset(str,opts) 
char *str; 
unsigned opts; 

A_pars: Command line parser 

A_pars(argc,argv,i) 
int argc; 
char *argv[ ]; 
int *i; 

A_argerr: Parses with descriptive errors 

A_argerr(argc,argv,i) 
int argc; 
char *argv[ ]; 
int *i; 

A_next: process next argument 

A_next (argc, argv, i, mode, flag) 
int argc; 
char *argv[); 
int *i; 

char ‘mode; 
char flag; 

A_until: process until non-associated argument 

A_until(argc,argv,i, mode, flag, count) 
int argc; 


char *argv[ ]; 
int *i; 

char ‘mode; 
char flag; 
int ‘count; 

A_while: process while non-associated arguments 

A_while (argc, argv,i, mode, flag, count) 

int argc; 

char *argv[ ]; 

int *i; 

char ‘mode; 
char flag; 
int ‘count; 

A_err: Report error message 

A_err(argc,argv,i, error, mode) 
int argc; 
char *argv[ ]; 
int i; 

char error; 
char mode; 


Utility Subroutines 

A_typed: tests if dash name typed 

A_typed(name) 

DASH name; 

A_t_arg: tests if dash argument typed 

A_t_arg(name) 

DASH name; 

A_t_sub: tests if dash sub-option typed 

A_t_sub(name) 

DASH name; 

A_t_plus: tests for plus usage 

A_t_plus(name) 

DASH name; 


A_copy: copy structures of type ARGUM 

A _ co py (dest, source) 

DASH dest; 

DASH source; 


Miscellaneous Subroutines 

A_match: compare dash names to input 

A_matchG,ptr,eptr,chr) 
int j; 

char * ptr; 
char “eptr; 
char chr; 

A_namexit: error utility 

A_namexit(str,argv) 
char *str; 
char(argv[]; 

A_desexit: error utility 

A_desexit(str,indx,argv) 

char *str; 

int indx; 

char *argv[ ); 

A_isarg: checks for legal dash 

A_isarg(ele,chr,pflag) 
char *ele; 
char *chr; 
char ‘pflag; 

A_digit: test for digit 

A _ digit (chr) 
char chr; 

A^isalpha: tests for letter 

A_isalpha(chr) 
char chr; 


type definitions 
typedef struct 


char 

ch; 

char 

‘strng; 

unsigned 

filled : 1 

unsigned 

farg : 1 

unsigned 

fsub : 1 

unsigned 

fplus : 1 

unsigned 

arg : 1 

unsigned 

sub : 1 

unsigned 

colop : 1 

unsigned 

nocol ; 1 

unsigned 

plus ; 1 

unsigned 

coleq : 1 

unsigned 

varln : 1 

char 

*a_addr; 

char 

*s_addr; 

] ARGUM, ‘DASH; 



/* dash character */ 

/* ptr for var. length mode */ 

/* filled flag */ 

/* filled argument */ 

/* filled sub-option */ 

/* plus invocation */ 

/* set if argument possible */ 

/* set if sub-option possible */ 

/* set if sub-option colon optional */ 
/* set if colon prohibited */ 

/* set if plus invocation okay */ 

/* set if colon is replaced by equal */ 
/* variable length flag */ 

/* pointer to argument */ 

/* pointer to sub-option */ 


Dr. Dobb’s Journal, Number 70, August 1982 




Letters (Continued from page 7) 


When I work out a distributor for 
VENUS, I will tell you! 

Sincerely, 

Herbert Gintis 
Department of Economics 
University of Massachusetts 
Amherst, MA 01003 

Dear Dr. Dobb's, 

Douglas Crockford’s suggestion ( DDJ 
#66) for giving different names to dis¬ 
tinct ADA dialects and look-alikes is 
basically sound, but a mere two dozen 
names probably won’t suffice. The mili¬ 
tary alone will probably come up with 
more than that number of variants. 
Crockford suggests ARMADA and 
RADAR as being of particular military 
interest, but there are other probables on 
his list. (READABLE, admittedly, can be 
immediately discarded as totally inap¬ 


propriate for a military environment.) 

Among the two dozen are HEAD¬ 
ACHE and GONADAL, likely candidates 
for the medical crowd. (It remains to be 
seen whether Walter Reed and Bethesda 
Naval will agree on the same dialect; my 
guess is that each will take one.) The 
Corps of Engineers will give ADAM tho¬ 
rough workout in flood control; CICADA 
will, of course, be reserved for the White 
House. 

It is likely that more names will be 
needed, if only for the proliferation of 
military ADA dialects. I will suggest a 
few: The Department of Defense will 
begin with a single standard version of the 
language for code development. Name — 
DADA. (The Police, by the way, seem to 
be pulling for a subset, called DODO- 
DODA-DADA. Or was that DO-DO-DO- 
DA-DA-DA?) Interservice rivalry will 
cause rapid divergence from the standard, 
as the Army builds an ARMADA, the 


Air Force relies on RADAR and, I sup¬ 
pose, the Navy gets left with NAD A. 
Then there is the regional specialization 
for different theaters of operation: 
ABADAN for the Persian Gulf and en¬ 
virons; ADAK for the North Pacific; 
CAPE-ADAR for the Antarctic; and so 
on ... IBADAN, ENSENADA, LADAKH, 
etc. 

Then there are dialects for special 
purposes: recreation and entertainment 
facilities will do their accounting in 
PINACOLADA; public relations comput¬ 
ing jobs (below the Joint Chiefs level) will 
use ABRACADABRA. .. . 

Roy Smith 
P.O. Box 4288 
Berkeley, CA 94704 

Editor’s note: Roy’s article went even fur¬ 
ther, but our prototype typesetting pro¬ 
gram (written in DELICADA) wouldn’t 
print the clever but rather off-color 
finale. SBj 


33 


Dr. Dobb’s Journal, Number 70, August 1982 

347 



Performance Evaluation 

in Small Computers 


T he evaluation of performance is es¬ 
sential in all branches of business or 
engineering. Through careful perfor¬ 
mance evaluation, one can find out the 
merits and deficits of a product and ob¬ 
jectively compare various products. The 
evaluation of performance of a complete 
computer system is especially complex 
because it involves both hardware and 
software components, as well as the spe¬ 
cific mixture of jobs to be run in the 
computer. A good understanding of com¬ 
puter performance evaluation is essential 
in choosing a cost-effective system to 
meet specific job requirements. 

Many factors can affect the per¬ 
formance of a computer including the 
CPU speed, disk and printer speed, nature 
of algorithm of the application program, 
the computer language used, memory 
speed and size, the sophistication of the 
operating system being used and the 
work load. Computer performance evalu¬ 
ation is at present an important, emerging 
field that helps the system programmer to 
design, install and improve the operation 
of a computer system. I have chosen to 
illustrate some of the factors that affect 
the performance of a computer by pro¬ 
gram examples and precise time measure¬ 
ments in a small computer system. 

Hardware Configuration 

The computer used for the perfor¬ 
mance test programs is a Cromemco 
Z-80 microcomputer equipped with 32K 
bytes of high speed (250 nsec) RAM with 
no wait state necessary at machine cycles 
of 4 MHz. The CPU speed can be chosen 
between 2 MHz or 4 MHz by means of a 
two-way toggle switch on the CPU-board. 
This feature is extremely handy to de¬ 
monstrate the effects of CPU speeds on 
computer performance in a given appli¬ 
cation. Other hardware includes a console 
and floppy disk interface (Cromemco 
4FDC board) and two serial ports (Cro¬ 
memco Tuart board). The disk drive is a 
Persi 277 drive for 8-inch single-sided, 
single-density diskettes. 

One of the two serial ports (port B) 
on the Tuart board is used as the printer 
output port. This is normally operated 
at 300 baud for a Texas Instruments 


by Michael Kan 


Michael K. Kan, Scripps Memorial Hos¬ 
pital, 9888 Genesee Ave., La Jolla, CA 
92038. 


Silent 700 thermal printer. For compar¬ 
ing the effects of changing the printer 
speed on the program performance, the 
baud rate of the printer output port is 
changed by software to 9600 baud and 
a CRT is attached to the printer output 
port to simulate the presence of a fast 
printer. This port is operated at 9600 
baud. Although the performance evalua¬ 
tion described in this paper was carried 
out in a Cromemco computer, the same 
program can be adapted to run on other 
computer systems to study the effects of 
CPU, I/O channels, computer languages 
and algorithms on computer perfor¬ 
mance. 

A system clock is necessary to pro¬ 
vide accurate time measurements of the 
system elapse times and printer I/O times 
in different version of test programs. 
Since a system clock is not available on 
the Cromemco computer, an external 
clock has been added. Communication 
between the system clock and the Cro¬ 
memco computer is carried out by a 
second serial I/O port on the Tuart board. 
The construction and operation of the 
external system clock was described in an 
earlier paper published in the May 1982 
issue of Dr. Dobb’s Journal 1 . 


Test Programs 

Two different programs have been 
designed to test the performance of the 
computer using different CPU speed, print¬ 
er I/O speed and different languages. The 
first test program is a random number 
generator based on a linear mixed congru- 
ential algorithm. This represents an I/O- 
bound job, since the calculation of the 
random number is relatively simple, in¬ 
volving only a few multiplications, addi¬ 
tions and divisions for each random num¬ 
ber. 

The second test program is a prime 
number generator. It has two versions. 
The first version (Primel) attempts to 
find the first n prifne number by a brute 
force approach. It simply examines a 
number of magnitude n and checks to see 
if there is any number between 2 and 
n- 1 that divides n without any remain¬ 
der. n is a prime number if it is not divisi¬ 
ble by any number. This is a very slow al¬ 
gorithm because as n becomes larger, the 
number of divisions becomes propor¬ 
tionally large. This kind of prime number 
generator serves as an example of a CPU- 
bound job. 


The second generator (Prime2) illus¬ 
trates the great importance of an efficient 
algorithm to achieve good performance. 
Although the Prime2 program only in¬ 
corporates three changes as described in 
the FORTRAN program (Listing 6), it 
improves the computational speed tre¬ 
mendously. A good discussion of prime 
number generator algorithms can be 
found in Niklaus Wirth’s text 2 . 

All test programs are implemented 
in both BASIC and FORTRAN for the 
comparison of performance of the two 
languages. Cromemco 16K Extended 
BASIC v. 5.4, which requires a minimum 
of 32K bytes to run was the version used. 
The FORTRAN program is compiled by 
an early version of the Cromemco FOR¬ 
TRAN IV that will run in a 32K system 
(the later version will require 64K bytes 
of memory and support more functions). 
The various BASIC and FORTRAN pro¬ 
grams are in Listings 1-6. 

Test Runs 

All test programs are run under the 
same hardware configuration within a 
period of two days to minimize any en¬ 
vironmental changes. The output formats 
of all programs are similar (Figures 1-2). 
The BASIC programs are first tested for 
correctness and then stored on disk. Simi¬ 
larly, the FORTRANs are compiled and 
tested before storing as relocatable mod¬ 
ules on disk. The FORTRAN system rou¬ 
tines are linked to the relocatable mod¬ 
ules by the linker each time the test run is 
performed. 

Apart from the test programs, two 
other programs are used to keep track of 
the system elapse time and to print out 
the ©lock times at the end of each test 
run. These two programs and the test 
program are stored in a command file for 
batch operation. The first program in the 
command file is a “Jobbeg” program that 
sends commands to the clock simulator 
to reset all clocks and turn on the system 
clock just before loading the test program 
specified in the command file. Each test 
program has incorporated instructions to 
turn on the printer clock just before a 
random or prime number is printed on 
the printer, and turn off the printer clock 
after completion of printing The last pro¬ 
gram in the command file is a “Jobend” 
program which sends a command to the 
clock simulator to stop the system clock 
and then gets the system and printer 


34 

348 


Dr. Dobb’s Journal, Number 70, August 1982 



clock data and prints them out on the 
console. The Jobbeg and Jobend pro¬ 
grams were described in the previous 
paper 1 . 

Results 

The total elapse time and printer I/O 
time for each test run are given in Tables 
1-3. The random number generator pro¬ 
grams illustrate the effects of I/O channel 
speed on the elapse time. For example, 
the elapse time averages 5 to 6 minutes 
for output at 300 baud on a slow printer. 
The elapse time is reduced to 1 to 2 min¬ 
utes for faster output at 9600 baud. The 
speed improvements will be more promi¬ 
nent if a longer run is performed by 
generating, for example, 10,000 random 
numbers instead of 500 random numbers. 
This is true because the system overhead 
time used in loading the program will 
then be relatively small compared to the 
total elapse time. Nevertheless, the ran¬ 
dom number generator test runs do illus¬ 
trate the characteristics of an I/O-bound 
job. The elapse time in such cases will not 
be affected greatly by the CPU speed or 
by the language used. The use of a high¬ 
speed printer, however, will dramatically 
reduce the system elapse time because the 
printing time is the bottleneck of the 
whole system. 

The Prime number generator test 
runs are extremely interesting because 
they serve to illustrate several important 
factors in computer performance. It can 
be seen that the most dramatic improve¬ 
ments in the speed of our test programs 
can be achieved by a good algorithm. For 
example, the Prime2 programs outper¬ 
form the Prime 1 programs by a factor up 
to 37.2:1. The various elapse time ratios 
between Prime 1 and Prime2 programs are 
summarized in Table 4. If we only con¬ 
sider the Prime 1 programs, and assuming 
that a faster algorithm were not available, 
then the CPU speed will govern the elapse 
time. The Primel program is an example 
of a CPU-bound program. By increasing 
the CPU speed from 2 MHz to 4MHz, we 
can achieve a 2:1 improvement in elapse 
time. It is also noted that in the Primel 
program, the FORTRAN program outper¬ 
formed the corresponding BASIC pro¬ 
grams by a factor of 5-6:1. It is generally 
true that a compiled program will run 
much faster than an interpreted program. 
The performance comparison between 
FORTRAN and BASIC for the Primel 
program is summarized in Table 5. 


Discussion 

The use of performance analysis in a 
computer system is very helpful in iden¬ 
tifying poor performance due to bottle¬ 
necks. For example, if the job of a com¬ 
puter system is to generate random num¬ 
bers continually on a printer, and one 
would like to have as many random num¬ 


bers in the shortest time, the most effec¬ 
tive way of doing so is to remove the 
bottleneck by providing a fast printer. 
Of course, the above example is only 
a hypothetical example and in a real 
computer system the bottleneck may be 
due to slow disk access time or due to 
insufficient main memory. There are 


Table 1. 

Elapse and Printer I/O Times for Generating 500 Pseudo-Random Numbers 

Baud 

Rate 

CPU at 2 MHz 

Elapse Time Printer Time 

CPU at 4 MHz 

Elapse Time Printer Time 

BASIC 

300 Baud 

9600 Baud 

5 min. 43 sec. 

1 min. 7 sec. 

4 min. 54 sec. 

12 sec. 

5 min. 42 sec. 

1 min. 1 sec. 

4 min. 42 sec. 

12 sec. 

FORTRAN 

300 Baud 

9600 Baud 

6 min. 3 sec. 

1 min. 40 sec. 

4 min. 45 sec. 

20 sec. 

5 min. 48 sec. 

1 min. 13 sec. 

4 min. 48 sec. 

11 sec. 


Table 2. 

Elapse and Printer I/O Times for Generating 500 Prime Numbers in BASIC 

Baud 

Rate 

CPU at 2 MHz 

Elapse Time Printer Time 

CPU at 4 MHz 

Elapse Time Printer Time 

Prime 1 

300 Baud 

9600 Baud 

3 hr. 1 min. 
40 sec. 

2 hr. 57 min. 
22 sec. 

4 min. 42 sec. 

49 sec. 

1 hr. 33 min. 
22 set. 

1 hr. 28 min. 
56 sec. 

4 min. 37 sec. 

13 sec. 

Prime2 

300 Baud 
9600 Baud 

9 min. 3 sec. 

4 min. 46 sec. 

4 min. 42 sec. 

26 sec. 

7 min. 2 sec. 

2 min. 36 sec. 

4 min. 37 sec. 

13 sec. 


Table 3. 

Elapse and Printer I/O Times for Generating 500 Prime No.’s in FORTRAN 

Baud 

Rate 

CPU at 2 MHz 

Elapse Time Printer Time 

CPU at 4 MHz 

Elapse Time Printer Time 

Primel 

300 Baud 

9600 Baud 

34 min. 0 sec. 

29 min. 52 sec. 

4 min. 31 sec. 

28 sec. 

19 min. 31 sec. 4 min. 23 sec. 

15 min. 20 sec. 15 sec. 

Prime 2 

300 Baud 

9600 Baud 

6 min. 1 sec. 

1 min. 53 sec. 

4 min. 34 sec. 

28 sec. 

5 min. 49 sec. 4 min. 39 sec. 

1 min. 22 sec. 15 sec. 


Dr. Dobb’s Journal, Number 70, August 1982 


35 

349 






Table 4. 

Elapse Time Ratios Between Versions of Prime Number Generators 

Baud 

CPU at 2 MHz 

CPU at 4 MHz 

Rate 

Elapse Time Ratio 

Elapse Time Ratio 

BASIC 

300 Prime 1 

181 min. 40 sec. 

93 min. 22 sec. 

Prime 2 

Q • O 20.07 

9 mm. 3 sec. 

„ . „ 13.27 

7 mm. 2 sec. 

9600 Prime 1 

177 min. 22 sec. 

88 min. 56 sec. 

Prime2 

. • 37.20 

4 mm. 46 sec. 

o • o* 34.20 

2 mm. 36 sec. 

FORTRAN 

300 Prime 1 

34 min. 0 sec. 

19 min. 31 sec. 

Prime2 

, 5.65 

6 mm. 1 sec 

5 min. 49 sec. 

9600 Prime 1 

29 min. 52 sec. , „ 

15 min. 20 sec. 

Prime2 

1 15.85 

1 mm. 53 sec. 

1 • 00 1L21 

1 mm. 22 sec. 



Table 5. 



Elapse Time Ratios Between BASIC versus FORTRAN Primel Program 

Baud 

CPU at 2 MHz 

CPU at 4 MHz 

Rate 

Elapse Time Ratio 

Elapse Time 

Ratio 

300 




BASIC 

181 min. 40 sec. ^ 

34 min. 0 sec. 

93 min. 22 sec. 

4.78 

FORTRAN 

19 min. 31 sec. 

9600 




BASIC 

177 min. 29 sec. ^ ^ 

29 min. 52 sec. 

88 min. 56 sec. 

5.83 

FORTRAN 

15 min. 20 sec. 


methods available that help determine 
the bottleneck of a computer system 
so that appropriate measures can be 
taken in a cost-effective manner. A 
good discussion of computer perfor¬ 
mance analysis can be found in Ferrari’s 
text 3 . 

I have also tried to emphasize in the 
test programs the importance of a good 
algorithm for efficiency and economy of 
computer utilization. The prime number 
generator is a good example of the large 
degree of speed improvements one can 
achieve without any modification to the 
hardware by using a good algorithm. As 
shown in our testing runs, a better algo¬ 
rithm for prime numbers (Prime2) can 
reduce the total elapse time by a factor 
of over 37:1. Many other important ex¬ 
amples can be found in commercial and 
scientific applications. The use of a good 
algorithm is extremely important in sort¬ 
ing and searching. Comprehensive discus¬ 
sion of various sorting & searching al¬ 
gorithms can be found in Knuth’s 4 and 
Lorin’s text 5 . Other examples of good 
algorithms can be found in applications 
of graphs, path-finding problems, matrix 
multiplication, fast fourier transforma¬ 
tion and pattern-matching algorithms 6 . 

References 

1. Kan, Michael: “Adding a System 
Clock.” Dr. Dobb’s Journal No. 67, 
pp. 30-38, May 1982. 

2. Wirth, Niklaus: Systematic Program¬ 
ming: An Introduction, pp. 137-141, 
Prentice-Hall, 1973. 

3. Ferrari, D.: Computer System Per¬ 
formance Evaluation. Prentice-Hall, 
1978. 

4. Knuth, D. E.: The Art of Computer 
Programming, Volume 3. “Sorting and 
Searching.” Addison-Wesley, Reading, 

1973. 

5. Lorin, Harold: Sorting and Sort Sys¬ 
tems. Addison-Wesley, Reading, 1975. 

6. Aho, A.; Hopcroft, J.E.; Ullman, J.D.; 
The Design and Analysis of Computer 
Algorithms. Addison-Wesley, Reading, 

1974. 




(Listing begins on page 38) 


36 

350 


Dr. Dobb’s Journal, Number 70, August 1982 





Figure 1. 


Console and printer output from pseudo-random 


number generator 


RIJN 



BASIC PSEUDO-RANDOM NO. 

GENERATOR 

HOW MANY RANDOM NUMBER TO GENERATE: 500 

DIRECT OUTPUT 

TO PRINTER 


PSDUDO-RANDOM 

NUMBERS: 


.063053 

.017092 

.104892 

.050776 

.093625 

.739222 

. 396512 

.135222 

.179806 

.343533 

.695523 

.855652 

. 698364 

.457697 

.806866 

. 172751 

.030697 

.349075 

. 680838 

.920559 

.315103 

.691544 

.604361 

.297998 

.044798 

.378459 

.251639 

. 148653 

.045417 

.153369 

. 263255 

.137400 

.201680 

.268237 

.835587 

.527572 

. 641538 

i. 505804 

.032254 

. 812054- 

.719176 

„040344 

. 389199 

.127783 

.587211 

.833924 

.558453 




Figure 2. 


Printer output from prime number generators 

PRIME NUMBERS: 


1 

41 

101 

2 

43 

103 

“i 

47 

107 

5 

53 

109 

7 

59 

113 

11 

61 

127 

13 

/-i~7 

1.31 

17 

71 

L37 

19 

73 

139 


79 

149 

29 

«I* 

151 

31 

39 


37 

97 



Dr. Dobb’s Journal, Number 70, August 1982 








LU 

z 


z z 

Z 

cr z 

HH 


z 

u 

X >-< >-i 


a. <r 

CL 

cr 


CQ 

LU CL IT 

z 

cr 

CL 

UJ 

CL 

E 

X CL CL 


0 0 


a 

Cl 

0 


UJ 

z o 

z 

z 


z 

1- 

z 

*-< cr 

4 

0 

1- 



Z z z rr. 

H H H Q LLJ 

cr cl cr _j > 

CL Q. CL O ill 

o in >o o o 
t >t 'nil «o 

Oj Oj 0j CO <0 


,0 

E £ 

3 O W 

rj co a: 

I Cl 

• a; co 
Tt* £ N z 

.S 1 <E 
W) C o cr 

r? Cl y 

.*5 > ir 

S I EL 

3 E o o o 


CL 0 0 

CL CL 0 0 

LU LlI LU Lu 

Z y f ill dj 

H W X - - 

CL LU LE CL CL 

Cl y Z LU UJ 

z z 

z CL CL ~ 

<r lu lu y y 

CL o O 
0 LU LU U <C 
Ohhhl- 
CL Z Z > d 

CL H w CD Q 


0. LU CL 
CL I O 
Ll LU O Ll 
0 CO 
Z cc -H 
• 0 0 UJ 

i zlL 5 

LU H CT 

ze>-cl 

DhZ 
Z CL M K 
M Q. JZ 


II JZU 

z ~ 

x h J Lil 

<n cl x i 

Z Cl Q H 


j in ~ in in ^ in ^ ii (N 

j«ilu<i <riu<XLU<EZ'iu<r 
-Zh-ZQZl-Zl-ZZL-Z 

^ho:<iii:hii:hii:hm(i:, 
: 0 lL 0 IU 0 CL O ll O C&-CE o i 
nL3L.CClL3LL3lLQ.3liC 


II I II z . 

MZZ h G LU 
II II II LU 0 

h C I— O £E • Z 

CL O E O LUZh 
MO w iN y - y 
Z _J CO Z 

j O 0 LU Ll 0 
Z Q 0 Q I— t—< O 


) rj O o O 0 O i 


^ a> 
C on 

S a 

(0 q* 


o -I 

d) X 

Jr V 

CL b 



y 

H 

z 

cr 

iT 

0 

i_i 


h 

CL 

£ 

cr z 

O 

o 

0 UJ 

\ 

\ 

Cl UJ 

1-1 

*-• 

jh 

iL 

bL 

<r uj 

O 

0 

z ao 

0 

n 

0 

-1 

_i 

i- 0 

o 

o 

o z 

o 

ri 

<i 

cr z 

H 

V- 

Ll o 

00 



cr 




\ 

UJ 

0 




cr 

y 

H- 




o 

<r 

<r 



CO 

y 

cr 

CL 




<r 

UJ 

LU 


s. 

_J 

CL 

z 

Z 


\ 

—* 

UJ 

UJ 

UJ 



y 

z 

0 

0 


0j 


UJ 





Z 

0 

0 

LU 


M 

II 


y 

0 

Q 

„ 




z 

UJ 

\ 

_J 

0 

cr 

LU 

UJ 

0j 


z 

UJ 


CO 

0 

Q 


p 

<3 



•_i 

z 

z 

UJ 

z 

M 

X O 



CO 

<r 


Q 

z 


CL 



z 


z 

y 


h- 

<1 

z 

0 

z 

u. 

Z I 

cr 

0 

Q 



UJ 

0 

Q 

Z 


M 

z o 

p 

z 

<E 

0 

\ 

UJ 


<E 

iT 

-1 


cr z 

LU 

cr 



o o 

0 LU 

CO 


Q 

Q 

0- CL 

Z LU 

CL 

> 

0 

0 

0 o 

M 3 


z 

UJ 

Z 

1— 

ii y 


c 

to 


CO Oj 

z UJ 


z 

a. 

z 


uj m 




UJ 

iL X. 

cr 


3 

o 

CL 

-1 _J 

0 . 


0 

0j 

0 

O 0 

z o 


X 

i 

z z 

0 0 

*-• z 




co ii cl : 

<E LU = = 

OiZOhl-l 

lu z z : 

z z Z z H *-< I-. C 

lu iu lu lu z cr o: : 

CL CL CL CT •-« 0- a. ► 


I- 00 O N o 

*-< CN . *0 . 

z O'- I> N co 

*-« 0 >l o 

^ O' c: o 

: Z E II <1 II IN 

J IU LU ^ II (N II 

: cr cl z ^ z co 


z z z Z 

<—• LU ►—* i—< 

ir ll cc a: 

CL o a. CL 


Z l 
-• ~ <L \ 

II in — CL l 

HldlLl 

v. CL 

cr co u. z 3 

0 II II LU l 

u_ cl w cr t 


« / LL - 

.NOIL O / 
l X h O W Z CJ 

> j- co o = / 

: z i— i— lu 
- w Z I— x Z CO 

» IT lu 0 LU t-H O Li! 

) cl cl 0 z cr j > 

0- o 00 


Z ~ ~ ~ 

o in 

h- u <L ~ <E 
<r i- z a z 
n m cl <i cr 
h cr 0 iu o 
_J Z Ll cr Ll 

<r 


'O ooooo OOOOOOOOOOOOOOOOOOOOOOOOOOO 
* in co in <i n cci o- o h in co *r in *o n co o- o <n oo <*- in <> n oj o. o w n m ^ 
H WH H H H w H ^ (-.J rj I'^-I C-J rg rv| eg eg oo r>j CO CO CO 


Dr. Dobb’s Journal, Number 70, August 1982 




& 

fc. 


0 

LU 

Y- 

Z 

0 

cl 

z 

o 


Q 

LU 


Z 

o 


d 

0 

UJ 

z 







J- 

09 






d 

cr 






0 

o LU 






LU 

o S9 






Z 

cr Z 






LU 







o 

o z 







1— 






cr 

o LU 


_l 



(J 

LU 

o z 


cj 



LL 

CD 






o 

Z 

— cr cr 


ill 



L— 

_i 

X LL CL 


III 


si 

CO 

z 

<E Z 

Si 



o 



- Z X 


0 

z 

o 

0 

LU 

+ . Z " 

o 

LU 


_l 

LU 

z 

*-* LU 

X 

z 


o 

Z 


cr a ~ o 

cj 





0 

CL • O *-* 


L— 

cr 

CL 

h" 

Cl 

Z H- U9 - 

0 



LU 



z> cr ^ x 

LU 

H 


H 


IL 

Z Cl LU - ^ 

h- 

~i 

01 

Z 

_i 

o 

ii zd in — 

Z 

Q 



O 


*-*XZ~l- 



LU 

CL 


h- 

CL z iu <r 

CL 

_J 

1- 

Cl 

_l 

•x 

fl.-h-1-Z 

CL 

_J 



_J 

Z 

Z Z ~ ll 


d 

0 

0 

d 


X Ll O CL O 

Z 

o 

3 

Ll 

CJ 


Z H o 3 IL 

o 



° 




z 



Z 


o 


AC 



CL 


LU 







I 


F 



H 


o 

o o o 
o o in 


O u Q o o o o o o o O CO ^ •'-< 


z 




































0 

Z 

h- 












to 













z 

0 













0 

0 



H 









CL 














0 













0 

o 



0 









LU 













0 















0 



i_i 




CO 





CQ 













z 














<r 




0 









Z 














H- 





















0 





_1 












h- 

0 














09 

o 







z 





~z_ 












0 

0 

Z 




z 










o 
























z 


3 





















CO 





LU 













X 

0 




0 









h- 




0 





z 




z 












0 

H 

X 




o 













CJ 





<r 

















iL 






















> 

CL 




CL 


_l 









cr 







> 










p 







CQ 





0 











0 

0 

0 

0 




1- 













1- 





o 















0 

0 

X 

0 














09 







z 

CL 















z 

0 

H 


z 



0 









z 




cT 




<r 

CL 


OJ 


in 












z 


z 

0 













Q 







CL 
















z 


X 

<r 

0 



0 










Z 



D 



CJ 

o 

z 


CL 


Y- 


Q 


cr 








z 


CJ 

1- 

0 











H 

<c 



z 




o 

d 




09 


UJ 


UJ 






Q 

0 


3 


<r 

<r 


09 










z 



<r 



x 

CL 

CL 


H 


cr 


CL 


h- 






UJ 

z 

0 



i- 

0 











0J 

z 



z 




Cl 

H- 


d 




t—i 


z 






h- 


z 

0 


z 



> 










o 



z 



< 


CL 


CL 


0 


09 


i—i 






<r 

cr 

1—1 

X 


u 

0 


L-l 









z 

o 



p 



CQ 




LU 




LU 


CL 






cr 

0 

0 

H 


z 

to 


0 









o 








IU 

Ll 


Z 


iu 


Ul 


Cl 






UJ 


0 


z 













0 







c 

Z 



LU 


> 










z 

09 


Q 


o 

0 


o 









0 

z 



h 



•a 


OJ 




d 


to 








UJ 

<r 

0 

Z 

0 


0 


z 

















CL 

LU 




to 


cr 


K 






0 


0 

■N 

z 

0 

H 












p 







O CL 

Z 


CL 




LU 









a 





<r 











d 

z 


z 








LU 


> 


CQ 


H 






UJ 

0 

0 

0 

0 

0 

0 


CJ 







cf 


z 

0 



CJ 




09 Z 

CL 


CQ 


_i 


z 








0 

h- 

H 

Z 

0 

0 

LU 


0 







'3' 



to 



z 




<r <i 

CL 


Z 


z 




CL 







to 


H 


09 

Z 


X 









> 







•53 

CQ I 



x 


o 


z 


\— 






0 

0 

Z 




0 


o 







O 


z 

> 


# 

Q 



ix 

Y- 



z 






0 






1- 

H 


>- 


1 

0 









1- 


<r 

0 



Z 



0- 

09 

P 




z 


UJ 


0 









0 

to 




0 







o 






0 




O CL 



LU 


o 


z 








09 

0 

CJ 




09 


l_l 




0<l 



Q 


> 

z 



09 



u* 

Q LU 

CL 


z 






CL 






r cr 

0 

0 

0 


z 

0 


0 









01 

c* 


# 




O 

CJ h- 

<1 




H 


CL 


UJ 






•N 0 


I 

0 

h- 


0 






0 



Z 






> 



-x 

i'O 

_J 


CL 


<r 


CL 


CQ 






0 

0 

(J 

0 



0 


1- 




0 



0 


0 

Si 



0 



03 

z <r 



Cl 


cr 




£ 



09 



z 

1- 




0 

Z 






1- 



X 


0 

o 


# 




M 

►x lL 

Z 




LU 


Ll 





CL 





0 

to 


0 



z 




to 



h- 


0 

o 



0 



<u 




O 


Q 


0 


Z 



LU 



z 

cr 

1- 


0 


z 












0 



0 



c 

01 CO 

09 











0 




0 


> 

0 

1- 



0 




o 



z 


09 

fj 



o 









to 


CL 


UJ 



z 



0 

0 

0 



0 

0 







+ 











00 

z 

09 




z 


UJ 


z 






z 

z 

0 

0 

0 

o 

z 







Si 


0 


> 

0 

X 


0 



Lh 

d Z 

Z 


CD 


0 


III 





z 




0 

to 


0 

0 








II 


* 



0 09 # 

0 



0) 

cl d 

o 

o 


to CJ _J 


z 


CL 






CL 

z 

_l 

1- 

<r 


0 






N 



—< 


0 

H 09 

: 

H 

09 


bO 

0 CL 

►— i 

09 







CL 



LU 



0 



o 

0 

0 

0 


0 




•N 


Si' 




Z o o 

Z 

o 



o o 

Y- 

1 



iu z 


z 




Cl Z 




1- 

0 

z 


0 







09 

Z 


z 


h- 


o 

Z 


o 


c 

CL O 

d 








h- 






0 

z 

0 


0 

C 

0 







0 o 



O 

0 ^ 


0 

X 



Cl CL 

o 09 


in <r z 


CL 


O 



CL 



0 

0 

to 

to 

0 


o 


0 




o SC X I— 0 


z 

0 

f 

& 

0 

» 


j3 

0 


1 



CL - 


LU 


UJ 



Cl 




0 



z 

G 



<r 




1- — 

1- 






X 



x 



LU 

u. 

o 


0. Oj m 


H 


CL 


/ 



: 


CL 

> 



to 

0 






0 


0 <l z 


to 

z 


7 

z 



<u 

Z 09 


,-1 





Z 




3 

/ 

/ 

/ 

> 0 



z 

<r 


o 


1- 




09 # 

z 

II 


z 


0 0 OJ 

0 

0 


c 


Q 



CL CL CL 


UJ 


0 



0-1 O'! 

N 

C4 Z 

o 

Q 


H 

0 

z 






II - 

II 

z 

II 




O / 


o 


S 

CL I 


si 


LU O LU 






O'! 

/ 


/ 

/ II 

II 

II 

0 

0 

X 

II 


z 



OJ 

Z Si' v 


z 

h- 

z 

1- O h- 

h- 


| r-. 

*C 

LL J— 

Z Z Y- 0 

Ll o 

h- 1- 

V 

1- 


/ 

h- 

l- H 

1- 0 

z 

Z 


0 

H 





II 

II 


to cr 


X 



X z 



*/ J 

CL 




Z LU 

UJ Z Z> z z z z 

Z 

Z Z 

Z 










«— 


0 0 


O 0 0 

z 

Z H 


Z 

1- 



z z 

z z 


Y- 

z 1- 


Q_ 




LU 




11 z 

z 

z 

z 

z 

Z 

z 

•N 

z 


•-« 

0-J o II 

0 

0 


Z 

0 

0 0 0 

0 

D 

uo 

-d 

LU LU 

LU 

LU 

CL 

Z LU Z CL Z CL 

cr 

cr 

LL 

CL 

CL 

CL 

cr 0 

0 

0 

0 

0 

0 

0 

II 

0 

II 



0 09 

•— t 




0 

0 C' 

0 

0 

o 

c 

fl 

CL CL 

CL 

0 

CL 

i-* 

LL 

CL 

•-< 

Q. CL Cl 0 a. CL Q_ 

CL CL 

0 

0 

0 

0 

0 

0 

*-* 

0 Si' 

0 

0 












*-*2 

o 

O O 

O 

o 

O 

o in o 

O 

o 

c . 

o o o 

o 

O 

O 

o o 

0 

o 

o 

o 

o 

o 

o 

o o in 

<0 0 0 

o 

O 

o 

o 

o 

Q 

o o 

o 

o 



in 

|V| 

cT O' 

■>0 

<i m i>. 



IN 

09 

■3- 

U9 <• 


09 O'- 

0 


•N 

0 

«fr 

in 

<1 

N 

CO 

09 

09 

|> o 


O J 09 


in 

<£• 

r- 09 

(>. 

o 

X 

C/1 








~ 1 


■”* 






TH 

•N 

iN 

•N 

iN 

iN 

IN IN 

IN O'! 

•N 

OJ 

•N 09 

I'O 

09 09 09 

09 

09 

0.1 

09 

09 

cr 


* 

e 

K 

o 

<U 

a 

c 




K 






H 


0 





0 


0 




o 

O 


0 





0 









0 





O 


\ 

-0 



1 














o 



Si 







o 




z 

<0 


0 




0 

o 


0 

II 



0 

0 


o 




3 

CJ 



p 



1- 



o 

0 

N 


0 

o 


h- 

H 

t- 


CQ ~ 

H 



d 

\ 


D 



cr 

0 

0 


• -i 

00 



0 

0 


O XI 



p 

z 

H 


z a 

p 


z 

0 

Z 


o 

z 


d 

0 



z z 

<x 


z 


0 


o 

z 


z 

0 

0 


a 

z 


0 

LU 



z z 

o 


o 

p 

O 


<E 0 

o 



z 

1— 


0 0 



0 

X 



CJ 

0 


z 

z 

h- 


O Z 

z 




_J 


o •-« 



p 

z 

0 


+ 

p 


z 

o 

F 


a 

z 


0 

— p 



i- 0 

0 

Si 

CO 

Si z 

o 


09 0 

to 

0 


O d 



0 09 


o 

> 

0 0 

h- 


►H Z> # 

> 

0 Z 

p 

0 

o 


0 0 0 

p 

0 0 


H- 0 

0 


X 


p 0 - 

Si 

09 0 

or 


0 D H- 

Si 

- <r >o 

o 

r X 



X X O 0 

o 

0 UJ ■ 

0 

0 d • 

a 


H d Z X> 

0 

0 0 cr 

0 

0 Z 0 

"09 N 


Z \ z 

0 

Z -1 

o 

z z 

— •> OJ 0- -o 


- " - p - 

CJ 

LH ~ 0 



in x o- cr x 


O - H0 — 


h- O - 

0 

H- O - 

-i h rj i>. w 

09 OJ x II 0u 

0 

— 09 x 

0 

w «3- X 

• -H-0C9O 

• W H 09 o 

0 

h- r- -< 

K 

H 0 * 

in ii ii ii 

O 

OJ - HZ 

h- 

X OJ - 

z 

x x in ~ 

— H 0 Z D 

Ol 

— H- O Z <t 

z 

O - K- 


0 Z - H 

0 <r 0 i 

II 

0 <r o 0 ii 


lu <r 

0 

l-< 0 d 

HZh-0XQ|-ZrH0Q 

0 

0 Y- z 

0 

0 1- H Z 

— cr i o o 0 

— cr 0 

0 

—1 H 0 


0 Z ~ 0 P 

0 O D z o 

0 0 O o 0 0 


<10 0 

0 

<r 0 0 0 z 

3 0 z M Z to 3 0 a 0 to 

z 

0 3 0 

0 

0 0 3 0 0 




o 


0 





z 


z 





0 


0 





_l 


X 





1- 


1- 

o 

in 


o 


o 


o o 



0<l 

CJ o o 

CO O CJ o 

t-i cr 






















0 



























z 





















0 



























0 






0 





















0 






z 





















z 







H 




















“1 






0 

0 


I - 


















z 






0 

o 


0 

























0 


0 


















0 






d 



0 


















z 







Si 



















\- 







to 

a 



















o 

0 







0 


a 

















z 

0 







0 


o 
























1- 

CJ 


0 

















0 

d 









<x 

















o 








o 











0 







0 


to 






r. 

H 


0 
















0 

0 







tH 



h- 
















0 

0 







1 

09 


















z 

p 

H 






z 



cT 

















z 








P 


















z 

X 







0 

Z 


P 






0 



p 


0 






z 

- 0 






H 

d 


Z 






O 



0 


0 





P LU 


•x d 







z 


<1 






H 



0 


H 





0 z 

0 

1 0 






CJ 

z 


z 






<r 





Z 





Y- — 

z 

Z 







0 


z 




U 


0 



09 







<l cr 


X 






z 

Q 


o 





u 



0 


0 





0 0 

0 

X to 






o 



0 





CJ 

z 



P 


0 





0 

0 

0 






0 

0 







0 










z to 


X p 






0 

z 


1- 




•< 

(0 

o 



if} 


O 





0 d 

0 

o 0 







IX 


X 





d 




0 


1- 





CD 

p 

0 Y- 







p 


0 




PQ 

p 

0 



0 







P 


x $ 






0 

z 


z 






0 



0 


h- 





0 UJ 

o 

1— 0 






z 

0 


- 0 




.5 

y 

0 



z 


X 





P 1- 

Y- 

0 









: Z 





-0 

Z 





0 





to 


Ol z 






> 



*-< 









z 


1- 





C9 0 

Z 

0 






z 

> 


# P 






z 





X 





Y- Y- 


> 0 




o 


<x 

p 


# z 




<U 

to 




0 


O 







p 




09 





* 0 




g 

o 

0 



z 







09 0 

o 

09 




09 


> 

z 


# 09 





p 

z 





0 





: 0 P 

0 

0 0 






p 

0 


# 




*c 

o 




0 


0 


— 



iN 0 

I 

X 0 




0 





> 




Ox 


0 



0 


0 


.. 



P o 

o 

p p 




1- 


0 

Si 


4C P 




'W 

z 

0 





z 


09 



E H- 


►X Z 




0 


0 

CJ 


# 




bH 





0 


X 


0 



X 

o 

to x 




0 


p 

0 


# 0 



O 

Q 


o 



o 


z 


0 



z cr 

H 

►X Z 







0 


0 



CJ- 










P 



0 


> 


o 


z 


to 

o 


# 0 



09 

C3 


to 



0 


0 


z 



0 p 

P 

IX 0 


• 


0 





4t= 




ix 

z 

d 



0 


z 





£ Z 

LU 

P z 


O' 


X 


> 

0 


* 0 



0 

<V 

d 

p 



p 




z 



X 




>C' 


1- 



0 

09 

* 0 

cr 


Y— 

c 

0 o 


0 


z 


0 





0 Z 


1- 0 


0- 




p 

1- 

09 

= H 

09 


0 

(U 

0 09 




~l 


0 


= 0 



0 


0 0 


OJ z z 



z o 

0 Z 

t~> 


0 

00 

0 1 


Z 


z 




0 z 



H 

0 

z 


0.i 




1- 


O 

z ^ 

o 




0 






h- 


X HH 



0 Z 

o 

0 






0 

CL 

X 

IX 0 

X 


Z 

o 

0 09 


z 


0 


o 


& cr 



O 0 

09 

09 0 


IX 1- 

z 


z 

0 

r. 

to 0 

r. 


0 

1 




0 


0 


= 0 



0 




r— 






X 

x 



X 

•P 

0 o 




h- 


0 


/• : 


z 

= ■ 0 

> 

X 



OJ z 


(0 

z 

.— ( 

/ z 



H 

g 

z 




z 


K-l 


3 / 


s' 

x D X 


z o 


09 

II 


z 


0 

0 

0-J 0 

0 



X 

l-t s 


0 


0 


p 


- OJ 

OJ 0-J 

OJ z o 

P 

z 


II 

z 

II 




o 

/■ X 

o 


X 

—> 

0 Si 

r 

0 


= 


= 


OJ x 


s' 

/ II II 

II 

0 II 


Z 


z 

Y— 

z 

F 


1- H 

o 

•X 

II 

c 

0 z 

H 

o 

1- 

H 

H 

h- 

1- 

X 

1- 

Y- 

T 

L 

N 

z 




0 


X 




Z 

M 

+ 


a> 


z 

0 z 


Z 

z z 

z z z z 

z 




0 

o 

0 

0 

z 

z 

H 

IX Z 

H 



z z 


H- 


0 




0 



~ z z 

z 

z F, 

■N 

0 

0 


Z 

0 

0 


0 0 


II 

0 

s 

0 LU 

0 

Z 

0 

z 

0 

0 0 0 0 

0 0 

0 0 0 

0 

0 0 

II 

0 




0 

0 

o 

0 0 

o 



) *c 

0 0 0 


0 


0 

0 0 

O 0 

0 0 

0 0 0 

0 

0 0 













a 

O O 

o 

o 

o 

o 

Q 

o 

o 

O 

o 

O 

o o o 

o 

o o 

O 

o 

o 

o 

o 

o 

o 

o 

o o 

o 

o o 


— OJ 

09 

cr U9 

X9 

P 

09 

0 

o P 

Ol 09 

in <i 

0* 

09 0- 



c-J co cr 

in 

>0 

O' 

P O'- 

o 


OJ 

ix 









-H ^ 



^ ^ 



0-J 

OJ 

Ol 

OJ 

Ol 

0-J 

0<J 

0-J 

OJ 0J 

09 

09 09 


.jg .F 

J £ 


oo 

& 

Cl 


CL 

O 

K 

O 

<U 

3 

K 


C 

6 


Dr. Dobb’s Journal, Number 70, August 1982 


39 

353 




co 

C 


e 

2 


j* ^ ^ in <n - 

^ — II - - (N II - 
~ JL ~ « II - <N 
^ I " - h E IN 
Jj-HJCD-uj 

EZZHZZEH 

ChhhiThhh 

P it cc a: o ir a: q: 

XXX3XXX3 


LU 


<r 

a: 

UJ 

z 


z 

(0 D 

^ z 
x > 

LU Z 

- cq <r 

~ > z 

^ ffl O j > 
2 1“ Z CD 

Z LU 

— -J _J G G 
CD <X I J 

• ph D h- P 
G CO G ph 
2 w IU CO 


O 0. 

I- o 
o 

<N _J 

Z UJ 
Ul X 
UJ b 
3 

I- O 
UJ z 

CD ph 
H 

a: *-< 

UJ x 
ca uj 


E PH CO PH > 

P PH PH 

E | Q 

2. 

G > 

Z flj 

X 

<X 


~ G t 

> X 

X 


XQTZQI- 
C <T ph G G 

Z G 
<1 P 

o 


E _J X Z 

z 

CO 


_ > 1' UJ 

G G G P C0 

1- I PH PH 

> D 

CO Z 

p 

G 


h- UJ CO 

G G 

1- 


oo X Z J— 

_J z 

<x 


^ X G G PH 

CD ph 

X 

H + 

E ph I u 

PH X 

G 

Z J— 


a: uj oh 
z u. ui » z 

S w wi-h>. 
i” £ z uj j 

£ UJ Q hh CQ 2 

¥ CD K _l o 

u z it x 

o dquujq: 

-! Z UJ CD Ul 
<1 M hDZffi 
_ G CO Z 3 Z 
3 Z|il«Z j 

O h (_ 2 . 

W £ M UJ J- 
1.0 0. UJ I UJ Z 

_ lE Z H E h 

<i u. <r uj m _j 
O G X X U: 

2 

<0 O UJ UJ UJ CO Q 
p CO CO D <1 2 

j£ <idq:hq <i 

£ 

• zqzouiz 

Tj G Q 3 <1 Q LU 
g oozzhuj 
£ CO 3 

£ ir _i > uj z i- 

P o JZIOUJ i 
0- x « <x K CJ ca 

OOOOOOOOOI 


CO X 

> o 
*-• z 
Q — 

UJ 

> CD 
_l 

I- CO 
OCh 

<T z 

x D LU 

LU UJ Z 

Q UJ 
CO X h- 

- <r <x 

<-» h- 
£ CO CO 

-So 

o 

x co on 

Ul PH 
CD o 
e h £ 
3 h o 
2 ^ o 

UJ J- ui 
x z X 


CO 

x 

UJ 

CD 

z 

3 

Z 


(N 


CN G G it ph H 
w ~ -J o x co 

" Z . - CL Ul 

^?yZ(N\h 

ii ix: • ii 2 . 

Z(UEm 3 01iJ 

" II JL 0- II UJ “ 

” H O Z Q o CC . 2 

&:PhCOX-<\|J-~h 
E _| a. co zr 

-!^OGUOUJU.g 
ZUD(0MQ(- W y 


<E 

CO 


z 

UJ 

UJ 

3 


G it 


UJ 

p 

— G 

PH O 

z 

Z II 

- o 

3 

PH h- 

X z 

Z 00 

z 

X PH 

X o 

> 

* _J 

X 1- 

z 

~ it 

CN h- (J 
" E H 

★ o 
^ ° 

<x 

> 

N ph ^ jr 
•0 J Z H 

- X 

p 


UJ 

-J 

CD 

CO 

> 

a 

H 

o 

z 

X IX 
LU UJ 
CD 00 

II 


* 

o 

G 


x 

X 


z 

o 


it 

a 

C' 


it 

o 

CL 

o 


<L 

tr 

UJ 

z 

UJ 

o 


CD 

z 

X 

z 


tr 

CL 

z 

3 

z 


IT 

0. 

z 

5 


> 

<r 

ir 

X 


UJ 

X 

Cl 


z 

UJ 

LU 


LU 

CD 

z 

z- 

z 


UJ 

o 


V5 

□ 

"O 

c 

UJ 


UOOOOOU o 


iZ 

o 

UJ 

I 


tr 

LU 

K 

z 


<1 

tr 

UJ 

z 

LU 

o 

(0 

tr 

UJ 

CD 

z 

3 

z 


G O (J (J G O o 


tr tr 

CL Q_ 

z 

3 
Z N 


in - 

h-h X 
UJ - •TH 

3 in - 
Z - I- 
ph LU <L 

I- I- z 
z tr q 
o tr o z 

03U.UI 


o o o 
o c in 

ro T —< 


c 

o 


(0 


-t 

d> 
00 

3 a 

a 


c 

o 

C A 

c 

‘So 

o 

pO 

<L> 


(0 
> 

III 

0 
o 

= - 

(0 £ 

c = 


z o 
II in 


— O 


ir 

UJ 

z 

LU 

0 


tr 

UJ 

CD 

Z 


z 

< 

as 

H 

as 

O 

u. 

.5 

<N 

a> 

e 


a lu 
UJ UJ 
ir x 

<X CO 
CL 

Z UJ 
O I 


Z UJ 
I CO 
b <L 
PH G 

x cr 
•5 z 


tr 

Q. 


0 

t 

0 ts 

CL 3 


c 

o 

o 

00 

c 


a. p 
z § 

UJ 

x z lL 

i- lu o 

i 
O b 

\T> G 

II -J Z Z 

7* V II = / 

*-« X Z z Z CO 
II Ll U UJ ph h m ~ 

^-HHZtrircr.,^ 
CL X X G P 

OOOOOOOOO 
(N 00 <T in sO N 0*1 (?•. 


CM 


n G 
> 


a> 

c 

4) 

00 

Lh 

V 
pO 

6 

s 

e 

V 

. s 
^0 ■§, 
00 - 
c " 

c 

o 

<Z3 y 
0) 

nJ 


X 

I- cc 

►H O 

3 "j 

<r 
¥ z 
P co 
tr uj 

Ll G 
Z D 
LU _| 
X G u 
o z 
Ll iT P-* 
. LU 

<N CD CO 

G E Z 
E D O 

PH 2 PH 

o: h 
cl g <i 
E O 

O PH PH 

oo tr u. 
i a. ph 

•N G 
I G Q 
rt Z E 

*H 0 

NOG 
it’ G I 
E CO K 


CO co G 

-U H J 

> CD 
W O PH PH 

- y- q co 


w > 

'Ll CO 
N CO 
•M G 
00 G 

g 

V- 1 z 


G 

G 

G CO 

a: ph 
G 

g tr 

PH LU 

CO GO 
Z E 
G Z< 

G Z 

G G 
Z X 


G U 

tL ^ X ^ 

■ j g tr g 

O (ft G CD . 
-iDfflZh 
_ <r z d z 

o G Z- Z PH 
ui G Z _J 
G G it 

G G X G 
=! N Z K 
Z <i ph o 
M N (L li 1- 
I- r j 0. PH 

z o*. CJ 

G ► CO G 

Gm<riijz 
^ II CO G 
v Z CL G 

V G G 3 

•0 oggk 

• O Z CO G 

• 00 Z* G G 

z 

o 0 CO X 

u- Q G PH G 

PO G G 

L U h Z 

O o ZD 

G X ph Z 

G G G 

LU <[ Q X’ > 

X G ph CJ Z 

K I- O'; <E 

tO Z G 
ZZGX>- 
PH PH G I- G 


£ £ 
<r 

G I |- 
G G Z 
0 G ph 
X ph G 
Q.hL 
Z G 
-H UJ 

iliq:i- 
Z X G 

x - ' J) 

CL ph o 
'f h- 
Z PH 

- I > 
N X 

- 00 <X 
I PH ,Vl 

z X to 

p G 

G Z G 
GOG 
PH Z 

O J— 

►- G > 

I- Q Z 
GOO 

<0 X 

H to 

to Z PH 
c: ph 
3 H 

Z PH 

K <L 
Z .. K 
- g <r 
JZI 

■it PH I— 

O E 
E Z . 

<r 3 z 

• IT 0 

X G I u 

LU O CO Q 
G X 

Z X CO K 

:• <r o 
Z E X n 
U CC 
G H - 
E tO 00 G 
ph > n rr 
X to |> <Z 
Cl ~ ^ 

0 

<1 I p to 

h- _l 
X G G 
g ph <r i 
Z 3 I P 


G CO 

G X 
> G Z 
»-h G 
X E X 
G D ph 

a z 

co 

G _J PH 
X _| 

<r <r z 
o 

oc e co 
o o <r 
co x G 

SSi 

X I- 
G J- 
I 

I- X . 

G E 
p X <E 
X K X 
o <r g 
o X o 
—I X 
CO x 
O X 

a g ph 

G G 
GEE 

iis 

§££ 
o X 
X (0 
o <X 

o (0 

(N j|- 
• O E 


G 

co a 

PH UJ 

5£^ 

G O O 
CD G O 

O G ^ 
CO X - 

Q E X 
=1 <X 
_• X P 
U G G 

3 o -I 

. £ -J 
i- x <r 

PH g 

_ CN 

z G > 

G Z <1 

X PH X 
»- X X 
X <1 

£ z z 

G~« 
E Z 


O > G 
O G it 

nxu 

X 

0 0 
P G h- 
I 

G h- CN 

I- E E 
0 0 
z X X 
PH u. X 


X it 
CL Q 
Z X G 
O O X 
Z 0 
CO I- 
<L X '/J 
0 

> K G 
CD G X 
, , <! <1 
G X 

-J CO 
G G X 
E E G 
CO ph G 
« X E 

> X D 
- Z 
P G 

I G 
G J- E 
X PH 
G > X 
3 ffi X 


a 

E 


00 X 

I o. 

CO 

CN Z 
i <r 
O X 
pH I— 
V X 
¥ 0 
E X 


X 

X 


G - 


G 


G X X 
0 0 
' !■ I" 

E CO CO 

G - r- 

Z it it 

M J J 
X o G 
X G G 
G G 
p G G 

X r r 

<1 X X 
EGG 
E E 

X PH H 

G H I- 


E Z 

PH hH 

X X G 

X X H 

E X X 

<X G G 

X O O 

G G G G G <L 

1 —* I— I— I— I— I— 

X Z Z z >- <r 
X ph ph G Q 


G goooogogcjooogooc 


_ G 
X CO CO 

o <r <r 

i- 

<1 X X 
-JOG 

rcw 

PH 00 00 


xGG 

8£5 

—I 

G it it 
G G 
X O o 
G _J _| 
X G G 

^ X X 
ph G G 
X K b- 
Z Z 

X PH PH 

G X X 

I X X 

I— 

CO X X 
CO <L O 
Ghh 
X (0 CO 

p 

P G G 
<11-1- 

I- P P 
X Z Z 
O <E <L 
X E E 
E E 
DOG 
v G G 

II il 

II 

X. ¥ 
X _l G 
UJ G X 
E G O 
PHlUh 
I— G CO 


E 

3 

z 


p 

LU 

K 

1- 

G 

<1 

OO 

■J 


CO 

G 


Ml 

<E 

1- 

G 

x‘ z 

G 

X PH 

P 

p _J 

Z it 

O 

3 G 

1- 

z 

G 

X 

G I 

LU 

E b 

P 


E 

X E 


x <r 

Z 

X 
G G 

G 

Z O 

Z 

ph cr 


it X 

X 

G 

X 

G X 


x G G LL 
G G 
E X ph 
■ D O G 
G Z X E 

G H X 
E Z ph X 
G ph E 
E X h- 
H (L JZ 
X x 

<x II II X 
E H X 
E ph G 
II G E G 
Z ph 

x h J LU 
<IXiiI 
E X G h- 


<L 

X 

G 

Z 

G 

0 

X 

G 

G 

E 

G 

Z 

G 

E 


X 

X 


X 
G 

z £ 

£ I 

I— 

X X x 

P g <r 

^ p - G ~ 

O X ° •, o 

O O PH 


G 

o 


p CN 


in 


m in • 

— i— — i 
G <1 G <E 
H E I- E Q 

h x ph x <r 
X O x 0 G 
3 X 3 X X 


r* in x o 

•O (N ph 00 
— . v - 

, in - cn 

i— — i— — 
<X G <X G 
El-Eh 

X ^ X PH 

O X 0 X 
X 3 X 3 


G O G G G G G G G G G G 


40 

354 


Dr. Dobb’s Journal, Number 70, August 1982 



File Transfer Utilities 

SendfReceive 


T hese routines are a follow-up to 
my article on MFT {Dr. Dobb’s 
Journal , #49, October 1980, Vol. 
5, #9), which was very well received. The 
original MFT utility was designed to solve 
the problem of transferring one or more 
files from one diskette to another on a 
single-drive system. These new utilities 
(SEND and RECV) are intended to solve 
a similar problem, namely transferring 
files from one CP/M system to another 
(with a different disk format), over a 
serial link. These are not intended to be 
suitable for file transfers over a phone 
line, for which I prefer my CLINK utili¬ 
ty. These are intended to be used where 
the systems are physically adjacent (or 
at least within 50 feet of each other), and 
can be linked with an RS-232 cable. 
Baud rates of 9600 or above minimize the 
transfer time on large files or collections 
of files. 

There are existing, commercially a- 
vailable utilities to perform this function 
but they are quite expensive and difficult 
to work with, since source code is not 
provided. As this is an essentially simple 
task, 1 have decided to release into the 
public domain a pair of programs (includ¬ 
ing source) that solve this problem in a 
general manner. Availability of source 
code makes it quite easy to bring them up 
on new systems. Note that the ability to 
program in assembly language, as well as 
information about port and status bit lo¬ 
cations are required to move these rou¬ 
tines to a new hardware system. Instead 


by Lawrence Hughes 


Note that these programs are the 
property of Mycroft Labs, and are here¬ 
by released into the public domain. They 
are not to be sold or included in a hard¬ 
ware or software package without the ex¬ 
press permission of Mycroft Labs. Copies 
of the Mycroft Labs Public Domain disk 
(which includes MFT, SEND and RECV) 
are available for $15.00. Sorry, only 8” 
SS/SD "CP/M Interchange Format " is 
available. To order and/or receive permis¬ 
sion to distribute any of these utilities, 
contact Lawrence E. Hughes at Mycroft 
Labs, Inc., P.O. Box 6045, Tallahassee, 
FL 32301, phone (904) 385-2708. In 
any case, the name "Mycroft Labs" must 
remain in the source code, and be dis¬ 
played when the programs are executed. 


of a complex “installation” procedure, 
simple subroutines are provided that can 
be modified, and the entire programs as¬ 
sembled and loaded. 

There are just three routines (INIT, 
initialize port; WACL, write ASCII char¬ 
acter to link; and RACL, read ASCII 
character from link) that need be modi¬ 
fied for any given system. Note that if the 
port in question can be initialized with a 
utility provided by the vendor (such as a 
CONFIG program), then the INIT routine 
can default to a simple RETURN. Note 
that both ends must be able to support 
8-bit characters. Since the source code 
for the RECV program is just a few pages 
long, it can be typed in on the new sys¬ 
tem (minus comments), the I/O routines 
modified for that system, and used to 
transfer over the full source of both 
RECV and SEND. At that point, the I/O 
routines in the original source code can 
be modified for the new system, and you 
are up and running; files can be trans¬ 
ferred in either direction. 

Program Execution 

To use these programs, execute 
RECV (no parameters) on the system 
which is to receive the new files, and then 
execute SEND on the system from which 
the files are to be sent. The argument of 
the SEND command may be a single file 
name, or an ambiguous file name (e.g., 
*.ASM). Files will be sent with check¬ 
sums and automatic re-transmission, if 
needed, one sector at a time. Use the 
highest baud rate your hardware is capa¬ 
ble of for minimum transfer time. 


(Listing begins on page 42) 


Dr. Dobb’s Journal, Number 70, August 1982 


41 

355 



a> 


u 

ai tn 


(j _ 

Hi 

jc id 

Cl 3 


i it) U- 
Oil V 
' W O 3 


u m in i- in 


v 

c 

"1 

o 

u 


c 

Oi 

s 

Oi 

(. 

0 

0 

T? 


O 

u 

0) £ 

N 

tfi 

r-< ^ 

■* u o 
•P Oi 
C £ V 
3 O h 

o. t? a. 
O id £ 
O Qj 3 
—' S- '"5 


(J 

• 

XT 

u 


c 

o 

■H 

ui 

in 


£ 

in 

c 

ID 

k. 

•P 

0) 


jc id 
v t- in 
D1 Oi in 
c<f m 

Qi <4- £ 

.h 3 
JO • 
Qi in 


•P 0i Qi TO 

in (• l id 

Oi O 0 Oi 

3 -P P u P 

e in in h 

Oi Oi Oi O X 

t- *- u w (u 


t- (J <4- 

u u ~ 

* ID •• 

ID 3 ID 


O 

U 

H3 

3 


jC to £t 


o «n 

ID 3 O 
- - TO 

oi o xj xi to r 


it m o l ® ^ tn 

n £ in c o in 

E ro *• ID £ 

-TO 3 t® 3 £ijC k Xi £ 


ci in 
3 O 
- "O 

X T? Xi OXH|-Q£ 


•h m 

o o 

- TO 

■c TO JO O JO X)V JC 


CJ 

<4- 

oi in 
■o o 

- to 

JC TO XI Cl JO £j TO 


JC 


> H -1 CL 0. 0. <*J> 

O > id O 0 O Oi 

£ £ (J 0. 0. CL k. 


> X t. 
O C Cl 
£ h TO 


N 

C 

*) 


ID 

Cl 


> ID H H H H a (L 4. J. 

O k N X ID >fD00£O 

£ O ") -h u £ O tfc T l 


Ol P 
O Oi 
CL fc- 



JZ JZ JZ - 
in in m h a. a. o. +j 
333 > n o o O Hi 
iLfl.iLeCJO.iJ.iu 


JZ JZ JZ 

in m in 

3 3 3 
cl cl a. 


i *H CL CL fl. 

ID 0 O O Ol 

ll id ft k 


■i- JZ JZ pH 

uiiniflHHftftft4) 

3 3 3 > H o O o 0 ) 

A-CLflLEOlJLCLOlC. 



01 

TO 


III 

> 

u 

o 

111 


III 

<0 


Cl H 

3 to 
r o 


in ^ 
Ol id 
JZ H 

tn p 


in p 

3 CL 

id v • £ 

P ID pH Hi 
fD P -h 

"0 in id k 

> Ol 
♦> *1 ID k- 
t- t- c*. 


0 k 0 

•D Qj Ol 

t- V U 

ID <♦- 

V JZ 3 Ol -h 

C O £i Ol h ID 

•H H H Ol 

O Ol Ul H c ♦> H 

OL -H -h c*. c h 

0 0 jtQj<*- 

3 in m jt in 3 

k c c in *h c jt 

p o o h to o< m 

c u o to in h 

qj ai "o 

Oi Qi Oi v ai 

W v ■*) ifl qi p Qj 


Qj to 

■H pH 

i TO V Qj 
1 Hi k V 

I H Ol 

<4- Xi TO 


o 

£ 


0 pH 
k ^ 0| k I) 

3 O T 3 £ 


Oi 

p at 

in p 


in 

»- in 

Ol H 

*o p £ 
id x in 
Oi Oi c 

X +J ID 


P P Oh O 


in <*.<*. ai c m ininQjoifojjHuc oio 




t- 

Qj 

TO 

QJ 




C 




o 


I 

u o 

c 

■H 




TO 




60 

63 

a 


© 

CJ 

UJ 

Ol >c 
*- © 

3 \ 

ut 

u 

P 

3 

0 

k. 

X 

X X 

X 

c 

QJ 

OL 

Qj 

X 

UT 


5CH 




ID O 

Oj 



ui r-j 

pH 

TO 

O 





v 


Xi 

Qi 

© 

0 

0 

© 

C 

O 


© © 

o 



•• 

3 

Ut 




•H 



C/1 


Oj 

U 

C 





QJ 




c 


JZ Q) 

P 

ol 




0 




W) 


P 

P P 

k. 

■P 

1 

3 3 

3 

> 

*i 

3 3 3 3 3 3 

3 3 

a* 

£> 


•H 


0 

0 

0 

c e 

0 

Oi 

0 

0 0 0 0 0 0 


60 



CL 

c 

QJ 

Oi Qj 

OJ 

TO 

Oj 

Oi Qj Qj Qi Oi Qj 

oi a* 


c 












X 











0 Cl 0 u o o 



ts 





ID 

■p 



m 

v V V ^ V 

Xi 

H 





•P 

»D ID 

Qj 


0 

o xi in u ji 

U 

Li 





ro 

■P TO 

jCi 

!!■ 

V 

0 0 ph Qi in ID 

<4- C 


XXXXXXXXXXX 
h M V liT O N < Q liT N CO 
OOOOOOOO’H »hph 


coo 
Qj Oj Oi 


3 3 3 3 3 3 

O C 0 C O 0 

Oi 0) Qj Ol Qj Ol 


3 3 3 3 3 

0 0 0 0 0 

Oi Qj Oi Oi Oi 


C Li 111 <*- fc. ID 


X £l L 


If) 

£ 

QJ 

P 

in 

71 

in 

Qi 

> 

ID 

ut 


x 

o o 

O - II 

h x ui 



42 

356 


Dr. Dobb’s Journal, Number 70, August 1982 


shld oldsp 

lxi sp»stack+64 

lxi d»msSO Jprint heading 

call wasc 

call init f initialize link 







soh i Jump if not SOH | write! push 



in 

m 

Qj 

u 

X 

X X 

it*: ai 

m £ 

L ll t Hi 
O i L - 
•H -« a» H 
*J -t V 

no ai 

L 51 ll 

H It *J 

*-> in x ro 
in m q ai 

Oj 0) Qj u 
X e t. a 





x ax ai 

^*0 -*-Cj ro l x ■+■ 

X 4- *J Hi >ro^*> Jj 

o m m uin-H-xii-jouGCj o 

3i * * £ I*. •'QjOJU'jOj •'foil «•- 

t-xxt-njmxxcrit-rojt-njin 


t- •+• 

c -o x r-j 

-♦-ui u o .* c in m c 

jGWU<*-*-*Ul^G'H'-t > > in o > 

UelMlHUiOltUOfillCOeinOX 

«4.».ro »*-£4i»iDit+) G it G * it Hi *> 

mx 3 X X 0 . 3 It 3 (- (I «- o t- x 3 fc- in 


ro «*- xi in 

•O TJ1 C X 3 CO GH O'tn c 

> in o » h > £ ri ti v ♦) > m o io h 

uemGGGX’-'ininr* oemuo 

(U-it*-foai--£-i- qj •. ro •. no 

l- X 3 <0 3 l-XX t- X 3 it L x 3 ID3 


x rv 

X t (j 1 iO O' Oi 

>cjH>i*in>inoin u w 

GfOUGinOtJeinx £ G if. 

llj *. it) G *. i—« Qj »- fO ■—i * ro e 

t-ro3^XG u X30 I'D X 3 X a. 


<H H H It It H ^ H H N H H ll It H Il H HHH rt H rl rt H H H M H H 0. H r4 r-4 r4 'r-i |]_ H rl H H H ro 'HH HH 0. HHU'HHll HHH£V > V c-i i- f-J 

iCX>lti.«>XltltiL>ilet+J*>XHX>itit>itl0iNl,CXn)6iLN::H>lt£>:>i0>:iOl.N>:iO> | O£>it£XI0£XI8XJ.(ll O L t Ll L 01 

JJ")-ietJXin>-HGGOT£G‘*3>:inin'HG^£GG£GOG1GTrHGTO")rHG£G“)-^£G^G r '"O r- 'U£CJ'’)£Ot'HG' , 5'^CJr-iinG E m u X 0 «- 



Dr. Dobb’s Journal, Number 70, August 1982 


43 

357 


(Continued on top of page 42) I (Continued on next page) 




SEND/RECEIVE 

(Listing continued, text begins on page 41) 



Oi 

> 

o 

£ 

O 

P 

in 

0 J 

p 
* 
£i 

4- 

O 


II 

JG 


in -h 
ui o 

e 0 j 
i 3 


£i 

o 

4- X 
m no 
* oi 
X <- ro 


X 

c 

0J 

in 


c 

H) -4 

O 0 
- ro 
ro 3 


x x 3 

X P —i .G 

c m o x 

QJ - ro ^ 
in ro 3 JZ 


CD CD-o 
r t mti-c 
-h m c c 

*■ t Hi HI 

jG in in m 


p 

£i iZ 
■G 0 Ql O 
v id h 

oiumov 

-ID--*.. 

n ir 0£ 


o x m 
r r in 
c c e 

U Oi * 

e in in xi 


o o 
in oi 
ro - 


in 

m a. 
h in u in 
o e in xi 
ro •• no h 
3 X 3 O 


CJ Ifi P X 

*- ii-3 ro n 
m rt w o ro ro 


ro ro ro *-< jz x x 


p 


4- 


ro 

o 


7* rH n> h h 

X ro <- f -4 flL n v 

^ DOT O ^ 



ro > ro 
u £ o 


0. H -4 H 

e > ro x 

"5 £ U -4 


* flL 

> ro U £ 
e cj 


> ro 

£ U 


ro X O 

U -4 X 


0 . 

£ 

3 


0 . 

£ 



ro > ro 
u £ u 



-nroroui-jH h x x x> r r 
j~ p x ro ol m c x x x x x 
mxiniiooirorororororo 


w x m 

H ’H x £ H £ ’H 

> x ro a £: o > 
e x x -H x £ 



in 

o 

ID 


in 

o 

ro 


V <t- 


u u o 

U O Oj 

in 

' ' 4- 0 
X ttl H Oj 
Qj Ol - ^ 
V J t 


Jj Hi ' (. 

ro tn c- u 
ro o *■ 

c in u % 

O III U L 

H OJ Qj 0 
in e u 
in g u 
h C 3 Ql 
£ 3 in 
in Ox i 
c c UP 
ro Ql M 
t- C £ c. 
K 3 u 3 


Oi 
3 C 
0 0 
Z Q 


0 

u. ro 
cn p 
in 


Xi jG jG jG jG jG 
X X X X X X 


X 

m m c 

XI X (L 


r-j n <o n mo 
in xi xn tn xn tn x ro 

in m in in in in h 

££££££ om 



tn 

ro 


m <♦- 

ro p . 
4 -> ro -h 
ro p -h 
x in ro 
> 

p p ro 
u u 
oo ro 
a. a. p , 
ro 

-i -h x 
ro ro 
•H H x 

t- u ro 
Oj Oj Qj 

in m u . 


m 

ai 

p 

ro 


f- £i 


ro o -4 


ui+j c 

Oi t- X Ol . . 

J H H li 3 H 

* <♦- c O 4- 

4 <4- Qj 

£1 Id E 


(U u 

•H 1-4 Qj 

Oj <4- 4 . jo 


Oj O O 
: m t- t- x 

ii o ro ro ro 

. Ql Ol Ol 
) u m m c. 


C V V 


P Ql Ol Oj 
111 H H 4 J 

31 H -H X 
m 4- < 4 . oi 


c 

o 


<4- 

P P 0 
U £- 

ro ro x 
p +> C 

m in Ol 


o 

Ol 


XXII 

in cm 

o o o o 


\n 

© 

o cm >> ut >0 n ao o 

000-4~4i-4^N 


i 

cj 

J-) 

O -4 

o o 


O' CM CM 

o r-t n 


i 

o 

00 

o 

o 


11 
*■4 cm 
o © 


I 

<T 

© 


3 3 3 3 

C C C G 

Ol Ol Ol Ql 


Ol 

U 

> 

Oi 

X 


3 

c 

0> 


0 3 3 3 

C 0 C G 

Oi Oi Oi Oj 


3 3 
6 G 
Ol Ol 


3 

G 

Ql 


? 3 3 3 3 

o e o c c 

oi oj oi Oi oi 


3 3 3 3 

G G G O 

Qj Qj Qj Qj 


ro p 

■p ro ro qi «*. 
ro +>x -G •- 
x in u +j 


u u u u u o u 

mi4-«4-«4-l4.4.l4-C4- 

ooxicmvcu. 

xoGarHi-um 

ii330umm(- 


£i 

o 

«4- c 

in v 


P X 
4- Ql 


4- 

X 

L 

x 


JZ 

o 

m 


x 

p 

in 


o 

Ol 


44 

358 


Dr. Dobb’s Journal, Number 70, August 1982 









bo 

H. 


H ■«-> 

<+■ C 

Oi 

QJ c 
-P OJ 

m (- 
•o o 
0 . c 

U 'H 


-C H 

(J 

(- CL 


■P 
t- o 

V pH 
0. <♦- 

V X 


Ci 

X <*- 
CJ in 
t- in oi 

•o *0 w ci m "O 


4- a. 

-C <4- 


a oi 

U IT 

ro e 

3 X iX 


>■ U<t- u 

o DH c 

- rs •• ro 

ro 3 fo 3 


x *0 


m 

Oi 


(J 

<♦- 

VJ 

a in 

3 O 
► *0 

Cl Xl Xi "0 X 


ro X "O r X 


t- m 

IT 0 

- "0 

■C f jj O JQ JO TJ £ 


Cl 

<+- 


£ r Xi 


in o 

- xi 

Cl JCi JO 


■D X 


rH oi 
ID Cl 

o x 


<-* rt N 

ro CL C 
0 0") 


a. 

c 

CL 


> X rH c- N 4-> 

o c id o c o> 

£ H U -0 T - 


- -h h a. 

> id > £ 

£ CJ £ n 


> H -H i ll. I). 

o > id o o o ai 

£ £ 0 iX CL CL t- 


.*6 s- t t .*J in 

+ 1 L O L H £1 

ip h r ■) i- 0. 


x x ^ 

lT Ip H H 0, i |X -*-> 

j 3 > ID O O O Ol 

iXlXfcUlXlXlXP- 


x £ x PH 

iPlPlPHniLiLiL+i 
?33>IOOOOHI 
0. Cl CL £ Cl CL CLiXr- 



h v h V 
ID -H H 
H -P <«- 


CJ H 

c <*- 

*0 V 

C- fH 


at x 
£ 

»D 01 


OJ rH 
£ H 

ID <4- 


XXXXXXXX 
111 *0 N € 3 111 N CD 
OOOOO-H^H^H 


UJ *• 10 

Hi IP O iPtl 3 HTODltf.fOinX>3 


+IVD Ol+iV D C h ' 

OUIhJiLIDIDlOiO 

h»»Oh+JD0i»U 

<t-DJj£«fiPl.ipi03 


I <f C 
Ci in Oi 
«*- * a. 

I Ip X? o 


ci m o m ih in r 

V * ID * » 6 

ro in d 3 i Xi in 


00 01 o 
in och 

£ m m h 

Oi - ro - 

in X? 3 X Xi 


ccooceco 


01 -H "O pH H H pH rH H pH ID 
S- X ID jC X X ro ID X ID -0 

Oh-OiPhh(jO-hU-, 


xx>idxccc>id£ 

H H £ O IP H IJ 1 £ [J 1 


10 ID 'H H 


ID ID H r-t H 

t- -p > ro x 

x in £ ci -h 


> ID (j X ID 


Dr. Dobb’s Journal, Number 70, August 1982 


45 

359 


(Continued on top of page 44) I (Continued on next 






SEND/RECEIVE 

(Listing continued, text begins on page 41) 


00 

c 


u 


CJ 

cc 

O' in 

rH O 

0) 


c/i 

□ 

-o 

C 

W 


<1 V 


u 

p 

u 

l/l in 
«- O 
- *0 

£-OLDJjJjti£ 


■c x x -< 

01 |/llfl HHO.|l.(X+J 

3 33>rooooai 

IL A. tX £ U 0. iX 0. t- 


X £ to £ in jCi 


H > X P S- N P 

x o c 3 u c ai 

h £ -h o r i t- 


X (- 

ai ci 


31 i- 
P o 


V 11 > 
1 P 

- P pH 


CJ •* t- CJ 01 


Hi 

p p 

c c 


p to n qi ai 


1/1 rtCIf If 


i p cd m p oi c. 


p ph no 
it m ci p 
p r n id 

l/l S- U TO 


ai ci 3 p 

x it in ft 

P 2 fll X 


? Hi Hi L Hi 


(- X ' 

o c x 
- ai ai 
in p 


' P C 3 0 


(N >o *h r-j ph 


3 C C N O 3 £ 21 


a. c u o 0 it e 


> p 

& xxxxxxxx 

t t t t T3 t t t 


X 

ro 



O pH Cl 

tt oi tn 

in in in 


ro in >o 

tJl TJl TJl TJl 

in in i/i m 

SEES 


H ip I- fi 

in o c p in 

x it ci fll H 


o in p p <*- 


<u x 
xn p 
ro w 


l Qi O 

: p tji 

I 0 IT) P 

i in x 


It ai 

ai > 

rH It 


JC 
Hi Ci 
> P 
It Ql 
in p 


C P Ql 
Qi C X 
£30 
Ql 

t- a. x 
0 0 c 

Ql 0 Ql 


in z 

C 

0 Z P 

cl o o 

me c 

Ql 

t- p <♦. 


it E 

3 3 


ft Z 

tn <c 
ro u 


x a. 

C £ 
Qi 3 


O 

0 X X 


£ 

ro 


<r n 

TJl TJl TJl 

x ui^ in m 

O £ it £ £ 

t in c in x x in 


ro E - 

o m x 


0 

in 

t 

3 


X X 


X 


XXX 


0 

p 

X 

o m 

3 o 

- x 

U x X X X 


p 

c 

ol in 
0 o 
- X 

x-ox uxxxx 


0 

p 

m 


o 

X X X 0 


m 

o 



X JC 


> 

E 


3 3 

a. a. 


> X H fc. N It X H pH 

OCtOCt-3rort 

fiHUXTxmuo 


H H N Ol OL 0. H 

Ol H 0. C 0 0 E a. N 

in u u n n 


phOlOlUPOlOlOOP 
m O OP 1 OOP £ Qi 
oo-iimt-flioimoc- 


xxx 
m in m 
3 3 3 

a. a. oi 


•H PH ll. IX 

> ft o o 

e o a. a 


x x 

m m 

3 3 
0- Ol 


X pH 
in pH PH 
3 > m 


Ol 

o 

OL 


XXX PH 


0. Ol Ol +) 
O o o Ql 
Ol OL Ol c. 



Dr. Dobb’s Journal, Number 70, August 1982 









Numeric Data Processor 

The Intel 8087 


T he Intel 8087 is an astonishingly 
powerful numeric co-processor for 
8086/8088 microcomputers. It im¬ 
plements the proposed IEEE floating¬ 
point standard on a single integrated cir¬ 
cuit. The 8087 is an order of magnitude 
faster than its forerunners (see Table 1) 
and incorporates a degree of precision 
and sophisticated exception handling that 
surpasses many mainframe computers. 

The 8086 was announced over three 
years ago, but due to production diffi¬ 
culties the chip has only become avail¬ 
able off-the-shelf in the last few months. 
Delivery delays aside, the high price (up¬ 
wards of $450) frightened off most of 
the experimenters who form the cutting 
edge for the interface and software ex¬ 
ploitation of new IC’s. Then a funny 
thing happened . .. IBM started selling a 
personal computer, built around the Intel 
8088 microprocessor, that was found to 
have an undocumented, empty 40-pin 
socket on the motherboard. Within a 
matter of hours, it became an open secret 
in microcomputer circles that the mys¬ 
tery socket was properly wired to accept 
an 8087 numeric processor. There was an 
immediate upsurge of interest in the 8087 
among scientists, engineers, speed freaks, 
and of course hungry software devel¬ 
opers. 

We will try to provide here a brief 
survey of the architecture and capabilities 
of the 8087 co-processor, and some 
warnings as well. But first, let us observe 
a moment of silent admiration for the 
pioneer IBM PC owner who, on the basis 
of faith and hearsay, plugged an 8087 
(literaly worth more than its weight in 
gold) into that famous empty socket and 
turned on the juice. 

Overview 

The 8087 is constructed with HMOS 
technology, and contains the equivalent 
of over 65,000 devices on a single sub¬ 
strate. It is packaged in a 40-pin DIP and 
operates from a single +5 volt power sup¬ 
ply. The numeric algorithms are em¬ 
bodied in some 30,000 bits of micro¬ 
code. 

Previous numeric processors for 
microcomputers, such as the AMD 9511 
and AMD 9512, could be interfaced to 


by Ray Duncan 


Ray Duncan, Laboratory Microsystems, 
4147 Beethoven Street, Los Angeles, 
CA 90066. 


practically any microprocessor with a 
minimum of fuss, and were handled by 
the software simply as other peripheral 
devices. In contrast, the 8087 operates in 
an extremely tightly coupled configura¬ 
tion with the host 8086 or 8088, sharing 
the same instruction stream and many 
control signals, and can not conceivably 
be made to work with any other micro¬ 
processor. 

When a program is created that will 
utilize the 8087 numeric data processor 
(NDP), the commands are assembled in 
line with the instructions executed by the 
8086/8088 central processing unit (CPU). 
All control codes for the NDP begin with 
a characteristic “Escape” byte, followed 
by one or more bytes which describe the 
operation to be performed and the loca¬ 
tion of the operands. As the CPU fetches 
and decodes instructions, the NDP moni¬ 
tors the address and data lines, ignoring 
any instructions that do not apply to it. 
When an Escape byte is encountered, the 
CPU proceeds to fetch the following 
bytes in the normal way, which gives the 
NDP the opportunity to grab and exam¬ 
ine the entire instruction sequence for its 
internal use. If the instruction contains 
an embedded reference to a memory 
operand, the CPU will also calculate the 
effective address and place it on the sys¬ 
tem bus; the NDP can capture the ad¬ 
dress, take control of the bus, and per¬ 
form the necessary data transfer. 

This scheme, where only one proces¬ 
sor is responsible for fetching the instruc¬ 
tion stream while each co-processor picks 
out the commands that it can execute, is 
both elegant and efficient. The need for 
transfer of control information between 
processors is minimized, since all have ac¬ 
cess to the same information. Memory ad¬ 
dress calculation logic can be localized 
in one processor. Lastly, there is little 
contention over the bus, since each pro¬ 
cessor is not trying to fetch its own in¬ 
struction stream. 

The pooled resources of the CPU and 
NDP are formidable (see Figure 1). The 
8086/88 has eight semi-general-purpose 
registers, four memory segment registers, 
a status word, and an instruction pointer. 
The 8087 adds two control and status 
words and eight 80-bit, floating-point 
(FP) registers. The FP registers may be 
addressed explicitly or the entire set used 
as a pushdown stack. The latter mode 
simplifies subroutine programming, since 
data may be referenced relative to the 
current top of stack without concern for 


its actual physical location. 

In general, the CPU/NDP combina¬ 
tion may be viewed and programmed as a 
single unit, with the advantage that opera¬ 
tions on each processor may proceed con¬ 
currently. The major restriction is that 
communication between the two proces¬ 
sors must take place via shared memory; 
there can be no direct transfer of data 
from the registers of one processor to the 
other. To forestall the possibility of one 
processor trying to fetch a data value 
from memory before the other had fin¬ 
ished writing it, a special “Wait” instruc¬ 
tion is provided that can be used to force 
synchronicity. 

Data Formats 

The 8087 recognizes three classes of 
data types: packed decimal integers, bi¬ 
nary integers, and binary real (floating 
point) numbers. The two binary classes 
are further subdivided into long and 
short variations (see Figure 2). All of 
these data formats exist in memory only. 
When data is loaded into an 8087 register, 
regardless of its original type, it is con¬ 
verted into a format called “temporary 
real” which is used for all internal opera¬ 
tions. A temporary real number is 80 (!) 
bits in length and consists of a sign bit, 
a 15-bit biased exponent, and a 64-bit 
significand (sometimes called the man¬ 
tissa or fraction). Its extra length shields 
the user from cumulative rounding errors 
or overflow/underflow in intermediate 
calculations. 

An interesting byproduct of this ap¬ 
proach is that the FIX and FLOAT opera¬ 
tions of other numeric processors are no 
longer necessary. To convert a number 
from one data type into another, you 
merely load the number into a NDP regis¬ 
ter, then issue a command to write it 
back to memory in the desired format. 

8087 Instruction Set 

The 8087 has 68 instructions which 
may be broadly divided into six groups: 
data transfer, arithmetic, comparison, 
transcendental, constants and control. 

Each instruction is composed of two to 
four bytes, depending on the location and 
addressing modes of the operands. Each 
byte is in turn broken up into bit fields 
that specify the operation, index regis¬ 
ters, displacement, floating-point source 
or destination registers, and in some cases 
the format of the number as it is stored in 
memory. See Table 2, which gives a sum¬ 
mary of the 8087 commands. 


Dr. Dobb’s Journal, Number 70, August 1982 


47 

361 





Control and Error Handling 

The 8087 provides the programmer 
with unprecedented control over the way 
numeric operations are performed. Four 
modes of rounding are available: round to 
nearest, round up, round down, and 
“chop.” Results may be calculated with 
64, 53, or 24 bits of precision (64 is the 
default, the others are for result compati¬ 
bility with previous floating-point pack¬ 
ages and do not offer any speed advan¬ 
tage). The programmer may select be¬ 
tween projective closure (all infinite re¬ 
sults are treated identically) and affine 
closure (negative infinity is differentiated 
from positive infinity). All of these op¬ 
tions may be selected or changed at exe¬ 
cution time by modifying the NDP con¬ 
trol word. 

During numeric operations, six 
classes of exception or error conditions 
are reported back to the host CPU: in¬ 
valid operation, overflow, underflow, 
zero-divide, denormalized number, and 
precision (advising that the result could 
not be represented exactly and rounding 
was required). Each type of exception 
sets a bit in the NDP status word, and 
may also cause an interrupt to the CPU 
depending on the mask bits in the NDP 
control word. By modifying the control 
word the programmer may accept respon¬ 
sibility for handling certain exceptions 
and delegate the others to the NDP. For 
any masked exception, the NDP’s default 
fixup responses have been tailored to 
deliver the most “reasonable” result. 


Programming the 8087 

Having caught your eye with that 
heading, I must now admit that program¬ 
ming the 8087 numeric processor is not a 
subject that can possibly be covered in 
the space allotted for this column. This is 
not a situation where you can plug in a 
chip, whip a few patches into your 
BASIC interpreter, and run rings around 
the competition. The many powerful 
operations of the 8087, when combined 
with the various addressing modes of the 
8086/88, result in an instruction set com¬ 
plex enough to give pause to even the 
most dedicated hacker. The intricacies 
of assembling those crazy 8086 address 
fields, using the NDP efficiently, avoiding 
deadlocks and race conditions with the 
host CPU, and handling asynchronous 
exception traps are simply going to put 
machine-level programming of the 8087 
outside the limits of time and patience 



Intel 8087 8086 machine 

5 mHz code emulation 

AMD 9512 

3 mHz 

64-bit multiply 

27 

2100 

590 

64-bit divide 

39 

3200 

1640 



Table 1. 


Comparative execution 

times (in 

microseconds) for real number operations. 


Data Transfer 

Fetch number from memory in any format, convert to temporary real, and 
load into floating-point register. Exchange any two floating-point registers. 
Convert contents of floating-point register into desired data type and store 
into memory. Optionally push the stack on a load from memory or pop the 
stack on a store. 

Arithmetic 

Add, subtract, subtract reversed, multiply, divide, divide reversed, square 
root, scale, modulo division, round to integer, absolute value, change sign. 
Optionally pop the floating-point register stack after operation complete. 

Comparison 

Compare two floating-point registers, or a floating-point register and a mem¬ 
ory operand. Alternatively, examine a single register or memory operand and 
set the status flags accordingly. Optionally pop the floating-point register 
stack to discard one or two operands. 

Transcendental 

Tangent, arctangent, powers, and logs to the base 2. 

Contants 

Load floating-point register with zero, one, pi, common or natural log of 
two, or base two log of the constant e. 

Processor control 

Load or store control word, store status word, load or store 8087 environ¬ 
ment and/or register set, enable or disable interrupts, clear exceptions, initial¬ 
ize processor. 

Table 2. 

Intel 8087 Numeric Data Processor instruction repertoire. 

available to the average personal comput- cently, Intel was only selling the 8087 

er user. I strongly advise that you sit back in matched and tested pairs with an 8088 

and let the high-level language implemen- and there was an eight-week lead time on 

tors get the headache instead. delivery. These problems appear to have 

If you are really interested, the ap- been overcome, and you can now pick up 

plication notes and manual cited at the an 8087 at will from Hamilton-Avnet 

end of this article provide some excellent and other distributors. Only a 5 mHz ver- 

tutorial material and detailed program- sion is available at present, so the 8 mHz 

ming examples; however, the latter won’t 8086 and 8088 owners are still out of 

do you much good without the $1250 luck. 

Intel 8087 software support package and The cost of an 8087 remains as a 

an Intel development system to run it on. major stumbling block. The current stick¬ 
er price of $450+ is a powerful deterrent 
Problems and Future Directions to experimenters and software developers. 

Over the past year, many rumors On the positive side, a combination of 

have been circulating concerning the progress on the production learning curve 

8087’s propensity to overheat and its and second-source manufacturers is ex- 

finicky timing characteristics. Until re- pected to bring the cost per chip down to 


48 

362 


Dr. Dobb’s Journal, Number 70, August 1982 





the neighborhood of $150 by the end of 
1983. Whether even this price will be low 
enough for the 8087 to win widespread 
use is uncertain. The AMD 9511 and 
95 12 have been selling in this range for 
several years, but their use in microcom¬ 
puter applications remains uncommon. 

Another barrier to acceptance of the 
8087 is certainly going to be lack of soft¬ 
ware development tools. Past history is 
again discouraging: the AMD 9511 and 
9512 have not received any significant at¬ 
tention from high-level language vendors 
(with the exception of one Pascal com¬ 
piler, one Fortran subroutine library, and 
one Forth system that I know of). 
However, the predictable machine en¬ 
vironment of the IBM PC, plus the 
incentive of the estimated one million 
machines that will be in the field within 
five years, may result in the appearance 
of many language packages that would 
have never been written otherwise. 


Further Reading 

Intel iAPX 86,88 User's Manual and Nu¬ 
meric Supplement, August 1981. $10.00 
from Intel Literature Department, 3065 
Bowers Avenue, Santa Clara, California 
95051. 

Getting Started with the Numeric Data 
Processor, Intel Application Note AP-113. 
Free when you order the User’s Manual. 

Making Mainframe Mathematics Accessi¬ 
ble to Microcomputers. Intel Article Re¬ 
print AR-135. Free when you order the 
User’s Manual. »*j 


50 



8086/8088 






CPU 



8087 Numeric Data Processor 


15 0 


79 

78 64 

63 0 


AX 



R 1 





BX 



R2 





CX 



R3 





DX 



R4 





SI 

source index 


R5 





DI 

destination index 


R6 





BP 

base pointer 


R7 





SP 

stack pointer 


R8 








\ 

\ 

t 

CS 

code segment 



sign exponent significand 


DS 

data segment 



15 

0 


ES 

extra segment 



NDP status 


SS 

stack segment 



NDP control 


IP 

instruction pointer 






PSW 

status 









Figure 1. 


The 8086/8088 

CPU and 8087 numeric co-processor 




register sets. 




Figure 2. 

The 8087 numeric data formats. S is sign bit. Exponent 
bias: 127 for short real, 1023 for long real, 16383 for 
temporary real. Short and long real significands are left 
normalized with an implicit integer bit. 


Dr. Dobb’s Journal, Number 70, August 1982 

363 




ur in It REST 


Apple-Verter, Model APX-800, is a 
high-fidelity color video modulator that 
connects Apple II and other computer 
systems to a home TV rather than a cost¬ 
ly color video monitor. Made by ATV re¬ 
search, and selling for $29.75, the Apple- 
Verter operates above normal computer 
harmonics, in the high VHF band (tun¬ 
able channels 7-10), giving it, they claim, 
“unusually high stability as compared to 
some UHF units.” The unit mounts inside 
the computer and plugs into the existing 
power/video plug, and attaches to the 
TV with a ten-foot direct-connect an¬ 
tenna cable (Reader Service No. 335). 

Microconnection for the Osborne 1 is 
a Bell 103-compatible modem that oper¬ 
ates in both originate and answer mode at 
300 baud. A cassette recorder can be 
plugged in to transcribe on-line commu¬ 
nications for later playback. Microcon¬ 
nection weighs less than a pound, and 
measures 7.7 by 5.5 by 1.7 inches. Made 
by Microperipheral Coporation, it costs 
$159 (Reader Service No. 345). 

Inmac’s direct-connect modem con¬ 
nects any phone line by an RS-232 
interface to a mini- or microcomputer 
or peripheral device. It is Bell 103- 
compatible, operates at 300 baud, and 
automatically switches between answer 
and originate modes. The modem uses 
full duplex, asynchronous data com¬ 
munication modes, and features self - 
diagnostics, a carrier-detect LED, and 
push-button switching between voice and 
data communications. It weighs less than 
two pounds, fits under the telephone, and 
costs “under $200” (Reader Service No. 
355). 

The Mimic speech processor is a low- 
cost audio signal processing unit, offering 
speech processing for several popular 
microcomputers. Packages range from 
bare boards for user assembly to com¬ 
plete systems. Mimtalk, a BASIC pro¬ 
gram, outputs speech from prepared vo¬ 
cabularies of phonemes, words, or 
phrases, and Mimhear is an automatic 
speech recognition program. Prices range 
from under $20 for the board to $199 
for a complete system. Mimtalk costs 
$34.95 (Reader Service No. 365). 

The Apple Speech Computer Board 
(SCB-APPLE), from Multitech Electron¬ 
ics, is based on Texas Instruments’ TMS 
5200 speech-synthesis device. It plugs 
directly into any spare slot of an Apple 
II, and has an on-board audio amplifier 
providing a driver for the 8-ohm Apple 
II speaker. A socket is provided for TI’s 


TMS 6100 voice synthesis memory for 
expansion. The system includes a mini¬ 
floppy with speech data and a 400-word 
English vocabulary, and three Chinese 
lessons. Other languages can be devel¬ 
oped, including male and female voice 
inflections. ($129. Reader Service No. 
375). 

Microsoft’s RAMCard for the IBM 
Personal Computer offers up to 25 6K 
additional memory, and disk emulation 
capability, using some or all of the mem¬ 
ory as RAMDrive for disk I/O. RAMCard 
can be used in any slot of the PC, and up 
to three can be installed simultaneously, 
for up to 480K additional memory. Con¬ 
figurations are 64, 128, 192, and 256K, 
ranging in price from $495 to $1095, and 
a 64K upgrade kit for the lower configu¬ 
rations, $200 (Reader Service No. 385). 

Do you want a good-looking printer? 
How about inexpensive? The Alphacom 
40 won the “Excellence of Design” award 
from Industrial Design magazine. This 
40-column, high-speed (four lines per 
second), thermal printer with graphics 
capability costs $295. The Alphacom 42, 
a two-lines-per-second version, costs 
$195 (Reader Service No. 395). 

Sixteen-Bit Systems 

Sixteen-bit systems are coming down 
in price. Computex’s Z8001-based X- 
8000, in a typical configuration (each 
system can be tailored to the user’s re¬ 
quirements), has 256K dynamic RAM, 
expandable to 16 megabytes, dual eight- 
inch floppy drives, a 15-slot mother¬ 
board, eight serial I/O ports, the ZMOS 
operating system, supporting up to 32 
users simultaneously (each running a dif¬ 
ferent program), paged-segmented mem¬ 
ory circuitry, sockets for two 2716 
EPROMs, eight vectored interrupt levels 
plus a non-maskable interrupt input, 
two programmable timers, a socket for 
optional 9511 arithmetic processor, a cast 
aluminum case and power supply and 
costs $7053. The 68000-based X-6000, 
is fully compatible with Intel’s Multibus, 
handles up to 64K of onboard PROM 
and 128K or onboard RAM, and has 
seven prioritized vectored interrupts and 
one non-maskable interrupt, two RS-232 
serial ports with 40 bits of parallel I/O, 
and a triple 16-bit timer/counter for 
generating interrupts or monitoring exter¬ 
nal events. In a similar configuration to 
the X-8000 just described, and with an 
RMX-86-like operating system, an X- 
6000 system costs $7099. Languages in¬ 


clude BASIC, SuperSoft C, COBOL, 
FORTRAN, Pascal, and Ada (Reader 
Service No. 415). 

Digital Microsystems offers its Sys¬ 
tem 5000 in either eight- (Z80-A CPU) 
or 16-bit (8086 CPU) configuration. 
Both have an 8086 video controller. The 
high-resolution, 15-inch, nonflicker (P- 
39 phosphor) display can be mounted 
either vertically, to function as a full- 
page word processor displaying 80 char¬ 
acters by 66 lines, or horizontally, with 
80 columns by 26 lines of high-resolution 
characters, or as a spread-sheet-type 
screen of 132 columns by 50 lines. The 
System 5000 has a detachable keyboard 
and 30 programmable function keys. 
Screen intensity can be changed and in¬ 
verse video invoked under program con¬ 
trol or by control key sequences. The 
stand-alone workstation can be incorpo¬ 
rated into the HiNet local area network, 
a CP/M-based packet-switched network, 
with availability of all CP/M software, 
and supporting up to 32 users. The sys¬ 
tem is fully bit-mapped, with a horizon¬ 
tal scan rate of 19,200 hertz, an inter¬ 
laced display of 64 hertz, and a display 
format of 800 by 560 pixels. High- 
resolution characters are 8 by 17 dots, in 
a cell size of 10 by 21. The eight-bit 
System 5000 starts at $3295, and the 
16-bit System 5000 at $4195 (Reader 
Service No. 425). 

Operator provides automatic dialing 
and answering for computer owners who 
now manually dial and answer phone calls 
using acoustic couplers or manual, direct- 
connect modems. Features include baud 
rates from 110 to 300, half- and full- 
duplex modes, fast dial (20 pulses per 
second), carrier monitor, command inter¬ 
preter, and command-prompting output. 
Operator can be in one of two modes, 
terminal (passing characters directly from 
computer to modem unchanged) and com¬ 
mand (processing input). The unit comes 
with complete documentation, and costs 
$129 (Reader Service No. 445). 

Conect software from Vector Graph¬ 
ic provides asynchronous data communi¬ 
cations in any of four basic operating 
modes for all Vector single- and multi¬ 
user microcomputer systems. In send/ 
receive mode, data files can be transmit¬ 
ted between any two Vector systems, 
with automatic error detection, and re¬ 
transmission if necessary. The link mode 
transfers files or programs between com¬ 
puters, permitting remote diagnostics and 
implementation of bulletin boards on 


Dr. Dobb’s Journal, Number 70, August 1982 
364 



Vector systems. Handshaking protocols 
permit communication with minis and 
mainframes. The terminal mode emulates 
the LSI ADM3A or Hazeltine 1500 dumb 
terminal, turning the microcomputer into 
an interactive communications terminal 
that can send or receive data at up to 
1200 baud. In the interactive mode, a 
Vector microcomputer can communicate, 
at 300 or 1200 baud, with minicomputers 
or mainframes without special software 
at the host end. In this mode, a Vector 
microcomputer can also communicate 
with other Vector systems or the LSI 
ADM3A or Hazeltine 1500. In the in¬ 
teractive mode, the Vector system can 
use a modem to access, public data bases, 
with automatic dialing and answering 
for some modems and a directory of tele¬ 
phone numbers that can be automatically 
dialed. Other options include selectable 
originate/answer mode, full- or half¬ 
duplex operation, auto-repeat dialing and 
answering, and voice communications in¬ 
terrupt. Conect software costs $150 
(Reader Service No. 455). 

One of the services you can access 
with some of this wonderful equipment is 
NewsNet, which electronically transmits 
over 100 newsletters from 30 publishing 
groups, including Communications Daily , 
Satellite Week, and Telephone News, and 
publications in the energy, government, 
environment, educational, and business 
fields. There is no initiation fee. Cost is 
$24 per hour, with a $15 per month 
minimum (Reader Service No. 465). 

A software vendor directory lists 
software compatible with Hayes prod¬ 
ucts, including the Micromodem II, 
Micromodem 100, Hayes Stack Smart- 
modem, and Hayes Stack Chronograph. 
Software for most popular computers in¬ 
cludes programs that automatically an¬ 
swer phone calls and determine trans¬ 
mission speed, automatically switch be¬ 
tween host and terminal modes, redial 
if necessary, make outgoing calls at pre¬ 
set times, automatically log on, send and 
receive ASCII files, terminate the call, re¬ 
quest passwords, communicate between 
any two systems, access PRESTEL, turn 

a microcomputer into an asynchronous 
terminal emulator, copy incoming data 
into a 30K buffer for later transfer to 
disk, play chess, Go-Moku, or backgam¬ 
mon between remote partners, emulate 
smart terminals, do word processing, ac¬ 
cess Western Union’s services, permit 
users to access their own computers by 
phone, time a call and maintain a log for 


comparison with phone bills, transfer 
high-resolution pictures between comput¬ 
ers, and much more (Reader Service No. 
475). 

The JobStream CP/M 2.2 Operating 
System, from Aton International, for 
TRS-80 Model II and Model 16 increases 
the average speed of diskette operations 
up to five times, by buffering several disk 
tracks in RAM, so that “floppies are no 
longer the major limiting factor in system 
efficiency.” User programs can be as large 
as 62K, and, if the program accesses other 
32K memory boards for data and pro¬ 
gram code storage, over 200K. JobStream 
permits Model II users to upgrade to 
CP/M. Level I operates in the standard 
64K memory and costs $179. Level II 
requires 96K or more and costs $235. An 
upgrade kit, from Level I to II, including 
diskette and documentation, is $81. They 
also offer BASIC Surrogate, and VisiCalc 
Surrogate, for $99 apiece, or $75 each if 
ordered with JobStream, to allow Radio 
Shack BASIC and VisiCalc to operate 
in the JobStream CP/M environment. 
OmniWriter, $150 (or $125 with Job- 
Stream) is a video text editor that can 
edit two files simultaneously, scroll for¬ 
ward or backward by line or page, and 
perform other word processing functions. 
Safety features include interrupting any 
automatic process with one keystroke, 
and holding deleted copy in a temporary 
buffer for recall of inadvertently deleted 
text (Reader Service No. 495). 

The Floppy Disk Librarian from Lit¬ 
tle Bit helps the IBM Personal Computer 
keep track of floppy disks and files. A 
consolidated catalog displays name, date, 
size, and comments for all disks and all 
files, and what is where. Reading the 
directory tracks of a disk automatically 
updates the Librarian. Information can be 
retrieved by disk or file name, and wild- 
carding can be used. Output can be sent 
to display, printer, or a disk file. $39.95 
includes a manual and on-line help files 
(Reader Service No. 505). 

Data Perfect is a spreadsheet program 
for Atari or Apple that allows users to 
design their own screen masks. It has 
utilities, a report generator, and a mailing 
label generator. It supports multiple 
searches and sorts. Complete formula and 
mathematical operations can be per¬ 
formed on and between fields. The pro¬ 
gram supports one or two disk drives, can 
be used with any parallel printer, and re¬ 
quires 32K. LJK Enterprises offers the 


program for $99.95 (Reader Service No. 
308). 

ZenCalc is a spreadsheet caclulator 
for Heath/Zenith computers. It does fi¬ 
nancial and numerical model building, 
forecasting, and problem solving, has a 
two-dimensional “What if?” calculator 
program, includes formulas, labels, and 
variable column width, and outputs to 
printer or disk file. Tailored to the H89/ 
Z89 computer or the H19/Z19 terminal, 
cursor control and function keys “pro¬ 
vide a true full-screen editor ‘feel’ in 
worksheet manipulations.” The manual 
includes a step-by-step tutorial. ZenCalc 
comes with examples, including templates 
that automatically compute the full IRS 
1040 form and itemized deduction 
Schedule A. The Software Toolworks 
offers the program for $99.95 — plus $2 
p and h (Reader Service No. 318). 

The Software Toolworks also offers 
several programs for the Osborne 1, 
which are priced from $19.95 to $49.95. 
Spell is a 50,000-word proofreader for 
WordStar files. MyChess is a champion¬ 
ship level chess program with a full 
graphics board display. “Original” Ad¬ 
venture is available. They have the Eliza 
“therapist,” and arcade-style video games. 
Programming languages include C, RAT- 
FOR, LISP, and macroassemblers for Z80 
and 8080. They offer a free software 
catalog (Reader Service No. 328). 

In a description of her Handy Home 
Hints program, Nancy Modney says, “Get 
your wife involved with your microcom¬ 
puter.” That sounds to me like reverse 
sexism: what if the lady of the house is 
also the programmer? Anyway, the cas¬ 
sette tape “teaches you 50 unique ways 
to save time and money in areas such as 
energy costs, cooking, cleaning, child 
care, and home maintenance.” System re¬ 
quirements are TRS-80 Model 1 or II 
level II with at least 16K. Nancy offers 
free details for an SASE. Nancy Modney, 
4144 N. Via Villas, Tucson, AZ 85719. 

macroP adds macro commands to a 
document formatter or language proces¬ 
sor. For assembly language, it converts 
simple assemblers into macro assemblers. 
For high-level languages, it permits in¬ 
definitely long variable names, compile¬ 
time expression evaluation, conditional 
compilation, and time and data stamping 
of source programs. For text formatting, 
macroP adds conditional nested inclusion 
of text files and automatic numbering of 
section headings. The package includes a 
manual and files of macros tailored to 


52 


Dr. Dobb’s Journal, Number 70, August 1982 

365 




BASIC, PL/I, Pascal, and to Text writer. 
Available for IBM PC-DOS, CP/M, and 
CP/M-86 from Pluto Research, macroP 
costs $135 (Reader Service No. 338). 

Languages 

basic’ (basic prime) is a “supremely 
logical programming environment” from 
Delta Micro Systems. It is a structured 
extension of BASIC. Blocks of code are 
indicated by a unique indentation con¬ 
vention, eliminating the need for extrane¬ 
ous statements (such as BEGIN and END) 
and statement numbers. Comments are 
right justified, block indentation reveals 
the flow of control, procedures are sepa¬ 
rated by white space, and an extensive 
cross reference is provided. A basic’ pro¬ 
gram is written with editor' (supplied), 
a full-function text file editor optimized 
for programming, and is then translated 
into a normal BASIC program, producing 
a listing that cross-references the basic' 
program to its BASIC translation, basic' 


Dr. Dobb’s Journal, Number 70, August 1982 
366 


comes with documentation and program 
diskette in a binder, is available for 
Apple, IBM PC, and TRS-80, with other 
systems under development, and costs 
$129 (Reader Service No. 348). 

I’ve saved the best bargain for last. 
You can get JRT Pascal, a Pascal compiler 
for CP/M, from JRT Systems for $29.95. 
They’ll let you copy the system and the 
manual and give them to friends, as long 
as you don’t resell them. The package in¬ 
cludes a one-pass compiler that does not 
need linking or macroassembly, Exec, the 
run-time environment, with dynamic 
storage, floating-point arithmetic, and 
random disk support, an assembler, an 
optional linker that merges Pascal or as¬ 
sembly external procedures and functions 
into one module, Customiz, to customize 
the Pascal system to individual hardware 
and software environments, and Activan, 
an activity analyzer that interacts with a 
program to monitor execution frequency 
by line number, printing a histogram to 


shown activity in each program area. Ex¬ 
ternal procedures are also included that 
compute statistical function on an input 
array, format and print X-Y graphs, scat¬ 
ter graphs, and histograms, and print 
large block letters for attention-getting 
report headers. Fourteen digits of preci¬ 
sion binary-coded-decimal (BCD) format 
eliminates conversion errors, with a 
floating-point exponent range from -64 
to +63. Strings can have up to 64K char¬ 
acters, not just the 255 limit of other ver¬ 
sions of Pascal. Records contain logically 
related data items, with key indexing. 
Random access to disk files is by both 
relative record number and 
relative byte address. Arrays can be 
formed from basic data types and from 
user-defined types. Indexes are user- 
defined and can be integers or characters. 
Arrays can be up to eight dimensions. 
You need an eight-inch, single-density 
disk drive and a 52K CP/M system (Read¬ 
er Service No. 358). 


53 


Clinic (Continued from page 9) 

V. Pitteway, “Algorithm for Drawing 
Ellipses or Hyperbolae With a Digital 
Plotter,” Computer Journal, 10(3):282- 
289, November 1967). Pitteway’s method 
will draw any ellipse using only addition 
and subtraction. 

The problem of finding the ellipse 
was solved by a number of DDJ readers. 
Almost all the solutions were equivalent. 
Most readers used one of two methods to 
find the solution. Either they treated the 
ellipsoid as a deformed unit sphere, or 
they took the formula for the rotated 
ellipsoid directly and used partial deriva¬ 
tives to find lines tangent to its surface. 
One of the first solutions to arrive was 
provided by Bruce Kendall. He showed 
that any ellipsoid could be represented 
by a product of matrices: 

cos (0)1 
sin(0) 



X t R' yz R t zx R t xy PR xy R zx R yz X= \ 

where R is the rotation of the axis matrix 
for each axis, and a superscript t denotes 
a matrix transpose. 

Kendall showed that a solution re¬ 
sulted from taking the partial derivative 
with respect to z and setting the result 
equal to zero. If the ellipsoid resulting 
from the rotation of axes is expressed as 



such that 


[* y z][Q] 



the projection of the ellipsoid (its shadow 
as cast by an infinitely distant light 
source) is 



0 

\ 

b 2 

0 




While this is a very compact way of 
expressing the solution, it might not be 



obvious what it means. If your ellipsoid 
is centered at the origin and, prior to ro¬ 
tation, extends from -a to a along the x- 
axis, from -b to b along the y-axis, and 
from -c to c along the z-axis, it is said to 
be in “standard form.” If you are on the 
z-axis, far from the origin, it will appear 
as an ellipse in standard form from -a to 
a, -b to b. If you now rotate the ellipsoid 
about the x-, y-, and z-axes by r, s, and 
t degrees respectively, the ellipsoid will 
still appear as an ellipse, though possibly 
not in standard form, at the origin. This 
solution gives the formula describing that 
ellipse. The solution, completely expand¬ 
ed and ready to use, is shown in the box 
below. 

To use the formula, substitute the 
known values for a, b, and c (the size of 
your ellipsoid), and plug in the sin and 
cosin of the angles by which it is rotated 
around the three axes. The result will be 
a constant times X 2 plus a constant times 
Y 2 plus a constant times XY, equated to 
1. Drawing this formula on the screen will 
show how the ellipsoid would appear to 
an observer who is far away on the z-axis. 

By this point you may have realized 
that this method is not going to give us 
the order of magnitude increase in speed 
that was the original goal. To find the 
projection of the ellipsoid will require 
roughly fifty multiplications, three times 
the number needed to find the projec¬ 
tion of a point. In addition, clipping along 
the edge of the screen is no longer a 
trivial task; it now requires solving quad¬ 
ratic equations. The hidden line problem 
is made both easier and harder, in that 
there are about a third as many lines 
cluttering up the screen but finding out 
what is hidden looks much more difficult. 

At this point it looks as if this meth¬ 
od, with a lot of work, could be as fast 
as the point-transformation method, 
but with a more complicated program. 
Given the number of points that a single 
ellipsoid might represent, the computa¬ 
tion time required would be roughly 
equal. 

I would like to thank every one who 
took the time to offer their assistance in 
solving the problem. I have not given 
up my search, and am now looking for 
another way that might be used to gain 
the order of magnitude increase in speed 
that I need. 

— Don Taylor 

Don also sent a program in BASIC 
that used the formula to draw outlines of 


58 


Dr. Dobb’s Journal, Number 70, August 1982 

367 






a rotated ellipsoid. We converted his code 
to run on our Atari. The program appears 
in Listing 3, below. When the program 
asks for the X, Y, and Z coefficients, give 
it input of 20, 40, 60. That defines an 
ellipsoid with about the proportions of a 
pumpkin seed. The largest dimension 
must be less than 80 or the Atari will try 
to plot a point off the screen and stop 
with an error. 

After it has drawn an outline, the 
program asks for “deltas for R, S, T.” 
Give it rotational angles in degrees. To see 
the ellipsoid along each of its main axes, 
give it 90, 0, 0 the first time, -90, 90, 0 
the second time, and 0, -90, 90 the third 
time. Then rotate it to both 45-degree 
positions for a rather nice, 1950s-style, 
atomic symbol. 




Listing 3. 

10 DIM SI(360):REM SINE TABLE 

470 M—CO(T)*CO(R)+SI (T)tSI(S> *SI (R) 

20 DIM CO(360):REM COSINE TABLE 

480 N—CO(T) *SI <R)*SI (T) »SI IS) *CO(R) 

30 DIM S2 (360): REM SIN**2 TABLE 

490 P-S2 (S) / (A*A) +C2 (S) *S2 (R) / (B*B) +C2 <S> *C2 (R) /C*C 

40 DIM C2(360):REM COS**2 TABLE 

500 Q—CO(T)*SC(S)/(A*A)+CO(S)*SI(R)*K/(B*B)+C0(S)*CO(R)*L/(C*C> 

50 DIM SC(360):REM SIN*C0S TABLE 

510 Rl—(SI(T)*SC(S)/(A*A))+CO <S)*SI(R)*M/(B*B)+C0(S)*C0(R)*N/<C*C) 

70 ANGLE-5:REM DISPLAY STEP 

520 REM 

80 REM ASK FOR SIZE OF ELLIPSOID 

530 REM NOW CALCULATE THE VALUES OF 

90 7 "X,Y,Z COEFFICIENTS";:INPUT A,B,C 

540 REM THE NEEDED COEFFICIENTS. 

100 REM 

550 REM XX,YY,XY GIVE THE COEFF.S 

110 REM BUILD A TABLE OF TRIG VALUES 

560 REM THAT ARE MULTIPLIED BY X*«2, 

120 REM IN' DEGREES, TO SPEED PROGRAM 

570 REM Y**2, AND XY FOR THE ELLIPSE. 

130 REM 

580 REM 

140 ? "BUILDING TABLES — BE PATIENT" 

590 XX=C2(T)*C2(S)/(A*A)+K*K/(B*B)+L*L/(CtC)-Q*Q/P 

160 FOR J«0 TO 360 STEP ANGLE 

600 YY=S2(T)*C2(S)/(A*A)+M*M/<B*B> +N*N/(C*C)-Rl*R1/P 

170 K«J*3.1415926/180 

610 XY=2*(SC(T)*C2(S)/(A*A)+M * K /(B*B)+L*N/<C*C)-Q*R1/P) 

180 SI(J)-SIN(K) 

630 REM 

190 CO(J)-COS(K) 

640 REM PLOT THE RESULTING ELLIPSE 

200 S2(J)=SI(J)*SI(J) 

650 REM THIS IS A SLOW BUT SIMPLE 

210 C2(J)=C0(J)*CO(J) 

660 REM METHOD — USE PITTEWAY’S 

220 SC(J)=SI(J)*C0(J) 

670 REM ALGORITHM FOR ANY SPEED. * 

230 NEXT J 

680 REM 

240 REM 

690 RD=SQR(1/(XX*C2(0> +YY*S2(0)+XY*SC(O))) 

250 REM SET INITIAL VALUES FOR 

700 PLOT RD*C0(0)+150,RD*SI(0)+80 

260 REM ROTATION ABOUT X,Y,Z AXES 

710 FOR D-ANGLE TO 360 STEP ANGLE 

270 REM 

720 RD=SQR(I/(XX*C2(D)-*-YY*S2(D)+XY*SC(D))> 

280 R-0:REM X-ROTATION 

730 DRAWTO RD*CO(D)+150,RD*SI(D)+80 

290 S=0:REM Y-ROTAT ION 

740 NEXT D 

300 T=0:REM Z-ROTATION 

750 REM 

310 REM 

760 REM GET DELTAS FOR THE ANGLES, 

320 REM ATARI: CLEAR SCREEN, SET MODE 

770 REM AND DRAW THE ROTATED FIGURE. 

330 REM OF 320h BY 160v, WHITE DOTS 

780 REM 

340 REM ON BLACK. LOOP TO 360 TO 

790 ? "DELTAS FOR R,S,T"; 

350 REM CLEAR SCREEN EACH TIME. 

800 INPUT DR,DS,DT 

355 REM 

810 DR=ANGLE*INT(DR/ANGLE):R=R+DR 

360 GRAPHICS 8 

820 DS=ANGLE*INT(DS/ANGLE):S-S+DS 

370 SETCOLOR 2,0,0:COLOR 1 

830 DT=ANGLE*INT(DT/ANGLE):T-T+DT 

375 REM 

900 REM KEEP ANGLES IN RANGE 

380 REM THE FOLLOWING TEMPS HAVE NO 

910 IF R>360 THEN R=R-360 

390 REM MEANING IN THEMSELVES j THEY 

920 IF R<0 THEN R-R+360 

400 REM ARE ONLY USED FOR CALCULATION 

930 IF S>360 THEN 8*8-360 

410 REM OF THE ELLIPSE COEFFICIENTS. 

940 IF S<0 THEN S-S+360 

420 REM *** TOP OF MAIN LOOP *** 

950 IF T>360 THEN T-T-360 

450 K«-(SI<T>*C0(R!)+C0(T)*SI(S)*SI(R) 

960 IF T<0 THEN T=T+360 

460 L=SI(T)*SI(R)+C0(T> *SI(Si*C0<R> 

970 GOTO 370 


Dr. Dobb’s Journal, Number 70, August 1982 
368 





For Users of Small Computer Systems 



$2.50 

($3.00 in Canada) 


OBB’S lOURNAL 


Number 71 September 1982 



Special 
Forth Issue! 


Floating-Point 
Package... 

... Relocating 
Linking 
Loader... 


... H-19 
Screen 
Editor.. 


Z8000 


Forth 


and even more! 























Dr. Dobbs Journal 

For Users of Small Computer Systems y 

September 1982 Volume 7, Issue 9 


Editor - Marlin Ouverson 
Assistant Editor - Fritzi Lareau 
Contributing Editors - 

Dave Caulkins, Dave Cortesi, 

Ray Duncan, Kim Harris, 

Gene Head, Michael Wiesenberg 
Marketing Director - Craig Harper 
Marketing Assistant - Beatrice Blatteis 
Advertising Director - Laird Foshay 
Circulation Manager - Gloria Romanoff 
Circulation Assistants - 

Theresa O’Rourke, Terri Marty 
Art Director - Clifford West 
Production Manager - Barbara Ruzgerian 
Production Assistant - Jane A. McKean 
Typesetter - Renny Wiggins 
Cover Illustration - Margaret Tsai 


© 1982 by People’s Computer Company 
unless otherwise noted on specific articles. 
All rights reserved. 


Subscription Rates: $25 per year within the 
United States; $40 for first class to Canada 
and Mexico; $58 for airmail to other coun¬ 
tries. Payment must be in U. S. Dollars, 
drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be 
typed, double-spaced on white paper. List¬ 
ings should be produced by the computer, 
using a fresh , dark ribbon on continuous 
white paper. Please avoid printing on perfo¬ 
rations. Payment is in contributor’s copies. 
Requests to review galleys must accompany 
the manuscript when it is first submitted. 
Authors may receive a copy of the complete 
writer’s guidelines by sending a self- 
addressed, stamped envelope. 

Donating Subscribers Contributing Sub¬ 
scriber: $ 50/year ($25 tax deductible). Re¬ 
taining Subscriber: $75/year ($50 tax de¬ 
ductible). Sustaining Subscriber: $i00/year 
($75 tax deductible). Lifetime Subscriber: 
$1000 ($800 tax deductible). Corporate 
Subscriber: $ 500/year ($400 tax deductible, 
receives five one -year subscriptions). 

Contributing Subscribers: Thomas H. 
Grohne, G. V. Elkins, Robert M. Connors, 
William J. McEown, Robert C. Luckey, 
Robert N. Stabler, DeWitt S. Brown, John 
B. Palmer, Burks A. Smith, Transdata Cor¬ 
poration, Mark Ketter, John W. Campbell, 
Friden Mailing Equipment, Howard E. 
Decker, Jim Wilson, Frank Lawyer, Chris 
Pettus, Paul Lutus, Ben Goldfarb, Rodney 
Black, Steven Weiss, Pat Phelan, John 
Brodie, James Fleming, Unison World, 
Thomas Davis, Jan Steinman, Ronald E. 
Johnson, G. Hunter, Kenneth Drexler, Real 
Paquin, Ed Malin, John Saylor, Jr. Sustain¬ 
ing Subscribers: Pete Roberts, Steven Fisher 
Enterprizes. Lifetime Subscriber: Michael S. 
Zick. 

Foreign Distributors UK & Europe: 
Hofacker-Verlag, Tegernseer Strass 18, D- 
8150 Holzkirchen, West Germany. Asia & 
Australia: ASCII Publishing Co., Ltd, 
Aoyama Building 5F, 5-16-1 Minami 

Aoyama, Minato-ku, Tokyo 107, Japan. 


CONTENTS 


Articles 

16 Forth Floating-Point Package 

by A. J. Monroe 

For those who prize portability, these Forth routines will prove valuable. But the 
author also shows readers who already have an assembly language floating-point 
package how to link that work to Forth, in what may be record time! 

30 Forth Programming Style 

by N. Solntseff 

The morning after: can you still read the Forth code you wrote the evening be¬ 
fore? Do you want to get your work published, but editors keep asking you what 
your program is supposed to do ? Here is one person’s remedy for such woes ... 

34 Relocating, Linking Loader in Forth 

by Joe Barnhart 

This is a fine utility for Forth programmers who are tired of waiting more than 
three minutes to compile an editor, for example, that can be loaded — with this 
software — in five seconds. It will allow you to link pre-compiled modules and 
load them at new addresses. 

42 H-19 Screen Editor in Forth 

by Albert S. Woodhull 

The various hardware editing features of the H-19 make it a popular terminal for 
programmers. This screen editor, written in Forth, takes advantage of them in an 
easy-to-use way. “What I hope I have created,” the author told us, “is an editor 
that can be used without any additional reference manuals or cards.” 

48 Z8000 Forth 

by Lou Odette 

This article and software will serve those looking for an example of the threaded, 
interpretive language, as well as those who wish to implement Forth on a Z8000 
system. The latter will only have to customize two subroutines handling terminal 
I/O, but familiarity with Forth is assumed. 


Departments 

6 Letters 

7 Editorial 

8 Dr. Dobb's Clinic 

QUITIF and Loglan 

64 16-Bit Software Toolbox 

8086 ASCBIN and BINASC 

66 Book Reviews 

Starting Forth, Discover Forth and 
Programming Language Translation 


69 Software Review 

The Working Forth Learning System 

72 Of Interest 



Dr Dobb’s Journal (USPS 307690) is published twelve times per year by People’s Computer 
Company, Box E, 1263 El Camino Real, Menlo Park, CA 94025. Second class postage paid at 
Menlo Park, California 94025 and additional entry points. Address correction requested. 
Postmaster: send form 3579 to Box E, Menlo Park, California 94025 • 415/323-3111 


4 


Di. Dobb’s Journal, Number 71, September 1982 







LETTERS 


Small System Interest 

Dear People, 

I really appreciate the articles you 
choose to publish, mostly oriented 
toward the small-system user. Mostly be¬ 
cause of the content and character of 
these articles, I have gotten into “C,” 
using Walt Bilofsky’s C80 compiler. His 
business is The Software Toolworks, and 
he used to advertise in DDJ, but it seems 
that he is concentrating his advertising 
more in the Heath-only oriented publica¬ 
tions now. His expansion of Ron Cain’s 
Small-C for the Heath H8 and H89 
systems handles everything but floating¬ 
point. I have modified the H9 terminal on 
my H8 system for program control of 
cursor up/down/left/right/home, erase- 
page and erase-to-end-of-line, and re¬ 
wired some keyboard switches for single¬ 
key input of some of the most-used 
control characters, deciding to go that 
route rather than buy what I think is an 
over-priced HI9, especially when I had 
the H9 already. 

I was thinking about writing a screen- 
oriented editor in the assembler language, 
and had actually started some of the 
ground-work and coding. When the Jan¬ 
uary ’82 issue of DDJ came, I dropped 
the whole business and typed in the edi¬ 
tor in C by Ed Ream. I have full-screen 
editing now, after adapting the editor to 
the C80 compiler, HDOS operating sys¬ 
tem, and special H9. It’s a bit slow, since 
the H9 is connected through a 4800-bps 
serial port, and has no direct-cursor ad¬ 
dressing; but the features of the editor, 
both the original features from Ed Ream 
and some improvements by yours truly, 
make my system time much more pro¬ 
ductive than when all I had was a line- 
and character-oriented editor. 

Please keep that small-system-user 
interest. 

Dwain Henderson 

172 Country Club Dr. 

Florida, NY 10921 


Grist for the Mills 

Dear Dr. Dobb's: 

Byte has the ads, but you’ve got the 
content! 

I’m writing in regard to Jonathan 
Mill’s articles on the Z-88 and XASM-86, 
particularly Part II. I am writing to ask 
you to try to persuade Mr. Mills to share 
with us his “Daughter Board” for adding 
an 8087 to the minimum-mode 8088, 


either as an article or add-on board. 
Thanks, and keep up the original work. 
Best wishes, 

Alan D. Howard 
Rt. 3, Box 680 
Crozet, VA 22932 


Multi-68000 Homebrew 

Dear sir: 

I just finished reading A1 Kossow’s 
article on the multi-68000 homebrew 
system that he and his friends are devel¬ 
oping ( DDJ #68). Please publish his 
68000 assembler in Fortran. Any other 
68000 articles will also be well-received 
by the hardware freaks like me. 

I’m also developing a DEC /li/T- 11 
16-bit-cpu-based system with a 64 Kbyte 
dynamic RAM system. Any interest for 
this from readers? 

Sincerely, 

Christopher J. Shaker 

1124 High St. 

Hillsboro, WI 54634 


Dear Editor, 

Here’s one note to publish the 68000 
cross-assembler mentioned in DDJ #68. 

The 68000 is very unusable without 
an assembler; of course, a cross-assembler 
written in Pascal would be better, but 
beggars can’t be choosers. 

Thanks, 

Eric C. Rehnke 
1067 Jadestone Lane 
Corona, CA 91720 


Dear Dr. Dobb ' s: 

I am submitting one clamor for A1 
Kossow’s 68000 Fortran cross-assembler. 
No sense in reinventing the wheel. The 
more public domain software, the better. 
Thanks, 

Milt Zlatic 
9605 Carrimae Ct. 

Crestwood, MO 63126 


Editor’s note: The above are a small sam¬ 
ple of the many letters we received asking 
for the entire listing prepared by A l 
Kossow. You asked for it. . . next month 
it appears. 



High-Resolution Vector Display 


Dear Sirs: 

As a 68000 homebrewer myself, I 
was very interested in A1 Kossow’s article 
in the June 1982 issue. I must take ex¬ 
ception, however, with his statement that 
“there was no practicable way to ever 
build a high-resolution vector display 
capable of displaying color.” 

I am currently building such a dis¬ 
play, and whilst not a trivial exercise, it 
is certainly practicable. Currently avail¬ 
able high-resolution color display tubes 
are capable of about 1000 x 1300 pixel 
resolution on a 20-inch diagonal screen, 
so 10-bit D-A converters were chosen, 
giving 1024 x 1024 dots. 

The key to getting good vector den¬ 
sity without flicker is to use a constant 
writing speed, (i.e., the time to write a 
vector is proportional to its length). A 
very low inductance deflection yoke 
keeps the writing speed up and allows a 
full-screen width to be written in 10 
microseconds. Allowing 20 ms as the 
limit of writing a whole screen before the 
onset of flicker, this allows a total length 
of vectors of over 700 m, surely enough 
for the most detailed graphics? 

Keeping the writing speed constant 
also keeps the brightness constant and al¬ 
lows beam modulation to be easily ap¬ 
plied; in fact, the 6 bits left over in each 
coordinate word are used to encode 
brightness information. A future addition 
will be a curve generator to generate arcs 
of circles from three pairs of coordinates. 
This will save enormous amounts of mem¬ 
ory in drawing smooth curves and, fur¬ 
thermore, no point of the curve except 
the three given points needs to he on the 
1024 x 1024 grid. 

Dynamic convergence is, of course, 
necessary, but given a quality deflection 
yoke, no terms higher than the second 
order should be necessary, and two 
analog multiplies and a handful of op- 
amps does the trick. 

Having built many raster-scan dis¬ 
plays, I would say that they are not as 
straightforward as they may seem — cer¬ 
tainly a far cry from the domestic televi¬ 
sion which they superficially resemble. 
Vector refresh is a useful alternative, even 
for high-resolution color, and is really 
not that much more difficult to build. 
And the latter, of course, is really eco¬ 
nomical on memory. My system, allow- 


6 


Dr. Dobb’s Journal, Number 71, September 1982 

37T 


ing a maximum of 8191 vectors, has 32 
Kbytes of refresh memory. A 1024 x 
1024 raster-scan display, 3 colors, 2 bits 
per color, would need 768 Kbytes. Even 
if memory were \<t a gigabyte, there still 
remains the problem of addressing and 
manipulating all this memory. Pending 
getting around to writing some software 
for the 68000, I have been testing the 
vector generator on a small CDP1802 sys¬ 
tem with success. I hope this letter may 
persuade some readers to give vector re¬ 
fresh a try. 

Yours sincerely, 

Greg Trice 

1131 Sandhurst Circle #111 
Scarborough, ON M1V 1V5 
Canada 


68xx Blurb 

Dear Editor, 

A users’ group is forming for those 
interested in the 6809 processor, the OS- 
9 operating system, and UNIX-like sys¬ 
tems on 68xx machines. All are welcome 
to participate with their ideas and other 
contributions. A Computer Bulletin 
Board System has been temporarily estab¬ 
lished to foster the group’s organization 
and to share information. Anyone with 
an ASCII terminal and 300 baud modem 
may use this public information utility 
by following these instructions: 

Dial 312-397-8308 (This is in a 
Chicago suburb.) 

When a connection is established, al¬ 
ternately press the carriage-return key 


and the line-feed keys (ctrl-m and ctrl-j) 
until you receive the system message: 
PLEASE LOG IN 

Respond with: HELLO-G500„3. No 
spaces or other changes may be made. 
System instructions will follow. 

Please logoff formally, not by sim¬ 
ply hanging up. You will have an oppor¬ 
tunity to leave suggestions or other in¬ 
formation to the system operators. 

Further information may be ob¬ 
tained from the bulletin board or from 
me. Thank you very much on behalf of 
all 6809 and OS-9 users. 

Sincerely, 

George C. Domer 
2163 Vermont St. 

Rolling Meadows, IL 60008 


Editorial 


Mirror, Mirror ... 


When we told a friend, John Gilmore, that DDJ was 
planning to publish a Forth issue, he said that the language 
had always seemed a little familiar. Then, John said, he 
realized that it looks like LISP, but written backwards 
and without the parentheses. If you are new to Forth and 
have trouble reading the listings, try looking at them in a 
mirror.. .. 


Everyone has his own programming style. Most lan¬ 
guages are easily bent into, or out of, shape and can still get 
the job done. The ready example is, of course, BASIC, with 
its sly GOTOs ready to slip between any two otherwise 
sequential statements. The slightest afterthought or inspira¬ 
tion on the programmer’s part means another GOTO, trail¬ 
ing its spaghetti-like path of logic before and after. 

A data base manager we know recently spent until 
four o’clock in the morning fixing a payroll routine that 
chose to fail after several years of faithful service. The un¬ 
reachable author of the code had left behind him a trail 
of employers as indecipherable as his program, the only 
consolation for which was that he problably wouldn’t have 
been able to read the program, either. After a night of trac¬ 
ing and patching, the paychecks ricocheted off the printer 
and the manager stumbled into bed. 

Most of us, of course, pride ourselves on the legibility 
and cleverness of our programs. We may stop short of tap¬ 
ing our favorite work to the hall mirror, but there is a cer¬ 
tain amount of pride in a job well done. Until someone else 
tries to read the listing. Even then, we tend to believe that 
the other person simply doesn’t possess the acumen to 


readily understand what our code does, and that its ele¬ 
gance baffles them. If we must make concessions, they are 
usually in the form of comment lines, which should be used 
with clean code, not as a substitute for it. 

Forth has been called a cryptic language; others say it 
is more hieroglyphic. The difference of opinion may result 
from personal preference, or from studying programs writ¬ 
ten in different styles. (Given the chance, would you really 
use long, distinct variable names? Or would you revert to 
encrypted forms requiring a look-up table to comprehend?) 
Any language can be made to seem opaque, intentionally or 
otherwise. Most languages, including Forth, can also be 
made to display order, logic and consistency to all but the 
most untrained of eyes. Perhaps by comparing the listings 
in this issue, you will weigh the importance of style and 
approach, as well as the results. 


Some people think Forth has outlived its practical use¬ 
fulness. It should serve, they say, as a learning tool for ex¬ 
tensible interpreter/compiler models of the future. But 
there are several thousand voices, and more daily, testifying 
to Forth’s flexibility and power. One thing is certain: Forth 
is a language in transition. Not all members of the standards 
committee left the 1979 meeting in agreement. As a result, 
subsequent meetings have occurred in order to bring about 
a consensus. We can look forward to something which, 
depending on its release date, will probably be called 
Forth-83. 

— Marlin Ouverson 


Dr. Dobb’s Journal, Number 71, September 1982 
372 


7 



DR. DOBB’S CLINIC 


by D.E. Cortesi 


Conditional Submit 

In the June Clinic we asked if some¬ 
one wouldn’t like to write CP/M com¬ 
mands to abort a submitted job under dif¬ 
ferent circumstances - if a submit oper¬ 
and was omitted, or if it was an ambigu¬ 
ous file reference, etc. Don Wright of San 
Antonio, TX, responded that he would, 
and he did. He called his program IF, 
but when we typed it in we renamed it 
QUITIF since that seemed to express its 
function more clearly. 

The QUITIF program (Listing 1, 
page 14) takes two parameters. The first 
is a keyword, one of AMBIG, EXISTS, 
MISSING, or NULL (actually, it looks 
only at the first letter of the keyword). 
The second parameter would usually be, 
in whole or in part, a SUBMIT parameter. 
That parameter is tested in one of four 
ways depending on the keyword; then 
QUITIF either kills the submitted job or 
lets it continue. 

Here are some examples. In a sub¬ 
mitted file, the line 

QUITIF AMBIG $1 

will cause the submit file to be aborted if 
the first parameter of the submit was an 
ambiguous file reference. The line 

QUITIF EXISTS $2 

will abort the job if the second parameter 
of the submit named a file that existed. 
(If that parameter were an ambiguous ref¬ 
erence, the job would be aborted if there 
were any file that matched the parame¬ 
ter.) The command 

QUITIF MISSING $3 

is the inverse; it will abort the job if there 
is no file that matches the given refer¬ 
ence. Finally, the NULL keyword tests 
the second parameter itself, not the file 
it refers to. If the second parameter is 
completely absent, the job is ended. 

Note that you have quite a bit of 
freedom in forming the second para¬ 
meter. For example, 

QUITIF MISSING B:$1.ASM 

might be appropriate in a submit file for 
doing assemblies. 

Prophecy Fulfilled 

We quote with great pleasure this 
passage from the version 1.1 manual for 
IBM PC BASIC (page Ml): 

“When BASIC wants to branch to a 
particular line number, it. .. has to 
search through ... the program, starting 


at the beginning, to find the line it’s 
looking for. 

“In some other BASICS this search 
must be performed each time the branch 
occurs .... In IBM Personal Computer 
BASIC, the search is only performed 
once, and thereafter the branch is direct. 
So placing frequently-used subroutines at 
the beginning of the program will not 
make your program run faster .” [empha¬ 
sis added] 

Loglan Lives 

Little fixes and improvements to 
existing systems are all very well, but we 
at DDJ like to think of our readers as 
hardy pioneers, working ’way out on the 
frontier of personal computing. In that 
spirit, we’d like to tell you about some¬ 
thing that lies just over the next moun¬ 
tain range, and how to find the blazes 
that mark the trail toward it. 

In the summer of 1965, a friend gave 
me a knee-high stack of back issues of 
Scientific American, and I read them all. 
Most of the articles I read then faded 
from memory long ago, but one of them 
stuck to my imagination like a leech. It 
was entitled “Loglan,” appeared in the 
June, 1960, issue and was written by 
James Cooke Brown, then at the Univer¬ 
sity of Florida. 

Brown described the design and con¬ 
struction of the artificial language Loglan 
and the uses to which it could be put. 
The design of Loglan had a marvellous 
elegance. The language and its uses were 
endlessly fascinating to anyone who liked 
verbal play, logical puzzles, or grand 
philosophical inquiries. At the end of the 
1960 article, Brown promised that a 
Loglan primer and teaching materials 
would soon be published. In 1965, a care¬ 
ful search of the reference sources of the 
San Francisco Public Library turned up 
absolutely nothing further on J. C. Brown 
or on the Loglan project. The language 
had, it seemed, dropped into limbo. 

Twice during the following decade, 
the memory of Loglan returned to haunt 
me with sufficient force that I reread the 
old article and tried again to locate some 
sign of Loglan in print, but it remained 
invisible. Then, in 1976, a tiny ad ap¬ 
peared in an issue of SciAm. Something 
called The Loglan Institute had been 
founded, offered a primer and a diction¬ 
ary, and was publishing The Loglanist, 
a journal of Loglan studies! I responded 
at once, and have been an interested ob¬ 



server of the progress of the language ever 
since. 

Until recently I felt that Loglan 
would not interest readers of this column. 
It’s true that most of you (according to 
our reader surveys) have a strong interest 
in programming languages, and so are 
probably the kind of people who would 
find the construction of a new human 
language a fascinating project. Further¬ 
more, from its birth, Loglan has carried 
a strong promise of being useful as a com¬ 
puter interface language. However, Log¬ 
lan has been in a state of flux and expan¬ 
sion for some time; the papers in The 
Loglanist have been painfully detailed 
and hard to read; and there was no prac¬ 
tical relevance to personal computing. 
Now, at last, the situation is changing. 
In particular, a major piece of work has 
been completed that makes Loglan rele¬ 
vant, and Loglan experiments accessible, 
to many computer enthusiasts. 

The Genesis of Loglan 

Loglan was first conceived as an ex¬ 
perimental tool to test the “Sapir-Whorf 
Hypothesis.” Crudely put, the hypothesis 
proposes that our minds can only compre¬ 
hend those things that our language can 
express. The structure of language, in 
other words, is the structure of thought, 
so the language that we use determines 
(in some sense) the boundaries of what 
we can think. It’s a fairly broad hypo¬ 
thesis. Since it crosses so many dis¬ 
ciplines (psychology, sociology, linguis¬ 
tics, to name a few), and since any mea¬ 
sure of “what we can think” would be 
confused by an immense number of vari¬ 
ables other than language, it is generally 
assumed that the hypothesis can’t be 
tested in any scientific way. You can ar¬ 
gue the matter from any of a thousand 
points of departure (programmers would 
start with the common observation that a 
change of programming language — from 
BASIC to Forth, say — can release a 
whole new class of problem solutions to 
view), but an experimental test would 
seem to be impossible. 

Or would it? Brown reasoned that if 
one devised a new language, one that was 
in some way radically different from all 
other human languages, and taught that 
language to a large sample of people, then 
some measurable difference might show 
up between the way those subjects 
thought in their native language and in 
the new one. The new language would 
have to be a usable, speakable, human 


8 


Dr. Dobb’s Journal, Number 71, September 1982 

373 



language; it would have to be at least no 
harder to learn than a natural language; 
and yet it would have to be unlike any 
other language. Loglan was the result of 
his efforts. 

The Shape of Loglan 

The original Scientific American arti¬ 
cle is still a good summary of the struc¬ 
ture of Loglan. A number of details have 
changed since then, but if you want to 
learn more about Loglan, your best first 
step is to visit your local public library 
and look up that article. Here I will point 
out a few of the design features that re¬ 
late Loglan to computing. 

The most striking thing about Loglan 
is the orderliness and regularity of its de¬ 
sign. It is like the better computing lan¬ 
guages (e.g. LISP, Forth) in that it is com¬ 
posed of a very few parts which are con¬ 
nected using a very few general rules. 
Words are built up from an alphabet of 
just twenty-two letters: five vowels and 
seventeen consonants (you will count 
only sixteen in the 1960 article; h was 
added in 1980). Each letter represents 
just one sound; the English ambiguity of 
“there,” “they’re,” and “their” cannot 
occur. Punctuation is represented by 
spoken words; the ambiguity of “its” and 
“it’s” can’t happen. 

There are only three classes of words 
(“parts of speech”): predicates (which 
play the combined roles of English verbs, 
nouns, and adjectives), structure words 
(connectives, punctuation, and “varia¬ 
bles” which are, roughly, pronouns), and 
proper names. Each class is distinguished 
by its pattern of consonants and vowels; 
a simple algorithm would allow a com¬ 
puter to identify the class of any word. 
Finally, the language as a whole is unam¬ 
biguous. There can be no doubt as to the 
role of any word in an utterance. In Log¬ 
lan, time flies like an arrow precisely the 
way fruit flies like a banana; there isn’t 
any other way of saying it. It is possible 
to be ridiculous or metaphorical in Loglan, 
but it is not possible to be ambiguous. 

The Development of Loglan 

From 1955 when he began work, un¬ 
til 1976 when he set up The Loglan In¬ 
stitute, James Brown had Loglan pretty 
much to himself. I picture him working 
alone, much in the style of that other 
obsessive linguiphile, J. R. R. Tolkein, 
although without Tolkein’s freedom to 
invent a universe to contain his language. 


The Institute’s ads attracted a mem¬ 
bership that has remained constant a- 
round 200 subscribers since 1976. The 
addition of so many minds to the devel¬ 
opment of the language produced a great 
deal of activity. The syntax was extended 
and improved in a number of ways, and 
many new words were added. An impor¬ 
tant milepost was passed in 1977, when 
Brown and two other people were able to 
engage in several hours of free, spontane¬ 
ous discourse completely in Loglan. 
Twenty-two years after its invention, 
Loglan had been demonstrated to be a 
speakable, learnable, human tongue. 
There may be as many as a dozen fluent 
Loglan speakers in the world today, and 
perhaps fifty more who can read and 
write it with some ease (I am not one of 
them). 

A major concern of the Institute has 
been the achievement of unambiguity. 
The Loglan primer (Loglan 1, J. C. 
Brown, The Loglan Institute, 1975; now 
out of print) contained as an example the 
possible meanings of the phrase “pretty 
little girl’s school,” and showed how each 
would have to be rendered in a unique 
Loglan phrase. A long correspondence on 
the “PLGS problem” exposed some 
shortcomings in the syntax used to group 
modifiers, and led to some deep changes 
in the language. 

The problem remained, how could 
Loglan be proven to be unambiguous? 
Small bugs (time flies?) kept cropping up 
unexpectedly. This was important, for 
the language was coming to be seen more 
as a way of communicating with comput¬ 
ers and less as an experimental tool in lin¬ 
guistics, and proven ambiguity was sig¬ 
nificant to that use. The solution, and a 
proof, came with the presentation of the 
grammar of Loglan as a deterministic, 
finite rule-set that can be parsed with 
standard compiler techniques. And that 
brings us to the work at hand. 

The Machine Grammar of Loglan 

The latest output of the Loglan In¬ 
stitute is a machine grammar of Loglan; 
specifically, the input to the well-known 
YACC utility of UNIX that will cause 
YACC to generate a Loglan parser. The 
machine grammar, or MACGRAM, pack¬ 
age is available as a 173-page xeroxed 
paper. It contains four parts. The first is 
the YACC input: a set of BNF-like rules, 
each clearly annotated. The second part is 


a lengthy glossary of the terms used in 
the grammar rules and in the notes on 
them. The third part is a set of some 700 
Loglan sentences and fragments which are 
the test database for a parser, with their 
English translations. The final part is the 
source code, in C, for a pre-parser, a 
module that tokenizes Loglan text for 
presentation to the parser. 

MACGRAM is a very significant 
achievement (its contributors include 
Sheldon Linker, Jeff Prothero, Scott 
Layson, Doug Landauer, and Bob 
Mclvor, and of course Brown himself). 
Loglan has been shown to be a genuine 
language; MACGRAM is therefore the 
first-ever complete machine parser for 
a human tongue. Nothing like it has ever 
been done before. It may be more sig¬ 
nificant to readers of DDJ that some of 
the most recent work has been performed 
on a Heath H89, to which Mclvor has 
managed to transport aversion of YACC! 

Loglan, the Future and You 

What is the future of Loglan in com¬ 
puting, or in any other endeavor? No one 
can say, yet. Your intern is prepared to 
bet that it has a future, however. It is a 
unique language for computing. Comput¬ 
er output of Loglan speech is trivial; the 
ASCII characters of Loglan text map 
directly onto Votrax phoneme codes 
without any complicated text-to-speech 
algorithm. The simple phoneme structure, 
and the one-for-one mapping of sounds 
to letters, means that Loglan has to be by 
far the simplest language for machine 
recognition, whether of speech sounds 
through a microphone or of letters 
through an optical reader. 

A useful dictionary of “basic Log¬ 
lan” would be only a very modest disk 
file. Loglan syntax can be parsed easily 
and without ambiguity. A system that 
takes Loglan input, “understands” it, 
acts on it, and reports its output in Log¬ 
lan speech, all in real time, could conceiv¬ 
ably be built on no larger a hardware base 
than a typical CP/M-80 system! 

But not yet. Loglan is not quite 
ready to “go public” again. Brown and 
the members of the Institute are in the 
midst of a “Great Morphological Revi¬ 
sion,” in which a significant part of the 
Loglan vocabulary is to be rebuilt for 
better recognizability and easier learning. 
Also, there is little in the way of up-to- 
date tutorial material. The 1975 primer 
is out of print, and both it and the 1975 


Dr. Dobb’s Journal, Number 71, September 1982 
374 


9 


dictionary have been outdated by work 
since. There is a great deal of work 
to be done to make a presentable, fin¬ 
ished, Loglan learning package. 

If this account has intrigued you, 
start by reading the 1960 article. If the 
elegance of the language then catches 
your mind the way it caught mine, you 
will want to participate in, or at least 
keep current on, the development of the 
language. You can do that by joining the 
Loglan Institute. Your involvement can 
be at any of several levels. 

A subscription to The Loglanist costs 
$20 for approximately four issues (the 
journal is published occasionally, and the 
cost of each issue is charged to your cur¬ 
rent balance.) Send an extra $20 and re¬ 
quest copies of “the Primer section of 
the June 1978 distribution” (a draft of 
the first chapters of a new primer), of 
Volume Four Number Two (a summary 
of language changes 1975-1980), and of 
the MACGRAM paper. Or, for biennial 
dues of $100, you can be a regular mem¬ 
ber of the Institute, receive a regular 
newsletter, and have a voice in the affairs 
of the Institute. Then, if you are really 
hooked, you can inquire into spending 
your vacation at the Institute, working 
on the language. 

The address is The Loglan Institute, 
Inc., 2261 Soledad Rancho Road, San 
Diego, CA 92109. Welcome to Loglandia! 


(QUITIF Listing begins on page 14) 


12 


Dr. Dobb’s Journal, Number 71, September 1 982 

375 


n* C P 
03 03 P P 
M C 3 O 
•h O W.Q 

*4-1 <D fO 


0(flC>, 
O iQ 


O E 
03 P X 

m 3 

*H C W 

44 (\« P 
<D 3 P 
0 ) C P P 


0 W >i C 
0 iQ 


CO 


o 


03 * 

E CN 


03 O 


C 


CP rH 


C O 

•H 

X - 


u o 

</>- P 

■p o 

' c 

03 

- O 03 

E * 

O - > 

*4-1 

rH O 0) 

-P 44 

«• » iH 

W || 

moo 

P < 

•H » P 

•H 

- O P 

*4-< G 

* % *H 

P 

Q * 

'O 3 

W 03 W 

C -P 

H D -h 

•H 0 

OS CO 

*P P 

O 03 




<13 

U 

E-* »p 



X 

OS <N 

h </>• 0 



-P 

< CQ 

E t/> 

CN 

»-3 


u u co 

CQ </>- P 

03 

i-3 

03 

CO IP O 

D' in IP 

u 

M 

in 

- - Q 

CO - (DM 

IP < 

X 

3 

U Q 03 

* rH p X 


OS > M E-* 
NZOtl,U W 
b h 2 U b K 


X) 

X M Qj 

<Q-n2 

uuitb 


■p Xl 

J H N D( 

*P < cu z s 

•H U U K P) 


L ,NHQ J N<<“S]a 

^zxezqcSze 
u2 ju2jo2^ 


XI 




Xj 

E-» 


Q 


w 

03 03 

£ 

O 

os 

Q Q 

CP 




0 ) <D 


rH rH 

CP 

E 





rH rH 


•H 

03 in 

(Q 





•H -H 



P — 03 P 

G 


p 



<D *P *P 

P 


0 'O c 



03 


(0 

e 

<D 


P P v 03 

CP 


P 


■p 

03 CP -P 

P 

• H—. 

in o <D e 

C 

p 

0 ) 


p 

C C C 

<D 

T 3 T 3 

5 p 3 

•H 

0 ) 

£ 


0 

•H <D 

E 

03 P 

S >i 03 CP 

£ 

p 

03 


43 

WPP 

03 

X 0 

0 03 0 ) P 

o 

p 

p 


03 

3 in in 

P 

0 s 

•H X P 03 

</> p 

03 

03 



0 *H *H 

03 

03 >, 

p 

03 

rH 

Cl, 

■ 

rH 

3 X X 

IP 

x 03 

G 

rH g 




03 

CP 0 ) 0 ) 


0 * 

•H rH - CN 

•H 

0 ) 

0 ) 

■ 

C 

•H | 1 

rH 


P 

P P 

f 0 

E 


0 

XI <D C M 

w os 

CQ P 01 P 

C in 

o 

03 

■ 

•H 

E P 0 

3 

•H 0 ) 

U 0 ) p 03 

3 P 

0 

G 


P 

03 CP C 

c 

p 

Cp 43 03 X 

•H 


03 

U. 

•H 



*3 P 

E E E 

|JIP 

G 

rH 


03 

C C C 

c 

P *H 

P 3 03 3 

c 

0 

•H 


c 

0 0 0 

0 

0 E 

M C P C 

•H P 0 ) 

•H 

*4-1 

W 

0 



i o 

3 03 

POM 

p 


«A 

u 

P P P 

P 

>1 

03 03 03 

P * 4-1 -H 

u 

0 

VI 


P P P 

p 

03 C 

*4-4 E E 

in 4-1 

G 

P 

ft 

p 

0 0 0 

0 

X <Q 

03 03 *0 03 

X 

3 


MB 

0 

XI XI XI X 


V C C C 

P 0 03 

44 

P 

0 

4-1 

03 03 03 

0 J 

03 P 

r* r\ 

0 ) 0 0 ) 

G p in 


c 


.Ets ~ 
*3 •£ 00 

(/) t 

J3 | 

u-t 1 

r © -a 

£j> £ 

D w * 

Og £ 


i i i i 
i i i i 


</> O rH 

CO Z </> 
O E-* H 
H CO CO X 
fflHW J 


X *H 0) -H 

4J *P 0) *P 


£ X X £ X X 
O in U Q U Q 
O O in in to i£> 
m o o o o o 
o o o o o o 


CQ 

, 

in 

3 

£ 

p 

0 

CO 

•H 

3 

• 


CP 

</> 

P 

•H 

to¬ 

3 

jQ 

co- 

0 

1 


xa 

03 


CP 

03 

c 

04 

•H 

M U 

in 

H U 

03 

0) 

p 

P 0 

03 

p 



>1 

G P 

XI 

03 *H 

• 

• X 

• 

• 03 



*- *' 


03 

"3 - 

O - - 
OS CO 

P 



rH CN 

0 

X 

W M 

E-* E 

Ck 



w w 

w Z 

p 

W C«4 

CO 3 




5 5 

OHM 


< CQ 

H XI 


* 


< z E Z 

M W W XI 

4-J 

2d w 

os h in 

G 



* W' M« U). J 

0 

W W O 

04 us 0 

0 


r- <p 

04 - - - 

<SWXSMZP 


- -S 

» vQ 

0 


O' H H 

E- X < K 

' <' W' E' Z 

0) 

c 

D 

B 

uno 

0) 

<e s 




c 



in 




0 








c 



0) 



03 

1 

M M M M 

E- E-* H H 

M M M M 

•H P 

44 G *H 

03 ^3 

D D P P P 

D 

D 3) D3 

CD 

1 

P D O p 

0) X c 

OOOOOO 

000 

OS 


0000 

X P 0 

w w WWW 

W 

WWW 

0 

PL4 

M 

H 

M 

0) 

CP 

P 0 

P C 
>, 0) 3 

M X 

M 

CN 

M 

os X 

HUM 


r> 

03 

CPC 

CO m W CN 

U 

W 04 </3 


0 

in 

O 0 (0 

< O CQ z CQ 

P 

Eh < < 

&u 


P 


G4 q u < u 
- H CQ fc4 Z Ch 

z - 

OS W K 
•- CU CO u • 

M 

- X 


CUNCUNCUNCUIS] 

U»-3UP)UP)UP) 




11 

376 


Dr. Dobb’s Journal, Number 71, September 1982 













Forth 

Floating-Point Package 


A floating-point arithmetic package for Forth can be 
mechanized in two quite different ways. There are ad¬ 
vantages to either approach. We shall briefly discuss 
both alternatives and then present one of them in detail. The 
first approach emphasizes the use of machine language rou¬ 
tines. The second uses only two simple machine language rou¬ 
tines, with the balance of the package written in high-level 
Forth. 

The first approach has several advantages. Variable preci¬ 
sion is easy to achieve; only three screens (approximately 600 
bytes) of Forth programming is required, thus it loads quickly; 
and it runs somewhat faster than the high-level Forth version. 

One disadvantage of this approach is that approximately 
2.4K bytes of object code must be developed by assembly- 
language routines. This proves to be a non-trivial task. On the 
other hand, if you have already written such a package for 
other purposes, you can link it to Forth with less than a single 
evening’s effort. 

I think the most significant disadvantage of this approach 
is its lack of portability. Nevertheless, I originally took this 
approach because I had on hand a package of floating-point 
routines written in the winter of 1975 and I could reassemble 
them to use otherwise wasted memory. (8K bytes below the 
NorthStar DOS.) 

The second approach has the distinct advantage that it is 
highly portable and requires only two simple CODE word rou¬ 
tines to make it work. 

Two disadvantages which accrue from this approach are 
that it generates somewhat more code (3200+ bytes, 19 Forth 
screens) and its precision is limited to 32 bits. The latter 
limitation is, of course, a direct result of the approach. Addi¬ 
tional precision can be achieved by a rewrite, but such work 
seems unwarranted by any application I have encountered to 
date. 

Another slight disadvantage is that the compiled package 
cannot be moved to arbitrary locations in memory, as is the 
case for the assembly language approach (but the source code 
may be compiled anywhere). 

Finally, there is a minor disadvantage in that it requires 
a considerable amount of time to load 19 screens of Forth. 
I have made this package a permanent part of one of my 
copies of Forth in order to avoid this annoyance. 

The Assembly Language Approach 

Figure One illustrates this approach pictorially. We pre¬ 
sume the existence of a set of machine-language floating-point 
subroutines which include a keyboard input routine (FINP) 
that accepts ASCII input characters, converting them to 
decimal binary and storing them in a known location. On exit 
from this routine, the decimal binary number is converted to 
a floating-point binary number, i.e., it is “normalized” by a 
call to FPNORM. Floating-point output is achieved by a call 
to FPOUT which essentially reverses the process of FPINP. 
Multiplication, addition, subtraction, and division are accom¬ 
plished by calls to FPMULT, FPADD, FPSUB, & FPDIV, re¬ 
spectively. To illustrate the approach, consider the implemen- 


by A.J. Monroe 


Alfred J. Monroe, 3769 Grandview Blvd., Los Angeles, CA 
90066. 


tation of a Forth floating-point multiplication command F*. 
It can be written as a CODE word linkage to a jump table pre¬ 
ceding the floating-point routines, e.g., 

CODE F* 0006 CALL NEXT JMP 

As I have mechanized it, the jump table resides at address 
HEX 0000 and up, i.e. 

0000 ( CODE FOR JMP EXEC1 ) ; FPINP 

0003 ( CODE FOR JMP EXEC2 ) ; FPOUT 

0006 ( CODE FOR JMP EXEC3 ) ; FPMULT 

where EXEC1, EXEC2, EXEC3, . . . first call a routine to save 
the Forth instruction pointer, then a routine to POP the re¬ 
quired number of floating-point numbers to working loca¬ 
tions, then call the appropriate machine-language routine, and 
finally jump to a routine that restores the Forth instruction 
pointer, pushes the results onto the stack and returns to the 
Forth calling address which then executes a NEXT JMP. 

Typical 8080 assembly language routines which accom¬ 
plish these tasks are as follows: 


EXEC3: 


EXEC: 


XFR2: 


SETS: 


IP: 

RETRDOR: 


CRLL EXEC 
CRLL XFR2 
CRLL FPMULT 
JMP SETS 
POP D 
POP H 

SHLD RETRDOR 

MOU L,C 

MOU H,B 

SHLD IP 

XCHG 

PCHL 

POP D 

POP H 

MOU R,L 

STR EXPR 

POP H 

SHLD LSUR+2 
POP H 
SHLD LSUR 
POP H 
MOU R,L 
STR EXPP 
POP H 

SHLD LSUP+2 
POP H 
SHLD LSUP 
XCHG 
PCHL 
LHLD IP 
PUSH H 
POP B 
LHLD LSUR 
PUSH H 
LHLD LSUR+2 
PUSH H 
LHLD EXPR 
XRR R 
MOU H,R 
PUSH H 
LHLD RETRDOR 
PCHL 
DS 2 
DS 2 


; SRUE THE FORTH IP & RET RDDR 
l POP 2 NO .'S TO WORK LOCRTION 
l DO ft FP MULT 

; RESTR IP, PUSH RESULT TO STK 

; LOCRL RET RDDR 

J FORTH RET RDDR ... 

; SRUE IT 
; SRUE IP 


RET TO LOCRL CRLL 
LOCRL CRLLING RDDR 
FP EXPONENT ... 

USES ONLV 1 BVTE 
STR IN FPRCC EXPONENT 

MSU OF FP NO. 

STRD IN MSU OF FPRCC 
LSU OF FP NO. ... 

STRD IN LSU OF FPRCC 
FP EXPONENT ... 

USES ONLV 1 BVTE ... 

STRD IN FPOP EXPONENT 
MSU OF FP NO. .. 

STRD IN MSU OF FPOP 
LSU OF FP NO. ... 

STRD IN LSU OF FPOP 
LOCRL CRLLING RET RDDR ... 
TO PROGRRM CNTR. 

RESTORE IP TO ... 

... THE BC REGISTER PRIR. 
FPRCC HRS RESULTS ... 

... UHICH _ 

... GET _ 

... PUSHED ... 

... ONTO THE ... 

... STRCK UITH HI _ 

... BVTE OF EXP SET .... 

... TO ZERO 

FORTH RETURN RDDR ... 

TO THE PROGRRM CNTR 


The jump table is not an essential requirement, but it is 
a convenient way to make the CODE word linkage insensitive 
to alterations of the assembly language package as occurs, for 
example, when the precision of the arithmetic is changed. 

Finally, the floating-point routines are autoloaded so that 
their existence is transparent to the user. In my case, this was 
accomplished by a CODE word DCOM which links to the 


16 


Dr. Dobb’s Journal, Number 71, September 1 982 

377 





disk read/write routine of the same name in NorthStar DOS. 
This linkage was made a permanent feature of the three 
Forth floating-point screens, so that it is not necessary to re¬ 
member to load the machine-language subroutines when these 
screens are loaded. 

And that’s all there is to it. 

As indicated earlier, it took only several hours to com¬ 
plete the linkage just as described. (I have, of course, com¬ 
pletely forgotten the original agony of writing and debugging 
that assembly language package in 1975.) 

Command Glossary 

Both versions of the floating-point package support the 
following commands. In semi-figForth style: 

F* FP#2 FP# 1 ... FP#2*FP#1 

Multiplies two top of stack FP#’s and leaves result 
on the stack. 

F+ FP#2 FP# 1 ... FP#2+FP#1 

Adds two top stack FP#’s and leaves result on the 
stack. 

F- FP#2 FP# 1 . . . FP#2-FP# 1 

Subtracts top of stack FP# from second FP# on 
the stack. Leaves result on the stack. 

F/ FP#2 FP# 1 . . . FP#2/FP# 1 

Divides the second FP# on the stack by the top of 
stack. Leaves result on the stack. 

FDUP FP# 1 ... FP#1 FP# 1 

Duplicates the top of stack FP# 

F2DUP FP#2 FP#1 ... FP#2 FP#1 FP#2 FP#1 
Duplicates the two top FP#’s. 

FSWAP FP#2 FP# 1 ... FP# 1 FP#2 

Swaps the two top of stack FP#’s. 

FDROP FP# 1 . . . 

Drop the top of stack FP#. 

F FP#1 N1 . . . 

Store FP#1 to address Nl. 

F@ Nl . . . FP#1 

Fetch FP#from address Nl. 

FVARIABLE 

FP#1 FVARIABLE FNAME (DEFINING) 

FNAME . . . Nl (EXECUTION) 

Defines a floating-point variable FNAME with an 

initial value FP#1. At execution time returns the ad¬ 
dress of FNAME to the top of stack. 

FCONSTANT 

FP#1 FCONSTANT FNAME (DEFINING) 

FNAME ... FP# 1 (EXECUTION) 

Defines a constant FNAME whose value is FP# 1. At 
execution time, invoking FNAME returns FP#1 to 
top of stack. 


FVAL FP# 1 FVAL FNAME (DEFINING) 

FNAME ... FP# 1 (EXECUTION) 

FP#1 TO FNAME . . . (EXECUTION) 

FNAME 1 TO FNAME2 . . . (EXECUTION) 

Defines a floating-point variable with initial value 
FP#1. At execution time, invoking the variable name 
returns its value, not its address to the stack. If the 
name is invoked following “TO” the FP# on the top 
of the stack will be stored in the variable. See Forth 
Dimensions, Vol. 1, #4, pg. 38, “The “TO” Solu¬ 
tion,” P. Bartholdi. 

D>F dl . . . FP#1 

Converts the double word integer on the top of the 
stack to floating point format, e.g. 

1.0 D>F produces 10 in floating format 

10. D>F produces 10 in floating format 

.10 D>F produces 10 in floating format 

0.10 D>F produces 10 in floating format 

Note that the placement of the decimal point is 
irrelevant; that leading zeroes are ignored; and that 
trailing zeroes are not ignored. A scaled FP#, say 
1.234, can be formed by: 

1234. D > F 1000. D > F F/ 

FINP . . . FP# 1 

Invoking FINP causes the subsequent keyboard input 
stream to be interpreted as a floating-point number. 
Error detection and recovery are provided. Cntrl-c 
will abort the command. Input may be either integer 
or “E” format. Decimal points are not allowed;they 
must be accounted for in the exponent, i.e. 

-1.234 is input as -1234E-3 
“+” signs are not permitted. Input is terminated by a 
space. FINP may be used within Forth words. A 
maximum of nine digits should be entered. (Also see 
D>F.) 

F. FP# 1 . . . 

This is the floating-point output routine. The output 
number format is: 

sign, digit, decimal point, 8 digits, space, 
exp, space, nl 

For example, 12.34 in FP format will be output as: 

+ 1.23400000 EXP 1 

All of the above commands may be executed in the im¬ 
mediate mode or included within other Forth words. 

All arithmetic operations are rounded to 32 bits of pre¬ 
cision in the case of the high-level Forth version. In the case of 
the machine language version, precision is set at assembly time 
in multiples of 8 bits. 

High-Level Forth Approach 

The second approach is illustrated pictorially in Figure 
Two. There are 17 screens of high-level Forth supported by 
two essential CODE words for a total of 19 screens. 

The format of a floating-point number on the stack is: 

dl nl ... 


18 

378 


Dr. Dobb’s Journal, Number 71, September 1982 


where nl is a signed word representing the exponent and dl 
is a signed double word representing the mantissa. 

The two essential CODE words (screens 90 and 91) are 
<-S and S->. Code word <-S performs a logical left shift on 
a double word. Code word S-> performs a logical right shift 
on a double word. Both expect the top word on the stack to 
be a logical carry. This word is popped and tested. If it is one, 
<-S shifts a one into the least significant bit of a double word 
on the stack; S-> shifts a one into the most significant bit of a 
double word on the stack. Both return a word to the top of 
the stack which indicates the state of the carry flag at the con¬ 
clusion of the shift operation. In effect, these words perform a 
multiplication and division of a positive double word by two. 
It will be noted that they are never used on negative double 
words in the routines, although this is a somewhat arbitrary 
restriction. In fig-Forth glossary format, for positive double 
words: 

<-S dl cyO ... dl *2 cyl 
S-> dl cyO ... dl /2 cyl 

Figure Three shows the binary format chosen to repre¬ 
sent a floating-point number. All numbers are represented 
in two’s complement form, i.e. the high-order bit is zero 
if the number is positive, and one if the number is negative. We 
assume a “binary point” between bit 31 and bit 30. This is 
equivalent to stating that all numbers are stored in the range 
plus one to minus one. That is, bit 30 has a binary weight of 
1/2, bit 29 has a binary weight of 1/4, and so on. 

The exponent will be held as a signed, most-significant 
word and it will represent the power of two by which the man¬ 
tissa is to be multiplied to obtain the correct number. 

To input a number in floating-point format, and to recti¬ 
fy floating-point numbers after an arithmetic operation, we 
require a normalization routine. In fact, we require two; 
DNORM in screen 92 and DDNORM in screen 96. DNORM 
will be used on double words that result from addition, sub¬ 
traction, and division. DDNORM will be used on quad-word 
mantissas which result from a floating-point multiplication. 

The normalization process works as follows. Consider a 
one in bit 0. In Forth, this is the positive integer “one.” If we 
shift this bit left until it is in bit 30, we will have made a total 
of 30 shifts and the value represented will have a binary weight 
of 1/2. Hence we need a binary exponent of one because 

2 * * 1 / 2=1 

Thus if we set our binary exponent initially to 31 and sub¬ 
tract one from it for every logical shift left, we will end up 
with the integer one properly represented in floating-point 
format. A little thought should convince the reader that all 
integers (up to our allowed maximum of nine) will be properly 
converted to floating point format by this procedure. 

The word D>F simply uses DNORM and an exponent of 
31 to achieve the floating-point representation of a double- 
word integer, e.g. unity in floating-point format can be accom¬ 
plished by keyboard input of 1. D>F. 

Screens 95, 96, and 97 develop the floating-point multi¬ 
plication routine. The key words required are <-S, S->, and 
D*. The latter word deserves some explanation. It performs a 
multiplication of two positive double words using the follow¬ 
ing artifice. We note that a positive double word dl is made up 
of two consecutive single words: 


dl . . . 
n2 nl ... 

dl can therefore be quite correctly represented as the sum of 
two double words: 

n2 0 0 nl D+ — > dl 

Letting LOl represent nl, and HI1 represent n2, the multipli¬ 
cation of one double word by another becomes 

(LOl + 2tl6*Hll) * (L02 + 2t 16*HI2) = 

LOl *L02 + HI1 *L02 *2116 + HI2 *L01 *2116 + 
HI1 * HI2 * 2132 

If L01*L02 is formed using the unsigned double-word 
multiply U*. then the least significant word of the double- 
word result will be the partial product representing the least 
significant word of a four-word product, and the most sig¬ 
nificant word of that double-word product, will be a carry 
which is to be added to the least significant word of the 
double-word partial product formed by HI1*L02 using U*. 
HI2*L01 formed by U* must be added to this partial result. 
The least significant word of this triple sum is then the next- 
to-least-significant word of the four-word product, and the 
most significant word is a carry to the least significant word of 
the double-word product of HI 1 *HI2. 

If all this sounds confusing, try it in decimal, 

1234. * 5678. = 34 *78 * 10 tO + 34 *56 * 1012 
+ 12*78*10t2 + 12*56*1014 

12*56*1014 = 6 72 00 00 = HI2*HI1 * 1014 

34*56 * lOt 2 = 19 04 00 = L02 *HI1 * 10t2 

12*78 * lot 2 = 9 36 00 = HI2 *L01 * lOt2 

34*78* lOt 0=_ 26 52 = L02*L01 * 1010 

07 00 66 52 

Note that products of any degree of precision can be 
formed by this cascading multiply and sum-the-carry process. 
Also note that D* works with positive numbers only. This is 
not a limitation, of course, since we will apply the word 
DMINUS to any negative mantissa before carrying out the cas¬ 
cading process just described, and then apply DMINUS once 
again if the signs of the two floating-point numbers are dif¬ 
ferent. 

Two additional minor points should be made concerning 
F*. Because the binary weight of bit 30 is 1/2, the unsigned 
product of 1*1 in floating-point format will yield 1/4. Thus 
we need to compensate the exponent of the product by 
adding unity to it. 

Further, to maintain accuracy we will do a round-off 
based on the third word of the normalized product. This 
round-off can lead to overflow into the sign bit. Accordingly, 
after the round-off addition is performed, the sign of the most 
significant word will be checked, and if it is negative, a right 
shift will be performed and one will be added to the exponent. 

There are at least three ways to implement division. The 
division routine given in screens 98 and 99 is based upon the 
age-old shift and trial subtract algorithm. This is not particu¬ 
larly elegant, but it is easy to mechanize. Initially, the quotient 
is made a double-word zero as the third number on the stack. 
The dividend is made positive (if it is negative), and the divisor 
is made negative (if it is positive). A trial subtraction of divisor 
from dividend is then made. If the result is negative, a zero is 


20 


Dr. Dobb’s Journal, Number 71, September 1982 

379 



right shifted into the quotient, and the divisor is added back 
into the dividend which is then shifted left. If the result of the 
trial subtraction is positive, a one is right shifted into the quo¬ 
tient and the dividend is shifted left. This process is repeated 
31 times. 

The CASE construct used in screens 98 and 99, and else¬ 
where, is shown in screens 144-145. This CASE construct is 
due to Dr. Eaker. It is described in detail in Forth Dimensions, 
Vol. 2, No. 3, pg. 37-40. The <OF and >OF and RNG-OF 
constructs are augmentations due to this writer. Discussion of 
these constructs is beyond the scope of this article. The reader 
is referred to Dr. Eaker’s excellent article for details. 

The floating-point keyboard input routine (FINP) is given 
in screens 100-103. It is designed to detect certain operator 
input errors; provide for error recovery; and permit command 
abort (Cntrl-c). It can be vastly simplified if the Forth con¬ 
structs WORD and NUMBER are utilized, but at the sacrifice 
the error recovery and operator-interactive features. The rou¬ 
tine first generates a double-word integer on the stack which is 
then converted to floating-point format using D>F. If an ex¬ 
ponent has been entered by the operator, the result of the 
D>F operation is then multiplied by either 10 (positive ex¬ 
ponent) or 0.1 (negative exponent) a number of times equal to 
the value of the exponent. That is to say, the exponent of the 
normalized floating-point number is saved as a power of two, 
not ten. 

Floating-point addition and subtraction are developed in 
screens 104 and 105 based solely upon the existing Forth 
word D+, DMINUS, and the new words S-> and DNORM. 
Note that adding two positive, normalized mantissas gives a 
guaranteed overflow into the sign bit which must be compen¬ 
sated for by S->. 

Screens 106 and 107 develop the floating-point output 
routine. The scheme used is essentially a reversal of the input 
routine. The mantissa is first made positive. The exponent, if 
positive, is forced negative or to zero by successive multiplica¬ 
tions by 0.1. If it is already negative, it is forced to zero or a 
positive value by successive multiplications by 10, and then it 
is forced negative. On exit from this procedure, the exponent 
will have been forced to lie in the range 0 to -4. It is then 
forced to zero (if necessary) by successive right shifts of the 
mantissa, i.e. divide by 2 a number of times equal to the 
residual exponent. The routine D* is then used to “spill” the 
mantissa one decimal digit at a time by successive multiplica¬ 
tions by 10. 

Finally, screens 109-117 present several useful functions, 
to wit: 

FINT Returns the integer portion of a floating-point number 
in floating-point format. 

FMOD Returns the remainder of a floating-point division in 
floating-point format. 

SINE Returns the sine of an angle expressed in degrees. Error 
is of the order 2*10t-9. 

COSINE Returns the cosine of an angle expressed in degrees. 
FSQR Returns the square root of a number. 

ARCSIN-DEG Returns the arcsin in degrees. Error is of the 
order 2*101—8. 


ARCSIN-RAD Returns the arcsin in radians. 

The sine and arcsin routines are based upon polynomial 
approximations given in section 4 of the Handbook of Mathe¬ 
matical Functions With Formulas, Graphs, and Mathematical 
Tables, U.S. Dept, of Commerce, National Bureau of Stan¬ 
dards, Applied Mathematics Series #55, June, 1964. Although 
I have not required logarithmic or exponential functions in my 
applications so far, they can be just as readily written in Forth 
using the polynomial approximations given in the above refer¬ 
ence. 


Conclusion 

The Forth package described here was written out of curi¬ 
osity. As stated at the outset, this writer has always preferred 
the assembly language approach to the implementation of 
floating-point routines. I must confess, however, that my 
assembly-language routines are considerably less readable than 
are the Forth routines, and since they consist of some 1100+ 
essentially undocumented statements, there is much to be said 
for writing the package in high-level Forth; especially when it 
comes to modifications - or just plain debugging. 

This writer is thoroughly impressed with Forth. It took 


FORTH 

COMMAND 

CODE 



WORD 

LINK TO JMP TBL 



JMP TBL 


. } 

FORTH 
3 SCREENS 
' 600 BYTES 

.i. 


MACHINE LNG. 


SUBROUTINES 

FPINP 

FPOUT 

FPMULT 

FPADD 

FPSUB 

FPDIV 

FPNORM 


STORE IP & 
RET ADDR 


CALL APPROP 
PRIATE RTN 


PUSH 

RESULTS 


ASSY 
LNG 
* 2.4K 


RET ADDR TO PC 


Figure 1. 

Assembly language approach to floating-point package. 


FORTH 

COMMAND 


HIGH 

LEVEL 


< S 
S> 
CODE WORD 
SUPPORT 


16 SCREENS 
2 SCREENS 


* 3200 BYTES 


Figure 2. 

High-level Forth approach to floating-point package. 


(Continued on page 71) 


Dr. Dobb’s Journal, Number 71, September 1982 
380 


21 






3 

ft ft ft ft 


! ft 

ft 

O 

a 

I *“< 

z 

§ 

Ld 

Ld 

U. 



S 

$ 

Ld 

'J 1 

— • 

® V 

Ld G 

+ qy 

01 

Ld id 

_J ft 
Ld G 

-« LL 

G 



01 - Q 

D ft 2 

ZOOIU 

, -• ft <r 

' Z 3 _J 01 

I 3 Ll 3 

in z 

| -• I r -4 


: ft u. u 
I I O H I ■ 

—I IL U- < 

: G LL G 

1 LL 3 S © i _ 

i X *■ Ld 

in ft u. u. cl 
ft uj o o 
id £ 3 
l JUJOO- 

■|i£| 

i i z B 5 


■» m t- z 

9 LU z 2? 8 

JU^lLlL 
u_ 3 to a 
2 u. a 

HI U. A 


1 .8 i 

H H I 


# v (jj •• *h I 

i v®-<fNK)Trir)'d^-oocr'®-.(NfO'tf- 


■w 

ft 

ft 


ft 

ft 


h“ 

^ ro 

>r i 

ft 

ft 

01 H* 


01 

Ld 6 

«> 

3 H- 


' Z O'I X 

U ft Ld Id 


1.0 H- 01 
■* 01 
•W B* 
« Id -• iL 
ft LL 

CN 

^ 'ft n ft 

x h X 1“ 

k- to k- un 
u*i to 


(n in 
r 1 ft O' 1 'ft 

ft h- ft K- 

1 h- 0*1 h- 01 

o*i in 

1 - Ld -• u. 

, Ll Ll 


:’S88855% i 'V 

' “ E 5 ^ i 

1 t •• 0 O O U. lL .. .... a, 

i< s 4fO^lOsDf s -00CT'®^^ro^ 

*■* *-« _t 


I ^ rt It o 


0 . 

0 ) H 

w £ 

LL £ 


5 e 

S 8 * 

■ 5 x 6 
2 u = 

M 

•O " « 

<U 03 £ 
JU j3 

^ *o 
"O ^ > 

C* . 

V «o 

«y ^ c 
-o s o 
0 ) ^ 

> Tt c 

« Tt 'O 

js Z c 
5 ^ Q 

.S W 9 "Z 

- g ■£ 

cSf 

3 « e 

8 | ■g 
2 a js 

~ "S-BS 

VO 2 ,o o, 

’ 1 E ■? >> 
a ? -a 
re o g § 
“ « 8 | 
O o 8 s. 

5/5 •• <u 22 

.S 52 C § 
oo o ~ *s 

piJ «5 <U e 

~ * « g 

X O «. e 

o a a g, 
C w >* g 


g £ • 5 ~ & 8 $ 

<-• So 01 ft 003 i 

S H x h O • ►— I Ln lD 
ft u. . In _i _i 
Jl A • 

JOO t • »“ 2 
Id ft « . z • Z 03 
X •>-» ^ I 

ft 01 3 . O Q. O 3 1 

£"= : £ S £ £5 

inSisSsSii' 

HOlEoJ'^Ol'^D 
| Z Id 3 u 3 O XI 

SEio^ceSalS^S 

fvvvvvvvvvv 


h- h- s 

GO id 


Ld id oi 

:m i 

A 

ft oi oi ON 
G d O "d 
' A ® J J 1 L 

ft H H 

5 - • + 3i m Z ~i ft 

! N T V V I : 01 

j K 

: ft ft Id H 01 t H 

1 

i 111- uh i- 

S 

i - » 3 U U U 
. Id Ld Id Id © 

in cn 

■ •■ ..S * ro 


;8 33 

’ft <r .r 


hi ft 
ui <r z 


U 

ft 

01 

V ft 


RfiL 

NEXT 

H 

2 

a: 

' | l3 

iliis 

2S 

K 

a 

ft 01 O 
ft CN 1 ft 

a: <r x ft ft 

x£ 




UI 3 QI 




A U ft 

in « x Sis 

o 0- 

' S I 3 


£ N ,V 

a in p 
UK I 

5^£§gx 


g ® -■ <N tn 


24 


Dr. Dobb’s Journal, Number 71, September 1982 

38T 




: 2 Z 9. 2 

J UJ UJ ul UJ 



Q 

H 

Z Cl rn 
hDI 
• Q 


O O 

2 a 
z z 

UJ UJ 

& 


• * 

U_ u. 


o © 

Ci —« 

u_ 


© 

o 

Ul Cl 


© 


z 

0-900 

O V A Q_ 

1 _ o UJ 
HOO(V^ 

^ in Sr 



ll 

o 

o 


0. 

o 

3 


I 

in 

© 

2 


© 9 A 

I 

9 i* i/I 

h— 

i in © 

h- i 

in 1 o 

is a 

g jq 


CL 

8 

_J 

Q. 

O 


*-< in 

Si 

1 H-. 

KUlZ 

in - 5 


§; 

-J 

uj! 


■ H 

' UL 


I 

in 


© 

u. 


+ 

o 


*i A 

I 

U. I 


I 

in ll 

H 

© a 

z 

- UJ 

+ 


UJ 

ll 
^ X 
UJ 

£- 


GS 

g 


* V 


u 


z 

13 

in 

r\ 05 

UJ CL 
ll X 
O UJ 

in uj 
zi 

13 m 

>n v 

uj - 
f'J z 



f- 

u. 

1 


1—1 

CM 

1 — 

X 

Ll 

in 


I 

9 

u. 

in 

x 

S 

Ll -• 


s 

O 


UJ 

g 1 

1 

Z f— 

h* 

in 

UJ ui 

in 

-J s\ 

1 

1 u. 

Z 

1 

05 Q 

hi LO 


j o 
o z 


I 


-J UJ 
I - 


8 
o 

9 Z 9 CL 

- w X 

CM *h m 

Q_ Q_ -• u_ 

X X X 9 
UJ UJ u. UJ 

CM 

9 9 UJ 9 Q. 

-5S''2E*S! ffi 

hmit,xx —«X- 

iN m m a; uj uj a. uj z 

_Uj x 

G-'^UILU.UJu. 

I K-. n Q O o 
u. in u_ u_ h- a w 


JlLlL 

IHH 
hCu 
K Z Z 
Hi uj UJ 
z 


i CM 


£ 

O A * 

1 * + 
UJ 

Cl I CM 


% V 

Z V o 

Cl O UJ 

9 Z 

X □ 1 


3 + 

Z C, 




9 •» 


9 


X 

UJ 


a -■ 

^ - „ _ <N <N 

Z O O h) 0. Q. 

,+ a , Ixx 

U- >—• a_ 0L I— LU LU 

DO J 

I 5 O X LU 
0, 13 U'l 

03-hi 

i ° - n ° 

t I- ° X X 3 <S> 

o -J + UJ UJ Q 1-1 

^ U. U. 21 

X 

* V .. 'V LU 

in ~ 


+ §? 2 ? 

9 O 




(N UJ 

Z CM «i ® r 
13 

HI UJ 

in ui 


9 5 


in 

-• cm ro v in 


s 

o 



in 


o 
u. ll 

►- UJ 

Ci r-j 

LL z 

x uj m 

3 H 


+ 

lL 

UJ 


O 

Ci 

UJ 


(0 

NO 

V. 

a> 
00 

0) 

C3 

a 

0 

c 

k 

0 

a 

cn 

s 


‘Sb 

0 

c 

-O 

-V-i 

■■■ 

X 

0 

O 

a 

-a 

■ 

a> 


■E t 

<q£ 
2 6> 

il£ 


c 

o 

o 

oo 

c 


C/3 

J 


_l 

ll 


M CM 

3 *-• '4 rj- 

Jill 


z 

o 

H-l 

in 

D 

* i 
o i 

i ! 

i 

o 
1 ! 
CL I 

H- i 
ID -I I 
<?. Ll . 


UJ © 

' O 

i -J 

. UJ 


J LU LU uj 
I J -J -J 

i all LU Uj 

: x x x 

I H H-l H-l 

\ 11 ii 

: 11 x 
o o © 


•43 * v 


cm r *j 
“■ ll 

ii LL -• 

1 X ■% 

O ^ ’T 

-J i in i 9 

a: 

“• 3 t + + rr 

m u o u i 

H f » 

x D D D D 

-•9999a; 

CM CM CM «h CM 9 

UUQOh^ 

- - W 9 9 .mi ^ 
9 

CM H C M iH 

H Q H H H 

X _J X I I QC 

* 

6 


1® ■ 

a 


-• ^ Ki 
X 1 1 

UJ UJ UJ 
-J -J _J 

11111 
| x x $ i 

© © © © 

> cm m m oo 0 s © -* cm m 


a uj -• 
i m i-3 
_j _r 
i uj 


1 o 

O X 


in 

at 

+ 

uJ 

N 

>—i 

XI 


O I o _ 
© H IL 
1 O -I 
uU U_ I f- 

O H-. LL 

1 O I 1 
II Ck L'j — 
1 © i i 

UJ -J I 

O 1 UJ l'I 

O Q Ci ! 


IL 1 1 ! O - 00 
*- t Q LU Cl + O 

i uJ oi 32 

^ 1 O ui -1 ll. 9 

■h. — * i. M / 

Ci 

1 ■ 


ig! 
d ^ ‘ 

_ CM I 


1 -• UJ j. 

5 1 j 7 " uj 

o in x i © 

. ‘ r -J 

n _j a u. z _j 

f u u IL ill HW n 

ill 13 

§003 i UJ 

3 

c ro tt 
Ci Ci 
i i 

13 S _ 

Z UJ 

8 & 


Sit _ 

o ci m 

'. ^ It fe 
> a. yj o o 

ij 6 o - 


'it 

H § 
'£ -I O 
ON 1 3 


„ 1 

9 O 

a ** 
g z 
X UJ UJ 

_j i>j 

i x 


z 

UJ 


1 ® -• 

o 

n 


<Npn^-inM)r.QOjN®-<iN 


* 

Ll 

l 

a 


JN U. 


- 9 O 

^ Z 1 

ll Ct 

1 ll O 

^ 1 A 

u ij u I 

LU UJ 1 ‘ 

i . . X © 

- l i n 3 

J j j m Ll 


ui 

Ll 

C. 

~T 

aj 

in 

D 


Z 

o 


in 

© 

x 


3 z z 2 2 U. I 

— IJ IJ 

do « m z + Ci v 
D1 D1 i O 2 
Ci E N 

- 1 - z • z 

z 0 H 90 

zii.ita s m 

ld — «: ui 

- ® £ ui 

ui v v in ■s 


. o ® 




® a , 
* 


UJ 


z 

13 

HH 

i © in 


♦ ■■ 

^©-.('•JiO'3-inviDfSwooiTvoo^cNro^ 

U ll ll 11 «~| iH 

in 


o 

o 


1 

o 


1 

X 1 
LU n 

C 
»n z 

o uj 


o 

1 

LU 

f'J 


UJ 

C. 

H-l 

D 

O 

ul = 

I 

1 

in o 

1 © 

05 JM 

oml g 

# ^ .. 

in 


UJ 

-• m 

.j © 
CM UJ I 
Z A 
13 © HH 

In 1 ^ 

hh q_ 

o 

*1 il 1 
LL 5 ® O 

CM 0 1 ^ 
n o m 


COO 

Ll C Lit UJ 

Ul Ul 

C.^35 


cm m ^ in 


26 


Dr. Dobb’s Journal, Number 71, September 1982 



0 Z 


Z LU 

LL 

UJ 

HH 

0 


z 

UJ 



I © 

LU 
0 -J 

H J H HJ 

K Z •-> 0 10 

2 ^ 5 S ^ S 

* '-' © 


-J 

s 


0 

l 

N H 
O -1 


0- 0 

§i 

Ul 
O CL 

*§ 

+ 8 

S£8 

i.O 

I -• 



+ 

b 



X 

UJ LL 



0 



r 


-• CL 

z 


— • 

CM ui 


h- 

0 


+ 

1 1 

— • 

0 10 


A 


Q_ 

+ 

--J 1 

+ 

1 

0 

U. X 


U. CL 


1 

0 

*-« UJ 

CL 

X 

X 


Ll 



I 

h* 

HH 

z 

LU 

+ 

CO 

LL 

o 

8 

* 

0 


0 

Z 

LU 


0. 

o 


CL 

o 

CL 

0 

CL 

O 


CL 

o 

o 

-J 0 

ofi 

UJ 



r 


— CNK)^-iDsONOo<y'®^ l .Nro^in 


o 

n 

H 

Z 

o 

0- 

Z 

9 

UJ 

£■ 


O CL 
CL 


CL 


I CL < 

v o c 

CL . 
CL G 


i z 
lo h> 


CL CL 
A 
CL 


~5S 

cn —• Ln : 


o 

Z G 


Z A ♦ 

5 Z Z -■ 
0. 


■» 

CL 

v 

UJ 


s 

LU 

l/l 

5 


z 

a 


CL 

O 

U_ 

CL 

LL 


Z 

O 

»-« 

Ul 

t—i 

0 

s 

z 


k i 
z i 
►—« ; 
u_ > 

I 

0 

X 

CL 


si: 

Ul 




l/i * 
: i cl 

I v OC CL 
l 3 X 
I 0 CO LU 

: CL A © 
I A | 

I/I 0 

. cl 

A © 

H 

J CL Z 
■ I— I— *-» 

cl a: i 

: hhh 

:££W 


a. u. 

JOm 
h-» CL 
H 0 * 

^o3 

ui cl i-O 

I 0 

V A 

CL CL 
© A 

A 

Z CL CL 

»-H A 

a 


V 

0 0 0 

u_ 

O 0 
CL CL 
3 G - 
0 

CL LU 
Z 0 




CL 

0 LU * 

5^ 

hJz 
z z ~ 

*-« UJ u_ 
I CL 
h* \ 
y L0 0 


.W 

■d 


Z 

%% 

LU 8 
Z Uu 

88 

EE 


•• s/ •• I 

-‘(NMVinvON0)O'®^NMvin 


L/l 

o 

o 

*3 « 

CL 

UJ CN 0 
Z H CE CE *r 

ui <r 

H J— H- K- 
CL C0 Z Z Z 
pzilt 
U- O H h- (— 
o w w in 
W U. Z Z 2 
H O O O 
W'NUUU 
Z IL U. U. 
(J N 

oo uj a: t 

I JLltL 
O ITJi 

,i!8*« 



o 

JC 


it 

0 I Cl 

Ul x 

-J UJ UJ 
LU 3 

O 

“ • J- h- 

z 

*-• 0 -« 
Z iu Cl 
0 Z X 
*-« uj 

L0 (V 

0 I 

L.0 

^ CN 
U- 3 CL 

0 UJ 

s r 

a.i- 

3 + 

Ur - X 
o Z UJ 


0 

3 

0 


.L 

ss 

Z 

H- 

LO 

0 

— o 


z 

L/l aJ 

3 ~ 


0 a 
— © 
<N ~ 

z 

0 

A 

Ul CL 

A 

CL 

U. 

- © 
V 0 
0 CL 
Cl 

3 CL ( 


0 

Z 





0 





0 

0 





+ 

_ 





0 

1 





L0 

Cl 





g 

0 

s 


0 



52 

0 


0 



0 

LO 


0 




V 

z 



Ll 



o 

z 


>—> 

z 

0 




0 



0 

Ul 

LO 

z 

A 

A 


z> 

H 

0 

0 

CL 

■f 

z 

U. 




tH 

1—1 

0 

H 

A 

A 


z 

0 


0 

CL 


0 

h- 

W 

Q- 

LL 

z 

Z 

U. 

0 


G 

X 

A 

►— « 

0 

£ 

CL 

LU 


I 


0 

0 


0 

Ul 

0 



CL 

t-H 



L0 

Ul 

o 


U- 

0 

1 -■ 

1 

z 

Ul 

o 

t-t 

V + 

s/ 

0 

$ 


w 

0 0 






Z 


CN 

1 


0 CL 3 

Qu 
2 


0 
* 

H JZ 


g s 


A 

I 

I 

< ON(0J'©HiNMtr 


0 

1 ^ 

I ill 


A | 

8 

0 

LU 

0 


. Z LL 
A O 
0 


O 

uj 3 LU 


0 » 
H CN 

-r 2 

3 0 


II 10 
UJ 0 
-• ul v 
Z 
u 

n 

_,3 

□ — 

10 


83 


OS 0 I 

as u. 

*i 

a . 


CL 

o 


LL 

o 


o 

o 


8 

8 


z 

o 


Cl 

z 

I—« 

Ll 

I 

H 


8-. 

A 

CL H 

lii 


z 

0. H O 
O ^ IL 


CL 

z 


0 Ul 

© H O 
2^® 


U. 

I 


h- 

Z 

z 


u 

u 

u. 


u_ 

0 

u. 


L0 


CL 

o 


CL 

0 

CL 

CL 

UJ 

z 

10 

Ul 


CL 

CJ 


CL 

o 

£L 

CL 

UJ 


^ CL Z 
O L0 
0 Ul 

UJiSh 

3 f— 
Z 0 Z 
^ z 

H 0 Z 

Q 0 CL 
(J UJ 
L“ 
0- Z 
05 0 UJ 
Z CL UJ 
►- 0 CL 
Ll Z _ 

I *T " 

0 Z 
^ CL 
0- UJ 
I 


© 0 ; 


8 

0 

~r 

LU 

Ll Ll Ll 
0 0 0 0 
0 0 0 
Z 0u Z Z 
LU 0 UJ UJ 

-8 

cN 

g- i 

Ll 0 I Ll 
U l i 
^ I 0 h“ 
0- 'T CL 
0- X 0 


§c8z 

"'z a 

= i 

• h- CL _ 

„ Z X H Q LU L , 
CL LU Ul ^ iv O Z 

O Z Z 0 -• I 
O 0 LU 0 &. 

*H 0 (J 


Z z d 

L = OS 

0 X Z U 

1 1 = 

h- 0 3 

z 

Z G 

8 

0 *“• 

0 


ll 1 


Ul 

I 

Ol 

s 


ro 


¥ 

a 


i v i 

,8z' 

H 

CL 0 
28 
i- ® 
8 


».. 

v CE (N 



3 

■S 

c 

<3 


rofl-invor^oo<7i®-.(\iK><«-in 


Dr. Dobb’s Journal, Number 71, September 1982 


27 

383 


on top of page 26/ I (Continued on next page) 





! |£ Floating-Point Program 

(fig-Forth) 

(Listing continued, text begins on page 16) 


M 

H 


II 

5 


© 

H 

Ul 


II 

t-i 

N 

9 


Vi in 

-ZhZKI 
z I Z I 2 $ 
r I- I HI I- 
t tQ lo i- cn 

J i w z m z 
101020 
300000 
Jli.Oli.OL. 
L L. L. 

Ll \ 111 \ lil 
L L. Ll 
^ CD Hi CO 
OOiDOiBO 
3 - 1 Q h 0 h 
U- *■* Li. -1 u. 
L LL LL 
li.li.lL 

. A II A li A 
N O A |2) A Q 
^ O 

r|oln^H 

;^2s§s 

- «-H (T> Si N (N 
:• O CO N '0 




* IT © 5 oo in <\4 1 

«-H -H • • ( 

! V lL U. H- I 


*B6 

•— o t- 

SdtsBi 


® -« (N M V IO ,y , 

o 


>rs.oo(r»cD*-«(Nro^-io 


QC ® -« CM 

ui 


i-Li D CL CL aJ aJ I 

LL' p o O & LL' 

OlLhh-OO I 

1— 01 01 h- I— lil * 

oi * oi oi cl i 

U- * * o . 

■ * U. Li. * * K I 

. LL LL U_ Ll 01 t 

D Vi’t 

■ ^ Ci <r cc in ^ * * 

■ cn Li. <r <f u_ i 

i a. a. 

0.1 jD^lln: 


e 

fo^-in>^ix_oo i ^ s oD»-.(N^ro^-in 


* (L © uj 

3 uj z a. 

. © 111 K- UJ 

« & a: u & 

a i4iu- 

J W LiJ H-t 

>1 5>5S§ 

JO 

1 £K •* r-i 

J ^ 03 UJ UJ 

J U. UJ Tf _l _J 
O L— UJ H. 
•v(t JL.n ft 

H w w £ t 

- UJ i2i lL Lj O O 

-j uj z z o o 

' *H Z O In UJ 

) a. Z U 01 

z »“« lL' (N 

- O 01 UJ hh 

1 o •* cl _j a: uj 

wwQ_| 

oi in a: a. c - 
cl cl z x 
: ' C ' o t 3 

i cc o 

► o. © in »-* uj 

> C- 0*1 

UJ U. CE 
ATCLO O 
UJ lj C 

•'fc 1 ^ S 

1 tA'TiO'XiL-(X)Cr>0 


H C I Z Z 
L/) H H d I 
Z 01 01 H H 
O Z Z 01 0*1 

uoozz 

LLOUOO 
Ul u. CJ U 
LL Ll Ll 

a U. u. 

Q A A ll ll 

Q A A 

. a a 


' 55 © in i 

I «H (K | 


01 

UJ 

UJ CL U. 
ll' 3 

a a. 

UJ Ll 3 
o a. i 
hi u. 

z _i •' 
►h m lL ‘ 

a S2C. 

IX LL LL 



T 

Z X 


X 



D * Z 


Ll 


«. 

Ll Ll »h 



© 

UJ 

LO 


iL 

© 

z 

© 9 LL 


3 

© © © 

t—« 

Ll U. 


5 

>.ij 0) 

01 

+ 


U. 

u. r - i *h © li 

o 

Oi U_ 

* 


u_ U. 0 s * 

u 

3 

LL 

* -• 

H Ul U. 


0. 9 


- U. u. 
Ul 


X CL' U. Ll 

t—« 

T Z Z H H 


Z G 

lL 

cl u: 


in>4)N03<T'®^(NKji<0‘ 


z g q. a. cl * oi 

W - Ul* X X 3 3 E U. 

Z Ul XilZMOLLIlE 
I-HU.U- «li.«Li.li.LiJCt» 

in a; oi ui i- uj ll 
ujLiiau.ou.Q.Q. i- 
I _l _l m 03 3DN o 
aii3jx#-i-.Qoa:^« 
OXIlLlLlLlLLLlLLLCCil 
v 1-1 M Ll ll 

IISzz 

^ H 3 D Ul Ql h 

-< -J IL IL X UJ 01 

Hll * 1- Li_ A 

© © 

t V ll 1 ,, I. .1 I 


u. u_ z 

t-4 Lll 

3 I 

Z U. Z Lil 

UJ M Z 

© 01 

+ CO Ll ul 

Ll 

Li. UJ + 

© i/1 Ll 


3 © 

M Ll Ll Ll 

list 


Q'QHNfO^in^NO) 

01 


1 

® 

* u. o 

g o -NM ’ 

in 


)^rvOoa\®«ruK)T»-ifi 


Dr. Dobb’s Journal, Number 71, September 1982 




00 

£ 


10 W O I 
h rr I v < 
WhPv 


) Ll © 8 

-• z 

' Q. a: 

vooi 

) uj £ 

' h- + O LU 

' a: - -j 

»-• Q_ *-* 

i a £ o a. 
j lj & K z 
• zoo 

. Z Q_ O 

! >-« n uj 
» o 01 in 
» •% _j ct: 

iz uj *-« 
i in uj a: 

O Ll Cl 
' O h C- 

A uj UJ 
UJ U_ h- 

■ LU U| OI 

UJ O I *-* 

. I Z ID O 

■ s Sk! 


*4 in o' © < 

«-i ju rr o 
O -* 01 


> so r- oo <r« © «-• <n 

H H H \,' 

O 


Dr. Dobb’s Journal, Number 71, September 1982 


ci 


Forth 

Programming Style 


T his note proposes a publication stan¬ 
dard for Forth programs in order to 
increase the comprehensibility of 
Forth program listings in magazines. I 
have also found that the technique de¬ 
scribed below is of great help to me in 
maintaining and testing Forth programs. 

Several articles and special issues of 
personal computer magazines have been 
devoted to Forth within the last eighteen 
months 1-3 . The version of Forth stan¬ 
dardized by the Forth Interest Group 
(fig) is now available for all popular 8-bit 
microcomputers. As an indication of the 
growing visibility of Forth on the person¬ 
al computer scene, I have counted at least 
four different versions of fig-Forth78 or 
fig-Forth79 being sold for Ohio Scientif¬ 
ic, Inc. (OSI) computers. There is even a 
version being distributed in ROM chips. 

The virtues of Forth can be sum¬ 
marized as follows: 

(1) It provides a very high degree of 
man/machine interaction, so that the pro¬ 
gram development cycle is considerably 
shortened by comparison with conven¬ 
tional languages. 

(2) The Forth System, as implement¬ 
ed on personal computers, is largely ma¬ 
chine independent and extremely com¬ 
pact. For example, memory used by a 
typical OSI implementation is 

Address Interpreter - 180 bytes 

Machine-code Forth 

primitives — 1670 bytes 

High-level Forth 

primitives — 4590 bytes 

Operating system 

interface — 600 bytes 

OS65D (OSI 

operating system) — 3710 bytes 

Disk buffers — 2056 bytes 

Total 12806 bytes 
A 16 Kbyte system with disk can be used 
for application programming in Forth. 

(3) The extensibility of Forth allows 
the application program to develop an 
application language which incorporates 
terms familiar to the end user. Hence, the 
latter will be able to read and understand 
his programs much more readily than 
those written in conventional languages. 
The drawbacks of Forth arise from 

by N. Solntseff 

N. Solntseff, Unit for Computer Science, 
McMaster University, Hamilton, Ontario 
L8S 4K1. 


its power and versatility as well as, in 
part, from the fact that until recently 
very little attention has been paid to it in 
educational circles. The most serious 
drawbacks are: 

(1) Forth allows the programmer un¬ 
restricted access to the underlying hard¬ 
ware, but offers almost no protection 
against misbehaving programs. Thus, the 
computer reset button is an indispensable 
tool in Forth program debugging, a fea¬ 
ture it shares with assembly-language pro¬ 
gramming. 

(2) Educational computer users 
generally have ignored Forth and, as a re¬ 
sult, there are few textbooks which dis¬ 
cuss programming in Forth and not mere¬ 
ly its linguistic features. 4 

(3) Apart from CONSTANT and 
VARIABLE declarations, fig-Forth pro¬ 
vides only tools for the construction of 
data structures. Every programmer has to 
invent his own set, so that cooperative 
programming is extremely difficult to 
manage. 

(4) Forth routines communicate 
with one another largely by means of the 
parameter (or data) stack. This means 
that the programmer or the reader of a 
program has to keep a mental picture of 
the stack and its changes during execu¬ 
tion in order to understand the behavior 
of a Forth routine (or word). Because of 
this, published algorithms in Forth tend 
to be rather cryptic in appearance, re¬ 
quiring a considerable mental effort to 
comprehend. 

My solution to the last problem is 
very simple - let us reserve the left-hand 
portion of each line in a Forth screen to 
show the appearance of the data stack 
during the execution of the word being 
defined. Only the topmost few elements 
of the stack need to be shown, enough to 
provide a visual aid to the programmer 
and the reader. An added advantage of 
this is that it is no longer necessary to 
give very long comments in order to ex¬ 
plain how a given word works. 

An example of the proposed tech¬ 
nique is shown in the accompanying fig¬ 
ure which gives the definitions for two 
non-trivial data-type definitions. The 
first defines BUFFER to be a data type 
which, as soon as the buffer becomes 
empty, automatically requests the user to 
input the next line from the terminal. In 
use, a call to a variable of type BUFFER 
returns the next available character in the 


buffer or a carriage return if the buffer is 
empty. The second example defines a 
data type for the storage of symmetrical 
matrices where only half of the off- 
diagonal elements need actually be 
stored. 

Some judgment must be exercised in 
breaking up a Forth definition into man¬ 
ageable lines, but this can be quickly 
learned if the following criterion is used: 
Can the line of Forth words be under¬ 
stood from an examination of the stack 
field and the accompanying comment 
field? If this is not possible, then the se¬ 
quence of Forth words is too long and 
needs to be broken down further. 

I have been using the above tech¬ 
nique for the last five months and strong¬ 
ly recommend it to all Forth program¬ 
mers. I would also like to see it adopted 
as a publication standard for Forth pro¬ 
grams. 

References 

1 Byte, Volume 5, No. 8 (August 1980), 
pp. 76-196. 

2 Gary Fierbach, “Forth - The Language 
of Machine Independence,” Computer 
Design, Volume 20, No. 6 (June 1981), 
pp. 117-121. 

3 Dr. Dobb’s Journal, Volume 6, No. 9 
(September 1981), pp. 6-53. 

4 Brodie, Leo, Starting Forth, Prentice- 
Hall, 1981. 

Editor’s Reply: 

The style Mr. Solntseff suggests is 
satisfactory, but we can imagine some 
useful variations. The right end of source 
lines can be used for stack comments in¬ 
stead of the left. Each word should have 
a comment giving the net stack inputs 
and outputs. DOES> words should have 
two such comments, one for the compile¬ 
time (after BUILDS>) and another for 
execute-time (afterDOES>). 

Generally, style is improved by 

(1) choosing good names for words, 

(2) using small, well-factored definitions, 
and (3) using only a few (fewer than five) 
parameters on the stack in a word. This 
reduces the need for comments. 

•»J 

(Listing begins at right) 


30 

386 


Dr. Dobb’s Journal, Number 71, September 1982 


Style Examples 

(fig-Forth) 


It 114 

( Self-Filling 
: :BUFFER 

<BUILDS 


Buffer — 


114/NS/14nov81) 


( data structure: cba : fba : lba : buffer ) 
HERE 86 ERASE ( clear space: 80 chars + ptrs) 


HERE 86 + 
HERE 4 + 
HERE 82 + 
80 ALLOT 


9 


( 

adr) 

DUP @ 

( get 

10 

( 

adr 

cba) 

OVER 4 + @ 

( check 

11 ( 

adr 

cba 

lba) 

= IF ." >»" 


12 


( 

adr) 

DUP 6 + 

80 EXPECT 

13 


( 

adr) 

DUP 6 + 

OVER ! ( ! 

14 


( 

adr) 

ENDIF 


15 


( 

adr) 

DUP @ C@ SWAP 

OVER —> 


, ( current ptr <== last byte +1) 

( first-byte ptr <== first byte ) 
, ( last-byte ptr <== last byte + 1) 

( allocate 80 byte + 6 bytes for ptrs) 
( returns next char on data stack) 


( if empty, issue prompt) 


( get current character) 


It 115 

( Self-Filling Buffer — continued 


115/NS/14nov81) 


( ch adr ch) 00 
( ch) 

( ch adr) 

( ch) 


IF DUP 4 + @ SWAP ! ( if retn, reset cba) 

DROP 13 ( replace 00 by car. return 

ELSE 1 SWAP + ! ( else, increment cba) 

ENDIF ; ( leave current char on stack) 


cba : address of current buffer position 
fba : address of first buffer position 
lba : address of last buffer position + 1 


SCR It 

0 ( 

1 

2 : 

3 

4 

5 

6 

7 

8 
9 

10 

11 ( 
12 ( 

13 

14 

15 ;S 


Data structure for symmetrical matrices 


116/NS/14nov81) 


TRIANGULAR ( n is matrix size; i,j are row,col indices) 

<BUILDS 


( n) DUP 1+ 2 */ 2 * 

( 2n*n+l/2) HERE OVER ERASE 

( 2n*n+l/2) ALLOT 

D0ES> 

( i j adr) ROT ROT OVER OV: 

( adr i j i j) < IF SWAP ENDIF 

( adr i 2j) SWAP DUP 1+ 2 * 
adr 2j 2i*i+l/2) + 

adr 2i*i+l/2+2j) + ( ge 

( array[i, j]) ; 


( calc. It Iocs needed) 
( clear memory area) 
( and allocate) 


ROT ROT OVER OVER 

< IF SWAP ENDIF 2 * ( exchange i,j if i<j) 
SWAP DUP 1+ 2 */ 2 * ( mi in a = aO+mi+j) 
+ ( get addr of 1-th row) 
+ ( get address of i,j-th element) 
; ( leave address on stack) 


McFORTH [llaug81] — Unit for C.Sc., McMaster University 

End Listing 


Dr. Dobb’s Journal, Number 71, September 1982 

387 



A Relocating Loader 

in Forth 


I f you now use Forth, you can appreci¬ 
ate loading a 10K byte screen editor 
(compiled size) as a binary image in 5 
seconds, instead of compiling it from 
source text in 200 seconds. Not only does 
this loader save and load Forth words 
very quickly, it can load the binary image 
at a different machine address than it 
was originally compiled at. Pre-compiled 
modules of commonly-used words can 
be kept on the disk and linked onto the 
Forth dictionary in any order. If you’re 
interested in the inner workings of Forth 
— especially the public domain Forth In¬ 
terest Group (fig) variety — you’ll find an 
enormous amount of information about 
the layout of Forth “dictionary” entries 
contained in this program. 

This relocating loader was written in 
a fig-compatible version of the language 
(Z-80 Forth by Laboratory Microsys¬ 
tems). By far the major difference be¬ 
tween fig-Forth and Z-80 Forth is in the 
way they treat disk files: fig-Forth main¬ 
tains a disk format incompatible with 
CP/M, while Z-80 Forth uses CP/M files 
to store programs and data. 

Operation of the Words 
GET and SAVE 

To create a binary image for later re¬ 
call, the desired Forth words are first 
compiled into the dictionary from their 
source text definitions. Once compiled, 
the binary image of that segment of the 
Forth dictionary is written to a file by 
typing: 

SAVE < word >< filename> 

where <word> is the first Forth word 
of the module and < filename > is the 
name of the CP/M file that holds the 
image. 

After the binary image has been 
created with SAVE, it can be recalled 
with the word GET. In operation, GET 
reads the binary image file and appends 
the Forth definitions contained in it onto 
the end of the current Forth dictionary. 
To load the definitions, type: 

GET < filename > 

where < filename > again represents the 
name of the CP/ M file that contains the 
binary image. 


by Joe Barnhart 


Joe Barnhart, P. 0. Box 4383, Santa 
Rosa, CA 95402. 


As implemented on 8080 and Z-80 
computers, Forth does not produce 
position-independent code. If a Forth 
program is compiled to run at one 
machine address and moved to another 
(or loaded at another), it will not run 
properly. After it loads a binary image, 
this loader modifies the Forth definitions 
so that they will operate properly at 
their new addresses. High-level (“colon”) 
definitions, constants, variables, and • 
< BUILDS DOES> definitions are all re¬ 
locatable. Machine code definitions are 
not relocatable and this loader issues an 
error message if you try to save one in a 
binary image file. 

SAVE 

The simplest of the two definitions 
presented here, SAVE performs the fol¬ 
lowing steps: 

1. Check the dictionary segment for ma¬ 
chine language definitions. Issue an er¬ 
ror message if any are found. 

2. Save the dictionary segment in a CP/M 
file. 

3. Save four numbers that are used in the 
relocation process. 

Checking the dictionary for ma¬ 
chine language (or “code”) definitions is 
straightforward. 7CODE-DEF checks a 
single word and reports an error if the 
word is a code definition. NO-CODE- 
DEFS calls the word 7CODE-DEF re¬ 
peatedly until all of the Forth definitions 
in the dictionary segment have been 
examined. 

When SAVEd, the dictionary seg¬ 
ment is written into a CP/M file separate 
from other Forth text and data. In 
Z-80 Forth, a filename is parsed from 
the console input stream by the word 
FILENAME. OPEN/MAKE tries to open 
a file of a given name. If the file doesn’t 
exist, OPEN/MAKE creates it. Finally, 
WRITESEC writes one sector (128 bytes) 
to the file sequentially. 

Before the file is closed, four num¬ 
bers are written into it that allow the dic¬ 
tionary segment to be relocated when it is 
read again. The numbers are: 

1. The size of the dictionary segment 
in bytes. It is used to allot enough space 
for the definitions when they are loaded 
again. 

2. The byte offset to the Link Field 
Address (LFA) of the last word in the 
dictionary segment. It allows the loader 
to find the last definition in the segment. 


3. The present compiled address of 
the first word in the dictionary segment. 
With it, the loader calculates the differ¬ 
ence between the original compiled ad¬ 
dress and the loaded address. 

4. The byte offset to the last vocabu¬ 
lary defined in the dictionary. When load¬ 
ing the segment again, it indicates wheth¬ 
er or not any vocabularies are in the seg¬ 
ment. 

GET 

Loading the segment into the dic¬ 
tionary again is a little more complicated 
than saving it. First, the CP/M file con¬ 
taining the segment is read into memory 
and appended to the dictionary. The four 
numbers are then recovered from the end 
of the file and the segment is relocated 
to run at its new address. 

Opening and reading the CP/M file is 
done in much the same way as the file 
was written. FILENAME again parses the 
name of the file from the console input 
stream. OPEN and READFILE do what 
their names imply. After the file has been 
read, the word GETADDR recovers the 
four numbers from the end of the CP/M 
file. It stores the difference between the 
segment’s original compiled address and its 
loaded address in the variable OFFSET. 
The original compiled address of the first 
definition in the segment is stored in the 
variable FIRST.NFA. The size of the seg¬ 
ment, the point to the last vocabulary, 
and the address of the last word in the 
segment are left on the stack. 

Central to the operation of the load¬ 
er is the definition RE-LINK. All of the 
actual relocation is performed by invok¬ 
ing RE-LINK with the address of the last 
word in the segment on the stack. RE¬ 
LINK has two jobs: (1) to re-establish 
the linked list of words that make up the 
Forth dictionary, and (2) to add any off¬ 
sets necessary to the definitions them¬ 
selves to make them operate at a new 
address. 

Restoring the linked list of words in 
the new portion of the dictionary is easy. 
The offset between the original compiled 
address and the loaded address of the 
words is the same for all of the words in 
the dictionary segment. By adding this 
offset to the linked list pointer in each 
Link Field Address, the integrity of the 
linked list is restored. 

RE-LINK examines each definition 
and “patches” it according to the type 
of Forth word it is. Colon definitions, 
< BUILDS DOES> definitions, and vo- 


34 


Dr. Dobb’s Journal, Number 71, September 1982 



cabularies require special treatment. Co¬ 
lon definitions are treated by the word 
COL.DEF and < BUILDS DOES> defi¬ 
nitions are treated by DOES.DEF. Vo¬ 
cabularies, which are a special kind of 
< BUILDS DOES> definition, are treat¬ 
ed by the word VOC.DEF. 

RE-LINK is a recursive Forth defi¬ 
nition. By using the word SMUDGE at 
the beginning of the definition and again 
at the end, the normal Forth mechanism 
for preventing “accidental” recursion is 
bypassed. Forth can have “tree struc¬ 
tured” vocabularies within its dictionary 
(Figure 1). To link and relocate all defi¬ 
nitions, each vocabulary must be fol¬ 
lowed to its end. When it detects a new 
vocabulary, RE-LINK treats it (with a 
call to VOC.DEF) and calls itself to re¬ 
locate the newly found vocabulary. When 
the new vocabulary has been completely 
relocated, RE-LINK continues where it 
left off (Figure 2). 

COL.DEF relocates a single colon 
definition to run at a different address 
than its compiled address. High-level 
Forth definitions are a list of the ad¬ 
dresses that are executed when the word 
is invoked. In the simplest case, a high- 
level definition that is composed entirely 
of words defined in the main Forth dic¬ 
tionary (not the loaded segment) needs 
no relocation. On the other hand, if some 
of the definitions are defined in the 
loaded dictionary segment, the addresses 
must be offset by the difference between 
the loaded and compiled address. Two 



Forth can have “tree structured” vocabu¬ 
lary. 


Forth words deserve special treatment: 
LIT and (.”). LIT pushes a 16-bit literal 
value onto the stack when executed. The 
literal value, which is compiled into the 
definition after LIT, is skipped by the 
loader to prevent it from accidentally 
being “relocated” and its value changed. 
Similarly, (.”) is followed by a string 
which, like the value after LIT, must be 
skipped by the loader. 

DOES.DEF relocates the DOES> 
portion of a <BUILDS DOES> defini¬ 
tion. First, it checks the address of the 
DOES > part to see if it is defined in the 
dictionary segment just loaded. If it is, 
the address of the DOES> word is offset 
by the difference between the compiled 
and loaded addresses. 

The pointers contained in the vocab¬ 
ulary definition are modified by the word 
VOC.DEF. A vocabulary definition con¬ 
tains a pointer to the last word defined 
in the vocabulary, and a pointer to the 
previous vocabulary defined in the dic¬ 
tionary. Each of these are checked and 
offset if they are within the loaded 
segment. The word VOC.DEF leaves the 
address of the last word defined in the 
vocabulary on the stack, for the recursive 
RE-LINK call. 

After the dictionary segment has 
been RE-LINKed, all that remains is to 
update the Forth variable VOC-LINK 
and allot space in the dictionary for the 
definitions. 



Figure 2. 

After relocating a new vocabulary, 
RE-LINK continues where it left off. 


36 


Suggested Modifications 

There are two modifications to per¬ 
form if this program is to be run on an 
8080 fig-Forth system. For one, GET 
and SAVE must be modified to use a 
standard Forth screen file instead of a 
separate CP/M file. Reserve the first line 
of each screen as a comment line to avoid 
sending machine code to the console 
whenever the screen file is INDEXed. 

A more subtle difference between 
fig-Forth and Z-80 Forth is found in the 
words BRANCH and OBRANCH. Both of 
these words cause the Forth interpreter 
to jump to an address, which is compiled 
just after the BRANCH or OBRANCH in¬ 
struction. In standard 8080 fig-Forth, the 
address is coded as a relative address. 
With Z-80 Forth, however, the address is 
an absolute address. Instead of relocating 
the address, modify the loader to skip 
over it. 

(Listing begins on page 38) 


Dr. Dobb’s Journal, Number 71, September 1982 

389 




03 

TJ 


os + 

z A 

u 

cl oa pa 
d co a 
a \ w j 

(N ffl K H 

E-< 

Z 

D A 

I 

I 

ai o h (N n 'T in 


TJ 
T3 Li 

H 0 

~ 0 2 — 

5 

• X <u 

— UU B1 ,-1 

X U) Li ^ -H 

• CL 03 -H X 

• —I X 

J * Z 03 

C X 03 03 x jk 

03 J AJ 

03 -H X X | 4J 

HTJ u 0-H 

U 4-1 4-1 O -»j 

03 0 0 > 03 

TJ XI 4-) CO 

C 4J < < <d -H 0 

03 CL 0-1 X r—( 

03 aJ Z X <D o 

03 44 4J 

O 0 <D <u TJ -H T~J 

-h x x x c u c 

C W 4J 4J (U 5 (0 


—' —• —• 


V 



A 

T3 

02 


Li 

0 

e 

“* 


> 

o 

+ 

V 


CN 

ua 

1 


> 


CL 

< 

CL OS 

< 

CO 

D 

z 

Q < 

CO 


Cl 

W — lJ 

i 



CO 

< as < 

a w cl 

w > CL — 

o 

u eh a 
w 1 co pa 

CO w > 
\ a Eh o 
CD < 
WJK 
04 a 

D W + + 
Q S3 <N <N 


A V 

as w 

CO 

® w w 

t-< CO 
&S X O 

z a: j 

■H Z CJ 

I 04 CL 
UDO a 
O D OS | 
> <N Q 1 


O H OJ 
L U 03 
*W U u 

U 

in x in 

TJ 4J 
Li *H Q3 
O 5 (13 
S* CO 
cp 

sc c • 

Eh O T! 

OS 1—1 d) 

O 03 03 

Cl a 

- in 

03 4J 

x: X 

x 

03 -H 

4h U) X 
O D 

X 

03 ro 
Cn • 

03 >1 in 

E u Q3 

•H -«H 

C L4 
>4 O 03 
L -H H 
03 4J 3 
C on 
•H -p4 (T3 

-Q T3 U 
O 

03 03 > 

X 

(/ILK 
03 E- 

> 4-4 OS • 
03 OOH 
W Cl -h 

TJ 03 
' C T3 43 
U 03 03 03 

> O T3 

< 03 X 

CO X 03 

X T3 Li 
“ C O ' 
TJ O 03 E 
Li 4-1 

O 03 Li 

^ A > O 

T! 03 4-i 
W Li W 

••ho r> 

X 5 O L-l 

Eh V 4-J f—H 


in 

03 * ^ 

E O 

03 f—I 4-J 

ch cn 

03 O *H 
X 4-1 X 
•H Qj 

^ 4-1 X 

03 03 4-3 
Li >iX X - 
03 JD 4J -H C 
4-1 W 
03 T3 03 03 

w 0) E C o 

£ 03 0) TJ 

cn o c a 

03 X 03 o 4-1 

H H H -r-l 

L O-H O 

03 4-4 4-1 4-1 X 
X U 

O ^ x >, 0 
03 Li x 
>4 C7> 4-J 03 

X — 


w w co 

> so 

< < Q 

00 CO 2 Cl 

rH W OS 

T3 Q iJ CL O 

=*= C < H < QS 

03 O Cl ^ OS 

C X Z CO W 
03 Eh W CL n. 

03 U m CL D in 

Li U lO O Q H CO 

o 

CO w 


TJ 4-1 ' 
L. C o 
O 03 
4-3 73 

o c c 

03 03 03 r 
cn x 

43 Eh . 
03 O 
C - 2 
O O 
A 03 1 
'O v H ! 
03 -r4 I 

03 4-1 x I 
Li -H £ 


Cl + CL 

W cc o 

-J u a. 

w _ cx w E-i o 

fc. Z O B 01 < 

QmD II J\BP, 
<UNOhBH< 
w W X w 3 

x CQ 3 « c/) 


6 - ra 

•H 03 
T3 C O O 
03 -H O 00 
03 OO 
Li < T3 T3 

Cl - - 

C Z 

03 44 4-1 

03 X O 0 
Z cn 

X Li < < 

03 -h ELi Cl 
X X CJ CJ 


>4 0 J 

Lt — X 
03 O 

rH - 3 ^ 

so cn O' 

X -H 

03 E X X 
O 0 ) O -H 
O cn TJ r-l 

> - - - 

X X X X 
OOOO 

< < < < 
Cl Cl Cl Cl 
CL U U U 


<<<<<<< 

P-i ClClClClClClCLi 

W ZUCJCLCJUCJ 

Q Eh. 

•Cd^JCOUHOtn 
COCOCOOWOSEhm 
Wti0SUQ>UOiJ 
O Cl w Q co D 
Q O Cl 

•'WWt-'EHEHEHEHEH 

WXX2ZZZZZ 

XCQDQ<<<<<S 

C<<EhEhEhEhEhEh 

OJWHCOCOCOCOCOCO 

xaaszzzzzz 

w<<000000 

c>>ouuuuo 

0 

O <2J CSI <S4 


< < < < < 
) Cl Cl + Cl Cl Cl 

OOUUCNUOU 


'XcNm-^r ld vo r^- co <r> o 1 —i 


OHMnT-lOvOhCO^Oi 


i in vo r* co 


c 


T3 •* 

Li 


TJ 

03 

2<S 

03 A 

CQ 

CO 

-Q CO 


< 

O W 

03 

Eh 

x o 

0 


Q 

^3 

•• 



U CL <—1 ■ 

O O-H 

> x 

w o 

S x O • 

< c r 

CO >4 

f\. LI X 

X -H : 


Cc 

g 1L 

0 o 

■JO 

ttN 


03 TO TO 03 

O ^ 03 03 

®o nx 
I H 0 o o 

N X X X c 

03 X X 

Li 03 03 03 

OX 3 ■ 

X 0 X X X 

c 0 0 03 

cn c c > 


0 x 
x 0 
c 
cn 

03 Li 
CP 0) 
03 X 

w in 
cn -h 
VO 03 C* 
E 03 


I -H T3 x 03 

: 4J c 0 c < 

I 03 03 C -h ( 

1 LI Li X 1 

i 03 o> c cn : 

) Qj CL O CD < 

I 0 0 -H T3 I 

X 

P X X O x r 

! 03 03 S3 03 < 

1 CP CP Li I 

) 03 03 X 03 ( 

) x x in x r 

l X X c X r 


oxcNrorr in vo p> co o x csn in 


) z co cq as 

< o \u w 

H CD Cl K 
1 Eh 

■ h fn 

: Z Z ro 

) x < 

Cl Eh CO 

5 W CO Q 

: Q Z *J 

3 O x 

DSUfflD 

< Eh CJ CQ 
] OS 00 Cl v 
) O cn 

Cl X •• 


oxcNm^r ltivop-cxdctnox! 


W l ^ 

CO l 
O l 

U cn 11 
cn 11 

•» 03 in 

U l m in 
i*s T3 cn in 
< T3 cn 
2 03 0a 
\ I O CL 

z jd as o 

w o q a; 

CL X Q 


O 

CO 


o 


^ O co 

Cl 

— as 


Q O 

M 

Q 

•• 

Cl Q 

Q 


w 

Cl 

Z 

CO 

> 

CL 

pa 

o 


< < CL as Q- 

CO H 2 < O CL Cl 

co its co 5 as o as n 

tj< coasas cl o o 

* cSin WQ <as > 

03 \x cn n. w £ as w 

c z 04 u co co w 2 
03 Eh W Cl ooco O a* < 

cdpjcldcl j t_a vo co 

Li CJ O D x pa CJ X CO (N. 

u 

CO ^ •• 

oxcNro-^invor^cocPox 


Dr. Dobb’s Journal, Number 71, September 1982 



TJ — 

04 

T 3 cn — 
CD C - 
(D -h 4J A* 

c u C (D 


<D 

Mi • TJ 

O O 


-P (TJ rH 

C QJ 

< e 

4-> 

fl3 TJ • <0 

rH £ 

4H 

(IlH 

O 0) 

Cm 

c 

a (v • 

0 

•rH 

W TJ 

- 

Z A 

•H 

A -P <D 

U 4H 


H C OH 

UJ 

1 


W (TJ -H A 

O 

TJ 

X O E -H 

(U ^ 4h 

A I 

• 

04 O -P 

O 

Ml 

0/ o 

e o 

W 

A 

O 0 -P 

A TJ 

0 

4J ^ 4J 

3 - 

(TJ ^ 

(TJ 

TJ >H 04 CM 

C 


rH d) <U 

WWW 

<H C 

o 

<U C/l O 

W 04 


a ru C (A 

C -H W 


0 

4H Ml 4H Ml 

4-> 

0) 

•H Ml 4H 

o e a/ 

0) rH 

> 

0 4H TS 

04 4J 

A 

-* <U C 4H 

U <D mi 

JC 1 


C O 

W O 

A 

W 4-1 -H O 

W TJ 

'—' 4-4 U 

'— 

< -H 0) 

4H C 


•H 

<D - TJ 

0 


Cm ' W 

4-1 

A 

^H Ml - 

w nj 

< A > 


Cm A O m 

O d) 

d) 

a) o 

(TJ rH 

Cm <D 


•H W 04 

rH 

W 

Cm CMTJ U) 

u -h a 

A W W 

u 

A 

TJ ^ 

4H O "H 

TJ 4J o 

1 4h Qj 

o 

04 W Mn • 

TJ A 

4H 

Q y (/l 4H 

C C Ml 

U 4h O 

> 

CP-h -h • 

(TJ £ 

0 

Z W -H -H 

<D 3 TJ 

— O O T) 


W (TJ 

<u — o 

— 4J O 

>1 TJ «—l 

< A H 0) 

Cm O mi 

A C 5 

I *H 04 

4-) 4-J Mi 

C/2 (D CO O 

<T 3 >—I ro M—I ' 

i—I D H (U ' 

TJ A 

0 4-4 

-* 6 O < 


< 0/0 
Cm A 
A A < 

I Cm 
-p x U 

CO U 
Ml 4-> 4J 

•h ro CD 

mh cm cp 


O CO 

< 


— 1 

• < 

< 


CO 

U Q 

Cm 


+ 

A Cm 

Cm 

+ + 

> 


A 


•» 

O A 

CJ 

CN CN A 

O 




CM 

U 





'— 

<24 

< Cm 

'— 

M 

Cm Cm <24 <24 




^ M 


2 

O O 




CM 

A CO Q 

•• 

CO 

< 

Eh CO 



D 

Z 

CO 

CO 

CO < Cm 

CO CO 

rH 


Q <24 <24 CO 

> CM 


CO Cm < Z 

CO < 

00 




< D 

<24 

< CJ Cm • 

Cm CJ 

o 


+ 

< Eh CM 

m co o 


U ‘UEh 

Cm Q 

< 

Cm 

CN 

Cm CO O 

rH 

CM 

Q • CO 

O Z 


CO 


Z CO OS 

TJ Cm 

D 

<24 Eh Eh OS 

CO 


Q 

+ 

• Cm D 

** G CO 

a 

Ohm 

Cm 


. CN E-* Cm 
CQ CQ O W 
W CM OS CO 
ODHt J 
Q D Cm h CD 


«JQ Z WCMQPCmmCM< 

C • m + J D D W CM 

(DEh jonhq q cm o 

04 W O W X W OS 

4UU CD S « Q A 

O I 

CO •• I 


O' 

oHCNmrnn 
rH rH rH rH rH rH 

0 

1 

2 

m 

-=r in 

6 

7 

8 
9 





CM 






O 


4-> 


—* 


O 


C 




A 


a/ 


w 




Ml 


e Ml Ml 


Cm 


Ml 


<D O TJ <a 


H 

CM 

3 

CM 

4-J O TJ A 


a 

O 

o 

0/ 

W rH (TJ u 


z 

— o 


g 

>1 XI 


co 

A 

TJ 

(TJ 

W 4-4 A 



A 

c 

W 

O rH X X 


Cm 

•H Cm 

(TJ 


Mi 0 C4 <14 


H 

M 


0) 

O Ml 4J C 


Q 

4-4 Q 

4-> 

X 

•H 4-1 


Z 

(0 04 Z 

X 

4J 

2 A c 

rH 

CO 

e u co 

a> 


4-4 0 

i—1 


H (TJ 


>. X O + CM 3 — O 

u 04 D C + Uh 

o 4J (D® Q 

4-J 04 rH Ml 2 CO 

H3 E-h2<sj^.Oh <1/ 

Mi (0 Ml H u >1 

O c M (DH^v 

O v mi Cm CM O U w 

(TJ (OHD'D'D + C'* 

a w a/ a q cl»h c 

2 H z 4-4 CO O O 


Q 

< 

•H 




< 

Cm Cm 

W 




Eh 

A H 





CO 

Q 





CJ 

Z 

1 





1 — CO 

1 




«■ 

1 + 

1 




Cm 

1 A — 



< 


CO 

OS + 



Cm 


Q 

CO <24 

Ml 


CM Z 


• 

< > + 

TJ 


< • 


CJ 

Cm O < cn 

TJ 


^ Eh 

Eh 

o 

►J 0-i 

(TJ 


co co 

CO 

> 

<24 z OS 



OS 

CO 


w . w 

'— 


+ H 

Cm 


Eh Eh > 



Cm 

Cm 

• • 

CO CO o 



CO 

O 

CO 

CO OS 



OS CM 


> 

Cm h (27 •- 



CO D 

1 — 

< 

Cm Cm 


CM 

32 a 


VO CO 

O Eh < 


< 


CM CM 

rH 

<24 CO Cm 


S (24 <24 < < 

TJ 

Cm + CO J 

OS 

CO 


£ £ 

=*= C 

CO + Cm 

a 


CM CM 

CO CO 


(TJ Q 00 CN Cm < 

C • O Cm 

04 E-» CJ CM CM CM 

OJUODDCm 
M l U > Q Q m <2j 

o 

CO '— •• 


D©DD 
< Q Q W <2; 

Eh CM OS 

W D + + W + 

o Q CN CN K CN A 

I 

•• I 


OH(Nnijinixihco(^OH(Nn^io 


- 

< 

U 

CO 


CM 

-H 

P 

UH CM 

c 

z 



UH 

< 

w 


■H < 

(TJ 

CO 

— 

<24 

<14 4-4 *H 


c 

o 

s 

O 

J 



e **h 

CO 

04 


4-> CO 

c 

M 

TO 

CQ 

(TJ 3 Ml 


4.4 

m 

•H -—s 

3 

Cm 

US 

H 

C O 

— • 

X 


3 — 

a 


z 

Eh 

04 

CJ 

04 

— 

- tru 


CO < rH — 

>, CO P W -H 

(TJ 04 CO CQ UH 

CO OS Ml p w 

2 T3H w -M CO H 
< 4-1 T! rH (0 P > 

Z O (TJ US E W < 

CO I CM U Mi CO 


co <D x: co co 

MI rH u > 

E-* <U < Eh 

O A + 4J CO O 



P >iXJ DO OCOQ 

os 

4-4 

iH 

X 

A 

OS 


c 

Eh 

H W O Q A UH > 




04 



-C 

(TJ 

Z 

Cm 04 Uh 03 < CM 

+ 

W 

CM 

c 

CM 

+ 

4-4 

04 

CO 

4-4 + 4J CO O 


•rH 

< 


O 


-rH 

rH 

OS 

Ml '-rH <24 WOOS 

H 


2 A 

OS H 


o 

OS 

..3 mi a 


'—' 

CO 

o 

a 




D 

CO O CO US -H CM 

CM 



4-) 


CM 

04 

'— 

CJ - 

> O CO A UH o Cm 

D 

II 

+ 

04 

Cm 

D 

c 


< < CQ OS H 

D 



UH 

H 

a 

0 


<24 OS 

co tj os — a 


VO 

CD 




TJ 

CM 


<P mi CO CO Cm 

TJ O 2 w 

=** C 2 < r- O 

fH Z n <5 j Q 

C CO CO 
04 E"< -rH P CM US O 
<UCO£HDO 
mi O Cm Q (Q CO 

U 

CO — ' 


v E-< ^ 

Cm O CM 

Mm OS C2> < < 

<n U £ i 
II CO CO 

CM CO CM i 

vo O O O Cm : 

^ Q CO Q h 


— 04 

Ml 




-X 


TJ 

04 < 



o 


TJ 0 

N 

Cm 



(TJ 


Ml O 


CM 



4-4 

W 

0 

A 




w 

UH 

£ UH 

W 

O 




04 

•H 

3 

4-4 



c 

TJ 

4-J 

a, 


,—, 

04 

(TJ 


04 04 


c 


c 

04 

04 

CP 3 

*» 

* ~ 

< 

0 

rH 

TJ 

Mi Mi 

TJ 

0 

Cm TJ 

o 

0 

(TJ 4-* 

Mi TJ A- 

CM 



O 

4-4 V 

0 

UH 


04 

• 



s 

W 04 

W 

Ml 

• 

UH 

UH A* 


TJ TJ 

- 

- 


•H 

O <N 

4-4 

Mi 

TJ 

04 

04 


+ 

W 

O <L> 

Mi 

5 

Mi 

Ml 

< H 

(TJ 

S TJ 

O 


(TJ 

0 

Cm TJ 

rH 

0 

^ UH 


Ml 

CJ TJ 


rH O 


-rH 

04 

Ml 

(TJ 

4-4 

rH 

4-4 


S 

04 

. 04 

(TJ 

(TJ (TJ 

X 

04 



A W 



04 

0) 

UH 

rH 

4-4 -H 

4-4 

4_> 

c 

w 

•rH 

(TJ 


Ml 

U -rH 




c 

' -P < 

— (TJ 

04 

4-4 

TJ 

TJ 

CP 

04 Cm 

4-4 

X w 

04 

C 

C 

•iH 

CPU 

W 

O -rH 

CP 

(0 

(TJ 

w 


1 ^ 

w w 

w 

.—. 




OHCNmM'invDhcoo^OrHOJ^^in 


CO II 

> 

i< CO Cm <24 CN 

O CO O CO 

•H H Q CM CO 

TJ Cm I D D 

«= CZCOQZ 

<T 3 M Q M 

C CQ O < 2 

04 E-* U Cm 
04 CO CQ A» U I 
m. O U 

U Cm •• 

CO 


OHNfO<fl/nOMX)0\OH(NfA^in 


OS CM OS D OS 

; co < co p os 

< > £ > H CM CO 

) O CO O Eh < ('• 

1 2 £ 



< 




5r 


Cm 

r-* 





CM 

CQ 



t>o 

A* 

* - 

U 


Ml 

<3 

4-> 

TJ 

Cm 


O 

CM 

c 

u W 



4-» 


04 

O UH 

04 


O 

o 

u 

^ 0) 

4-> 

<—. 

04 


Ml 

TJ 

(TJ 


W 

cm 

3 

04 

O 

04 


o 

O X 04 

O »H 

(TJ 



4-J TJ 

rH 

•H 


c 

TJ 

O rH U-l 

04 

o 

c 

UH u 

(TJ 


4-J 

"T3 

(TJ 

O 


(TJ 

•H 



>i 

»> 


Ml 

3 

4-4 

04 C 

04 

04 


•S 

X 

E OJ 

E -X 



04 

(0 

(TJ 

(TJ 

0 

c 

4-* 

C Ml 

C 

E 4-> 

o 

c 

O 

04 



<o 

0 

04 UH 

rH 

Ml 

04 


O X 

•H 

O 

Ml 



4-1 -X 

UH 


(TJ 


04 

O 


c 

CM 


e 44 o) 

4-J 

04 

04 


(TJ 

04 X 

04 

a u 


W 

CP O 

CP O 

CM 




w 





w 

CM 


TJ 

OS 


A 

< 


- Ml 

A 


M 

es s 


0 



Cm 

O CQ 


CxJ 5 

< 


Z 


CM 

> 

Cm 


w 

Cm < 

O 

< 

Z CQ 

W 

CQ 

O W Cm 

OS 

CQ W 

Cm 

OJ US 


CM CO 2 < < 

D Q 3 S 2 

Q I Z\W 

CO CO z 

- Q A CO CO 

O m Oh P 

—• CJ Cm O m 

CO I Cm 

JO to CO z 

M Z P P M 

CM M M CQ Z 

2 Cm Cm m 

O CM Z Z < O 

CJ D h H Cm CO 

1 — 1 Q CQ CQ Z CD 


O HMfO^l^^MD 


Dr. Dobb’s Journal, Number 71, September 1982 



50 


•o 

c 

UJ 


o 

CN 


c 

oj 

<13 

u 

cn 


oxAiro^mvor'-coiPoxcNroTrin 


x E 
0> r* E-i 
.* x < 

03 M 

e a) a 

CP E 

• 03 S 
w as 

w 

W x 
03 \ •» 
x M 

U H 

03 

-c cn a 
uz w 
o CJ 

>1 H — 

xj cn 
2 cs> 
- e 
S a 


sc 

CJ 

z 

< 

e 

CQ 

o 

e 

E 

x 

e 

s 

O 

CJ 


c 

03 

e 

03 

CN X 


in «3 a o 

x o u 

=*^ CO pL4 o. 

c 03 6 E 
<d w o cn 

0> 03 x < 

u uu U 
u 

cn — — 


b 

Eh 
< 
B M 
E Q 
M B 

a, s 
s s 

O M 

u 

e 

W in 

> 

O E 
O 
w e 
e a 

X 

e b 

S E 
O M 
cj a 
s 
cn o 
E cj 
w 

< - 

a 

(V. o 

B 

e 
B b 
O EC 


** e 
cn 

o B 
Eh Z 

b < h a 

K H U H 

B Q B Q 

m cd z 

£ B 
SC S E 
O H O '— 1 
Z EE 

< •«* Q E 

E M 

ffl^r Wfl^U 
E S Eh 
B B m O < 
e h a u h 
H D S“Q 
E Z O B 
S B CJ cn S 
O S 

cj 1—1 cn u h 
CD E J 

WdHH - 

E m < 33 
x E E 2 — 

< X a. 

E O HE 
n* u ^ o cn 
“ U 
in b n 
cn cn Eh 
B < <a> < 

2 E U B 
< Q E E 
Z2ZWCD 

uwwue 



03 


CD 


73 


2 


0 


0 


6 


X 




X 


w 


01 


w 




<13 


(0 


U 


C 

w 

73 


0 

03 

73 



CP X 

03 


X 

03 X 



•pH 

W 3 

X 


c 

W 4-1 

O 

03 

•pH 

0) 

03 

3 

X 


^ E O >iU (TlU (DJC 


cj 

03 

=*»= e jj 03 
a; w c 

C X 0 

(D in >,.h 

03 >i X X 

ucn au 
O E x 

cn 03 T3 


X •! 

o c 

o 3 

c 


73 
J-J O 

- o 


73 CP O 0 
C 03 x 
0) 03 X x 
W 03 


c 

03 W 


O X 
C 73 


X O 
X W 
3 x 
X 73 


OHINrOTTiD^r-CO^OrHCNrOTfip 


OHCNrOrtif)vOr s *CDONO 


X 
XI C 

< X 

s o 
m a 
cj 

b X 
Q 03 

E 

03 X 

A O 

Q3 K 

■U T3 Eh 
W E 

3 CP O 
6 C B 

•H 

B W O 

cn co co 

< x | 

CQ E N 

H cn co in 


a. a. 
c c 
0 0 


<13 

> — 
•H 

W 4h 
—' U <13 
3 T3 

n. o 

>i 03 A 

v-i cn 
u 

4-1 o 

Q 


03 


<D C3 
TJ T3 

C A 

0 cn 
•—i w 

88 


E 

O 

Q 

Z 

w 

E 

M 

Q 

O 

U 


JxC u 


> H 3 
I CP 
03 Q3 C3 
U U 
X) 

■H » d) 

w w 
w fl)H 

H >, <U 


E E + 

O O cn 


E 
E m 

z a 

M 2 

XI w 
I 

W E 
E W 
Q 
E • 

w cn 

Q W 
• O 

u a 


— 03 

rH 

W 3 
E X) 
W 03 
EC O 
O 

V > 
< 4H 

E 0 
X 

V 

rH C 
•H <13 
4J 

C U 
3 0 


II 

O 

E 

O 

v II 

W CJ 
E O 
W > 

a: 


4J 

x — 

<13 . 

C • 

0 c 

4J 03 

<D 

u 

w o 

•H w 


T3 X 

<U 03 
^ C 

c 

•h T3 
rH Q3 

3 

S C 

0 -H 
rH 4-1 
rH C 

0 o 

4 H U 


<4H 

<13 

• Eh 

• cn 

o w 

V) Eh 

< 

- X 

<13 — 

rH 03 

3 x: u 

TJ 4J C3 
0 T? 

E O 03 
4J <13 
C X 


E 

a 


< 4-» 

cn 

E 

03 0 
X U 
4-> 14H 


X T 3 OD 

4J 03 03 
•H<DJ 
^ 03 03 
O O 
'O rH O 
<13 rH 
> 73 <13 
03 C U 
W 03 r 


C * C O 0 

D C/1 O 00 u 

k-i 03 |4-l 

rH N 

0 XI • O 

4J 03 T3 w < 

•H <U - o 

»H 4J E X 


03 03 03 
> 73 4-1 O 
O W 4J 

** E >1 
wo w w 
4H o O 73 

0) U M C 
73 03 O 0 
•h O 
rH <13 S <D 
03 U 


•rH 

03 


03 73 

03 > 03 

>1 


X 

CP 


X c 

X 03 

x in 


03 ^ 73 


•H 3 

03 X W 

0 o 


73 C 

3 


X 0 

1 03 

X X 


•pH 

e 

A 

X 

x x: x 

03 


X X 

w 

03 

03 

•H CP x 

X X 


w • 

1 

e 

CP W 

•H 03 

0 3 


03 • 

c 

03 

03 *pH 

C -C x A o 


X • 

3 

C 

E 

•H D 

03 JD 

• 



03 

•H <D 

x: X3 

E 03 

Eh 

-r --- 


X 

CP 73 X 03 


E 



•pH 

>i 03 

03 X U 

W 

O 

• 


X 

u E 

coo 

. a; 

X 


V 

03 *H 

•H X > 

03 

0 


Eh 

E 


C 03 rH m 4-> 

•H >, 4J X 73 X3 4J 
X U c rH c 03 w 


U Q) Eh 03 W U X 

4J 4J E O <1> O C 




A* —. 



03 —03 



X — X w 

A* 


•H Eh 3 X 

X 


x w cn 73 — <D 

c 


CEO 73 

03 

E 

6 0 Eh E E 

X 

Q 

0 x < Z 5 

X 


x X E C x p-k <u 

3 — 

X 

Xx x |J c 

CJ 

03 

C C IX 


03 W -H -H X U *H u 
73 E <13 <L> 4H 03O o —' 
C03XWQ3UO> aUH 
03C-HW73 73O O 03 

Q34HQ3 73 > <U U fcH 
4-3 rH U H 03 4J73Q-H 

X -H Q3 -O H 4-3 03 4H 

Q34HU7303a3W73 «• <13 

4-3 -h 03 X 03 a 03 X <13 
C <D 4-3 <13 4J H D (() 4J X 

0 X 

o -x 


G3 C 73 
E <D 03 
03 a 03 
W 0 U 


X 03 
4-> U 
0 

4-3 X 
03 <13 

CP U 


03 03 * £ 73 

4-3 X 0 X C <13 

03 4J W <13 Q3 W 

73 X 4-3 0 

a w HH 4-» XX 
D -H -H 0 <13 U 


•* 

u 

03 

0 < 03 

X *• 73 

rH 

- Eh 


>i C 

0 

03 03 C 


e cn e 


C x 

* 

0 CJ 0 

X 

Z E X 


03 A 

w • w 

0 C 0 

V 

x Eh Q 



73 W X 

X 03 03 


E < Z 


W 03 

X W 03 

03 X W 

~ Eh 

1 J E 


03 A 

0 03 73 

x w 

Eh E 

E 


> 4J 

£ x 

1 c 

E U 

E E E 


03 

73 A 

C x 

U 

x o 


x u 

sc 73 cn 

3 >i 



< + 

> E 

Q 

E v 


03 x O 

5 Q x x O 


< E <N 

cn 

E E Z < 

> w 



03 

03 


E CJ 

E E 

Q D E E A 

< e cn 



C 

- - X 


CJ • E 

x E 

Q E Q El 

co cn E e 


73 03 


W W X 3 

CP 

• cn o 


z cn < 2 j 1 

x EE 


x • A 

X 

X X 03 A 


E E Q 


E <C csj < 

73 X 


0 73 X 

•pH 

C 03 X 


o o 


CJ E E Eh 

^ C 

E 

5 C 

03 

in >o ja J* 


U Q 


Q E < E E < 

03 <a> 

CJ 

03 - 

A 

■u e oi 




Z D S W 

C E 

D 

W E 

X 

W 03 03 x 

c 



EQcnx®E 

03 Eh E < 

D 

■H E in 


C 73 W 73 

03 



X E 

0)EDSS 

x: o x 

X 

0 0 W 

03 



5 E 

x cj Q cn 

cn a 

Eh CJ 73 

03 

O O 03 03 

X 




CJ 

i 




O 




cn 

i 




cn 

4 

5 

6 

r- oo 

ON O X <N m TT in 

0 

1 

2 

m rr 

5 

6 

7 

8 

9 

o 

x cn x tp m 




X X X X X X 




X 

X X X rH X 



w 

X 

w 

E 

a 

< 

E 

E 

Z E 
E E 
E E 
O EC 


Eh 
X 
E 
&4 
2 
O 
E CJ 
Z 

3-H < 

X E 


E 

Z 

M 

X E 
I x 
U D 

9 2 

> E 


E 

cn 

O 

X 

u 


+ E 
O 
E E 

CJ X E E Q 

73 OEEEIZAE E 
C > X X Q E EC E X 
03 EmxQE+O cn Eh h 
SEE< cn EXOE 
EhEh^ZZEhE EMEXZ 
EEExxED + D X h cn 

UUfNCQCQUQcNQ <C CQ 


ox(Nn^mi£)M»^oxNn^in 


40 Dr. Dobb’s Journal, Number 71, September 1982 

392 




For the H-19 

Forth Screen Editor 


T his article describes an editor writ¬ 
ten in Forth Interest Group Forth, 
and used for editing Forth source 
programs. It uses the built-in editing 
capabilities of a Heath H-19 terminal. 
It was designed for use by students just 
learning Forth, and has several features 
that I consider particularly important for 
the novice. These are: 

1. The use of function keys and in¬ 
formation displayed permanently on the 
terminal to make reference to external 
documentation unnecessary; 

2. Use of terminal hardware for char¬ 
acter and line insertion and deletion, 
which gives immediate feedback to the 
user; and 

3. Inclusion of features designed to 
encourage and simplify program docu¬ 
mentation. 

I use Forth in several environments. 
At home, where I have a memory-mapped 
video display on my homebrew CP/M 
system, one of my first projects after 
getting Forth up from the fig listings 
was the creation of a screen-oriented 
editor to replace the simple fig editor. 
One of the joys of Forth programming 
became the ability to shove my program 
text around, knowing that what I saw on 
the screen was exactly what would appear 
in the final listing. 

One of the other environments in 
which I use Forth is at Hampshire Col¬ 
lege, where I am a professor. I soon got 
Forth going on the CP/M equipment that 
was available to me there. My nice editor 
wasn’t easily moved to that system, how¬ 
ever. The Heath H-19 terminal used at 
the College precluded direct manipulation 
of text in memory. The Heath terminal 
has a lot of built-in editing features of its 
own, but for lack of time to work on the 
problem I continued to use the fig editor. 
My inability to use the H-19’s character 
and line insertion and deletion features 
was a constant irritant, however. 

For an intensive January term course 
exploring the techniques used to imple¬ 
ment high-level interpreters and compil¬ 
ers, I wanted to get a number of students 
working with Forth. Although Forth is 
not sophisticated as high-level languages 

by A.S. Woodhull 

Albert S. Woodhull, School of Natural 
Science, Hampshire College, Amherst, 
MA 01002. 


go, it is a complete system, and concepts 
of operating systems, interpreters, and 
compilers are all part of Forth. A second 
reason for choosing Forth for this pur¬ 
pose was that all the inner workings of 
the Forth system are visible - Forth is 
like a plastic mechanical toy in which you 
can see the gears turning inside. 

The fig editor, like CP/M’s ED, uses 
various letters of the alphabet as com¬ 
mands. My experience in using ED, and 
my observations of student’s experiences 
with it, convinced me that better editing 
was needed. With neither of these editors 
do you see the effects of your command 
string until after you have pressed Re¬ 
turn. A skilled user of such a system can 
get good results, but for the novice it 
means working with an open users manu¬ 
al and frustrations that divert attention 
from the real task. 

The editor presented in Listing 1 is 
my response to the situation. It was put 
together in a fairly short period of time, 
but it incorporates what I learned from 
almost a year of use of my memory- 
mapped editor. I consider it a particular¬ 
ly good editor for student use, because all 
the documentation needed to make it 
work is actually on the terminal keys or 
on the H-19 screen at all times, and the 
effect of all actions are instantly visible. 

The Editor is invoked by typing 

n ED 

where n is the number of the first screen 
to edit. This clears the screen and sets up 
a border around the text area. Current 
documentation strings which identify the 
project, the programmer, and the date are 
then displayed and the user is asked if 
they are to be kept or changed. Following 
the response to this query the first screen 
to be edited is fetched. 

Figure 1 shows the appearance of the 
screen during an editing session. Since 
Forth works with screens of 16 lines of 
64 characters and the Heath terminal has 
24 lines of 80 characters plus a 25th line 
for status, there is room for presentation 
of additional information. The editor 
runs with the numeric keypad in its al¬ 
ternate mode, enabling the built-in edit¬ 
ing functions. The four arrow keys for 
cursor control are self-explanatory, but 
the insertion and deletion labels seemed a 
bit cryptic and are further explained on 
the screen. The 25 th line on the screen 
furnishes labels for the user-definable 
function keys. From left to right these 
functions are: 


I.D. — inserts the current project name, 
the user’s initials, and the date, on 
line zero. This line, often called the 
index line, is conventionally devoted 
to comments by Forth programmers. 
The relabelling does not affect the 
middle part of the line, so the char¬ 
acters in positions 20 through 47 are 
available to identify the individual 
screens. 

Border — the border around the text area 
gets messed up by deletions and in¬ 
sertions, and can be redrawn by this 
function. 

< Erase — this erases from the cursor to 
the left edge. 

IC — this terminates the character inser¬ 
tion mode. 

Erase> — this erases the right-hand end 
of a line. 

Quit — this quits without replacing the 
screen on the disk. 

SCR#— this assigns a new screen num¬ 
ber, where the edited screen will be 
stored on the disk after an End com¬ 
mand. This allows copying and mov¬ 
ing single screens. 

End — this terminates the edit and places 
the edited screen on the disk. 

Editing is itself a fairly simple pro¬ 
cess — text is typed at the position where 
it is wanted, using the cursor control keys 
and the insertion/deletion keys. In this 
mode, all characters except escape se¬ 
quences are immediately echoed to the 
screen. The program only has to filter out 
the escape sequences that correspond to 
commands. The sequence generated by 
the HOME key is also trapped and direct 
cursor addressing is used to put the cur¬ 
sor on its new “home” within the text 
area. 

Following interception of the code 
corresponding to the End key, the H-19 
is commanded to transmit the entire 
screen. Since the H-19 is not smart 
enough to transmit only part of the 
screen, this required some Forth words to 
ignore the superfluous parts of the screen. 
This is the only part of the editor where I 
found Forth’s ability to compile assembly 
language CODE routines necessary. 

After either an End or Quit com¬ 
mand, the functions of the left- and 
right-arrow keys and the HOME key are 
redefined. The operator is prompted to 
use the arrows to select either the next 
higher or lower numbered screen for edit¬ 
ing, or to use the HOME key to enable 


42 


Dr. Dobb’s Journal, Number 71, September 1982 

393 





entry of a new screen number where 
editing should recommence. Hitting any 
other command key (i.e., one generating 
an escape sequence) at this point termi¬ 
nates the editing session. 

The listing of the program should be 
easy to follow if you are used to Forth 
programs, which are (or should be) de¬ 
signed from the top down but listed from 
the bottom up. The last screen in the list¬ 
ing defines ED, the outer loop which does 
the setup and queries for the next screen 
to edit after each Quit or End. The next- 
to-last screen defines EDEXEC, which 
gets the screen to be edited from the disk 
and checks to see if keyboard input is an 
escape sequence to be processed further 
or a character to be echoed. Most of the 
Forth words defined in the editor are 
named with the Heath mnemonics for the 
H-19 escape sequences. The few CODE 
routines that are used are written as hex 
values to be entered into the Forth 
dictionary with comma words ( , and C,), 
so a Forth assembler is not needed. 

There are a few items in the listing 
that are not part of the standard fig- 
Forth 8080 version 1.1. I added a word 
? DECIMAL to check whether I was in 
decimal mode before attempting a disk Figure 1. 

access, since the CP/M disk routines used Appearance of screen during editing. | Box] indicates reversed video, 

by Forth do not respond gracefully when 
asked to fetch the 256th screen on a 

250K disk. I also have added the string I am willing to copy the Forth source 
routines described by Ralph Deane in code for this editor onto an IBM format 
DDJ #50. I extended these by adding a 8” single-density floppy disk for anyone 
word #IN which uses the SINP (string who will send a blank disk with a suitable 
input) word to fetch a string from the return mail package and adequate return 
keyboard which is then converted to a postage. *»j 

number. Those whose Forths differ from 
mine will find it easy to define similar 
words. 

I hope readers will find the ideas in (Listing begins on page 45) 

this editor useful. Although it does not 
do everything one might wish — in par¬ 
ticular it cannot move blocks of text 
smaller than a screen — it does put the 
considerable power of the H-19 terminal 
to good use. I am also convinced that a 
less-powerful editor that is easy to use 
may be more desirable for some purpose, 
particularly in teaching, than a power¬ 
ful editor the novice can use only with 
the help of a reference manual. Many of 
us who have become skilled in working 
with computers tend to forget the feel¬ 
ings of frustration created by the arbi¬ 
trary nature of the abbreviated com¬ 
mands to which our tools respond. 



Dr. Dobb’s Journal, Number 71, September 1982 
394 


43 








( STRING ROUTINES FROM DDJ «50 LEAVE ADDRESS OF FIRST BYTE AND 
( CURRENT LENGTH OF STRING ON STACK WHEN STPING NAME INVOKED ) 
( STRING DECLARATIONS SET MAXIMUM LENGTH , CREATE NULL STRINGS 
9 STRING DATES 3 STRING NAMES 20 STPING PPOJS 

32 STRING TEMPS 


ft 



CO 

Co ft 



t»M 

a 


\ 

ft Em 



Em 



CO 

ft 


Co 


ft 

ft 

xs 

ft ft 

ft 

ft 

: 

Co 

ft 

N. 

ft s: ft ^ 

ft 

ft 


co 

>. 

CD 

Co ft 

ft 

Em 



Em 

CM 

ft ft : 

3. : 

Co 





ft ft ft MS 

5: 

ft 




ft 

ft St: 

ft N1 

ft — 


ft 

ft in 

co 

ft ID X 

ft Co ft *• 

ft Co 

ft 

ft 

Em rM 

s; 

ft 3 ft 

ft ft Co 

ft 


ft 

S 


ID 5. O 

Co 

ft 6* 


ft 

ft 


ft TM o ft 

ft Co Vi 


CO 

Co 



ft Co 

Co Em ft ft 

is O 


Co 



ft Em 

ft ft 5. 

CM ft 

e 


Co 

co 

ft ft CO 

ft Co ft 

ft 



ft ft 

Em 

Co ft ft ft 

ft ft ft 

ft 

ft 


ft ft 

ft 

ft ft ft Em 

Em Vi ft 

Em Vi 


cn co j m id > co o' is 


ft ft • 
ft: ft 

Em CO 

Co •• ft ft; 

• v 

Em ft ft, 
ft • • ft 
ft ft ft ft 
ft ft 
ft ft ft 
ft ft ft w 
s; ft 
ft ft 

ft ft ft II 
ft ft is. 


s; Em ft ft 

ft ft ft ft ft ft 

ft ft ft ft ft 
ft ft ft ft ft 

ft ft ft - 

ft V* ft V* 

ft ft ft tS ft ft 

ft 3 ft ft Em 3 

ft ft ft 5; ft ft 

ft ft ft ft ft ft 

ft 

ft CM ft ft IS 

ft ri ft CO ft CM 

ft ft ft 

ft ft ft ft ft ft 

ft ft ft ft ft ft ■ 







Em 


ft 







Co 


Em 

ft 






ft 

ID 

• ft ft 

Co ft 

IS 

ft 

Co 



ft ft 

®. 

Co • ft ft 

ft ^c 

CM 

ft 

ft 


ft ft 

ft ft 

CM 

ft ft ft ft ft 

ft 

a 

Co 

6; 


Co ft 

ft 

a 

Em ft fci • ^ Co 

Ei Cl 



ft 


ft Em 

Em Co 


ft Co ft Cl ft ft ft ft 

Co ft 

CN 

ft 



ft 

Co S; 

CM 

ftftftEiftftClft 

ft ft 

00 

ft 

ft 


ft 


00 

ft ft Co E ft ft 

Co ^ 

ft 


ft 


ft ft 

ft 

\ 

00 Em £Xj ft Co ft ft 

ft 

CO 

ft 

* 


ft ft 

Em El 

CO 

CM ft Em ft ft 

co ft • 


ft 



Co 

ft 

is 

rM ft ft ft ft ft ft ft 

Co ft 

ft 

ft 

Co 


Co ft 

ft 

M*. 

ft ft ft ft ft ft Em 

ft ft 

00 

Em 

ft 


ft 

ft ft 

CD 

ft ft ft ft ft Em 

ft Em Cl 

Cm 

Co 

ft 


ft • 

Co ft 

CM 

Em ft ft ft ft ft 

Em ft ft 



ft 


ft ft 

ft ft 


ft^ftCoiftftft 

ft ft 

3 

• 



ft ft 

ft 


i i ft ft ft 

Em Em 

Co 

ft 



ft ft 

ft a. 

Co 

ft as ft s; ft ft 

ft ft ft 

ft 

ft 



Co S! 

ft 


Co ft Cl ft ft 

ft ft 


ft 


A 

ft 

5: 


ft ft uq ft ft Co ft 

ft 


ft 

ft 

1 

ft ft 

Co ft 


S. ft ft S; ft ft Co 

ft ft ft 


ft 

ft 

1 

ft ft 

ft ft 


ft ft ft ^ • ft 

Em s; ft 


ft 

ft 


ft ft 

ft ft 


ft rs: CO Co ft ft ft 

ft 



ft 

ft 


Em 


3. E- ft Co -Oft 

Cl Co ft 


Em 

ft 


ft ft 

ft 


ft Co ft E- ft Em 

ft ft Em 


ft 

ft 

ft 

ft ft 

ft ft 

Co* 

CoftftEMftftftCO 

Co ft ft 


ft 


ft 

ft 

ft 

ft 

^ Co Co ft ft Cl ft 

Ci ft ft 




c 

ft ft 

CO Em 

ft 

ft ft ft Cl ft Em 

ft 

ft 

• 

ft 

ft 

ft ft 

v; 


ft ft ft • ft ft 

Co ft ft 

ft 

E. 

ft 

ft 

'C 

ft ft 

ft 

ftiCoftftftfcift 

H ft ft 

H 

ft 

ft 


ft 

ft ft 

ft 

Em ft ft ft ft 


ft 

ft 

ft .. 


ft ft 

ft ft 

ft 

ft ft s; Em ft ft*- 

Em ft ft 

ft 

ft 

Co 


ft ft 


ft 

ft ft ft Co ft Ci ft 

ft ft ft 

ft 

ft 

ft 


ft ft 

■ Em 

ft 

ft ft ft ft Co ft 

Co Em ft 

5; 

ft 

ft ft 


>M ft 

ft ft 

ft 

ftOO^tCoftftCoft 

Co i 


ft 

ft Co i 

ft 

ft 

ft i 

ft 

ft II 

: Co: 

Co: 

co ft 


EmJ ft 



• Cl ft 


ft . ft in 


Vi 

Vi ft 


ft ft ft ft 
ft ft ft 
ft Cl ft 
ft ft ft 
ft H ft ft 
ft ft Em ft 
ft ft ft 
ft 

Co ft • s 
ft ft ft 
ft Cl ft Em 



ft 



ft ft 


o Si ci si 

0 5: m 


1 

' cj 




Co ft 




ft ft ft ft 


ft ft ft ft 

ft ft Co 





ft ft ft 


Em ft ft 

ft 



ft ft Ci ft 


ft Em ft; Em 

ft Em Co ft 



ft Co 


ft O ft 


Cl ft 

CD 



ft ft 



O ft 



'i ft 

co 

ft 


ft ID 



ft 



^ 'C 

X ft 

ft 


5; ft -• 

ft 

Co ft ft 

ft 

CD 



ft 

Co ft 


Co ft 

Co 

O 


ft 

ft ft ft Co 

O 





ft ft ft 


ft ft 

ft ID 

Em 


Co ID ft 

Em 


Em 




ft 

ft ft ft 


ft ft 

ft 

ft 


ft Co 


ft s: 

ft 

ID 



ft 

ft ft ft ft 



IS. 

ft 


ft IS Co 


Co N ft 

O 

ft ft 



ft ft 

ft ft 


ID ID 

ID 

ft ft 

ft 



O ft 

ft 


ft 


v: 

ft ID >M 



ft 

s: 

ft 



ft Em Em 


ft 5: 



CD 3 

ft : ft 


cs ts. 

IS ft 


Cj 



ft ft ft 

CD 

ft ft 


3 

ri ft 

Co ts .ft 



ft 

i0 »-* ft 




ft Cl • 

ID rM 


ft 

IS 

1 Co 

O 

ft 


ft 

IS 1 Co 

ft 




IS l 




ft 

ft 


ft 

CN ft ft 

ft 




cn tt; 




ft 





ft 




Cl 55 ft 




* 

w 





» w 




ft Cj ^ ft 

a w 















ri ri ri 


ft 

is th 

CN n S ID ID 

fM 

CD CD IS. ri 

in n j i/ 

O: S H <N 

CO J 

in id pm cd 

O' S H 

cn ci s in 










CO 





O 



Co 



_ 



CO 





co 


c ft ft ^ ft 
- ft co ft 
1 ft ft ft 

1 Co 6 i 3 
ft ft ft ft 

d Cj ft ft *«t 

S ^ ft 

i ft CO ft ft 
Co Co ft ft 

1 I'M ft Cl 

^ ft 5; _ ft 

^ ft ft 

i ft ft o- 
5 ft ft ft 
ft ft ft 

; ft Em Cl ft 
J ft ft ft ft 
1 ft ft 3 ft 
= ft ft ft ft 
t s; a, ft ft 
ft ft 

■* ft Co 
:> ft s: ft 

s: ft ft 

C i S; ft Et 
j ft ft 
< o ft ft ft 
0 ft CO ft Co 


ft Co Co 
ft ft ft 
. ft ft ft 
Co ft ft Em 
ft ft ft ft 
E-i Co ft ft 
s: co Co 

Em "C 

Co ft 00 
ft ft 

ft ft ft ft 
Ei H ft ft 
^ Em ft Em 
ft ft 

ft ft ft ft 

ft ft Em CO 

ft 

ft ft ft ft 
ft ft ft ft 
"t ft N3 
ft ft ft 
ft ft ft ft 
ft Ei s; 
ft ft ft 
ft Em ft Em 
% Em ft 
ft ft ft 
ft ft ft 


I CM (O J U) ID C* CO O' ® H CM W 


TJ S' 5 

III t 2 

a>£ % 
V o> g 

I •*- H 


CO 

O Em 


IS 

ft O 



O ft 


CD 

ft 


CN 

^ ft 



Co 



ft s; 


Co 

Oft 






o 



ft CO 

ft 


ft kM 

n: 


ft 

S 


ft CD 

ft 


o 

Co 


i ft 

ft 

ft 

O 

O 

ft 

Cl s ft 

CN. 

ft 

ft co o 


ft 

O Co ft 

ft 


Sk ft ft 

CO 

ft 

s; 5: ft 

O 

s: 

c>. 


o 

O . 

o 

ft 

Em ft CD 

Em 


O 


o 

-St il 

Co 

ft 

ft s; is 

o 


s ft 

ft 

Em 

5: ii 

o 

ft 

ft ft 

i - 

n: 

Co Co is 


Em 

ft ft ri 

Co ft •• •• 

Co 

o o 

Co ft 


e 

ft ft Em Cl 


co ft 

Co ft co ^ 


ft o ft 

Co ft ft O 


co 

s: ft ft 


ft Em 

ft 


co O ft 

ft ft ft 


o 

co 5 3 5 

ft 

ft 

ft ft 5: 5: 

o 

o 

O O ft ft 


IS 

Co 




ft 

IS 



ft 

ft 


ft ft 


IS 

\ 

ft ft Cl ft 




'“** c> 

— 



ft 

S 




N 

cd Cr 

ft Cl ft ft: 




^ ft 

CD 



o 

ft 


IS ri 

O’ 

CD 

CN O 

CO Cl Em ft 



ft 

C.1 Em 

CN 



ft 

Co 



ID 

CN 

ft 

5: ft ft 


ft 

ft 

ft ft ft 


Cl 


ft 



ft 5. 



ft ^ 



Cl 

c> 

Cl ft Co 


ft 

ft 

C) 

ft 


Cl ft 

ID 


CO O 

ft ci ft ft: 



5. C. O 

Co 

ft s: 

ft 


ft 


ft ft 

ri 

Co 

s: 5. ft 

CO S. ft ft 


^M C 


ft ft 

n: 

c c> 


ft 



ft ft 



ft O 

ft 


ft s: ft 


Em 


CO ft 

c 

Cl 

ft 





ft -c •• 

ft Cl Em 


ft ft ft 


ft Em ft 


ft ft 

ft 

Cl 

ft 


^ ft 

ft 


5. ft 


ft Q ft ft 


ft ft Cl 


Ci ft 

ft 

Sl 

Co 


ft Ci 

Em 


Co Em 

ft ft s; 

ft 

5: to ^ 


Co ft Co 


Co ft 

ft 


Cl 


^ ft 



ft ft Em ft 

ft Em 

ft 



ft Co ft 



ft 

Em 



ft ft 

ft 


Co ft ft 5. 

1 ft ft CO 


Em ft ft 


ft ft ft 


ft ft 


ft 

ft 



c> 


ft s; 5: ft 

Ift ft 


ft . Co 


ft Co 


ft ft 

ft 

ft 

ft 





ft ft to 

IEm ft 


Co tt ft 


ft 


Cl ft 

ft 

CO 

ft 


ft 

Co 



ft Em Co 


s: ft 


ft Em ft 


Em ^ 

ft 

ft 

Em 


ft 

ft 

o 

O O s: 


w ft 


Em ft n. 


Co Co 


ft 



ft ft 


Cl 

ft Co ft is 

ft ft ft 


ft t. 


ft s; 


ft ft 

ft 


Cl 


Cl 

ft 

Em 

Co Em CN Co ft ft 


•- Co ft 


ft ft Co 


ft ft 

ft 

ft 

Em 

ft 


Em 


ft 









ft 


ft 


ft 

ft 

ft Em W Em 



Em w w 





w 


O 

o 

. 

o 

O 







Ci 



ft 

ft 


ft 

ft 

ft 




5: 



Co 



ft 

Q ft^O 


Em 

Co ft ft 



ft 



ft 



ft 

ft O ft 

ft 


co 









5. 



ft: 

O 

Em 




4- 



ft 



ft 


ft ft . 

ft 

ft 

ft 






s; 



5: 

ft 

Ci 



ft 




IS 



ft 



ft 



s ^ 

ft 

5: 

Em •• CN 



m .« •• 



Co 



ft 

ft ft 

Co ft 

5: 

Cl 







ft 


• • 


ft 

ft 

Ci ft 

c 

Co 

ft Cl Em Em 

Em Em Em 

Em 

Em Em Em 

Em 

Em Em Em 

ft 

Em Em 


w 


Em 

ft ft 

ft 

c> 

ft ft ft ft 



ft ft 

Em 


ft 

ft 



Ci 

O 5. 5. 

5: 5: 5: 5: 5: 5: 5. 

5; 5; 3 S 


S 5: ft 


ft 

ft 

a- s: 




ft ft ft ft ft ft I 


ft Co Co 
ft ft ft ft 
ft: *n ft ft 

l-M C'. 

ft * 

ft ft Ei ft 
ft ft ft 
ft ft: ft ft 
ft ft ft ft 


ft Em Em 

ft ft ft 
ft ft 3 : 5 ; 
Em ft ft ft 
ft Em 

ft ft ft 
ft w ri ri 

CD ft Mj; 
M-* - 3 ft 

is i >< ft 

CN ft ft ft ft 

ft 


H;csTMCMn^ifliD>cooi8.ncMn^ i 

Co hhhhh 

Co 


3 m ft ft co m is 

ri IS ft s: 


ft Cl 

to 

ft ft CN ft 

• • 

A 


c-m id 3 r> 3 ft 

O' 3 3 ID 


ID MU 


to 


1 





CM 

ft 

ft ft 3 

n: 

1 


Em Em Em Em Em Em Em 

Em Em Em Em 


Em Em 

ft 

Em CO ft 

Co 




ft ft ft ft 

ft 

ft ft Em 

C> 

Cl ft ft 

ft 


ft 

5: 5: 5: 5: 5: 5: 5: 

5: 5: 3 5: 

o 

5: 5: ft 

ft 

ft ft CN 

ft 


ft 

ft ft ft ft ft ft ft 

ft ft ft ft 

Em 

ft ft 5: 


ft 


ft 

Ei 



ft 

ft 

ft 

s: ft 3 ft 

CO 

s; 

ft 

CQ CQ (Q CXI ft ft ft 

ft ft ft ft 

Ci 

ft ft 

ft 

ft ft Co 


3 

ft ft 

ri ri ri ri ri ri ri 


ft 

ri ri C 0 

ft 


00 

ft 







ft ft ft cxi 


ft 

3 

to ft ft ft ^ 

^ S 5 : ft 

CD 

ft 

ft 

ft 

ft 

ft 


ft ft ft O 5 : ft ft 

ft ft ft Ci 

CN ri 

Cl ft ft 

ft 

Em CO l 4- 

5 : 

Cl 

CO ri ft 


>< ft ft to 

IS l 

ft Cl ft 


ft ft Co Cl 

ft 



ftftftft t ftftftftftftft 

CN ft >< 

a w ft 

ft ft ft 


ft ft ft ft 

ft 


M t ft 









a w 

in ID r- CD oi IS ri 

CN CO 3 in 

ft IS ri 

cn co 3 in 

ID 

CM co CD IS ri CN 

to 

3 in 


ri «H 

ri ri ri ri 

Co 



ri ri ri 


ri ri 

ft 


Dr. Dobb’s Journal, Number 71, September 1982 


11 

395 








Ci 

k 


k 


k 

i 

k 



ft: k 

CO 

Co 

i 

4. 



Co 

la 


i 

k 



Si k a 

\ 

k 





k k i 

CO 

k 

i 

Co 



k CQ 1 

CM 

— k 

i 

k f" 



ft 


k 

i 

k 


• a 

k k k 

k 

'ft 

i 

k 'c 



k k ft 

Co 

k k 

i 

k co 

k 

k 

'ft i 4. 

'ft 

k k 

4- 

Cj k 

k 

k 

ft k 


'ft k 

i 

k ft: 

k 

Cj 

k Co 


k 

i 

k 

k 

k w k 


k Si 

i 

k k 

c 


'C k 


>< 

i 

k 

k 

k 


k CQ 

k, .* 
e* k k 
.3 CJ k k 
k k k 
k k ft: 


k C" k 

• ci e-, i. 

i ft. ft: k 

■ k • k 

l Cl k Co 

i k co ft. t'' 

+• Co 

i i i>m 

• Si ft o 

i Offlht; 

l Co ft: 

i tosti 

i Q; k ^ 

i k o Cj 

I BQ Cj Cl 

i 5. C ft: a: 

4- k ft: k 

• k k k 

I k ft; 

ik Cj co 

i k «Sl co it 

I k 

i k cj ft; CJ 

i k -«ft k 

i Ei k 

i Si oo c oo 

k Co 


ft; w r» 

O 

Ei 


O' >< 

* ri k >< 

i k o 

CM ft; k 


ft* k k k 
k k k 
CO k CJ 


CM 

Co 

Co k 4; 

th Co 



k k 

k 

k 

k 

k k k k 


Si 

k 

k k k 


k 

k 

oikk 

^ k 

k 

ft: 

k k Co Co 

k co 

Co 

co 

k k k 

k 'ft 


k 

k k k 

ft: k 


4: 

k " ii 

k 


'ft 

k co k Co 

4: v 


ft: 

k k k k 

Co 

ft: k 



: : s : 

k 


^ m; k Tj; ^ ^ ^c 
ft; Co ft; Co Co Co Co 
kft^QQCiQ 
ft: ft: ft: ft: ft: ft; ft; 


kcs.»HCMfOj-ma>r-a3<jitS' 

Co tH , 

to 


ft; Sri in n j i 

Co 

co 


k Ei cj 

k 

& >< 5: 
to »-i k ft; 

^ ' ft: CJ 
cm ft: k 


k 

k k k k 

Cj ft; co Co 

e- c» 5: 5: 

k Co Co 

k co co 

k co 

^ k 

o' k k co co 

t~~ n ft: so co co 

th i k 5: 5: 

cm ft: cm k o 


ft; is h (n n j 

Co 

co 


■o £ 
u t 

0) f 


t 2 

• k 

CJ) « 

!C - 


ft 4. 

1 k k 

i 

k k 


4. Cj ft ft • 

k ft: 

CO 

O Cj i k k k k 

k k 

ta 

Co Co 'ft k Co 

k 

CM 

k k k Co k 

k k 

X 

k ft: 'ft • k k 

Co So 


oj Ei ft Co ft ft 

k k 

CM 

k k Cj k 

k 

CO 

k Co k 'ft 4. ft: 

k 

\ 

Cj ft ft k ft k 

Co k 

CO 

ktoftrk k 

k k 

<a 


^ ft; fe; Cl 
k k k 'ft E-* 

'ft E* ft k 

Co k Cj k ft: co 4. 

k Co i ft; k 

cn co cj k ft; 

«-< Ei k Ei k Ei 

• Cj ft; os 'ft k 

ft: Co Sj k 

k k Co ftj Co 

k « ft: k ■ft 

ft: ^ k E Co t. ft 

k Cj 4. co ft; k 

k C k k k k 

k to k ft k 

k k k 

iktokkC 
k k ^ ^ k 

k cj ft 

k k ft k co ft: 

k co k k k co 

k k k k k 

Co k aj k 
co C k k i ft 

k ft: k k 

k k cj k co 

k k CJ ft: k k 

k Co k k 

k k Cj ft 

k X ft: k k Co 

k k k Si 

k k k 

cj k k k co k 

k Co co k 

Ei ft ft Si ft; 

k k k 

4: k k co . 

tQ k k k • 

k k cj k k 

ft ft Ei to ft k 

ft; Cj k Cj k 

k ft; k k k n: 

k k k co k 


Co 

k 

\ 

'ft k 

ft -• ft 

^ ft 

CO 

k Co 

k Co 

k 

IS. 

to Cj 

ft S* CJ 

k k 

\ 

k 

k k k 

c 

CO 

k a. 

Si k 

k ft: 

CM 

k 

k k k 

k Co 


k k 

Cj 

Cj 


ft- k 

k 4 - ft 

cc. k 

co 

Si 

k Cj 

k 

'ft 

k Co 

k 

k co 


Cj 

k 'i; k 

k k 


ft* k 

co k co 

Co k 


Cj 

k k Cj 

k >- 


to 

k k k 

cj k 


k k 

k k 



k 


ft 

k k 


k ft 


ft; 

k cn 

Co 0 

k 

k 


k 4- 

k 

k k 

to 

Cj 

k 

k k 

k 

k 

k 

Co CJ 

k k 

* 

k 

'ft 

to k 

k k 

to 


k 

k v; 

Si 

» k 

k 


k k 

k k 

Co 

k k 

k 

k cj k 

k 

k to 

to 

k 

k k 'ft •• 

k cj 

Co \ 

k k 

k 

'ft 'ft 

k ^ 

Cj aj 

Co k 


co + 
I •• k 
Ik k k 
Ik co co 
Cj k k 
k k co k 
k 


O ^ k k 

i k k 

k 



Ei 'ft 

4 

CO 

k 

k 

k 

• k 

k k 

k 


k k 

k 



k k 4: 



ftj 

k 

Si 

k Co to 

k k 

k 

k k k k 

k 




k 4; k 

k 

k • 


k 

CQ 

E, CO k 

to k 


k k k to 

to k 

O' 


CO 

k to k to 

to 

k ^ 

O' 

'ft 

\ 

\ Si 

\ Ei k 

C~i 

k k k k 'ft 

k 

CO *-l 

>< 

k 

k k 

k 

ft, k 

CP iH 

k 

k 

k k k 

k S> H 

ca t-n 



CS 1 

k 

aj 

k k 

ft: 

k 

IS 1 

*: Si 


k k 

k 

T-1 1 

k Si co k k 

k 

CM ft; 

ft: 

to 

to 


Ei k 

cm ft; 

k as 


k N 

Co 

CM ft; 


k k 






k to 


ft: 





4; k 4: 'c k 'c 

to k 

m w 





to Co 

* _ _ 





* w 


O' S. H (N n J to 

k ca 

tH CM 

co & m 

to N CO O' 8 rt 

CM CO 

•3- i/J 

k 

h cn n j 

5 

6 
7 

CO O' ® H 

CM CO 3 in 

k » 



Co 



H H 

r-i H 


k 



i-l r-< 

i-i i-i i-( T-t 

k 



to 






Co 





to 


Dr. Dobb’s Journal, Number 71, September 1982 






00 

£ 

c n 

3 




to 

00 


ft 






ft 

tX 


Ci 




<"X 


ft 

CN 


ft 






o* 

■ 


ft 




ft 









ft ft 


ft 

CN 


to 




ft ft 


ft 

03 


ft 




ft Ci ft 


ft ft ft 

V /*> 


ft 




ft ft 


ft ft ^ 

co 


S3 




ft 0 0 

/"X 

ft ft ft 

CS Ci 


ft 




ft ft 


ft ^ ft 

N ft 


CN 




ft ft 

ft 

ft 'C ft 

co ft 






ft ft ft 

ft ft 

to to 

CN • 


ft 




ft ft ft 

ft ft 

ft 

ft 


X. 

ft 

ft 

ft 

ft 5: 

ft ft 

ft ft 

Ii Ex 


ft 

ft 

ft 

ft 

ft 

ft ft 

ft ft 

ft ft 


ft 

ft 

ft 

ft 

ft ^ ft 


ft Ik to 

ft 

to 


ft 

ft 


■s: ft 

ft ft 

ft 


ft 

ft 

ft 

ft 

ft 

ft ft ft 

to to 

ft Ex • 

ii 

n: 

ft 




ft ft ft 

'C ■'£ 

ft ft ft 

ft 

ft 


CN 

3 

CD 

ft ft ft 

ft ft 

ft ft ft 


ft 

II 

ft 

ft 

ft 

ft ft ft 

ft ft 

ft O' ft 

Ex 



ft 

ft 

ft 




ft 

CN 

CO 







S3 


3 

ft 

ft 

ft 




. Ql 

ft 


ft 

ft 

ft 




ft * 

0* 

ft 







ft ft 

n: 

ft 

II 

II 

11 



Ex 

to S3 

ft 

ft 






ft 

ft 

ft 


3 

ID 

v-x 



ft 

ft ft 



in 

in 

m 



s>. 

ft II 

Ex 







•• 

n: ft 

to 

ft 

ft 

ft 

ft 



CO 

to 

S3 

ft 

S3 

S3 

S3 



ft ft 

to l 

5: 

ft 

ft 

ft 

ft 



ft £ 

ft ft 

ft 

ft 






5: ft 

ft 

to ft 

ft 





ft 

-Cl .. 

ft •* 

ft S3 ft to 

ft ft ft ft ft 

ft cm ft ft ft 

Si Si ft S3 

ft * ft So ft 

WO(N%N 
ft CN 

Cl ft ft 

ft I ft I CO 

CO to ft to bi 

C> ft St ft ft 


to X 
•• -* ft 
ft ft 
to ft c 
^ Q ^ 
ft ft ft 
S3 ft 
ft tx 

CN tX 

to A 
ft ft ft i 
ft ft ft i 
to ft S3 

ft ft ft 

ft CN 5: 


HCNDJinCDhCJlO 

ftftftftftftftftft 

ftftftftftftftftCi 


ft • 

Cl cn 
CO II 
to ft 
ft 

Ci Ex 

5 

ft; 

o 

ft, 

CM 

ft; ii 

co Ex 

Ex 

ft • 
ft ft 
ft; • 
ft 

O' * >< 
a) h h tj 
tX I II ft; 

CN b; to 


ft) ft: 
ft to 

ft Ii ft ft ft 
ft O ft ft ft 
t, ft S Cl Ci 
ft ft ft ft ft 
^ O (N ft ft 
ft 

ft + t-< tn 
kz ft to ft ft 
ft ft ft ft ft 
to Ex 

ft ft ft 
ft ft ft ft ft 


ft 

ft 

ft ft 
to ft 
ft ft 
ft 


ft 

Co ts tn m 
't ^ in in 
ft 

ft ft ft 
w S3 ft ft 
ft ft ft 


ft ft ft 
ft ft ft 
ft ft ft 
ft ft ft 
ft ft ft 

in r' o' 
ft ft ft ft 
ft ft ft ft 

ft ft ft ft 
ft ft ft 

ft 

ii ii n ft 
5: 

r- ts cn ft 
in m in 

ft 

ft ft ft n: 
ft ft ft Ii 
C> Q Q ft 


ft 

ft 

ft 

ft 

ft 


ft 

ft 

ft 

ft 


ft 

Ci 

O 

5. 



ft ft 


ft v: 


ft ft 


ft ft 

ft 

ft ft 

't 

ft S3 

ft 

ft ft 

— ft 

Ex 

* 

ft 

ft ft 

ft ft 

m ft 

ft ft 

ft Ex 

Ex ft 

ft 

ft 

ft ft 

to ft 

ft Ex ~ 

ft ft 

ft 

S. 

to «x. 

Ii ft 

tSl ft 

ft ft 

ft ft 

^ ft 

^ to 


ft ft 


ft 

Cl 

ft ft Ex 

ft ft 

5: ft 

ft ft 

ft ft 

Ci 

ft ft ft 

ft ft 

ft ft 

ft o 

ft ft 


ft ft ^ 

i Ex 

5: ft 

to ft 

ft 

ft S3 

ft ft 

o 

ft 

ft 

't 

ft ~ 

ft ii 


ft ft 

e 

ft ft ft 


b tj H 

to ft 


ft to 

ft 

cr> >< >< 

O' tx ft ft 
TH I ft Cl 
CN ft ft 


ft ft 
ft ft 

ft W ft 

to ft 

to to C3 

Cl ft 

ft e ft ft ft 
ft ft 
ID ft CO ft 
to ft 
e* Co ft 


ft 
ft ft 
ft Co 


. ft CO 


to to ft 5: ► 

ft ft to ft Cl ft 

ft ft ft 

ft ft Cl i 

ft 
ft 


ft ft 
ft ^ 

ft 5; 



.. 

Ex 



m 

ft 


CN 


S3 


CN 

Ii 

Cr 


* 

ft 




ft 

Ci 


CN 


Ex 


CD 




\ 


ft 


CO 


ft 

ft 

is 


ft 

CO 

\ 

i 



CD 

i 

Ci 

ll 

CN 

V 

ft 





co 


•• 

* 

3 

to 

to 

5: 



Si 

co 

ft 


c> 

to 



ft 


Ik 



ft 

to ft 


ft 

ft 

ft 


ft 

ft 

ft Cl 


ft 

Ex 

CO ft 



Ci 

ft 




II 



ft 




ft 

3 TX 



'j: 

3 


A 


ft 

ft 

1 

ft ft 

ft Cl 

Ci 

1 

O ft ft 

Ci 


Ex 

Ii ft 


ft : 
ft 

ft ft 
ft 5: 

co i 

: ft 


ft 
CO to 
3 ft 
ft 
ft 


ft 

■ 



ft s 

Ci IS 

.. 


ft -• 



o 

• ft 



ft 



ft 

ft ft ft 

to 


ft ft 

o 


ft 

ft S3 to 

ft 


ft to 

ft 



Ci to 

ft 


to to 

ft 



Ii 

ft 


to 

ft 


to 

ft ft 




to 

to 

Cl 

ft ft 

Cl 

ft 

W 10 

o 

ft 

ft 

ft Cl 

to 

Ci 

■t 

c» 

ft 


ft 

ft 

ft 

5: 


ft 

ID 

to ft 


ft 

ft 

ft ft Cl 


ft ft ft 

ft 

Ci 

to 

S3 ft ft 

ai 

ft ft ft 

ft 

ft 

ft 

Ex to 




Ex 


C» 

ft ft 




ft 

O' ft 

CN 

to ft 




S3 

»H ft 








mior'CDO'»HOinjin 


ft i 

to 

to 


IlNCOJiniOt'CDCTlSi 


cn co 3 in 


j in id f' o o' s. ■ 


ft sh in n j 


to 

ft 

ft 

ft 

ft 

ft 

ft 
ao ft 


Ex S 
to 
ft ft 
ft ft 


V. ft 

ft ~ Co 
ft "x 

^ ft ft 
ft 

i ■'t ft 

ft ft ft 
ft ft 
ft ft ft 
ft ft ft 
Ii ft v: 

ft ft to 
ft ft ft 
ft ft 

ft ^ ft 

ft CO ft 
ft ft 
ft ft CN 


ft V 
to 

03 ft 


ft Cl 
S3 

ft * 


ft ft 
ft ft 
O' ft 
ft ft 
ft 

Co ft 
ft 
ft ft 
i: 't 
ft ft 
ft ft 


ft 
ft 
ft 

to 

to 

Ex ft 

ft Cl 

ft 

ft ft Si 
ft ft 

ft 03 


Ci S 
3 

ft 


SI ft 
ft -3 ft 
ft 


00 ft 
ft 
CO ft 


to 

ft 


i-iCNcn^inujr-coaii 


tH 





~ Ex 

tX 



1 


ft 

CN 





ft ^ S3 

■ 



CD 


ft Ci 






ft ft to - 

CN 



ft 






ft 


ft to • 

'—. 



ft 


Ex to ft to 

CO 



ft 


^ Ci 

IS 






\ 

ft 

ft 

• 


Ii ft • to 

CO 

ft 


to 


Ci — to ft 

CN 

ft 




Ex C3 i 


ft 

ft 

CN 


to c; w Q 

Ii 

to 

5 

ft 


ft to 

to 

to 

ft 

«—• 


* ea 



ft 

• 


to ft -to 


ft 

Ex to to 


ft ft to ft ft 


ft 


ft 


Ex c. Cfc, ft 


Ex 

O' 

ft 


>X ft ^x b. to 



TX 

ft t" 


ft ft ft • ft Cl 


ft 

1 

to 


ft ft S3 



ft 





ft 


ft to 




ftl 




Ex - to 


ft 

ft 

ft ft 


ft ft rx Ex 


ft 

ft 

ft tX 


ft ft ft Ii ft: ^ 

to 

ft 


o 


Ci S3 

ft 


ft 

ft • 


ft - Ex C Ex 

ft 

Ci 

ft 

to to 



ft 

ft 


ft 


ft ft 

Ci 


c 


ft 


ft 

Ci 

ft 

Ci 

t-3 

ft ID Ex 

n: 

ft 

ft 


ft 

1 S3 *x to ft 

ft 

to 

ft 

» 

s. 

Ift ft 5. 


S3 

ft 


ft 

Ito - -Ex 

ft 


S. 

ft 


to to 

ft 

ft 

to 

3 


w _ __ 

ft 

ft 

ft 

ID 

• 

ft ft ft 

ft 


't 



tO XH 

to 


ft 

1 

in 

to 

to 

to 

ft 

1 • 

3 



ft 


Itj 

«-x 

ft to to to to 


ft 




ft in 


ft 


ft Ci 

• 

Cl n in cn cn 3 


Ex 


to to 

Ci ft Cl CN ft »x 


S3 






C, 



cn 



ft 


to 

to 

w to to to ft to 

ft 



to 



Ci 

ft 


>x m 


rx m cx ft cn 

Ex 

Cl 


ft Ci 



ft 

ft 


ft 


ft 

ft 

ft 


ft - 

to 

to 

ft 



O to 


ft 


ft 


ft 

CN 

>< 

O' 

to 


Ci i-x 

to 

ft 

»"« ft ft 


Ci 



1 ft 

tt; 


ft 


ft 

ft ft Ex 


Ci 


ft 




o 


ft 

w 



to 


to 


ft 

't 

5: 

ft 

to 

ft 

Cl 


ttsHCNn^minhcoo'® 
ft tH 

to 


cn co 3 in 











'-x 

^ -X '-x 

CN 

— ft 




CO 

to 

ft 

ft 


ft Ex ft 


ft 

ft 




ft 

ft 

C 

ft 

ft ft ft 

CN 

ft 

S3 



CN 

ft 

CO 

ft 

ft 

ft bi ft 

■ 

ft Ex 

Ci 




ft 

\ 

to 

ft 

ft Ex ci 


Ex to 





ft 

tg; 

to 

to 

to 

CN 

S3 

+ 



CN 

Si 

CO 

ft 

to 

to ft Ex 

CD 

ft 5. 




CD 

ft 




ft ft 


ft 

cs 



\ 


c 

to 

ft 

ft CO ft 

cn 

ft ft 

3 



cn 

ft 

ft 

ft 

Cl 

CO ft ft 

Sl 

Ci ft 




IS. 

to 

c 

xj; 

CO 

bi 

N 

Cl ft 

• 



N 

o 

ft 

ft 

ft 

ft ft ft 

CD 

ft ft 




CD 


s- 

Ex 

Ii 

CO O 

CN 

ft ft 

ft 



CN 

ft 




Ex to ft 


to 

S3 






to 

Cl 

ft 


» 

Ci 



Ii 

ft 

b.* 

ft 

ft 

ft to 

to 

to Cl 

* * 

• 


to 

ft 

ft 

ft 

ft 

ft ft to 


Ex ft 

+ 




Ex 

ft 

ft 

to 

Ci to ft 


ft Ex 

ft ft 

ft 





S3 


ft ft 


ft c, 

3 Si S3 

S3 



CO 

ft 

Ci 

CO 

to CD Cl 


i. c 

3 Ci Cl 

Cl 



Ex 

CO 


Ex 

ft ft 


ft ft 






ft 

Ci 


ft xj; 


ft 

•4-4- 




ft 


ft 

cn 

W co 


ft ft 





to 

to 


rX 

ft Ex 


ft 

ft (51 S 

®. 



'l 

ft 

Ci 

| 

ft bi 


CD Ex 

Si 3 3 

3 



ft 


ft 

ft 

to to 


»x 

Ci 





ft 

>x 


ft W 


ft 


• 



ft 

to 

ft 

Ci 

ft w 

to 

ft ft 

4- 



to 

to 


ft 

ft 

ft 

ft 

ft 

ft ft 

ft 


ft 

N. 




ft 

ft 

to 

ISi ft ft 

Si 


bi 

ft 

ft 

ft 


ft 

Cl 

>x ft 

3 Ci Cl 

Ci 


Cl 


Ex 

Ci 


ft 

ft 

't 




Cl 

■^c 

>< 

ft 

co 

ft 

ft 

ft ft 

to 4- 4- 

4- 


ft 


ft 

't 

to 



ft ft 

ft 



n; 

ft 


to 


Cl 

ft 


ft 3 3 

3 


ft 

b 

i 

ft 

w 

n: 


ID 

ft 3 3 

3 



ft 

i 

Cl 


ft 

ft 

ft TH 

Cl 



ft 

ft 

to 



ft e 

ft 


ft • • 

• 


ft 

to 

ft 

w 


Ex 

ft 

ft 

ft 



ft 

ft 

ft 



ft 4- 

ft 

to ft 

ft ft 

ft 


ft 

ft 

ft 



ft 

to 

ft Ex 

ft S3 S3 

ft 


to 


ft 



4- 

to 

Ex 

ci ci Ci 

Ci 


to 

N_, 






ft 

ft 





CO 



ft 


ft to 

■^4-4- 

4- 







4- ft 


ft ft 

ft 





ft 



ft ft 


to ft 

ft e& 

cs 




ft 



CO ft 


Ii 

■n: 3 3 

3 




ft 



ft to 


to 






to 



* ft ft 


ft to 


• 







CO CO ft 

ft 

ft ft 

ft 



ft 





IS ft ft ft 

ft 

Ii ^ 

ft ft ft 

ft 


CO 





in Ci Cl 

Ex 

O to 

Cl S3 S3 

ft 


Ex 




ft 

is ft 

H 

ft ft Cl 

Ci Ci 

Ci 


ft 



ft 

5: 

CO CO ft 

ft 

ft to ft 

4- 



Ci 



Ci 

ft 

IS 

ft 

CO to ft 

4- 4- 

4- 


ft 



ft 

ft 

1_| tX 


ft ft ft 

CN 









O' 

ft ft 

3 3 

3 


O' 

Ex 






ft Ci ft 

Ex 3 3 

3 


cn tx 

S3 





^ i 

ft Ci ft 

to 



tx i 

ft 





* ft ft 

ft ft 

ft 


A 

CN ft ft 






ft 


ft 


• 

ft 






i ■—- 

—• '— X/ 

ft 


1 

m w 







ftlSHCNtojinicr^cDoitS 
ft *-* 

to 


cn co 3 m 


ft ts tx cn co 3 m lor'coa'ts. 

ft tX 

to 


Dr. Dobb’s Journal, Number 71, September 1982 


47 

397 


(Continued on top of page 46) I End 





Z8000 Forth 


T his version of Forth was written as 
a tool with which to develop a 
Data Base Management System 
(DBMS). The DBMS forms the core of a 
special purpose communications system 
built around the Z8000 microprocessor. 
Two features of Forth make it particular¬ 
ly attractive for this level of systems pro¬ 
gramming. The first feature is Forth’s 
dual nature as an interpreter and compil¬ 
er. This makes program development and 
testing interactive and consequently fast¬ 
er than the usual development cycle of 
edit, assemble, link and test. The second 
feature is the ability to extend the Forth 
instruction set by adding operators, func¬ 
tions and data structures as needed. Ex¬ 
tensibility means that the language can be 
tailored to the application. The DBMS 
mentioned above is designed as a virtual 
machine whose instruction set is imple¬ 
mented as Forth words. Forth is used in 
this context as a high-level assembly lan¬ 
guage. 

The Forth described here includes 
many of the words in the Forth-79 stan¬ 
dard. The major omission is the word set 
dealing with mass storage access. Installa¬ 
tion of this Forth on a particular system 
using the Z8000 requires customization 
of the terminal I/O subroutines. However, 
there are only two subroutines involved, 
one that gets an input line from the con¬ 
sole, and another that sends an output 
line to the console. The details of register 
usage by these routines are given in the 
program listing. 

R. G. Loeliger motivated this Z8000 
Forth project with an outstanding presen¬ 
tation of the features of Forth-like lan¬ 
guages in his book Threaded Interpretive 
Languages. My design for Z8000 Forth is 
a descendant of the Z80 threaded inter¬ 
pretive language (TIL) discussed by 
Loeliger. In order to take advantage of 
addressing and stack manipulation fea¬ 
tures of the Z8000, I have written a dif¬ 
ferent address interpreter and modified 
Loeliger’s dictionary format. In particu¬ 
lar, since the Z8000 can use any of its 
general purpose registers as a stack point¬ 
er, it is convenient to treat the instruction 
register as a stack pointer and the Forth 
word definition as a stack. The address 

by Lou Odette 

Lou Odette, College of Engineering, 
Boston University, 110 Cummington St., 
Boston, MA 02215. 


interpreter just pops compilation ad¬ 
dresses and data as needed. In addition 
the indirect addressing mode provided by 
the Z8000 allows one less level of indirec¬ 
tion than used by Loeliger’s Z80 TIL. 
Thus, the compilation address of a word 
definition can be the address of executa¬ 
ble machine code. [This is called “direct 
threaded code.”] In the Z80 TIL, the 
compilation address contains a pointer to 
the machine code. [This is called “in¬ 
direct threaded code. ”] 

This article assumes familiarity with 
the Forth language and with some of the 
details of the implementation of the lan¬ 
guage on another machine. I expect that 
if readers have installed fig-Forth on their 
own machines they shouldn’t have too 
much difficulty following the source code 
presented here. Readers of Loeliger’s 
book should also be able to follow the 
source readily, and can use the Z8000 
code as an additional example of a 
threaded language. Details of the Z8000 
implementation of Forth are discussed 
below. 

Memory Allocation The language re¬ 
sides in the lower memory address space 
and occupies less than 3K bytes. System 
variables occupy memory beneath the 
system code. Data on the system data 
area can be accessed with Forth words 
like CONTEXT, which gets the address of 
the context vocabulary from the system 
data area and leaves it on the data stack. 
Since data is indexed by position relative 
to the start of the system data area, the 
order of the system data must be main¬ 
tained. 

When Forth is started, the initializa¬ 
tion routine initializes the data and re¬ 
turn stacks to the upper end of the ad¬ 
dress space, and the dictionary pointer 
is set to the first free byte after the lan¬ 
guage. The data and return stack build 
down in memory while the language 
builds upward. 

Dictionary Format Dictionary en¬ 
tries for each word in the language con¬ 
sist of a header and a code body located 
in contiguous memory locations. I use a 
header that is six bytes long for each dic¬ 
tionary entry:the first four bytes consist 
of the number of characters in the word 
name (one byte), followed by the ASCII 
code for the first three characters of the 
word. Thus, two words are the same if 
they have both the same number of 
characters in their names, and the same 
first three characters. The final two bytes 


of the header is the link field and con¬ 
tains the address of the header of the 
preceding dictionary entry. To construct 
headers and clearly identify dictionary 
entries in the program listing, I use the 
macro construct HEADER. 

The code body of each Forth word is 
located after its header. Since the address 
of the code body of a dictionary entry is 
the compilation address of the word, the 
compilation address is equivalent to the 
word definition. 

The first four bytes of the code 
body always contain executable machine 
code, while the remainder of the code 
body is either machine code or a list of 
the compilation addresses of other Forth 
words, intermixed with data. In a word 
definition, the first address available for 
the storage of compilation address and 
data (compilation address + 4) is called 
the parameter field address. In this im¬ 
plementation, compilation address and 
data in a word definition occupy two 
bytes of memory. 

The headers of the words in the dic¬ 
tionary form a linked list that is searched 
to locate the compilation address of a 
Forth word. The last dictionary entry is 
indicated by a zero link address, and a 
zero link signals the dictionary search 
algorithm that the search has terminated 
unsuccessfully. If the search routine suc¬ 
cessfully locates a Forth word in the dic¬ 
tionary, it places the address of the code 
body (compilation address) on the data 
stack. 

Address Interpreter The address in¬ 
terpreter interprets the sequence of com¬ 
pilation addresses in a word definition by 
executing the definition at each one. 
Since each compilation address in a defi¬ 
nition may point to another list of com¬ 
pilation addresses, a Forth word defini¬ 
tion has a tree structure. It is the job of 
the address interpreter to traverse the tree 
to the leaves, which are always machine 
code routines. In other words, only native 
machine code can be executed, and the 
address interpreter is used to control the 
order of execution of machine code rou¬ 
tines. 

As the address interpreter traverses 
the tree defined by the list of compila¬ 
tion addresses in a word definition, it 
maintains an instruction register that 
points to the next element in the current 
list (the compilation addresss of the next 
word to be executed) while execution be¬ 
gins at the compilation address of the cur¬ 
rent word. Execution begins when the 


48 

398 


Dr. Dobb’s Journal, Number 71, September 1982 


Z8000 program counter is set to the 
compilation address of the word. 

If the code body of a word contains 
machine code, execution proceeds. How¬ 
ever, if the code body is a list of com¬ 
pilation addresses and data, the code at 
the compilation address of the word calls 
a routine in the address interpreter called 
COLON. The COLON routine pushes the 
contents of the instruction register on the 
return stack and then loads the instruc¬ 
tion register with the parameter field ad¬ 
dress of the word. The address interpreter 
then executes the word whose compila¬ 
tion address is at the parameter field ad¬ 
dress. The effect is that COLON nests 
down to begin execution of a lower level 
routine. 

Threaded lists end with the address 
of the address interpreter routine SEMI. 
When SEMI is executed, the top of the 
return stack is popped to the instruction 
register, de-nesting one level. 

The address interpreter routine that 
executes the next compilation address is 
called NEXT. NEXT consists of two in¬ 
structions: (1) a pop instruction which 
uses the instruction register as the stack 
pointer to both increment the instruction 
register and move the compilation address 
to a Z8000 general register, and (2) an 
indirect jump to the compilation address 
of the word to be executed. Since ma¬ 
chine code routines are the leaves of the 
tree, they terminate with the instructions 
of the NEXT routine. 

Text Interpreter The text interpreter 
is a Forth word that serves as the system 
executive. My text interpreter follows 
Loeliger’s design: The interpreter brings 
in a line at a time from the terminal and 
parses the line a word at a time. Each 
word in the input line is a sequence of 
characters terminated by one or more 
spaces. The word is moved to the diction¬ 
ary in extended header format: the 
length of the character string (one byte) 
followed by the complete ASCII code for 
the string. 

Once the word is moved to the end 
of the dictionary, a search routine in the 
text interpreter searches the linked list 
of dictionary entry headers for the first 
header that matches the input word and, 
if a match is found, leaves the compila¬ 
tion address of the matching word on the 
data stack. The search routine always 
leaves a flag on the stack, indicating suc¬ 
cess or failure of the search. 

Following a successful search, the 
next word executed in the text interpret¬ 


Dr. Dobb’s Journal, Number 71, September 1982 


er depends on the system mode. If the 
system is in execute mode, the word is 
executed. If the system is in compile 
mode, and the word is not an immediate 
word, the compilation address on the 
data stack is added to the list of compila¬ 
tion addresses and data at the end of the 
dictionary, and the dictionary pointer is 
incremented. Immediate words are com¬ 
piler directives and are executed directly 
in compile mode. 

I use a separate vocabulary to imple¬ 
ment immediate words. This vocabulary 
is searched by the search routine if the 
word is not found in the context vocabu¬ 
lary and the system is in compile mode. 

If the search of the headers is unsuc¬ 
cessful, the text interpreter tries to con¬ 
vert the input word at the end of the dic¬ 
tionary into a number, using the current 
number base. If the number conversion is 
successful and the system is in execute 
mode, the number is placed on the data 
stack. When in compile mode, the num¬ 
ber, together with a literal handler, is 
placed in the list of compilation addresses 
and data being compiled. 

If a word cannot be found in the dic¬ 
tionary and cannot be converted to a 
number, the character string is passed to 
the terminal output routine, followed by 
a The text interpreter ceases to 

parse the present input line, and instead 
jumps back to execute the word that ac¬ 
cepts a new line from the terminal. 

Defining Words Defining words are 
used to make new words from previously 
defined words. The character “: ” (colon) 
is a defining word that, when executed, 
creates a dictionary header for the word 
following in the input stream, and 
then sets the compile mode. The compila¬ 
tion address following the new header 
contains the instruction CALL COLON. 
The remainder of the input character 
stream is then compiled by the text inter¬ 
preter as described above. 

New word definitions initiated by a 
colon are terminated by the immediate 
word “(semicolon). Since “is an 
immediate word it is executed in the 
compile mode. Execution of “encloses 
the compilation address of the address 
interpreter routine SEMI in the diction¬ 
ary and sets the system to execute mode. 
With the exception of “: ”, defining 
words return the system to execute mode 
on completion. 

Examples of other defining words 
are the words “VARIABLE” and 


“CONSTANT”. Like “:” these words 
create dictionary entries for the next 
word in the input stream. The compila¬ 
tion address of “CONSTANT” contains 
a call to a routine that pushes the con¬ 
tents of the parameter field address onto 
the stack. The compilation address of 
words created by “VARIABLE” contain 
a call to the address interpreter routine 
NEXT. This leaves the parameter field 
address on the data stack and causes the 
address interpreter to proceed with exe¬ 
cution of the next word. 

The word pair CREATE . . . DOES> 
is used in the definition of new defining 
words. When “CREATE” is executed, a 
header for the next word in the input 
character stream is added to the diction¬ 
ary. Words following CREATE in the 
defining word definition can be used 
to add data and compilation addresses of 
other words to the dictionary. Execution 
of DOES> places a call to a special ma¬ 
chine language routine in the compilation 
address of the new word. This causes the 
machine code to be executed when the 
new word is interpreted by the address 
interpreter. The machine language routine 
places the parameter field address of the 
word on the data stack and sets the in¬ 
struction register to the address of the 
word following DOES> in the defining 
word definition. 

Like any other word, a defining word 
containing CREATE . . . DOES > is a list 
of compilation addresses and data. How¬ 
ever, this list is divided into defining-time 
code (between CREATE and DOES>) 
and run-time code (words following 
DOES>). Defining-time code is executed 
when the defining word is executed. Run¬ 
time code is executed when the word 
built by the defining word is executed. 

Control Structures With the excep¬ 
tion of EXECUTE, the control words are 
immediate words that are executed dur¬ 
ing compilation. The effect of execution 
is to add both the compilation address of 
system directives and relative branch data 
to the list of addresses and data being 
constructed by the compiler. For exam¬ 
ple, during compilation of a word con¬ 
taining the word pair BEGIN . . . UNTIL, 
execution of BEGIN places the address of 
the next free dictionary byte on the data 
stack. Execution of UNTIL adds the com¬ 
pilation address of the system directive 
sysend to the dictionary, pops the data 
stack and subtracts the stack entry from 
the address of the next free dictionary 


49 

399 




byte. The result (two bytes) is added to 
the dictionary as a relative branch con¬ 
stant. 

When sysend is executed during the 
execution of the word containing BEGIN 
. . . UNTIL, the top of the data stack is 
popped and compared to zero. If equal 
to zero, the relative branch constant is 
subtracted from the instruction register. 
Otherwise the instruction register is in¬ 
cremented by two, and points to the list 
element after the branch constant. The 
sequence of words between BEGIN and 
UNTIL are thus executed until a non¬ 
zero number is left on the data stack at 
the end of the sequence. 

DO . . . LOOP, IF . . . THEN, and 
other control structures are implemented 
in a similar manner, using two levels of 
code: run-time code consisting of system 
directives, and compile-time code that in¬ 
serts the appropriate system directives 
and data into the word definition. 

The control word EXECUTE can be 
executed in the interpreter mode or 
compiled in a word definition. EXECUTE 
passes the top entry of the data stack to 
the address interpreter. Care should be 
taken to ensure that this number is the 
compilation address of a valid word. 

Conclusion I hope you find, in this 
example of the implementation of a 
threaded language, something you can use 
in solving a programming problem that 
interests you. Remember that the imple¬ 
mentation can (should?) be application- 
dependent. For the DBMS I mentioned at 
the beginning of this article, I wrote ma¬ 
chine code word definitions for the com¬ 
mon disk operations (read a record, 
write a record, index look-up, etc.) and 
used high-level definitions to implement 
the database Find, Create, Delete and 
other operations. When system develop¬ 
ment and debugging was complete, I 
removed the text interpreter and all 
headers, leaving one word each for the 
entry point and exit point of the program. 
The DBMS is thus implemented as a sin¬ 
gle word. 

To get an idea of the speed of this 
Forth, I coded the Eratosthenes Sieve 
benchmark (Knuth, 1969; Gilbreath, 
1981) and ran it on a Z8002 system at 
4MHz. The time for execution of ten 
iterations of the sieve program was 27 
seconds. This compares favorably with 
with Decus Forth on the PDP 11/70 


(11.8 seconds) and polyforth on the TI 
990/10 (60.2 seconds). 

I would like to thank Jim Gonzalez 
and Bernard Elliot for their helpful com¬ 
ments on the manuscript. 


References: 

Gilbreath, J. (1981). “A High-Level Lan¬ 
guage Benchmark.” Byte 6:9. 

Knuth, D. E. (1969). The Art of Comput¬ 
er Programming Vol. 2: Semi-Numerical 
Algorithms. Addison-Wesley, Reading, 
MA. 

Loeliger, R.G. (1981). Threaded Interpre¬ 
tive Languages. Byte Books, Peterbo¬ 
rough, NH. 


(Listing begins on next page) 


Z8000 Forth (Text begins on page 48) 


0000 0000 
0000 4D08 00DE R 
0004 4D08 00DC R 
0008 5E08 01 EE R 


NAME FORTH 
CLR BASE 
CLR START 
JP INIT 


FORCE A START 


* FORTH LANGUAGE FOR THE Z8000 MICROPROCESSOR 

* 

* Copyright (C) 1982 by Louis L. Odette 

* Permission is granted for individual, personal use in a non-commercial 

* manner. All commercial rights reserved. 

* 

* FORTH is a registered trade mark of FORTH, Inc., 2309 Pacific Coast 

* Highway, Hermosa Beach CA 90254 


* IN THIS SYSTEM: 

* Rl IS THE INSTRUCTION REGISTER AND MUST BE PRESERVED BY ALL ROUTINES 

* R14 IS THE RETURN STACK POINTER 

* R15 IS THE DATA STACK POINTER 

******************** 

* MACRO DEFINITIONS 

HEADER MACRO 

* USE: HEADER N,NFIELD,LFIELD 

* USED TO DEFINE A WORD HEADER IN THE DICTIONARY 

* N IS THE NUMBER OF CHARACTERS IN THE NAME 

* NFIELD IS THE FIRST THREE CHARACTERS OF THE NAME 

* LFIELD IS THE COMPILATION ADDRESS OF THE PREVIOUS ENTRY 

* 

DB &0 
DC 'fcl' 

DW &2-6 
ENDM 


NEXT MACRO 

* USE: NEXT IS THE ADDRESS INTERPRETER ROUTINE 

* THAT TERMINATES ALL MACHINE CODE WORDS 

* 

POP R2,@R1 
JP @R2 
ENDM 


000C 5E08 0000 
0010 5E08 0000 


HARDWARE DEPENDENT I/O ROUTINES 

EXTERNAL CONOUT 
EXTERNAL CONIN 


* The two hardware dependent routines used here are 

* (1) CONOUT - (output a line to the console) - expects R13 to 

contain the address of the output line, with the output 

line terminated with either OD(hex) or 04(hex). A 0D terminator 

* causes a carriage return-line feed to be sent to the terminal. 

* (2) CONIN - (input a line from the console) - gets an input line from the 


0061 




* 

console 

and places it in the input line buffer. CONIN 

0062 




* 

terminates the input line with the word 8080(hex), and 

0063 




* 

initializes the buffer pointer (BUFPNT in the system da 

0064 




* 

area) to 

the start of the input buffer. 

0065 




* 



0066 




******************** 


0067 




* 



0068 




* DATA 

AREAS 


0069 




* 



0070 




******* 

************* 


0071 




* 



0072 




* I/O BUFFERS 


0073 




* 



0074 

0014 

0064 


INBUF 

DS 100 

INPUT BUFFER 

0075 

0078 

0064 


OUTBUF 

DS 100 

OUTPUT BUFFER 

0076 




* 



0077 




******* 

************* 


0078 




* 



0079 




* SYSTEM DATA AREA: DO 

NOT CHANGE ORDER OF PARAMETERS 

0080 




* 



0081 

00 DC 

0002 


START 

DS 2 


0082 

00DE 

0002 


BASE 

DS 2 


0083 

00E0 

00 


MODE 

DB 0 

FLAG 

0084 

00 El 

00 


STATE 

DB 0 

FLAG 

0085 

00E2 

0002 


DICPNT 

DS 2 

DICTIONARY POINTER 

0086 

00E4 

0002 


CONXT 

DS 2 

ADDRESS OF VOCABULARY FOR SEARCH 

0087 

00E6 

0002 


CURRNT 

DS 2 

ADDRESS OF VOCABULARY FOR COMPILATION 

0088 

00E8 

0002 


BUFPNT 

DS 2 

ADDRESS OF NEXT WORD TO BE SCANNED 

0089 

00 EA 

0002 


STKPNT 

DS 2 

INITIAL ADDRESS OF SYSTEM STACK 

0090 

00 EC 

0A9A 


R CMPLER 

DW SEMI1-6 

ADDRESS OF LAST ENTRY IN COMPILER VOCABULARY 

0091 




* 



0092 

00 EE 

0000 

00 DC 

R SYSTEM 

EQU START 


0093 

00 EE 

0000 

0080 

TERM 

EQU %80 

STRING TERMINATOR 

0094 




******: 

************** 


0095 




* 




Dr. Dobb’s Journal, Number 71, September 1982 

40T 




-M O 


0096 

0097 00EE 09 
0098 00EF 52 
0099 00F7 OD 
0100 00F8 2D 
0101 00F9 5A 
0102 0125 OD 
0103 0126 03 
0104 0127 4F 
0105 0129 OD 
0106 012A 02 
0107 012B 3F 
0108 012C OD 
0109 012D 10 
0110 012E 53 
0111 013D OD 
0112 
0113 
0114 
0115 

0116 013E 93E1 
0117 0140 97F1 
0118 
0121 

0122 0146 97E1 
0123 
0126 
0127 
0128 
0129 

0130 014C 0750 
0131 014E 07AC 
0132 0150 07F0 
0133 0152 0760 
0134 0154 0686 
0135 0156 016E 
0136 0158 04OC 
0137 015A OOOE 
0138 015C 01C6 
0139 015E 0420 
0140 0160 0010 
0141 0162 02CA 
0142 0164 042C 
0143 0166 001A 
0144 0168 01A4 
0145 016A 042C 
0146 016C 001C 
0147 
0148 
0149 

0150 016E 5F00 013E R 
0151 0172 0856 
0152 0174 0474 
0153 0176 0474 
0154 0178 0368 
0155 017A 067A 
0156 017C 040C 
0157 017E 0024 
0158 0180 02B2 
0159 0182 0484 
0160 0184 040C 
0161 0186 001C 
0162 0186 0686 
0163 018A 02C4 
0164 018C 0474 
0165 018E 0368 
0166 0190 067A 
0167 0192 040C 
0168 0194 0008 
0169 0196 07C6 
0170 0198 0418 
0171 019A 0004 
0172 019C 07D4 
0173 019E 092C 
0174 01AO 04A4 
0175 01A2 0146 
0176 

0177 01A4 5F00 013E R 
0178 01A8 092C 
0179 01AA 0484 
0180 01AC 092C 
0181 01AE 0838 
0182 01B0 02B2 
0183 01B2 0484 
0184 01B4 0534 
0185 01B6 040C 
0186 01B8 OOOA 
0187 01BA 0946 
0188 01BC 02F0 
0189 01BE 0418 
0190 01C0 0004 
0191 01C2 08DA 
0192 01C4 0146 
0193 


* SYSTEM MESSAGES 
RSTMSG DB 9 

DC 'RESTART!' 

DB % OD 

SRTMSG DB 45 

DC 'Z8000-FORTH: COPYRIGHT (C) 
DB %0D 

OK DB 3 

DC 'OK* 

DB %0D 

NOTKNO DB 2 

DC '?' 

DB % OD 

STKMSG DB 16 

DC 'STACK UNDERFLOW' 

DB % OD 


1982 , 


L. L. 


ODETTE' 


* ADDRESS INTERPRETER 


COLON 

PUSH @R14,R1 

PUSH INTRUCTION 

REGISTER 


POP Rl,@ R15 

GET NEW INSTRUCTION 


NEXT 

DO NEXT 


SEMI 

POP Rl,@ R14 

NEXT 

GET INSTRUCTION 

FROM RETURN STACK 


************************** 

* TEXT INTERPRETER 


R OUTINT 

DW 

TYPE 

SEND MESSAGE TO CONSOL 

R 

DW 

QUERY 

GET AN INPUT LINE 

R 

DW 

ASPACE 


R 

DW 

WORD 

GET THE NEXT WORD IN THE INPUT STREAM 

R 

DW 

DROP 

DROP POINTER TO LENGTH BYTE 

R 

DW 

SERCHl 

LOOK FOR A MATCHING WORD IN THE DICTIONARY 

R 

DW 

SYSIF 

CONDITIONAL JUMP TO EXECUTE 


DW 

14 


R 

DW 

NUMBRl 

IF NOT FOUND SEE IF WORD IS A NUMBER 

R 

DW 

SYSEND 

CONDITIONAL JUMP TO ASPACE 


DW 

16 


R 

DW 

QUESTN 

IF NOT FOUND AND NOT NUMBER, ECHO WITH ? 

R 

DW 

SYSWHL 

UNCONDITIONAL JUMP TO TYPE 


DW 

26 


R 

DW 

EXEC 1 

EXECUTE OR COMPILE WORD 

R 

DW 

SYSWHL 

UNCONDITIONAL JUMP TO ASPACE 


DW 

28 



* WORDS USED IN TEXT INTERPRETER 


SERCHl 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 

R 


CALL COLON 

DW CONTXT 
DW FETCH 
DW FETCH 
DW SEARCH 
DW DUP 
DW SYSIF 
DW 36 
DW MOD 
DW CFETCH 
DW SYSIF 
DW 28 
DW DROP 
DW CMPLR 
DW FETCH 
DW SEARCH 
DW DUP 
DW SYSIF 
DW 8 
DW ZERO 
DW SYSELS 
DW 4 
DW ONE 
DW ST8 
DW CSTORE 
DW SEMI 


SEARCH ROUTINE 

GET ADDRESS OF CONTEXT VOCABULARY 


SEARCH VOCAB FOR HEADER MATCH 

DUPLICATE FLAG 

"IF" 

JUMP TO SEMI IF FALSE (SEARCH SUCCESSFUL) 
OTHERWISE SEE IF WE'RE IN COMPILE MODE 

"IF" 

JUMP TO SEMI IF IN EXECUTE MODE 

OTHERWISE DROP FLAG AND SEARCH COMPILER VOCAB 

GET ADDRESS OF COMPILER VOCAB 

SEARCH FOR HEADER MATCH 

DUPLICATE FLAG 

"IF" 

SET STATE FLAG ACCORDING TO SEARCH FLAG 
SET TO ZERO IF SEARCH SUCCESSFUL 
"ELSE" 

SET TO ONE IF SEARCH UNSUCCESSFUL 


EXEC 1 
R 
R 
R 
R 
R 
R 
R 
R 

R 

R 

R 

R 

R 


CALL COLON 
DW ST8 
DW CFETCH 
DW ST8 
DW COSET 
DW MOD 
DW CFETCH 
DW EQUALS 
DW SYSIF 
DW 10 
DW EXECUT 
DW STACK 
DW SYSELS 
DW 4 

DW COMMA 
DW SEMI 


EXECUTE ROUTINE 

GET SYSTEM STATE FLAG 

SET STATE FLAG TO ZERO 

GET SYSTEM MODE FLAG 

MODE = STATE ? 

"IF" 

IF EQUAL, EXECUTE COMP ADDR ON STACK 

TEST FOR STACK OVERFLOW 

"ELSE" 

IF NOT EQUAL, ENCLOSE TOP OF STACK IN DICT 


0194 01C6 5F00 013E R NUMBRl CALL COLON 

0195 01CA 0304 R DW NUMBER 

0196 01CC 040C R DW SYSIF 

0197 01CE 0018 DW 24 

0198 01D0 02B2 R DW MOD 

0199 01D2 0484 R DW CFETCH 


NUMBER HANDLING ROUTINE 

TRY TO CONVERT WORD AT END OF DICT TO A NUMBER 
"IF" 

IF SUCCESSFUL TEST SYSTEM MODE 

(Continued on next page) 


i. Dobb’s Journal, Number 71, September 1982 
22 


Z8000 Forth (Listing continued, text begins on page 48) 

0200 01D4 040C 

R 

DW SYSIF 

„ IF M 

0201 01D6 000A 


DW 10 


0202 01D8 0434 

R 

DW LITERL 

IF COMPILE, ADD LITERL+NUMB TO DICTIONARY 

0203 01DA 0434 

R 

DW LITERL 


0204 01DC 08DA 

R 

DW COMMA 


0205 01DE 08DA 

R 

DW COMMA 


0206 01E0 07C6 

R 

DW ZERO 

PUSH FALSE FLAG IF CONVERSION SUCCESSFUL 

0207 01E2 0418 

R 

DW SYSELS 

"ELSE" 

0208 01E4 0004 


DW 4 


0209 01E6 07D4 

R 

DW ONE 

PUSH TRUE FLAG IF CONVERSION UNSUCCESSFUL 

0210 01E8 0146 

R 

DW SEMI 


0211 

* 



0212 

******** 

****************** 


0213 

* SYSTEM 

1 SUBROUTINES 


0214 

* 



0215 

* START/RESTART 


0216 

* 



0217 01EA 0002 

CONVOC 

DS 2 

STORAGE FOR POINTER TO CONTEXT VOCAB 

0218 01 EC 0002 

CURVOC 

DS 2 

STORAGE FOR POINTER TO CURRENT VOCAB 

0219 

* 



0220 01 EE 7602 00EE R 

INIT 

LDA R2,RSTMSG 

LOAD ADDRESS OF RESTART MESSAGE 

0221 01F2 4D04 00DE R 


TEST BASE 

TEST BASE 

0222 01F6 EElB 


JR NZ,ABORT 

START IF ZERO 

0223 

* 



0224 01F8 210F FFFO 


LD R15,#%FFF0 

SET DATA STACK ADDRESS 

0225 01FC 6F0F OOEA R 


LD STKPNT,R15 

STORE STACK ADDRESS 

0226 0200 760C OABO R 


LDA R12,DP 

GET FREE MEMORY ADDRESS 

0227 0204 6F0C 00E2 R 


LD DICPNT, R12 

STORE IN DICTIONARY POINTER 

0228 0208 760C 09CO R 


LDA R12,COLONl-6 

GET ADDRESS OF LAST DICTIONARY ENTRY 

0229 020C 6F0C OlEA R 


LD CONVOC,R12 

STORE IN CONTEXT VOCABULARY 

0230 0210 6F0C OlEC R 


LD CURVOC,R12 

STORE IN CURRENT VOCABULARY ALSO 

0231 0214 760C OlEA R 


LDA R12,CONVOC 

GET ADDRESS OF CONTEXT VOCAB 

0232 0218 6F0C 00E4 R 


LD CONXT,R12 

STORE IN CONXT 

0233 021C 760C OlEC R 


LDA R12,CURVOC 

GET ADDRESS OF CURRENT VOCAB 

0234 0220 6F0C 00E6 R 


LD CURRNT,R12 

STORE IN CURRNT 

0235 0224 4D05 OODE R 0010 

LD BASE,# % 10 

MAKE HEX 

0236 022A 7602 00F8 R 


LDA R2,SRTMSG 

LOAD START MESSAGE 

0237 

* 



0238 022E 93F2 

ABORT 

PUSH @R15,R2 

PUSH ADDRESS ON STACK 

0239 0230 4D08 00E0 R 


CLR MODE 

CLEAR MODE AND STATE 

0240 0234 210E FFOO 


LD R14,#%FF00 

SET RETURN STACK 

0241 0238 7601 014C R 


LDA Rl,OUTINT 

SET INSTRUCT REG TO FIRST WORD OF TEXT INTERP 

0242 


NEXT 


0245 

* 



0246 

* CONWRT 


0247 

* 



0248 0240 8C68 

CONWRT 

CLRB RH6 

EXPECTS MESSAGE ADDRESS IN R12 

0249 0242 20CE 


LDB RL6,@ R12 

GET COUNT 

0250 0244 A9CO 


INC R12 

BUMP POINTER 

0251 0246 760D 0078 R 


LDA R13,OUTBUF 

GET BUFFER ADDRESS 

0252 024A BACl 06D0 


LDIRB @R13,@R12,R6 

TRANSFER MESSAGE TO BUFFER 

0253 024E 0CD5 0404 


LDB @R13,#%04 

SET END OF STRING 

0254 0252 760D 0078 R 


LDA R13,OUTBUF 


0255 0256 5F00 000C R 


CALL CONOUT 

PRINT IT 

0256 025A 9E08 


RET 


0257 

* 



0258 

* CRLF 



0259 

* 



0260 025C 760D 0078 R 

CRLF 

LDA R13,OUTBUF 

GET BUFFER ADDRESS 

0261 0260 0CD5 ODOD 


LDB @R13,#%OD 

CRLF 

0262 0264 5F00 000C R 


CALL CONOUT 


0263 0268 9E08 


RET 


0264 

* 



0265 

* PATCH 



0266 

* 



0267 026A 4C04 00E0 R 

PATCH 

TESTB MODE 

MODE=0 (EXECUTE) 

0268 026E 5E06 022E R 


JP EQ,ABORT 

YES 

0269 0272 6108 00E6 R 


LD R8,CURRNT 

GET ADDRESS OF CURRENT VOCAB 

0270 0276 2189 


LD R9,@R8 

RESET DICTIONARY POINTER 

0271 0278 6F09 00E2 R 


LD DICPNT,R9 


0272 027C A993 


INC R9 , #4 

GET LINK ADDRESS 

0273 027E 2199 


LD R9,@R9 


0274 0280 2F89 


LD @R8,R9 


0275 0282 5E08 022E R 


JP ABORT 


0276 

* 



0277 

* ASCWD 


0278 

* 



0279 0286 0DF9 0020 

ASCWD 

PUSH @R15,#% 0020 

PUSH SPACE ON STACK 

0280 028A 8D68 

ASCII 

CLR R6 

CLEAR HIGH WORD 

0281 028C 5B06 OODE R 


DIV RR6,BASE 

DIVIDE BY BASE 

0282 0290 OAOE OAOA 


CPB RL6,#10 

REMAINDER < 10 

0283 0294 E102 


JR LT,ASCII0 

YES 

0284 0296 OOOE 0707 


ADDB RL6,# 7 

OTHERWISE ADD OFFSET TO ALPHABET 

0285 029A OOOE 3030 

ASCII0 

ADDB RL6,#'0' 

CONVERT TO ASCII 

0286 029E 93F6 


PUSH @R15,R6 

PUSH ON STACK 

0287 02AO 8D74 


TEST R7 

QUOTIENT = 0 ? 

0288 02A2 EEF3 


JR NE,ASCII 

NO 

0289 02A4 97F6 

ASCIII 

POP R6,@R15 

RETIEVE CHARACTERS 

0290 02A6 2EDE 


LDB @R13,RL6 

PUT CHAR IN BUFFER 

0291 02A8 A9D0 


INC R13 

BUMP POINTER 

0292 02AA OAOE 2020 


CPB RL6,#%20 

WAS CHARACTER A SPACE 

0293 02AE EEFA 


JR NE,ASCIII 

NO 

0294 02BO 9E08 


RET 


0295 

* 



0296 

******* 

************* 



54 


Dr. Dobb’s Journal, Number 71, September 1982 

403 




0297 

0298 

0299 

0300 

0301 

0302 

0303 

0304 02B2 5F00 0460 R 

0305 02B6 0004 

0306 

0307 02B8 5F00 0460 R 

0308 02BC 0006 

0309 

0310 02BE 5F00 0460 R 
0311 02C2 000C 
0312 

0313 02C4 5F00 0460 R 

0314 02C8 0010 

0315 

0316 

0317 

0318 

0319 

0320 02CA 610C 00E2 R 

0321 02CE A9C0 

0322 02DO 26C7 

0323 02D2 E605 

0324 02D4 7602 0126 R 

0325 02D8 93F2 

0326 

0329 02DE 5F00 025C R 
0330 02E2 ABCO 
0331 02E4 5F00 0240 R 
0332 02E8 7602 012A R 
0333 02EC 5E08 026A R 
0334 

0335 02F0 4B0F OOEA R 
0336 02F4 5E02 0148 R 
0337 02F8 610F OOEA R 
0338 02FC 7602 012D R 
0339 0300 5E08 026A R 
0340 

0341 0304 8D68 

0342 0306 8DA8 

0343 0308 6108 00E2 R 

0344 030C 2080 

0345 030E A980 

0346 

0347 0310 0C81 2D2D 
0348 0314 8C88 
0349 0316 EE03 

0350 0318 AA80 

0351 03lA AAOO 
0352 031C A980 
0353 

0354 031E 0DF9 0000 
0355 0322 208E 
0356 0324 020E 3030 
0357 0328 E50B 
0358 032A OAOE OAOA 
0359 032E E505 
0360 0330 OAOE 1111 
0361 0334 E505 
0362 0336 020E 0707 
0363 

0364 033A 4B06 OODE R 
0365 033E E504 
0366 0340 0DF5 0000 
0367 
0370 

0371 0348 21FB 
0372 034A 590A OODE R 
0373 034E 816B 
0374 0350 2FFB 
0375 

0376 0352 A980 
0377 0354 FOlA 
0378 

0379 0356 8C84 
0380 0358 E603 
0381 035A 8DB8 
0382 035C 03FB 
0383 035E 2FFB 
0384 

0385 0360 0DF9 OOFF 

0386 

0389 

0390 0368 21F8 
0391 036A 6109 00E2 R 
0392 036E 2090 
0393 0370 0A80 
0394 0372 EEOE 
0395 

0396 0374 OAOO 0404 
0397 0378 E101 
0398 037A C003 
0399 

0400 037C A990 
0401 037E A980 
0402 0380 2098 


* SYSTEM WORDS (HEADERLESS) 
********** 


* SYSTEM VARIABLES 


MOD 

CALL SYS 

MODE 

* 

DW 4 


DPNT 

CALL SYS 

DICTIONARY POINTER 

* 

DW 6 


BFPNT 

CALL SYS 

BUFFER POINTER 

* 

DW 12 


CMPLR 

CALL SYS 

COMPILER 

* 

DW 16 


******* 

* 

* * * 


* SYSTEM I/O, NUMBER CONVERSION 

* 

, SEARCH 

QUESTN 

LD R12,DICPNT 

PQUESTION 


INC R12 

BITB @R12, # 7 

GET DICT POINTER AND STEP OVER LENGTH 


JR EQ,$+12 

IF BIT SET - WORD IS A TERMINATOR 


LDA R2,OK 

POINT TO "OK" MESSAGE 


PUSH @R15,k2 

NEXT 

CALL CRLF 

PUT MESSAGE ON STACK 


DEC R12 

BACK UP TO WORD LENGTH 


CALL CONWRT 

ECHO UNKNOWN WORD 


LDA R2,NOTKNO 

POINT TO UNKNOWN-WORD MESSAGE 

* 

JP PATCH 


STACK 

CP R15 , STKPNT 

COMPARE STKPNT 


JP LE , SEMI+2 

NO UNDERFLOW 


LD R15,STKPNT 

RESET STACK 


LDA R2 , STKMSG 

STACK MESSAGE TO WA 

* 

JP PATCH 


NUMBER 

CLR R6 

CLR RIO 

7NUMBER 


LD R8,DICPNT 

GET DICTIONARY POINTER 


LDB RHO ,@ R8 

GET COUNT 

* 

INC R8 

STEP OVER COUNT 


CPB @R8,#'-' 

CHECK FOR MINUS SIGN 


CLRB RLO 

SET SIGN PLAC FALSE 


JR NE,$+8 

SKIP IF NOT 


DECB RLO 

SET FLAG TRUE 


DECB RHO 

DECREASE COUNT 

* 

INC R8 

NEXT CHAR 


PUSH @R15,#0 

SET 0 RESULT 

NLOOP 

LDB RL6,@R8 

GET CHAR 


SUBB RL6 ,#% 30 

SUBTRACT NUMBER OFFSET 


JR MI , NOTNO 

CPB RL6 , #10 

NOT NUMBER IF <%30 


JR MI,NUMB 

CPB RL6,#17 

IF <10 ITS A DIGIT 


JR MI,NOTNO 

NOT A NUMBER IF <17 AND >10 

* 

SUBB RL6,#7 

SUBTRACT OFFSET 

NUMB 

CP R6,BASE 

COMPARE WITH THE BASE 


JR MI,$+10 

OK IF <BASE 

NOTNO 

LD @ R15 ,# 0 

SET FALSE FLAG 

* 

NEXT 



LD Rll, @ R15 

GET RESULT 


MULT RRlO,BASE 

MULTIPLY BY BASE 


ADD Rll,R6 

ADD NUM TO LOW ORDER WORD 

* 

LD @ R15,R11 

SAVE RESULT 


INC R8 

NEXT CHAR 

* 

DBJNZ RHO,NLOOP 

DECREMENT COUNT AND LOOP 


TESTB RLO 

TEST SIGN WHEN FINISHED 


JR EQ ,$ + 8 

PLUS 


CLR Rll 

MINUS 


SUB Rll ,@ R15 

COMPLEMENT 

* 

LD @ R15,Rll 



PUSH @R15 , #%FF 

TRUE FLAG 

* 

NEXT 


SEARCH 

LD R8,@R15 



LD R9,DICPNT 

GET DICTIONARY POINTER 


LDB RHO ,@ R9 

GET CHAR COUNT 


CPB RH0,@R8 

SAME AS IN FIRST HEADER? 


JR NE,NXTHDR 

NO? - GET NEXT HEADER 


CPB RHO,#4 

JR LT,NXTCH 

LENGTH> 4 


LDB RHO,#3 

NO - SET TO 3 

NXTCH 

INC R9 



INC R8 

BUMP POINTERS 


LDB RLO,@R9 

GET NEXT CHAR 


(Continued on next page) 


Dr. Dobb’s Journal, Number 71, September 1982 
404 


55 


Z8000 Forth (Listing continued, text begins on page 48) 


0403 0382 0A88 



CPB RL0,@R8 

COMPARE 


0404 0384 EE05 



JR NE,NXTHDR 



0405 0386 F006 



DBJNZ RH0,NXTCH 



0406 


* 




0407 0388 29F5 



INC @R15,#6 

IF MATCH POINT TO CODE ADDRESS 


0408 038A 0DF9 0000 



PUSH @R15,#0 

FLAG = 0 


0409 038E E808 



JR $+18 



0410 


* 




0411 0390 21F8 


NXTHDR 

LD R8,@R15 



0412 0392 A983 



INC R8,#4 

POINT TO LINK 


0413 0394 2187 



LD R7,@R8 

GET IT 


0414 0396 2FF7 



LD @R15,R7 



0415 0398 8D74 



TEST R7 

TEST LINK 


0416 039A EEE6 



JR NE,SEARCH 

IF NOT END - DO MORE SEARCH 


0417 


* 




0418 039C 0DF5 0001 



LD @R15,#1 

SET FLAG=1 IF END OF DICTIONARY 


0419 



NEXT 

DO NEXT 


0422 


* 




0423 03A4 5F00 013E 

R 

ENDC 

CALL COLON 



0424 03A8 08DA 


R 

DW COMMA 

STACK ON ENTRY: CNTRL ADDRS,JUMP ADDR 


0425 03AA 0938 


R 

DW HERE 



0426 03AC 0692 


R 

DW SWAP 



0427 03AE 0588 


R 

DW MINUS 



0428 03B0 08DA 


R 

DW COMMA 



0429 03B2 0146 


R 

DW SEMI 

STACK ON EXIT: NULL 


0430 


* 




0431 03B4 5F00 013E 

R 

DOC 

CALL COLON 



0432 03B8 08DA 


R 

DW COMMA 

ENCLOSE ADDRESS OF SYSDO DIRECTIVE 


0433 03BA 0938 


R 

DW HERE 

LEAVE ADDRESS OF NEXT FREE DICTIONARY 

ENTRY 

0434 03BC 0146 


R 

DW SEMI 



0435 


* 




0436 03BE 5F00 013E 

R 

BUILD 

CALL COLON 

MAKE A HEADER IN THE DICTIONARY 


0437 03C2 03E6 


R 

DW ENTRY 



0438 03C4 07F0 


R 

DW ASPACE 



0439 03C6 0760 


R 

DW WORD 



0440 03C8 0862 


R 

DW CRNT 



0441 03CA 0474 


R 

DW FETCH 

GET CURRENT VOCAB 


0442 03CC 0496 


R 

DW STORE 

UPDATE IT 


0443 03CE 0434 


R 

DW LITERL 



0444 03D0 0004 



DW 4 



0445 03D2 02B8 


R 

DW DPNT 



0446 03D4 04B2 


R 

DW PSTORE 

UPDATE DICTIONARY 


0447 03D6 08DA 


R 

DW COMMA 

ENCLOSE LINK TO LAST ENTRY 


0448 03D8 0434 


R 

DW LITERL 



0449 03DA 5F00 



DW %5F00 

PUT A CALL INSTRUCTION AT COMPILATION 

ADDRESS 

0450 03DC 08DA 


R 

DW COMMA 



0451 03DE 0434 


R 

DW LITERL 



0452 03E0 013E 


R 

DW COLON 



0453 03E2 08DA 


R 

DW COMMA 

ARGUEMENT OF CALL IS COLON 


0454 03E4 0146 


R 

DW SEMI 



0455 


* 




0456 03E6 5F00 013E 

R 

ENTRY 

CALL COLON 



0457 03EA 0862 


R 

DW CRNT 



0458 03BC 0474 


R 

DW FETCH 



0459 03EE 0474 


R 

DW FETCH 

LEAVE ADDRESS OF CURRENT VOCABULARY ENTRY 

0460 03F0 0146 


R 

DW SEMI 



0461 


* 




0462 03F2 5F00 013E 

R 

CAXCLM 

CALL COLON 



0463 03F6 03E6 


R 

DW ENTRY 



0464 03F8 0434 


R 

DW LITERL 



0465 03FA 0008 



DW 8 



0466 03FC 0578 


R 

DW PLUS 

COMPUTE ADDRESS OF CALL ARGUEMENT OF 

ENTRY 

0467 03FE 0496 


R 

DW STORE 

REPLACE WITH TOP OF STACK 


0468 0400 0146 


R 

DW SEMI 



0469 


* 




0470 0402 5F00 013E 

R 

SCODE 

CALL COLON 



0471 0406 0652 


R 

DW RFROM 



0472 0408 03F2 


R 

DW CAXCLM 

PUT RETURN STACK ENTRY IN CALL ARGUEMENT 

0473 040A 0146 


R 

DW SEMI 



0474 


* 




0475 


****** 

* * * * 



0476 


* 




0477 


* SYSTEM DIRECTIVES: USED TO 

IMPLEMENT CONTROL STRUCTURES 


0478 


* 




0479 040C 97F8 


SYSIF 

POP R8,@R15 

* IF 


0480 040E 8D84 



TEST R8 

TEST TOP OF STACK 


0481 0410 E603 



JR EQ,SYSELS 

DO RELATTVE JUMP 


0482 0412 A911 



INC Rl, #2 

OTHERWISE BUMP IR 


0483 



NEXT 



0486 


* 




0487 0418 2116 


SYSELS 

LD R6,@R1 

♦ELSE 


0488 041A 8161 



ADD Rl,R6 

BUMP INTRUCTION REG 


0489 



NEXT 



0492 


* 




0493 0420 97F8 


SYSEND 

POP R8,@R15 

♦END 


0494 0422 8D84 



TEST R8 

TEST FLAG 


0495 0424 E603 



JR EQ,SYSWHL 

DO RELATIVE JUMP 


0496 0426 A911 



INC Rl , # 2 

OTHERWISE BUMP IR 


0497 



NEXT 



0500 


* 




0501 042C 2116 


SYSWHL 

LD R6,@ Rl 

♦WHILE 


0502 042E 8361 



SUB Rl,R6 

BUMP INTRUCTION REG 


0503 



NEXT 



0506 


* 




0507 0434 13F1 


LITERL 

PUSH @R15,@Rl 

*# 



56 


Dr. Dobb’s Journal, Number 71, September 1982 

405 




INC Rl,# 2 


BUMP INSTRUCTION REG 


0508 0436 A911 

0509 

0512 

0513 043C 97E8 
0514 043E 97F7 
0515 0440 E803 
0516 

0517 0442 97E8 
0518 0444 2107 0001 
0519 0448 8178 
0520 044A 0BE8 
0521 044C 93E8 
0522 044E E5EE 
0523 0450 95E8 
0524 0452 A911 
0525 
0528 

0529 0458 95F8 
0530 045A 91E8 
0531 
0534 

0535 0460 7608 00DC R 

0536 0464 97F2 

0537 0466 0128 

0538 0468 93F8 

0539 

0542 

0543 

0544 

0545 

0546 

0547 

0548 

0549 

0550 

0551 

0555 0474 21F6 
0556 0476 2166 


0557 0478 2FF6 

0558 

0561 

0562 

0566 0484 21F6 

0567 0486 206D 

0568 0488 BlDO 

0569 048A 2FF5 

0570 

0573 

0574 

0578 0496 95F6 

0579 0498 2F67 

0580 

0583 

0584 

0588 04A4 95F6 

0589 04A6 2E6F 

0590 

0593 

0594 

0598 04B2 95F6 

0599 04B4 0167 

0600 04B6 2F67 

0601 

0604 

0605 

0609 04C2 97F6 
0610 04C4 2167 
0611 04C6 760D 0078 R 
0612 04CA 5F00 0286 R 
0613 04CE 0CD5 0404 
0614 04D2 760D 0078 R 
0615 04D6 5F00 000C R 
0616 
0619 
0620 

0624 04E4 95F6 
0625 04E6 97F5 
0626 04E8 A76F 
0627 04EA EE02 
0628 04EC BB51 0670 
0629 
0632 
0633 

0637 04FA 95F6 
0638 04FC 97F5 
0639 04FE A76F 
0640 0500 EE02 
0641 0502 BA51 0670 
0642 
0645 
0646 

0650 0510 95F6 
0651 0512 97F5 

0652 0514 A77F 
0653 0516 EE03 
0654 0518 2E5E 
0655 051A A950 
0656 051C F783 



*+LOOP 

GET INCREMENT FROM STACK 


SYSLOP POP R8,@R14 *LOOP 

LD R7, # 1 UNIT 

LP ADD R8,R7 

CP R8,@R14 COMPARE INDEX WITH TERMINAL COUNT 

PUSH @R14,R8 RESTORE INDEX 

JR MI,SYSWHL DO RELATIVE JUMP WHILE MINUS 

POPL RR8,@R14 ELSE CLEAN STACK 

INC Rl, #2 BUMP INSTRUCTION REG (STEP OVER JUMP) 

NEXT 


SYSDO POPL RR8, @ R15 *DO 

PUSHL @R14,RR8 MOVE INDEX AND TERMINAL COUNT TO RETURN STACK 

NEXT 


SYS LDA R8,SYSTEM *SYS 

POP R2,@R15 POP ADDRESS OF OFFSET 

ADD R8 , @ R2 ADD OFFSET 

PUSH @R15,R8 PUSH ADDRESS ON STACK 

NEXT 

* 

******************** 


* DICTIONARY WORD SETS 

* 

******************** 


* MEMORY REFERENCE WORD SET 

* 

HEADER 1,@XX,6, @ 

FETCH LD R6,@R15 

LD R6,@R6 REPLACE ADDRESS AT TOP OF DATA STACK 

mSv ! R15/R6 WITH w 0 * 0 AT THAT address 


HEADER 2, C@X,FETCH, 
CFETCH LD R6,@R15 
LDB RL5,@R6 
EXTSB RL5 
LD @R15,R5 
NEXT 


C@ 

REPLACE ADDRESS AT TOP OF DATA STACK 
WITH BYTE AT THAT ADDRESS, SIGN EXTENDED 
TO HIGH BYTE OF STACK WORD 


HEADER 1,1XX,CFETCH, ! 

STORE POPL RR6,@R15 

LD @R6,R7 STORE TOP-1 AT TOP ADDRESS 

NEXT 


HEADER 2,C1X,STORE, C! 

CSTORE POPL RR6,@R15 

LDB @R6,RL7 STORE LOW BYTE OF TOP-1 AT TOP ADDRESS 

NEXT 


HEADER 2,+!X,CSTORE, +! 

PSTORE POPL RR6,@R15 

ADD R7,@R6 ADD TOP-1 TO WORD AT TOP 

LD @R6,R7 

NEXT 

* 

HEADER 1,?XX,PSTORE, ? 

QMARK POP R6,@R15 

LD R7,@R6 GET WORD AT ADDRESS ON DATA STACK 

LDA R13,OUTBUF POINT TO BUFFER 

CALL ASCWD CONVERT NUMBER TO ASCII 

LDB §Rl3,#%04 END OF LINE 

LDA R13,OUTBUF 

CALL CONOUT PRINT CONVERTED NUMBER 

NEXT 


HEADER 4,MOV,QMARK, MOVE 

MOVE POPL RR6,@R15 GET COUNT AND DESTINATION ADDRESS 

POP R5,@R15 GET SOURCE ADDRESS 

BIT R6,#15 TEST SIGN BIT 

JR NE,$+6 MOVE WORDS IF COUNT IS POSITIVE 

LDIR @R7,@R5,R6 

NEXT 


CMOVE 


FILL 


HEADER 5,CMO,MOVE, 

POPL RR6,@R15 

POP R5,@R15 

BIT R6,♦15 

JR NE,$+6 

LDIRB @R7,@R5,R6 

NEXT 


HEADER 4,FIL,CMOVE, 
POPL RR6,@R15 
POP R5,@R15 


BIT R7.#15 
JR NE,$+8 
LDB @R5,RL6 
INC R5 


DJNZ R7,$-4 


CMOVE 

GET COUNT AND DESTINATION ADDRESS 
GET SOURCE ADDRESS 

MOVE BYTES OF COUNT IS POSITIVE 


FILL 

GET FILL BYTE AND COUNT 
GET START ADDRESS 


STORE BYTE 


(Continued on next page) 


Dr. Dobb’s Journal, Number 71, September 1982 
406 


57 


Z8000 Forth 

(Listing continued, text begins on 

page 48) 

06 57 


NEXT 


0660 

* 



0661 

******* 

************* 


0662 

* 



0663 

* COMPARISON WORD SET 


0664 

* 



0665 


HEADER 3,NOT,FILL, 

NOT 

0669 0528 0DF0 

NOT 

COM @R15 

COMPLEMENT NUMBER ON STACK 

0670 


NEXT 


0673 

* 



0674 


HEADER 1,=XX,NOT, 

= 

0678 0534 97F6 

EQUALS 

POP R6,@R15 


0679 0536 0BF6 


CP R6,@R15 

COMPARE TOP WITH TOP-1 

0680 0538 0DF8 


CLR @R15 

SET FALSE FLAG 

0681 053A EE01 


JR NE,$+4 


0682 053C 0DF0 


COM @R15 

SET TRUE IF THEY'RE EQUAL 

0683 


NEXT 


0686 

* 



0687 


HEADER 2,0=X,EQUALS, 

0= 

0691 0548 E8EF 

EQUALO 

JR NOT 

COMPLEMENT TOP 

0692 

* 



0693 


HEADER 1,<XX,EQUALO, 

< 

0697 0550 97F6 

LESS 

POP R6,@R15 


0698 0552 0BF6 


CP R6,@R15 

COMPARE TOP WITH TOP-1 

0699 0554 0DF8 


CLR @R15 

SET FALSE FLAG 

0700 0556 E201 


JR LE, $ + 4 


0701 0558 0DF0 


COM @R15 

SET TRUE IF TOP < TOP-1 

0702 


NEXT 


0705 

* 



0706 


HEADER 1,>XX,LESS/ 

> 

0710 0564 97F6 

GREATR 

POP R6,@R15 


0711 0566 OBF6 


CP R6,@R15 

COMPARE TOP WITH TOP-1 

0712 0568 0DF8 


CLR @R15 

SET FALSE FLAG 

0713 056A E901 


JR GE, $ + 4 


0714 056C ODFO 


COM @R15 

SET TRUE IF TOP > TOP-1 

0715 


NEXT 


0718 

* 



0719 

******* 

************* 


0720 

* 



0721 

* ARITHMETIC AND LOGICAL WORD SET 

0722 

* 



0723 


HEADER 1,+XX,GREATR, 

+ 

0727 0578 97F6 

PLUS 

POP R6,@R15 


0728 057A 01F6 


ADD R6,@R15 

ADD TOP TO TOP-1 

0729 057C 2FF6 


LD @R15,R6 

LEAVE RESULT ON STACK 

0730 


NEXT 


0733 

* 



0734 


HEADER 1,-XX,PLUS, 

- 

0738 0588 95F6 

MINUS 

POPL RR6,@ R15 


0739 058A 8367 


SUB R7,R6 

SUBTRACT TOP FROM TOP-1 

0740 058C 93F7 


PUSH @R15,R7 


0741 


NEXT 


0744 

* 



0745 


HEADER 2,1+X,MINUS, 

1+ 

0749 0598 29F0 

PLUS 1 

INC @R15 

INCREMENT TOP 

0750 


NEXT 


0753 

* 



0754 


HEADER 2,1-X,PLUS1, 

1- 

0758 05A4 2BF0 

MINUS1 

DEC @R15 

DECREMENT TOP 

0759 


NEXT 


0762 

* 



0763 


HEADER 2,2+X,MINUSl, 

2 + 

0767 05B0 29F1 

PLUS2 

INC @R15,#2 

INCREMENT TOP BY 2 

0768 


NEXT 


0771 

* 



0772 


HEADER 2,2-X,PLUS2, 

2- 

0776 05BC 2BF1 

MINUS2 

DEC @R15,#2 

DECREMENT TOP BY 2 

0777 


NEXT 


0780 

* 



0781 


HEADER 1,*XX,MINUS2, 

* 

0785 05C8 95F6 

TIMES 

POPL RR6,@ R15 


0786 05CA A165 


LD R5,R6 


0787 05CC 9956 


MULT RR6,R5 

MULTIPLY TOP BY TOP-1 

0788 05CE 93F7 


PUSH @R15,R7 

LEAVE RESULT ON STACK 

0789 


NEXT 


0792 

* 



0793 


HEADER 1,/XX,TIMES, 

/ 

0797 05DA 95F6 

DIVIDE 

POPL RR6,@R15 


0798 05DC A165 


LD R5,R6 


0799 05DE 8D68 


CLR R6 


0800 05E0 9B56 


DIV RR6,R5 

DIVIDE TOP-1 BY TOP 

0801 05E2 93F7 


PUSH @R15,R7 

LEAVE QUOTIENT ON STACK 

0802 


NEXT 


0805 

* 



0806 


HEADER 3,MOD,DIVIDE, 

, MOD 

0810 05EE 95F6 

MODO 

POPL RR6,@R15 


0811 05F0 A165 


LD R5,R6 


0812 05F2 8D68 


CLR R6 


0813 05F4 9B56 


DIV RR6,R5 

DIVIDE TOP-1 BY TOP 

0814 05F6 93F6 


PUSH @R15,R6 

LEAVE REMAINDER 

0815 


NEXT 


0818 

* 



0819 


HEADER 4,/MO,MODO, 

/MOD 

0823 0602 95F6 

DIVMOD 

POPL RR6,@R15 


0824 0604 A165 


LD R5,R6 



58 Dr. Dobb’s Journal, Number 71, September 1 982 

407 




0825 

0606 

8D68 


0826 

0608 

9B56 


0827 

060A 

AD7 6 


0828 

0829 

0832 

0833 

060C 

91F6 


0837 

0838 

0841 

0842 

0618 

0DF2 


0846 

0624 

27FF 


0847 

0848 

0851 

0852 

0626 

EEF8 


0856 

0632 

97F6 


0857 

0634 

07F6 


0858 

0859 

0862 

0863 

0636 

2FF6 


0867 

0642 

97F6 


0868 

0644 

05F6 


0869 

0870 

0873 

0874 

0875 

0876 

0877 

0878 

0879 

0646 

2FF6 


0883 

0652 

97E6 


0884 

0885 

0888 

0889 

0654 

93F6 


0893 

0660 

97F6 


0894 

0895 

0898 

0899 

0662 

93E6 


0903 

0904 

0907 

0908 

066E 

13FE 


0912 

0913 

0916 

0917 

067A 

13FF 


0921 

0922 

0925 

0926 

0686 

97F6 


0930 

0692 

97F6 


0931 

0694 

2DF6 


0932 

0933 

0936 

0937 

0696 

93F6 


0941 

0942 

0945 

0946 

06A2 

53FF 

0002 

0950 

06B0 

95F6 


0951 

06B2 

97F5 


0952 

06B4 

91F6 


0953 

0954 

0957 

0958 

06B6 

93F5 


0962 

06C2 

97F4 


0963 

06C4 

AB40 


0964 

06C6 

A1F6 


0965 

06C8 

8146 


0966 

06CA 

8146 


0967 

06CC 

2167 


0968 

06CE 

A165 


0969 

06D0 

AB51 


0970 

06D2 

BB59 

0460 

0971 

0972 

0975 

0976 

06D6 

2FF7 


0980 

06E2 

97F4 


0981 

06E4 

AB40 


0982 

06E6 

A1F6 


0983 

06E8 

8146 


0984 

06EA 

8146 


0985 

0986 

0989 

0990 

06 EC 

13F6 


0994 

06F8 

0DF4 


0995 

06 FA 

E601 


0996 

0997 

1000 

1001 

06FC 

13FF 




CLR R6 

DIV RR6,R5 

DIVIDE TOP-1 BY TOP 



EX R6,R7 

PUSHL @R15,RR6 

LEAVE QUOTIENT,REMAINDER 

ON STACK 

* 

NEXT 




HEADER 6,NEG,DIVMOD, 

NEGATE 


NEGATE 

NEG @R15 

NEXT 

REPLACE TOP WITH ITS 2'S 

COMPLEMENT 


HEADER 3,ABS,NEGATE, 

ABS 


ABS 

BIT @R15,#15 

TOP NEGATIVE? 



JR NE,NEGATE 

YES - NEGATE 



NEXT 




HEADER 3,AND,ABS, 

AND 


ANDO 

POP R6,@R15 

AND R6,@R15 

AND TOP WITH TOP-1 



LD @R15,R6 

NEXT 

LEAVE RESULT ON STACK 


ORO 

HEADER 2 ,QRX,ANDO, 

POP R6,@R15 

OR 



OR R6,@R15 

LD @R15,R6 

OR TOP AND TOP-1 

LEAVE RESULT ON STACK 


* 

NEXT 





* STACK 

* 

MANIPULATION 


* 

HEADER 2,R>X,ORO, 

R> 

RFROM 

POP R6,@R14 



PUSH @R15,R6 

PUT TOP OF RETURN STACK ON DATA STACK 

* 

NEXT 



HEADER 2,>RX,RFROM, 

>R 

TOR 

POP R6,@R15 



PUSH @R14,R6 

MOVE TOP OF DATA STACK TO RETURN STACK 

* 

NEXT 



HEADER 2,R@X,TOR, 

R@ 

RFETCH 

PUSH @R15,@R14 

COPY TOP OF RETURN STACK TO DATA STACK 

* 

NEXT 



HEADER 3,DUP,RFETCH, 

DUP 

DUP 

PUSH @R15,@R15 

DUPLICATE TOP 

* 

NEXT 



HEADER 4,DRO,DUP, 

DROP 

DROP 

POP R6,8 R15 

DROP TOP 

* 

NEXT 



HEADER 4,SWA,DROP, 

SWAP 

SWAP 

POP R6,@R15 

* 


EX R6,@R15 

PUSH @R15,R6 

EXCHANGE TWO TOP STACK ENTRIES 

* 

NEXT 



HEADER 4,OVE,SWAP, 

OVER 

OVER 

PUSH @R15,2(R15) 

COPY TOP-1 

* 

NEXT 



HEADER 3,ROT,OVER, 

ROT 

ROT 

POPL RR6,@R15 

POP R5,@R15 

PUSHL @R15,RR6 



PUSH @R15,R5 

ROTATE THIRD ITEM TO TOP 

* 

NEXT 



HEADER 4,ROL,ROT, 

ROLL 

ROLL 

POP R4,@R15 

DEC R4 

LD R6,R15 

ADD R6,R4 

GET COUNT 


ADD R6,R4 

POINT TO WORD TO BE ROTATED 


LD R7,@R6 

LD R5,R6 

SAVE WORD 


DEC R5,#2 

POINT TO NEXT HIGHER WORD IN STACK 


LDDR @R6,@R5,R4 

SHIFT STACK 


LD @R15,R7 

PUT N'TH ITEM ON TOP 

* 

NEXT 



HEADER 4,PIC,ROLL, 

PICK 

PICK 

POP R4,@R15 

DEC R4 

LD R6,R15 

ADD R6,R4 

GET COUNT 


ADD R6,R4 

POINT TO WOULD TO BE COPIED 


PUSH @R15,@R6 

COPY WORD TO TOP 

* 

NEXT 



HEADER 4,?DU,PICK, 

?DUP 

QDUP 

TEST @R15 

JR EQ, $ + 4 



PUSH @R15,@R15 

NEXT 

COPY TOP IF NOT ZERO 




(Continued on next page) 


Dr. Dobb’s Journal, Number 71, September 1982 


59 


Z8000 Forth (Listing continued, text begins on page 48) 


1002 





* 




1003 





* TERMINAL INPUT-OUTPUT WORDS 



1004 





* 




1005 






HEADER 2,CRX,QDUP, 

CR 


1009 

0708 

760D 

0078 

R 

CR 

LDA R13,0UTBUF 



1010 

070C 

0CD5 

0D0D 



LDB @R13,#%0D 



1011 

0710 

5F00 

oooc 

R 


CALL CONOUT 

DO A CARRIAGE RETURN (AUTO LINEFEED ASSUMED) 

1012 






NEXT 



1015 





* 




1016 






HEADER 4,EMI,CR, 

EMIT 


1020 

07 1E 

760D 

0078 

R 

EMIT 

LDA R13,OUTBUF 



1021 

0722 

97F6 




POP R6,@R15 



1022 

0724 

2EDE 




LDB @R13,RL6 



1023 

0726 

4CD5 

0001 

0404 


LDB 1(R13),#%04 

SET END OF STRING 


1024 

072C 

5F00 

OOOC 

R 


CALL CONOUT 



1025 






NEXT 



1028 





* 




1029 






HEADER 5,SPA,EMIT, 

SPACE 


1033 

073A 

760D 

0078 

R 

SPACE 

LDA R13,OUTBUF 



1034 

07 3E 

0DD5 

2004 



LD @R13,#%2004 

SET SPACE AND END-OF-STRING 


1035 

0742 

5F00 

OOOC 

R 


CALL CONOUT 

WRITE IT 


1036 






NEXT 



1039 





* 




1040 






HEADER 4,TYP,SPACE, 

TYPE 


1044 

0750 

97FC 



TYPE 

POP R12,@R15 



1045 

0752 

5F00 

0240 

R 


CALL CONWRT 

GET ADDRESS OF STRING AND WRITE 

STRING 

1046 






NEXT 



1049 





* 




1050 






HEADER 4,WOR,TYPE, 

WORD 


1054 

0760 

6108 

00E8 

R 

WORD 

LD R8,BUFPNT 



1055 

0764 

6109 

00E2 

R 


LD R9,DICPNT 

GET BUFFER AND DICTIONARY POINTERS 

1056 

0768 

97F6 




POP R6,@R15 

GET TERMINATOR FROM STACK 


1057 

076A 

0A0E 

2020 



CPB RL6,#%20 

SPACE? 


1058 

076E 

EE05 




JR NE,TOK 

NO - THEN START 


1059 

0770 

0C81 

2020 


IGNLB 

CPB @R8,#%20 

IGNORE SPACES IN BUFFER 


1060 

0774 

EE02 




JR NE,TOK 



1061 

0776 

A980 




INC R8 



1062 

0778 

E8FB 




JR IGNLB 



1063 

077A 

93F8 



TOK 

PUSH @R15,R8 

SAVE STARTING ADDRESS 


1064 

077C 

A860 



COUNT 

INCB RH6 

KEEP COUNT IN RH6 


1065 

077E 

A980 




INC R8 



1066 

0780 

0A8E 




CPB RL6,@R8 



1067 

0782 

E604 




JR EQ,ENDTOK 

FIND NEXT SEPARATOR 


1068 

0784 

0C81 

8080 



CPB @R8,#TERM 

COMPARE WITH TERMINATOR 


1069 

0788 

EEF9 




JR NE,COUNT 



1070 

078A 

AB80 




DEC R8 



1071 

078C 

A980 



ENDTOK 

INC R8 

BUMP POINTER 


1072 

078E 

6F08 

00E8 

R 


LD BUFPNT,R8 

RESET POINTER 


1073 

0792 

2E96 




LDB @R9,RH6 

WRITE COUNT AT START OF ENTRY 


1074 

0794 

21F8 




LD R8,@R15 

GET STARTING ADDRESS OF WORD IN 

BUFFER 

1075 

0796 

2FF9 




LD @R15,R9 

LEAVE ADDRESS OF LENGTH BYTE ON 

STACK 

1076 

0798 

A990 




INC R9 

BUMP POINTER 


1077 

079A 

A06E 




LDB RL6,RH6 



1078 

079C 

8C68 




CLRB RH6 



1079 

079E 

BA 81 

0690 



LDIRB @R9,@R8,R6 

MOVE THE WORD TO THE DICTIONARY 


1080 






NEXT 

DO NEXT 


1083 





* 




1084 






HEADER 5,QUE,WORD, 

QUERY 


1088 

07 AC 

5F00 

0010 

R 

QUERY 

CALL CONIN 

GET AN INPUT LINE FROM THE CONSOL 

1089 






NEXT 



1092 





* 




1093 





******************** 



1094 





* 




1095 





* MISCELLANEOUS WORDS 



1096 





* 




1097 






HEADER 4,BAS,QUERY, 

BASE 


1101 

07 BA 

5F00 

0460 

R 

BASEO 

CALL SYS 



1102 

07 BE 

0002 




DW 2 



1103 





* 




1104 






HEADER 1,0XX,BASEO, 

ZERO 


1108 

07C6 

0DF9 

0000 


ZERO 

PUSH @R15,#0 



1109 






NEXT 



1112 





* 




1113 






HEADER 1,1XX,ZERO, 

ONE 


1117 

07D4 

0DF9 

0001 


ONE 

PUSH @R15, # 1 



1118 






NEXT 



1121 





* 




1122 






HEADER 1, 2 XX,ONE, 

TWO 


1126 

07E2 

0DF9 

0002 


TWO 

PUSH @R15, # 2 



1127 






NEXT 



1130 





* 




1131 






HEADER 6,ASP,TWO, 

ASPACE 


1135 

07F0 

0DF9 

0020 


ASPACE 

PUSH @R15,#%20 



1136 






NEXT 



1139 





* 




1140 






HEADER 1,.XX,ASPACE, 



1144 

07FE 

97F7 



PERIOD 

POP R7,@R15 



1145 

0800 

760D 

0078 

R 


LDA R13,OUTBUF 



1146 

0804 

5F00 

0286 

R 


CALL ASCWD 

CONVERT WORD AT TOP OF STACK TO 

ASCII 

1147 

0808 

0CD5 

0404 



LDB @R13,#04 

SET END-OF-STRING 


1148 

08 0C 

760D 

0078 

R 


LDA R13,OUTBUF 



1149 

0810 

5F00 

OOOC 

R 


CALL CONOUT 

PRINT IT 


1150 






NEXT 



1153 





* 




1154 






HEADER 4,2DU,PERIOD, 

2DUP 



60 


Dr. Dobb’s Journal, Number 71, September 1982 

409 



1158 081E 13FF 

DUP2 

PUSH @R15,@R15 


1159 0820 13FF 


PUSH @R15,@R15 


1160 


NEXT 


1163 

* 



1164 


HEADER 5,2DR,DUP2, 

2DROP 

1168 082C 95F6 

DROP 2 

POPL RR6, @ R15 

DROP TOP TWO ENTRIES 

1169 


NEXT 


1172 

* 



1173 


HEADER 5,C0S,DROP2, 

COSET 

1177 0838 97F6 

COSET 

POP R6,@R15 


1178 083A 0C68 


CLRB @R6 

CLEAR BYTE AT TOP 

1179 


NEXT 


1182 

* 



1183 


HEADER 5,CIS,COSET, 

Cl SET 

1187 0846 97F6 

Cl SET 

POP R6,@R15 


1188 0848 0C65 0101 


LDB @R6,#1 

SET BYTE = 1 AT TOP 

1189 


NEXT 


1192 

* 



1193 

******* 

************* 


1194 

* 



1195 

* VOCABULARIES 


1196 

* 



1197 

* 



1198 


HEADER 7,CON,ClSET, 

CONTEXT 

1202 0856 5F00 0460 R 

CONTXT 

CALL SYS 


1203 085A 0008 


DW 8 


1204 

* 



1205 


HEADER 7,CUR,CONTXT 

, CURRENT 

1209 0862 5F00 0460 R 

CRNT 

CALL SYS 


1210 0866 000A 


DW 10 


1211 

* 



1212 


HEADER 11,DEF,CRNT, 

DEFINITIONS 

1216 086E 5F00 013E R 

DEFN 

CALL COLON 


1217 0872 0862 

R 

DW CRNT 

SET CURRENT TO CONTEXT 

1218 0874 0474 

R 

DW FETCH 


1219 0876 0856 

R 

DW CONTXT 


1220 0878 0496 

R 

DW STORE 


1221 087A 0146 

R 

DW SEMI 


1222 

* 



1223 


HEADER 4,FIN,DEFN, 

FIND 

1227 0882 5FOO 013E R 

FIND 

CALL COLON 


1228 0886 07F0 

R 

DW ASPACE 


1229 0888 0760 

R 

DW WORD 

READ NEXT WORD FROM INPUT BUFFER 

1230 088A 0686 

R 

DW DROP 

DROP ADDRESS OF WORD 

1231 088C 0856 

R 

DW CONTXT 


1232 088E 0474 

R 

DW FETCH 


1233 0890 0474 

R 

DW FETCH 


1234 0892 0368 

R 

DW SEARCH 

SEARCH CONTEXT VOCABULARY FOR WORD 

1235 0894 04OC 

R 

DW SYSIF 

"IF" 

1236 0896 0004 


DW 4 


1237 0898 07C6 

R 

DW ZERO 


1238 089A 0146 

R 

DW SEMI 


1239 

* 



1240 


HEADER 6,FOR,FIND, 

FORGET 

1244 08A2 5F00 013E R 

FORGET 

CALL COLON 


1245 08A6 07F0 

R 

DW ASPACE 


1246 08A8 0760 

R 

DW WORD 

GET NEXT WORD FROM INPUT STREAM 

1247 08AA 0686 

R 

DW DROP 

DROP ADDRESS 

1248 08AC 0862 

R 

DW CRNT 

GET ADDRESS OF CURRENT VOCABULARY 

1249 08AE 0474 

R 

DW FETCH 


1250 08BO 0474 

R 

DW FETCH 


1251 08B2 0368 

R 

DW SEARCH 

SEARCH FOR THE WORD IN DICTIONARY 

1252 08B4 040C 

R 

DW SYSIF 

ERROR IF NOT FOUND 

1253 08B6 0004 


DW 4 


1254 08B8 02CA 

R 

DW QUESTN 


1255 08BA 067A 

R 

DW DUP 

DUPLICATE COMPILATION ADDRESS 

1256 08BC 07E2 

R 

DW TWO 


1257 08BE 0588 

R 

DW MINUS 

SUBTRACT TWO TO GET LINK 

1258 08C0 0474 

R 

DW FETCH 


1259 08C2 0862 

R 

DW CRNT 


1260 08C4 0474 

R 

DW FETCH 

GET CURRENT VOCAB 

1261 08C6 0496 

R 

DW STORE 

SET CURRENT VOCAB TO LINK OF FORGOTTEN WORD 

1262 08C8 0434 

R 

DW LITERL 


1263 08CA 0006 


DW 6 


1264 08CC 0588 

R 

DW MINUS 

SUBTRACT 6 TO POINT TO HEADER 

1265 08CE 02B8 

R 

DW DPNT 


1266 08D0 0496 

R 

DW STORE 

RESET DICTIONARY POINTER 

1267 08D2 0146 

R 

DW SEMI 


1268 

* 



1269 

* 



1270 

******************** 


1271 

* 



1272 

* 



1273 

* DEFINING WORDS, COMPILER 

WORDS, CONTROL WORDS 

1274 

* 



1275 

* 



1276 08D4 01 


DB 1 


1277 08D5 2C 


DC ' , ' 


1278 08D8 089C 

R 

DW FORGET-6 


1279 08DA 97F6 

COMMA 

POP R6,@R15 


1280 08DC 6107 00E2 R 


LD R7,DICPNT 


1281 08E0 2F76 


LD @R7,R6 

PUT TOP OF DATA STACK INTO DICTIONARY 

1282 08E2 6901 00E2 R 


INC DICPNT,#2 

INCREMENT DICTIONARY POINTER 

1283 


NEXT 


1286 

* 



1287 


HEADER 5,ALL,COMMA, 

, ALLOT 

1291 08F0 97F6 

ALLOT 

POP R6,@R15 

qET COUNT 

1292 08F2 4106 00E2 R 


ADD R6,DICPNT 

ADD OFFSET 

1293 08F6 6F06 00E2 R 


LD DICPNT,R6 

UPDATE DICTIONARY POINTER 

1294 


NEXT 





(Continued on next page) 

Dr. Dobb’s Journal, Number 71, September 1982 


61 

410 





Z8000 Forth (Listing continued, text begins on 

page 48) 

1297 





* 



1298 






HEADER 5,LEA,ALLOT, 

LEAVE 

1302 

0904 

A9E1 



LEAVE 

INC R14,#2 

BUMP RETURN STACK 

1303 

0906 

13EE 




PUSH £R14,@R14 

SET INDEX = TERMINAL COUNT 

1304 






NEXT 


1307 





* 



1308 






HEADER 1,IXX,LEAVE, 

I 

1312 

0912 

13 FE 



I 

PUSH @R15,@R14 

PUSH LOOP INDEX ON DATA STACK 

1313 






NEXT 


1316 





* 



1317 






HEADER 1,JXX,I, 

J 

1321 

09 IE 

53FE 

0004 


J 

PUSH @R15,4(R14) 

PUSH LOOP INDEX OF NEXT OUTER LOOP 

1322 






NEXT 


1325 





* 



1326 






HEADER 5,STA, J, 

STATE 

1330 

092C 

5F00 

0460 

R 

ST 8 

CALL SYS 


1331 

0930 

0005 




DW 5 


1332 





* 



1333 






HEADER 4,HER,ST8, 

HERE 

1337 

0938 

53F0 

00E2 

R 

HERE 

PUSH @R15,DICPNT 

PUSH DICTIONARY POINTER 

1338 






NEXT 


1341 





* 



1342 






HEADER 7 ,EXE,HERE, 

EXECUTE 

1346 

0946 

97F2 



EXECUT 

POP R2,@ R15 

GET COMP ILARTION ADDRESS FROM STACK 

1347 

0948 

1E28 




JP @R2 

GO DO IT 

1348 





* 



1349 






HEADER 6,CRE,EXECUT, 

CREATE 

1353 

0950 

5F00 

013 E 

R 

CREATE 

CALL COLON 


1354 

0954 

07C6 



R 

DW ZERO 


1355 

0956 

0996 



R 

DW CNSTNT 


1356 

0958 

0146 



R 

DW SEMI 


1357 





* 



1358 






HEADER 5,DOE,CREATE, 

DOES> 

1362 

0960 

5F00 

013 E 

R 

DOES 

CALL COLON 


1363 

0964 

0652 



R 

DW RFROM 


1364 

0966 

03E6 



R 

DW ENTRY 


1365 

0968 

0434 



R 

DW LITERL 


1366 

096A 

0O0A 




DW 10 


1367 

096C 

0578 



R 

DW PLUS 


1368 

096E 

0496 



R 

DW STORE 


1369 

0970 

0402 



R 

DW SCODE 


1370 

0972 

93E1 




PUSH @R14,R1 

PUSH INSTRUCTION REG ON RETURN STACK 

1371 

0974 

97F2 




POP R2,@R15 

POP RETURN ADDRESS (OF CALL TO THIS ROUTINE) 

1372 

0976 

9721 




POP R1,@R2 

WORD THERE IS NEW INSTRUCTION ADDR 

1373 

0978 

93F2 




PUSH §R15,R2 

PUSH ADDRESS OF PARAMETER FIELD ON STACK 

1374 






NEXT 


1377 





* 



1378 






HEADER 8,VAR,DOES, 

VARIABLE 

1382 

0984 

5F00 

013E 

R 

VARIBL 

CALL COLON 


1383 

0988 

0996 



R 

DW CNSTNT 


1384 

098A 

0402 



R 

DW SCODE 


1385 





R 

NEXT 


1388 





* 



1389 






HEADER 8,CON,VARIBL, 

CONSTANT 

1393 

0996 

5F00 

013E 

R 

CNSTNT 

CALL COLON 


1394 

099A 

03BE 



R 

DW BUILD 

MAKE A PRIMITIVE HEADER 

1395 

099C 

08 DA 



R 

DW COMMA 

ENCLOSE TOP OF STACK 

1396 

099E 

0402 



R 

DW SCODE 


1397 

09 A0 

97F2 




POP R2,@R15 

GET ADDRESS OF THE CONSTANT 

1398 

09A2 

13F2 




PUSH @R15,@R2 

PUSH CONSTANT ON STACK 

1399 






NEXT 


1402 





* 



1403 






HEADER 10,VOC,CNSTNT 

VOCABULARY 

1407 

09 AE 

5F00 

01 3 E 

R 

VOCAB 

CALL COLON 


1408 

09 B2 

0950 



R 

DW CREATE 


1409 

09B4 

03E6 



R 

DW ENTRY 


1410 

09 B6 

08 DA 



R 

DW COMMA 

MAKE HEADER AND ENCLOSE ADDRESS OF LAST ENTRY 

1411 

09B8 

0960 



R 

DW DOES 


1412 

09 BA 

0856 



R 

DW CONTXT 


1413 

09 BC 

0496 



R 

DW STORE 

WHEN EXECUTED SET CONEXT VOCAB TO PARAM FIELD 

1414 

09 BE 

0146 



R 

DW SEMI 


1415 





* 



1416 






HEADER 1,:XX,VOCAB, 


1420 

09C6 

5F00 

013 E 

R 

COLONl 

CALL COLON 


1421 

09CA 

0862 



R 

DW CRNT 

CURRENT 

1422 

09CC 

0474 



R 

DW FETCH 


1423 

09CE 

0856 



R 

DW CONTXT 

CONTEXT 

1424 

09D0 

0496 



R 

DW STORE 


1425 

09D2 

0 3 BE 



R 

DW BUILD 

MAKE A PRIMITIVE HEADER 

1426 

09D4 

02B2 



R 

DW MOD 


1427 

09 D6 

0846 



R 

DW ClSET 


1428 

09 D8 

0146 



R 

DW SEMI 


1429 





* 



1430 





* 



1431 





******************** 


1432 





* 



1433 





* COMPILER VOCABULARY 


1434 





* 



1435 






HEADER 2,DOX,6, 

DO 

1439 

09 E0 

5F00 

013E 

R 

DO 

CALL COLON 


1440 

09E4 

0434 



R 

DW LITERL 


1441 

09E6 

0458 



R 

DW SYSDO 

PLACE COMPILATION ADDRESS ON STACK 

1442 

09E8 

03B4 



R 

DW DOC 

COMPILE AND PUT DICTIONARY ADDRESS ON STACK 

1443 

09 EA 

0146 



R 

DW SEMI 


1444 





* 




62 Dr. Dobb’s Journal, Number 71, September 






LOOP 


1445 






HEADER 4,LOO,DO, 

1449 

09F2 

5F00 

013E 

R 

LOOP 

CALL COLON 

1450 

09F6 

0434 



R 

DW LITERL 

1451 

09F8 

0442 



R 

DW SYSLOP 

1452 

09 FA 

03A4 



R 

DW ENDC 

1453 

09 FC 

0146 



R 

DW SEMI 

1454 





* 


1455 






HEADER 5,+LO,LOOP, 

1459 

0A04 

5F00 

013E 

R 

PLOOP 

CALL COLON 

1460 

0A08 

0434 



R 

DW LITERL 

1461 

0A0A 

043C 



R 

DW SYSPLP 

1462 

0A0C 

03A4 



R 

DW ENDC 

1463 

0A0E 

0146 



R 

DW SEMI 

1464 





* 


1465 






HEADER 5,BEG,PLOOP, 

1469 

0A16 

5F00 

013E 

R 

BEGIN 

CALL COLON 

1470 

0 AlA 

0938 



R 

DW HERE 

1471 

0A1C 

0146 



R 

DW SEMI 

1472 





* 


1473 






HEADER 5,UNT,BEGIN, 

1477 

0A24 

5F00 

013E 

R 

UNTIL 

CALL COLON 

1478 

0A28 

0434 



R 

DW LITERL 

1479 

0A2A 

0420 



R 

DW SYSEND 

1480 

0A2C 

03A4 



R 

DW ENDC 

1481 

0A2E 

0146 



R 

DW SEMI 

1482 





* 


1483 






HEADER 5,WHI,UNTIL, 

1487 

0A36 

5F00 

013E 

R 

WHILE 

CALL COLON 

1488 

0A3A 

0A5A 



R 

DW IF 

1489 

0A3C 

0146 



R 

DW SEMI 

1490 





* 


1491 






HEADER 6,REP,WHILE, 

1495 

0A44 

5F00 

013E 

R 

REPEAT 

CALL COLON 

1496 

0A48 

0692 



R 

DW SWAP 

1497 

0A4A 

0434 



R 

DW LITERL 

1498 

0A4C 

042C 



R 

DW SYSWHL 

1499 

0A4E 

03A4 



R 

DW ENDC 

1500 

0A50 

0A70 



R 

DW THEN 

1501 

0A52 

0146 



R 

DW SEMI 

1502 





* 


1503 






HEADER 2,IFX,REPEAT 

1507 

0A5A 

5F00 

013E 

R 

IF 

CALL COLON 

1508 

0A5E 

0434 



R 

DW LITERL 

1509 

0A60 

040C 



R 

DW SYSIF 

1510 

0A62 

03B4 



R 

DW DOC 

1511 

0A64 

07C6 



R 

DW ZERO 

1512 

0A66 

08 DA 



R 

DW COMMA 

1513 

0A68 

0146 



R 

DW SEMI 

1514 





* 


1515 






HEADER 4,THE,IF, 

1519 

0A70 

5F00 

013E 

R 

THEN 

CALL COLON 

1520 

0A74 

0938 



R 

DW HERE 

1521 

0A76 

06A2 



R 

DW OVER 

1522 

0A78 

0588 



R 

DW MINUS 

1523 

0A7A 

0692 



R 

DW SWAP 

1524 

0A7C 

0496 



R 

DW STORE 

1525 

0A7E 

0146 



R 

DW SEMI 

1526 





* 


1527 






HEADER 4,ELS,THEN, 

1531 

0A86 

5F00 

013E 

R 

ELSE 

CALL COLON 

1532 

0A8A 

0434 



R 

DW LITERL 

1533 

0A8C 

0418 



R 

DW SYSELS 

1534 

0A8E 

03B4 



R 

DW DOC 

1535 

0A90 

07C6 



R 

DW ZERO 

1536 

0A92 

08 DA 



R 

DW COMMA 

1537 

0A94 

0692 



R 

DW SWAP 

1538 

0A96 

0A70 



R 

DW THEN 

1539 

0A98 

0146 



R 

DW SEMI 

1540 





* 


1541 






HEADER 1,;XX,ELSE, 

1545 

0AA0 

5F00 

013E 

R 

SEMI 1 

CALL COLON 

1546 

0AA4 

0434 



R 

DW LITERL 

1547 

0AA6 

0146 



R 

DW SEMI 

1548 

0AA8 

08 DA 



R 

DW COMMA 

1549 

0AAA 

02B2 



R 

DW MOD 

1550 

0AAC 

0838 



R 

DW COSET 

1551 

0AAE 

0146 



R 

DW SEMI 

1552 





* 


1553 





****** 

***************** 

1554 





* 


1555 





* 


1556 

0AB0 

0002 



DP 

DS 2 

1557 





* 


1558 





* 


1559 





* 


1560 






END 

THERE WERE: 00000 ERRORS 




PLACE COMPILATION ADDRESS ON STACK 
ENCLOSE AND COMPUTE JUMP OFFSET 


+LOOP 


PLACE COMPILATION ADDRESS ON STACK 
ENCLOSE AND COMPUTE JUMP OFFSET 

BEGIN 

PLACE DICTIONARY POINTER ON STACK 

UNTIL 


PLACE COMPILATION ADDRESS ON STACK 
ENCLOSE AND COMPUTE JUMP OFFSET 


WHILE 


REPEAT 


PUT COMPILATION ADDRESS ON STACK 
ENCLOSE AND COMPUTE JUMP OFFSET 


IF 


PLACE COMPILATION ADDRESS ON STACK 
ENCLOSE AND PUT DICTIONARY POINTER ON STACK 

SAVE A WORD IN DEFINITION FOR JUMP OFFSET 


THEN 


COMPUTE JUMP OFFSET FOR "IF" 

STORE IN OFFSET WORD 

ELSE 

PUT COMPILATION ADDRESS ON STACK 

COMPILE AND PLACE DICTIONARY ADDRESS ON STACK 

RESERVE A WORD FOR JUMP OFFSET 


FIRST ENTRY OF COMPILER DIRECTIVES 


ENCLOSE ADDRESS OF SEMI IN THE DEFINITION 
SET EXECUTE MODE 


NEW DICTIONARY ENTRIES ARE BUILT STARTING HERE 


COMMON LENGTH= 0000 


End Listing 


Dr. Dobb’s Journal, Number 71, September 1982 


63 


16-BIT SOFTWARE TOOLBOX 


by Ray Duncan 


Just after watching Doc Dobb’s na¬ 
tionally televised speech from the NCC in 
Texas, I was surprised to receive a collect 
call from the Old Man himself. “The lack 
of public domain software for 16-bit 
microcomputers is appalling!” remarked 
our Fearless Leader. “No one wants to 
shell out that kind of money just so they 
can stare at the operating system’s sign- 
on message. I want you to institute a 
regular column in DDJ that will address 
the needs of 16-bit system users and 
promote the discussion and interchange 
of software.” 

Luckily, after laying down that 
sweeping and rather alarming mandate, 
the good Doctor had to hang up to go out 
on a house call (someone had choked on 
an Apple) and I was left to my own de¬ 
vices. After brooding on the subject for 
a while I have decided on the following 
objectives for this new column: 

1) Implement, test, and publish a set 
of utility subroutines for the common 
16-bit processors. Besides serving as 


building blocks for larger programs, these 
will demonstrate the relative merits of 
the different assembly languages and ma¬ 
chines. 

2) Translate the most useful pro¬ 
grams from the CP/M-80 User’s Group 
into 8086 code and place them in the 
public domain for further refinement by 
our readers. 

3) Review commercial 16-bit soft¬ 
ware products, particularly applications 
and language systems produced by the 
smaller companies who can’t afford to 
spend zillions of dollars on advertising. 

All of the above is tentative, and I 
will be grateful for any suggestions and 
contributions. 

Toolbox Installment #1 

The accompanying listing contains 
two useful subroutines that we have to 
reinvent on every new microcomputer so 
that the program can interact with the 
operator. This version is in Standard Intel 
8086 assembly language. 


ASCBIN converts a number repre¬ 
sented as an ASCII string (which presum¬ 
ably was read in from the console) into 
its binary equivalent. The field to be pro¬ 
cessed may contain the following charac¬ 
ters: [0123456789+-.] . The routine is 
passed the beginning address of the ASCII 
field, and returns the two’s complement 
value, the number of digits after the deci¬ 
mal point (if any), and the address of the 
first non-convertible character. 

BINASC performs the opposite func¬ 
tion, converting a signed binary number 
into an equivalent ASCII character string. 
The subroutine is passed the two’s com¬ 
plement value and the address of a six- 
byte buffer where it can build the output, 
and returns the actual first byte address 
and length of the resulting string. SBj 


(Listing begins on next page) 


64 


Dr. Dobb’s Journal, Number 71, September 1982 

4(3 




CP P 4J I* 

C 0 — 

•H L (J 0 

L ■— — X 0 

P *4- TJ 4 2 

0 

0 0 o L 

UVH4J 0 

- £ c £ 

L V H H U 

0 C P 
E-H L 14J 

3 0 11 0 0 

c a > 2 - * 

c 0 | 

* 4 - - 0 c H* - 
OT) U (-H *l 

C I n 

TJ 3 C P 0 x 

C O O 3 ® n 

0 p c a 0 i-i 


C 0 — 

L 0 

L ® U 

• p 

2 0 0 

0 ••* P 

c O' 

0 0 C 

L L 

0 3 

a jc 0 p 

e 0 l 0 

3 6 0 L 

n - P 
-00 TJ 

0 0 0 C 

C >s L 0 


jQ 0 
- p >0 

— xx>-£xxx 

00-QXJ00-QTJ 


0 

0 O' 

L L C 

0 0 - ~ 

£ l 0 
6 0 P P 
3 P 0 — 
C > CP 

H M -H 

> — TJ 

L >0 U 
0 cd m 
c p <x 

— Q TJ 

JD TJ C 

0—0 

TJ 0 — 

0 0 3 C 

*-« c l n cp 

O' TJ — 

U -hTJ O 0 

CD 0 0 P "** 

I I 

0 

P x — 

<x a) 


TJ TJ 

0 0 

P > 

L L 

0 O' 0 

> C 0 
C - 0 
0 UL L 

u c p a 

— 0 

*4- L 0 
0 P P L 

0 0 0 
0 P 

0 P £ 0 

0 3 P — 
l a a» cp 

TJ P C 0 
TJ 3 0 L 
* O - 

L 

I I 0 

£ 

►-« X +1 

(D (JO 


0 C 

TJ U 3 
0 0 L 

V- — U 0 0 

o - 0 > 0 

P — P — — > 

0 2 3 > p - 

a — 0 p 

•O U P TJ CP — 

C 3 0 0 

— 0 0 0 C 0 

•*« n a 

P O L — 0 

C| 0 — 3 p 

3 X *4- 0 — — 

U - 0 

Q. TJ P > 0 

0 2 0 - -X 

O 0 0 C p 0 

- C 3 - - 6 


P O L 

0 P 0 

C P 

P — * 4 - . 

V. TJ 3 

0 C L £ 

a 0 0 

TJ O TJ 3 ' 

L — — C P L 

0 > - - £ 

a — >- 0 o p 

a tj £ e — j 

3 ® tj cl - 

P 0 L 3 

L — TJ *-• 

0 D -h 0 •-* -X I 

0 > -x U U i 

- CM - 0 CD 0 . 

U K) TJ 6 <1 n i 


0 L c 

- P 0 L 

> *j 3 

• TJ 0 P 

I TJ 0 0 

• 0 L L 


X X X X 

tj £ 0 U 


Ox x O 

— 0 TJ 

- - CM 

X x 0 X X XX 

£ 0 £ 0 TJ D TJ 


n 0 

- - CM 

■- 0 X X 0 
• u U 0 £ 


0 0 

mW P 

XX0— >xxx 
0 0 D 0-0 U £ *0 


u > o. a n cp a a p 
0OOEC0OO0 
TJEO-u^caav. 


£ £ £ 

0 0 0 > 

3 3 3 0 

a a a € 


> 0 O' l > TJ 

O L C 0 0 — TJ 

6 0 -n C x TJ 0 


y>u n a 0 u > u a a p 
0 0 C k. C Ok.C0OcOO0 

tj e - o *n ao^TJE — aaL 


o 

Q 

Q 

CM 

n U. CM CD 

UJ 

Q 

u n o q 

m - as 

ujajCQomrvaj<xn 

h* * UJ 

^tDDincDNu.ininu 

1 O Q 

LLOnn>OCD<lCDU 

n n n 


o o o 

ooooooooo 

o o o 

ooooooooo 


o 

o 

>0 

o 

CM K> o O' 

in in m m 

o uj u. o 

«r <r «r in 

o o o o 

o o o o 


o 

o 

€ O CM GD CM 

o O O Q Q 

ffl at O' rv n 

fflOMiW 

O' U 111 O CC 

m m in >o ~o 

o o o o o 

ooooo 


O — 

-« u u. 

id od - a in 

<* a) <*■ o n 

O' <z u q u. 

M) O O >0 >0 

o o o o o 

o o o o o 


Q 

CM 

o m <* 

u o o 

GDGGO'UJ'O — GQ^n 

noNtOfininu 

HNt>0N4fflUQ 

NNNNNNNNN 

ooooooooo 

ooooooooo 


>1 

?£ 


-Ico 

00 

O o 
(/>« 

<.£ 




0 


— 

0 


E 


— 

0 


GD 0 


u 

— 


GD P 


CD 

p 


O 0 



— 


GD > 



— 


N 0 


N- 

— 


>0 0 


0 

p 


GD L 



□ 


O u 


0 



© - 


0 

GD 


r 


0 

GD 


L 

> 

L 

o 


0 * 

L 

TJ 

GD 


N- L 

0 

TJ 

\ 


0 

C 

0 

>0 


0 P 

— 


GD (h 


0 0 

Oi 

1 

O N 


C L 



GD 


- 0 

0 

— 

* £ 


P £ 

p 

CD 

P 


3 0 



TJ 


0 -1 

— 


-«4 


L CM 

— 


0 2 


£ -CD 

u 


- 0 

CP 

3 C O' 

CD 

■a 

P CP 0 

0 0 - 

<T 

£ 

— 0 

0 

U 


P 

p a 

U 

> C - 

P 

— 



P 3 — 

L 

2 



- Q 

0 




— >> 

> 

— 



— > — 

C 

— 



P 0 3 

0 

0 



□ oc n 

u 

U 


I • L TJ TJ 

: TJ 0 0® 

C £ L > 

■3 U 0 L 

• Op 00 

P 0 0 — 0 

l L — U 0 

p - £ l 

c s- - 0 a 

. p — 

I 0 *+■ k. 0 

a o 0 o« l 

* >00 

I 0 C — P 

i 0 0 0 H- Ip 

: e 0 u - 

I - L I C O' 

I U TJ C 0 0 

I 0 TJ 0 H L 

I TJ 0 C P 

U L 

I ® ® 

L £ 
►4 — p 

CO Q O 


0 

0 

u 

0 

cn pa 

« C 0 

-• 3 

•4- LOO 

0 u c 

C 2 

0 0 0 0 TJ 

- L C U 0 

P 0 0 0 0 

UP — — 

00 0 a 

L •— N P 

— 0 — • 0 * 

TJ 0 — U 0 

l 00 a. 

L •— TJ 

0 0 P C n 

0 > - TJ 0 — 

- 0 C c U 0 

U 0 h ( «u 


P 

L 

0 

> 0 

CP P 

o a o - 
u p cr 


n 

> •— •— 

0 -X 0 0 

0 0 <-* i-J 


P TJ - 
L 

0 CP L 

0 0 0 _ 

6 L L • 
■*< P 3 
U 0 C 

0 P 0 

TJ C 0 L 
3 -x 
o 0 C 
- U E 


£ I 0 
- - p CM - 

xxxx >*£ - £ 

TJ££U £000 


£ £ 0 £ 
tj • 0 l > a n u a 0 

— 3300 ECCC3 
u a a x e u n — n a 


a a . . * £ 

• x O O' 4 -xO xx 

0100 - u - 0£*4 0 u 

p cm p to 

>•£ >'£•— — — £ XXJ - £-£ X X X X XX 

£0£00000U0000000TJTJ£U 


0 0 

a aNUTjawLaa a tj£>^tj 
6nEcCOEcOEE£E0CUO3tJL 
Un U -n - — Unx^iU^U^0 x E 6 <t 0 


0 * 

TJ £ > -• TJ 


■0 3 

S! 


UU.lL 

— nn 
o o o 
o o o 


— (A 

co i 

o > 

2 § 

<o 


u. C CD Q O O 

U. CM CM C-4 O O 

Dili. UM CD U 10 U — Ul'tO'NO *0 0* (M II «ICMCD0' 

an no il n o n o CMouu.n^K)-*o oujqu 

u n n n 5> om>oiB>o o^on>ouuinnajONuMnK)«Nnffl 
a m in n ai odn^uiio (DMiiN'c<inNniiiK)NWNNiMiHiOO 


o^cMnm odcqqujo -t'0iMiiuQii H ninN(hfflQOHj'0ffl 
ooooo oooo— — — — — — — — — cMCMCMCMCMCMCMnnwnn 
o o 5 o o ooooo ooooooooooo ooooooooo 
ooooo 


OOOO— — — — — — — — — IM CM IN H IN H rJ r) rJ rj rl 

ooooo ooooo ooooooooooooooo 
ooooo ooooo ooooooooooooooo 


Dr. Dobb’s Journal, Number 71, September 1982 
414 


65 





BOOK REVIEWS 


Starting Forth 
by Leo Brodie 
Prentice - Hall 
366 pages, $15.95 

Circle No. 302 on Reader Service Card 

Reviewed by Richard L. Lozes 

When I first picked it up, I thought 
that Starting FORTH was merely “cute.” 
The author, it appeared, had gone over¬ 
board in illustrating with silly cartoons. 
Later, as I read about less familiar aspects 
of FORTH, I completely changed my 
mind; I found the cartoons an efficient 
and interest-boosting medium of com¬ 
munication. 

Starting FOR TH begins with two in¬ 
troductions, one for beginners and one 
for professionals. That duality persists, 
with special sections for computer 
novices and concise footnotes liberally 
sprinkled about, addressed to more or 
less advanced programmers. 

Especially useful features of the 
book are the reviews of definitions ap¬ 
pearing after each chapter and the last ap¬ 
pendix, detailing all FORTH commands 
introduced. There is no index in the usual 
sense, but I did not miss it. 

A word of warning for those more in¬ 
terested in poly FORTH — only the high- 
level, single-task commands of FORTH 
are presented here; the assembler, multi- 
prommer, printer and disking utilities are 
excluded. But then, the book is starting 
FORTH. 

Overall, I think Mr. Brodie has done 
his job well. Both the novice and the sea¬ 
soned programmer will take interest and 
learn FORTH with the help of this book. 

Discover Forth 
by Thom Hogan 
Osborne / McGraw - Hill 
142 pages, $14.95 

Circle No. 322 on Reader Service Card 

Reviewed by George W. Jolly 

Discover Forth is aptly named. I 
had been using Fortran and assembly lan¬ 
guage for ten years when my friends dis¬ 
covered Forth. They were virtually in¬ 
coherent as they extolled the virtues of 
the new language. My reaction was, I 
think, typical. How could Forth possibly 
be worth the effort of learning to use 
Polish notation and such strange sym¬ 
bols? Eventually I came to share their en¬ 
thusiasm, but it could have been much 
sooner if Discover Forth were available. 


66 


Author Hogan pleasantly explains 
the basics of Forth for the newcomer. 
Illustrations by Mary M. Milewski and 
section headings in a cheerful typeface 
make the book a pleasure to read. With 
some texts you work as hard reading the 
book as you do understanding the sub¬ 
ject. Discover Forth is easy to read. 

Fundamental to Forth is the concept 
of building-block programming. Each rou¬ 
tine you write becomes a new feature to 
be used at will in your environment. 
Thus, you can tailor your programming 
tools to suit your own preferences. You 
can use the same routine as a command 
from the keyboard and as a subroutine in 
future programs without any special ef¬ 
fort. You can even cause text on disk to 
be processed as if you were typing it, 
which opens many possibilities. 

Once you learn the basic building 
blocks provided with your Forth system, 
you can evolve it into whatever system 
you want. However, the basic budding 
blocks are somewhat unusual at first 
glance. Operations are performed in 
reverse-Polish notation on a data stack. 
Although many calculators operate this 
way, languages like BASIC and For¬ 
tran do not. There is no explicit as¬ 
signment statement for variables; assign¬ 
ment is done by an operator. In fact, in 
the strictest sense, there are no state¬ 
ments in Forth at all, only definitions of 
words. 

I found these differences between 
Forth and other languages only a minor 
stumbling block. Once you start using 
Forth, its advantages quickly outweigh 
the initial learning effort. Discover Forth 
would go a long way toward minimizing 
that initial effort. 

Discover Forth describes the basic 
Forth language elements and how they 
are used. The stacks and the dictionary 
are clearly explained and illustrated, as 
are disk buffer I/O and structured branch¬ 
ing. Most important, the philosophy of 
Forth programming is explained along 
with the basic ideas of top-down design. 
Forth-79 and fig-Forth are the basis for 
the discussion, with common differences 
of other systems pointed out for you. 
The required word set of Forth-79 is in 
an appendix for your reference. Ad¬ 
vanced methods like DOES> are beyond 
the scope of this book. 

While reading Discover Forth, you 


should be aware that advanced material 
is sprinkled into introductory dialogue. 
If you don’t understand something, keep 
reading, you won’t really need it yet. It is 
only there to whet your appetite for 
later. I like this because it helps keep the 
interest level up and gives the reader 
something to explore once the basics are 
over. 

If you are curious about this strange 
language, and want an enjoyable look at 
it, try Discover Forth. Be careful, though; 
Forth is definitely habit-forming! 


Programming Language Translation 
by R. E. Berry 

John Wiley & Sons (Ellis Horwood Ltd / 

Halsted Press) 

175 pages, $41.95 

Circle No. 312 on Reader Service Card 

Reviewed by Edward T. Ordman 
New England College 

This is an unusual and excellent book 
that belongs on the shelf of anyone who 
wants to write a compiler, as well as any 
teacher of computer science courses be¬ 
yond elementary programming. It is, 
however, sufficiently unconventional to 
require considerable sophistication from 
the reader. A first glance at the title and 
table of contents may suggest that this is 
a text for a standard compiler design 
course; it is not. Rather, it is a careful 
guided tour through a particular com¬ 
piler. 

Pages 1 15 through 152 (fine print — 
over 2000 lines) is the source code of a 
compiler and interpreter for Wirth’s 
Pascal S. The rest of pages 85 to 171 are 
comments and explanations, including 
the pseudo-machine language for the 
stack-oriented machine and compiler out¬ 
put for sample programs (unsuccessful 
ones with diagnostics, and successful ones 
with pseudo-machine code output and 
run-time stack snapshots). Pages 9 
through 84 contain a very abbreviated 
course in compiler and assembler con¬ 
struction, probably insufficient if one has 
not studied related material at greater 
length previously. 

The extensive commenting and dis¬ 
cussion of the compiler is very readable 
and will be helpful to anyone who has 
ever wondered how some particular fea¬ 
ture of a compiler works. While Pascal 
S is not full Pascal (it lacks files other 
than INPUT and OUTPUT, GOTOs, sets, 


Dr. Dobb’s Journal, Number 71, September 1 982 

415 



and pointer variables), and the interpreter 
assumes that built-in functions (writeln, 
sin, cos, etc.) are provided elsewhere, it 
does have record structures, recursive 
procedures with value and variable para¬ 
meters, and many other important Pas¬ 
cal features. Compiler directives are sup¬ 
ported. (The source code, incidentally, is 
in a somewhat larger subset of Pascal — 
it uses sets heavily.) The author asserts 
that it is consistent with Data General 
NOVA (Lancaster P4) Pascal, as well as 
with UCSD Pascal for the Apple II and 
Western Digital Microengine. 

One must jump around considerably, 
sometimes without warning, to read the 
book. The exercises to Chapter 1 are 
really questions about the source code 
100 pages later. Page 106 explains the IF 
statement by showing what pseudo¬ 
machine code is produced; that code is 
not given in detail until page 169. There 
are a few errors: e.g., the explanation of 
procedure EMIT (insert in array CODE a 
pseudo-machine instruction with no 
operands) has been omitted on page 114. 
Despite these very minor shortcomings, 
the book will be a major help to anyone 
interested in how Pascal works and in 
how compilers work. 




Dr. Dobb’s Journal, Number 71, September 1982 
416 


SOFTWARE REVIEW 


“The Working Forth Learning System” 
Price: $57.95 
Distributed on: 

Two 8-inch, soft-sectored, single¬ 
density diskettes 
System requirements: 

8080 or Z80 microcomputer 
Digital Research CP/M (tm) 
operating system 
One flexible-disk drive 
32 Kbytes RAM 
Available from: 

Laxen and Harris, Inc. 

24301 Southland Drive, Suite 216 
Hayward, California 94545 

Circle No. 332 on Reader Service Card 
Reviewed by Ray Duncan 

Forth is a high-level language well- 
suited to many microcomputer applica¬ 
tions because of its speed, portability and 
efficient use of memory. However, new¬ 
comers to it often become baffled and 
discouraged by the syntax (or lack of syn¬ 
tax), methods of disk access, and postfix 
notation, and they never reach a level of 
skill sufficient to exploit Forth’s unique 
capabilities. 

“Working Forth” is a computer- 
assisted tutorial that aims to boost the 
beginning Forth programmer past the ini¬ 
tial awkward phase. The package was 
written by Kim Harris and Henry Laxen, 
well-known figures in Forth circles, 
whose firm provides consulting and edu¬ 
cational services to many large corpora¬ 
tions. Both are prolific authors and soft¬ 
ware designers (see September 1981 DDJ 
for examples), and have made major con¬ 
tributions to the development and stan¬ 
dardization of the Forth language. 

“Working Forth” is an interesting ex¬ 
ample of self-reference. This is a pro¬ 
grammed instruction course about Forth 
which is written in Forth, and which is 
executed by a Forth interpreter/compiler 
that is in turn largely written in itself! 
Douglas Hofstadter fans will find plenty 
to ponder here. 

Disk # 1 of the set includes the fol¬ 
lowing files: 

• The executable Forth interpreter/ 
compiler, which runs under the CP/M 
operating system. 

• The source code for the nucleus of the 
interpreter/compiler. This is a stan¬ 
dard ASCII text file that can be edited 
and assembled with the usual CP/M 
utilities. 


• A text file containing the system docu¬ 
mentation. This is a particularly nice 
touch — as you begin to modify and 
extend Forth for your own purposes, 
you can customize the documentation 
to suit yourself. 

Disk #2 of the set includes many 
utilities and the programmed lessons. The 
former are for the convenience of the 
user in developing his own programs and 
include: 

• miscellaneous debugging tools 

• a line editor 

• documentation aids 

• partial or complete disk backup 

• Forth 8080 assembler 

• source code for additional data and 
control structures 

• a decompiler 

In my opinion, the utilities in themselves 
are worth more than the price of the pack¬ 
age. They are friendly, well-documented 
and (so far as I have been able to dis¬ 
cover) essentially bug-free. In addition, 
they serve as examples of excellent Forth 
coding style, showing how two veteran 
programmers have applied a wide range of 
techniques to create a variety of tools. 

Getting started with the Forth pro¬ 
grammed lessons is simple. Boot up CP/M, 
put disk #1 into drive A, and enter: 
FORTH < return >. The interpreter/ 
compiler will load into memory, take 
control of the system, and print an iden¬ 
tifying message. Replace disk #1 with 
disk #2 and enter: LEARNING LOAD 
< return >. From here on the system is 
self-instructing. 

In general, the lessons organize in¬ 
formation into nicely digestible chunks 
which will fit on one display screen. After 
a concept is presented, the learner is given 
access to the Forth interpreter so he can 
try out his new knowledge interactively. 
The tone of the lessons is chatty and 
affable, yet lucid. 

The instruction begins with a brief 
review of the “philosophy of Forth,” 
then a description of the virtual machine 
and how it is implemented. This leads 
into a discussion of Forth “words” or 
operators, how they are created, and how 
they are built into usable programs. 

The user is led gently through con¬ 
cise but clear explanations of stacks, post¬ 
fix or Reverse Polish Notation, compari¬ 


son operators, constants, variables and 
control structures. By the time the user 
gets this far, he has built up a base of 
knowledge adequate to read most Forth 
programs intelligently and to write simple 
ones of his own. 

The lessons subsequently become 
somewhat more technical, providing 
glimpses into the internal structure of the 
Forth runtime system. There is an intro¬ 
duction to “defining words” which allow 
the programmer to create new data types, 
as well as overviews of the representation 
of numbers, string handling, and output 
formatting. Next, the user is guided 
through Forth’s mass storage access 
methods and how to use them properly. 
Finally, there are detailed descriptions 
and examples for each of the commands 
in the Forth line editor. 

Once the user has absorbed all of the 
material in this learning system, he can go 
on to the excellent book Starting Forth 
by Leo Brodie which covers each topic in 
greater depth [see Book Reviews, page 
66], Laxen and Harris have taken pains 
to make their interpreter/compiler com¬ 
pletely compatible with Brodie’s pro¬ 
grams and examples, so the reader can sit 
down with the book in front of a termi¬ 
nal and truly learn by doing. 

In summary, the “Working Forth” 
lessons provide an inexpensive and en¬ 
joyable introduction to the Forth pro¬ 
gramming language. They will give you a 
clearer idea why people tend to polarize 
either violently against or fanatically in 
favor of Forth, and will let you judge 
whether the language is suited to your 
technical background, temperament, and 
applications. 

As a bonus, the purchaser gets a 
highly functional Forth program develop¬ 
ment system complete with utilities, edi¬ 
tor, and all source code. Laxen and Harris 
apparently have no desire to become 
language vendors, and state prominently 
in their documentation that “Working 
Forth” is meant to be used only as a 
teaching device. Such disclaimers aside, 
the fact remains that for a minimal cost 
you are actually getting a finely crafted 
tool, written by professionals, which can 
be used to create very sophisticated 
Forth applications. This is one of the 
great software bargains of the century. 

(See Figure 1 next page) 


Dr. Dobb’s Journal, Number 71, September 1982 


69 

417 




What's going on Hsrs? 

Thank you -for your lntsrsst in Learning Forth. This packag* is 
dssignsd to hslp you ltarn Forth quickly and sasily. It usss ths Forth 
systsm dsscribsd in ths wondarful book STARTING FORTH by Lso Brodis. In 
ordsr to gst ths most out of this systsm, thsrs ars a law things you 
should know. 

This so-ftwara automatically dscidss whan your scrssn is 'full and 
stops displaying information. Whan this happans, ths cursor will ba at 
tha bottom of tha scraan just bahind a > charactar. That is your signal 
that tha program thinks tha scraan is full. At this point you should 
prass the space bar and tha information will continue. 

Tha number appearing on tha upper right hand corner of your 
display is called tha Scraan number. It is tha place on tha disk where 
each particular piece of text resides. If you want to review any 
particular scraan and you know tha scraan number, you need simply type 
tha number followed by a space, followed by tha word GO and a carriage 
return. This will start tha lesson at that particular scraan. 

Often during tha course of this session, you will ba asked to try 
something inForth, and we will exit from this package and leave you 
in tha Forth Interpreter. After you have completed the problem, or have 
given up, you can return to the next instruction screen by typing G 
followed by a carriage return. > 


Figure 1. 

Sample screen from the “WORKING FORTH Learning System” programmed lesson 
sequence. 


(Continued from page 21) 



Figure 3. 
Format of the FP#. 


only about one and one-half weeks to write and debug the 
floating-point package described above. It has taken twice 
that time to write this article. The fact that Forth is structured 
and forces the user to build routines incrementally tends to 
foster error-free programming. 

But best of all, Forth is extensible. It is application sensi¬ 
tive. This writer’s ingrained prejudice for a good macro¬ 
assembler is fast disappearing. 




Dr. Dobb’s Journal, Number 71, September 1982 
418 


71 






OF INTEREST 


by Michael Wiesenberg 


The trend of systems with two pro¬ 
cessors, eight- and sixteen-bit, continues 
with the Dynabyte Monarch. It has an 8- 
megahertz 8086 main CPU isolated on its 
own board, and a 6-MHz Z80B to handle 
input/output and other “housekeeping” 
tasks. Direct Memory Access (DMA) pro¬ 
vides high-speed data transfers between 
disk, memory, and tape, completely inde¬ 
pendent of the two microprocessors. An 
optional 8087 math co-processor is avail¬ 
able for heavy number crunching. With 
eight operating systems, Monarch runs, 
concurrently, virtually any 8- or 16-bit 
software. Available eight-bit operating 
systems are CP/M, MP/M-II, and OASIS; 
and 16-bit are CP/M-86, MP/M-86, 
OASIS-16, UNIX, and Business Basic 
(Basic Four). Two bus architectures are 
offered, either S-100 or Multibus. Up to 
16 users are supported. The standard sys¬ 
tem includes 256 kilobytes of memory, a 
19-megabyte 514-inch Winchester drive, 
an 8-inch 800K floppy disk drive, eight 
RS-232C asynchronous ports for modem 
or remote computer communications, 
plus one RS-232C asynchronous/syn¬ 
chronous port that has hand-shaking 
support for bisynchronous communica¬ 
tions using IBM 2780/3780 protocols and 
3270 terminal emulation, one RS-422 
high-speed synchronous port, and one 
parallel (Centronics-compatible) port. 
(That’s eleven I/O ports standard!) This 
system costs under $11,000, without op¬ 
tional additions like a 17-MB cartridge 
tape drive, memory expansion to 1MB, 
eight more serial ports, up to 76MB stor¬ 
age, and error detection and correction 
circuitry. Available languages include 
CBasic, Microsoft BASIC interpreter and 
compiler, Phase One Systems’ BAS¬ 
IC interpreter/compiler, Ryan-McFarland 
COBOL, and, from Microsoft, COBOL- 
86, FORTRAN-86, and Pascal-86. Read¬ 
er Service No. 306. 

Similar features for considerably low¬ 
er cost are offered by Zenith Data Sys¬ 
tems’ Z100 desktop series. Processors are 
the 8088 16-bit and 8085 8-bit micro¬ 
processors. Two versions are available, 
the one-piece Z-120 with monochrome, 
green phosphor, non-glare screen, and the 
Z-110, a color computer without moni¬ 
tor. The “low-profile” model, with one 
internal 320K 514-inch diskette drive, 
monochrome graphics, and 128K RAM 
sells for $3249. All models have five S- 
100 slots, software-definable characters, 
blinking, underline, or reverse video cur¬ 
sor with relative and direct cursor ad¬ 


dressing, a Z207 disk controller that 
simultaneously supports 514- and 8-inch 
drives, a 108-key keyboard with standard 
word processing keys, cursor control 
keys, a numeric keypad, and 13 function 
keys, two RS-232 ports in asynchronous 
mode, full or half duplex, and bisyn¬ 
chronous mode, one parallel port, and 
power switchable from 120 to 240 volts. 
Options include an extra internal 514-inch 
floppy disk drive, a 514-inch 5K Winches¬ 
ter drive, external 8-inch floppy disk 
drive (single- or double-density, single- 
or double-sided), memory expansion to 
768K, and high-resolution color graphics. 
Available software includes Z-DOS (Zen¬ 
ith’s implementation of Microsoft’s 
MDOS), CP/M-85, Microsoft BASIC, Z- 
BASIC color extension, Multiplan elec¬ 
tronic spreadsheet, and almost anything 
else that can be used by the IBM Personal 
Computer with PC-DOS or by any 8-bit 
CP/M. Reader Service No. 316. 

Hewlett-Packard announced its 
lowest-priced personal computer, the 
HP-86, a modular unit with 128K of 
memory, expandable to 512K. It runs all 
HP Series 80 BASIC software, in addition 
to most CP/M software (with HP’s plug¬ 
in CP/M system). The HP-86 is compati¬ 
ble with HP’s personal computer modem, 
and a number of printers and graphics 
plotters. Using a Hewlett-Packard Inter¬ 
face Loop (HPIL), data gathered with an 
HP-41 handheld computer can be upload¬ 
ed to any Series 80 computer. You can 
also get for the HP-86 a 9- or 12-inch 
display, a 270K flexible disk drive, an 
HP 82950 modem or HP Data Communi¬ 
cations Pac, accounting software, dBASE 
II data base software, WordStar, Spell- 
Star, MailMerge, VisiCalc PLUS, and 
graphics software. The HP-86 alone costs 
$1795, and a complete system costs 
under $3900. Reader Service No. 326. 

Cyberdrive, from Cybernetics, is a 
13.5- or 27-megabyte Winchester disk 
drive, with 6.4MB minicartridge tape for 
backup, for the IBM Personal Computer. 
It has an average seek time, they claim, 
of 33 milliseconds (including head 
settling), across more than five times as 
much data as other typical Winchester 
drives with seek times in the range of 100 
to 200 ms. For $5750 (for the 13.5MB 
drive), you get all the hardware and soft¬ 
ware, and an extendable six-month war¬ 
ranty. Reader Service No. 326. 

Interface Inc. offers 250K 5!4-inch 
floppy disk drives for the Apple II. The 
double-density, double-sided drive offers 


40 tracks per diskette with half-tracking 
and 75ms average access times. You can 
get it (in any one of eight colors) for 
$375 for the single drive, and $850 for a 
dual-drive system with disk controller. 
Reader Service No. 336. 

While we’re talking storage for 
Apples, Innovative Data Technology 
offers the SCDR-1050, a tape drive 
that stores over 40 MB of data in IBM- 
compatible format, using nine-track 
800- or 1600-cpi magnetic tape. The 
SCDR-1050 connects directly to an 
Apple II or III RS232C/CTTV-24 port 
with no modifications. The complete sys¬ 
tem includes an input/output controller 
with up to 32K of RAM, a TDF-4050 
formatter, and IDT’s TDI-1050 tape 
transport. It can transfer data for backup 
at about a megabyte per minute. One unit 
costs $8500, with additional daisy-chained 
drives at $4250 each. Reader Service 
No.346. 

You can get the new three-inch flop¬ 
py disk drive and cartridge system, plug- 
compatible with standard 514-inch drives 
the Micro -Floppydisk, from Amdek. 
With up to one megabyte of storage on a 
dual-disk drive, it sells for $899. Reader 
Service No. 356. 

Amdek also offers an X-Y four- 
color plotter, the Model DXY, for most 
computers using a parallel interface. It 
has a 10- by 14-inch plotting range, plots 
at 2.73 inches per second with a step size 
of .003 inch, comes complete with four 
pens, pen holders, and chart hold-downs, 
and costs $949. Reader Service No. 366, 

Qunix from Quantum Software Sys¬ 
tems is a Unix-like operating system for 
the IBM Personal Computer. Multi¬ 
tasking permits spooled output to a print¬ 
er, and one to eight users are supported. 
Qunix is not the same as full Version 7 
Unix, even though it uses message passing 
and generalized pipes and filters, but it is 
functionally equivalent in many ways, in¬ 
cluding the ability to run C programs that 
run under Unix. On the PC, any key can 
be redefined to represent a command se¬ 
quence of variable length. A ROFF-like 
text-formatting program comes with 
Qunix. On-line help is available, and com¬ 
mands can be reassigned any names the 
user wishes. Qunix starts at $150 for a 
single-user system for the PC and 8088, 
8086, and 6809 computers. The C com¬ 
piler costs $350, including an 8086 
assembler (which costs $100 by itself). A 


72 


Dr. Dobb’s Journal, Number 71, September 1982 

419 




full-screen editor (in addition to the 
supplied text formatter) costs $125, a 
BASIC compiler is $125, Pascal compiler 
$200, and FORTRAN compiler $125. 
Reader Service No. 406. 

RMS (Record Management System) 
is a database management system (DBMS) 
from Washington Computer Services, for 
the IBM PC, or any computer using 
CP/M, CP/M-86, OS-9, Flex, or Uniflex. 
They say it is easily configured for any 
CRT, and consists of five machine lan¬ 
guage programs. Programming expertise 
is not required to use RMS, but its files 
can be accessed from most languages. A 
screen-oriented editor enters and re¬ 
trieves records, with record layout deter¬ 
mined by a user-definable data diction¬ 
ary. A sort/merge program builds a sorted 
index, with direct access by key field, and 
multiple index files for ordered sequential 
access. Records can contain up to 50 
fields, and be up to 1021 bytes long. A 
two-level record hierarchy lets any pri¬ 
mary record “own” multiple secondary 
records. A file can be up to 64K in length. 
Field validation can automatically ensure 
entering of only valid data. A report pro¬ 
gram prints reports in sorted order, with 
certain records either explicitly skipped 
or included, output formatting specified, 
special forms accommodated, and headers 
and trailers included. A copy program 
merges RMS files, posts one to another, 
or changes the record format of a file. 
RMS prices range from $200 for Flex to 
$395 for IBM PC or CP/M. Reader Ser¬ 
vice No. 416. 

Superfile from Elliam Associates, 
whose motto is, “It’s what you can find 
that counts!”, is another information re¬ 
trieval system. Text files are created with 
any CP/M-compatible text editor or user 
program in “free form format.” Superfile 
then searches these files, which can be on 
any number of different drives, using up 
to 64 key words, each of which can be up 
to 64 characters long. The search can be 
used with Boolean operators (AND, OR, 
NOT), and has a “close to” feature. That 
is, if a key word entry is not valid, Super- 
file displays a group of key words that are 
alphabetically close, so you can search 
semi-blindly for desired information. 
Superfile includes a customizing program, 
an alphanumeric sort, a merge program, 
and a program that splits records and files. 
Superfile also has a 150-page manual and 
a demonstration data base. It is supplied 
on various disk formats for Z80 systems 
with at least 48 K and two floppy disk 


drives or a hard disk, and costs $196.50. 
Reader Service No. 426. 

System 75 is a CP/M cross-assembler 
from Allen Ashley for the NEC 7500 
microprocessor. The software system in¬ 
cludes macroassembler, interactive editor/ 
assembler, text editor, cross-reference 
generator, and facilities to offload the 
output. This development system is avail¬ 
able on diskette for $150, including docu¬ 
mentation, and user support by mail or 
phone. Reader Service No. 446. 

Sinclair has announced new ZX81 
software, on cassette and developed by 
ICL, a large British computer company, 
and Psion, a British software company. 
The software is available in the U.S. only 
by mail order, and ranges in price from 
$12.95 to $17.95. In the business applica¬ 
tions category, VU-CALC is a Visi-Clone, 
and VU-FILE files and retrieves informa¬ 
tion. Collectors’ Pack holds 400 records 
on hobby items (stamps, coins, etc.). 
Club Record Controller holds personal 
records of 100 people. The “Fun to 
Learn” series includes English Literature, 
Geography, History, Mathematics, Inven¬ 
tions, and Music, and the “Super Pro¬ 
grams” series has games, quizzes, conver¬ 
sions, and houshold programs. Other 
games include Backgammon, six-level 
Chess, Flight Simulations, Space Raiders 
and Bombers, and Fantasy Games. There 
is also a Biorhythms. All cassettes, ex¬ 
cept the “Super Programs,” require an 
add-on 16K RAM pack. Reader Service 
No. 456. 

FORTH-79 from MicroMotion meets 
all provisions of the FORTH-79 stan¬ 
dard, and is available for Apple, Z80 
CP/M, and NorthStar DOS. It comes with 
a screen editor, macroassembler, string 
package, 32-bit integer arithmetic, and a 
tutorial and reference manual of some 
200 pages, and costs $99.95. For floating¬ 
point and HIRES Graphics, add $40 for 
Apple and $49.95 for NorthStar (not 
available for CP/M). Reader Service 
No.476. 

GraFORTH, from Insoft, is a com¬ 
piled graphics programming language for 
the Apple II. Three-dimensional color 
animation graphics employ rotation, 
scale, transposition, and perspective. 
Character set graphics come in full color, 
with variable character sizes and upper 
and lower case, and block print to manip¬ 
ulate large shapes. GraFORTH draws lines 
faster, says Insoft, than BASIC, and never 


breaks colored lines. It uses Turtlegraph- 
ics to draw lines. GraFORTH also has a 
software-based music synthesizer that 
adds music or sound effects to programs. 
GraFORTH comes with a 220-page tutor¬ 
ial manual, and costs $75. You’ll need 
48K, one disk drive with DOS 3.3, and 
Insoft recommends the 16K RAMcard. 
Reader Service No. 486. 

DATABS, from Softronics, was in¬ 
spired by MIT’s CLU language. It is a 
strongly-typed data abstraction language 
with UNIX-like command line arguments 
and I/O redirection. It comes on eight- 
inch CP/M disk, together with a 73-page 
manual, for $60. Softronics APL is a sub¬ 
set of APL, containing most of the func¬ 
tions and operators of the full language. 
Also for CP/M, it comes with a 112- 
page manual, and costs $350. Manuals 
alone are, respectively, $20 and $30. 
Write to Softronics, 366 Homestead 
Lane, Roosevelt, NJ 08555. 


74 

420 


Dr. Dobb’s Journal, Number 71, September 1982 


#72 


October 1982 


$2.50 


($3.00 in Canada) 


Dr. Dobb's Journal 

For Users of Small Computer Systems 



Test 

bit i 2 

Test 

bit v 

Branch to 

Test 

bit iJ2 

it ll 

y (inJ 

Branch to^B 

Test 



Portable Pidgin 
for the Z80 


68000 Cross 
Assembler 

8086 Graphics 
Subroutines 

and even more! 


G OPERATION 


3 A y,i_ Add y to y 

1 Aa_ v Add y to a (y # 1 

ABab Add BCD lb to la 

ABtu Add BCD lMDu_ to 

Add a_ tc emoq 

4 ASd_ v2 Arith. shift. vJ2 

ASd_ ma^yc Arith. shift ma 

1 At. vx Add vx to t_ 

AXmab Add extended mb 


AX mtu " " mMDu to mMI 

ton ( x )=sin( x ) HOOP 


























CONTENTS 


Dr. Dobb s Journal 

Fo» Users ot Small Computer Systems f 

October 1982 Volume 7, Issue 10 


Editor — Marlin Ouverson 
Assistant Editor — Fritzi Lareau 
Contributing Editors — 

Dave Caulkins, Dave Cortesi, 

Ray Duncan, Gene Head, 

Michael Wiesenberg 
Marketing Director — Craig Harper 
Marketing Assistant - Beatrice Blatteis 
Advertising Director - Laird Foshay 
Circulation Manager — Gloria Romanoff 
Circulation Assistants - 

Terri Marty, Linda Marohn 
Art Director - Clifford West 
Production Manager - Barbara Ruzgerian 
Production Assistant - Jane A. McKean 
Typesetter - Renny Wiggins 
Cover Illustration - A1 McCahon 


© 1982 by People’s Computer Company 
unless otherwise noted on specific articles. 
All rights reserved. 


Subscription Rates: $2 5 per year within the 
United States; $44 for first class Canada 
and Mexico; $62 for airmail to other coun¬ 
tries. Payment must be in U.S. Dollars, 
drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be 
typed, double-spaced on white paper. List¬ 
ings should be produced by the computer, 
using a fresh, dark ribbon on continuous 
white paper. Please avoid printing on perfo¬ 
rations. Payment is in contributor’s copies. 
Requests to review galleys must accompany 
the manuscript when it is first submitted. 
Authors may receive a copy of the complete 
writer’s guidelines by sending a self- 
addressed, stamped envelope. 

Donating Subscribers Contributing Sub¬ 
scriber: $ 50/year ($25 tax deductible). Re¬ 
taining Subscriber: $ 7 5/year ($50 tax de¬ 
ductible). Sustaining Subscriber: $ 100/year 
($75 tax deductible). Lifetime Subscriber: 
$1000 ($800 tax deductible). Corporate 
Subscriber: $S00/year ($400 tax deductible, 
receives five one-year subscriptions). 

Contributing Subscribers: Thomas H. 
Grohne, G. V. Elkins, Robert M. Connors, 
William J. McEown, Robert C. Luckey, 
Robert N. Stabler, DeWitt S. Brown, John 
B. Palmer, Burks A. Smith, Transdata Cor¬ 
poration, Mark Ketter, John W. Campbell, 
Friden Mailing Equipment, Howard E. 
Decker, Jim Wilson, Frank Lawyer, Chris 
Pettus, Paul Lutus, Ben Goldfarb, Rodney 
Black, Steven Weiss, Pat Phelan, John 
Brodie, James Fleming, Unison World, 
Thomas Davis, Jan Steinman, Ronald E. 
Johnson, G. Hunter, Kenneth Drexler, Real 
Paquin, Ed Malin, John Saylor, Jr. Sustain¬ 
ing Subscribers: Pete Roberts, Steven Fisher 
Enterprizes. Lifetime Subscriber: Michael S. 
Zick. 

Foreign Distributors UK & Europe: 

Hofacker-Verlag, Tegernseer Strass 18, D- 
8150 Holzkirchen, West Germany. Asia & 
Australia: ASCII Publishing Co., Ltd, 
Aoyama Building 5F, 5-16-1 Minami 

Aoyama, Minato-ku, Tokyo 107, Japan. 


Articles 

12 68000 Cross Assembler 

by Allen Kossow 

DDJ #68 described a homebrew, multi-68000 development system; readers re¬ 
sponded with many requests for publication of the Fortran cross assembler 
mentioned in that article. The main program and subroutines will be presented 
in their entirety, beginning this month. 


25 The Portable Pidgin 

Z80 Macro-Assembly Implementation 

by Herbert Gintis 

Software portability often comes at the expense of size and speed. Author Gintis 
found Pidgin to be low-level, structured and portable. Here he presents his Z80 
macro-assembly implementation intended to run under CP/M. 


36 Simplified 68000 Mnemonics 

by W. D. Maurer 

Motorola’s powerful and versatile 68000 microprocessor offers many features to 
the experienced programmer. But how does one ever become fluent in its complex 
assembler mnemonics? As this article points out, redesigning to a simpler 
mnemonic set may be a reasonable step to take. 


Departments 

6 Letters 

6 Editorial 

7 Dr. Dobb's Clinic 

Debuggers, Nested SUBMITS and PC BASIC 

42 CP/M Exchange 

RCP/Ms, MBOOT3 and Downloading MODEM 

51 16-Bit Software Toolbox 

8086/88 Trig Lookup Functions 

55 Of Interest 


Dr. Dobb's Journal (USPS 307690) is published twelve times per year by People’s Computer 
Company, Box E, 1263 El Camino Real, Menlo Park, CA 94025. Second class postage paid at 
Menlo Park, California 94025 and additional entry points. Address correction requested. 
Postmaster: send form 3579 to Box E, Menlo Park, California 94025 • 415/323-3111 


4 


Dr. Dobb’s Journal, Number 72, October 1982 





LETTERS 


Dear Gary Kildall .. . 

Dear Dr. Dobb’s, 

I found the article comparing CP/M- 
86 with MS-DOS (and CP/M-80) quite 
interesting, though I certainly agree with 
the conclusion that it is disappointing 
that Digital Research and Microsoft can’t 
come up with anything better than a 
copy of CP/M-80. In my opinion, the 
biggest item missing from all three of 
these systems is I/O redirection. 

Recently, Digital Research ran ads 
in a newspaper in this area for people to 
work on CP/M for the Motorola 68000. 
Are we in for yet another copy of CP/M- 
80? That would be rather like running a 
Ferrari engine on one cylinder. (It is grati¬ 
fying, however, that Digital Research has 
finally recognized that someone besides 


Intel makes microprocessors!) I would 
like to suggest to Digital Research that 
they use Microware’s OS-9 tm operating 
system (for the 6809) as a model for 
CP/M-68K (or whatever they call it), 
rather than giving us yet another copy 
of CP/M-80. 

Sincerely, 

Jim Howell 
5472 Playa Del Rey 
San Jose, CA 95123 

Micro Compiler in Brobdingnag 

Dear Marlin Ouverson, 

Enclosed is an article and program 
submitted for your review and inclusion 
in Dr. Dobb’s, if you so desire. Let me 
add that I enjoy your magazine very 
much, have all the issues from #1, and it 



would be the last magazine I would drop. 
(I get over thirty engineering or comput¬ 
ing magazines.) 

I have modified the Small-C compil¬ 
er to work on a 370 under VM. How’s 
that for reverse engineering? It also has 
FOR, GOTO, two-dimension arrays, etc. 
Regards, 

Chris L. Torkildson 
13791 Hey wood Ct. 

Apple Valley, MN 55124 

Dear Mr. Ouverson, 

I have been using Small-C since the 
Software Works first offered it for CP/M. 
I recently got enough memory to allow it 
to compile itself correctly, and have start¬ 
ed implementing all the changes suggested 

(Continued on page 59) 


Editorial ' 

Going Public. . . 


Dr. Dobb’s Journal has always championed the cause 
of public-domain software. It was accidentally founded by 
a group of idealistic hackers who only wanted to write and 
publish a tiny Basic interpreter. Their challenge was to fit 
it in about 4K; their commitment was to put it in the pub¬ 
lic domain. 

This idea — doing good work and letting the public 
have it with no strings — was so good that readers who 
managed to get their hands on a copy just wouldn’t let DDJ 
finish its intended three-issue life cycle. Instead, seven 
years later it is the landmark publication for systems 
software. 

One reason for practically giving away perfectly good 
programs is to enable individuals to build a library of tools 
for their own use. In the larger sense, of course, commer¬ 
cial products would be greatly enhanced by drawing on 
some of the truly superb items that have been launched 
into the public domain. In fact, a number of good packages 
for sale these days may find their roots in a Dr. Dobb’s 
Journal listing, or some other non-proprietary source. 

This altruistic influence on end-user technology has, 
we think, improved the state of the art. The DDJ commu¬ 
nity waves the public-domain flag because we think it is im¬ 
portant. With this kind of material, the available computing 
power is greater than would otherwise be true. 

Many generous and sympathetic authors should be 
thanked for making DDJ’ s mission successful. In addition 
to our present contributors, we remember the work of 
Dennis Allison, Steve Wozniak, Gary Kildall, Tom Pittman, 


Ron Cain, Li-Chen Wang and Ward Christensen. They are 
among the many fine people who have used DDJ to make 
important contributions to the microcomputing com¬ 
munity. 

Unfortunately, the creation of public-domain soft¬ 
ware is not as popular a pastime as it once was. Maybe, in 
the beginning, we had more of a sense of community — 
wonderful machines with unlimited potential, but with 
nothing more helpful than a row of switches on the front 
panel. And if you think today’s documentation is bad ... it 
took a major team effort just to get the things operating. 

Now, software protection schemes seem to get more 
creative thought than the programs they were designed to 
protect. Instead of sharing resources, one sees even (or 
perhaps especially) inexperienced programmers becoming 
canny to any possible profit to be gained or lost. Fortu¬ 
nately, there is still a body of people willing to share their 
work for just the good feeling, or the prestige, or the com¬ 
mon cause of more public-domain software. 

In the interest of building the public domain, we en¬ 
courage authors not to reserve rights to programs published 
in DDJ, even though we will publish ones which reserve 
commercial rights. If the technical growth potential of com¬ 
puters is going to be realized, it won’t be by those large 
companies with heavy investments in current technology 
— it will be by individuals working together to push beyond 
the limits of today’s product line. When you hear one of 
us refer to the DDJ community, that’s what we mean. 

— Marlin Ouverson 


6 


Dr. Dobb’s Journal, Number 72, October 1 982 

423 



urt. UUBB’S CLINIC 


by Dave Cortesi 


The Very Last SUBMIT Item 

For months we have been droning on 
about the SUBMIT command of CP/M, 
telling you how useful it can be and 
showing how to increase its usefulness 
with fixes and small utilities. In June we 
showed the utilities PAUSE and BEEP, 
which increase the operator’s control over 
a submitted job. In August we brought 
you Robert Pasky’s nicely-integrated set 
of patches that make SUBMIT handle 
lowercase input, control characters and 
null lines correctly. With them applied, 
you can submit command streams to ED 
and PIP for unattended execution. In 
September we presented Don Wright’s 
QUITIF program, which gives the design¬ 
er of a SUBMIT file the ability to check 
for some errors. 

Now, courtesy of Digital Research, 
we SUBMIT users have the ultimate in 
SUBMIT patches. The July/August issue 
of Microsystems reproduces, unedited 
and without commentary, a set of appli¬ 
cations notes, the work of the Technical 
Support Group at Digital Research, Inc. 
One of these is a lengthy patch which 
causes SUBMIT to append its output to 
an existing $$$.SUB file, instead of re¬ 
placing that file. The result is that we can 
include a SUBMIT command in a submit¬ 
ted job. The inner submit file will be ap¬ 
pended to the active submit file; when it 
completes, the outer submit file will be 
resumed with the line following the SUB¬ 
MIT command. 

Nested submits! And they come so 
easily, too. When SUBMIT runs, it places 
the submitted commands, one per 128- 
byte record, in reverse order in the file 
$$$.SUB. This was originally done, we 
think, for the convenience of the Con¬ 
sole Command Processor (CCP). TheCCP 
consumes records from $$$.SUB from 
the end of the file toward the beginning. 
That lets it use the “record count” byte 
of the directory entry for $$$.SUB as its 
pointer to the next record of the file. It 
couldn’t keep such a pointer in storage, 
because there is no location in storage 
that is proof against overlay by an appli¬ 
cation program. 

But this use of $$$.SUB makes the 
file work like a push-down stack. The 
CCP pops records off the end of the file. 
The new patch makes SUBMIT push rec¬ 
ords onto the end of the file, rather than 
erasing the file and budding a whole new 
one. Nesting of submitted jobs follows 
automatically. 


The Digital Research patch, with our 
own comments, is shown in Listing 1 
(page 58). Assemble it, then use the I and 
R commands of DDT to overlay its hex 
file onto a copy of SUBMIT.COM (one 
with the Pasky Patches applied to it). 
The updated SUBMIT command does just 
about everything we could ask of it, so 
with this item we are turning the whole 
matter of CP/M SUBMIT over to Gene 
Head and the CP/M Exchange. 

Debugging the Debuggers 

We’ve had some letters from peo¬ 
ple who have problems with the Digi¬ 
tal Research debug utilities, DDT and 
ZSID. L. Barker sent us a note on two 
holes in ZSID. It doesn’t interpret the 
LDIR instruction correctly when the 
operands (the two strings defined by the 
HL, DE and BC registers) overlap on each 
other. The LDIR (long move) instruction 
of the Z80 copies a source string into a 
target string. When the target string over¬ 
laps on the source string (as when the 
source begins at 0200h, the target at 
020lh, and the length is 255 bytes), 
LDIR becomes a Replicate instruction, 
duplicating the leading byte of the source 
into the target over and over. ZSID 
doesn’t handle it right, though; it stops 
after copying one byte. 

Barker also noted that the disassem¬ 
bler in ZSID can’t seem to handle the 
“LD A,R” and “LD R,A” instructions. 
Its List command won’t display them and 
its Assemble command won’t accept 
them. 

Gavin Brick ell of Auckland, New 
Zealand, thought that he’d found a bug 
in DDT, but he hadn’t. It appeared that 
DDT was modifying a word in storage 
without any reason. However, it had a 
reason: the word in question was the top 
word of the stack as defined by the pro¬ 
gram under test. DDT uses one word on 
the program’s stack in at least three 
points during the execution of the Go 
command. The remarkable thing is that 
DDT manages to get by with only one 
word of the program’s stack; it seems not 
to need any more. 

Dana Trout of Goleta, CA, wrote in 
with a method for changing the number 
of the RST vector that DDT uses for 
breakpoints. One of the Digital Research 
applications notes mentioned above cov¬ 
ers the same area. We think that DDT’s 
use of RST 7 should be left alone if at all 
possible. DDT (and SID, and ZSID, and 
any other debugging tool) is going to use 


some restart vector, and RST 7 is the one 
that is documented as being for this use. 
The great majority of CP/M systems will 
leave RST 7 free for debuggers. A modi¬ 
fied debugger, exported to another sys¬ 
tem, is quite likely to crash that system 
by conflicting with a legitimate interrupt 
vector. Furthermore, there’s a good rea¬ 
son for using RST 7 for debug break¬ 
points: most hardware will return FFh 
when asked to read from RAM that 
doesn’t exist. FFh is the opcode for an 
RST 7 instruction; if that is the break¬ 
point vector, a wild branch to non¬ 
existent memory will cause an automatic 
breakpoint! 

Finally, Nick Hammond of Pebble 
Beach, CA, contributed a cute trick that 
can be played with DDT. DDT could be 
useful for poking around in the innards of 
CP/M, if only it would leave things alone. 
“The problem with DDT,” Hammond 
writes, “is that it changes things when it 
gets control. Location 5 no longer points 
to the BDOS except via a circuitous series 
of jumps, and the CCP is missing, having 
been overwritten.” Hammond supplies a 
technique for getting a copy of DDT into 
the transient area below the CCP, and get¬ 
ting control into it with the BDOS vec¬ 
tor and the CCP intact. It works like this. 

First, invoke DDT as a command, 
with its own .COM file as argument: 

A>ddt ddt.com 

DDT will start up and load DDT.COM. 
Give the Go command with no address; 
control will enter the loaded copy. It will 
relocate itself just below the first-started 
copy of DDT, clear of the CCP, put its 
own vector into the RST 7 location, and 
prompt for a command. Use the Assem¬ 
ble or Substitute command to put an RS T 
7 instruction at location OlOOh. Then use 
the GO or a control-c to do a warm start. 
The CCP will be reloaded over the first 
copy of DDT, but the second copy will 
remain. Then create and call a null com¬ 
mand file as a means of causing a branch 
to location lOOh, where you stored a 
RST 7: 

A > save 0 null.com 

A > null 

Control will pass to the RST 7 at location 
100, which will return control to the sec¬ 
ond copy of DDT. You can now use it to 
peer about the system, observing low 
storage and the CCP in their native states. 

Ask Uncle 

“I have a Diablo 1620,” says Ernest 



Dr. Dobb’s Journal, Number 72, October 1982 

424 


7 



Knipp of Houston, TX, “and the Courier- 
10 print wheel has a pound-sterling sym¬ 
bol. I can’t get this symbol to print. Is 
there any way to reach this unreachable 
character?” 

You betcha, Ernest. There are 96 
spokes on the Diablo printwheel. Ninety- 
four of them print in response to the 94 
printing chracters of the ASCII code. 
Two of the spokes correspond to the 
ASCII space (32h) and the DEL (7Fh) 
codes. Those two can’t be reached by 
sending the printer a single ASCII code. 
When it gets a space, the printer just 
advances the carriage; it doesn’t use the 
printwheel at all. And it conforms to the 
ASCII standard by ignoring DEL charac¬ 
ters entirely. 

However, the manual for our 1650 
printer says that the sequence ESCape, 
“Y” will print the spoke matching 32h, 
and ESCape, “Z” will print the one 
matching 7Fh. In other words, if your 
printer receives the two bytes IBh, 59h, 
it should print the sterling symbol. If 
it receives the bytes IBh, 5Ah, it should 
print a logical-not symbol. 

Assorted Grumps 

A person who would rather remain 
anonymous has told us that he had it 
from an equally anonymous, but sup¬ 
posedly well-informed, source that the 
code of the IBM PC’s BASIC interpreter 
was indeed produced by an 8080-to- 
8086 translator program. That’s all very 
well, but we’d rather see some evidence. 
Surely somebody out there has a PC, a 
suspicious mind, experience with the 
typical output of translator programs, 
and a few hours to spare. The MSDOS 
command DEBUG will disassemble stor¬ 
age. Use Ctrl-PrtSc to start a log of its 
output on the printer. 

Actually, there are very good reasons 
why Microsoft would translate an existing 
interpeter rather than write a new one. 
Their MBASIC is a mature, well-debugged 
piece of code. Translation would let them 
produce a reliable product quickly and 
cheaply. Reliability, quick development, 
and low cost are three qualities that are 
conspicuously absent when you build a 
large piece of software from scratch. One 
can see how the “technical” considera¬ 
tion of execution speed could easily take 
a back seat to these desirable “manage¬ 
ment” criteria. . . . 

Burke Smith of Shawnee Mission, 
KS, has found a bug in that mature 
product, MBASIC. It only seems to sur¬ 


face in version 5.1 of BASIC-80, and in 
IBM version D1.00. Try this sequence: 

LET A#=0 
I FT A#=_A # 

PRINT INT( A#),FIX(A#) 

Smith claims that in the noted versions 
(but not in the more common versions 
4.51 and 5.2) two answers of -1 will be 
diplayed, “rather than the zeroes that any 
reasonable person would expect.” 

Smith goes on to blame the problem 
on Microsoft’s choice of binary floating¬ 
point rather than decimal float using a 
BCD representation. We think that’s a red 
herring. We’ve seen a lot of misguided 
complaints along this line; the writers 
seem to think that there is something pe¬ 
culiar about the binary number system 
that makes it more prone to truncation 
errors (“round-off errors”) than decimal 
is. Tain’t so; a digit is a digit, no matter 


what your radix. The problem is the lim¬ 
ited precision of the representation, not 
the number base. A decimal representa¬ 
tion of a real number is just as prone to 
truncation errors as a binary, octal or 
hexadecimal one is. 

There are standard techniques that 
will mitigate the effect of truncation er¬ 
rors. Hardware designers can incorporate 
an extra digit of precision in the tempo¬ 
rary results held in machine registers, 
and round any bits that turn up in such 
a “guard digit” back into the result 
before storing the result. Few people 
remember now, but the initial design for 
the IBM 360 line lacked guard digits in 
the floating-point ALU; the first ma¬ 
chines had them added in the field as en¬ 
gineering changes. Good scientific calcu¬ 
lators get the same effect by carrying 
several low-order digits that don’t show 
in the display. MBASIC could have 


SUBMIT.COM 

A patch to SUBMIT.COM which forces it to open an existing 
$$$.SUB file for appending, rather than erasing it. The 
CCP reads that file in reverse order. Thus a SUBMIT within 
a submitted file will "push" new records onto the end of the 
file, from whence the CCP will "pop" them. The result is 
correct execution of nested SUBMIT commands. 


subfcb 

equ 

05BBh 

7 FCB 

for $$$.SUB 

BDOS 

equ 

0005h 



OPEN 

equ 

0211H 

7 open 

-file subroutine of SUBMIT 


org 

022Dh 

7 the 

erase-file routine of SUBMIT 


It would seem that this location is called when an attempted 
open of $$$.SUB succeeds, showing that the file exists. 
Previously, this code would have erased the file. 

opsl Ida subfcb+15 ; open ok if extent not full 

ral ; extent full if record count=>80h 

rnc ; exit if count < 80h 

lxi h,subfcb+12 ? extent number in FCB 

inr m 7 try the next extent 

; Code to invoke or re-invoke the create-next-extent routine 
; of SUBMIT—which will call "opsl" above if the extent exists? 


ops lxi 

d,subfcb 

open first (next?) extent 

jmp 

create 


7 Routine to 

create the $$$.SUB file 

org 

025Dh 


create call 

OPEN 

test $$$.SUB by opening it? 

inr 

a 7 

FFh -> OOh if open fails 

jnz 

opsl 

do above code if file exists 

lxi 

d,subfcb 

file does not exist, make it 

mvi 

c, 22 


call 

BDOS 


adi 

Olh 

set carry flag if retcode=FFh 

ret 



7 Replacement 

code for original logic to open $$$.SUB 

org 

04FEh 


call 

ops 

open last extent of $$$.SUB 

jc 

0517h 

error if open failed 

Ida 

subfcb+15 

7 use the FCB "record count" 

sta 

subfcb+32 

,* ..to set the "current record 

jmp 

051Dh 7 

continue with original code? 

end 




8 


Dr. Dobb’s Journal, Number 72, October 1982 

425 








achieved the same effect in software; we 
don’t know if it tries to. 

A decimal representation is better in 
just one way: it will get truncation errors 
on the numbers that people expect it to. 
Nobody is too surprised when the ex¬ 
pression ((l/3)*3) does not yield a result 
of 1.0; most people can picture the string 
0.333333 . . . being truncated and multi¬ 
plied by 3 to yield 0.999999. The trouble 
with binary (or any other radix) is that 
some fractions that have finite represen¬ 
tations in decimal become repeating “dec¬ 
imals” in another radix (and vice versa). 
When the system converts such a con¬ 
stant to its internal radix, it loses some 
precision before any calculations are done 
at all. For commercial arithmetic, the 
only answer is to use a fixed-point deci¬ 
mal representation like the ones available 
in PL/I and COBOL compilers. Floating¬ 
point arithmetic should never be used for 
commercial calculations, no matter what 
radix it is based on. 

John Palmer of Boonville, CA, is 
grumpy about his new CP/M-86 system, 
which he procured from Godbout along 
with the Godbout 8085/8088 dual pro¬ 
cessor board. “The Godbout hardware is 
very good,” he writes. “If you buy all the 
stuff from Godbout it will run.” How¬ 
ever, problems arose when he had to 
modify the Godbout BIOS. The first 
problem was that “the BIOS is very hard 
to modify without the Sorcim anti-Intel 
ACT assembler.” That would make us 
grumpy, too. There is no excuse for dis¬ 
tributing a BIOS that requires an assem¬ 
bler that isn’t part of the distributed sys¬ 
tem. “The source code for the BIOS is 
on the diskette,” Palmer reports, “but 
you cannot use it until you buy Sorcim’s 
ACT-86 for $175.” Palmer thinks this is 
a tacky way of selling assemblers, and we 
agree. 

Passing the Hat 

We’re scraping the bottom of the 
mailbag again, readers. You’ve all been 
very flattering in your praise of this col¬ 
umn, but you aren’t contributing. We 
need questions, like Knipp’s. Pitfalls and 
Warnings, like Palmer’s. Bugs, like 
Barker’s. Patches, like Pasky’s. Discov¬ 
eries, like Hammond’s. Puzzles. Confu¬ 
sions. Grumps. Cheap software. Material! 
Please? 


Dr. Dobb’s Journal, Number 72, October 1982 
426 



68000 Cross Assembler 


T he June 1982 issue of DDJ contained a brief description 
of the computer system which is being developed by my¬ 
self, Darryl Uchitil, and Jim Hannas as a test bed for sys¬ 
tem software and hardware using the Motorola 68000 micro¬ 
processor. The reader response to both DDJ and myself as a 
result of that article has been interesting and informative to 
Jim, Darryl and myself, and I would like to thank all of you 
who have called or written me since June. I will present at the 
end of this article a summary of answers to some of the most 
frequently asked questions about our system for the benefit of 
those who have not tried to contact me or who have written 
but have not yet received my reply. 

Cross-Assembler Description 

This article will describe the cross assembler that was 
mentioned in the June 1982 issue of DDJ. It was developed 
because we needed a way to write small programs for execu¬ 
tion on a single 68000 processor to test the hardware and to 
test the interface between the 68000 processors and the I/O 
bus control processor. The cross assembler for the 68000 has 
been run on two different PDP-11 systems, one running 
RT-11, and one running RSX-11M. It has also been run on a 
VAX/VMS system under the applications migration executive. 
It should be possible to adapt the assembler to other machines 
by recoding assembly-language subroutines for 32-bit arithme¬ 
tic and modifying the routines that reference octal constants, 
but as of this writing, no attempt has been made to do so. 

The cross assembler consists of a main program and a col¬ 
lection of subroutines, each performing part of the assembly 
process. The cross assembler is a two-pass assembler; the 
source code is read twice by the program. The first pass 
through the source code picks up all of the labels, and the 
second pass generates the listing and object files. All opera¬ 
tions to files are handled by individual subroutines. These 
subroutines are SOURCE, LIST, and OBJECT. All machine- 
dependent routines for opening and closing of files are located 
in these routines. 

Each of the three routines for the source, listing and ob¬ 
ject files is called when the program is first started, to deter¬ 
mine where each is to be sent. Some checking is done to deter¬ 
mine if just a carriage-return was typed, so that there is a de¬ 
fault of only a listing to the terminal and no object file is es¬ 
tablished. Once the source for the assembler and the destina¬ 
tions of the listing and object are established, the assembler 
starts the assembly by setting the pass number to one and calls 
the subroutine PARSE. 

PARSE scans the input line and determines if the state¬ 
ment is just a comment. If it is not a comment, it splits apart 
the label, opcode and operand fields of the statement, and re¬ 
turns pointers to these fields to be used by the statement eval¬ 
uation routines. 

After the line is parsed, the statement opcode is evaluated 
by the subroutine PRCESS. PRCESS calls DECOPC, which 
takes the characters pointed to by the opcode pointer from 


by Al Kossow 


Allen Kossow, Medical College of Wisconsin, Department of 
Physiology, 8701 Watertown Plank Road, Milwaukee, WI 
53226. 


PARSE and attempts to find an opcode that matches. If an 
opcode is found, the values of one or more skeletal opcodes 
(opcodes without effective addresses or sizes) are returned. 

After evaluating the opcode, the operands are evaluated 
to determine their general type. All “simple” operands, such as 
registers, are evaluated immediately, while “complex” oper¬ 
ands (i.e., operands containing labels) are not evaluated. 

If a valid opcode skeleton was returned, there will be a 
number returned by DECOPC which represents a general way 
in which to evaluate this type of operation. This number is 
used by PRCESS in a multi-way branch to different sections 
of code for evaluation of the opcode. Once in the specific sec¬ 
tion of code for the opcode, the operands are checked for 
validity in the opcode, and if the operand was “complex” it is 
evaluated and a value is returned. 

Each specific section of code for an opcode builds up the 
opcode skeleton, filling in the size and effective address fields 
as necessary for that type of instruction. The result of this 
evaluation is an array of 16-bit values which represent the re¬ 
sult of that line of the assembly, and a count of the number of 
words generated by that line. 

At the end of the opcode processing routine is the section 
of code that handles labels. If a label was detected and is valid 
for the opcode type, the current value of the location counter 
is placed in the symbol table entry for that label. 

If this is the second pass, the object and listing is generat¬ 
ed based on the values in the instruction word array; other¬ 
wise, the next line is fetched and the evaluation process is re¬ 
peated. After the last line of the program is read, the input file 
is closed, and a routine is called to print the contents of the 
symbol table. 


Frequently Asked Questions About 
The Multi-68000 System 

Q: Can I get a copy of your assembler? 

A: If you don’t feel like typing in the source code in this arti¬ 
cle, I can send you the source as it appears here on an 8” 
single-sided, single-density floppy disk in either CP/M or 
RT-11 format for $25 on an as-is, no-support basis. I 
can provide the source on a CP/M disk, but I have no way 
to compile it or test it there. 

Q: What is CL1CS? Where can I get it ? 

A: CLICS is a collection of subroutines for 2-D graphics 
developed by Mike Garrett while he was with the Depart¬ 
ment of Defense. Since the time I wrote the article, I 
have heard that Mike left DOD and started a company sell¬ 
ing graphics software written in C. I have not been able to 
reach him to determine if this is true or not. The CLICS 
software I have been working with came off of the 1980 
Spring DECUS RSX-11 special interest group symposium 
tape. This tape is available from the DECUS library. 


12 


Dr. Dobb’s Journal, Number 72, October 1982 

427 



Q: When/where can I buy one of your systems? 

A: The notion of selling this system has been discussed a 
number of times between the three of us, but we just 
don’t want to get into the computer business. The 
schematics and blank PC boards will probably be available 
from us on an as-is, no-support basis, along with the 
software we develop, but we have no plans to sell or sup¬ 
port systems. 

Q: Why didn’t you build your system on a “XYZ” bus? 

A: I had expected much more flack about using the PUNI- 
BUS than I actually received. The primary reason for not 
using a commercial bus was the desire to build a system 
which had a few large (8” by 15”) cards to minimize the 
number of cards to build. We also probably would not 
have used a special bus if we had planned on selling the 
system once we finished it. 


In closing, I would like to thank all of you that have taken 
the time to call or write me about our project, and will 
promise to keep you informed of our progress in future issues 
of DDJ. 


(Listing begins on page 14) 


Dr. Dobb’s Journal, Number 72, October 1982 
428 



68000 Cross Assembler 



14 


Dr. Dobb’s Journal, Number 72, October 1982 

429 


(Continued on column 2) I (Continued on column 3) | (Continued on page 16, column 1) 










Dr. Dobb’s Journal, Number 72, October 1982 


u o o 


u CJ 


17 

431 






Dr. Dobb’s Journal, Number 72, October 1982 


19 

433 


I 

i 



20 Dr. Dobb’s Journal, Number 72, October 1982 

434 


S’ 

Cl 


s 

o 

£ 


s 

o 

w 


a 32 _ *2£i s j *3 

i £ Ei £ £ 3 £ 3 £ £ 5 £b££ 


!*• 


U O U rH 



I 


£ 


8 


$ 


* 



I i! 
-*- —» 

■ 4 - CD 


* 

-*- 

-♦- 

t 


X 




s 

i 

& 

i 

5 


S 

N 



I 

I 


a u u u 



K ►— H- ►— 

S 8 8 S 


2 

CD 

s 


CO (N 0 > O 

a uj cat cat 
Ui f Ui Ul 

« « CM 

|SS£ 

• a p 

S 5 i S 

O - . o 

Ui O Ul UJ 

• UJ * • 

<c « « P 

&SS 8 


£ 

9 


<c 

£ 



Si 


U U U I 


£ 

s 


3 

£ 


3 

i CJ U 


s e 


8 § 

£* 

3t 

£ £ 

ig 


fi u u ki S 

££ g * g s 


° fe S 
££ -i S £ 
<e| X £ 3 
£ ° » £ “ 
£3833 


u u 

£ ££ 

- - U 

£ S 


1*3 5 

ac <=> ►— 


lii 

is! 


£ 
£ P 

«—• U 

3 £ 
£ 3 


£ 

2 

u. 

£ 


£ 


£ 


SI t 


O — CM « » ir> >0 fN CO O- 


£ 


U UUUUUOUU 


a 

£ 


8 


£ CO CD 
_ ££ 
S o « 


IIt 2 8§| 


O^CMW^IO>CNi 


I 

a § 

u. 

c_> 55 

& g 

S 0 

in 

g - » -c “ 

o ^ cm n 


*~g 

Sou 

£ £* 

lSs 

B S u 


£ 

i 


3 

0 

H 


& 

i 


= g*g 

8 SfcJ ? 


£ 5~ £ 

I i! i 




O CD CD <_» U U C_J UUUUUUUOUUUUUOUUUUUUUOUOUUU 


Dr. Dobb’s Journal, Number 72, October 1982 


21 

435 


(Continued on page 20, column 2) I (Continued on page 20, column 3) I (Continued on next 




22 

436 


Dr. Dobb’s Journal, Number 72, October 1982 






u n u o u m u c_j t-j 


U U U M U u U I 


Dr. Dobb’s Journal, Number 72, October 1982 


t_j u n u u u 


23 

437 



The Portable Pidgin 

Z80 Macro-Assembly Implementation 


W hen in doubt, write in a machine- 
independent language. Anyone 
who has seen a cherished program 
lie fallow for lack of portability will 
recognize the wisdom of this maxim. Yet 
machine-independent languages are nor¬ 
mally high-level affairs ill-suited for sup¬ 
porting the compact code and rapid exe¬ 
cution times required of many systems 
programs. Whence my excitement upon 
learning of William Gale’s Pidgin, a low- 
level, structured, portable programming 
language (DDJ #57). I suspect that Dr. 
Gale’s compiler generator Meta4 (DDJ 
#58) is only the first of many powerful 
systems programs that will be written in 
the flexible format of Pidgin. 

Pidgin is portable because it was de¬ 
signed to be supported by a portable 
compiler. Indeed, Dr. Gale has provided 
us with Tincmp, a Pidgin compiler written 
in Pidgin itself, yet organized to facilitate 
its relatively easy implementation on any 
machine. But only relatively! What I shall 
suggest here is that Tincmp can be imple¬ 
mented with little difficulty on any ma¬ 
chine for which a reasonably powerful 
macro-assembler exists. The example pre¬ 
sented here uses a Z80 microprocessor run¬ 
ning under CP/M, and the macroprocessor 
is Venus, a structured editor-assembler- 
linker-symbolic debugger which I’ve de¬ 
veloped over the past year. 

The strategy for implementing 
Tincmp is straightforward: generate an 
assembly-language version of the compil¬ 
er by translating each and every Pidgin 
statement into a macro. 

The result of this exercise is a new 
Tincmp source file which I have called 
Tinsource, shown in Listing 2, and a 
source file of macros called Tinmacro, 
shown in Listing 1. I shall discuss these 
two source files in turn. 

Since Venus uses standard assembly- 
language pseudo-ops (e.g., CP/M’s ASM.- 
COM), Tinsource should be easy to 
understand, subject to the following 
notes. First, Venus uses the pseudo-op 
INCBG <filename.filetype> to instruct 
the assembler to include the specified file 
at the beginning of the source code be¬ 
fore assembly. In this case, Tinmacro will 
be so included. Second, a string of one to 


by Herbert Gintis 

Dr. Herbert Gintis, Dept, of Economics, 
Harvard University, Cambridge, MA 
02138. 


five alphanumerics beginning with a 
letter, occurring where Venus expects a 
mnemonic opcode or pseudo-op, and fol¬ 
lowed by an exclamation point (!), is 
treated as a macro call. 

The meaning of the macros is either 
the same as that of the corresponding 
Pidgin statement, is indicated in the re¬ 
marks, or can be inferred by comparing 
Tinsource with Tincmp. 1 have attempted 
to use obvious mnemonics where possi¬ 
ble. Thus “B” stands for “byte”, “I” for 
“int”, “E” for “set equal to”, “O” for 
“or”, “A” for “and”, “EE” for “is equal 
to”, “LE” for “is less than or equal to”, 
and so forth. 

Since Venus is a structured assem¬ 
bler, I in fact implemented the control 
statements WHILE-ON-ENDWHILE and 
IF-ELSE-ENDIF directly. However, 
since structured facilities are rare in 
assemblers, I have rewritten Tinsource by 
treating these control statements as pro¬ 
gram labels. Thus a WHILE becomes the 
string “WH” followed by a number, and 
ENDWHILE becomes “NDWH” followed 
by a number. The ON in the WHILE- 
ENDWHILE construction is translated 
into the macro IFNOT, which moves be¬ 
yond the ENDWHILE if the condition 
tested is false. The IF-ELSE-ENDIF is 
similarly treated, using the common be¬ 
ginning string IF followed by a number. 
The CHOOSE ON-CASE construction is 
directly implemented as a macro. 

Tinmacro, given in Listing 1 is also 
by and large self-explanatory. The macro¬ 
processor of Venus is fairly standard. 
The name of the macro is written in 
the label column followed by the pseudo¬ 
op MACRO, followed in turn by a list of 
the prototype variables separated by 
commas. A proto-type variable is pre¬ 
ceded by the ampersand (&). The period 
(.) is a non-printed string terminator. 
Thus if the macroprocessor encounters 
the line 

LD HL, (I.&DEST) 

and the current value of &DEST is GG, 
the line will be expanded as 

LD HL, (IGG) 

Tinmacro is organized according to 
the principle that each byte variable in 
the object code generated (which is in 
this case an assembly source file) is pre¬ 
ceded by the string BB, and each integer 
variable is preceded by the single letter I. 
By comparing the listing of Tinmacro 


with the 8080A macros suggested by 
Andrew Bender ( DDJ #65 — March 
1982), the reader will notice that I have 
streamlined some of the coding, using the 
fact that the Z80 accumulator can be 
loaded without altering the flag condi¬ 
tions. 

To implement Tincmp for your ma¬ 
chine, alter Tinmacro and Tinsource to 
meet the conventions of your assembler. 
If you do not have a pseudo-op like 
INCBG, then Tinmacro will have to be 
merged directly with Tinsource, an easy 
task on a text editor. If you do not have 
a macroprocessor, you are probably out 
of luck, since the full source code of 
Tinsource with all macros expanded 
would probably run some 4000 lines. 

When Tinsource assembles without 
errors, then you must implement the 
Tincmp macros, following the example of 
Bender’s, perhaps with the streamlining 
suggested in Listing 1. Note that Bender’s 
implementation of the structured control 
statements uses multiple ORG’s, which 
are disliked by some relocating assem¬ 
blers. Venus does not mind such multiple 
ORG’s, but there is an easy alternative 
strategy which I have successfully tested 
anyway. 

The problem arises with the CHOOSE 
ON $$ and CASE $$ statements in 
Pidgin. Unlike the C language, Pidgin does 
not allow a program to “fall through” to 
the next CASE upon the execution of 
one CASE, but rather demands exiting 
the control structure. Thus in generating 
the assembly source code for the CASE 
$$ statement, the first line must be a 
jump over any remaining CASE $$ state¬ 
ments. However, this jump must be sup¬ 
pressed in the first such statement after 
the CHOOSE ON $$. The strategy for 
handling this is to have the CHOOSE ON 
$$ place a comment symbol (;) on the 
top of the stack, and have each CASE $$ 
immediately place the top of the stack in 
the destination file, and replace it with a 
blank ( ), which will be ignored by the as¬ 
sembler. The relevant Tincmp macros will 
then be: 


: CHOOSE ON $$; 

LD A, (BBtPlCtP2C) ; 

LD HL,ERASER; 

LD (HL),AtUOStL@;StU1S; 


Dr. Dobb’s Journal, Number 72, October 1982 


25 

439 



:CASE $$; 
t!OPt!9Pt!8P; 
tP9CJP NDCHtPON; 

CStP8N LD A, (BBtPICtP2C) ; 
CP (HL) ; 

JP NZ,CStU1StS8NtL@ StPOS; 


The final step in implementing 
Tincmp involves developing the system 
utilities, including the algebraic routines 
ICOMP, ISUB, CDEHL, IMUL, and IDIV, 
as well as the CP/M input-output rou¬ 
tines START, BREAD, BWRITE, PRT, 
IOPEN, MSG, CONOUT, and BCLOSE. 
The requirements for the algebraic rou¬ 
tines are well-described in Bender’s excel¬ 
lent article. CONOUT is essentially 
CP/M’s Direct Consol I/O (Function 6), 
but preserving all registers. PRT uses 
CONOUT to output the string pointed to 
by the HL register; the string must termi¬ 
nate with a carriage return (Odh in 
ASCII). MSG is the same as PRT, except 
that precisely 9 characters are transmit¬ 
ted. The I/O routines must be written 
using the system utilities associated with 
your assembler. Their functions will be 
obvious from the places in Listing 1 
where they are used, after a careful read¬ 
ing of the discussion of these routines in 
Bender’s article. 


•*} 

(Listing begins at right) 


26 

440 


Dr. Dobb’s Journal, Number 72, October 1982 


Tinmacro (Text begins on page 25) 

Listing One 







*f* 

rf* 



* 


t* 

t* 

*f* 



if* 


if* 

if* 

+ 

a* 


*—i 


if* 

+ 

ifi 

if* 


II 


+ 

II 

if* 

II 


a* 


II 

*f* 

II 

a* 


if* 


if* 

aa 

if* 

a* 


►H 


if* 

Ki 

if* 

” 


•• 



,p 

•• 


a 


- _i 

a 

J 


CD 

w 


ill X 

w 

I 

u rj 

oC 

<"N 


06 - 



06 oc 

■ 

a 


• 

a 


• 

III 111 

OH 

111 

*-• a 

III 06 

oi iii a 

111 ill 

o <5 ill 


«C 

v 06 

06 ill . 

oc 06 oc 

06 ill 

r- — 

111 

r 

r • 

r 06 | 1 | 

• r ■ 


a - 

111 

a 

-J *-< 

a r 111 

CE -J *-« 

a J 

on a 

w 

06 

x — 

06 a ~ 

06 x ~ 

06 I 


a 




a 




a 




a 




| 

» 

u u 

CD 


*- 

U U ill 


, 

u u 

CD 




CD 


X 


O6 oc 

oc 



oc 06 

o 6 



oc oc 

06 




06 



a 

r • 



a 

- • 

, 


a 

„ . 

, 


cr 





06 

111 CD 

CD 


oC 

CD ill 

CD 


oc 

CD CD 

CD 


o6 

CD 

t -4 

a 

a 

CD 

o6 ill ill 


• 

06 III 

ill 


. 

06 CD 

CD 


, 

06 


Z 

06 

w w 


-J CD 

r. r> 

•»' 

_l 

CD 

r w 


.j 

CD 



□ 


CD 

a .j 

m 

I 

CD 

a .j 

r- 

I 

CD 

a _j 


X 

CD 

a 

_J u 

r-i 

w 

06 X 

a 



06 I 

a 

W 


06 x 

a: 

w 


06 

I 


— 


Q Z L) 
Q Q Q LU a 
_KI J E Z 


* # , Q* ^ Q* oS q£ q§ q §5 CD z U q Z U =i 

H33il3^3J33iig3§33Bf3g|S33iS33|g^ggig3 8 3E23333ai33i3BI99g3B83a3 


cr» cs cu ro •*■ m u3 co cb <s -*cu to m u) <d cr« >s r-i oj ro • 
in ijtOgj u3u3U)u)i£iu3u3r^t s ^r'r s -r v -r''r N -r^h'r^cocococo< 



Z 

Z 

CD 


o 

o 

a 

H 

u 

u 

CD 

UJ 

UJ 

UJ 

IJ 

*"* 

CD 

*-• 

CD 

U1 U3 

r- co cn is 

cu ro <r 

IT) u3 N 

CD CO 

CD CO CO Cb 

cn cb cr> j> 

cn cb cn 


G* • J fO -t LI Ul f' C3 Cb S» • 


ioj n >t- bi u) n a) cn s cu ro 

, ^ -i *-« rH _ (,j ,;,j flj ,-»j OJ 


* 


* 

r-t 















J 



^s 










111 





CJ 





* 


* 

4 -» 

u 

CD 




u 







a 


X 


u cu a 


u 




a 



u 

oC 


a u 


u ®e 

CD 



CD 

* 


* 

•ti 


oc CL 




oc 







oC 




OC 

OC oc 


oc 




oC 



OC 



oC oc 


oC 


oC — 




4 


♦ 

4 -> 

«• 

. oc 





CL 



a 







.. 



• 

a 






. 

CD 



a 

, 

CD 





* 


* 

c 

iii 

►-* • 

_j 

UJ 

. 1 

4-4 

w 



w 





a 


Ul 

-< CD 

i.j 

Ol 

r. 



ai 



ill CD 


CD UJ CD 


CD 

CD 




H 

* 


4 

111 

o6 

w ►-< 

J. 

Q 

T 








—• 


oc 


oc 

w U 4 

u 

Ul 




X 



aC 

—* 


CD Q CD 


•<5 


cd a x . 



•w 

* 

T-< 

4 

s 

w 

r r 

m- 

r 


V- 

-J UJ 


X 

ill 





. 


. 

r , 

r- 


J 




J 


. 


•S 


_l 

, 


S - - — CD 




* 


4 

Ql 

a 

_l UJ 

-I 

-J 

llj 

_J 

-a uj 

V 

u 


a: 

-J 




a 

_J LU 

-I 

.. 

X 


a 

_j 

X 


a 

-J 


uT _r - 

I 

a 

J 

. LU .J ^ CD 


cr 

■J 


Ol 

4 

■—< 


x a 

X 

X 


X 

a ~ 

a a 

w 


«« 

X 

X 

— 


OC 

X Q 

X 

a 



«C 

X 

— 


oC 

X 

l" 

a i a 


oc 

I 

IQIiI- 



I 

* 

V 

4 






































* 

r -4 

4 

E 






































* 


4 

■r% 

o 











o 





n 






n 




o 





n 






* 

l/l 

4 












Q CE 




Q 

a: 





Q 

u: 



q tr 




Q 

cr 






* 

H 

4 

QJ 

u 


Ui 

Q 




u 



Z 

u 


u 


Z 

13 


Cl 



Z 

i i 


11 

z 

u 



a 

Z 

() 


a 




4 

-J 

4 

r 

a a q 

Ci 

Q X 

a 

Q Q 

A 

Q Q 

u a 

Q 

Z Ci 

UJ 

CI 

Q Q 

u 

a a 

UJ 

CL 

Ci 

z 

uj a 

Cl Q 

Q Q Q Q U 

cr 

a 

q q a q q uj a 

Q 



4 

■p 

e: 

_j 

a 

CI 

UJ 


-J J 


_J 

-J 

e: 

K 

_J 


.j 

X 

h. 

_j. j a 

_j 

-J 

K 

X 

-J 



z 

_l 

j J a .j 

-J z 

z 

_j 

_j _j a _j _i 

z 

z 

-I 


> oj ro in «d to 


cu ro -t in a) r-- od (T» «s »i cu to -4* m u3 T- co cn <s • < ru ro >!■ in U3 h- cn Cb s> ^ cu ro <r in <u3 n co cn s -< cu ro in gd n co 
H h h h -i h ,i h oj cu cu cu cu cu cu cu cu cu ro ro ro ro ro ro ro ro ro ro ^ t 4- <r g- <r <r -r in in in in in in in in in 


Dr. Dobb’s Journal, Number 72, October 1982 


(Continued on column 2) I (Continued on next page) 



;|oo ITinmacro (Listing continued, text begins on page 25) 

Listing One (Continued) 


1 • 4 w . ..J 

I Q ►-« X 

r • uT j _j u 

I Q I I Q C 


CL 

— a 

H *3 Hi 

* 

_j - 

oc . oC 

•^s 

i ~ 


UJ 

UJ 

^ ^ Hi 

Q 

—J UJ » Q 

Hi *- Hi 


i q a - 

•6 cr 


Hi J UJ iU 

•SICC v CI) v 


“d ~ - .J 

-U CD X 

• AU A 

i CQ »—• •—« 

l y-i «6 oo (i 

■ “6 . . a 

I « M J M 

i a ~ x ~ _i •« 

r .J a r- r- , n . 

IX H J QJ J jr m 

: w «s x q x ►. ~ 


a i 

a a z < 

a _j z o i.j ( 

u tr a j f . j 


06 - ~ j 

• Hi CJ X 

Hi Hi u 


- Hi a u -a r. 

v 03 a u ^ S ^ 

ia o<5 o6^cr - a -d . m 

' Hi .J . LU . UJ ^ UJ «. „ k-i ao 

a r <S » » » .. w _j ~ _j ci »• _J Hi 
_T .J }U J UJ rl IiJ J X »-« _J „|3i 
“ a XXXQXQQ[ w QXG w x (I _ 


l 53 ilfJ 33 ^ 33 l^ 3 f 3 ig 33 S^ 53 iil 3 gill 333 ^ 3 lIl 33 g^allfl 3 i 3 i 335 ^ 33 Si 95 g 


•4’ in UJ T" U) •& »•« 

LI bT bT 111 bl bT uJ »i) 

OJ fu OJ 01 "J OJ OJ OJ 



U 


Hi 

a 

IJ 

UJ 

\- 

UJ 

.. 1 

LU 

a 

Hi 

CO 

Hi 


1 ‘J i-i 4- D 
uD >J uJ ij 
OJ OJ OJ *'• j 


uJ I s * CO CO is »-i oj 
ill ifl y) ij) b (• fs 

oj ru oj oj oj oj oj 


^ n ^ i 3 oj o] a y s Eu ffl $ § m y i* s y s s s % z y i j ^ y $ & g g * « a 2 z " *° ^ ^ ?. r w 
11 .. . J " J " J " J " J11 flJ nj IIJ u ^ ^ CJ % *3 A A 3 -3 3 5 % 5 3 5 a w m ,T n n n .-i £ n 'A 14 14 


Hi -« -J a 

•d ~ I w Hi ®6 

- ► - -D . 

a j bj jwh 

•« i a x >- ~ 


CL *-< »-• Hi 

HH 06 *6 1 X 1 

•d • • ac «d 

. u . 

Hi - b- ffl 

Hi UJ _J Z Hi 

«d Q I ~ 



-J 

U oc 




I 

^ X 

a 



a 

- 

. IU 

K Hi 

Hi 


CL 

UJ 

. J Q 

UJ Hi 

Hi 



Q 

I U 

CO ~ 

od 


•3 



Z 2 

G 


a 


z 

2 

UJ D 

z 

tZ. 

Z 

Z O 

Q 

oC 

Z 

*-h a: 

UJ 

r. 

06 

b- od 

■f a 

a 


D . 

* is a 

a 

* 

O Hi 

rh <S)- 

*-* 


a. d 

Z -1 CC S CO 

oC 

OJ 

•*6 tn 

oc x a s *. 


n a 
q a: _j q tr 


SK? 33 S 55 sli 3323 sii 3 S 32 b 523 iig 2 ^'liig^iils^l?lssllsli 3 g 2 i§ii 3332 S^ 











Hi 


a 




a 



a 

»-« 





.J 

U 


Hi 


a 

Hi 

Hi 


a 

CD 


E 

E 

Hi 

*-* 

u 

*-« 

I 

a 

u 

oC 



UJ 

C6> 


i ■« 

-J 

a 

O 

H 

D 

UJ 

K 

UJ 

IU 

)- 

H 

, 

b- 

06 

h- 


I- 

ad 

CD 

o 

u 

UJ 

CO 

z 

Z 

_l 

Q 

UJ 

> 

Hi 

Z 


>■ 

CD 

z 

# 

a 

b- 


y-i 

* 1 


n 

>—i 

U 

G 

Hi 

Hi 

*-i 

»-* 

Hi 

Hi 


1—« 

(D 

cn 


UT d) h- CO CTi 1S1 OJ f’-j <r UT uD I s - OD CO Si *-* Oj 01 <r UT ai r- CO CO IS •-* t''J f’T -T UT CO N CO CO IS T-* OJ to >r bT uD HI CO IS» OJ OT bT a) h- CO CO s ’-I OJ M 4- bT uD N 
OJ t ij OJ OJ "J 01 f’T M 01 f’l f’T M l’l M M 4- 4- 4- 4- 4 >t 4- 4- 4 bT UT bT bT bT UT bT bT bT bT cO UT ul CjO CD u3 4) ID u) vO N N r^. N h» N CO CO CO 00 01 0) CO CO 


Dr. Dobb’s Journal, Number 72, October 1982 



ts 

a 

* 

c 

c 

O 


0 

0 


•■•J 

at 

•6 

I at 

r tXl 

a ~ 


•o a cu 

- a at 

cr k-* kh 

d otf a6 


lXi_.JUJQr.r- ill 

«iauaNa- 


o 

o 

CD 


z u 
z o 


. I- 

1 X 1 -J 

at a 
~ ~ z 
0 -a 
oc a u 




UJ 





cn 


il 



.j 





a 





u 


r t 





Cl 








Oj 







11. 



L. 


n 


t* 

► i 




<P 



I 



b • 


in 


2 

cn 


LU 

* 

a 

ui 


Q 

t* 


a 




UJ 



Cl 

w 

cn 

G 


h- 

cn 

n 

H 


a 

a 

a 

C1 


0 

-i 

X 

ID 



u 

CJ 

■ r- 



0 

0 

cn * 


Ul 

06 

06 

u <« 

j— 

UI 

■ Li! — h- 

• 

q . 

cn 

Q 

iii cn cc cc 

ill 

“6 Q 

hi 

66 

iii a uj a 

ill 

r III 

CD 

r. 

*-• -. j 



•6 

r 4 

0 g u - ini 

ill r- 

ill »• 


ill 

«iaiaaz 

oc a 

06 cr a 

M 

06 


. UJ 

ill Q 

|X| — oo 

r- J r- 
• J T M 

x ~z 


ip 

cr 


til o 

or 

C U 

- a . 
i y 
q z 

•Jl U 


u 

a 

e 

z 


3 

•S 

c 

o 

O 


o 

Q 0 
Z U 


z a 
a: q a 

- z u 


o 

Q 0 

: u 


— CD 
.jinn 
_J h Z CJ 


a 

.j a: q cr. 
. j j— z u 


o 
n 0 
z u 


o 

CJ cc 

z u 


_zy J cc h-z u zu _j h z cj _i _ih-zu ^ li z lj z 

QQUffaaaQaoQxLJCQLucQiixLKioaoKcxidffoiiianaciLiaQQQui 

JJIIJJUJDX.JIiJEE f iElJUUEZ.Jl.l.JOUlilEXJEF.IOhi:EJU H )F 




>-» 






X 


o 






n 


m 






CJ 


a 


CJ 








u 






u 


h- 



►-« 



/ 


u 






j 


cn 


z 





UJ 









u 


a 



cc 



11 


G 






11 


T 


i. 





cr 









u 


0 



3 



u 


U 






ai 


C) 







CJ 

in 

-r 

UJ u) 

r* 

CO 

Cn 

s •« 

oj m 


UJ 

0 

I s - 

0 

cn 

8 


Oj 

in 

<r 

UJ 

0 

t" 

ai 

0 



• j m 

< 

UJ 

ii) 


0 

0 


0) 

■'j 


OJ 

•■•j 

UJ 

in in 

in m 

m 

in 


in 

fn 

m 


■4" 

>r 

vj- 

<r 


--r 




U) 

i/J 



U) 

ui 





M 

3 

3 

in 

m 

m 

n in 

rn in 

rn 

in 

rn 

in 

in 

rn 

in 

in 

in 

rn 

in 

m 

in 

in 

rn 

m 

rn 

rn 

rn in 

rn 

rn 

rn 

n 

rn 

rn 

rn rn 


0 ) 

o 

3 
O 

(A 

E « 


o 

* 

H 

0) 


CJ r« 

CC ,x 

u a 
a >: 
} ■: u 
*. •: z 


J-- 

U) 


E 

u 

z 


• J • i -r iii ci h* 


* ¥ 

U 3 O'* 


h- CD 

cn iii i 

_J CJ t 

z z * 

D - 


Oo 

<N 

$L> 

& 

o 


o 


3 

•S 

c 


h- 

z 


a 

i 

u 




••• 





•- 








z 









•» 






rn 






m 









■ r- 



G 


m 




a 














*-< 

— 

E 













0 

,v 



a 


0 







a 





I 


0 




r- 


u 





u 







06 

3 

Z 










0 



a 6 

m oj 





06 

rn 

OJ 












06 

•'•J 

m 


— 


CJ 

U_ 




u 

0 






r. 

0 0 











0 




0 0 






0 

0 








0 





0 

0 


0 

»-« 

o 6 

•a 



»■« 

•3 

•6 






3 

>6 06 

06 







CO 



, 

0 


OJ 

06 06 



H 


OJ 

06 

06 





H 


0 

06 


d 


OJ 

o 6 

06 


Ot 

u_ 


• 



0 


• 

0 


H 



0 





K 




Z UJ 



X 

z 


0 

, , 



0 


0 







0 


06 



d 


0 




•c 

•6 

iTQ 

0 Q 



06 

0 

0 

t— 

cr 

cr 



06 

0 0 

►-< 

Z 

0 

0 




►-i ♦ 



X 



06 

0 0 



06 


06 

0 

0 





06 



0 




06 

0 

0 



r> 

0 

0 a 



r 

0 

0 


0 

a 



» 

0 0 


UI 

0 

Q 




0 IP 



06 

0 



0 0- 






0 

0 







<f 

0 


«6 



0 

0 


0 

u 

r- 

-G 



u 

w 

w 

01 


r- 




r- w 

r- 

a 


v 




h *• 

0 


( 

H 


r4 

. — G 

s» 


0 





G 




0 


d 


d 

Si • 


«-4 




0 

u 

—1 

u cr 



u 

r- 

0 

3 

r> 

M 



0 

0 - 

G 

o 

•> 

p>l 




0 -J 

to 


0 

0 


0 

G - X 



0 


0 

.1 


I 




0 


»—« 





0 

r _ 

G 



•6 

X 

Q 0 



«6 

a 

Q 

0 

a a 

z 



•6 

q a 

I 


a a 

z 




“6 I 

E 


E 

06 


06 

i a - 

a n a 



06 

X 

CC 


cr 

r>4 CC 



06 

d 

G 

X* ~ 


06 

a 

I 



o 



z 


a 






z z 


a 






z 

Z 

z 

O 


z 




O 






o 









n 





o 





Q CC 


G 

cr 

Q 

0 



G 


G 

cr a 

Q 

0 



.j 


G 

0 

0 

0 

Q 0 

G 

0 



Q 

0 





Q 0 








Q 0 




Q 

0 



Q 


Z U 


G 

H- 

Z 

U 



_i 



h- H 

z 

L) 



G 


J 

1- 

1 

1- 

Z CJ 

G H 


E 

Z 

L) 



u 


Z 

u 






0 


Z 

U 




z 

CJ 



Z 

a 

uj a 

Q 

a a 

X 

0 cr 

Q 

a 

a 

q a' 

a 

x x 0 a 

Q Q 

Q 

cr q 0 

a 

X 

X 

x u a q 

a 

X 

0 

0 0 0 

a 

D 

D 

P 

Q 0 

z 

Q 0 

a 

Q 

Q 

a 

Q 0 

o 

Q LiJ 

d 

D 

D 

Q Q 

LiJ 

a 

Q 

Q 

a 

gee 

G 

G (J 

0 

y 


G 

G 

CJ 

g a u 

0 0 



G G 

G 

CJ 

G o u 

0 

0 

0 

E E G 

U 0 *1 

Q 0 

E 

E 

G -J CJ 

G *-1 


-J 

E 

E 

G 

G U 

G 


X 

G 

E 

E 

.J 

.1 G G 

E 

E 

-J 

G 


Q 

cr 


CO (P 8 <-> > 
CO aj cn cn ; 


d 

G 






HI 

z 







UJ 




OH 

0 





0 



0 

0 






0 I- 

UJ 





»- 


a 


ID 



CJ 





UJ 



0 

0 






3 0 

a 





0 

0 

CD IS) 


U) 


CO 

z 





Ld 



0 

3 






0 a 

o 





a 

ui 

►- E 


E 


E 

0 





0 



UJ ii) 


CD 

Cn 

s 

T-i Oj 

rn 

'T UJ vO fN 

0 

cn 

S 

t-i oj rn >r 

UJ 

u) 

7 

e 

9 

8 

oj m n- 

UJ il) 

r • 

0 cn f-t ft oj in 

vC 

UJ 

0 


0 Cn 

Ul Ul 

CO 

U 

CO 

8 

rsrf Si Q 

•a 5i Si 


S 

S 






OJ 

Cu OJ 

OJ OJ 

•:-j •‘•j 

ij 

OJ 

oj m m m n 

rn 

rn 

rn 

rn 

m rn 

T-i W~i 




OJ 

OJ OJ 

0 

OJ OJ OJ 

0 

OJ 

cu 

OJ 

OJ OJ 0 cu 

0 

OJ 

OJ OJ CJ OJ 

OJ OJ 

0J 0J 

OJ OJ 

CJ 

OJ 

OJ OJ CJ OJ OJ 

cu 

cu oj 

OJ 

oj OJ 


ill 

UJ 


CJ) 

0 

J co cn 6i *1 cu rn 

■ n ^ UJ U) UJ UJ 
I OJ OJ OJ OJ OJ OJ OJ 


Dr. Dobb’s Journal, Number 72, October 1982 


29 

443 



3 

z 


0 

a 



cf 

z a 


X 


Q 



z 

E 







►H z 


u 


Z 



a 

a 






co 



b- 


LJ 




or 






ft 

LU 


a 





co 

a 






a 

Z UJ 


E 





z 

a 



E 



T Ct 

z 




Cl 



a 



a 

Z 



U LU 

-J tl 


Q 


LU 



a 

UJ 


a 

t-H 



U. 

-J 


h- b- 


t-H 



X 

b- 


t-i 




0 U- 

CD 


cn 





LU 

a 

a 

ii 

a 


-J 

CO 3 

Z CD 


hh E b- 



3 U ~ 



.1 

LU ct 


_J 


2 

CQ 

a z 

LD 

3 E re 


a 

n cr a 

01 

G 

0 a 

I Hi 

a 

»— i 

a vi ,h 

II 

*-'■ 

-J o 

a 

ii a 

0 

Q 

^ ii co 

o 

cr 

Z E 

CJ b- 

a 

ll 

ill u o 


Z 

_l 

_J 

Ll ~ I 

0 

0 t-1 

CO II ~ 

<*5 

CJ 

•-< LJ 

1 - LU 


a 

w + 

U 

LU t-i 

Q 

u. 

o a co 

H 

U II 

3 CI Ll 

a 

a 

X J- 

a e 

IT 

Q 

u. a ll 

U 

_J 

z a 


iii 

II 

ii a 

ii a co 

a 

E 

CJ 

e ct 

a 

>—< 

III CQ co 

II 

f b- 

3 E 

-.1 

quo 

a 

e a 

a n ii 

ii 


b- h- 

0 a 

n 

■ r- 

ll ll ii 

a 

X 3 

Cl ZD 

o 

z a o 

Q 

z 

a a i’i 

a 

O 

a a 

-i a 

• r 


u a 

CE 

3 a 

— Q 

LU 

uj a: j- 

»—i 

t-t 

-a: o 

a 

a 

E Z 

e a 



u o a 







■ r- 







E 








Q 





co 

a 

Z 










0 













lu 

T-i 

OJ 







t-i 



a 





n 







-J CO 

0 01 

( ) 



J 

T 1 



U 

1 

v 








t—i 

>< 

IU 

0 CJ 

a 

U f’l a 

-i 0 

0 



a 


t-i 





r. 



a i 

i 

1 


z u 

ui ,.t: 

LJ 



z 

T 



Ct 

Z 

E 







0 


X 

3 X 

t-t CE 0 

ct o bl 0 

t-H 0 0 

in 


0 

0 







LL 

a 


0 U 

O 

z 


r r 

r .£ 

v. 




i 






f’l 




0 


0 

0 a 

3 

- 3 


r. 

-fO 

- r- f’l 

r- f’l 


t-« 


a 

u 





3 a 


.. 

r. 


_j 

(J a 

CI CJ 

a 



i i 

a 



a 

a 

a a 

L. 




1-1 

0 

f—« 

C J q q 0 a q is) a 

ll 

f’i a 0 0 

0 a 0 

0 0 


X 

0 

a 

a 



ft 


>-i 

n 


ft 0 a 

0 

CL 

z 

U ill 

CL Z 

Oj 



u 

z 


0 

Ul 

CQ 

CQ CQ 


0 


T-i 

r. 

u 

» 

». H-t 

Z 0 0 z 

3 a 

0 

□ a m 0 

3 a t-H 

0 t-t 


b- 

0 

r- 

i- 


C'J 

u 


T- 

r 

Tl 

U 0 0 0 

a 






IT' 












a 



E » 











a 

0 

^"1 



y 

a 


1 




u 

a co 

a a 

Ll 

Cl 

X 

CI 

a 

u 

T 

u a 

i:. 

0 a 

CT 

1 


1 

Q 

a 

•-1 z a 

a u 

a a 

a a 

f’J 

f’i a a e 0 a 

0 a a 

a a 

0 

a 

a 

a 

a 

Q *~i 

I 

a 

z 

Q 

t“) 

I 

a u 

CI 

a 

u 

a co 

a a 

Oj 

Hi 

3 

a 

a 0 

3 

pj gci Pi 

3 a 

a 

>: 


E 

*"* 

a 

1-1 

t-i a 

a 0 

a a 

a a 

o o a a q 0 a 

0 a a 

■s a a 



a 



0 t-i 

3 

u 

1—1 



3 

0 u o 

a 

a 



co b- 

... 




i- 

Uj 





j- 

y 


z 





b- 

- b- 



- 0 |- 0 - - 

-• - b- 

- -■ b- 



.. 







.. 



-• 0 



- • 

co m 

a u co 

LJ 


co 

n 

rj 


Uj U 

Uj 

- CQ 

n 

o a o 

- ■ 


- - 

- i-i 

o - 

0 o 

t-i 0 

0 

0 a □ zd o 0 

t-i 0 Q 

a 0 □ 

a 

u 

0 

- • 

t-i 

CJ CJ 


- • 

n 

n 

-• 


- 0 a 

0 

0 

ill 

LU LU 

CQ z 

LU 

z 


LU 

z 

m 


LU Z 

hi CQ 0 

z 

u 

b- 

0 

►—1 

CQ 

t-i 

Ui 3 

Z 0 

0 z 

0 0 

0 

0 0 Z CO J— 0 

0 0 z 

: uj z 

b- 

z 

0 

0 

UJ 

z z 


0 

z 

11 

t-1 


0 0 0 

0 

0 

III 

z z 

LU U. 

CU 

t-1 

a 

Z 

ii 

(J 

CE 

DO t- i 

Uj 

LU . J U. 

ui 

LJ 

UJ 

LJ 

LU 

0 

0 CO 

ll III 

3 0 

0 0 

III 

0 0 0 a o 0 

0 0 0 

a z 0 

□ 

1-1 

0 

0 

0 

t-l 11 

a 

UJ 

t-i 

0 LU a 

0 0 0 

IU 

z 

III 

III III 

* 'H 

Ui 

Oj 


Ul 

t-H 

0 


CQ DO Uj Uj Hi 


CQ 0 CQ 


Uj 

t-*i 

►-< t-i 

ft 0 

0 *“» 

0 0 

0 

0 0 t—i CD CD 0 

0 0 t—< 

i 3 0 h 

0 

0 

0 

*“l 

t-i 

0 t-1 


0 

*-• 

»-i 

H 

•“1 

0 0 0 0 0 


OJ I’l 

cn 

X ft 

ft 

X 

<r 


OJ 

bl 

0 

h- 

ft 

OJ 

1 Q 

X -1 

Tl fs. 

X -n f’l 

f’l f’l 

3 

3 

n 

,i 


f’l 

f’l 

f’l 

CJ 

3 L) 

3 CJ --1 

ll. U. 

q :r 

a 

0 

X 

X 

Ll 

Ll 

0 

o 

Q O 

q a x 

t-1 t-1 

Z 3 

z 

t-i 

'l 

3 

t-i 

M 

t~i 

-J 

Z 3 

Z 3 3 


0 h- CQ IU ft T - OJ I'l -. 4 - ui 0 f- CO (?■ ft -1 OJ 10 vf 111 0 T" CO 0 ft i-i OJ f’l 4 bl U3 N 03 P S -h C'J f’l >J' 1)1 0 CQ O' ft «-< ''U £? 3 Is J ifl N CO Cn Q h OJ f’l <T Ul uO r- CO IX> 0 ri OJ f’l 

•4 -4 -4- Ll Ll Ul Ul Ul bl bl Ll Ul Ul 0 0 0 0 0 0 0 0 0 0 N r'' N N h- N N r-> N 0 0 ® 0 0 0 0 0 0 0 0 0 0 0 Cn 0 IT> 0 0 0» ft ft 5t ft ft ft ft ft ft ft *h ,1 ,1 ,1 T i 

■r-t t-I ri % I r-f -.1 '.in ,1 ri ,1 ,1 t -1 ri ri ri ,1 ri ,-t „ T 1 Y , ,1 H H .1 rl rt H H r! H ,1 H H H .H ,1 H v-l ri r-4 .H ri r-1 H H H rl rt rl H ' 1 OJ OJ OJ OJ OJ OJ OJ OJ OJ OJ OJ OJ OJ OJ OJ 



0 










0 r 

0 



ID 








Z II 

5 _ 

ji 


a 






0 


- t-1 L_ 

CJ 

■p 








m lu 


X 3 E 

>n 

• ri 


0 






cj in 




3 








a cj 


Tl 3 CO 




0 



0 



co a LJ 

g 

0 IU CO 


C 


O 



□ 


X 

t-t ui cn 

a 

O Z 0 


•ri 

Ll 

b- 


b- 

b- 


CJ 

a t-i o 

3 

3 


Ul 

LU 

a 


Z 3 

a 


b- 

q a 

u. 

0 0 Z 

□i 

QJ 

Q Q 

0 


a 

a 


0 

0 cn 


CO Z ZD 


Jl 

CO 

LJ 


b- 

Ul T. 

0 

0 

Cl - i-h 

r-% 

LU ti 

•H 


0 

a 


ZD 

a cj 

in 


\- a 

b- 

-J CO 0 

■P 

Ul 

0 0 

o 


CD 

Q J- 

X CJ 

3 

X u 

Z ID 

Z 0 ZD 

SI 

111 

b- ZD 

CO 



0 

U a 

a 

u a 0 

0 a 

3 0 0 

•ri 

ri 

LU CO 

0 j- 

X 

a 

13 0 

J- I CO 

0 

b- 0 o 

E _J 

0 J- 


Jl ft 

E ^ 

0 z 

b- 

co 

in 

UJ G t-1 

0 

lu j- 

E 0 

0 0 a 

a 

<T> LU 

a 0 or. 

Q UJ 

ID 


o . 

0 b- Q 

b- 

0 0 :r 

0 a 

U 3 3 - 


a cc co co 
a b- z 
b- t- ci 


-p 

> 




0 


Li. 





m iu lu 0 

b- u 

CJ 

a 

H 


CO 



Q 0 G Q 

U 0 

Z 3 3 

U 

b- 

0 


a 


0 0 



G 

t-i 








0 



ft 

E 

U 3 lr ll. 

co 

a 

3 

0 

a 

b- 

0 

0 

O O b- 

a 

g a e 

M 

0 

0 

0 

ti 


Z E 

o 

LU 

Z 

J • 

ul 

Ql 




Z 





a 

O 

a t-1 0 3 

t-i Cl 

E 

a 

Z 

0 

t-1 

a 

Cl 

cj a a . 

b- T 

U 0 

0 

E 

U 1 C 

a 


ll 

ti a 0 

z 

0 


a 

Ul 

3 




o 


CJ 



X 

0 

b- Ll 3 0 

3 UJ 


0 

0 

CJ 

0 

0 G 

o 

0 0 0 

t-H 0 U 

0 - 

0 

a 

3 CJ 

3 

o 

0 

3 0 b- 


O 

0 

0 

0) 

>, 




t-1 


b- 



u 

Ll 

0 0 

LU 

0 

0 

3 a 

t-1 

z u u lu 0 0 a 

0 CI 

x b- 

E 

0 

q a 

0 

b- 

Cl 

a a 

Ll 

Z 

G 

0 

5 _ 

Jl 




0 


2 





0 b- 

0 U. 

□ 



E 

a 

n 


co a a x 

t-1 X 0 

0 t-1 - 

3 

a 

LU b" 


z 


0 a 


0 

0 

a 

a 





z 

0 

n 



b- 

1 - 

b- O b- 1 

o 


G 

o 



-J X 

X 

o o o u 

Q U 0 

T 3 UJ 

2 

a 0 co 

0 

t-1 

2 

D X' 




o 

a 

ri 

T 

'ii 

:l it 

a 

z 




3 

t-i 

t-i 3 a 

0 

J-- 

0 

0 

, 

0 

u 

LU 

a 

o 

J- 




u 


t-i 

m cj 0 


0 


3 

ri 

0 

0 

0 0 

Cl 

a 

0 



a 

0 

0 Q a J- r- r 

Q Z 

0 u 

u 

Z 

a 

3 b- 

Q 

0 r r r 

r U Z 


r 


W , 

a 

0 

0 

q 0 a 

3 0 

a 

0 

l/l 

moo 

OGx 

3 

1- 

ft 

ft 

Z ft 

t-i 

t-i z z 3 a 0 

Z *-i 

n 

a 

a 

t-i 


0 I.U 

Z 

11 + -• u 

> CO 0 

I 3 CQ 

z 

a 

1 0 

0 

b- 

0 

Z 3 b- 

0 

CO 

3 

0 



3 

3 

3 3 

UJ 0 

a ft 

h oj iO <r 

0 0 

t-1 1-1 

Q Q UJ t-i O r - 

0 3 

-J 

E 

E 

E 

# 

Z U. 

t-* 

Q r - - 

-0 1-1 

- - - 

r 

- 

- - 

b- 

a 

0 

0 CO 0 

b- 

3 

0 

3 


CE CC ill Q LU Ll* 3 a ft -i OJ 01 >T 0 0 U x 
ujcrfliqbjfliiiifliutjcjuuucjuu 


CD to Ll -t OJ a Ll Ul Ll CO Ll 3 E 
QPbJlLlLlIJJJEZE 


q _i -« oj f’j a a u q lj 0 i j e z 
zzooooaaoooooo a 


ho.nuiLao:02 □ 
OQtcircflini-DDD 


O o 

2 I 

3 H 
O 0 > 
m c 

■3 w 


z .. jx, - - 

U a LtJ LiJ LlI 0 LU LU LU LxJ LU U LU LU LlI LU Lii UJ 

ci b- :i b- b- b- b- i— b- j- i— b- h~ b- b- b- b- b- b- 

T. X G>>>>>>>> >>>>>>>> 

X(_lJLiJlXi|X||X|CQp4Plp4iXiiXipQiXillC4iXilX|i;QiXi 


— pj - - pj pj - - - - - • Pj — — - - 

UJ LU LJ UJ LU U UJ LU LJ UJ UJ UJ IU 

b~ b- I- b - b- b~ b- J— b- b- I— I— b— 

>>>>>>>>>>>>> 

pjpjpupjpjpjpjpjpjpjpjpiaj 


UJ UJ UJ UJ UJ UJ U LO UJ LO u UJ LU UJ LO 

I— J— J-- b“ J— J— b- b- h* J— b' i— b - I— J— 

>>>>>>>>>>>>>>> 

pjpjpjpjpjpjpjpjpjpjpj pjpjpj ill 


LU UJ LO U UJ LU LO LO UJ LU 
l_ b- b- b- b- b- b- I- b- b- 
>>>>>>>>>> 
OQUiUiCQDQUiUiQioiQi 


bl UJ b' co 01 0 -r« OJ f’l <4 bl 0 J-- 0 0ft' OJ f’l 4" bl 0 r~ 0 0 ft -i OJ f'l <r bl 0 h- 0 0 ft -h OJ 01 <j- bl ul b~ co it. 0 .1 oj 01 -4- bl 0 r- 0 0 ft »i OJ 01 <4 bl 0 b- cO 
, i T-1 -ri »i -,1 OJ OJ OJ OJ OJ OJ OJ OJ OJ OJ 01 f-1 f’l 01 f’l (1 f’l f’l f’lfJ 4 4 4 C 4 4 4 <r 4 4 bl bl bl bl bl Ll bl bl Ll bl 0 0 0 0 0 0 0 0 0 0 r>- f'- ft ft ft ft ft ft 


Dr. Dobb’s Journal, Number 72, October 1982 












be 

0 





Ci. 

n 


4-i 

-J 


X 



<i> 

0 


C 

Z 


K 



O 

0 

cn 


0 

0 


CD 

LJ 

<iJ 

U) 

cc 


LU 

a 

•S 

cc 

o 


Cl 

O 

cn 

to 

h- 

O 

C 

»- 

Z 





co 


© 






Q. 

h- 0 



0 


-3- 






z 

a >-1 



0 


0 

0 


0 



0 

0 z 


0 



K-t 

z 


0 



z 

►-« ►—( 



.. 



v . 





>—i 

a 0 

a 

X 

0 

cr 

z 

CL 

a 

a: 

a 

X. 

H 

z 

Hi 

3 

z 

u 

o 

a 

3 

a 

3 

3 

*• 

- - 



H 

Hi h- 


0 


0 




CJ 


O 

O 

o 

- • 

o 


O 




z 


z 

0 

z 

0 

0 

0 

0 


- • 

-■ -• 

K-1 

a 

0 

O 

0 

0 

O 

0 

o 

a 

0 0 0 

Hi 0 

►-1 

0 

•-* 

0 

CD 0 

CD 


Z E Z 


£Ti Q CT 0 

CO Q h (T\ ^ & Si ^ Cn ^ ti d Q h cr 

, r- r - -S -1 OJ fO ” <f CO r-& ^ „ .. .. _ rl 

Z © ^ © 0 ^r-^^r-r-^UD -•>,-,....-.. (J ^ 

_jQ'S--'S'Si^C'jMLL' 4 -ca*-«Q.cT'Q:_jLLa:xiiici: 
MHHHHUUU(JUJ(JUMtnUNfliIIUH(- 


zzzzzzzzzzzzzzzzzzzz 

ooooaaoaoooopqqaoooa-i 

CJCJUCJCJCJCJUUOUCJCJCJ(J|JUL)CJUhi( 
Lxi Lxl LlI LiJ LU IxJ LxJ LxJ LJ LU LlJ LU LU LU LU Lxl LU LU LxJ Ixl LU i 

•—• ►—» i—» •—* •—• OQ 1 X 1 Pj 1 X 1 1 X 1 PCi 1 X 1 »—• CQ CQ 1 X 1 1 X 1 PQ 1 X 1 1 X 1 •—• i 



1— 

0 

0 0 





o a: 

0 


0 

z 

CC 0 

O 


o 

o 

H 0 

0 


0 

0 





0 

0 0 

od 


»-l 


0 0 


r-1 

0 

a 

II Q 

Q 

Q 

v 

a 


Z 

1—1 

Z 3 + 


a: z 

0 

II 

0 - + 

Ci 

a i-i 

z 

CJ 

a ii u 

a 

ii o 

z 

0 

O 0 0 

0 

Z 0 

o 

►H 

■- b- M 

0 

O 0 

u 


,r 

■ r- 


,r 


u 

u 




0 

0 

0 



*-1 

»—1 

0 



U - - 
aj a: 3 
►—< 1— »- 
- -CJ 
I tH CC Hi 
H 0 H HH 

hi 

3 

— Z - 
-i Z O U 
LU U Z 
ffl a u m 

UOffiH 

0 


u y- x a 
cj - s - ci 


IOjMdh|-|IiZH|I|H 

l-00CrO00O0CE0 


- 0 Z Z 

OJ Z □ - □ □ 

0 0 0 U CJ 

III a o LU LU LU 

CJ O 0 0 0 0 


Z -• 0 ill 
0 0 0-0 

u lu 0 iii cn 

LU Z O LU o 

Hi ill 0 ill 0 


0 

ro 

X 

0 

© 

r- 0 

X 0 

-p 

-1 z 

£ ' 

ro 

3 

ro 

•4- 

3 U 

i—i 0 

Ll 

0 

0 

0 

Q O 

o 


Z 

t-i 


Z O 

* * * cn 


I 0 © »i "J 

I -r-i OJ Oj OJ 

I OJ OJ OJ OJ 


o j- in iu 

:u OJ OJ OJ 
XI OJ CU OJ 


r' co cn © ■ 

OJ OJ OJ 0 l 
OJ OJ OJ OJ i 


I ro <iii'iu]ocoij'S^ oj ro <f in 0 r^- co co © »i oj 0 <r yi ^ mu ^ 15 .n oj 0 

I 0 0 0 0 0 0 M ^ < ■T ^ ^ ^ ^ in 0 0 UT 0 0 0 liJ 0 0 ill ul 11] u] 

I OJ OJ OJ OJ OJ OJ CU OJ OJ OJ OJ OJ OJ OJ OJ OJ CU CU CU OJ OJ OJ OJ CU OJ CU OJ OJ OJ OJ CU 


-f IfJ IJ] MS cn s 
0 UJ 0 U) 0 UJ f s - 
OJ Oj OJ CU OJ CU OJ 


*■« oj 0 in 0 

N M>- 

CU OJ OJ OJ OJ OJ 


r. 000-1 
r- 0 r- 0 0 

OJ OJ OJ OJ OJ 




0 

y 







ri 


LJ 




z 

hi 


cn 




»1 

U) 


o 



0 


z 





V 

CD 

CL 


o 



hi 

2 

LX 


h- 


:c 

Q 

hi 

X 




CJ 

CQ ci 

CC 

0 


or. 


h 

0 LlJ 

a 



LJ 

cc 

CI 

0 CC 

H 

0 

cn 

H 

a 

z 

Q 

0 

Z 

LJ 

0 

I-- 


0 


cn • i 

o 

z 

a 

0 

0 0 

CC 

a cc 

0 

a 

re 

0 

a hi 

a 

0 o 

CL 

LT. 

iu 

ii 

X 

0 

u a 

cn > 

cr 

z 


0 - 
0 <S> 

0 - © -I 


© -1 l 

h tt Q & 1 

0 IN hi hi I 


rr »-< X 
ui j. a 3 

Hi 3 Z 
z lu .j 
o a: 

z i- a 0 

CL h - h- 

: 0* 0 

: cc _J Ll a: or 
1 a *-1 iu I- h- 
: 3 Ll q a n 


-J +■* I- C) 0 ( 
E O Q (I I- I 
□ H h E 0 l 
h- _J 0 E 

0 cc 0 a : 

a x mj o a » 

h ci h a cr < 

a >: ci e # n. ; 


0 0 a 0 

: ir cc u 0 


0 

z 



i-i 


r 

o 



Q 


0 o 

cc 



cr 


M CC 

0 

0 


0 

o 

*1 u 


z 

a 

_j 

u 

0 a 

u 

ll 

Q 


CC II 

CL z 

u 

II 

r- 

0 

I— 

hi 


u 

0 

CC 

a © 

h- Q 

Q 

CJ 

0 

o 

CJ 

>-• a 

CL 

II 

II 

z 

0 ~ 

Z 0 

0 

0 

0 

0 

O 0 

•1 tr 

CC 

0 

0 


0 0 


4-> OJ 

£ CD -P I 

ai 0 s. 

‘•■1 -1 QJ Ul ' 

S. n -H I 

Q a >. ~ s. +> 

•• •• au a c 1 

- r- O v I H I 

..J ll. CC u 0 CC I 

Z -J (J - - - - u . 


LJ 0 ... ... - hi - - 

I- h I- l- !• I- I” l- h h H” h H- h- h- i- 
>>ZZZZZZZZZZZZZZZ2 
0 0 H H H hi hi hi hi H hi hi h I H H hi hi h 


> Z Z Z 0 Hi 000 

-a jaQOD 0 O0O 

_ n ... !_ J-. t- n .J I-- r.j u 0 - -• - - 0 ----- 0 0 0 

H I- H Z Z Z .crx 00 CD 000000000000 
ZZZ»-«n>-'CJCJ0000EEEE0EEEE000 

hi UK-1 cl 


© 0 - j il 0 q j a a m 
cj x -1 z_JOQ0crcrx 

•>3 0 »'r.r*r-r '*-*>3 

CC Q ll UUCJ0CJ00Q 
0 Z*-iuuunuH 0 Z 

rr.. rrr^rrrr 0 

»-«crcr 00 Qcr 00 cra:crcji 

0acDfflQ(iiiiffl<rcrcr03 


0 - 1-1 -- -- 0 - 001-0 

O0OO000O0OOOO 
00ZZ0000000Z0 
a 0 0 0 00000000 O 0 

00 KHKH 0000000 K- 10 ^ 


U Z OJ 0 0 

- cfO r- 0 
-1 S U 0 U 0 

(J CJ U K-i CJ i-i 

a 0 " u ci ci u a d 

0 0 0 cr a: 0 a a 


-• 0 -• l— 0 - • h- 
-• 0 O 0 OO 0 O 
0000 Z 0 LUZ 
00 O 00 O LU 0 
0000 *— 100 1 —1 


o h oj 0 - 3-00 r- 0 0 © Ti oj 0 <r 0 0 0 0 © -1 oj 0 <r 0 00 - 000-1 oj 0 < 1 - 0 0 r- 0 0 © -1 oj 0 <r in 

O'* © ••« OJ 0 <T 111 ijJ N CO O' G . 1 OJ 0 <r 0 0 h- 0 0 © © © © © © © © © © .1 --1 -i •-« *-i «-• -i ri T-I -1 oj OJ OJ OJ C'J OJ CU OJ oj oj 0 0 0 0 0 0 0 0 0 ro <t <f -<r -4- <r 

MDtOfl)lOCOaiCOa)aiCOiriCIUMn(JICnOUI'CIUIlt1<1HrtHTlrlHi1,HrtiHH.1r1,1HrlHrtnTlHr1rtH ,1 rl rl n rl rl t -1 <-1 r-t rl rl -rl ii rl rl rl rl vl rl r-1 


Dr. Dobb’s Journal, Number 72, October 1982 











to I Tinsource (Listing continued, text begins on page 25) 

Listing Two (Continued) 


n Q Cl 

• Oj E U 

a - x h < .« f. 

.J a 3 * vh 
- E Q LO U C <S 

• h 7 . i m a nj u 
: a ..... .. .... 
:Qa(iaoaua 
' — aaaDa--*a: 


(1 (J H H n H Cl III 

*-• z hi _j z m z lj at 

LU ►I IxJ 0) Lu u Ll LU cr LU 

H H H M W ill H (U »■! iB 


h. m in n a mu 

..j _i a a _j 

» a >. Q r r »- a . V- 

a £ e a I'j q 0 t m i- h oj 01 

ci»-a»-<aouQ>-.nziooo 


I-- - • - |X| - - t-UJUIUI 

p u H U H - D - UnOH-f- 
Z2iiiza)iiiniiiZiii7Hr^M 

u m LU h ij Lu o Ld h ixj u cr cr or 


^ ** cr mom (j 

<ra uj a a a u> m . - g 

m *-« oj m a a oj m »< a u i - - 

L) * i u .- *-i . :i: u . m - • m u 

-u u - a - u u . o , . 

-4 a h q q a a a h- q * t- cr a to a cl 
aa — zo — cru-zorna a . urn 


H • * - - ilj 

CJ LU m LU III -• 2D - Lu ill Oj 3 D - 

mm*-* m — *-• to m m — lu z - in a 

i a ui a cr lu lu o lu a a uj j u in o ui 


a 

H 





o 

m 





a 

z 






o 





o 

u 




X 

z 




T 

u 


X 



u 

h- 


LU 



I- 

UJ 

X 

X 



LU 

U 

r. j 




L. 


a ~ 

UJ 




H 

i a 

H 

«j3 


IU 


cn m 




l~ 

0 


cr 



> 


a m 

X 

* 


m 

a 

o m 


a 




H 

oc 

cr 


-j 

. j 

ii 


a 


a oj 

a 

T. 3 

X 

CC II 


cr o 

cr 

U h - 

u 

ii a 


UJ ll 

UJ 

1 

I-- 

a a 


h- U 

H* 

HI ■*• 

UJ 

a 


h-l \- 


u 

u 



J •-* 

J 



- u3 

m 



a 



m 



m 






10 


cf 

cr 


S 

r : m 

CO 

a: a 

G a 

Cf> OJ 



•'•J m «-i rij m oj cr ►h 01 a • < lj oj m o oj m 

TO .TUG . .O . .OXU .XU 

u . u u . - cr a - mo.o.o u. 

a p m h- o x a i a a a i m h- oi a .j h q z 

mza*-«zoauf4i-»ao*-i*-iazoi-4Zo 


- - - m - cri 

o u m lu- d - m - n - a- ui - iu 

ui m — g in m .ii f: iii 0 iii h iii mm m 

n a a lu a a lu o lu i iu o lu lu iu a a iu □ a 

ill ^ U m u ill 0 « m iii lq m mi h lJ h h U 


I U N CD cn S ■--< Oj io 
i . . .1 r.j . .j ,.j j 
w v.* <r .j- 


i j i.J nj nj n| nj |Vj f ,j ,V) l0 


- 10 <t U‘J i/l L- 0} iTi iSi »-« OJ 01 <4 Ll U) h- 03 Cb <S ’ 


''2 ♦ ' T ^ ^ UJ 111 ill U) in U"i Ul U i U1 U i iD tjj al lj G iD 0 0 S 2 N r- 






U H lL H Li. 

CC000E 


m m 
- □ - d - 
00000 
ui a lu □ ui 
00000 


rr 




Q 

iu 




Cl 

a 




a 

□ 









<*2 

z 





b-t 


Lu 


IU 



h X 


LO 

cr 


-< u 


a 

O 


cr \- 


m 

h- 


15 LU I 

0 


(I 


•o U O 


> 

Z 


)— 

m 

m 

CD 

CD 

I O UJ 

UJ 



K-t 

u « u 

0 Q 1' 

X 

CO 

y. lo 

t- cr 

*- u 

u 


a ui lu ui uj to 
a a uj u f ui 

a - u > a 

Q X 0 1- Z ffi 

u uj m h- 

t- Q Q Z J .J D 

a i- a a cr o 
i lu m u or cr 
> u iu u cl 

i z a a x h a 

I G O I- LU h h I 

i u a m x j .j u 


I 1 ' Q Q 

i u h h- or 

i a to m a 

i- x 
m e > u 

I o _l 
i o a: a iu 

h U n E 

K O 

q m .j z 

Q J G 0 
IC0Eh 


X ll U IS -I 

► E O O 

. . r . OJ 

m cc a a u o 

m a a u ~ d 


z - J~ 
o m a - 
uiuz0 m 
LU UJ U LU CT UI 
dKBHffihH 


0 

o 

... „ OJ 

a & > - mxz_io + i * uxau 
. u - cc ~ & - 

a lj q 0 0 i z J J a e e m 0 a 0 0 r 0 u 0 r 
ooooooooooooooammDt-HD 

zzzzzzzzzzzzm z - l- z z 

oooooaooaooaij- omoo o 

u o u o u u u lj u u u o m m u u z u u 


4 


S 

z 

u z 

.J 

1 


u 

O cr 

hi 

Z 



II 

a 

U -- 


m 

•s r- 

II 

IU X 

lu a 

LU 

in 

u oj 

cr 

m u 

Q .J 

cr 

LO 

ii ^ 

iu 

o 

hi 

o 

a 

E il 

li 

o u 

u — 

z 


Z E 

a 

x m 

a 

CD 

IU 

n E 

a 

o UI 

E 

hi 




•».... 

.»• ►—i 

.. 





i-i 










<s 

*-« 



s 

S 

u 

X 

E 

cr 


OJ 

h m - 
Q X O X 


0 

~ a a 

u 

D 

- Z E 

uGauuji-om.jz 

.J Q ,J O 


0 a a 


.I hi 

hi M E 

0 a a u o m j 

a m m 

E Z Z Z 

z 

m - 


- z 

Z 

m - h z - m 


Z 

o 

d m o 


a o 

- - o 

00OOUJD 

LU — U 

Q LU 

u 

LO iu z 

- • 

OU[- 

m cj 

m u z 0 0 0 

m lu z 

u m 

LU 

o z u 

UJ r- LU UJ 

LU LU UJ 

ouuiaoQ 

a hi hi 

lu a a a 

m 

0 m- 

E 

m - x 

hi M flj 

0 m •-< u u 0 

CJ •- hi 

m *-> u *-) 


OJ oj -t lfl UJ r - CO Cfi IS T 1 OJ 1 ) ,T Ll m 1^ 03 CO IS -1 OJ I’) T 0 0 N 0 L^ fii H OJ OJ UJ 0 03 0 Cat «4 OJ OJ -T UJ O h- OJ IT' Q ^ OJ 0 UJ O N 03 Cb S -h Oj f-J -4' UJ 

03 03 0) CO CO m CO 03 CO CO CO m cn tr> CO LTt cn CC. IS) <S IS IS Q Si IS S S» S *•« ,H .-1 oj OJ oj OJ -ij OJ nj OJ OJ oj 03 Oj Oj 03 01 01 m 01 01 Oj <4 -j- r T 't <r 

OJ OJ OJ OJ OJ oj oj oj oj oj OJ oj OJ OJ O.J Oj OJ OJ 01 01 01 01 01 01 01 01 01 OJ 0) 01 OJ OJ 01 01 01 01 01 01 01 OJ OJ OJ 01 01 01 01 01 01 01 01 01 01 OJ 01 OJ OJ OJ OJ OJ oj OJ OJ 01 01 


446 


Dr. Dobb’s Journal, Number 72, October 1982 







Ul 

X 




0 


lJ 

U 

a 


Pl 

h- 

1: 

a 

H 

01 


Q h- 


U 

cc 

Ul 

■— 


G 

>—1 

a 

h- 

U. 

cn 


z a 


K- 



01 


0 \- 

Ci 

OJ 

Z 

•• G 

IH 


G 

a 


O <S 

H G 

II 

a 

uj n 


2 

<S 

J 

G 

G 

cn 

LJ 

0 

Z f 

G II 

h- 

11 

0 cc 

h- 


K II 

a G 

H 

G 

0 a: 


h- 

G »- 

Ul 1- 

• • 

h- 

x 1 

cc 

-J 

\~ G 

UJ h 



U CJ 

X 

a 

... — 

Q •• 


... 






n 

0 




- H 

u 

a 


u 

h 

cr 

| 

>- 

* 

;r g z 

LU 



cr 

•X 

u. 

a 

CD 

a 

G 1 — t-i 

Q 

Ll 


H 

cr 


a 


a 

1-1 n 


0 

u 

01 

1 

1 — 

1 1 

> 

hH 

x - a 

in 


cr 


11 

CJ 

11 

.J 

II 

a 

a 

Q 

n 

O 


a 

cr 

Q. 

a 

K u 


Z 


H 

X 

tr 

cc 

k-i 

a: 

g a iu 

LU 

UJ 

a 


•—1 

H- 

1—< 

h- 

tH 

a a h 

H 


cr 

Q 

■» 

* 

•• 

G 

■ r- 

H Z *-1 


IU 

11 

Q 


G 


G 


G g cr 

a. 

01 

tii 

a 


01 


E 


0 •• 3 

3 

-J 

CD 


a - 

Oj C. OJ 01 i'U 

O - X U - T 

. :j u . -u 

Q D h Q h- (- Q 

a U — Z G 3 z 


' 01 — Oi »-• PI 01 -4- U. > >T 

. . - CJ— XCJL)— OL) 

I 3 n — • LJ — r r 

z h- z »- a r’lucaQcnaaaoitra 
i ci — a h u ooa:32O0)acrr uoi 


- sr c in oi 
a — g — g 

G PI G Q f’l 01 - 

- I CJ - X (J . 
g u . a: u .a 
oi a a a q a a 
— z o — z o - 


- oi a 
a ’■'uni 
< in pi cn — — 
, - x cj - 
: oi u . a a 
oiQiaa 

' — Z O — — 


— oi f’l oi cr G 

- - x u * x 

a oi u - g u 

aoioihaaz 

— — Z CJ — 3 Z 3 


CD - Z 

- 71 - UJ □ - CJ 

ill 01 Oj 01 U E — Z 

u a id o. a uj a u g — 

CD G - •“) CJ CO -j a — — 


h- ill - Oi Oi ill 

O - • D 111 U - G - G 

Z — G — IS) III 01 — 01 

ii. uj a iu □ iij □ y o 

— — CD — G — CD ' « CD 


Z - Hi - - - - pci 

O U - G U CJ CD O G - 

g g - g oizuz-cniii 

iauioaaHjii.inoij 

UUiBGhuaifflMElDili 


— LU — LU |X 

UJ 01 UJ G - 

iii a a iii a a u 

»-i •“> U — G L) •- 


I-.-. - ■ - — - - - - - - -|U lX| - f- ~ 

a - g co z - uminan iu co g g moo 

■ -.lu g — — g cn h e m iii oi iii oi oi e; iii z lu 
lUiiiaaLULuoiaciujh-ujiiiaah-oiio a u lu a z 

HH*-l|jHHHhUMHHHhUH0h0 G CE ill •“> Oj 


— '*-J i’i -r yi iii r • m ^ -1 cu >’i vr in g p- co C" is . i uj to sr li 

CO uj oj aj ® iD Oi CD CO i. 11 0> O' LTi O' IJI |T> IT* G O' <S <S <S >S <S S> 

si- si- sr <r vt t 4- sr >r >r -j- *4- >r si- >i- sr si sj ui in in in ui ui 


O) u. oi oi oj m oi oi q u. 

u ~ L) CJ U u U U Z - 

[U (, 1 -s- Ll ul P- OJ 01 <S "J f’l sr LI Ul N CO S H |-|J f’l •! Ill ifl MO cn S ^ OJ f’l sj- u j ijl Qj LTi S. H 01 pj >r ui G p. CO m iS — i‘ij fV] h-) in 

cr* o* cr» cn tn cn cu © <s <s <s <s <s s s »-• — — oj oj >j > u > j oj >'ij > .j oj oj m m m f-j m oi m ro m oi ^ ^ <r «*■ 

f -♦ .+ .-*■ ^ -T in in in in in in y-) y-j y-) y-] y-) |,t y-} y-j y-) y-) y-) y-) y^ y-) y-j y-j y-) y-) y-) y-, y-j y-, y-j y-^ y-j y-j y^ y^ y-j y^ y-, y-j y-j y-j y-, y-j y-j y^ y^ y^ y-j 



01 




Id 






►- 




a 






z 




O 




K-( 


LU 




z 




H 


E U 




G 



u 

r-i 


E a 




KH 



L J 

- 

Ll 

O 11 

E 


Ll 




II 


-J 

u — 

E 


G 

G 




E 


M 

— - 


H 

Z 




G 

UJ 

IU *■’ 






L- 

>—1 


cr 

a. « . 

J 


U 

G 


G 


ll 

a 

O ~ 

E 


u 

G 


G 


a 

z 

Z 01 

II 


II 



a 

G 

a 

CD 

G G 

a 


a 

u. 


u. 

G 


•-* 

►1 •• 

a 


a 



LiJ 



*» 

■* 

.- 


•» 

•- 


Q 


r. 












U 







( 1 

-s G 


a 

E 


a oj 




U 

l-H X 

CD 

- 

E 


G X 





- E 

OJ 

pi * ■« 

-G 


.3 

si r- 



n 

E Cn LU 

01 - 

G *- * 

G Ll 

G 

U Q 

G Ll 

I s * 

H 

►H 

G Ll E 

U X 

U ► • 

>: ^ 

E 

U Z 

X U ^ 

r- 

X 

M 

U 

. Cj 

.. » 1—< 

. r 

r 

- - OJ 

U - -co 

c i 

u 

. 

*-• - -cr 

Ll a 

l) G ► < 

a a 

E 

— a a 1 

Q G G Ll 

u 

Q 

0 ) 

cr a e 

~J z 

a g — 

a a 

E 

g cr a 3 

Z O G - 

G 

Z 

G 

naa- 

_ 

_ _ 

- 1- 


CD - G- 

- 1 - 




- - K- 

UJ 

LU CD U CO □ 

- • 

D ill [J 

IU 0 



til 

u - a 

01 

G U Z 

G Z 

CD 

G LU Z 

G Z 


E 

Ixl 

Z J z - 

a a 

a •- 

G U. 

UJ 

OZlitr 

a a u. a 

a 

a lu 


G Ll G 

u *-1 

L) 3 M 

1I1 — 

Uj 

03 mhj 

P LJ « *7 


a 

lD 

E 


u u. z 

UHlL 

- -LU 

ci a Q 
a a - cu 


AO a 
LU Z - O 
Z U. 01 h- 
11 ►-* z 01 


O CO 

t -4 



a uj 

►H 


z 

z 

- 

G 

LU 

G *-i 

E E 

O 

G 

g a 

z z 

a e 


1 - LU 

L -1 

U E 

Z 

> Q 

— — 

a - 

h-i 

CO 

a g _ 

E G 

E 



- 

»-• a - 

- Uh 

— a - — 

a - CJ 


Z 







£ 




Oj 

CD - 

CD 

ill CD 

-> 

G 



- G 

G »-•• 

-• G 

G G 

+> 

H 

•—1 


►h G - 

- G G 

— G - CD 

G - G h 

OJ 

— 

LU 

G 

G O CO 

GO*-’ 

G O G G 

CJ 01 O G 


a 


E 

G E 

EG — 

- G E - 

G E G a 


3 


a 

OJ 

CD 

OJ 

G OJ 

OJ 

X 

3 

pi 

r- co 

p- 
p- 
•4- u 

G 

G 

a x 

a 

OJ 

a u. 

g n 

U 

U 

— 3 

z 

CJ 

n 

L) -J 


sU P’- CD CO <S> th OJ f’l 4 bl Ul I'- 3 LTi G < OJ I I •? Ill ul f'- 3 P iS OJ I’l sf U1 U) I s - CO Iji iS *-« OJ f’l ^ UD -D f- CO 
t -4" t U~J uD Ul ifl 111 U'J U"J liT U'J UT *U UJ U3 U) ul Ml Ul ijl cD iJ3 I’- S- I s * h* h- N CO CO »B <D CD CD CO QD CO CO 

f’l f’l oi f’i f-n pi pi pi pi pi n pi r i f’j pi pi pi in pi pi pi pi m pi pi pi pi pi m pi p-j f’-j m p-j in m pi ro pi pi f’l pi pi pi 


o u 

Q ill 

G 

* * * CD 

OJ f’l 4 111 3 P 3 p S n OJ I’l sj UT ul P' CO QJ IS 

O' p P p Oi p p p p pi is is 15 0 (5 & it, ^ ^ 

f’l pi f’l pi pi pi pi pi pi pi 'j- sr sj- > 4 - <r > 4 - -r <r <- 4 - 


Dr. Dobb’s Journal, Number 72, October 1982 


33 

447 


2 Tinsource (Listing continued, text begins on page 25) 

Listing Two (Continued) 


Cl Q 
d z 

» r- -4- 

ainoi 
a a z z 


p - - 
ci ill u 
P uj z 
t.ii a i-« a 
1 X 1 ill 1 X 1 »—» 


z 

U'J 


cr 

f 


D 

CD d 


Ll 

►*« a: 
a >-< 


Z 



CD 

1 - v 


01 

:.i s 

Q 

Q *S 

Z 

Pi 



Ul D 

Li 11 

cn 

■j cn 

t-- Cl 

Q 

Z Q 

*-< d 

11 

*4 Z. 

ft •• 

a 

E UJ 

3 

a 



n 

Ul 

Q 



x 

Z 

Q 

G 

3 


-f 

G 

Ll 

cn 

, 

► * 

z 

Q 

d 

- 

r- 



Q CI CI c Q CT CI I 

0 • 4 a d z d 3 3 


- »■— - P 
■D - n O U ill 0 
cn oi j 2 uj id in 
a w 0 L. q li a tr 


i Q 0) 

4 Z Q 

c »■ v . 0 

C CI Q d CI X 

[ a z a a 3 


1 — - iu 

«OUiIil— 

J Z UJ III *“t 

) u. Q uj a: cr 

< iii iii 3 •-) 


a 

u 

o: 


n 

u 

M 


v 

OC 

1 Z 

P 

a: 

Pj 

d K 

n 

M 

ii 

a d 

p 

11 

II 

11 1 - 

a 

Pi 

P 

a u 

z 

Pi 

P 

a cr 

UJ 

• V 

• V 

■' ,r 


a 

Ct> U 

cr 



a u u (o n 

»• •• r l,U r 

cr a oi u a 

n a lq -< a 

u oi a 

Pi u iii pj a 


- - Pi t il 

P P d O F 

U UJ Pi Z li h- 111 I- 

J J Ul U. UJ Ul UJ L 

Pi Pi pj ^ at cr ii c 


d cn lj cr 
a u U LTi M 
• *' *- oj - 
cr cr oi u. a 

n a ii d 

Pi* (J Pi* li a 
ii U III Pi a 


d u_ u d x 
a: x u <s x cj 
- - ^ 
a a Pi u. d d 

iaiinda 

Pi" CJ ii Pi d* d~ 

Pi (J Pi Pi d d 


- - Pi t- Pi -Pi H Pi ii 

PiPidQE Pi Pi a O E a 
UJUliiZPih- LULiPZPPI-Ph- 
-J => W Ll UJ IP -J - J UJ ULi li LiJ UJ LU 
CQiXiiijh-'izicrixifficQ^tXitfjCiipja: 


® (X* S . H OJ f’l . 4 - U J i h- CJ pi G 

G G '+ *4 * 1 .-I — • . i r-i -r-i , H 

ii ii ii ii ii ii ii ii 0 0 0 0 


’ 1 1 J i’i <4 Ul ii N ii pi 

•■J -.J OJ . j oj oj oj . j oj OJ ro . 

u3 uD ii ii ip ii vj ip ip ii ii 1 


I tfl h- 03 Q 1 S h OJ f’l sf Ul 0 4*- CO C^i G oj pj 4 - in ul r^- 1 

1 ' } f ’x r ’2 "1 ^ ^ ^ ^ ^ <r ui U") uj Uj uj Uj un u j 1 

iiliuDiilililiiiiiiiuDiiiiuDix)u3u3u3yDuDiUiii 


1 S ’■* OJ 0 <f Ul 0 N <0 0 G OJ f 
100000000001^^1^ r 
000000000000 ,^ 


-4 u. _J u_ 

G CJ m OJ Z -J 

OJ . - OJ . 

ll ai ai d u. a a a (i 

H|Iiili 3 H(l 3 a 2 




h* 

P 



p 


p 




- ■ 

□ 

□ 


- • 

:i 

-• 

0 

(J 



P 

Z 

cn 


p 

cn 

p 

0 

z 


cr 

LU 

L. 

□ 

iX 

Li 

□ 

UJ 

0 

*-4 

a 

h i 

P 


0 

*1 

p 

0 

p 

0 

HI 

0 


li. 




E 




0 




cr 

cr 



U. 

d 

U 


U 

X 

0 


CJ 

13 

u 


P 



d 

D 


Q 


0 


d 

h- 

Q 

CJ 

LU 

LU 

Z 

I/I 

cr 

0 

0 

05 


K-. d a co d a: to 

CD d d (0 d d co 


Pi - 

XJ ii O □ ii □ o 

cnuzh-uzi- 

O Z Ll O UJ u. o 

CD ttl M 0 li M 0 






>, 




a£ 






O 


05 










r 


i- 






05 


a 


05 










JI 






QJ 


05 


a 






+j 









f’l 

f—i 

d 

+j 

H4 

-p 

U 

0 G 

•-I 

Oj <4 

X 

c. 

3 

ai 

0 

QJ 

0 

v4 OJ 

OJ 

OJ -4 

3 

3 

P 

0 

P 

0 

P 

it. Ll 

u. 

0 Li. 

Q 


0 


0 


0 

b-i r-4 

b-4 

•• » ^"4 

Z 

+ * 4 

0 

4 4 

4 0 

4 4 

4 0 


' 4 — rlliS 

• • r- ID CO w 
d d P I- U P 

adiiHHiii 


- b- z - z 

•4 □ □ >- O 

J Z (J E U 

cn Ll UJ UJ cn UJ 

M M li M ^ Qi 


G > d 

13 *4 > d 

H" *-4 b-4 

Ct 4-4 - 

m r l D Si D > 

- IS 3 h- -4 h- > X 

S rj Q Q m m m h x 

I U U h- U 1-1 Z r- ^ rH 

r - -Oj „ -> d X D . 

:QcnpQdd>dxi--d 

:zQ-«zdd*- 4 *-.nK-,d 


— H 

H O - Pj 
UJ Z Pi UJ 


- 1-4 O - cn f - - 

PjZ>E*- 4 l- 4 l -4 


UULUlPlQUl/HiahLUliJU 

HH|I|p|hP|HHHHMHp| 


u 0 

* * * 10 


C- co CTi IS >4 i.ij f'l <t UO <1: f'- CO in S *-1 Oj f’l -7 uj ii Pi to S >4 OJ f’l sf Ul ii L- cO Qj S '4 cu f’l <4 Ul 0 h- co Pi O *-4 oj f’l <r Ul ci N oO 0 G ’4 OJ f’l - 4 - u'J ii L- 

<r -4 4- Uj Uj Ul Ul U) Ul UJ UJ ID Ulu'i000ii00 0 00r''r'-Nr''-r s -N[''-t'-T''-r''<icOCO0cQCO0cOaicOcr>0 0 0000000&GGGGGGG 

Ul Ul Ul Ul Ul Ul Ul Ul Ul Ul Ul Ul Ul Ul Ul Ul Uj Uj Uj Uj Uj Uj Uj Ul Uj Uj Uj Uj Uj Ul Ul Uj Ul Uj Ul Ul Uj Uj Uj Ul Uj ul li") in Uj uj ul Ul Ul Ul Ul Ul Ul ii ii ul CO li li ii Ul 


Dr. Dobb’s Journal, Number 72, October 1982 


(Continued on column 2) \ £ n( | | ,j s ring 



Simplified 68000 Mnemonics 


I f the 68000 is to become the most 
important new computer of the next 
five years, there will necessarily be a 
tremendous amount of interest in its as¬ 
sembly language. The profusion of fea¬ 
tures and facilities on the 68000, how¬ 
ever, makes it very difficult to get a 
clear overall view of the instruction set. 
If one is to program reasonably well in 
assembly language, one must be able to 
lay out in one’s mind which facilities are 
there and which are not. With the 68000, 
it often seems as if one is let loose upon a 
tropical island, full of flowers of dazzling 
beauty but so much underbrush that it 
seems impossible to scale its central 
mountain peak and survey the totality of 
the landscape. 

The main problem is with the mne¬ 
monics. This is not to say that the mne¬ 
monics show any glaring examples of 
bad design. They are serviceable, as far as 
they go; it is simply that it is possible to 
do much better. The purpose of this 
paper is to propose a new collection of 
mnemonics for the 68000. This is not to 
say that an assembler has been written, 
using these mnemonics (at the moment 
the author does not have access to a 
68000-based system). Rather, the pur¬ 
pose here is to show the many advantages 
of this set of mnemonics over Motorola’s. 
There is precedent for such redesigns; 
for example, the mnemonics of the UNI- 
VAC 1100 series were redone by CSC in 
1962 in connection with CSC’s design of 
the EXEC II operating system for the 
1100 series (a project in which this au¬ 
thor took part). 

The new mnemonics are given in 
Table I. The notation used in Table I is 
explained in Table II. It is important to 
note that the new mnemonics allow the 
entire instruction repertoire of the 68000 
— together with very brief explanations 
of all instructions — to be presented upon 
one single-spaced page, with all notation- 
al conventions laid out on another single¬ 
spaced page. 

A program selected at random from a 
recent book on the 68000 1 is presented 
in Table III with both the old and new 
mnemonics. Except for labels, which re¬ 
main the same in the two cases, the total 
number of keystrokes of non-blank char- 


by W.D. Maurer 


W. D. Maurer, George Washington Univer¬ 
sity, S.E.A.S., Washington, DC 20052. 


acters has been reduced from 196 to 98 — 
a reduction of 50%. The simplicity of 
understanding for the new mnemonics 
makes it easy, in fact, to spot a bug in 
the program of Table III. This will be ex¬ 
plained in more detail at the end of the 
paper. 

The basic ideas behind the new mne¬ 
monics are as follows: 

(1) The data registers and the address 
registers all receive new designations. The 
data registers are now called the A, B, C, 
D, E, F, G, and H registers, each of which 
is 32 bits long. The address registers are 


now called the S, T, U, V, W, X, Y, and Z 
registers, and each of these is 32 bits long. 
In particular, the S register is the stack 
pointer, known conventionally as A7. 
(The original designations for the registers 
A through H are DO through D7, and 
those for S through Z are A7 through A0, 
in reverse order, with A0 corresponding 
to Z.) 

(2) There are no suffixes B, W, and L 
for byte, word, and long word operations. 
As we shall see, most instructions do not 
need such suffixes because they operate 
on data which has been defined as byte, 


G 

OPERATION 

DESCRIPTION 

G 

OPERATION 

DESCRIPTION 

3 

A v , i 

Add 1 to v 

3 

N v , i 

Logical AND i to v 

1 

Aa v 

Add v to a (v ^ It) 

6 

Na v 

Logical AND v to a 


ABab 

Add BCD lb to la 


N B a 

Negate BCD la 


AB tu 

Add BCD lMDu to lMDt 

A 

NBM vl 

Negate BCD vl in mem. 

A 

AMa_v 

Add £ to v (memory) 


NCC il 

Logical AND i;l_ to CC 

A 

ASd v 2 

Arith. shift v_2 by 1 


NGma 

Negate ma_ (2's comp.) 


ASd ma,sc 

Arlth. shift ma by sc 

A 

NGM v 

Negate v in memory 

1 

At vx 

Add vx to t 

3 

NM a v 

AND a to v (memory) 


AXm ab 

Add extended mb to ma 


NO 

No opera tion 


AXm t u 

" " mMDu to mMDt 

P 

N SR 12 

Logical AND i2 to SR 

2 

An v 

Add n to v (v 4 It) 


NTm a 

NOT mai^ (ones' compl.) 


B £ 

Branch to £ 

A 

NTM v 

NOT v in memory 


Baf 12 

Test bit 1_2_ of £, op t_ 

" " y_ (in b) " " " " 


NXma 

Negate extended ma 


Baf b 

A 

NXM v 

" " v_ in memory 


BaT 12 

Test bit 12 of a 

3 

0 v , i 

Logical OR i to v 


BaTb 

Test bit y (in b) of a 

6 

0 a v 

Logical OR v to a 


Bcc £ 

Branch to p on cc 


OCC il 

Logical OR il to CC 

A 

Bf vl,12 

Test bit 12 of vl,op f 

3 

OMa v 

OR a to v (memory) 

A 

Bfa vl 

" " (in a) " " " " 

P 

OSR 12 

Logical OR 12 to SS 


BS £ 

Branch to subroutine £ 

7 

PA v 

Push address of v 

3 

BT vl,12 

Test bit 12 of vl 

1 

PH v 

Push v (= M raMDS ,v) 

5 

BTa v_l 

Test bit (in £)of v_l^ 

1 

PL v 

Pull v (- M v ,mMSI) 

3 

C v_,i 

Compare 1 with v 


PMxa Q(t ) 

xa+-Q(t) alternate bytes 

1 

C a v 

Compare a with v(v^l£) 


Pxa Q (t) 

Q(£)«-xa " " (periph.) 

6 

CKa v2 

Check 2a bounded by v2 


R 

Return from subroutine 


Crat u 

Compare raMtI with mMul 


RE 

" " exeptn. (pull SR) 

1 

Ct vx 

Compare t with vx 

8 

RM rs.vx 

Regs to memory rs -*■ vx 


D cc a p 

Bcc $; a-^a-1; a=-l?->£; B: 


RMx t r s 

Regs-mem . (=RM rs.xMDt) 

6 

DSa v 2 

Divide signed Aa/v2 


ROd v 2 

Rotate v2 by 1 

6 

DUa v 2 

Divide unsigned Aa/v2 


R Od ma,sc 

Rotate ma by sc 


Ea 

Exchange halves of a 


RR 

Ret .{.restore (pull CC) 


Eg_h 

Exchange Ag with Ah 


RS 

Reset external devices 


FAt -12 

Frame allocation (iMt) 


RXd v 2 

Rot. extended v2 by 1 


FDt 

Frame deallocation 


RXd ma,sc 

Rot. extended ma by sc 


H 12 

Halt (status reg.-«-i2) 

3 

S v ,i 

Subtract i from v 

7 

J V 

Jump to v 

1 

Sa v 

Subtr . v from a (v^lt) 

7 

JS v 

Jump to subroutine v 


SBab 

Subtr. BCD lb from la 

7 

L At v 

Load t with addr. of v 


S B tu 

" " lMDu from lMDt 

A 

L Sd v 2 

Logical shift v2 by 1 

3 

See v 1 

Set vl=-l (if cc) or 0 


LSd ma,sc 

Logical shift ma by sc 

A 

SMa v 

Subtr. a from v (mem.) 

1 

M v r w 

Move w to v (wj^lt) 

1 

St vx 

Subtract vx from t 

1 

Ma v 

Move v to a (v^lt) 


SXmab 

Subtr. extended ma-mb 

6 

MCC v2 

Move v2 (byte 2) to CC 


SXmtu 

Subtr. ext. raMDt-mMDu 


MKa k 

Move signed const, k^a^ 

2 

Sri v 

Subtr. n from v (vjAlt) 

1 

MM a v 

Move ai to v (memory) 

3 

TE v 

Test v, set flags N&Z 

1 

MMt vx 

Move t to vie (memory) 


TR vn 

Trap, using vector vn 

9 

MR rs.vx 

Move vx -*■ registers rs 

3 

TS vl 

TE vl; vl(hi-order) =1 


MRxt rs 

Move regs(*=MR rs.xMtl) 


TV 

BVC 8; TR 7; 8: 

6 

M S a v 2 

Multiply signed 2a*v2 

3 

X v, i 

Exclusive OR i to v 

3 

MSM v 2 

Move status reg. to v2 


XCC il 

Exclusive OR il to CC 

P6 

MSR v2 

Move v2. to status reg. 

3 

XMa v 

Excl. OR a to v (mem.) 

P 

MSt 

Move t to S 

P 

XSR 12 

Exclusive OR i2 to SR 

1 

Mt vx 

Move vx to t 


Xxa 

Extend sign a (to xa) 

P 

MtS 

Move S to t 

3 

Z v 

Zero (cl ear) v 

6 

MUa v_2 

Multiply uns. 2 a *v 2 

I 





Table I 


36 


Dr. Dobb’s Journal, Number 72, October 1 982 

449 





word, or long word data, which deter¬ 
mines the type of the operation auto¬ 
matically. In cases where the length must 
be given, however, it is given in bytes as 
1, 2, or 4. This has the immediate advan¬ 
tage of avoiding the non-standard term 
“word.” (A word has 32 bits, not 16, on 
the IBM 360 and 370, for example.) 

The length designation appears in the 
following places: 

(a) In certain of the mnemonics. The in¬ 
struction whose Motorola mnemonic 
is ADDX.L D4,D3 (Add Extended, 
Long Word, register D4 to register 


D3) is simply AX4DE in the new 
mnemonics. Here D and E denote the 
D register (formerly D3) and the E 
register (formerly D4) and the 4 
denotes, very simply, “four bytes.” 
Note that the order is “destination 
first, then source”; see point (3) be¬ 
low to appreciate how much simpler 
this makes a great number of the 
mnemonics. The corresponding byte 
and word comparison instructions 
ADDX.B D4,D3 and ADDX.W D4, 
D3 become AX1DE and AX2DE re¬ 
spectively. 


(b) Preceding register designations. The 
instruction MOVE.L A3,A6 (old 
mnemonics) moves A3 to A6. Re¬ 
naming these registers W and T re¬ 
spectively, we can write M 4T,4W 
(reversing the order as before). It is 
simpler, however, to write MT 4W 
where MT means “move to the T 
register” and 4W means “four bytes 
of the W register.” The correspond¬ 
ing byte and word move instructions 
MOVE.B A3,A6 and MOVE.W A3, 
A6 become MT 1W and MT 2W re¬ 
spectively. 

(c) As part of more general addressing 
modes. Address register indirect ad¬ 
dressing, involving the X register, in 
a one-byte instruction, would be de¬ 
noted by 1MX ( one byte of memory 
indexed by X.) The same thing, with 
auto-increment or auto-decrement, 
would be 1MXI or 1MDX respective¬ 
ly. (Note that the I, for “increment,” 
follows the register name, whereas 
D, for “decrement,” precedes it; this 
resembles the placement of + and - 
in the Motorola mnemonics, and is 
done for the same reason - because 
incrementation follows the reference 
to memory, while decrementation 
precedes it.) Even the most complex 
mode, namely based indexed long, 
is straightforward; thus 2MU4E-9 
means “two bytes of memory, in¬ 
dexed by the U register and by all 
four bytes of the E register, minus 
the displacement 9.” The same thing 
in Motorola mnemonics would be 
-9(A5,D4.L) — over 50% more char¬ 
acters (not counting the extra ,W 
on the instruction mnemonic) and 
lacking the straightforward reada¬ 
bility of the new expression. 

(3) Most operation codes have only 
one argument. In fact the only operation 
codes with two arguments are moves, 
shifts, and immediate addressing in¬ 
structions. Thus M KPREV.KCURR 
sets K.PREV (in memory) equal to 
KCURR (in memory); A FCOUNT,5 
adds 5 to FCOUNT in memory; ASL 
1H,4 shifts 1H ( one byte of the H regis¬ 
ter, formerly known as D7) left arithme¬ 
tically by 4. (If the mnemonic variations 
are counted separately — if MA through 
MH are counted as eight instructions in¬ 
stead of one, for example — then almost 
75% of the mnemonics have no argu¬ 
ments; about 25% have one; and only 
2% have two.) 


a ■ A, B, C, D, E, F, G, or H (data registers) 
b. ■ A, B, C, D, E, F, G, or H (data registers) 

CC * condition code register (rightmost byte of SR) 
cc * one of the following forms: 


T 

true 

VC 

overflow clear 

F 

f alse 

VS 

overflow set 

HI 

high 

PL 

plus 

LS 

low or same 

MI 

m inu s 

CC 

carry clear 

GE 

greater or equ 

CS 

carry set 

LT 

less than 

NE 

not equal 

GT 

greater than 

EQ 

equa 1 

LE 

less or equal 

, (left shift) or R 

(right 

shift) 


e ■ label, label±j_, or other address expression (length defined 
in definition of given label) or mBlabel (length m) 

L " N (op-AND with 0), 0 (op=0R with 1), or X (op=X0R with 1) 
g. ■ A, B, C, D, E, F, G, H, S (stack pointer), T, U, V, W, 

X, Y, or Z (data register or address register); length ■ 4 
h -- same as & (second register in exchange instruction) 
i " X. (constant) or e_ (address of e) (immediate data) 

11 — same as i^ but length must be 1 (immediate data) 

12 — same as i but length must be 2 (immediate data) 

JL " $hh... or dd. . . or Zbb. . . where the h's are hexadecimal digits, 
the d's decimal digits, and the b's binary digits (constant) 
k -- +k is +0 through +127; -k is -1 through -128 (constant in move 
instruction MK; 8-bit displacement in based indexed modes) 

® — 1» 2, or 4 (length, or number of bytes in register or memory) 

n -- 1, 2, 3, 4, 5, 6, 7, or 8 (additive or subtractive constant) 

2 . ■ £.3, but *-32766 <.£.£. *+32769 (relative address; *"this loc.) 

£L * ®. (data) or mBJ_ (data, length m, at address j) (memory loc.) 

<j_2 -- same as £ but address must have length 2 (memory location) 

iliL -- same as £ but address must have length 3 (memory location) 

r. * £3, but *-126 £ r_ <_ *+129 (relative address; *“this location) 
rjB c zl/z2/.,. where each z_k - £ or £-h (£, h as above; £-h means 
registers £, £+1, h.) (multiple registers for MR and RM) 

sc ■ 1, 2, 3, 4, 5, 6, 7, 8, A, B, C, D, E, F, G, H (shift count 
-- in rightmost 6 bits of register A-H if this is specified) 

SR « status register (length 2; CC - rightmost byte of SR) 

t_ ■ S (stack pointer), T, U, V, W, X, Y, or Z (address registers) 

£ - S (stack pointer), T, U, V, W, X, Y, or Z (address registers) 

v ■ one of the following forms (variable in register or memory): 

#i. (immediate) (Groups 1 and 6 only) 

33 (absolute long) (All groups) 

£2 (absolute short) (All groups) 

ma (data register direct) (Groups 1, 2, 3, and 6 only) 

mt (address register direct) (Groups 1 and 2 only) 

mMt_ (address register indirect) (All groups) 

raM^I (post-increment) (All groups except 7 and 8) 

mMDlt (pre-decrement) (All groups except 7 and 9) 

mMt£ or mMt£±k. (based indexed short) (all groups) 

mMt4g_ or nMt4g±k (based indexed long) (all groups) 

^2(0 or raM£±£2 (based) (All groups) 

£ (relative) (Groups 1 and 5 through 9 only) 

r_(0 or r_(4£) (relative indexed) (Groups 1 and 5 through 9 only) 
vm -- like v but with length m (variable in register or memory) 
vjt — — 0 through 15 (vector number in trap instruction) 
w — like v in M v,w but group 3 and length must equal length of v 
x -- like m, but x 4 1 (vx is like v but with length 2 or 4) 

2 * ® B i (length m) or (length as small as possible) (integer) 


Table II 


Dr. Dobb’s Journal, Number 72, October 1982 
450 


37 



The destination register in a great 
number of the arguments is incorporated 
into the mnemonic. For the C register, 
for example (formerly D2), we have MC 
(move to C, AC, SC, CC (add, subtract, 
and compare), MSC, MUC, DSC, DUC 
(multiply and divide by C, signed and 
unsigned), NC (AND), OC (OR), and so 
on. For a few “operate to memory 
instructions” such as AMC (add to 
memory), SMC, NMC, and OMC, the C 
register is the source, rather than the 
destination. There are also EC (exchange 
halves of C), ECD (exchange C and D), 
NG4C (set C to its two’s complement), 
X2C and X4C (extend sign to two bytes 
or four bytes of C), and other such ex¬ 
ceptional cases. 

(4) All operations on data have 
lengths determined by the data unless 
otherwise directed. If AMOUNT is a 32- 
bit variable, then MF AMOUNT moves 
AMOUNT to the F register, and is a long- 
word (32-bit) operation. To move only 
one or two bytes of AMOUNT to the F 
register, one uses MF IB AMOUNT or MF 
2BAMOUNT respectively. 

Tables I and II are meant to be used 
in tandem. As an example, consider the 
second entry in Table I, namely A a v 
(Add v to a). By consulting Table II, one 
learns that a may be A, B, C, D, E, F, 
G, or H, and that v may have one of sev¬ 
eral forms. Let us consider the form mt. 


Here m is 1, 2, or 4, but in the descrip¬ 
tion of A<z v we find the designation 
“v=/=lr”; that is, v cannot be of the form 
1 1, so that m, here, must be 2 or 4, while 
t is S, T, U, V, W, X, Y, or Z (again by 
reference to Table II). Thus there are the 
following possibilities (for example): 

AA 2X 

(Add to A from two bytes of X) 
AD 4T 

(Add to D from four bytes of T) 

for a total of 128 (8 x 2 x 8) possibilities. 
Another form of v, in this same instruc¬ 
tion, is q 3, described as “same as q but 
address must have length 3.” So this is a 
24-bit (or three-byte) address, and we 
have the following further possibilities 
for v: 

q = e = label 

(label of location with three-byte 
address) 

q = mBj= 4B$hh. . . 

(length 4, but address still has 
length 3) 

q = e = labeli/ = label+dd. . . 
q = e = m Blabel 

(data has length m; address has 
length 3) 

This means that if NST is a two-byte vari¬ 
able, ECOUNT a four-byte variable, and 


F7 an array of single-byte variables, we 
could also write 

AF ECOUNT 

(Add to four bytes of F from 
ECOUNT) 

AD 4BSFC 

(Add to D from four bytes start¬ 
ing at address $FC) 

AG F7+50 

(Add to one byte of G from byte 
50 ofF7) 

AA 1BNST 

(Add to one byte of A from one 
byte of NST) 

Still another form of v, in this same in¬ 
struction, is #i, for immediate data. By 
Table II, we can have i = y = mBj = 
4B$hh. . . which gives us the possible 
instruction 

AD #4B$FC 

(Add $FC to four bytes of D) 

Note the two meanings of the 4 in 
4B$FC — in this instruction it means “the 
constant SFC as a four-byte constant,” 
whereas in AD 4B$FC it means “four 
bytes of memory.” 

The column headed G in Table I is 
the group. Instructions belong to groups, 
and each group can use only certain of 
the v options as specified in Table II. For 
example, the instruction LAf v belongs 
to group 7. This means that v can be of 
the form r(t) or r(4t), since these are 
specified in Table II as “groups 1 and 5 
through 9 only.” Thus if WTABLE is a 
suitable relative address, then each of the 
following is legal: 

LAT WTABLE(Z) 

(Load address of WTABLE plus Z 
into T) 

LAV WTABLE (4W) 

(Load address of WTABLE plus W 
into V) 

where two bytes of Z, and four bytes of 
W, are used. On the other hand, v cannot 
be of the form mMtl or mMD(, since 
these are specified in Table II as “all 
groups except 7 and 8” or “all groups ex¬ 
cept 7 and 9.” Thus each of the follow¬ 
ing is illegal: 

LAT 2MZI 

LAV 4MDW 

It should be noted that the length (1, 2, 
or 4) is meaningless in the case of the spe¬ 
cific instructions LA t, PAf, J, and JS. 
Thus in the program of Table III, LAY 


OLD 

MNEMONICS 


NEW MNEMONICS 

PGM 9 4A 

MOVEA .L 

LIST, AO 

PGM 9 

AA 

MZ 

LIST 


CLR. W 

DO 



Z 

2A 


MOVE. B 

(A 0) + ,D 0 



MA 

1MZI 


LEA 

-1(A0.D0.W), A1 



LAY 

1MZA-1 

SORT 

CLR . W 

D1 

SORT 


Z 

2 B 


MOVEA.L 

AO ,A2 



MX 

AZ 

NEXT 

MOVE.B 

(A2) + ,D 0 

NEXT 


MA 

1MXI 


CMP . B 

(A2 ) ,D0 



CA 

1MX 


BCC.S 

NSWITCH 



BCC 

NSWITCH 


MOVE. B 

(A2),D1 



MB 

1MX 


MOVE.B 

D1,-1(A2) 



MMB 

1MX-] 


MOVE.B 

DO,(A2) 



MM A 

1MX 


ADDQ.W 

II1 , D1 



Al 

2B 

N SWITCH 

CMPA.L 

A 2 ,A1 

NSWITCH 

CY 

AX 


BHI 

NEXT 



BHI 

NEXT 


TST .W 

D1 



TE 

2B 


BNE 

SORT 



BNE 

SORT 


RTS 




R 




REGISTERS 




OLD DO D1 D2 D3 

DA D5 D6 D7 AO 

Al A2 

A3 

AA A5 

A 6 A7 

NEW A 

BCD 

E F G H Z 

Y X 

W 

V U 

T S 









Table III 


38 


Dr. Dobb’s Journal, Number 72, October 1 982 

451 





1MZA-1 means “Load Address, into Y, 
of the memory word indexed by Z and 
by A, minus 1." The 1 before the M 
means nothing, but it must be present (al¬ 
though 2 or 4 would do just as well), 
since LAY MZA-1 would load the ad¬ 
dress of a variable called MZA, minus 1. 
(Privileged instructions are group P.) 

Examples of the v options which 
start with a length (1, 2, or 4) are as fol¬ 
lows: 

(1) 1C (one byte of the C register; the 
other three bytes are ignored) 

(2) 2V (two bytes of the V register; ex¬ 
tended through the other two bytes) 

(3) 1MU (one byte in memory, indexed 
by U — that is, the address of this 
byte is contained in U) 

(4) 2MWI (two bytes in memory, in¬ 
dexed by W, and then increment W 
by 2 after making the reference) 

(5) 4MDT (four bytes in memory, in¬ 
dexed by T, and decrement T by 4 
before making the reference) 

(6) 2MUE (two bytes in memory, in¬ 
dexed by U and by E — that is, the 
address of this byte is the sum of 
U and two bytes of E) 

(7) 1MWX (one byte in memory, in¬ 
dexed by W and by X) 

(8) 4MZ4G (four bytes in memory, in¬ 
dexed by Z and all four bytes of G) 

(9) 4MXY+8 (four bytes in memory, 
indexed by X and by Y, plus 8 — 
that is, the address of this byte is 
the sum of X and two bytes of Y, 
plus 8) 

(10) 1MZ4S-16 (one byte in memory, 
indexed by Z and by all four bytes 
of the stack pointer S, minus 16) 

Table IV gives examples of all the 
instructions in both the old and the new 
mnemonics; Table V gives a more expand¬ 
ed explanation of the program of Table 
III. We may note from Table V that the 
use of the new mnemonics makes it much 
easier to spot a bug in this sorting pro¬ 
gram, intended to sort a table of un¬ 
signed, single-byte quantities into de¬ 
scending order. The B register (formerly 
Dl) is being used as the exchange flag: 
set to zero (Z 2B), incremented to show 
the exchange (A1 2B), and tested at the 
end TE 2B). But it is also used as a tem¬ 
porary register in moving 1MX to 1MX-1 
(in the instructions MB 1MX and MMB 
1MX-1). If the bug is not fixed, the in¬ 
struction A1 2B might increment -1 to 


zero, making it look like the exchange sorted in the proper order. Therefore, MB 
flag is still clear. and A1 are executed only twice in each 

pass through the table. In the first pass, 
An example which shows the bug is $FF is moved into B and this is then in- 
that of a table of size greater than $82 cremented by 1 as a two-byte quantity, 
(that is, hexadecimal 82), which is al- producing $100. Subsequently, $FF is 
ready sorted in descending order except moved into the rightmost byte of B, leav- 
that its last two bytes are $FF (and no ing the rest of B undisturbed; this pro- 
other byte is $FF). In the given program, duces $1FF, which is then incremented 
these final two bytes move up by one to $200. Thus the final value of B is $200 
position in each pass through the table; at the end of the first pass, and, in gener- 
and only two exchanges (the ones involv- al, it is 2 x $k00 at the end of the kth 
ing these two bytes) are made in each pass. At the end of the 128th pass, there- 
pass, since the table is otherwise already fore, B will be zero; the TE then tests for 


MNEMONIC 

EXAMPLE 

MOTOROLA 

MNEMONIC 

MNEMONIC 

EXAMPLE 

MOTOROLA 

MNEMONIC 

A v, 1 

A 2MZI.1 

ADD .W #1, (A0) + 

N v , i 

N AMDY,8 

AND,L #8,-(Al) 

Aa v 

AA 4MDY 

ADD.L -(Al) ,D 0 1 

Na v 

NB 1MXI 

AND.B (A2)+,D1 

A Ba b 

ABGH 

ABCD D7,D6 

N B a 

NBC 

NB CD D2 

ABtu 

ABWX ABCD -(A2) ,-(A3) 

NBM v 1 

NBM 1MZT 

NBCD O(A0,A6) 

AMa v 

AMB BYT1 

ADD.B Dl,BYT 1 

NCC 11 

NCC $ 1A 

AND . B 11$ IK, SR 

ASd v 2 

ASR WD1 

ASR WDl 

NGma 

NG1A 

NEG.B DO 

A Sd ma, s c 

ASL 2 C,4 

ASL.W A,D2 

NGM v 

NGM 2MUD 

NEG.W 0(A5,D3) 

At vx 

AY 4MV 

ADD.L (A4),Al 

NM a v 

NMD AMDS 

AND.L D3 , -(A7) 

A Xm ab 

AX1DE 

ADDX.B DA,D3 

NO 

NO 

NOP 

AXm tu 

AX2UZ ADDX.W -(A0),-(A5) 

N SR 12 

NSR $FOF 

AND.W 0 $ F OF,SR 

An v 

A 4 4F 

AD DQ .L 0 4,D 5 

NTma 

NT2E 

NOT .W DA 

B E 

B LAB EL 1 

BRA LABEL 1 

NTM v 

NTM BYT1 

NOT.B BYT 1 

Baf 12 

BGN 8 

BCLR 08,D6 

NXma 

NXAF 

NEGX.L D5 

Baf b 

BHOF 

BSET D5.D7 

NXM v 

NXM IMS 

NEGX.B (A7) 

BaT 12 

BET $10 

BTST $10,D4 

0 v, i 

0 2G, $AA 

OR .W #$AA,D6 

BaTb 

BDTC 

BTST D2 , D 3 

Oa v 

OH BYT 1 

OR .B BYT 1,D 7 

Bcc p 

BEQ BETA 

BEQ BETA 

OCC il 

OCC 8 

OR . B It 8 , S R 

Bf v1,i2 

BX M9,6 

BCHG 6 ,M9 

0M a v 

OMB 4MUI 

OR.L Dl,(A5)+ 

Bfa vl 

BNB 1MTI 

BCLR Dl,(A6)+ 

OSR 12 

OSR $200 

OR . W 11$ 200 , SR 

BS £ 

BS PROG3 

B SR PROG 3 

PA v 

PA 1MV 

PEA (A4 ) 

BT vl, 12 

BT M8 , 3 

BTST 3,M8 

PH v 

PH WDl MOVE.W WD1 ,- (A7 ) 

BTa vl 

BTA 1MDZ 

BTST DO,-(A0) 
CMP.L D 5,(A7)+ 

PL v 

PL 4A MOVE.L (A 7 ) + ,D 0 

C v, 1 

C 4MSI , 5 

PMxa Oft) 

PM2B J(Z) 

MOVEP.W Dl,J ( A0) 

C a v 

CD 1A 

CMP.B DO , D3 

Pxa Q(t) 

P4C J (Y) 

MOVEP.L J ( Al ) , D2 

CKa v 2 

CKB WDl 

CHK WDl,Dl 

R 

R 

RTS 

Cm tu 

C4YZ CMPM.L (A 0) +,(Al) + 

RE 

RE 

RTE 

Ct vx 

CX 2W 

CMP.W A3,A2 

RM r s,vx 

RM T , LW1 

MOVEM.L A6, LW1 
" A1-A6,-(A0) 

Dc c a p 

DCSC LI9 

DBCS D2 , LI9 

RMxt rs 

RMAZ T-Y 

DSa v2 

DSD WDl 

DIVS WDl , D3 

ROd v 2 

R0R WDl 

ROR WDl 

DUa v 2 

DUE 2MU 

DIVU (A5) ,D4 

R Od m a , sc 

ROL ID , C 

ROL.B D2.D3 

Ea 

EF 

SWAP D 5 

RR 

RR 

RTR 

Egh 

ESA 

EXG A? DO 

RS 

RS 

RESET 

FAt -12 

FAZ -23 

LINK A0,-23 

RXd v 2 

RXL WDl 

ROXL WDl 

FDt 

FDT 

UNLK A6 

RXd ma,sc 

RXR AE , 6 

ROXR.L 6,DA 

H 12 

H $F0F0 

STOP $F0F0 

S v ,i 

S 1MW , 3 2 

SUB.B #32,(A3) 

J V 

J 1MYD-8 

JMP -8(A1,D3) 

Sa v SA 

2MXAG-8 SUB.W -8(A2,D6 . L),D0 

JS v 

JS 1MXAG 

JSR (A2.D6.W) 

SBab 

SBFE 

SBCD D4.D5 

LAt v 

LAW 1MVI 

LEA (A4)+,A3 

S B t u 

SBZY 

SBCD -(Al),-(A0) 

L Sd v2 

L SL WDl 

LSL WDl 

See v 1 

SGT BYT1 

SGT BYT1 

LSd ma,sc 

I,SR IF ,H 

LSR . B D7 ,D5 

SMa v 

SME 4MWH 

SUB.L D4,0(A3,D7) 

M v ,w 

M LW1.J3 

MOVE.L J3.LW1 

St vx 

SO 2F 

SUB.W D5 ,A5 

Ma v 

MC 2,#$C 

MOVE.B #$C,D2 

SXmab 

SX 4HB 

SUBX.L Dl,D7 

MCC v2 

MCC $1A 

MOVE $1A,CCR 

SXm tu 

SX1US SUBX.B -(A7),-(A5) 

MKa k 

MKH -100 

MOVEQ -100,D7 

Sn v 

S7 2MTI 

SUBQ.W #7,(A6) + 

MM a v 

MMA WD2 

MOVE.W DO,WD2 

TE v 

TE 1MV4X 

TST.B 0(A4,A2.W) 

MMt vx 

MMV AMU 

MOVE . L A4, (AS) 

TR vn 

TR 4 

TRAP 4 

MR rs,vx 

MR T,LW1 

MOV EM.L LW1,A 6 

TS vl 

TS 1G 

TAS D6 

MRxt rs 

MR4Z A/H 

" (A0)+,D0/D7 

TV 

TV 

TRAPV 

M S a v2 

MSB 2MDW 

MULS -(A3),D1 

X v, 1 

X 1MW,$FF 

EOR.B #$FF,(A3) 

MSM v2 

MSM 2MVX 

MOVE SR, ( A4)+ 

XCC 11 

XCC $2 

EOR.B #$ 2,SR 

M SR v 2 

MSR 2MU 

MOVE (A 5),SR 

XMa v 

XMD LW1 

EOR.L D 3,LW1 

MSt 

MSX 

MOVE A2,USP 

XSR 12 

XSR $400 

EOR.W 11$ 400,SR 

Mt vx 

MY 2MZ 

MOVE.W (A0),A1 

I Xxa 

X Ac 

EXT .L D 2 

MtS 

MUS 

MOVE USP.A5 

Z v 

Z 1MZ4Y+2 

CLR.B 2(A0,Al.W) 

MUa v2 

MUC WD3 

MULU WD3.D2 

1 




Table IV 


Dr. Dobb’s Journal, Number 72, October 1982 
452 


39 



PGM_9_4A 

MZ 

LIST 

(Move LIST, which is a 4-byte quan¬ 
tity, to the Z-register) 


Z 

2 A 

(Zero, or clear, two bytes of the 

A-register) 


MA 

1MZI 

(Move, to the A-register, one byte of 
memory, indexed by the Z-register, 
and then increment the Z-register by 1) 


LAY 

1MZA-1 

(Load into the Y-register the address 
in memory indexed by the Z register 
and by the A register, minus 1) 

SORT 

Z 

2B 

(Zero, or clear, two bytes of the 

B-r eg is ter ) 


MX 

4Z 

(Move, to the X-register, four bytes 
of the Z-register) 

NEXT 

MA 

1MXI 

(Move, to the A-register, one byte in 
memory, indexed by the X-register, and 
then increment the X-register by 1) 


CA 

1MX 

(Compare the A-register with one byte 
in memory, indexed by the X-register) 


BCC 

N S WITCH 

(Branch on carry clear to NSWITCH) 


MB 

1MX 

(Move, to the B-register, one byte in 
memory indexed by the X-register) 


MMB 

1MX-1 

(Move to memory, from the B-register, 
to one byte in memory, indexed by the 

X-register minus 1) 


MMA 

1MX 

(Move to memory, from the A-register, 
to one byte in memory, indexed by the 

X-r eg is t er ) 


A1 

2B 

(Add 1 to two bytes of the B-register) 

N SWITCH 

CY 

4X 

(Compare the Y-register with four bytes 
of the X-register) 


BHI 

NEXT 

(Branch on high, J. s ., Y > X, to NEXT) 


TE 

2B 

(Test two bytes of the B register) 


BNE 

R 

SORT (Branch to SORT on unequal to zero) 

(Return from subroutine) 

REGISTERS 

OLD DO 

D1 D 2 

D3 DA D5 

D6 D7 AO A1 A2 A3 A4 A5 A6 A7 

NEW A 

B C 

D E F 

GHZYXWVUTS 


Table V 

zero; the BNE does not branch back; and 
the sort terminates with the two $FF 
bytes in positions 129 and 130 from the 
end, instead of in the first two positions, 
where they belong. 


References 

1 Kane, G., D. Hawkins, and L. Leventhal, 
68000 Assembly Language Program¬ 
ming, Osborne/McGraw-Hill, Berkeley, 
1981. 




40 


Dr. Dobb’s Journal, Number 72, October 1982 





V/Wiw EXCHANGE 


by Gene Head 


Mail received after the first CP/M Ex¬ 
change was encouraging. There is heavy 
interest in modem communication and 
program exchange. The most often asked 
question was, “How do I get started using 
my modem?” Well, it may be as simple as 
one, two three. I say may because each 
modem installation is different. If you 
have a basic understanding of the follow¬ 
ing three steps, you should be able to get 
signed-on to a Remote CP/M (RCP/M) 
System using the MBOOT3 program (list¬ 
ing begins on page 47). 

1. Modem Status 

2. Modem Input 

3. Modem Output 

If you understand how the CP/M 
functions CONSOLE STATUS, CON¬ 
SOLE INPUT and CONSOLE OUTPUT 
operate, you also understand how the 
modem should operate. (Note: CONSOLE 
routines use only seven bits of data and 
the MODEM routines must use all 
eight bits.) Don’t be put off if you fail 
to understand how to get the CP/M 
CONSOLE functions to operate. You’ll 
need special assistance to get your mo¬ 
dem functional, but I have a plan for you 
too! 

MBOOT3 is a simple, stripped-down, 
receive-only version of Ward Christensen’s 
MODEM program. The idea is to get 
MBOOT3 operating and use it to down¬ 
load (receive) a full MODEM program 
from an RCP/M system. If you have a 
modem, the software to simulate a ter¬ 
minal and the ability to “capture” re¬ 
ceived data into a file, just log on to an 
RCP/M and command the remote com¬ 
puter to list the MBOOT3 file using the 
CP/M command TYPE. Otherwise, spend 
an hour or so and type in MBOOT3. 

Customize the hardware-dependent 
equates, assemble, and load MBOOT3. Fol¬ 
low the instructions on the facing page, 
remembering that each RCP/M system 
may be slightly different. Use your head. 
Don’t be discouraged. Try to get the SYS- 
tem OPerator’s help by using the CHAT 
command, or try ringing his bell by typ¬ 
ing control-G. You can’t hurt the remote 
system, and every RCP/M I’ve ever used 
has been very forgiving of errors and even 
untimely disconnections. 

Modem Hint # 1 

You will probably need cooperation 
from someone with a modem to test your 
system out before making long-distance 


42 

454 


calls to RCP/M’s. If you can’t get that 
special help, consider this: colleges with 
computer departments usually have a 
modem telephone for remote users. With¬ 
out an account number and/or password 
you can’t do much but you can at least 
verify that the basic communication, 
modem-to-modem, is operating. Execute 
the MBOOT3 program as directed in the 
source listing and then access any modem 
line by telephone. Try a few carriage re¬ 
turns to get the remote system “talking” 
to your system. Words like FULL and 
HALF and HELP might get results. Check 
it out. .. 

Special Assistance 

Here is where the novice can be 
helped by the experienced modem user. 
If you have the MODEM program work¬ 
ing on your system, send me a card 


with all the details about your specific 
hardware, the source listing of just the 
hardware-dependent equates and any 
unique hardware-dependent code, and 
how they are configured for your set-up. 

Likewise, if you have the hardware 
but don’t know exactly how to custom¬ 
ize the software, send me a card with 
your specific hardware specifications. 
(Keep it simple!) I’ll match your request 
with a known working system and send 
you the customization details. If I can’t 
get an exact match. I’ll send along the 
best data I have available. Be sure to 
enclose an SASE with your request. I’ll 
do free photocopying (but no free 
postage) as long as this doesn’t get too 
involved. . . 

If you can offer help or need help, 
let the “CP/M Exchange” know! Be sure 


Dr. Dobb’s Journal, Number 72, October 1982 


Downloading MODEM Using 
MBOOT3 

First, execute MBOOT3 as in¬ 
structed in the source listing (begins 
on page 47). It will sign on, but there 
will be no screen activity after the 
sign-on messages. In the TERMINAL 
mode, all displayed console characters 
come from the remote system. Even 
keys from your keyboard are “echoed” 
back, so if there is no remote system 
to echo back the keystrokes, you 
won’t see them on your CRT. 

Now, call a remote CP/M System 
(see list on page 44), when you hear 
the remote modem carrier tone, con¬ 
nect your modem to the phone line. 
The two modems are now connected 
and your computer is “talking” to the 
remote computer. Press the Return 
key once a second until you see the re¬ 
mote computer’s sign-on message, usu¬ 
ally asking how many nulls you need. 
(Answer 0 to the nulls question if 
you’re using a video terminal.) 

Follow the host computer’s in¬ 
structions until you finally reach the 
CP/M operating level with the expect¬ 
ed A>. You are now in control of the 
remote machine. 

To find the MODEM program 
type: 

DIR MODEM *.* 


This will show you the exact name of 
the MODEM files available. You should 
see in the listing the MODEM. ASM file 
or some similar source code file. 

To receive the file type: 

XMODEM filename.type 

The remote system should tell you 
that XMODEM is ready to send the 
requested file, then it will wait. There 
will be no further screen activity from 
the host computer. It will look as 
though you have lost control, but 
don’t fret. The host is waiting for your 
MBOOT3 program to send special pro¬ 
tocol characters to begin the transfer 
and won’t respond to your keyboard 
characters until the transfer is com¬ 
pleted or aborted. 

Now that you know the host is 
ready to send and is waiting for you to 
be ready to receive, press your ESCape 
key. This key tells MBOOT3 to receive 
the file the host is sending. 

Most CP/M commands are avail¬ 
able to remote users, so use the re¬ 
mote system just as you would your 
local computer. Be sure to sign off by 
typing BYE and disconnect your 
modem from your phone line, if it 
isn’t automatically disconnected by 
your software. 

As with any new operation, prac¬ 
tice and experience are the best teach¬ 
ers. 




to include your disk format and complete 
modem configuration. Send your com¬ 
plete name, address, city, state, zip, and 
phone with area code. 

Exchange Mail 

The first response to the CP/M Ex¬ 
change came from DDJ contributor 
Bob Blum. Bob suggested electronic mail 
for communication. If the interest is 
there, we might be able to compile a 
directory of those using this form of 
communication. I will make my RCP/M 
system available if there is serious inter¬ 
est. Anyone else have ideas along these 
lines? Bob is also preparing a contribution 
on keyboard buffering in a modified CCP 
for CP/M that will be included in a future 
“CP/M Exchange.” 

The most specific letter seeking help 
came from Charles Henderson of Mid¬ 
land, Texas. Charles is interested in why 
SPEED and FAST won’t work with CP/M 
2.x. He suspects the track buffering is 
involved but doesn’t understand all the 
implications. A definitive article on 
track and sector skewing, interleaving, 
sector tables, etc. would be most appro¬ 
priate. If you have a solid understanding 
of these principles, write a paper and send 
it in! Share with others what you have 
learned. 

Dana Trout of Goleta, California, 
notes that CP/M Function #37 does not 
work as described in the manual. This 
function to reset the disk drives will reset 
all drives except the current default drive. 
If the current default drive is set to R/O 
and function thirty-seven is executed, 
the default drive is still in R/O! Anyone 
have a fix and/or explanation for this? 

Roland Lupient, KB9RR, has ham 
radio gear, an Altair 8800 and CP/M 
User’s Group volume 41. He would like 
to hear from anyone who can help inter¬ 
face the ham gear and computer (ad¬ 
dress: 1953 Graham Lane, Mosinee, WI 
54455). 

Finally, William Burnett of Sinton, 
Texas, wonders if there are any Super¬ 
brain users out there who have access to 
the CP/M User’s Library? The same ques¬ 
tion can be asked about North Star, Os¬ 
borne, and all the other five-inch for¬ 
mats. If you can copy the CP/M User’s 
Library to any of the many five-inch disk 
formats, let me know. I suspect you will 
be in great demand, and while you may 


not make a lot of money at this, a couple 
of bucks copying fee seems reasonable. 

That covers it for now. Every letter 
to the “CP/M Exchange” has received 
either a personal response or was noted 
in this column. If you have something to 
contribute, a question or comment, let’s 
hear from you! 


Dr. Dobb’s Journal, Number 72, October 1982 


43 

455 




Remote CP/M Software Exchange Systems 
List #24 

Last Revised March 21,1982 

f 


List #24 revised and updated courtesy of Hyde Park 
RCPM, CP/M-Net, and Mississauga RCPM. 

This is part of a CP/M file called RCPMLIST.xx. It is found 
on most RCP/M systems. The systems presented here are 
representative of what you can expect to find. Each was 
“up” as of February, 1982, unless otherwise noted. Log on 
to any system and then get a copy of this complete file for 
an accurate directory. 

This is a partial list. 

California 

(Best) 

Bakersfield, CA 

CP/M-Net tm , (805) 527-9321, Kelly Smith 
No A.L.D.S.; 1900-2300 (PST) Monday-Friday, 

1900 Friday to 0700 Monday 
110-600+ baud 

20 Mb of files on 2 hard disks (=8 logical disks) 

System now includes SIG/M Vol. 1-10 = E:, SIG/M 
Vol. 11-20= F:, SIG/M Vol 21-25 = G:. XMODEM 
’DISKMENU.DOC’ for entire system directory (over 
2100 files now available!). 

Garden Grove, CA 

G.F.R.N. Data Exchange RBBS, (714) 534-1547, 

Doug Laing 
24 hour operation 
300 and 1200 baud 
5 Mb of files on 4 drives 

Special interest in amateur radio and Apple/CPM. This is 
the second G.F.R.N. system. 

Larkspur, CA 

Larkspur RBBS/RCPM (415) 461-7726, Jim C. 

24 hour operation 
Up as of 3/20/81 

110, 300, 450, 710 baud; SPRINT, ITT, MCI 
2+ Mb on 2 drives 

The system carries general and new CP/M software. System 
now running MP/M and plans are afoot to install a 
second telephone line, making it the first multi-user 
remote system. SYSOP will assist others in bringing up 
MP/M remotely. 

Palos Verdes, CA 

G.F.R.N. Data Exchange RBBS, (213) 541-2503, 

Skip Hansen 
24 hour operation 

300 and 1200 baud; SPRINT, MCI, ITT 
2.4 Mb of files on 2 drives 

Standard CP/M software with special interest in ham radio- 
related programs. Soon (with MP/M) will also be reach¬ 
able through 450 MHz radio. 

44 

456 


San Diego, CA 

San Diego RCPM, (714) 271-5615, Brian Kantor 
No call back; 24 hour operation 
300 and 1200 baud; ITT, SPRINT, MCI 
2.4 Mb of files on 2 drives 

Now with 212-compatible modem; yet another 1200-baud. 

East Central 

Allentown, PA 

AUentown RBBS/RCPM System, (215) 398-3937, 

Bill Ernest 

No call back; 24 hour operation 

110, 300,450, 600, 710 baud; SPRINT and ITT 

4.25 Mb of files on hard disk (=4 logical disks) 

General CP/M software. Bulletin board of the Lehigh 
Valley Computer Club. 

Grafton, VA 

Grafton, VA RBBS, (804) 898-7493, Dave Holmes 
No call back, no A.L.D.S; 24 hour operation 
300 baud 

200 Kb of files on 2 drives 

Carries CP/M, TRS-80 and Apple software; plans for 

setting up a dual system (on one line) with an LNW-80 
as well as the CP/M computer. Active as bulletin board. 
McClean, VA 

RLP RCP/M, McClean, VA, (703) 524-2549, Bob Plouffe 

No call back; 24 hour operation 

SPRINT and MCI 

4 (N*) drives with 640 Kb of files 

Running CBBS for messages. New system. 

Midwest 

Chicago (area), IL 

Calamity Cliffs Computer Center, (312) 234-9257 
No call back; 1400-0200 daily 
300, 450, 600 baud; ITT, SPRINT, MCI 
11 Mb of files on a hard disk and 2 floppies 
Many of the CPMUG and SIG/M programs available by 
request. 

Chicago, IL 

HUG-CBBS, (312) 671-4992, Paul Mayer, Dave Leonard 
No call back; 2300 to 1900, 7 days/week 
300 baud; SPRINT, ITT, MCI 
2 Mb of files on 2 drives 

H89-based, operated for the Heath-Zenith Users’ Group 
and with a special interest in H19- and H89-adapted 
(as well as general CP/M) software. 

Hyde Park, IL 

Hyde Park RCPM/RBBS, (312) 955-4493, Ben Bronson 
No call back ; 0100-1700 daily 
110, 300,450, 600, 710 baud; SPRINT, ITT, MCI 
2 Mb of files on 2 drives 

Special interest in hardware and software reviews, C pro¬ 
grams, and very recent releases of standard programs. 
SYSOP now testing substantial upgrade of RBBS 
programs. 

Royal Oak, MI 

Royal Oak CP/M, (313) 759-6569, Keith Petersen 

Dr. Dobb’s Journal, Number 72, October 1982 



Call back; 24 hour operation 

110, 300, 450, 600 baud — 1200 baud modem now avail¬ 
able on request; use CHAT or leave a message if you 
want the 212A switched in - ITT, SPRINT, MCI 
600 Kb on two floppy drives and 10 Mb on hard disk 
(=2 logical drives) 

Emphasis on new programs and recent updates of standard 
programs. 

Westland, Ml 

Westland, MI RBBS/RCPM, (313) 729-1905, Ron Fowler 

Call back; 24 hour operation 

110, 300, 450 and 600 baud; SPRINT, MCI, ITT 

1.4 Mb of files on 2 drives 

Emphasis on very recent releases. 

Northeast 

Lexington, MA 

Superbrain RCPM, (617) 862-0781, Paul Kelly 
1900-0700 Weekdays, 24 hours weekends 
110, 300, 1200 baud; SPRINT, ITT, MCI 
300 Kb files on-line 

Special interest in Superbrain-adapted CP/M programs. 
Bearsville, NY 

Bearsville Town SJBBS, (914) 679-6559, Hank Szyszka 
No call back, no A.L.D.S. 

110.300.450.600. 710 baud 
2 Mb of files on 4 drives 

Installing MP/M. All CP/MUG programs available by re¬ 
quest. General CP/M software. 

Rochester, NY 

Rochester RBBS, (716) 223-1 100, Arnie McCall 
No call back; 24 hour operation 
110 and 300 baud; SPRINT, MCI, ITT 
1.8 Mb of files on 3 drives 

S-100 based. General CP/M software. The standard RBBS/ 
RCPM system co-exists with a separate passworded 
message system called DataStar, which can be entered 
from CP/M but runs on a separate computer. 600 baud 
capability expected soon. 

Hamilton, ON 

Hamilton Area Packet Radio Network (HAPN). (416) 335- 
6620, Stu Beal 

No A.L.D.S; 24 hour operation 
110,300,450, 600, 710 baud 
@? Kb files on-line 

New system. System is also linked to radio network and 
may be accessed via ham radio. Special interest in 
radio software. 

Toronto, ON 

Mississauga, Ontario RCPM, (416) 826-5394, Jud Newell 
No A.L.D.S.; 24 hour operation 

110.300.450.600, 710, 1200 baud 

20 Mb hard disk now on-line 24 hours a day 
1200 baud Vadic/Bell 212A standard both supported. 
300/1200 baud modem available Monday-Friday, 
PMMI weekends. XMODEM, DISKMENU.DOC and 
MAST.CAT for details of over 3000 available files. 
System now restricted to CP/M users only by use of a 
familiarity question. 


Toronto, ON 

Mississauga, Ontario HUG-RCP/M, (416) 273-3011 
No A.L.D.S.; 1800-0600 weekdays, 24 hours weekends 
110, 300,450, 600, 710 baud 
2+ Mb of files on 5 drives 
Toronto Heath Users’ Group. 


South 

Huntsville, AL 

NACS/UAH RBBS/RCPM, (205) 895-6749, Don Wilkes 
Call back, no A.L.D.S.; 24 hour operation 
110, 300,450,600 baud 
700 Kb files on 4 drives 

Run for North Alabama Computer Society at University 
of Alabama; general CP/M software. 

Louisville, KY 

Louisville RBBS/RCPM, (502) 245-7811, Mike Jung 
No call back; 0900-2100 weekdays, 24 hours weekends 
300 baud; SPRINT, MCI 
2.5 Mb of files on 5 drives 

Heath/Zenith-based. Emphasis on BASIC software. Some 
HDOS stuff available for downloading. 

Fort Mill, SC 

Fort Mill RIBBS, (803) 547-6576, Bill Taylor 
Up as of 08/15/81 

No call back, no A.L.D.S.; 24 hour operation 
300 and 1200 baud 
3 Mb of files on 2 drives 

Heath/Zenith-based with 212-compatible modem. The 
system carries ham stuff, general software, and on-line 
games. The fourth 1200-baud RCM. 

(Listing begins at right) 


Dr. Dobb’s Journal, Number 72, October 1982 


45 

457 




0 

in 

<r 

izi 


0 

> 

u 

CL 

LU 
E 0 

X X 

U 

O 
O h- 
K 

UJ 

0 cj 
Q O 
o e 
E 

E 

e a: 
a: uj 

UJ h- 


x UJ 
UJ 

o 

O h- 

h- 

0 
UJ a. 
I <t 
0 U 
h- 0 
U UJ 


E 

X X 

u o 
H O 
_l (N 

<r <* 


2 Q 
x a z 
*-< UJ uj 


i i 

111 0 


G G 
G Q 

UJ UJ 

CL 

I 

U 

K 

*-< U 
x If) 
' 00 ' 


X 

E 


G 

a 

UJ 


Q 

O 

r 

E cn 
UJ UJ 
Q > 
O «T 
E I 


E U 
E • 
a. q 


UJ UJ 
G G 
X X 
I- K 


UJ 
UJ 0 
G 0 

x <r 
j- x 


G G 

a a 

UJ UJ 


e x 

E (J 

' 0. Q 


2 cn 

*-» h- 
I Z 
CD UJ 
G E 
-J UJ 
0. CL 

HH 

O G 
O G 
-< UJ 
I i X 

cn 

h* 
J— CL 
Q O 

2 a. 

E 
E Ul 
UJ Q 
Q O 
O E 
E 

iX 

-J G 

<r o 
2 > 
X 

UJ CL 
H O 
x U 
UJ 

cn 

2 UJ 

<1 K 

<r 

0 G 
2 G 
UJ 

cn 

G UJ 

in 
UJ UJ 
CL X 
<T h- 

G Ul 
Q 0 
> 2 
<r 
x x 
-< g 


X 

<z 

(f) 
Q G 

G X 
UJ O 
X X 


J- X 

- o 

2 X 

_J 
h- K 
X U 
O 

X Q 
I- 
E 

UJ X 

a <x 
o i 
E U 


2 s s s 


G *- Q Q X 

X If) 2 X H 

^ r-j K) «*• 


UJ 

cn i 

-J S i i i 

<c <i O uj rv 

lL O <T t K) 


G G D G 3 

a a a q g 

UJ UJ UJ UJ uj 

a 

x -< cm to «*■ 

x u u CJ CJ 

l-J-Hh-J- 

Z 2 Z 2 Z 


0 

X 

0 

I 

K 

X 

O Q 
X 2 
0 

fg 

0 K 
0 
z 0 

0 K 
Q 

ie 

G - 

1 o X 
u > 

a x 

Q X > 

2 » .. 


Q 0 0 

2 0 (J UJ 

0 > 0 l- 

0 — X <z 

0 G 

o u o a 

J- 0 b~ 0 

X 

> > E 

QXQhlil 
<1 O <E CL O 
0 X 0 OO 
* X X E 


2 0 2 
0 0 0 

1 >— X 

3 3 

O 

0 H 0 

G G 
0 1-0 
Ch<I 

> CCl > 

XXX 

2 3 3 
o o o 

> > > 


a 

z 

<1 

>-• I I I I I T 

ENOOOO to 
Z O CD CD T o 


O u. 

C. •—I 

0 G G D G G Q 

xoqogoqz 

>-<0000000 

X 0 X Oi CL Cl 
0QQ>>»- 
I- 2 2 CJ U <X 
U 0 0 X X Q 
O Q Q Q Q Q 

o o o o o o 

Z E E E E E 


3 

3. 

* 

3 

3 

o 

3 

.3 

ct 

5 


<r 0 
>— <x 
<1 z 

Q X 
0 
E K 

0 X 
Q 0 
O 

E X 
O 
X 

g a 
o z 
> 0 


r XXI 

ft HfJK) IX 

y U U U Q 0 

© ~ ^ CM CM o O o -« 


E 

E 

X 

G 

x a 
-< 0 


00000000^0 

XXiliXX fJ Q Q 
QQ>>HX_JOn 
ZZUU'IXhEE 
00IXQQU03 
QQQQQOQ^, m 
ClOOOO<IOX7 

eeeeexeo$ 


£ 5 x i i 

QJ f'J rj H H i CD (D CD ft 

I 

Q « 

11.0003000002 3 

•“<0000000000 Q 

joq>>S:j Q q ^ 

{“Z2uU<IKEE S 

U0UDXXQU03 

QQQQQQQmU) 2 

ogoooooxz x 

ZEEEEEEO<I 0 


-4 >0 1 -H 


I I 

in CD O K) 


G G D 
a g a 
000 


Xhi; 

o o u 
cn 0 d 


o G G o 

a a q a 

0000 


* 2 

‘X <r x x 

2 U G U 


\n 

+ 

0 

cn 

<z 


o 

o 

Q 


(0 

< 

o 

o 


(N 

X) 

OJO 

C3 

a 

c 

o 

C/5 

s 

’Sb 

0 ) 

X) 

•w 

X 

OJ 

H 


I— 3 
0 0 
z r> 
i 

E tn 
\ « 
X & 
u n 
o 

i/i a 

r l 
G o 

•H -M 
6 U 
0 0 
P 

> 

-1 c 
at 

x c 

o 

6 H 
0 -M 

l ns 

s- U 

XJ r-. 

at n 
> 3 
ri a 
0 ) 

u L 

Qi 0 
X X 


2 

3 

a 

X 

0 

0 
<1 - 


Q OJ 
0 4J 

h <n 
G 3 
U CT 
0 QJ 
X 

0 E 
0 

Q 4J 

z m 

<1 3 
u 
Q 

0 L 

Q 0 

<t H- 

o 

0 4J 

a 

* QJ 
Q U 
0 X 
0 OJ 
0 ~ 
E 
0 
0 
0 
<r 


o o 

■ m 

n 

> 

L 0 

S 2 


>* 

0 

E 

<1 

X K 

0 

O C 
X X 
0 


•> CM 

o in 

. E 

CPCN 0 
C > Q 
- O 

+J E E 
1 0 
l <i e 
o . o 
az l 

L 0 H- 

o Q 
u o in 

C Z 4J 

c 

C QJ 
*+• 0 E 

0 OJ 

TJ U 
J II C 

m in <n 
tj *u r 
* Xi c 

QJ 

L 

0 . X 

QJ 4J 

c -< 

V- -H 5 

0 4J 
r 3 C 
> 0 QJ 

t l in 


01 r-. 


„ 

111 

E 

h- 

n 

E L 

L A 

E 

\ 


0 TJ 

O 

0 

Ql U 

X 

>« 

-X 01 

□ 

4J 

4J 

u 

l 


• in 

H 

0 

in 

TJ 

Ol L 


o > 

Q Ol 

E 

UJ 

.X 

C 

r —1 <B 

a 3 

E 


a L 

Q 

(IS 

E 

\ 

•* 

E ~ 

O 

A 

i >- 

X 



E 

K 

in n 

u 


E 

Oi 

TJ 

0 . 

E XJ 

0 0 3 

4J 4J >■ Ul rc 

C 0 XI 

> E U > 

it) 0 ill O 
J <t 4J I O 

■ m to 

iB E 0 . 

0 E U .. 

in Q ri . QJ 

•B O I® Q T] 

. ^ o 

qj r u e 

m l G o 

3 0 n . 

_ J ^ 0 

L E E H- 

0 O -0 E <x 

^ L) Qj X z 


in 

z 3 4- g 

0 HH 

Q QJ X 

On o 

> ~ ' 
l ib in in 

Qj e ‘ 


QJ , 

a in 

i <B 3 
i 3 

7 c 

Ol Qj 


L OJ . 
>» OJ 01 

— in in 

r-, J ~ 

«B 

-• 2 E 
G Qj Qj 
h C T) 

C 0 
-• IB 6 


h Ob o 

-I -n H £ 
iB 0 
c H 01 

e o i r 

1 ) H C +1 
L L J 

cn a o 4 - 
0 TJ o 
L E 

a oi o a 

■M 4J L 

4 - in <b 
o > oj a 

in r-i 

n oj 
n 
in a 


L Oi 
IB A 
+1 0 III 


in 


w c 
a o 


OJ -H 

C X QJ 4J 


L Ol o 


Crt +J Uj 

3 4- 3 L 


O 
ib r 


i o h 
a -*J > 
E 


OJ E 


L OJ 


in qj 
in 

<x 3 


CP IB 

'i w c u 

-> Qj -< in 

a r a m 

c u * > 

3 C x G Qj 

»B Qj x: 

ri L 

u n o n 

C tfl l 

1 C r-4 Qj Q 

6 OJ (B -• 4- 

L X i 

Ol -M > 4- 


: x x 


0 

x 

> 

h- 

0 0 0 
0 X X 
*-•>■> 
Xl-h 
• 0 0 
0 0 0 
E • 

<1 I 
2 

0 0 0 
0 Z E 
*-> <1 <X 
X 2 Z 
0 0 
b- 0 0 
Q ^ i 
O X X 

E <C lij 


.. O Q 

0 O O 

O III III 

2 Z E 

<1 

E 

E L V- 
O 0 o 
U 


iB 

A E 


0 ) 


I 


QJ Ol > 
in u 
3 Oj qj 
L XI 
QJ K 

IflHX 111 

H L h £ 


OJ u _ 

■*j v • cn ib 

IB Ol C c 

L TJ c 1 1 

Ol OJ i C 6 

a a v Oj l 

o > j am 

■*J 0 0 4J 

-< L 

n in 4J 01 

•4 oi 3 r 

2 > 0 g 

>■ 1 £ 

6 oi oi 4J e 

fl ^ U 4 0 

L Ol 2 l 

CT - L 4- 

0 U E 

L 0 Ol \ 0 

a 0 l x i 

- 4J U r-, 

01 L 

r c o o 4J 

h ns 4-* 4J U 


Ol 

A Ol • 

v x in 

4J L 
A Ql 
4J Q| 4J 

1 > U 

2 iB <B 
A L 

Ol D 
U G A 
C 0 U 
iB C 
TJ — 
LOO 
One 

U 4 j 
U Ul C 
u TJ 0 


C IB 
- 0 
0 
TJ > 
QJ Qj 


- 0 
> 4- 


CT . 


>■ L 

IB Q| 

E tfl 
3 
in 

>* Q| 

qi r 


4 

4J 4- Ol I 

h o ^ : 
i in - i 

TJ u 
TJ Qj 0 i 
C QJ 0 i 
TJ C ' C 


TJ 

0 L 
U Ol 


L Ol 

0 Ql ^ 
in h q_ 
i x 

c * ~ 

•M tfl 


I 4J L 

Ql 

1 4J 

; ib o 


I 0 

E 4-1 
0 

(J TJ 
Ql 
> 

0 0 
6 

□ Q| 


Q 

Q 


C 

•B 

a 

oi 

i 

OJ 


o 

0 

0 

X 


X 

o 


X 

o 


E 
E \ 
\ X 
X u 
u 

0 
Q K 
CL <1 

<r z 

Q CL 
Z 0 

<r k 

H- 0 
0 <1 

0 0 


0 0 
G G 
X X 


A 

<1 


E 


X 

0 

X 

0 


0 0 

(J 

ill 


G 0 

Q 

<1 

o 

CL <T 

K 

K 

o z 

H X 

0 O 


<N 

C 

5 

3 

8 

3 

O 

*3 

3 

.3 

•Cl 

3 

<3 


C 

.. 





•B 

0 






H 

3 

G 

3 3 

G 

0 

O 

Q 

a 

O G 

X G 

4J 

z 

0 

0 

0 0 

|—< 0 

E 






OJ 




E E 


4J 

0 

0 


X X 


Ul 

H 

0 

0 

u u 

0 

> 

O 

0 

g 

Q H 

0 

tfl 

2 

<X 
- X 

X 

s- 

1 - 0 
•» 0 <X « 

«X 

* |X| 


r^Dobb’s Journal, Number 72, October 1982 
458 


47 









MBOOT.ASM 

(Listing continued, text begins on page 42) 


u u 


cn i 

H 

O <t LL H u. 

H 

UJ o 

LL 

J Q (fl « J 

U 

o > cn cn 

X 

a z o x • 

X 

- U > X > 

> H 

X UJ _J X x 

X 

- UJ u o u 

u o 

3 cn u uj u 

<Z UJ 

a a ce (Si x 

<T X UJ 


> U5 $ 
^ U > Z 

- UJ U - 

a x x <r 


o O 
h a 
<r 

Ui ♦ 
-i + 
-j a * 
eh ~ <i - 

I- H Q. U. H Z U. 

qu y _j ie cn *-• d _j 

z x x a: > o x + - 

uj cn cn cn u _i cn + x 

cn lu <r uj lu a: u uj . u 


cn cn 

Cd lE 

UJ UJ 

> (Si >0) 

^ U > <1 « u > 

* UJ U - • UI u 

a cn cn a a tr o: 


x 

X X 

UJ I 

> cn u > 

^ u > « > u ~ u 

• UI (J • (J . . UJ 

au:aE jiTQiDfl: 


H -i A _j -i -i J 

y —i a. _i .j j _j 

<r <i e <i <r <x <r c 

u u n u u u u < 


<1 <r ~ 

eh > 

x (Si E 


J 

-J ►-« <E *-< CJ 
5UH.NllNQ.hN 

UtUtOtui/ih 


-J -J _l _J 

Hju^jairaH _j _i 

><iz>«iqzi-q.u <i <x a a 

EUnEU-J^cnun CJUQQ 


-J -J 

-• _J >~_J <X Cl a. 

>«IUO><tUEEME 
EUnEEUnUU^n 


> <X « M *-• -J 

OH > x > <x u 

E cn E -J E U n 


>iTN>h j 

o z z o > <X 
E *-• O E E U 


o 

UJ 

X 

UJ 

cn 

X 

> 

> 

> 

u 

u 

u 

X 

- X 

.•cn 


U lC CD U. 

«I Q H \ 

^h5hOK)H h h O 

UtDhHOV + E iE Z H 

o <i in a. + ^ 

.Q.h(LZ JE^U UJ —J + x 

Z U) (0 (0 - U. *• I— ^ UJ 


X u. 

X Jh 

j z u -i <r 

H E ~ H H U. Q 

hUlmxxdlUO 

tnH^wujuJcnx 


a a: CL 

> > H 

U U <1 

cn x e a uj e 

Q Q X Q X CL iE 

O O UI O U. > UJ 

E E H E N H H 


Q -I -I _l 

»—• Q —J • _J _J <t -• m _l Cl 

x5Ix^ J cqe 

jQW-IUUQQjUnUQn 


<l z z <r a a a 

U U Q Q Q 


5N<ia.NiN3 

unuuouno 


o u. u u. 

Z « Q w 

Q Q 

Ll z z u_ z z 

« UJ — UJ 


X 

u u. 

Q « -J -J -I -J 

Q M H JO. _l _J _j 

u. z z z (L z z z 5 i <r <t <r a 

h h uj U *"3 ^ (J n U U CJ Q 


Dr. Dobb’s Journal, Number 72, October 1982 

459 


(Continued on top of page 48) I (Continued on page 49, column 


X 

u 


>< 


X x 

0 i- 
0 x 

Q U 
- UJ 

i cn 


Q 
•-« X 
x X 
x cn 


>o cn 

(N Q 

• Q 
U Hi 


0 

Z 


x 

3 

X 

o 

x 

<X K X b- 
X X LU X 
Q CL + O 

0 -1 + Hi 
CX - - <E 


0 ill d 

<r - 

ix <i <r 0 


x > E 
X E ra 

<1 

U 

<X 0 
U Q 

E 

n 

0 

X 

IF 

MOV* 

ADE 

MOV 

a 

z 

X 

X 

X 

<1 

X 








E 

Q 

0 

X 

X 
X 
X 
- 3 



RECV 




u 

X 
0 
« E 


x 

x 

f- 
U 
Q 
I O 

u e 

Q 


i ft 

X Z § 
Ui 


M 
X 
h- 
U 
X Q 
U O 

q e 


U. Z 2 

• LU 


0 X 
> > 

CJ CJ X 
X X <x 
Q Q I 

oou 
e e r x 


•-* « Cj 

K K Ui 

3 3 0 

E Q E 0 j; q 


<X 

Q 

Q 

O 


^ XmX mXmXui- 
ZUnCJZU z U Z □ k i m 
<1 U O Q T Q OQnQL0X 


3 

E 


E Q X U U X <1 


X0Q>x<r»- 

ZO0QOOXX 

•^xx<xzxox 


X 

<r 

X 



w4 

+ 



+ 

z 

•f 

+ 

K 


X 

X 

<L 

> 

x 

0 n 

h- 

X 

> 

x • 

0 

2 

b- 

B 

D 

D 

> Q 

> Q 

> 


Q Q Q Q 

^ H Q JQ JQ JK 

i^^Xcrx^xiL 

_J_IQ0QU)Q(/5^ 


0 

cs 

0 

Q 

O 

E 


3 

o 

3 

.3 

ci 

<3 


iij 

£ .w x hutMfl 

' 3 1 J 3 I » ►hX»h0 

00>X0X>x - .Q 
^■Xf-uxin - e Q u 0 


—j i -i _j 

-IUIJJXhhnhhiI 

<xp < r<rozx2x>r 

uxuux<iu' , DjEr) 


x 

u w 0 

X CN O 
- -Q 
Q CJ 0 <t 


►-« X 
X _J 

0 

UJ x 

■5 x 

E 0 


- 0 

- 0 

Z E 

<r 

u > 

X 

I o 

J— 

cc CJ 

O X 

X X 
K X -« 
►h x Q 
x + + 
X 4- + 
X ' - 


M ^ J li N J 

*><XZz<I0ffl 

XEU^XCJQQ 


X 

0 

o 


0 

CJ O 0 
X - o 

' * Q 
Q UiZi <1 


H « J X M 
X > <1 z z 
X E CJ x 



• 


■f 

0 


z 

X 

X 

CN 

H 

<1 

H 

0 



CJ 

X 

c 

X 

X 

+ 

u 

0 

> 

X 

♦ 

X 


o 

X 


0 

I 

E 


X 

■X 0 
U Q 


X 

LfJ 

O 


X 
0 
' z 

i u 
X 

0 <1 


5 

£ 

o 

3 

o 

<*> 

3 

.3 

ci 

3 

<3 


0 

z 

u 

X 

0 1 


X 
0 
0 
<1 Q 

CJ Q 


Q 0 
X X 
I U 
X X 


U 
X 
0 
X 
' 3 


X 0 Q 
~ X I X 
X <T o X 
X U x 0 


X 

0 

<1 X U 
o 2 X 
X ~ 0 


X 

X 

I 

Q, 

X 

X 

X 

u. 

0 

z 

X 

CD 

3 

u 

0 Q I <Z 3 

I* Q 

cj q <r 

X 

0 


X Z 
U X 


<r «x > ~ 

Q X m o x 

x o x r x 


0 

CN 


U 

o 

X 

0 

X 

- 3 


0 

0 0 0^0 
NOXNO 

- Q » *. Q 


lilil 5 ig|||lS=!!gs|g 

X 

X 

X 

3 


a 

x 


0 

•x 

X 

X 


<N 

3 

^3 

"o 

O 

3 

O 


X 

X 

X 

cc o 

X 

x z 

0 

0 0 

> 

> > <r 

u 

CJ u * 

0 Q 

0X0 


O U 

Z <1 k 

S 3 6 

XX 0 


. x NJ 5 > <x x X x N h- 

UEZQOQEmZEZx 

'HIOXExUTwq^ 


u u 

<L X 
Q 0 
Z > 
X u 
0 X 


X X 
<1 E 
u n 


3 <1 

0 

X u u 


I 

0 Q > 
0 0 O 
X <t E 


X 

N 

0 X 


X 

X 

X 

Q Q 


b- 

V— 

r 

Z Z 3 


<x 

CJ 

U 

0 0 Q 


Q 

Q 

Q 

Q Q Z 

3 

Q 

X □ 

O 

□ OX 

0 

o 

CJ E 

Q 

E 

E E 0 

X 

E 


u 

<x 


u 

<r 

> 

u 

X 

►X 


u 

<r 

Q 

z 

X 

« 0 


o X 

z -« 

X Z z 

H H UJ 


I 

u 

Q 


Q 

z Z 

I •— X 


HH NiKt- 

z X z O 0 X 
<x u x o x 


X 

H Z 

> X <X Q 

-« U O U Z 

- X 0 - X 

0 0 1 <1 0 


« X U *-« X 

> <1 Z > <1 

E U rj E u 


> X 

- CJ o 

-X 0 

0 x <r 


~ x u 
> <r z 

E u n 


X 

u 

z 

<1 

u 

E 

<r 

X 

0 

o 

X 

X 


^ H ° 
Q - □ 
- Z x X 
* X X E 
<X 0 X .. 


> <t <X 0 
E U U Q 


I- 

X 

o 

0 


X 

0 


□ 

z 

b- 

u 


<r x 
Q Z 


Q 

z 

0 

ic 

u 

z 


<E h- 
K X 
0 x 


x a 

X 3 

c. ^ 

K 3 

o 

0 SJ 


0 

u r- ui 
U- -* o 
'• -Q 
Q U 0 <1 


X X 
X + 
X + 


X 

hH HH X X 

X > <1 z M 

X E u ~ x 


<1 0 
U Q 


X 

0 

<x 

X 
— X 


Dr. Dobb’s Journal, Number 72, October 1982 
460 


49 



MBOOT.ASM 

(Listing continued, text begins on page 42) 


CUQI*IQCD<X 




UJ 

CL 


h- 

u. 

u. 

jL 

CD 



CL 

UJ -J 

in 

LL 


_l 

o 

N 

UJ 

Ll 

CL 

0. CL 

O' Q 

Cl 

*. 

» 

<r 

T~t 

E 

XI 

-J 

> -J 

» Q 

-I 

CL 

o: 


. 

. O 

CD 

*“• 

HI*-* 

QUO. 


U 

u 

in 

CD 

d Q I Q Ii E 

O O O O Q 


I I I -J 

cntna)_jcLu.u.<i»- 

DDDCOOO^kJ 

q.o.q.uclQ.cloq: 


x x x -j 

tncntn_iLLQ.u.«(_ 

DZ)D<XOOOZLU 
a. cl £L a i a. A. «i a 


> <X -I x Q. 
□ CL m <X 2 X 
r □ n U -• n 


-1 Q -J 

-I Jll- 

<1 III III I CL LU 

U a a _j in a: 


>dxxcrN|- 
O H Z Z (J Z UJ 
eu)hhqo(i: 


ciiiZiaiiXiziXiininc 

QQQQQQQQl. 



z 

z 

<L 


> 

y— 

> 

UJ 

in 

UJ 


> 

- * 

> 


o o a: ai 

Z Z h 0 K Z 

cn i- u J ll « 

> u cl ll u u 

U UJ CL O UJ LU 

* cl in uj ui in in 



CM 

K) «r 




Q 



Q 

U Cl 

CL U CL 0- 

U CL Cl U 0. Cl 









O h JO 

H JO K JO 





Q 



►— 


X H Z - 1- Z 


CL I 1- 

X K 


r. 



Z U 


2 U Z U 

—i 

NQILU 

•0 u 

i-i 


a 




*-« Q - *-• Q - 

E 

in d n q 

I - Q 

E 

«r 

Ll 

II O Q 

<1 E 

CL u. <t E 0- 

o o o 

CLdEiLUdEilCL 

O O O O O 

E 

Cl 

• <i * o 
<X Hi <X E 

U * O 

Q <r E 

E 

CL 

X 

lL 

-J o 

Ll -O 
X O <1 E 


CL LU LL 

U IL _J 3. <L + 3 

*•>•*• in » i ui 

«IK<I lffiQI(j#IQ(I|iL 


'-'H-CLCi.’-^KClCl'-'KCllL'-'KILClO 

>DOO>DOO>DOO>DOOZ 

EOZZEOZZEOZZEOZZUJ 


*-« h- *-< H Q 
. > D > D Z 
•EOEOUI 


*-* K Q 

IL>DZ Ll 

h E □ IU ^ 


CC N CC N h h Q 

U Z U Z > D z 

Cl n O D E O UJ 


XIII -J 

incnu)in>_ia.cLii.LL»- 

ZiDDDO<IOOOOLU 

ClilClClEUClClClCLCL 


Dr. Dobb’s Journal, Number 72, October 1982 

46T 


16 -BIT SOFTWARE TOOLBOX 


by Ray Duncan 


Late News for 8087 Fanciers 

Intel recently dropped the price of 
the Intel 8087 numeric processor to $230 
in single-unit quantities. Some high- 
level software tools to exploit the 8087 
are also beginning to appear. In addition 
to my own company’s version of Forth 
which can use the 8087 co-processor, 
Lifeboat Associates is marketing the 
Lattice C Compiler which includes an 
8087 runtime library, and rumor tells of 
a UCSD Pascal support file named 
8087.PLS which is not yet officially 
announced. 


16-Bit Tools, Installment # 2 

The accompanying listing is an 8086/ 
88 assembly language subroutine that re¬ 
turns the sine or cosine of an angle to 
four significant digits. The precision is 
adequate for most graphics applications, 
and the routines are implemented by a 
combination of deduction and table- 
lookup techniques that are extremely 
fast. The original version of these routines 
was coded in Forth by John James and 
placed in the public domain; interested 
readers are referred to his article in Forth 
Dimensions, volume 4, no. 1. 

Readers who also need a tangent 
function can derive it easily: 


tan(x) = 


sin(x) * 10000 
cos(x) 


But watch out: finding tangents in this 
way for angles greater than seventy-two 
degrees will lead to a divide overflow, 
which causes a hardware interrupt on the 


8086/88. 


A more precise (but slower) method 


of finding sine, cosine and tangent 
through a simple polynomial expansion 
will be presented in a later column. 


Product Report: 

Microsoft RAMCard with 
RAM Drive 

This integrated combination of hard¬ 
ware and software can be installed in any 
IBM Personal Computer, and will marked¬ 
ly enhance its operation. “RAMDrive” re¬ 
fers to a technique of mapping a disk di¬ 
rectory and file structure onto a portion 
of the machine’s random access memory. 
The operating system drivers are modified 
so that the simulated disk can be accessed 
by application programs like any other 
peripheral device. Since there are no mov¬ 
ing parts, data can be retrieved nearly in¬ 
stantaneously. As many as three RAM- 
Cards may be installed, yielding a maxi¬ 
mum of 768 Kbytes of RAMDrive storage. 


The package contains a memory ex¬ 
pansion board of average-quality con¬ 
struction socketed for 256 Kbytes with 
parity, a diskette of utility programs and 
a sixty-page manual. The product is avail¬ 
able in several versions and' prices, de¬ 
pending on the amount of RAM initially 
supplied. The user can upgrade a partially 
filled card by simply plugging in more dy¬ 
namic memory chips. 

Installing the memory card in the 
IBM PC is quite simple, and can be done 
in a few minutes by anyone who can read 
and handle a screwdriver. The manual is 
clear and complete, and has plenty of 
helpful troubleshooting tips. 

Next, you use a memory test provid¬ 
ed on the Microsoft diskette to make sure 
the RAMCard is working properly. This 
program is a classic of its kind. It was 
obviously written by a programmer who 
was told to make the product “user- 
friendly,” and who thought he could 
meet that objective with liberal use of 
reverse-video, blinking text, complicated 
screen-oriented presentations and, of 
course, using the special-function keys at 
any cost. For example, the user is asked 
to respond to one of the program’s setup 
questions by pushing either the F9 func¬ 
tion button or the space bar, neither of 
which are conveniently located or have 
the slightest mnemonic value. In spite of 
its veneer of razzle-dazzle, the program 
suffers from major design faults in the 
human interface that make it awkward to 
use, such as a lack of backspace capability 
should you be unfortunate enough to 
make an error in numeric entry. The pro¬ 
gram and documentation don’t provide 
the smallest morsel of information about 
the testing process itself, and the only 
way to terminate the test once it is 
running is to reset the computer. This is 
not my idea of a classy program. 

After you are convinced that the 
memory card is working correctly, you 
run the configuration program, which 
patches the PC-DOS operating system 
and makes the extra memory available as 
a simulated disk device. This is a simple 
procedure and requires only a few sec¬ 
onds — afterwards, you can copy the re¬ 
vised operating system to your various 
working disks. You might wonder what 
would prevent someone from pirating the 
configuration programs and using them 
with other companies’ less-expensive 
memory cards. Never fear, Microsoft has 
provided against this eventuality: part of 
the necessary software is in a pro¬ 


grammed read-only memory chip in¬ 
stalled right on the RAMCard. 

Using the RAMDrive capability can 
result in astonishing improvements in per¬ 
formance for programs which are disk 
I/O bound. For example, a simple Forth 
program to sequentially read through a 
100 Kbyte file, accessing it as 1024-byte 
records, completed in 24.9 seconds using 
a regular 514-inch floppy disk drive but 
only required one second on the RAM¬ 
Drive. 

The RAMCard and RAMDrive pack¬ 
age costs $495 with 64Kbytes installed, 
and each additional 64Kbytes costs you 
$200 from Microsoft up to a grand total 
of $1095 for a complete 256Kbyte card. 
Here is where a little careful shopping can 
save you a bundle of money. I bought the 
minimum 64Kbyte card from Microsoft 
via Computerland, and obtained the 
twenty-seven dynamic RAM (type 4164) 
chips necessary to fill up the card for 
$227 from BG Micro in Garland, Texas. 
Thus, I saved $373 as compared to buy¬ 
ing the RAM expansions from Microsoft. 

Note that if you do not want the 
RAMDrive feature of this product, there 
are many memory cards available from 
reputable companies at considerably 
lower cost. But if you really need in¬ 
creased speed from your IBM PC, but 
aren’t yet ready to take the plunge on a 
hard disk, then this product is great! 

(Listing begins at right) 


Dr. Dobb’s Journal, Number 72, October 1982 
462 


51 



8086 Trig 

(Text begins on page 51) 

title 'Trig Lookup Function*' 
pagewidth 79 

I 

I Trig lookup -function* for 8086/80 
I adapted by Ray Duncan from a public 
I domain FORTH routine written by John James. 


» 

I 'Trig' i* a common routine u*ed by 'sin' 

I and 'cos’ to reduce an angle into the 
I range 0-90 degrees then extract the 
I appropriate -function value -from the table. 


0000 

BBDB 

1 

trigs 

mov 

bx, ax 

ybx <- degrees 

0002 

83FB5A 


cmp 

bx, 90 

yif >90 degrees 

0005 

7E06 

000D 

jl« 

tri gl 

yreduce the angle 

0007 

B1EBB400 


sub 

bx,180 


0008 

F7DB 


neg 

bx 


000D 

D1E3 

trigls 

sal 

bx, 1 

ytable index ■ 2*deg 
inow extract value 

000F 

2E8B873F00 


mov 

AXfSintbl Cbx3 

0014 

C3 


ret 


yback to caller 


0015 055A00 


I Cosine lookups add 90 degrees to 
I argument and use sine lookup. 

I call withi ax ■ degrees 

I returnsi ax ■ cosine * 10000 

y other registers preserved. 

I 

cost add ax f 90 

I 

I Sine lookups reduce to angle in 
I range 0-359 degrees, then call 
I 'trig' to extract function value 
I from table. 

I call withs ax ■ degrees 

I returnss ax ■ sine * 10000 

I other registers preserved. 


0018 

52 

sins 

push 

dx 

1 save registers 

0019 

53 


push 

bx 


001A 

99 


cwd 


ydeg -> double prec. 

0018 

B86801 


mov 

bx,360 

yreduce angle to 

00 IE 

F7FB 


i di v 

bx 

yrange 0-359 degrees 

0020 

BBC2 


mov 

ax, dx 

ylet ax»remaind«r 

0022 

0BC0 


or 

ax, ax 

yis angle negative? 

0024 

7903 

0029 

Jns 

sin2 

y no,Jump 

0026 

056801 


add 

ax,360 

yyes,make it positive 

0029 

3DB400 

sin2s 

cmp 

ax,100 

ynow reduce angle to 

002C 

7E0B 

0039 

Jle 

si n3 

yrange 0-180 degrees 

002E 

2D8400 


sub 

ax,180 

yangle was > 180 deg. 

0031 

E8CCFF 

0000 

cal 1 

trig 

y1ook up function value 

0034 

F7D8 


neg 

ax 


0036 

E90300 

003C 

Jmp 

si n4 


0039 

E8C4FF 

0000 sin3s 

call 

trig 

yangle was <• 180 deg 

003C 

5B 

si n4 s 

pop 

bx 

yrestore register* 

003D 

5A 


pop 

dx 


003E 

C3 


ret 


yback to caller 



y lookup table 

■for trig 

functions 

003F 

0000 

sintbl 

dw 

0 

yO degrees 

0041 

AF00 


dw 

175 

H 

0043 

5D01 


dw 

349 

»2 

0045 

0B02 


dw 

523 

»3 

0047 

BA02 


dw 

698 

|4 

0049 

6003 


dw 

872 

|3 

0048 

1504 


dw 

1045 


004D 

C304 


dw 

1219 

)7 

004F 

7005 


dw 

1392 

is 

0051 

1C06 


dw 

1564 

|9 

0053 

C806 


dw 

1736 

no 

0055 

7407 


dw 

1908 

in 

0057 

1F08 


dw 

2079 

1 12 

0059 

CAO0 


dw 

2250 

1 13 

0058 

7309 


dw 

2419 

1 14 

005D 

1C0A 


dw 

2588 

1 1® 

005F 

C40A 


dw 

2756 

lit 

0061 

6C08 


dw 

2924 

|17 

0063 

120C 


dw 

3090 

1 IB 

0065 

B80C 


dw 

3256 

1 19 

0067 

5C0D 


dw 

3420 

1 20 


(Continued on next page) 


Dr. Dobb’s Journal, Number 72, October 1982 


53 





8086 Trig 


(Listing continued. 

text begins on 

page 51) 


0069 000E 

dM 

3504 

1 21 

006B A20E 

dw 

3746 

1 22 

006D 430F 

dw 

3907 

1 23 

006F E30F 

dw 

4067 

I 24 

0071 0210 

dw 

4226 

1 25 

0073 2011 

dw 

4304 

I 26 

0075 BCU 

dw 

4540 

I 27 

0077 5712 

dw 

4695 

1 20 

0079 F012 

dw 

4040 

1 29 

007B 0013 

dw 

5000 

| 30 

007D 1E14 

dw 

5150 

1 31 

007F B314 

dw 

5299 

1 32 

0001 4615 

dw 

5446 

I 33 

0003 D015 

dw 

5592 

I 34 

0005 6016 

dw 

5736 

1 35 

0007 F616 

dw 

5070 

I 36 

0009 0217 

dw 

6010 

1 37 

OO0B 0D10 

dw 

6157 

y 30 

OO0D 9510 

d w 

6293 

I 39 

OO0F 1C19 

dw 

6420 

»40 

0091 A119 

dw 

6561 

I 41 

0093 231A 

dw 

6691 

| 42 

0095 A41A 

dw 

6020 

| 43 

0097 231B 

dw 

6947 

| 44 

0099 9F1B 

dw 

7071 

1 45 

009B 191C 

dw 

7193 

| 46 

009D 921C 

dw 

7314 

| 47 

009F 07ID 

dw 

7431 

| 40 

00A1 7B1D 

dw 

7547 

| 49 

00A3 ECID 

dw 

7660 

| 50 

00A5 SBIE 

dw 

7771 

| 51 

00A7 C01E 

dw 

7000 

| 52 

00A9 32IF 

dw 

7906 

1 53 

OOAB 9A1F 

dw 

0090 

1 54 

OOAD 0020 

dw 

0192 

) 55 

OOAF 6220 

dw 

0290 

y 56 

00B1 C320 

dw 

0307 

l 57 

OOB3 2021 

dw 

0400 

| 50 

00B5 7C21 

dw 

0572 

| 59 

00B7 D421 

dw 

0660 

I 60 

00B9 2A22 

dw 

0746 

| 61 

OOBB 7D22 

dw 

0029 

| 62 

OOBD CE22 

dw 

0910 

y 63 

OOBF 1C23 

dw 

0900 

I 64 

00C1 6723 

dw 

9063 

y 65 

00C3 AF23 

dw 

9135 

y 66 

00C5 F523 

dw 

9205 

1 67 

00C7 3024 

dw 

9272 

y 60 

00C9 7024 

dw 

9336 

y 69 

OOCB B524 

dw 

9397 

y 70 

OOCD EF24 

dw 

9455 

y 71 

OOCF 2725 

dw 

9511 

y 72 

OOD1 5B25 

dw 

9563 

y 73 

00D3 0D25 

dw 

9613 

i 74 

00D5 BB25 

dw 

9659 

y 75 

00D7 E725 

dw 

9703 

y 76 

00D9 1026 

dw 

9744 

y 77 

OODB 3526 

dw 

9701 

y 70 

OODD 5026 

dw 

9016 

y 79 

OODF 7026 

dw 

9040 

y0O 

OOE1 9526 

dw 

9077 

y 61 

00E3 AF26 

dw 

9903 

y 02 

OOE 5 C526 

dw 

9925 

y 03 

00E7 D926 

dw 

9945 

y 04 

OOE9 EA26 

dw 

9962 

y 65 

OOEB F026 

dw 

9976 

y 66 

OOED 0227 

dw 

9906 

y 07 

OOEF 0A27 

dw 

9994 

y 66 

OOF 1 0E27 

dw 

9990 

y 09 

00F3 1027 

dw 

10000 

y 90 degree* 


end 




End Listing 


54 

464 


Dr. Dobb’s Journal, Number 72, October 1982 



OF INTEREST 


by Michael Wiesenberg 


A Potpourri of 
Good-Priced Hardware 

The three-inch Winchesters are com¬ 
ing! One of the first is from SyQuest 
Technology. Their SQ306 they claim is 
“the industry’s first 3.9-inch (100mm) 
removable cartridge Winchester disk 
drive.” SyQuest is aiming at the OEM 
market, but the price of $400 per unit in 
large quantities means we can expect to 
see these five-megabyte Winchesters arrive 
reasonably priced. The cartridges will sell 
in quantity for $30 each. The small size 
of this unit (1.625 inches tall) allows two 
SyQuest drives to fit into the same space 
as one 5.25-inch Winchester or mini¬ 
floppy drive. We should see these units 
integrated, probably stacked two at a 
time, into the next generation of portable 
computers. Reader Service No. 306. 

Monitor the status of the “seven 
most important” (we are told) RS-232 
lines with, what else?, RS-232 Tester 
from B & B Electronics. A female 25-pin 
connector at one end and a male connec¬ 
tor at the other let you attach the Tester 
directly to the interface and leave it per¬ 
manently in the line, with LEDs constant¬ 
ly displaying status, but not interfering 
with data transfer ability. $39.95 post¬ 
paid. Reader Service No. 316. 

The SSB-MPF Speech Synthesizer 
Board from Etronix provides a 400- 
word vocabulary for the MPF-1 Micro- 
Professor, the Z-80-based single-board 
computer-in-a-book described in a pre¬ 
vious column. The board does its input/ 
output with the Micro-Professor’s key¬ 
board and speaker, and features a 4K 
time clock and speech utility EPROM, 
two EPROM sockets that can be used to 
expand the vocabulary, adjustable pitch 
and volume controls, a power adaptor, 
all necessary connection accessories and a 
manual. $129. Reader Service No. 326. 

A Gallimaufry of 
Inexpensive Software 

AUTODIFF is a file difference detec¬ 
tor for CP/M by the Software Toolworks. 
Not only does this comparison utility list 
differences between files or produce a 
copy of the file with all changes flagged, 
it also reports insertions, deletions and 
changes, listing them in ASCII or hexa¬ 
decimal format to a terminal, printer or 
disk file. Filters can be set to ignore non¬ 
printing characters or to display control 
characters. AUTODIFF can be used on 
most files and costs $29.95 (plus $2 post¬ 
age and handling) on 5 -inch disk for 


Dr. Dobb’s Journal, Number 72, October 1982 


Osborne I and Heath/Zenith, and 8-inch 
CP/M disk. Reader Service No. 346. 

Disk-Edit is a screen-oriented disk 
editor from Supersoft for CP/M pro¬ 
grams. It can call up files that, according 
to Supersoft, “are not even accessible 
with a normal text editor, then edit those 
files in either ASCII or hexadecimal nota¬ 
tion.” The program loads a one-kilobyte 
section of a disk (hard or floppy) into a 
buffer, and then displays a dual-view 
“window” into the buffer. On the left are 
the hexadecimal values of each byte; on 
the right, the ASCII. Change either, and 
the corresponding value changes instant¬ 
ly in the other. Simple commands move 
the cursor up, down, left, right, to the 
next page or screen, to the start of the file 
and so on. There are also string searches 
and many other functions. Disk-Edit 
has a “terminal definition package” and 
can be configured to most CP/M systems. 
$100, or $15 for the manual only. Read¬ 
er Service No. 356. 

You probably thought that a text 
editor for the IBM Personal Computer 
would be expensive, but WINDOW, a 
full-screen text editor program from 
Intellect Associates Inc., costs $150. It 
uses all the screen and keyboard capabili¬ 
ties of the PC, including single-stroke 
editing commands with the function 
keys. It’s not quite a word processor, but 
WINDOW does most of the things a word 
processor can, such as easily move the 
cursor, scroll in four directions, do global 
search and replace, insert and delete char¬ 
acters and lines, move, copy, split and 
join lines and edit text files larger than 
available memory. WINDOW runs under 
IBM-DOS, comes on 5.25-inch diskette, 
with documentation, and requires 64K, 
one drive, and a monochrome display and 
adapter. To turn WINDOW into a real 
word processor, add Intellect’s PCTEXT 
for $100, and get a text processing pack¬ 
age that indents, centers, controls line 
spacing and margins, justifies, inserts 
headings and footings, numbers pages, 
underlines and merges documents. It, too, 
runs under IBM-DOS, requires 48K, one 
drive and a printer. And while we’re talk¬ 
ing about Intellect Associates, they offer 
for the same configuration a data manage¬ 
ment system, DMS, a self-prompting, 
menu-driven system with which users 
create data entry forms on the screen 
in user-specified formats, and then enter, 
retrieve, modify, correct and delete data 
with the forms and print reports. The se¬ 
quential ASCII data base files can be ac¬ 


cessed by any language. DMS is written 
in C88 (Intellect Associates’ one-pass- 
compiler subset of C that costs $250, 
generates compact 8088 machine code 
and comes with a linker), which makes it 
run, they say, very fast, and also makes 
good use of the PC’s screen and keyboard 
features. It requires 48K, one drive (two 
recommended) and monochrome display 
adapter. Reader Service No. 366. 

Cross-assemblers can cost a bundle, 
but here’s one for the Zilog Z8 that costs 
$150. SYSTEM-Z8, by Allen Ashley, for 
CP/M, includes a down-loader for the 
Zilog Z8 Development Module to trans¬ 
mit developed programs for in-circuit 
test. You get a macro-assembler with 
macro and conditional assembly and 
chaining, interactive editor/assembler, 
text editor, cross-reference generator, 
complete documentation and user sup¬ 
port by mail or phone. Current SYSTEM- 
Z8 owners can phone for a free update. 
Reader Service No. 376. 




55 

465 




Letters (Continued from page 6) 


by DDJ readers. First, however, I at¬ 
tacked its primary problem: it’s slow. 

I studied the code for a while, and 
decided to change the global symbol table 
from a linearly searched list to a hash 
table. I also put the macros in the global 
symbol table, with pointers into the array 
of macro definitions. Since the original 
code was well-structured, changing algo¬ 
rithms was not difficult. 

I changed “numglbs” from 300 to 
512 (a power of two), “SYMTBSZ” from 
5040 to 8008, and introduced “#define 
MASKGLBS 5 11”. I introduced “#define 
MACRO 5”, giving a new possible entry 
for “ident”. Since I’m putting the macro 
names into the global symbol table 
rather than the macro table, I changed 
“macqsize” from 1000 to 500. “macptr” 
has to be initialized to 1 instead of 0. 
(Initializing it to 0 causes a subtle bug af¬ 
fecting only the first macro. I’ll leave the 
details as an exercise for the student.) 

I added the following initializing 
code to main(): 

glbptr-STARTGLB; 

while(glbptr<ENDGLB){ 

*glbptr»0; 

glbptr-glbptr+SYMSIZ; 

) 

glbptr»STARTGLB+SYMSIZ*5; 

/* clear global symbols 

*/ 

“dumpglbsO” needed the declaration 
“int i;”, and the top of the loop changed 
to 

i=NUMGLBS; 

whiled—){ /* 6/19/82 jrvz */ 

If(*cptr){ 

if((cptr[ident]!*function) 
&(cptr [ident] 1=*1ACR0)) 

/* do if anything but 
function or macro 
jrvz 6/19/82 */ 

I introduced a simple hash function: 

hash(sname) 

char *sname; 

{ int h,c; 
h-*sname; 

while(c-*(++sname)) h»(h<<l)+c; 
return h; 

> 

I then rewrote the following routines 
where boxes indicate changes): 

findglb(sname) 

/* cptr is set to entry if found, 
or appropriate empty slot if not */ 
char *sname; 


{ int h; 

h-hash(sname)&MASKGLBS; 
cp t r-STARTGLB+h *SYMSIZ; 
while(0-- 

astreq(sname,cptr.namemax)){ 
if(*cptr—0) return 0; 
cptr-cptr+SYMSIZ; 
if(cptr--ENDGLB)cptr-STARTGLB; 

> 

return cptr; 

> 


addglb(sname,id,typ,value) 
char *sname,id,typ; 
int value; 

{ char *ptr; 

if(findglb(sname))return cptr; 
if(glbptr>«ENDGLB) 

( errorC'global symbol table 
overflow"); 

return 0; 

> 

ptr-cptr; 

while(an(*ptr++ * *sname++)); 

/* copy name */ 
cptr[ident]-id; 
cptr[type]-typ; 
cptr[storage]-statik; 
cptr[offset]-value; 
cptr[offset+1]-value>>8; 
glbptr-glbptr+SYMSIZ; 
return cptr; 

> 


addmac() 

( char sname[namesize]; 

if(symname(sname)-»0) 

(illname(); 

killO; 

return; 

> 

addglb(sname,MACRO,0,macptr); 
while(ch()-■' ' | ch()--9) 
gch(); 

while(putmac(gch())); 
if(macptr>=macmax) 

error("macro table full"); 

> 


findmac(sname) 

/* rewritten 6/19/82 jrvz */ 
char *sname; 

{ if ((findglb(sname) 1-0)6. 

(cptr [ ident ]-^iACR0 )) 

{return((cptr[offset]&255)+ 
(cptr[offset+1]<<8)); 

> 

return 0; 

> 


As a result of these changes, the compiler 
speed has more than doubled. I also en¬ 
larged the disk buffers from 128 bytes to 
512 bytes. That sped compilation up a 
further 20%, to about 220 lines/minute 
on my 2.5 MHz Z-80. 

Has anyone installed floating-point 
variables? Does anyone have a C inter¬ 
preter, that would let me debug my code 


quickly? (Note that Tiny-c accepts a dif¬ 
ferent language.) 

Keep the Small-C articles coming! 
Yours, 

James R. Van Zandt 
26 Shelton St. 

Nashua, NH 03062 


Editor’s Note: Readers who are following 
the developments in Small-C, which origi¬ 
nated with Ron Cain’s Small-C compiler, 
should keep a close eye on DDJ in the 
coming months. We have a number of 
exciting articles and listings scheduled. 

»»J 


Dr. Dobb’s Journal, Number 72, October 1982 
466 


59 


#73 November 1982 


$2.50 ($3.00 in Canada) 


Dr. Dobb s Journal 

For Users of Small Computer Systems 



UNIX 

Wildcard 

Filenames 

IBM-PC 

Subroutines 

Hash ’n Pascal 

Novice Builds 
Sinclair’s ZX81 

Memory 
Management 
in BASIC 

and more inside! 
































CONTENTS 


's Jo 




For Users of Small Computer Systems 

November 1982 Volume 7, Issue 11 


Editor — Marlin Ouverson 
Assistant Editor - Fritzi Lareau 
Contributing Editors — 

Dave Caulkins, Dave Cortesi, 

Ray Duncan, Gene Head, 

Michael Wiesenberg 
Marketing Director - Craig Harper 
Marketing Assistant - Beatrice Blatteis 
Advertising Director - Carl Landau 
Circulation Manager — Gloria Romanoff 
Circulation Assistants - 

Terri Marty, Linda Marohn 
Art Director - Clifford West 
Production Manager - Barbara Ruzgerian 
Production Assistant — Jane A. McKean 
Typesetter - Renny Wiggins 
Cover Illustration - A1 McCahon 


© 1982 by People’s Computer Company 
unless otherwise noted on specific articles. 
All rights reserved. 


Subscription Rates: $25 per year within the 
United States; $44 for first class to Canada 
and Mexico; $62 for airmail to other coun¬ 
tries. Payment must be in U.S. Dollars, 
drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be 
typed, double-spaced on white paper. List¬ 
ings should be produced by the computer, 
using a fresh, dark ribbon on continuous 
white paper. Please avoid printing on perfo¬ 
rations. Payment is in contributor’s copies. 
Requests to review galleys must accompany 
the manuscript when it is first submitted. 
Authors may receive a copy of the complete 
writer’s guidelines by sending a self- 
addressed, stamped envelope. 

Donating Subscribers Contributing Sub¬ 
scriber: $50/year ($25 tax deductible). Re¬ 
taining Subscriber: $7 5/year ($50 tax de¬ 
ductible). Sustaining Subscriber: $100/year 
($75 tax deductible). Lifetime Subscriber: 
$1000 ($800 tax deductible). Corporate 
Subscriber: $ 500/year ($400 tax deductible, 
receives five one-year subscriptions). 

Contributing Subscribers: Thomas H. 
Grohne, G. V. Elkins, Robert M. Connors, 
Robert C. Luckey, Robert N. Stabler, 
Dewitt S. Brown, Burks A. Smith, Trans- 
data Corporation, Mark Ketter, John W. 
Campbell, Friden Mailing Equipment, 
Howard E. Decker, Jim Wilson, Frank 
Lawyer, Chris Pettus, Paul Lutus, Ben 
Goldfarb, Rodney Black, Steven Weiss, 
Pat Phelan, John Brodie, James Flemming, 
Unison World, Thomas Davis, Jan Steinman, 
Ronald E. Johnson, G. Hunter, Kenneth 
Drexler, Real Paquin, Ed Malin, John 
Saylor, Jr. Sustaining Subscribers: Pete 
Roberts, Steven Fisher Enterprizes. Life¬ 
time Subscriber: Michael S. Zick. 

Foreign Distributors UK & Europe: 

Hofacker-Verlag, Tegernseer Strass 18, D- 
8150 Holzkirchen, West Germany. Asia & 
Australia: ASCII Publishing Co. Ltd, 4F 
Segawa Building 5-2-2, Jingumae, Shibuya 
ku, Tokyo 150, Japan. 


Articles- - - 

12 Expand Wildcards Under UNIX 

by Anthony Skjellum 

Unix users know their system provides for wildcard filename expansion at exe¬ 
cution. Along with this article, you will find code to enable wildcard filename 
expansion from within a program, increasing the flexibility and available power. 

18 Tests for Pidgin 

by William A. Gale 

Ever since programmer Gale published Pidgin in DDJ, our readers have been 
praising its power, portability and economical size. This month its creator pro¬ 
vides seven test programs, essentially a functional definition of the language, to 
help implementors catch any bugs in their own versions. 

28 A Novice Builds the Sinclair ZX81 

by John Connell, Jr. 

When he began, this author couldn’t tell an 1C from PCB, and had never soldered 
in his life. The perfect choice, we thought, for a test of Sinclair’s kit version of 
the ZX81. With the retail price of the pre-assembled computer at $100, why 
bother building one? Read the author’s account and judge for yourself. 

32 68000 Cross Assembler 

by Allen Kossow 

This listing completes the presentation of Kossow’s cross assembler (the first 
installment was published in our last issue). It was created to run on the author’s 
multi-68000 homebrew system featured in DDJ #68. 

44 Memory Management in BASIC 

by Henry Seymour 

Dynamic memory allocation can use array-switching techniques to store more var¬ 
iables than allowed for by RAM size. It’s all in how you manage your memory. . . 


Departments ~— 

6 CP/M Exchange 

How to add more BDOS calls; executing machine-language routines under 
MBASIC; the RCP/M Exchange system. 

9 Dr. Dobb's Clinic 

The perfect hash, with code for Pascal/Z and CP/M. 

46 16-Bit Software Toolbox 

CP/M-86 vs. MSDOS benchmarks; Intel 8087 benchmarks; 8086 SQRT. 

48 Software Review 

“JRT Pascal” 

50 Book Review 

“Teaching Your Computer to Talk” 

52 Of Interest 


Dr. Dobb's Journal (USPS 307690) is published twelve times per year by People’s Computer 
Company, Box E, 1263 El Camino Real, Menlo Park, CA 94025. Second class postage paid at 
Menlo Park, California 94025 and additional entry points. Address correction requested. 
Postmaster: send form 3579 to Box E, Menlo Park, California 94025 • 415/323-3111 


4 

468 


Dr. Dobb’s Journal, Number 73, November 1982 




CP/M EXCHANGE 


by Gene Head 


I said in the very first installment of the CP/M Exchange 
that you people, the readers, would become the real writers of 
this column. This month I present two excellent contributions 
from readers. 

Oscar Goldman developed a method of extending the 
number of system functions available to CP/M programmers. 
You remember system functions? Set up the C register with 
the function number, load appropriate data into other registers 
and then call address 5. My version of CP/M 2.2 supports up 
through function 40 (decimal). Goldman’s program is far bet¬ 
ter and the additional utilities will be most appreciated by 
serious programmers. If you have the source code for your 
BIOS and want to add special functions, give this scheme a try. 
These additional functions will not be universally transporta¬ 
ble. However, for a group or club working on modules of a sin¬ 
gle project, it could enhance the coding process. I’m working 
on modem communications programs and plan to use this pro¬ 
gram to add modem functions similar to the console functions 
(IN, OUT, and STATUS). I think of these additional functions 
as “on-line macros.” The source code with some preliminary 
comments from Mr. Goldman begins on page 7. Don’t expect 
to find this caliber of program in any other magazine! 

Cal Sondgeroth has written a fifty-line program in MBA- 
SIC that will load a machine language program into memory 
for execution under MBASIC. I imagine just about any BASIC 
program could be made more efficient by writing some of the 
code in assembler, then use Cal’s loading program to load the 
machine code. This self-documenting program (Listing 2) 
begins on page 7. 

I have established a Remote CP/M System for the CP/M 


Exchange. The primary purpose of the CP/M Exchange RCP/M 
is to receive your material for this column and provide the 
programs you will need to establish your own RCP/M, as 
well as the most current release of Christensen’s MODEM 
program. The CP/M Exchange RCP/M is tutorial, and ex¬ 
tremely friendly to first-time users. Column material and 
messages to me should be sent to drive A with file names like 
YOURNAME.MSG. 

The system is Ring-Back. That means the computer 
sometimes shares the phone with people. You call and let 
the phone ring once and hang up before the second ring. Call 
right back and let it ring until the computer answers. The 
computer is available to callers from 9 p.m. until 9 a.m. 
(Pacific time) on weekdays, and on weekends by appointment. 
The Ring-Back computer line is (503) 758-8408. The people 
phone is (503) 758-0279 from 9 a.m. to 9 p.m. every day. 
I cannot return long distance calls, so please don’t leave a 
message for me to call you! 

Finally, remember to register your known-working 
modem configuration with the CP/M Exchange either by mail 
or the CP/M Exchange RCP/M. That way, others with the 
same hardware can build on your experiences. When I get a 
request for help from someone with a similar system, I’ll send 
the request along to you. You as Helper can then contact the 
Helpee. 

Now, get a modem and go off hook! 

Dear Gene, 

This scheme is based on intercepting calls to the BDOS. 
The only visible entry point into the BDOS is the jump in- 


Editorial “ 

Functioning Randomly 


The British Broadcasting Corporation isn’t sitting still. 
Not only are they producing a series of microcomputer 
shows for broadcast, they have arranged the manufacture 
of their own machine. Viewers who follow the series will 
be able to “compute along,” making television an active 
learning process. Now, if they only would add interactive 
cable features. . . One of BBC’s people called the other day 
to let us know they are using a DDJ version of Lisp for a 
program demonstrating non-procedural languages. When I 
told Doc, he said, “Veni, vidi, vici,” but I reminded him 
that was on the other side of the Channel. 

* * * 

A short continuation of last month’s exhortation on 
the public domain: No one wants to see his “good will” 
programming effort become the key part of a piece of big- 
bucks software with nothing going to the author. So, in the 
interest of fairness, quite a few authors offer their work 
freely for individual, non-profit use, but reserve commer¬ 


cial rights. Astute readers know we have been publishing 
such material for some time — our foremost concern is that 
great software be available at a reasonable price (the most 
reasonable price is free, of course, author willing). 

But the punch line is that ideas are not copyright-able, 
only their implementation in code. If someone has a re¬ 
markable programming idea, like an electronic spreadsheet 
calculator, it will find its way around no matter how well- 
protected the original program. No one has a monopoly on 
ideas, the only trade currency DDJ accepts. 

* * * 

Speaking of ideas, have you had any lately? We know 
from the reader surveys many of you received that DDJ 
readers have some interest in advanced utilities for the 
6809, and a few other hardware odds and ends. We only 
repeat ourselves by saying that we can’t print what you 
don’t send us. Get the ball rolling and watch the result¬ 
ing systems work in our pages. 

— Marlin Ouverson 


6 


Dr. Dobb’s Journal, Number 73, November 1 982 

469 






struction at the absolute memory address of 5. While it might 
seem a simple matter to change the address to 6 and 7 in order 
to effect the interception, many applications programs (e.g., 
DDT) determine memory size from the information contained 
there. Therefore, it would seem prudent to leave the content 
of 6 and 7 alone. Fortunately, for our purpose, the instruction 
jumped to from 5 is also a jump instruction. This observation 
is the key to the interception process. 

Here is an outline of the modification to be made in the 
BIOS. (If necessary, change the identifiers to avoid dupli¬ 
cation.) 

Add the following two equates: 

MAXFUN EQU 49 ) Last of the standard BDOS function 

| numbers. 

EXTRA EQU ? ; Replace the "?-mark" by the actual 

I number of new BDOS calls. The new 
I function numbers will start from 50. 

Toward the end of the warm boot there is a routine called 
“gocpm”. (This name is used by Digital Research in the listing 
of the skeletal CBIOS.) Somewhere in there will be found the 
two lines: 

LX I H,BDOS 

SHLD 6 


FINi 


j Return to 
LHLD SAVSTK 
SPHL 

LHLD XITPAR 
MOV A,L 
MOV B.H 
RET 


here when done. 

: Restore old stack pointer. 

! Get the result of the routine. 

> As per CP/M protocol. 

; A11 done. 


TABLEi 

| Jump table for the various new BDOS calls, 
i There should be one entry for each of "EXTRA" 
NEW0I DM DONEM0 

NEMli DM D0NEM1 


i terns. 


NTRPARs 
XITPARi 

SAVSTKi 


DS 2 
DS 2 
DS 40 

DS 2 


I Save the entry value of DE. 

1 Save the result of the BDOS call, 
s Ample local stack - 
; change this if necessary, 
t Save the stack pointer on entry. 


Each of the following routines must end with a RET instruction. 
If the routine returns a value, then it should be stored 
in XITPAR. 


DONEMCh 
D0NEM1: 

etc. 


Actual routine 4tC>. 
Actual routine #1. 


Load hex. Bas 

Listing Two 


Immediately after these, insert the following 4 lines: 


LHLD BDOS+1 
SHLD NORMAL*1 
LX I H,DIVERT 
SHLD BDOS+1 


and finish with the rest of “gocpm”. 

At a convenient point in the BIOS add the following: 

Expanded BDOS 

Listing One 

NORMALi JMP 0 I The 0 wi11 be replaced during 


t 0 REM "LOADHEX BAS' IS A MICROSOFT BASIC program that CAN BE USED TO 
1J PEM LOAD ASSEMBLY LANGUAGE SUBROUTINES INTO UNUSED MEMORY FROM 

12 REM STANDARD HEX FILES AS OUTPUT BY THE CP/M "ASM" OR "MAC" ASSEMBLERS 

13 REM ASSEMBLE YOUR SUBROUTINES TO ORG AT THE DESIRED LOAD ADDRESS 

14 REM THIS CAN BE EITHER IN SOME UNUSED MEMORY OR JUST BELOW THE 
1? REM CP/M BDOS YOU CAN LOAD MBAS IC WITH REDUCED MEMORY BY USING 

15 REM THE COMMAND "MBASIC M sHADRS" WHERE "ADRS" IS THE HIGHEST 

17 REM ADDRESS THAT MBASIC IS TO USE RUTTING YOUR ASSEMBLER ROUTINES 

18 REM ABOVE THAT POINT 

19 REM 

108 CLEAR 1000 
110 PRINT CHR*-. 26 - 

120 Fit*"BASIC' HEX" REM NAME OF HEX FILE TO LOAD 

130 OPEN "I",#1 FI* 

140 PRINT "LOADING ASSEMBLER HEX FILE —> MEMORY" 

150 POKE 4HD004,1 REM THIS KEEPS MV DISk HEAD LOADED FOR SLOW I/O 
160 INPUT #1, J* PRINT J* 

170 IF MID*CJ*, 2, 2'*"00" THEN 490 

180 L*-MID*CJ#•4, 4 • REM LOAD ADDRESS STRING 

190 D#-MID*<J«, 10, LEN- J*—11 • REM HEX DATA CHAR STRING 
200 REM 

210 REM COMPUTE THE HEX LOAD AC-DRESS 
220 REM 

230 X-ASCCRIGHT*-L* 1• —48 IF X>9 THEN X-X-7 
240 L-X 


This point is reached with the function 
number in C, and the BDOS call information in DE. 


1 
I 

MV I 
CMP 
JNC 
ADI 
CMP 

JNC 
LX I 
MOV 
RET 


A,MAXFUN 
C 

NORMAL 

EXTRA 

C 

OKAY 
H,0 
A, L 


Is it an old or 
Old ones are div 


new call? 

to NORMAL. 


tr t 


) Are we exceeding the number of 
; allowed calls? 

I Continue if not. 

I Protocol requires these registers to 
1 be 2 eroed for out-of-range calls. 


i H. 

LX I H,0 
DAD SP 
SHLD SAVSTK 


we handle the new functions. 
1 HL i s 1 ost. 


) Save stack pointer for a later return, 


250 

260 

270 

280 

290 

300 I 

310 

320 

330 i 

340 

350 

360 

370 


-48 IF 


THEN X-X-7 


LX I 

SP,SAVSTK 

1 and set up a local stack. 

430 

REM 


XCHG 



440 

REM 

STORE NEX- 

SHLD 

NTRPAR 

) Save the entry parameters. 

450 

REM 


LX I 

D, FIN 


460 

POKE 

L, B L»L*1 

PUSH 

D 

I A place to return to when done. 

470 

NEXT 

J 

MOV 

A, C 


480 

GOTO 

160 

SBI 

MAXFUN*1 

) Start counting from 0. 

490 

POKE 

&HD004, 0 

ADD 

A 

1 Double it. 

500 

END 


MOV 

E, A 





MV I 

D, 0 





LX I 

H,TABLE 





DAD 

D 

1 HL points to the relevant table entry. 




MOV 

E, M 

1 Get the address 




INX 

H 

1 contained there. 




MOV 

D,M 

1 and move it 




XCHG 


1 into (HL). 




PCHL 


1 Go do it. 





X-ASCCMIDf-L* 3, 1• 

=L*‘X*16.> 

X-ASCCMID*' L*- 2 1 • --48 IF X>9 THEN X-X-7 
L-L*CX*256> 

X-ASC CLEFT*-L*. 1 - —48 IF XI 9 THEN X-X-7 
L-L*-X-4096• 

REM 

REM FETCH ASSEMBLER DATA AND STORF —> MEMORY 
REM 

FOR J-i TO LEN-D* • STEP 2 
B*=MIC'*' C-*, J, 2 • 

REM 

REM COMPUTE THE 8-BIT VALUE TO PUT IN MEMORY 
380 REM 

390 X-ASCCRIGHT*-B*.J * -48 IF X/9 THEN X-X-7 

400 B-X 

410 X-ASCCL.EFT*-B* 1 • —48 IF X>9 THEN X-X-7 
420 B-6*CX*16:- 


REM ALl.OWS MY DISK HEAD TO UNLOAD 


End Listing 




Dr. Dobb’s Journal, Number 73, November 1982 


7 




DR. DOBB’S CLINIC 




by Dave Cortesi 


The deflated condition of our mail- 
bag (broad hint) means that this month’s 
Clinic will be both short and long. Short 
because we don’t have much to say;long 
because the one subject we have is imple¬ 
mented in a fairly sizable program. 

Perfect Hashing 

Everybody knows what hashing is, 
right? You have a collection of n unique 
values, and a table of size m. You also 
have a function hash(v) which, given a 
value v, returns a index between one 
and m (or between zero and m-1). You 
store an item v in the table at location 
TABLE[ hash(v) ]. Normally, the result of 
hash(v) is not unique for all v; some v’s 
yield identical table indexes. The differ¬ 
ent v’s are said to “collide.” There are 
various schemes for handling collisions. 
When there is a collision, it will take more 
than one “probe” into the table to find 
one of the colliding values. 

A perfect hash function is one that 
produces no collisions. A perfect hash is a 
very nice thing to have, because it ensures 
that you will be able to find any v in just 
one probe of the table. Perfect hash func¬ 
tions are possible, but they are hard to 
find. The function that will produce a 
perfect hash for one set of values will 
collide all over the place for a different 
set or for a table of slightly different size. 
A minimal perfect hash is one that maps 
the n values onto a table of size n, with 
no extra slots and no collisions. 

Algorithms have been published for 
finding perfect hash functions. A new one 
appeared recently: “A Letter-Oriented 
Minimal Perfect Hashing Function” by 
Curtis R. Cook and R. R. Oldehoeft, in 
SigPlan Notices, Volume 17, No. 9 (Sept. 
1982). Although Cook and Oldehoeft did 
not publish a program, their description 
of the algorithm seemed clear enough 
that we, lacking other material for this 
column (hint, hint), decided to try imple¬ 
menting it ourselves. 

Cook’s and Oldehoeft’s algorithm 
assumes that the values to be hashed are 
uppercase keywords in ASCII, and that 
the function hash is defined as 

hash(A,Z,L, M) = (encoding[A ] + 
encoding[Z] + L) mod M 

where A is the initial letter of a keyword, 
Z is the word’s final letter, L is the 
length of the word, and M is the size of 
the table. The function depends on a vec¬ 


tor of letter codes which might be de¬ 
clared in pseudo-Pascal as 

var encoding : array [‘A’. ,‘Z’] 
of 0. .m -1 

The aim of the algorithm is to find a 
permutation of numbers in the “encod¬ 
ing” array which will cause the function 
hash to be minimal and perfect. It is es¬ 
sentially a backtracking algorithm. It pro¬ 
ceeds through a list of keywords, looking 
at their initial and final letters. When it 
finds a letter that hasn’t been assigned an 
encoding yet, it assigns the next free 
code. When both numbers have codes, it 
computes the hash function. If that entry 
of the table is free, it is claimed for that 
word and the algorithm proceeds. If the 
table entry isn’t free, the encoding to that 
point isn’t perfect. The last-assigned code 
is given up, and the algorithm backtracks 
to an earlier point to try another code. 

The contribution of Cook and 
Oldehoeft is in the ordering of the words 
before the algorithm begins. By ordering 
the words in a particular way (described 
in the comments in Listing 1, page 56), 
they assign the most important codes 
first. The ordering also allows groups of 
words to be considered at once. Doing so 


<4ev) 

XL Y 



complicates the program, but speeds it 
up quite a bit. 

There is no way of knowing whether 
a perfect hash exists for any particular set 
of keywords. It’s entirely possible that 
the algorithm could run through all pos¬ 
sible encodings and report failure. On the 
other hand, there might be many “en¬ 
coding” permutations that will serve. The 
behavior of our program demonstrated 
this. For some of the sets of keywords 
displayed by Cook and Oldehoeft, it 
found solutions in less than a minute. For 
others, it ran for hours and found no¬ 
thing. Our program’s times seemed to 
bear no relation to the times reported in 
the paper that inspired it. We didn’t have 
the patience to let it run to completion in 
any case — assuming there is time enough 
in the universe to do so. .. . 

While it is running, our program 
documents its recursive operations on the 
console. The cursor buzzes in place, 
surges forward, falls back unexpectedly — 
it makes quite an amusing movie of a 
backtracking algorithm in operation. 

In an effort (probably a misguided 
one) to speed up our program, we added 

(Continued on page 55) 


Letter encodings: 


A = 22 

H = 

9 

R = 12 

B = 21 

I = 

11 

S = 31 

C = 28 

L = 

1 

T = 4 

D = 2 

M = 

5 

U = 6 

E = 0 

N = 

10 

V = 26 

F = 15 

0 = 

7 

W= 29 

G = 24 

P = 

17 

Y = 13 


Hash values: 


0= ARRAY 

10= MOD 

20= RECORD 

30= FOR 

1 = VAR 

11 = DO 

21 = OR 

31 = DIV 

2 = WITH 

12= UNTIL 

22 = REPEAT 

32 = CASE 

3 = (empty) 

13 = TO 

23 = IN 

33 = FUNCTION 

4 = ELSE 

14= NIL 

24= OF 

34= WHILE 

5 = END 

15 = DOWNTO 

25 = PACKED 

35 = GOTO 

6 = (empty) 

16 = OTHERWISE 

26 = PROCEDURE 

36= BEGIN 

7 = LABEL 

17 = NOT 

27 = AND 

37 = CONST 

8 = TYPE 

18 = THEN 

28 = IF 

38 = SET 

9 = EXTERNAL 

19 = FILE 

29 = PROGRAM 

39, 40 empty 


Table 1 

A near-minimal perfect hash function for a set of Pascal keywords. 


Dr. Dobb’s Journal, Number 73, November 1982 


9 

471 






Expand Wildcards 
Under UNIX 


T he Unix shell provides wildcard file¬ 
name expansion for programs at 
execution. However, no standard 
facility was provided to expand wild¬ 
card filenames from within a program. 
This package provides the capability to 
expand wildcard expressions from within 
a Unix program. Thus, programs which 
accept/require wildcard filename expres¬ 
sions may be made interactive, if desired. 

Description 

The Wild package consists of five 
subroutines. These subroutines provide 
the ability to specify a wildcard expres¬ 
sion and then request the name of each 
unambiguous file satisfying that expres¬ 
sion, one at a time. This provides a low- 
level mechanism which may be elaborated 
upon in specific programs. 

The essential mechanism for wild¬ 
card expansion involves the use of the 
standard Unix LS(1) (directory lister) 
facility in a subprocess. LS is used to 
create a list of file names, which are then 
read from a temporary file as needed. 

Tutorial Introduction 

Wild allows a program to handle one 
or more wildcard expressions concurrent¬ 
ly. Each active wildcard expansion uses 
a file, so the number is limited to the 
number of files which a given process 
may have open at a given time. Normally, 
programs will only perform one wildcard 
expansion at a time. 

C programs which use Wild should 
include the following: 

#include <Lstdio.h> 

#include <.wild.h> 

which includes the standard library head¬ 
er (stdio.h) and Wild’s header fwild.h). 
Successful compilation will not occur un¬ 
less these statements are present near the 
beginning of each C program which uses 
Wild. 

Each unique wildcard process re¬ 
quires a structure of type WILD. Most of 
the internal parts of this structure won’t 

by Anthony Skjellum 

Copyright © 1982, A. Skjellum. All rights 
reserved. May be used for any non¬ 
commercial purposes. May be freely dis¬ 
tributed for any non-commercial pur¬ 
pose but all copyright notices must be 
retained. Anthony Skjellum, 1695 Shen- 
nandoah Road, San Marino, CA 91108. 


concern users. For each concurrent wild¬ 
card expansion to be performed, include 
a declaration of the form WILD wild; in 
the appropriate routine of the C pro¬ 
gram. This declares the structure wild in 
a form suitable for use by this package. 

It will be up to the user program to 
obtain or generate wildcard expressions. 
These will most often result from a user 
request (e.g., the program may obtain 
such an expression when it requests a file 
list). In any case, the subroutine wopen 
will be used to initiate wildcard expan¬ 
sion once the wildcard expression is avail¬ 
able. wopen' s sole argument is a pointer 
to the string containing the wildcard ex¬ 
pression. It, in turn, returns the informa¬ 
tion that will be needed for actual wild¬ 
card expansion. Calls to wopen take the 
form: 

wild = wopen (expr); 

where wild is a structure declared previ¬ 
ously and expr is an appropriate wildcard 
expression. Conceptually, we provide the 
expression through expr and certain para¬ 
meters are placed in wild as a result. The 
wild structure will be used by the other 
subroutines in this package to do the ac¬ 
tual work of wildcard expansion. 

A complementary function, called 
wclose, is provided to terminate wild¬ 
card processing. This is used when wild¬ 
card processing is completed and we wish 
to release the file pointer associated with 
the wildcard expansion. Always issue a 
wclose call for each open wildcard ex¬ 
pansion before the program exits. 

wclose takes a single argument which 
is a pointer to a structure of type WILD. 
Thus to close the expansion process wild 
we’ve used above, the call wclose (&wild); 
would be executed. 

We have now seen how to open wild¬ 
card processing and terminate it. Now 
we’ll discuss the most important subrou¬ 
tine in this package: wnext which actu¬ 
ally supplies the filenames which have 
matched the specification given to 
wopen. Again, we will specify a pointer 
to the structure of type WILD (e.g., 
error = wnext(&wild);). wnext returns a 
completion value which is zero for suc¬ 
cessful completion. A non-zero value 
means that no filenames remain. 

Once the call to wnext has been com¬ 
pleted, the filename is available (if the 
call was successful). This is accessed as a 
component of the WILD structure. Thus, 
wild.fnnam [] is the string containing the 
filename just obtained. This may be ma¬ 


nipulated as desired but will be overwrit¬ 
ten during the next successful call to 
wnext. 

The three subroutines already dis¬ 
cussed allow for wildcard processing in C 
programs. One further subroutine, wwind 
allows the process to be restarted without 
the need to use wclose followed by a new 
call to wopen. (Should a program need to 
scan through the list of file names several 
times, it may be more advantageous to 
store them in a string array.) Note that, 
like wnext, wwind takes a pointer to type 
WILD as its argument. 

This concludes the tutorial introduc¬ 
tion. It is recommended that the reader 
study the file wtest.c which is an example 
of the Wild package in use. 

More on Subroutines 

wopen: initialization 

The subroutine wopen must be called to 
open the wildcard processing for a given 
specification. 

wopen (dir) 
char *dir; 

wpopen: alt. initialization 

Same as wopen but uses a pipe to effect 
processing. This may prove faster than 
wopen but wildcard processing with 
wpopen may not be restarted with 
wwind. 

wpopen (dir) 
char *dir; 

wclose: termination subroutine 

The subroutine wclose is called when the 
processing of a given wildcard is com¬ 
pleted. 

wclose (wild) 

WILD *wild; 

wnext: get next matching filename 
The subroutine wnext returns the next 
filename as wnext.fnnam[ ] if one is avail¬ 
able. It returns zero for successful com¬ 
pletion. 

wnext (wild) 

WILD *wild; 

wwind: restart wildcard processing 

This allows a rescan as described in the 
tutorial. This may only be used with pro¬ 
cessing initiated with wopen. 
wwind (wild) 

WILD *wild; 

Linking 

To link in the Wild subroutines, use 
the command -Iwild as part of the link 
command line. 


12 

472 


Dr. Dobb’s Journal, Number 73, November 1982 



Wildcard Expressions 

Wildcard expressions consist of any 
collection of regular expressions separat¬ 
ed by spaces. Any file specifications that 
work with LS(1) work with this package. 
The following is an example of a valid 
wildcard expression: 

* c *,o *.s 

which specifies all files ending in .c, .o, 
and .s in the current dictionary. 

Limitations 

File names were arbitrarily limited 
to 128 characters in length. 

Files 

/ul /src/Wild/wtest.c 
/ul/lib/libwild.a 

•*J 

(Listing begins on page 14) 


WILD Listing 


Synopsis 

#include <wild.h> 

Subroutines 
wopen: Initializer 
WILD wopen(dir) 
char *dir; 

wpopen: Alt. Initializer 
WILD wpopen(dir) 
char *dir; 

wclose: signals completion 
wclose(wild) 

WILD *wild; 

wnext: get next file name 
wnext(wild) 

WILD *wild; 

wwind: permits rescan of file names 

wwind(wild) 

WILD *wild; 


type definitions 


typedef struct 

i 


char 

W_actv; 

1* signals initialization */ 

char 

W fnam[ 128] ; 

/* contains current file name */ 

char 

W nam [128]; 

1* contains name of temp file */ 

char 

W eol; 

/* indicates out of names */ 

FILE 

*W fp; 

/* pointer to temp file */ 

> WILD; 




Dr. Dobb’s Journal, Number 73, November 1982 


13 

473 




O TJ 

TJ — 

V 3 

W I 

V V 

Qj <U 
TJ TJ 
3 3 


— TJ 

Hi 


U1 
in 
Qi 

C 

a. 

x 

cu 


o — 

t_ XJ 
Ol - 
6 £ 
E O 
O t. 
U CL 


CP 

QJ 

C 

C 

o 


o c 
a o 
l. — 

3 W 

cl in 


— Q. 
L. 

• & C 

wen 

CD E v 

cr> a •*-» 

v o — 

I L. 

~ c 3 


E 3» l_ 
3 C O 
— * c 


n l 3 
-> 0*0 
X 

in 

TJ 3 
3> Oi O 

c in £ 

O 3 4-* 

c — 

^ 01 3 
c n 
<r in 

3» Oi 
3> * in 
X) Z 3 


cn 

c 

in 

in 

a* 

o 

o 

c. 

a. 


TJ 


tj 

U 

TJ 



3 


a. in a* 

3» C 3 

- cr i 

tj n i 
*4- V L. 

O C I 
O 3» I 
n u - 

t_ — i 
3 Q <0 . 
V _| 3 ( 
O *H 4-» 

3 3 u * 


in a c cu 
3» a; a 
•0 v £ in 
3 

in «*- tj 

C O T3 Qi « 

L. Hi TJ « 

3 Oi in C w 

♦» L 3 <» ♦» 

(U 3 CL X 
L U Oi X Oi 

U D Qi C 

(U 3 3 

C l_ O CU 

— V V £ O' 


o a» o 

L C- 


in Q o 

- J f 
JC H C 
»- 3 - 


l a e in tj 


in «♦- 

• cu 

oi in • 

o> 3 <« w 

L. 4-> O 

t_ «0 C 
c CU TJ - 
ON 3 

— C 3 
CT—O 
c tj — q, 

— - w c 
in v c v 
in - tj 

CU C QU 
(J - X 3 

o a > a 
c. a* 

Q. TJ » 
TJ l_ l_ 
TJ C D Oi 
L. l_ O V 

•0 Oj in 

O V TJ <0 
TJ — — <4- 

— TJ — 

— 3 Oi 

3 in xj 

— c 

01 c - o 

♦> I- t ♦* 


oi in 
I — c 
xj tj 
i -« a 

in x 


o o 
c c 

— — * 

n u \ 


TJ 

Ol 

N O 

— V 

TJ t_ TJ 

— V Oi 

V Q. 4-> 

- w w 

C . 3 

- TJ Ol Tj 

Oi — E £ 

l_ - *0 X 

CL 3 C CU 


o> 3» 4^ in 

£ xj c — 

v cu 

tj i_ ♦-» 

E Oi l_ in 

O 4-> 3 — 

l_ «« u — 

*4- U 

- 01 <U 

Oi tj £ £ 

EC «-> ♦-> 

'TJ — 

c in «4> 

Oi C — 

Oi O — 

— C u) H 

— Oi V I 

*4-3 C 

o' o in 

V Oi U — 

x in • 

Oi — Oi 

C TJ Q E 

L. _l tj — 

CU « H CO 

C 0 3 «4- Oi 

4-> . . 

TJ Ol TJ TJ 

V ~ Q. — — 

Oi — 3* - - 

0 3 4-> 3 3 


— cn w tj 

TJ 3 TJ — 

C O — 4-» 


tj in c o 


O 3 4-> O 

Oi C - c 

C-OiC- 
v in E o in 

in tj 3 w 
♦-* oi in ai 
Qi u in u 

in o oi - o 

Oi L £C L 

c a. v *- a. 


in 
E oi 

t_ tj — 

0) TJ L - 

O Oi 0*4- 

c in o 

o 3 i_ • 

- a. a. 

oi e • 

O XJ Ol Qi in 

C C V Ol 

TJ V O 
4-> — 3* l_ 

- 3 Oi L 3 

o l_ tj q. 

in c o in 

oi in *4- in c 

X Ol Ol Ol 

Tl — XJ U 01 

Z — Qi 3 

• C 4-1 

O o C Ol 

Oi 3 XJ 

u in a. 

cu -'* in % cl 

Q- x: cu E 

in J- tj in 4-> 

i_ - \ 

TJ -TJ 3 

L. • O L. C 

TJ Qi ^ Qi o 

o in — c 

TJ 3 - ^ Ql 

- 3 0 4-1 


3 O C — 


— VO 
XJ C TJ U 
TJ O C TJ 

— TJ — 

— Ol E — 
TJ L - 

D c m - 

*0 o v 3 


TJ 

3 


Ol 

in 

o 


u 

3 


\ 

* 



S * 
c r) i 


3 
I Q 


CL - 
O TJ 
3 * 

Q C 
_J *0 

•-4 JC! 

3 O »■ 


3 

•S 

C 


\ 

* 



# * 

« # 

* » 

* # 

* * 


I 

I * 

Q C 
_l — 
m r 


o o o 


—) C\J 
X CD 
U) O' 

o 

C V 

o c 


3> O 
XJ U 


in * 

Ol v 


XJ <4- o l_ 


\**#*###*####*»* 


O <4- 
\ - 
* X TJ 
3 Oi 

oi in 

E Oi D 
TJ E 


\ in - 
# 3 C 
u - 


\ (_ C O O 4-» o 


c >0 « 4 - 

O £ 

— VO 


— # 


\ \ 


Oi V V 
TJ TJ Ol 

o 

— Ol 
TJ — 
C — 


* CD n 
\ (VJ CD 
v (XJ 

^ E u 
V <TJ E 


I I I 

3 3 3 


1 _ Ui HI 

* _l 3 

£ hi 
O li. 




in — in 

o Oi 

o. — o 
i_ u — 
3 o v 
a oi o 
E C 

— S 

TJ O V 

— O £ 
o I cn 
l_ C — 
Ol O L. 
E C 3 < 


— C 0 ) TJ 


E 

3 ~ 
— O 


— 3 

— a 
* — 


cn 

V c 

c — 
oi in 
c in 

o Oi 

cl o 
E o 
o (. 
o a 


tj in oi 

Oi 3 * * c 

in — 

3 oi in tj 
O l Ol v 
oi c in oi 

XJ <*■ O L 

a. 

O' TJ l_ Ol 
TJ C 3 L. 
E <0 o. <a 


\#***#***###**#» 



14 

474 


Dr. Dobb’s Journal, Number 73, November 1982 


, Page 




16 


Dr. Dobb’s Journal, Number 73, November 1982 

475 


Tests for Pidgin 


T his note introduces seven test pro¬ 
grams designed to test an implemen¬ 
tation of Pidgin. Passing all of these 
tests probably means that only a few 
macro bugs are left, or none if you are 
lucky. They form a useful functional defi¬ 
nition of the language, even if not quite 
complete. 

I would be delighted to hear from 
anyone with a macro bug that was not 
caught by these tests, so that a test for it 
could be added. (Such a bug would show, 
if the previously published code for 
Tincmp, for instance, failed to run even 
though all these tests were passed.) 

The first program looks very simple, 
yet when it runs, your job is at least half 
done. It basically shows that you have a 
compiler capable of accepting an input 
and producing a running output. 

The second program introduces the 
test methodology used in the remaining 
programs. The IF and ENDIF macros 
must work for the tests to be useful. 
Bugs on IF . . . ENDIF usually result in 
completely wild response and so are easy 
to see. The messages printed out if every¬ 
thing works right will just give sequences 
of numbers, then of letters. These turned 
out to be helpful in identifying pieces of 
code in the machine. Sequences of nine 
identical characters stand out fairly well, 
and you can locate parts of code for 
single step checking. If something wrong 
happens, a brief message is put out be¬ 
tween the blocks of numbers. 

The second program tests byte arith¬ 
metic, and the third tests integer addition 
and subtraction. Special tests are made 
for cases where there might be some try 
at optimization. Test 4 exercises the 
multiplication and division, with several 
cases covering the good possibility that 
these are done by subroutine. The logical 
operations are also checked. 

Test 5 is a test of subscripting and 
of the WHILE control statement. Test 
6 tests the remaining control structures 
and pack and unpack. 

Test 7 is the most difficult of the in¬ 
dividual tests. It is very specific about 
what needs to happen for the I/O state¬ 
ments, and requires taking out idiot in¬ 
surance against such things as writing on 

by William A. Gale 

William A. Gale, Ph.D., 439 South Orange 
Avenue, South Orange, NJ 07079. 


files opened to read, and vice versa. Since 
these functions are almost surely done by 
subroutine, they probably require the 
most assembly language programming. 

These seven test programs for Pidgin 
are public domain. Machine readable 
copies for Apple are available for the $5 
cost of a disk and mailing from Bootstrap 
Toolkit, 439 S. Orange Ave., S. Orange, 
NJ 07079. 

(Listing begins at right) 


18 

476 


Dr. Dobb’s Journal, Number 73, November 1982 



XI 

-Q 

II 

v 

TO X 
HX 11 

ii in 

X U-I i-H 
X-H 11 


a\ 

Ch 

o\ 

i <n 

cr\ jq 
cn XI 

<T> (N II 
o\ o v 

U-I a\ O (0 
•rH - + TO 

X) II II 

c tn a x 
m ex x 


o 

o 

o 

o 

O XI 

o X) 

O II 

o 

O TO X 
- + <0 X 

+ II 

i/i n xm 

e <u x -h 


1 

XI 


TO 

o 



• 

XI 



o 




J 3 



o 



tn 

.Q 


m 

o 



E 

-Q 

CN <D 

E 

o 


O T 3 


XI XI 

•% <D 


o 

TO 



X o vr x 

v* II 


u o o 

TO 

O || 


X) in vn + 

rH —• 


u o m 

1 

O — 


+ i 
tn to <o 
Emm 


wXoo m rt-o x 
- + + <(J + X> X 

X> II II II || || 

C «l H J U 1 ) X W 

iiEmX’oox-H 


- + + xi + to 

ii ii ii ii n 

m u jo x> <o x 

E u xi xi <o x 


• 

- 




• 


— 


m 

CN 

n 


II 


li 


H 


»• 

CN 

n 


II 




H 


A 

CN 

in 


in 


cn 


ui 


cn 

Csl 

H 


r—i 


H 


r —1 


r—i 

CN 

•rH 


•rH 


•H 


■•H 


•r-i 

CN 

TO 


TO 


<T 3 


TO 


CO 

CN 

U-I 


U-I 


U-I 


U-I 


U-I 

CN 

II 


II 

- 

II 

• 

“• 

• 

_« 

CN 

II 



m 

•• 

V 

V 

in 

V 

• 

m 


m 

m 

•* 

VT 

» 

in 

m 





m 


vr 


in 


cn 

in 


tn 

m 

tn 

VT 

W 

in 

cn 

E 

E 

XI 

E 

m 

E 

VT XI 

E 

in to 

B 



XI 


m jo 


vr .Q 


m to 




II 


m in ii 


VT rH — 


in <n -• 






mo — 


vr o v 


in o v 



U-i TO X 

■h m x 

X) II 
C XU 
<D X —• 


u-i m o <o x 

•h • + m x m 

xi ii ii m 

C in XI X UH r-H 

« E x X -H 1) 


w ^ o m x 

•-I - + m x 

X) II II 

c nx xw 
<U £ X) x -h 


umoX 
•-< - + X 

XI II II 

c in xi x 
0 ) e .Q x 


vo 

VO 

vo 

VO 

vr XI 
vo XI 
vo —• 

vo v 

«m vo m x 

- m x 1) 

x> ii in 

C M XWH 

d> E x <u 


- 


II 

• 

t"- 


V 

on 



- 

00 

r- 



on 

r~ 


in 

00 

to 


E 

00 

r~ to 



00 

r- ii 



00 rH 

r~ v 



00 o 

uu r- xi 

X 

U-I 

00 o 

•rH . xi 

X 

•rH 

- + 


il xw 
E X 


XI II 

c in xi 
<u e xi 


ii u c 

O ■'-* 

tn 4 J 


- u m • 
IT (J O 'H t? 


-W 

u. 

o 

UO 

o 

00 to 3 

c 

.V « 

VD 

o 

00 

0 ] 





H 

e 

Q 

c 

CTs 

o 

c 

W rH 

h S 

o> 

o 

o 

— w 

in 

(/i 

UI 

(11 



o 

O 

o 

II c o 

E .X 


O 

o 

II 

C E 

XI E 

E 

E 

E 


V VO Vj -H H Ih 

on ii ioh • o C 
II II u £ 0) D ) 'H E 

EEWCXTr-t too 

II U -H <H > . . g 4 J 

O* E E O' O' T3 

OO'HlIOMfllllllcO 

•prHx:uxiEEe<uxi 


<rvo vi 
on® 
II II -u 


E E 

Q-E E tojj wu o o o o> 
O O — 0 ) >,>,>,>,>,>,(0 

*JrH.c uxix>x>.ax>x)x> 


m x o xi ii m 
m x o tj ii E 


O O "3 


Dr. Dobb’s Journal, Number 73, November 1982 


(Continued on column 2) I (Continued on column 3)\ (Continued on next page) 




• 





+ 




+ 




• 





+ 




1 




in 





+ 




+ 




rH 





• 




• 




• rH 





• 




• 




03 





• 




• 




UH 





in 




XI 


— 


1 

• 




TJ 

r 



D 

m 

03 


1 

X) 




03 

O 



in 

tj 

03 


- 

XI 


CN 


— 

O 



_ 

TJ 

03 

XI 


XI 

XI 


03 


O 

03 

T3 


no 

03 

XI 

in 

.Q SI * 3 * 

XI 


03 

in 

u s s 

03 

(Si TJ 

in 

TJ 


03 **4 E .Q in VO *4 rH -rH 

<0 II D s s + H It 

03 — _Q <3 S UJ Q - 

<tj m ia^-trHfljtNTJ 

■'0 + I 0J X 44 X) 4- + -M 4- T3 X 

- + I —I X *—• - II II II II -<4 X 

0303 II TJ 03 X) TJ 03 II 

w 0! 03 X >H CWOJD'DdJX'W 
E "4 "rH X *H QJ E *•—I *<H -rt ..H X "14 


D Q Q | 13 II 
U Q S U B - 


U rH 
44 O + 

•rH - || 

TJ O 

c in o 
oj e -<h 


U H H H S 03 
O + + •H + 03 
- II II II II *H 
O XI TJ 03 II 
W O XI TJ 03 X 


TJ CM 

TJ X) XI •*£> TJ 0) 

TJSSXM'XM'X'O <13 
T) <3 IT) -rH CD —I rH -rH -H -rH 

T) S Q I S | rH | 4- II 

TJ SI SI 03 SI 0] ® (13 U ■* 

T) 13 H .5 H 03 CM 03 U XI 


4H TJ + + 
"4 - II II 
TJ 03 X) 
C W 03 XI 
0) E •-> >r H 


X) + + -rH + -n 4 . -rH -rH X) X 
- II II II II II II II II "H X 

n3X>OX3T3X>OJX)ll 
in o3Xi uxiT3Xiaija xuh 


Sl 

TJ •» X) 

TJ XI 

•rH rH .rH 

I SI II 
O SI — 
US 11 

•rH + ai x 

II II "4 X 
XI 03 II 

X3 0) X 4H 

•rH -rH X -rH 


to ® 
0> ® 


■- O) 

0 ) C 

"O 7 

« w 

a □ 


VO O 

CO IS 00 03 

O' SI SI —' 

S SI II C 

'Tlfi U -rH 

taro ai x 03 X) O T3 o> 03 

II II 4-> X 03 X) U TJ 03 E 

E E W "rH .rH -rH -rH .rH C 

03 03 -rH <U -rH 


» 

• 

m m 


• 


m 




ro 

II 

u C 


II 


II 


II 


(Si 


O 


II 


II 


—• 


4J 

W 

4J 


0) 


(/) 


ID 



rH 

•H 


rH 


rH 


rH 


— c 

•rH 

UH c 


•rH 


•rH 


•rH 


> -rH 

(TJ 

•rH *rH 


03 


03 


(TJ 


<TJ cr* 

UH 

UH 


UH 


UH 


4U 


•rH d) 

II 

Wh 0) 

• 

II 

- 

II 

• 

II 

- 

-X) 

II 

O TJ 

rH 

II 

(N 

»• 

ro 



0 - 

m 

■» m 

rH 

• 

(N 

• 

ro 

• 


(TJ A 



rH XI 


<N X 


ro x 



—' C/1 H fN D 

U) 

in in 

*"H rH X 

in 

(N X 

in 

ro in X 

ID 


C E si si -h 

£ 

E E 

rH (Si *H 

E 

(N -H 

E 

ro (Si *h 

£ 



SI S> II 
»—1 .—I 03 


ro si II 
roi t3 — 

ro rH 03 


in **4 

•rH 

•rH 

•rH 

•H C 

+ + 

03 X 

Uh 

rH 

+ 

03 X 


UH 

CM 

03 X 

UH 

m 4 . 

03 X 


UH 

sr 

■rH <D 




•rH 

II II 

**4 X 

•rH 


11 

~4 X 

03 

•H 


••4 X 

•rH 

- 11 

•H X 

03 

•rH 

m 

O' MJ 4-1 

4-3 

+J 

4J 

4-3 O' 

03 XI 

II 

TJ 


XI 

II 

in 

TJ 


II 

TJ 

XI 

11 

in 

T3 


03 >. C 

c 

c 

c 

C 03 

03 X3 

X UH 

C 

in 

XI 

X UH 

rH 

C 

in 

X UH 

C 

in xi 

X UH 

rH 

C 

in 

M X3 -rH 

•rH 

•rH 

•rH 

•r4 XI 

•rH »rH 

X -r4 

03 

E 

•rH 

X -rH 

03 

0 ) 

E 

X -M 

03 

E ••• 

X -rH 

03 

03 

E 


TJ 

TJ 

n 

TJ 

TJ O CM 03 

TJ •* XI XI •• .Q TJ 03 

TJ O O X) T X) V X) TJ || 

D O in I CD | rH | + — 

uh TJ o o 03 o u h n u XI 

•n - + + 03 + 03+030X3 

II II II 


.H- + + 03 + 03 + 03UX3X 

TJ II II II II II II II II II 

CW03X>OX>T!X>aiX>X4j 
oeiuXuX'DXaixx.H 


+ 


A 


A 

1 


II 


II 

• 


1 


1 

• 


1 


1 

• 


1 


1 

TJ 


X) 


XI 

TJ 

_ 

O 

» 

D 

03 

03 

in 

UH 

in 

* 

03 

• 

UH 

m 


03 


UH 


in 

03 

in 

U-4 

in 


03 O XJ 
03 T! •* XI 

03 T) T II 

03 I rH r» 

UH 03 (J O 03 X 

■rH . O + 03 X 

TJ II II II 

c w .a 03 x cm 

0 g X 0) X .4 


4h O u 
4J U .«• 03 U 

CM U C 03 II 

UH | O I — 

»M 4h T> O 03 XI X 
■rH . *0 + 03 XI X 
TJ II II II II 

in xi 03 o x uh 


c in xi 03 
oi e xa 03 


cn 

CTC 

m 

O' 

O' CM 03 

O' X) — 03 

O' •—! co X) 11 

O' o o + o — 
UH O' O O 03 O O 
"4 - 4- 4- 03 4- U 

TJ II II II II II 

C in 03 XJ 03 U X 

03 E 03 XJ 03 O X 


Dr. Dobb’s Journal, Number 73, November 1982 





4-1 O 
4-1 U 
U-l ■«-( 

4-1 I 
4-1 T) 
4-1 T3 
4-1 4-1 -h 

•rH - || 

•D XI 

c in x 

4) e •-< 


<1) U 
S HI O 


El TO -• 
(3 ID XI 


TO Cl II 
<0 U X 


m 



- 


m 


_ 


1 



• 


X 


X 


A 



+ 


+ 


+ 


II 



X 


• 


X 


1 



II 


II 


II 


1 



X 


X 


X 


1 



• 


• 


• 


£) 



0) 


(/> 


in 


3 

- 


T> 

- 

TO 

• 

•o 


If) 

cn 


TO 

X 

TO 

•H 

TO 

•m 

• 

CP 

CN 

- 

x m 

- 

•rH l£> 


•m 


CP X 

(T3 


X X «*x 


•rH O •- U 


•m 

if) 

O' h m x 

03 

</) 

x X r- x 

W 

•rH U ^ U 

to 

•men 

B 

CP S> S' ■'■4 

IS) 

6 

X -H Q H 

e 

•H ’H H *H 

g 

•m o 


CP El El + 

SI II 


X + El II 


•«H + IS II 


•m Q 


CP Si El TO 

ts — 


X TO <S —• 


•cH O Q 


•m q 


CT* ’—( H TO 

(N U 


X TO CO Cl 


•rH U VD XI 


TH rH 

4-4 

CP + + •-« 

+ ci 

X 

4-1 X -rH + Cl 

X 4-1 

•H *H -f- jQ 

X 

(4-1 -1— 


-Q *>» <X3 
XI <o 
•■h s> *<-i 


to X) 
w (ox 

£ 'H >rl 


- II II —I 

Cl XI II 
in ci x x 


4-i -n+ + —i 
- II II II 

T> TO X TO 

C W TO XI TO 

(1) £ *H -*H *H ' 



• 


- 


• 


• 


• 







II 


—• 


—• 


—• 


II 


—• 



• 


II 


A 


V 


A 


II 


V 



• 


If) 


if) 


w 


0) 


if) 


w 



w 


rH 


rH 


rH 


r—i 


rH 


rH 



rH 


•rH 


•rH 


•rH 


•rH 


•rH 


•rH 



•rH 


03 


03 


03 


03 


03 


03 



03 


(4H 


44 


(4H 


(4H 


44 


4-4 



4H 


—• 

• 

—• 

- 

—• 

— 

II 

• 

II 

m. 

|| 

• 


+ 


V 

m 

V 

ID 

V 

r~ 

V 

00 

V 

CT» 

V 

CS) 


+ 


• 

in 

• 

ID 

• 


• 

00 

• 

CT. 


ca 



XI 


in 03 


ID X 


r~ to 


00 X) 


CTv XI 


<S> 

x 


f—i X) 

if) 

in CN 03 

w 

ID X 

if) 

r-' to 

w 

00 rH X) 

w 

Ch CN XI 

w 

S3 

X 

if) 

<S) *rH 

B 

ins-H 

B 

ID ’-4 

B 

r-~ -<-i 

B 

00 <S) *H 

B 

CTv «S) *H 

e 

IS) 

•r4 

B 


ID SI -• 

ms v 
(AHXl 
4-i m + xi 
—I - n —i 
TJ X II 
C W X X 
HI E'H X 


ID 

ID V 
ID TO 
ID TO X 


r- ii 
r~ v 
r- X 

4-i r~ x x 
"H - •'-•X 
T> II 
C W X 4-1 

ai E x •*-< 


oo s || 
oo si v 

00 -—I TO 
4-4 00 + TO X 
•-< - II 'H X 41 
T> X II W 
C W X X 4-1 r-t 
01 e-^ X-H « 


cn si ii 

CD Q V 

Ol H TO 

44 01 + TO X 

- II X 04 

TJ X II M 

C W X X 4-1 r-t 

0) E ’H X H 01 


4-4 IS + TO X 

•■H - + —I X 

T> TO II 

C V) TO X 4-1 

04 6 **H X *<H 



- 





T3 


• 





T> 


• 


X 





TO 


•rH 





TO 


•r-» 


X 





- 


•rH 







•n 


X 







•rH 







•m 


X 





(/) 


•rH 





(n 


•n 


X 


m x 


E 


•rH 


IX 

C4 


E 


•rH 


X 

X 

•% 

X 




• rH 

Cl 


Cl 




•IH 


X 

X 

r- 

II 




•rH 

Cl 


II 




•fH 0> 


X 

+ 

o 

-• 




•rH 

+ 

rH 





•no 

44 X 

TO 

o 

Cl 

X 


4-1 

•rH 

o 

o X 

X 


4H 

•me 

•rH 

• 

TO 

+ 

Cl 

X 


■H 

• 

Cl 

+ 

X 

X 


•rH 

- + 

TJ 

if) 

II 

ii 

II 



T> 


II 

ii 

II 



T3 

II 

C 

X 

o 

X 

4-1 


C 

if) 

U X 

X 

4-1 


C 

if) 03 

04 

E X 

o 

X 

•rH 


04 

e 

Cl X 

X 

•rH 


cu 

e ro 


O TO 
X •» TO 


II II II II 


• 


- 


m 

• 

• 


X 


X 

CN 

1 


1 


1 

O 

X 


• 


X 

4J 

II 


II 


II 


X 


X 


X 

(44 

• 


• 


• 

O 

JQ 


X 


X 

T3 

3 

- 

3 

» 

3 

c 

if) 


in 

rH 

in 

<D 

• 

.X 

— 

rH 




-X 


rH 



(/) 

-X 

in 

rH 

in 



-X X 

-X XX 

■X CTl X II 
-XO| — 
4-1 X O TO O 

•-H - + TO Cl 

T) II II II 

C W TO X X 

04 E TO X X 


X 4-1 

X ->H 

T> 

44 C 

i-4 (14 


o x 

TO •* X 
TOOK 

I O — 

TO O TO X 
TO + TO X 

II II II 

TO X X 4-1 
TO X X --1 


Dr. Dobb’s Journal, Number 73, November 1982 


(Continued on page 20, colutnn 2) I (Continued on page 20, colutnn 3) | (Continued on next page) 










+ 







+ 








4-1 





__ s 






H 






ia 








\ 







\ 








•rH 





4-1 






<a 






ca 








+ 







1 













•rH 






*—1 






ca 








> 







> 








u 











# 






0 








•H 







•rH 








o 





o 






0 






0 








X 







XI 













—■ 






0 






0 








O 







o 








s 





s 






s 






s 




- 




3-1 


— 





3-1 


- 








• 



ca 


• 




n* 






(\0 


m 


O' 




44 


x 





4-1 


•rH 






s 


•n 



c 


2* 




c 


rH 




t 


B 


O' 




— 


x 





— 


•rH 






• 


•ra 



. 


2*f 




V 


rH 






£ 


O' XI 


X 




-C 

X 


X 




•rH 








•r-i 











rH 






£ 


O'l-' XI 

ro 

X 


01 


x 

X 


X 


1/3 


•rH 






W 


•m 



in 


2* 




in 


rH 




in 


£ 


O' •-H ■•"* 

Q 

• rH 


g 


X 

•rH 


•rH 


e 


•rH 






E 


•r-» 



B 


2* 




B 


rH 




£ 


£ 


U*ca \ VO 

II 




X 03 

\ 

X 

ii 




•rH 



X 





•r-» 

X) 





X 





rH 


X 




£ 


O' SI 03 

ta 





X 03 

03 

TO 

—• 




•rH 

#—i 

rH 

X 





•r-* Si 

X) 




2* 

X 





rH 

ca 

X 




£ 


O' Q 03 

ca 

O 




x 

03 

•rH 

O 




•rH 

ca 

ca 

I* 





•r"» ca 

«4J 




2* 

C'- 





rH 

ca 

o* 




£ 

03 

O' + ■-> 

+ 

o 

o 


44 

X 1 

•rH 

1 

O 

o 


44 

•rH 

ca 

ca 

03 

o 



344 

•r-i csj 

03 

u 


4-1 

2* 

03 

O 



44 

rH 

ca 

03 

o 


44 

£ 

03 

- II II 

II 

•H 

u 


•H 

- n 

ii 

II 

•rH 

o 


•rH 

- 

+ 

+ 

03 

u 

0) 


*H 

- + 

03 

o 


•rH 

_ 

03 

U 

01 


•rH 


+ 

03 

o 


•rH 



X) U 

X 

ii 



X 

03 

o 

X 

II 



X) 


II 

n 

II 


in 


XI 

II 

II 



X 


II 


03 


X 


II 

II 





|| 

0) X U 

X 

o 

u-t 


C 

to 03 

o 

X 

o 44 


c 

l/) 

03 

X 

U 

44 

rH 


c 

in x) 

O 4-1 


c 

in 

U 

»*4 

H 


c 

in 

03 

O 

344 


c 

in 

u 

g "H 

•H 

o 

•rH 


a) 

e •'i 

•rH 

•rH 

O 

•rH 


01 

e 

03 

X 

O 

•rH 

01 


01 

E X) 

o 

•rH 


01 

E 

U 

•rH 

01 


01 

£ 

03 

o 

•rH 


0) 

E 

o 


4J 

c 

•H 

i 

ii 


« 

+ 

»-H 

3 

G 

4-1 

c 


I 

* 

+ 

I—I 

3 

£ 


* 

X 

II 

x 


x 

■K 

0 

II 

X 






•rH 


f- 







•rH 


00 






•rH 


CT3 







E 


ca 





g 


03 









• 


r-' 







• 


00 






• 


CT3 







- 


ca 







03 





m 


X 


in 


r- 



X 


o 


oi 


00 


X 


o 




03 



X 


03 




ca 


X 

X 




03 

03 


o 



X 




tO 

ro 

X 

00 

u 



00 


X 


o 


c/l 


O' 

a 

ca 

X 

ca 

03 


to 


ca 

ca 

X 

X 


to 


03 

03 

ca 

(J 


ca 

03 

■r4 


E 


r» 

in 

ta 

•rH 

3X1 

•rH 


E 


00 


•rH 


•rH 


E 


O' 

CO 


•rH 

ca 

•rH 


E 


ca 

ro 

•rH 

•rH 


g 


03 

•rH 

ca 

•rH 


ca 

II 




r-~ 

(N 

ta 

« 

r- 

ii 




00 

X 

* 

X 

ll 




O' 

ca 

ca 

•It 

CN 

II 




ca 

ca 

* 

II 




03 

* 


|| 


ca 

03 

—• 




r-~ 

ca 

ca 

03 

ca 





00 

X 

03 

X 





O' 

ca 

ca 

03 

rH 





ca 

ca 

03 





03 

03 

ca 



ca 

•r4 

u 

u 




rH 

ca 

03 

ro 

X 




00 

•rH 

03 

•rH 

X 




O' 

ca 

ca 

03 

ca 

U 




ca 

ca 

03 

O 




03 

03 

ca 

03 


4* 

1 

II 

u 


344 

t" 

+ 

+ 

•rH 

+ 

X 

o 


44 

00 

1 

•rH 

| 

X 

O 


44 

O' 

+ 

+ 

•rH 

+ 

O 

03 


44 

ca 

+ 

•rH 

o 

03 


44 

03 

•rH 

+ 

03 

03 

ll 

•rH 

o 


•rH 

m 

II 

ll 

II 

ll 

•rH 

u 


•rH 

• 

II 

II 

ll 

•rH 

o 


•rH 

- 

ll 

ll 

II 

ll 

•rH 

03 


•rH 

_ 

II 

n 

•rH 

03 


•rH 


|| 

ll 

•rH 

03 

03 

o 

II 



X 

01 

03 

X 

U 

X 

it 



X 


X 

o 

X 

II 



X 


03 

-O 

03 

o 

ii 



X 


03 

X 

ll 


TJ 


03 

o 

|| 

03 

o 

u 

344 


c 

03 

X 

o 

X 

u 

344 


c 

in 

X 

o 

X 

O 

344 


c 

to 

10 

X) 

03 

o 

03 

344 


c 

in 

CT3 

X 

03 

344 


c 

in 

03 

o 

03 

44 

•rH 

•rH 

u 

•rH 


01 

E 

•rH 

•rH 

•rH 

•rH 

u 

•rH 


01 

E 

•rH 

•rH 

•rH 

O 

•rH 


01 

E 

•rH 

•rH 

•rH 

•rH 

03 

•rH 


01 

E 

•rH 

•rH 

03 

•rH 


<D 

E 

•rH 

•rH 

03 

•rH 


oo 


<L> 

oo 

C3 

q. 



c 



- 




- 

— 


o 



X 




X 

m 


C /5 



1 




1 

ca 


r“ 



• 




X 

X 

<0 

*ob 



II 

X 




II 

X 

C 44 




0 




0 

o 


X 



X 




X 

X 


0 ) 



3 


• 


3 

c 

(A 

a> 

- 4—1 

« 


01 


rH 


01 

41 

T3 

0) 

0 ) 

u 

X X 

• 


rH 

rH 03 

X 

~ 


H 

3 

C 

• r* 

£ 

H 

O' x X 

(3 'rH .rH 

0 ) 

g 


rH 03 

rH *rH 

ca X 
ca -h 

SU1 

SU1 

C 

c 

ca 1 II 



rH | 

ca ll 



o 

0 ) 

Q (IJ -• 



rH 03 

ca — 



Mmm 

O 

rH 03 U 



rH 03 

ca 03 



CD 

DO 

c 

+ -rH (J 

X 

44 

rH *rH 

+ 03 

X 

44 

■o 

c 

• rN 
■4H 

■■■ 

M 

II II 

03 X II 

X 

•rH 

X 

- n ii 

03 X II 

X 

•rH 

X 

■ Hi 

CA 

• rN 

03 X X <44 

c 

01 03 X X 4-1 

c 

0. 

-J 

3 

•rH -rH X 

•rH 

41 

E -• 

•rH X 

•H 

4 ) 


c 

•H g 
03 O 

e x 

no 4-i 

C O 
41 XI 


* 


(/> . 

£ i 

•E » 

2 5 

Q. 3 


•S' 

ca 

4-1 


c 

> -I 
03 O' 

•rH 0) 

- XI 




VO 


O 

- 





VO 

caoo 


03 

01 





(Ti 

ca ca 


— 





ca 

ca n 


C 

E 


X 



KT 

vo u 


•rH 



X 



ca 

m <u 

03 03 X X 

U U X X 03 


m 

II 



II 

II 4-> 

03 03 X X 

O U X X g 


ta 

—• 



E 

E <n 

•rH *rH 

•rH *rH C 


ca os 

03 

o 


0) 

d) *rH 

41 41 

(U <11 -rH 


+ 03 

03 

o 

a g 

P rpX XXX 

4J X X X O' 


II II 

II 


o 

o 

•rH d) 

>. C >. C 

>H C C >1 41 


03 X 

u 44 

X 

rH XI ^ X) S3 '»H X) "H *»H X) JD 


03 X 

o 

•H 


22 

480 


Dr. Dobb’s Journal, Number 73, November 1982 




a 

ft. 


S3 


El 

rH SI 


in 

e 


o 

U 0 
W 

XI rH 
•rH d> 


T3 

c 

d> 


0) 

e 


o 

X 

C 

d) 


in 

e 


f—i 

43 


c 

SI 

1 O 


•rH g 

S3 

HUT) 

44 

(0 o 

+ 

<D — x 

•rH 

E X 

II 

II II 

X 

X X 

XI 

U X UH 

C 

C O 

43 

O T) -rH 

<u 

0) 43 


10 

ft 


(A 

* 


« 

> 


>- 0> 

0) c 

■O 

n W 

0. J 


<D 

CP 

Si 

S* 


SI 

II 


e 


0) 

a g 
o o 






in 

in 





SI 

rH 





X 

•rH 






(0 





— c 

UH 





>-n 

o 





id cr 

X 



r—u 

--- 

• rH O 

o 



Cl 

Cl 

-XI 

CP 


VO 

^ Cl 

^ si 

u - 

• 

d 

00 

Cl CO 

d CO 

10 


d 

Cl 

d Cl 

Cl d 

^ w 

in 

o 

II 

rH si 

f—i s> 

C E 

E 

VO 

Wh 

— — 

—r — 

•rH 



nomijmxiU'oui/iiU'u'DDw id si s 

iixtoxiDXOxutnd>UHXd>uHg rH ts m 

gw "H -rH — .rH H H C IN 

d)-H(i)<D <ua) a) ai q) -h o o 

g CP X XXXXXXXXXXXX01 *J O 4J 

• rHQ)>,>,CC>H>.C>i>H>lCCC<l) O OO 

X X X X — X X —< X X X ^ X CP H ^ 


R 

R 

O 

^3 

3 

.R 

R 

O 

o 


R 


X 








• 





X 






X 








+ 






i 


•K 

X 

II 








/* 





\ 

• 






\ 

X 








\ 

+ 






\ 

+ 


II 

X 








II 

X 





it 

X 






ii 

X 








> 

•rH 






> 

•rH 


rH 








• 

> 





• 

> 






• 

> 








XI 

X 






X) 

X 


J 

E 


-O 






•rH 

X 


O 



•rH 

X 


X 




•rH 

XI 


HI 






c 

•rH 


4-1 




c 

•rH 




X) 






- 


o 



m 


X 




_ 


ai 








4H 








XI 


X 


o 




U X 

X 




X U 


o 




ai 


X 


o 




4-1 

X) 

o 




C/5 


X) 

co 

m 43 

*H 

o 


in 


O X 

f*i X 


in 


X O 

rH 

o 


in 


<u 

vo 

ID X 

r—i 

o 


tn 


4-1 

X) 

o 


(/) 


g 


X) 

d 

tSl 'rH 

d 

•rH 


E 


O -rH 

ta -n 


E 


X -rH 

d 

•rH 


E 


<d 

m 

rH ‘H 


•rH 


g 


4-1 

•rH 

•rH 






£) 

d 

d \ d 

II 




o \ r- II 




X \ Sl 

it 




d> 

CM 

El \ ID 

ii 




4-1 

X5 \ 13 

|| 


u— 




X) 

d 

d 03 

d 





U ID 

m — 




X O 

S3 

—• 




d> 

d 

SI ID 

si 





4-1 

X) 03 T) 



1 




XI 

CO 

d 03 

r—i 

ID 




O ID 

Si o 




X O 

SI 

ID 




tu 

rH 

El ID 

si 

X 




4-1 

•rH fQ *rH 

T3 


/ 



U—1 

-Q 

+ 

+ ,rH 

+ 

<0 

03 


4-1 

O -rH 

+ o 

03 


4-1 

X -n 

+ 

ID 

ID 


UH 

hj 

+ 

+ 

+ 

X) 

o 


4-1 

4-1 

1 *-* 1 

T3 

u 


44 


•rH 

• 

II 

II II 

II 

•rH 

ID 


•rH 

- II 

II "rH 

03 


•rH 

- II 

II 

•H 

ID 


•rH 

« 

II 

II II 

II 

•rH 

o 


•rH 

m 

II II II 

•rH 

u 


•rH 


13 


03 Xi 03 

o 

II 



T3 

X 

O II 



TO 

U 

ID 

II 



X) 


03 

X O 

X! 

it 



X) 


X3 O T3 

|| 



13 


C 

l/) 

03 X) 03 

u 

H3 

UH 


C 

in x 

O ID 

4-1 


c 

in o 

ID 

ID 

UH 


c 

in 

03 

X O 

XI 

O 4H 


c 

U) 

X) U TJ 

o 

44 


c 


<1) 

G 

•rH 

•rH *rH 

•rH 

H3 

•rH 


03 

E -rH 

•rH ftj 

•rH 


a) 

E 

•rH 

ID 

•rH 


0) 

E 

•rH 

•rH *rH 

•rH 

o 

•rH 


dJ 

G 

•rH *rH »rH 

o 

•rH 


0) 


<N 

<N 

<X) 

& 

R. 

R 

O 


3 

R 

R 

Cj 


c 






in 













c 






d 





d 



03 






c 







X 






•rH 






V 





V 



l-l 






03 



















1 





1 



4J 













o 






o 






• 





• 









44 







4J 






X 






II 





—• 



dJ 

























V 





V 



4J 






44 







44 






X 






44 





44 



N 


• 




c 


• 





c 


• 










c 





c 



X5 


rH 




•rH 


nj 





•rH 


CO 




X 






•rH 


m 



•rH 


VO 

• 


rH 




• 


CM 





• 


CO 




• 






• 


in 





VO 



rH 


X 




CM 







CO 


o 





X ID 





in 03 





VO 

10 


r—i 

m 

X 


(A 


CM 

in 




in 


CO 

d 

o 


in 



is in x id 



tn 


m 03 



in 


VO 

G 


r—i 


•rH 


E 


CM 

CO 


X 


E 


CO 

d 

•rH 


E 



O d *H *rH 



g 


in *rH 



g 


VO 



r—i 

CO 

II 




CM 

CM 


X 




CO 

*—i 

ii 





Sl S3 1 II 





in -• 





VO 



r—i 

IN ID 





CM 

d 

m 

II 




CO 

d 

d 




vr 

d d 03 V 





in v 





VO 



*—i 

rH 03 

ID 




CM 

Sl o 

CO 





CO 03 

d 

51 ID X 




^3* 

d d 03 X) 





m X3 





VO 


44 

r—i 

4* ,rH 

ID 

o 


44 

CM 

+ o 

CM 

ID 

O 


44 

ro ID 

+ 

r—i 03 X3 

O 


44 


+ + —1 X 

u 



44 

m x 

u 



44 

VO 


•rH 

• 

II II 

•rH 

u 


•rH 

• 

II —1 

+ 

ID 

O 


•rH 

- II 

II 

+ II —1 

O 


•rH 

• 

II II II —I 

o 

id 


•rH 

» ’r—i 

u 

Q) 





13 


ID X 

II 



X3 


O II 

ii 

II 



X3 

X 

o 

II X II 



X 


ID X X II 


in 


13 

|| 


(A 


T3 



C 

(A 

ID X 

U 

44 


c 

(A 

O X 

ID 

O 

44 


c 

in x 

o 

ID X O U^ 


c 

in 

ID X X V 

44 



c 

in u 

44 



c 

CA 

___ 

(1) 

G 

•rH »rH 

O 

•rH 


d) 

E 

—1 X 

ID 

U 

•rH 


<u 

E 

•rH 

ID -h O 

•rH 


d> 

E 

•rH -rH -rH (J 

•rH 

d> 


<D 

E o 

•rH 

dl 


n> 

E 


<N 

R 


<N 

<N 

&> 

CiO 

R 

Rh 

R 

O 


3 

.R 

R 

£ 


Dr. Dobb’s Journal, Number 73, November 1982 


23 

481 


in 

in *3* 
in XI 
in 

in c 
m o 
m <r *—i 

in is a) (o 
m si i/i 

“ + O QI 

II o U) 
i/i x; m 
ED O U 


p vo 

VO 

VO XI 

1 vo 

: ai vo c 

in vo o 

4-> o vo co r—i 

•—i o vo is) ai to 

3 X VO IS) w 

•DO- +0(1) 
*44 XJ II o UI 
HI C ID ij £ nj 

D HI E D U U 


O 1^- oo 

r- cd 

n oo 

w i" oo 

E ai c- oo 

w r- oo 

o r- <—i cm oo is) in 

or-K>r-itscMoocs)ts) 

•C F' <3 <3 00 IS) IS) 

o-o o - + + 

X) 44 O 4-1 O II II 

cwoooot/).—ICM 
•u E tr> <—i ov i—i £ to .Q 


■-I N 
m in m 
» ca 
X G) II 

to <s -• 

•-< G> X 
^ + TO l 

■* II -rH 

U N || 

(0 <0 CO l 

a,~< o • 


X 

■ m n vr 

O XI C0 
'-'II II u. 

^ •• “• 4 

cj <h cm m m 

m m £ o o 

CL, II II || 

c in co in iw 

3 HI O II *h 


VO Q 

vo is 

VO IS) 

VO G) G) G) 

VO CO G) G) l 

vo in h is + a> 

“ + + II r-l 

U II II (D *r4 

in o d u ai x 

E <H xi o -H s 


o 

o + 

' + + 
TO 0! + 

to oi o 

•'-> -r4 U 


G> 

G) 

ai g> 

H IS S 
••■4 G> t 

x G> + ai 

s + II r-i 
X) II QI -r4 
C U ll£ 
HI U'H 3 


^ 0) 
o ai 
o -4 
^ ii 

to 

10 XJ 
•'"I XI <4-1 

11 —4 <4-1 

XI II 

XJ <44 >4-1 


»W + 

-• + + 
XJ 01 + 

c ai o 

II'H U 


f" 

r~ 

r- 
r- 
ai r~- 
r-H r- 
•h c> vj, 

x m 

5 - 

xi o 
C IQ O 

ID £ r-l 


C E 
QI ro O 
- E 4J 
XJ 4-1 

in c o 

E ai xi 


c „ 

« 0) 

5>.s 
2 « 
CL j 


vo 

VO G) 00 
CT, G) G) 
G) G) II 
V VO U 

gi co ai 

II II 4-1 

E E w 
ai at -h 
D r E E CP 
O O ,r4 ai 
4-1 H x >4 


c 


to 

IOl fJ 


cn 



•0 

X 


X) 

m a> 


c 

0) _r 


(0 

© ■§ 

0) 

- 

p- c 

> 

in 

Ft 


C e 

o 

'Si u 

0) sp 

Us 

■— .<s 

a d 


<-* O r-* U 

■H o xj u 

G> r-4 I—I CS II XJ II 
H CM Gl H S IS — -— 

■H COHSQDI01IIW 
O - + + XJ TO QI <44 

UD U II II — || || 

OOOI/1UX)IO<DU-|<44 
H IJlH £ U D 10 HI <44*1 




<T> 



QI 



• 



01 



4-1 



G) II 

* 



- 


G) — 

CN 


XI 

co 


G) XJ 

<N 


- 

CO 

1 

+ XJ 

CN 



CO 

1 

II II 

CN 


in 

CO 

XJ 

QI >44 

CN 

0 — 0 

E 

co 

XJ 

QI <44 

CN 

U XJ o 


CO 



CN CJ\ 

II XJ II 


CO 

G) 


CN CT\ 

,—. ■—- —• 


CO 

G) 


CM 13 XJ (0 (D <44 

<44 

co 

G> QI 


- + 

XJ (0 Q) <44 

•H 

• 

+ ,H 


II 

— II II 

XJ 


II •*—< 


in xj 

(0 QI 144 144 

c 

in 

in x 


E XJ 

10 QI >44 -iH 

QI 

E 

in s 



cn -—. tn 
in xj in 
II v ii 

X) 10 (D 

xj <o ai 
ii ii 
(o ai <44 
<o ai < 4-4 


24 

482 


Dr. Dobb’s Journal, Number 73, November 1982 







- 

c 

m 

- 

(0 

u 

• 

If) 

CM 

3 

• 

H 

to 

X 

• 

If) 

CM 

tt) 

c 

H 

10 

u 

u 

W 

CM 


D 

1 — i 

CO i-H 


4J 

l/> El 


C (0 .X 

•H (\J O) S 

m is in is h 
E - + m 
XJ X II 
c 3 to i x 

(U 0) E HJ .H 


I) H H H is il 
in 3 a ill s 3 
■x - to - + in 
X3 XJ X II XJ 

c to c 3 to «*r c 


a)Ea)(/)E’ua>X) 


VD 

ro >X) oo 
VO (Ti IS1 

co ts ii 
vo vr n 
ro is 0 ) 

II II 4-1 

E E <0 

<U <o -t-i 

CL E E CP 
O -H O <0 
*J£H n 


SH(NMHJi)O'O0)nOlD 

OOOUrtJXOXJ<l>XX<tJ 

•H *H 

OHMIOltHlOHHJii 

XXXXXXXXXXXX 

-QXXXXXXXXX-x.x 


h n n vj in x >iN ra 

<Dj3U'oa)<o(oroE 

•X *X ..H C 

a> a> a> a> <u -h 

xxxxxxxx cn 
>,>.>,>, c cc a> 

X) ^ X X *H ’ H >rl O 


u 

H 


CM 

CP 

CO 




H 

X XJ 

• 

rH 


CM 

* 

CO 



xr 

• 


to 

*H 


CM 


ro 



XJ 



r—\ 


CM 

to 

co 



If) 

(0 (0 

E 

rH 


<N 

E 

co 



c 

B 

E E 


*H 

•—i 

CM 


co 

CM 


0 




rH • —\ 

El 

CM 


co 

El 

M* H CM CO 

»—1 •—1 (N 

CO 

X 


cs m h m 

- + + + - id o 

11 + + + 11 11 

H rl H H (N n 

<0 <0 <0 ro X o -x 


X K) CM 
1*4 H S x CM *3* 
•X - + 3 *■ X) 

X) II (0 

C t/1 X O 10 L-l 

oj e xj cp £ -x 


ro X Q B S s a) (OX 
H4/nXXQBBlS to 
•x - CJ - + + + +OQ)Q> 

XJ 10 II II II II O 10 10 

ClOOI/lHPInx£lDlD 

DED'EUXU’DUUO 


x> — 

XJ O XJ 

II O XJ 

*—* ’*"4 II 

u ^ — 

U X 0) v*4 

+ -x X 0) »*4 

+ II II 
xj x a) vm »*4 

XJ X 0) »*4 -x 


X 

X 

+ -X + 

+ II + 

a> i*4 o 

0) 4-1 u 


m 

ta 

<D 44 

x + + a> 

44 

X m m 


+ 

Q) 44 

•x || || x 

44 

3 - 

u 

11 

II 

XJ XJ CJ -x 


X) 0 

0 

<u 

44 44 

C XJ CJ X 

c 

C to 0 

fX 

0) 

4-1 -H 

a) -x *x s 

0 

<1) EX 


+ + Q) 
II II -x 
a) o -x 

tu o x 

•X -X 5 


Dr. Dobb’s Journal, Number 73, November 1982 


25 

483 





a 

o 


TJ 

C 

a> 


<u 

QJ 

<u 

d) IS 

qj in 
aj cn 
ai o 
qj ts - 
Qi + x 
- ii - 

O II 
W .Q X 
E •’-* x 


o 

XI 


X 

QJ 


X 

O 

X S3 
O 
CN || 

X — 

X QJ 
C QJ QJ 
QJ II 
a. qj u-i 
O QJ'd 


c 

a 

o 

QJ 

X 

X 

C 

QJ 

O 


W 

E 


CP x 

C ,rH 
UH 

•rH 

X 'O 

4J 0) 

W 

x o 
o t 1 


QJ 

c 

QJ 

a 

o 

o 

x 


a 

o 

X 

W 


U-I 


X 


TJ 

C 

QJ 


m 

es 

si 

+ 

II 

XI 

XI 


fNI 


E 

o 

x 

U-I u 

o 

XI II 
X — 

X QJ 
TJ X qj 
QJ II 
0) QJ X 
Id QJ -rd 


TJ E 
QJ O 
X X 
QJ U-I 
X 

4-> W 

c x 

QJ OJ 
U U-I 


to >o 
E 


X 4-1 


S) 

o 

x xi 

O X 

0 > *H 


-1 

a 

3 

a 

V 

QJ 



<N 
• mh 

c 

X 

X QJ 


+ 

cn 

•X 

3 

•X ‘X 

+ 

+ 

O' E 

OJ 

O 

TJ II 

+ 

QJ 

o> O 


C QJ 

CJ 

QJ 

O' u 

-C 

X 

m 

the 

QJ QJ 

o 

•H 

O' ^ 
0) O' 
rH O' 


X QJ 
U rH 
II -H 
U X 
O 3 


QJ 

QJ 

c 

o 


X . 

3 - 

TJ 

C 

QJ 


O 

CP QJ I 
CP SI 
tj a 

QJ II 
IQ Q) CJ 


o 

o 

II 


E x 


o u 

ii a 

— — (V 
QJ u X X 
QJ QJ X X 
II II II 
Q U X U-i 
Q O X -rH 


U) 


O 

QJ 


l/J 

E 


X 

X 

o 

X 

OJ 

> 

QJ 

X 


in 

3 

E 


O 

OJ 

c 

o 


II 

X 

OJ 

TJ 

c 

QJ 


X 

QJ 

X 

o 



• 

CN 

o 

3 

X - 

XI 

C 

CP 

•H 

QJ 

c C 


a 

QJ -X 

X 

o 

a x 

QJ 

X 

O X 


c 

X 

X 

QJ 

x 3 

X 

CJ 

c 


- 

QJ X 

X 


CJ o 

o 

in 

• X 

X X 

E 

■» 


QJ 
CN || 

X — 

Si QJ 
C O QJ 
QJ II 
a, qj u-i 

O QJ *rd 


IN 

a 

o 

x 

w 


CM 


00 

oo 

CO 

00 

00 

00 

00 

00 


E 
o 

X 

X CN 

o 

o II 

u 

x oo si x qj 

•rd - O TJ OJ QJ 

TJ II QJ II 

C t/1 X QJ qj x 

QJ E QJ x qj th 


QJ 

■ X 

• -rd 

» 3 

£ c 
o o 

'P TJ 

x (tj 
- QJ 
X 

in _ 
E 


IN 

II 

X 

QJ 


OJ 

in 

TJ 

H 

3 

o 

X 

in 

TJ 

QJ 

c 

0) 

a 

o 


QJ 

X 


x (D 

QJ u, 

3 

f w 

QJ 

in xj 


c 

0) 


QJ •'H 

X X 

x 3 


QJ 


X 

> 


CP 

c 


TJ 
QJ 
X x 
QJ QJ 
X X 


<P 

CP 

CP 

CP 

CP 

CP 

CP 

CP 

X OJ H Q 
•x - O t) 
TJ II || 

c in o x 


o 

c 


S3 

o o 

o II 


■ o 

tn in QJ 
in «. ■» 


QJ E 


QJ X QJ 
X 0) QJ 
■x || 

X QJ U-I 
O QJ 5 QJ .rd 


S3 
SI 
SI 
SI 
SI 
S3 
S3 
S3 

X S3 U QJ 
•X - U QJ 
TJ II 
c in qj x 
QJ E QJ -x 


o 

II 


rH QJ QJ 
rH 

QJ X 
X 4 J QJ 

3 .-d ‘X 

- X x 

5 03 
in . > 
E • v 


QJ 
QJ 
QJ 
QJ 
QJ 
QJ 
QJ 
QJ 

X QJ IN CN 
•x - U O 
TJ II II 
C w X CJ 
QJ E QJ CJ 


<N 

X 

O 

X 

c 

•x 

S3 
CJ CJ 
O II 


X 

QJ 

in 

x x 

QJ c “ 
X t-j O 
OJ -x X 

W TJ HI 

X N 
0) 

Xu o 

3 .x X 
“ X 

3 x 
in - qj 


QJ 


X QJ 
QJ QJ 
II 

QJ X 
(0 *H 


00 


a> 

W) 

eg 

a 

c 

o 

V5 

E 


<L» 

?>; 

^ s 

E e 

CD m 
TJ 5 

■■ c/3 

D.d 


S3 


r- C 


> 

QJ 


CP 


TJ 

in 

o 

rH 

CJ 

in 


x 

o 

X 

X 

OJ 

c 

X 

3 

X 

QJ 


QJ 

x, ° 

CP 4J 

c 


0 

> 

0 

(A 

0) 

e 


— r- .X 

QJ 






w *H 

TJ 

m 


IS IS *■ 

XI 






o £ 

QJ 

rH 


S3 S3 CJ 

. 






o 

C 

rH 


ro co qj 







"" 1 — 1 

r i 

OJ 

rH 


S3 S3 

in 






in 

a 

rH 


S3 S3 C 

E 





X 

E 

0 

rH 


r NX 1 *H 





CN 

OJ 


• V 

rH 


rH CN rd QJ 


IS X 

CN 

CO 

X 

II 



rH 


X X C e 


S3 S3 

S3 






rH 


c 


ISIS 

S3 


0) 

IN 

QJ 


^ rH 

X 

QJ Q) QJ -X 


+ + 

+ 

+ 

in 

O 

QJ 


•rH • 

_ 

x x x cn 


II II 

II 

II 

o 

II 



TS 

II 

>d >d >t QJ 


53 rd 

CN 

CO rH 

QJ X 


C W 

X 

XI X) XI & 


OO 

O 

O 

o 

QJ 

•rH 


QJ E X 


o 


X 

QJ 

X 

X 

X 

S3 o 
in x 

•—i 

IS rH 

S3 X 

+ 


c 

QJ 

a 

o 

X 

c 

QJ 


in 

c 

X 

3 

X 

QJ 

X 

C 

QJ 

a 

o 

0) 

in 

3 


O 

XI 


X 

QJ 


u 

.a 


QJ 




o 

O 

QJ M 

X 




•U 





- 

0) 

a in 











JD 

X O IN 

X 




u 





in 


QJ 4-J CN 

0 



CN 

o 



Vh 


E 


in cn 

X 

X 


S3 

4H 

X 


d) 




v CN 


QJ 


S3 


OJ JQ 


II 




CN 

X 

II 


S3 

rH 

II X) 


•• 




CN 

X 

—• 

• 

S3 

**H 

— (V. 


G5 

QJ 



X IN 


CN 


+ 


CN QJ 

<0 

O 

QJ 



•rH ■ 

c 

O 

- 

II 

c 

O QJ 

<0 

II 




TJ 

QJ 

II 

II 

o 

<D 

II II 


QJ X 



c in 

a qj 

X XI 

a xi qj 

4H 


••H 



0) £ 

o 

QJ 

X 

•rH 

O XI QJ 

•rH 


TJ 

c 

QJ 

a 

o 

c 

OJ 

a 

o 


in 

E 


TJ 

OJ 

C 

QJ 

a 

o 

c 

QJ 

CP 

C 

•H 

c 

OJ 

a 

o 


26 

484 


Dr. Dobb’s Journal, Number 73, November 1982 



:file to return error' endif endif 

stop 2 ms 'bbbbbbbbb' ms 'hhhhhhhhh' 


>. 04 
4-1 c 


E4 

N" 

U 

O 


(1) 

w 

ID 
d) 

i—i oi 

a a 




»H c 






XI 




u 


r-*K 











rH 


XI 




■H 


XI 











XI c 


II 




— t 


XI 

ID 









XI 

XI II 






V 


•rH 

ID 









X) 

—• 


o 




XI 


'-' 





_ 






ai xi 


o 

+ 



XI 


»H 

ai 

+ 



r- 




73 

4-4 XI 


•rH 

+ 



•-4 


4H 

4J 

+ 



c 

2 




ID 

•rH || 


—" 

o 



II 


II 

•H 

XI 



4 

J 



Q 

ai 

4-1 ID 


*H 

V 


ts 

ID 


03 

u 

XI 







is 

4-1 

3 ID 


4-1 

•H 


cs 

ID 


03 

3 

•rH 



U~i 



IS 






d) 

SI 






0) 

r-H 

i 

3 



ca 






rH 

SI 






rH 

C 7 

3 

C 


Q 






•rH 

SI 






•rH 


i 

— 

•rH 

£ 

+ d) 



ID 



sz 

+ ai 


ID 




£Z 

d> 

HI 

ID 

o 

II rH 



ID 



3 

il .-i 


ID 




3 

4J 

• 


e 

4-4 

u *h 






73 

XI —i 






73 

•rH 



73 

4-1 

o x: 



C 



c 

XI sz 


C 




C 

u 

in 

C 

o 

•r-» ^ 



o 



HI 

•h 3 


o 




ai 

3 

f 


ai 

XI 


*H IS 


>4-1 <H 

e o 

o -u 



lj 


o 





c 


<4-1 

rH 

cn 

SI 




03 



o 


o 






U 

ii 


II 




T3 


o 

n 


—• 



- 

C 



u XI 

144 

ID 



73 

•rH 


73 

ai xi 

•rH 

+ ID 



<D 

U-l 


ID 

n 

73 

+ II 



0) 



ai 

XI U-l 

C 

ID XI 



4-1 

4~> 


4-1 

XI -4 

HI 

ID 23 



444 

c 







01 

O 

TJ 







1 —1 

01 

•rH 







•*H 

o 

T3 

<s ai 





23 SZ 

c 


U r—1 





23 

3 

- 

d> 

II —1 






73 



ID SZ 





C 

C 

in 


ID 3 





o 

01 

E 



CT> 

c 


VO 

73 





in 

ID 





CN 

01 






u 





c 






•rH 

444 






O 


o 



0) 



u 



rH 

in 


O 



•rH 

4-1 


u 

CN 


UH 

ai 


O 

> — i 



44 


o 

m 


U-l 

O 


O 

IS 


O 

ID 

IS 

U rH 

is 



44 

H 

o o 

+ 

IN 04 

TJ 

ID 


- II 

II 

O .-1 

C 

23 

o 

id 23 

II -H 

a) 

U 

o 

in ID 23 

U 23 

• v 

• »•» 

rH 

E 'r"4 

•rH 

U 3 






H 








O 








H 








in 








d) 





CN 



4J 





U-l 



•rH 

CS) 







u 

<N 




O 



:* 





-U 



• 

o 




c 




4J 


23 


•rH 



in 

O 


23 



IS) 


e 

U> 


•rH 


u 

o 





— • 


u 

II 





V 



—• 





ID 


0) 

u 

03 



U-l 

ID 

+ 

4-4 

d) 

03 



•rH 

•rH 

+ 

•rH 

II 




73 

II 

o 

u 

03 

U-l 



C 

ID 

O 

3 

03 

•rH 



04 

ID 


c 

0) 

SZ 

3 


<N 

14-1 


a) 

in 

o 



+ 



73 


+ 



73 


ID 



73 


ID 



73 


•rH 



73 



d) 


73 



iH 


73 



•rH 

IS 

73 

ID 


23 

CN 

73 

ID 


3 


• 



73 

O 


C 


C 

O 

in 

O 


0) 

rH 

E 


o 

4-4 

c 

m 

o 


in 

s e 

IN O 
444 II 

0) 4-1 ID 

in ai id 
O II 

i—I ID 14-1 

O ID •ft 


V-i 

o a> 
u in 
w o 
a> i-4 
u 
c 

ID O 
4-1 
4J 

04 cn 

CD C 

•H 

ID >i 
5 4-1 


u 

ai 

4-> 

o 


73 

C 

0) 









In 






4J 


















73 

- 












03 






d> 


















ID 

lH 












x: 

o 






in 

















to 

04 

k4 

03 

-C 











• 






— 

4J 







• 









— 



U 











in 

03 





44 

t 







• 









44 

u 

4-4 












rH 






04 

c 

- 






73 









04 

<D 

D 

4J 











•rH 

c 






in 

o 






44 









4-4 


23 

u 











ID 

u 





4-4 

<d 

44 















04 

4J 


d) 











<44 

3 





ai 

o 

0) 






C 









in 

d) 

O 

u 











73 

•U 





in 

T3 

N 



»—i 



o 









c 

in 

44 

u 









»—I 


ID 

d) 










>44 







rH 





D 


04 

o 





“ 




444 


0) 

u 


• 



73 

T) 

o 


- 




44 


- 


U-l 





73 

T3 

N 

u 


• 



ro 






4-1 






44 

03 

4-1 


m 

o 



3 


VO 







44 

03 







ro 




E 


- 

o 





- 

d) 



in 

4-4 



- 


VO 


E 





- 

d) 

C 

<d 





ro 




O 



4J 






u 

Wi 


m 

c 





VO 


o 






u 

O 

x: 


r- 



ro 




u 


in 

• 





in 


01 


m 

H 



in 


VO 


i4 





in 


c 



r- 


is 

ro 




444 ID 


E 




44 


E 




in 


44 


E 


VO 


444 

o 

IS 



E 


• s 

• v 




in 

ro 




ID 






0) 






m 

u 

Q> 




VO 



o 

O 23 









CN 

ro 


B 


U II 






II 






in 

a 

II 




VO 


o 

|i 

II 

23 







r- 


is 

ro 

• 

S4 


O — 












in 


—• 




vo 


'J 

- it 

«—• 

i« 








m. 

is 

ro 

•—i 

El 

rH 

O 23 



4-1 


SI 

ID 




444 in 

04 

CM 

03 


U-l VO 

SI 


CM ID 

44 

ID 

03 





>44 


3 

+ 

- 

• 

+ 

o 

73 O 23 



•rH 

• 

o 

ID 




•rH 

- 

4-4 

O 

03 


•rH 

- 

o 

73 

- ID 

a> 

ID 

03 





•H 

• 

- 

II 


II 

II 

ii 

ID II 




73 


II 





73 


•rH 

II 



73 


II 

ID 

II II 

ii 

II 






73 


II 

u 

in 

03 

O 

n 

04 23 

U-l 



C 

in 

ID 

>44 




C 

in 

U 

ID 

U-l 


C 

in 

44 

04 

ID 23 

ID 

ID 

UH 





C 

in 

44 23 

E 

03 

o 

01 

4-. 23 

•rH 



01 

B 

(D 

•rH 




0J 

E 

3 

ID 

•rH 


04 

E 

0) 

44 

ID 23 

ID 

ID 

•H 





04 

B 

42 

•rH 


Dr. Dobb’s Journal, Number 73, November 1982 


27 

485 


(Continued on page 24, column 2) \ (Continued on pge 24, column 3) I End Listing 


A Novice Builds 
the Sinclair ZX81 


S inclair offers its ZX81 computer in 
kit form for those into electronic 
kit building or saving money. I fall 
into the latter category — the idea of sav¬ 
ing (at that time) $50 on a microcomput¬ 
er appealed to me. The drawback was 
that I had no experience in computers or 
electronics. I had never soldered anything 
in my life, and I couldn’t tell a resistor 
from a capacitor. 

So what? How does all this relate to 
the reader? Why would a computer pro¬ 
fessional or a dedicated amateur be inter¬ 
ested in the struggles of an electronic 
novice? Suppose your teenager wants 
your advice on the acquisition of an af¬ 
fordable computer. Your next door 
neighbor has been hinting that he might 
like to “fool around” with a computer. 
You are a wizard programmer and opera¬ 
tor, but would like a chance to see what 
the insides of a microcomputer are 
like. If so, the ZX81 kit is of interest to 
you; take comfort in the fact that your 
son or neighbor will be able to do what a 
beginner like me has done. 

Without further ado, I will describe 
my adventures building a computer from 
a kit. 

Preliminaries 

While waiting for UPS to deliver my 
kit, I ventured out to Radio Shack and 
bought a soldering iron. The salesman was 
very helpful and even maintained his 
composure when I told him I was build¬ 
ing a computer and needed a soldering 
iron. After answering a few of his ques¬ 
tions, he sold me a 30-watt iron, some 
.032 diameter rosin-core solder, desolder¬ 
ing braid, and a super-deluxe soldering 
iron holder. Thanks to his foresight and 
sales ability, I avoided at least three more 
trips to Radio Shack when I discovered 
that I really needed those things. Unfor¬ 
tunately, I still don’t know what the dia¬ 
meter is .032 of... but it worked. 

On to the kit! Although I am not an 
experienced electronic kit builder, I knew 
enough to thoroughly read the instruc¬ 
tions before I did anything else. What a 
shock! Apparently, the instructions that 
come with electronics kits are different 
from the kind you get with model air¬ 
planes and children’s bicycles. I expected 
step-by-step, fully-illustrated, foolproof 

by John Connell, Jr. 

John C. Connell, Jr., 144 Lexington 
Street, Middletown, RI 02840. 


instructions to lead me by the hand 
through the assembly process. 

In reality, Sinclair’s “ZX81 Assembly 
Instructions” contain only ten steps. 
Only four of the steps deal with the in¬ 
stallation of components onto the circuit 
board. There are critical pieces of infor¬ 
mation hidden throughout the sections 
entitled Precautions , Component Identifi¬ 
cation, and Circuit Board Assembly. The 
instructions are obviously written by an 
Englishman and it took me a while to de¬ 
termine that a “Pozidrive screwdriver 
with a No. 1 point” meant a small Phillips 
head screwdriver. One line in the fault¬ 
finding section bears quoting. “If you 
find a bad joint or short, shame on you! 
You should have checked more closely 
the first time.” With advice like that, how 
can you go wrong? 

Once I got past the shock of not be¬ 
ing spoonfed, I found the instructions to 
be complete and understandable. If clari¬ 
fication was required, Sinclair usually 
provided an illustration. The instructions 
included a drawing of the physical loca¬ 
tion of components on the circuit board 
and a circuit diagram. I recommend that 
Sinclair include a drawing of the printed 
wiring on the circuit board. This would 
allow verification of component place¬ 
ment and depict the relationship among 
parts. No doubt, the circuit diagram pro¬ 
vides the same information, but it seems 
to be arranged according to function 
rather than physical location. At times, it 
is hard for the inexperienced kit builder 
to follow. 

Having read the instructions, I pulled 
out the various parts and began the iden¬ 
tification process. Not knowing exactly 
how to proceed, I pulled out a piece of 
paper and copied the parts list from 
the section entitled Component List and 
matched parts to the list. After the first 
time through the list, I found that I had 
more parts than called for in the instruc¬ 
tions. Fortunately, I discovered the ad¬ 
dendum page to the instructions which 
apply to the U.S. version of the kit. 
Armed with this additional information, I 
was able to account for the use of all but 
three parts. I was a little worried, but 
didn’t let it slow me down. One minor 
point . . . resistor R-30 was missing from 
my kit and I had to make another quick 
trip to Radio Shack. 

Construction 

Confident that I had the proper 
equipment and all the necessary parts, 


I cautiously approached my first solder¬ 
ing operation. The instructions indicated 
that the order of installation should be, 
“resistors, capacitors and IC sockets.” 

I was overcome by doubt. I didn’t want 
to ruin any of the components or the cir¬ 
cuit board by improper soldering, so I 
cheated a little bit. The IC sockets 
seemed to be fairly foolproof and I didn’t 
see too much in them that could burn 
out. I soldered one of them in place and 
knocked off for the night. The next day 
I carried the board and newly soldered 
socket into work to be checked out by a 
friend who had done some soldering. 
He approved my work and reassured 
me. I started back to work on the kit. 

The IC sockets presented no prob¬ 
lem. One nice feature of the Sinclair kit 
revealed itself during this phase. The back 
of the circuit board was coated in plastic 
to prevent drips of solder from making 
contact between the printed circuits. A 
touch like this is an outstanding idea for 
use in a kit that might be assembled by 
amateurs. 

Resistors proved to be a little frus¬ 
trating. Sinclair took it upon itself to pre¬ 
clip the leads on about half of the resis¬ 
tors. Generally speaking, this was con¬ 
venient; however, some of the resistors 
had to be installed vertically. When the 
clipped leads coincided with the vertical 
placement, I ran into trouble. On two oc¬ 
casions, I had to solder more wire onto a 
resistor lead so that it could be installed. 
This added work, which occurred as a 
result of an attempt by Sinclair to lighten 
my load, was only a minor set-back. 

Capacitors were easy! Two of them 
had to be oriented according to their po¬ 
larity, but the instructions were clear and 
the board properly marked. Even the 
diodes were simple to put in correctly. In 
general, the board markings which indi¬ 
cated positioning of the components were 
easy to read and understand. The excep¬ 
tion occurred when I tried to place the 
additional parts required for the U.S. ver¬ 
sion. For some reason, the markings on 
the board left room for doubt as to which 
hole matched which markings. The solu¬ 
tion proved to lie in the circuit diagram. 
I was able to determine that one end of 
resistor R-32 was tied into diode D-9 and 
pin 3 of the TV modulator, and I was in 
business. Again, a novice, I would have 
been more comfortable with a drawing of 
the circuit board as it is physically con¬ 
stituted in addition to the functional lay¬ 
out provided in the circuit diagram. 


28 

486 


Dr. Dobb’s Journal, Number 73, November 1982 




Although the resistors, capacitors, IC 
sockets, diodes and transistors represent¬ 
ed only two sub-steps of the directions, 
they provided the bulk of the work and 
took the most time. There are 34 resis¬ 
tors, 14 capacitors, 5 integrated circuits 
with 140 pins all together, and 9 diodes. 
I don’t want to forget to mention the two 
resistor packs. It was during the installa¬ 
tion of the first of the resistor packs that 
1 had to resort to the use of “assembly 
language.” Fortunately, the children were 
in bed and did not hear their father in his 
role as a “cursor.” 

Prior to putting the ZX81 together, 
I had read two accounts of this operation 
by experienced kit builders. In each case, 
they warned me not to install the resistor 
packs backwards, as they had. The in¬ 
structions warned me not to install the 
resistor packs “the wrong way round.” 
I had been well warned! So, I very care¬ 
fully soldered the first resistor pack into 
the circuit board backwards. Imagine how 
I felt. I have a weak excuse: there is an 
orientation mark on each resistor pack 
which is to be aligned with a correspond¬ 
ing mark on the circuit board. Proper in¬ 
stallation will result in the mark on the 
resistor pack being placed away from the 
front of the board. I guess it is impossible 
for an American to get this right the first 
time. There is something unnatural in in¬ 
stalling a component with markings 
where you can’t read them! Oh well, 
Radio Shack had provided the desolder¬ 
ing braid and I managed to get my 
money’s worth out of it. 

With one exception, the remaining 
parts were easily installed. These parts 
consisted of power, ear and microphone 
jacks, TV modulator, power regulator, 
heat sink, keyboard connectors, keyboard 
and case. The U.S. version also included a 
channel select switch to allow for choice 
between channels 2 and 3. It was this 
switch that I installed incorrectly. It is 
designed to protrude below the bottom 
of the case; therefore, it must be soldered 
to the bottom of the circuit board. Na¬ 
turally, I put the switch on the same side 
of the board as all the other components. 
Back to the desoldering braid.. . . 

With all the parts soldered in place, 
it was a simple matter to push the ICs 
into their sockets and hook the keyboard 
up to the keyboard connectors on the cir¬ 
cuit board. I was ready to “power up.” 
(See how quickly I picked up the “tech¬ 
nical” jargon!) First, though, I checked 


the placement and orientation of every 
component. I thoroughly checked the 
back of the board for solder bridges and 
shorts. Then I checked everything again 
with a magnifying glass. There was no¬ 
thing left to do but try it. 

I plugged in the TV connection and 
applied power. . . there were no loud 
noises and I couldn’t see any smoke. I 
was encouraged. The next step was to 
tune the TV. I fiddled and fiddled, but 
couldn’t get the “K” to appear in the 
lower left-hand corner of the TV screen. 
I was beginning to reach for the fault¬ 
finding section of the directions when I 
realized that the switch on the TV an¬ 
tenna box was in the “TV” position and 
not in the “Computer” position. Could 
this be the problem? Yes! That is all that 
was wrong. The computer worked! I had 
built a computer that worked! All that re¬ 
mained was to put the computer in its 
case and stick down the keyboard. This 
was child’s play for the world’s newest 
electronics whiz-kid. 

Conclusions 

The ZX81 kit took just over 6 V 2 
hours to build. About one hour of that 
was instruction reading and part identi¬ 
fication. I believe that an experienced 
kit builder could put the ZX81 together 
in about 4 hours. In addition to acquiring 
a computer for less than $100, I learned 
quite a lot about electronics in general 
and the ZX81 computer in particular. I 
had fun! I had no idea that an activity 
like soldering small electronic parts onto 
a printed circuit board would be enjoy¬ 
able. I would willingly put a ZX81 to¬ 
gether for a friend just for the fun of it. 

Since building the ZX81, I have had 
a chance to read the 164-page manual en¬ 
titled ZX81 BASIC Programming. The 
book is written to be useful for both the 
novice and the individual familiar with 
BASIC or Z-80 Assembly Language. The 
more I experiment with programming, 
the greater my respect for the designers 
of the ZX8 1. It may be a little slow and 
not have all the features of the “main¬ 
frame” microcomputers, but it is a nifty 
little computer, and I expect a lot of time 
to pass before I reach the limits of its 
capabilities. Of course, the ZX81 only has 
IK of RAM built in and I was able to use 
that up very quickly, but any day now 
UPS will deliver my 16K RAM Memory 
Module and I will be back in business. 


30 


Dr. Dobb’s Journal, Number 73, November 


00 CO 
OS |Tt 






32 

488 


Dr. Dobb’s Journal, Number 73, November 1982 








34 

490 


Dr. Dobb’s Journal, Number 73, November 1982 



Dr. Dobb’s Journal, Number 73, November 1982 


35 

491 









Dr. Dobb’s Journal, Number 73, November 1982 


C.... PROCESS UAL ftS PC REL UNLESS ITS ABS OR IHMOIATE 410 TYP=5 C 

ml w 

co| 'J (Continued on page 36, column 2) (Continued on page 36, column 3) (Continued on next page) 























38 

494 


Dr. Dobb’s Journal, Number 73, November 1982 


































Dr. Dobb’s Journal, Number 73, November 1982 


39 

495 



|o 68000 Cross Assembler 
(XASM) 





















_JI » O TH M 

aroranaoatfticcccaKCKioaccoctOKS 


at o_ —«■ cn 

o in o. c*j 

-♦- ►-. — to o> ► 

^ CO I OC OC £L - a O 

O --• —+ -T-* >— - - - CO I - <-> 

cc: a ct a - -t-ae o 

^ al in ~ - S ai^inin o 

S H m «* I N * cn •* N ▼ CN a: j r j u 

c. cm -*r cc oc •-••-• a oc a ai a: ct cl i —■ -— Cr: au »-* ac cc qc C4 cc: 


zztnSK«Icf£Q(j£ai«4a>««Ka!<i2«ruo2EI ± ui t t r ct - M Dtrrrrrtaj * z to <r a. 




Dr. Dobb’s Journal, Number 73, November 1982 


41 

497 




















68000 XASM Subroutines 

Listing Two 




X 


£ £ £ 

co co £ 

*— ►— !» 

® a a. i 

2 a w » S 

£ £ £ co - 

Ul ^ I * I OQ ijj 

O 5 o CD l CD 

* tz * £ ■=> £ * 

on o (/> <r ►— uj 

I 51! g I i 


£ ~2 

- QC •• «— 

o-o in 

5 Hh d ^ a 

N tfJ N OC A 

r-. 5: •• - 

rH rH O •-* U 

au a: cc a a. 


CO CD 

cj 5 u <c <n d ui <c 
—<ok- a_ 
a z n to a c q: . 


£ 

i 


is i 

Q ^ S =• «| 

X _J 1- Q CC UJ 

19 UJ 4 M Z H U Q £v- 

aK-xnuJ^Qaa 

<£ x cd »— 3 a: o u 

uj a a. x cd o 

S U> UJM z 5 ES 

cjco^rc^S ge 

►—* CJ CD UJ UJ •—• 

h£-5_ggg£ 

>e. z lu ac uj a *— »— z 
cn mB« cd <x cn cd ^ 


qc u: qc 

- w c&J 

- U~> - 

oc r-i _ «» CNJ ce O r J o CJ 

'— arc*..-* a ai a cc a: a. 


ir> 

' eg “ 
C*r r*. 


CJ :> o- :> CK CD z 


o 

E 
« 

a 

s 

0) 

< 
X. 

o p 

O o> 

0.5 

00 (A 

<0 j 


e- £ 

3 *: 
2 a 

<r S 


s 

CD X 


CJ -J UJ 

a z 

SuS 

UJ CJ X 
2r ® ui 


a 


s 

s 

QC 

UJ 

zo 


I X X § 


3 _, _, 

l - 1 

CD UJ • UJ 

CD => Q_ Z> 

O O Z CJ 

QC t U £ 


If £ 

1 3c 


s 


O <C D» 
h* • 

DC A 
—• II CD 
»—* 
n 

UJ UJ |- 

m £ g 

<t « <£ 

►— *— U_ 

SIS 

<X <x P-' 
I— ^ ^ I 

s s §§ 


=> ►— 


& 


? S ? 8 ‘is? 

8 <5 2 => ~ ~ eg 

§ 8 8 £ 

—• O u. •—« 


isi 


3 

£ 

O 


s 


|S£ 


ISH 


g £ 

<r c 


3is 

I eg£ 

w 

S " 3 
~ g =■ 
fc *3 h 

« => CD 


£ 

» -4- 

w> in S£ 

OC ^ ♦ 

~ 4i a 

=> |> »— _J 


<c => 

CD *H 


a 

z 

►— 

CD 

£ 


QC UJ 

g£ 

S »— 
ii 

5 £ 


UJ 

-a 

«» 

uj 5 

£ i 

hi 

rs 


r^- 




o » 

o ♦ 

^ o- S 

^ S: 

z z oc 

C_> A A 

t— A 




£ 

5 


$s 
£ £ 
8 8 


g 

QC CO r> CD <x 

j »- o k o. 

CJ OC £ QC - 


S - eg 

g eli- 5 

u_ « oc oc qc « 

UJ UJ 4 tL 

S % & S °" Z 

5 2 u * S £ 
5 u 5 o _j i 


2 g 


S £ £ £ 

D Q 6 6 
« <r r *: 


4-- -£ -£ Du 

to in in < ♦ 

£ £ ~ “ ou £ 


I 

CD 

UJ 

QC 

1 


a! 

CD 


o 


;£ 


I 


uj cd : 


si 

§ 3 


<N 

C 


“ s s a 
a a e s - 

5E ►— S CD 
5 CA o uj 

CD QC ►— <E 23 
<£ A Z CD 


M Of t V) 
H 3 ui 
cd <r z o 


CD ►— CD _! u_ 

i ii: !l 

A « JQk 

K- U « AC % 

O u_ I 3 cn Q 

o 5 ^ »~i o ^ 

z cd 5 re _j a u. 

*—« CD *—•< 

►— ►— t— »— _ 

t fc g g 

S 3?55g3 


£ 3 

CD 

•-» CD 
CD QC 

►- | 

A 2 
-O 

_g ^ 


I ^ 

£ 3 


c 

c 

13 

5b 

S 

c 


g s 

<r 

^ £ 

CD 

g 


-g £ £ 

a ei -5 w 

o - oc eg 

QC • - - 

-t - £ S ^ ~ 

in m w oc o o 

oc oc eg oc oc h 


- £ 


S - • 


- g 




h-QD^DQ^OO-MUCtCCU oc 

CDOOOOOCDUJZ3:_IOOUJ S H 
»— ACJACJCrCAQ ® t - 3 


s 


Ul o 

» 3 ~ 

** 3 M 


42 

498 


Dr. Dobb’s Journal, Number 73, November 1982 


(Continued on top half of page 













Dr. Dobb’s Journal, Number 73, November 1982 


43 

499 



Memory Management 
in BASIC 


T he allocation of memory is made at 
the beginning of the program by 
the use of a DIM statement. This is 
called static memory allocation because 
the size of the dimensioned variable can¬ 
not be changed during the execution of 
the program. There are times, however, 
when one needs dynamic memory alloca¬ 
tion; that is the ability to create and 
delete arrays as the program is being 
executed. The primary reason why one 
would need such capability is when two 
or more arrays are required, but not 
simultaneously, and there is not enough 
memory to represent them separately. 

It is possible to allocate the maxi¬ 
mum amount of memory that will be 
needed by using a single dimension state¬ 
ment and dynamically, within the pro¬ 
gram, operate upon two or more arrays 
as if they had been defined at the be¬ 
ginning of the program. There are two 
methods of accessing arrays: column 
major order and row major order. Infor¬ 
mation stored according to column major 
order would be A(l, 1), A(2, 1), A(l, 2), 
A(2, 2), All, 3), and A(2, 3). Note that 
the leftmost subscript changes first. Row 
major order is the method of storing 
data in memory a row at a time. An array 
A(2, 3) would be stored in memory as 
A(l, 1), A(1,2), A( 1,3), A(2,1), A(2,2), 
and A(2,3). Again note the subscript; the 
rightmost subscript changes first. 

Management Methods 

The equations which will permit one 
to define the arrays are, 

B+ ((J - 1) * R + I-1)) (1) 

B + ((I-1)*C + J-1)) (2) 

Equation (1) is for column major 
order and equation (2) is for row major 
order. The definitions of the variables in 
the equations are; 

B represents the beginning address 
of the array 

R represents the number of rows 
C represents the number of columns 
I is the row subscript 
J is the column subscript 


by Henry Seymour 

Henry A. Seymour, Senior Designer - 
Computer Systems, Martin Marietta Aero¬ 
space, P.O. Box 29304, New Orleans, 
LA 70189. 


In order to demonstrate this capa¬ 
bility I will define an array, read data into 
it, and manipulate the data by using equa¬ 
tions (1) and (2). Pictorially, the memory 
layout is shown in Figure 1. 



As shown in Figure 2, an array X has 
been created and filled with the values 1 

to 9. 


110 DIM X(9) 

120 MAT READ X 

130 DATA 1,2,3,4,5,6,7,8,9 

140 LET B = 1 

150 LET R = 2 

160 FOR J= 1 TO 3 

170 FOR I = 1 TO 2 

180 PRINT X(B+'((J-1)* R + I-1)), 

U 

190 NEXT I 
200 NEXT J 
210 LET B = 2 
220 LET C = 3 
230 FOR 1= 1 TO 2 
240 FOR J = 1 TO 3 
250 PRINT X(B + ((I - 1) * C + J - 1)) 
I, J 

260 NEXT J 
270 NEXT I 

Figure 2. 

Program demonstrating memory 
management. 


The variable B in statement 140, 
which represents the beginning address, 
has been set to one. This implies that the 
pseudo-array Y that is about to be emu¬ 


lated will begin at the same address as the 
array X. That is X(l) and Y(l, 1) are 
equivalent. The print statement is being 
used as an example in order to reference 
the pseudo-array. The output from print 
statement 180 is, 

1 1 1 

2 2 1 

3 1 2 

4 2 2 

5 1 3 

6 2 3 

which represents a two-dimensional array 
Y(2, 3) stored in column major order. 
Graphically, it would be represented as, 



The code beginning at statement 210 
equates X(2) and Z(l, 1). The print state¬ 
ment 250 produces the output, 

2 1 1 

3 1 2 

4 1 3 

5 2 1 

6 2 2 

7 2 3 

which represents a two-dimensional array 
Z(2,3) stored in row major order. Graph¬ 
ically, it would be represented as, 

J 



Summary 

The programmer has the flexibility, 
power, and ease of use of two equations 
which allows the dynamic definition of 
memory. By changing the value of B one 
may equate a hypothetical array any 
place along the continuum of the original 
array and by using one of the equations it 
is possible to access the data in either col¬ 
umn or row major order. Also, multiple 
arrays may be defined simultaneously, 
thereby allowing the coexistence of mul¬ 
tiple dynamic arrays. This will permit 
some programs to run in a restricted 
memory size that could not otherwise 
run. The maximum amount of memory 
required must be dimensioned and is al¬ 
located during the time of the execution 
of the program. »»j 


44 

500 


Dr. Dobb’s Journal, Number 73, November 1982 






16-BIT SOFTWARE TOOLBOX 


by Ray Duncan 

CP/M-86 vs. PC-DOS 
Benchmarks 

Now that both Digital Research 
CP/M-86 and Microsoft PC-DOS are 
readily available for the IBM Personal 
Computer, we finally have the opportu¬ 
nity to compare the performance of these 
two operating systems in the same hard¬ 
ware environment. Dave Cortesi’s techni¬ 
cal analysis published in DDJ July 1982 
pointed out that although the systems 
appear very similar to the casual user, 
they use drastically different allocation 
schemes to manage disk files. This has 
surprisingly large effects on the speed of 
disk operations. Here are some exam¬ 
ple timings, run on an IBM PC with 
128 Kbytes RAM and two double-sided, 
double-density, 5'A-inch diskette drives. 

PC-DOS CP/M-86 

Batch copy of 26 sec. 86 sec. 
three data files; 
total data trans¬ 
ferred = 101 
Kbytes 

Sequentially read 4.6 sec. 3.5 sec. 
a 10 Kbyte file in 
128-byte blocks 

Perform 100 13.5 sec. 32.0 sec. 

semi-random 
reads of 128 
byte records, 10 
Kbyte file (iden¬ 
tical record num¬ 
ber sequence used 
on both systems) 

Now for the Bad News . . . 

PC-DOS gets a large measure of its 
snappy performance from a resident 
File Allocation Table (FAT) that com¬ 
pletely describes the blocks in use on the 
diskette. The operating system reads this 
table into memory when a file is opened, 
and does not refer back to the diskette 
copy of the table thereafter. If a file 
changes size during processing, the modi¬ 
fied directory entry and the FAT are 
written back to the disk when the file is 
closed. This process apparently does not 
have any safeguards. 

Consider the following situation: 
You are using a program, such as an edi¬ 
tor, that executes with a file open. You 
accidentally change diskettes before leav¬ 
ing the editor. When the editor receives 
the command to exit, it naturally flushes 
its buffers and reissues a request to the 
operating system to close the working 


file. PC-DOS unilaterally writes the direc¬ 
tory and File Allocation Table from the 
previous diskette onto the new diskette, 
making it completely unusable without 
any warning! This disaster has struck me 
twice already, and I believe it is bound to 
happen to everyone sooner or later. Such 
lack of concern for data integrity on the 
part of PC-DOS’s designers is very worri¬ 
some. In contrast, CP/M-86 always 
checks the identity of a floppy disk 
before modifying directory information; 
if it finds a mismatch it will simply mark 
the disk as “Read-Only” and return an 
error message. 

The PC-DOS disk storage scheme 
can also lead to inefficient use of disk 
space under certain circumstances. If 
your program creates a random access file 
and only writes a few scattered records, 
CP/M-86 will assign just enough disk 
blocks to hold-the actual data, while PC- 
DOS will also allocate the “missing” 
empty records whether they are ever used 
or not. 

More on the Intel 8087 

The price of the 8087 arithmetic co¬ 
processor chip continues to fall, now list¬ 
ing for $237 in single unit quantities from 
your friendly local distributor. If you’re 
still wondering what all the fuss is about, 
Figure 1 shows some benchmarks run on 
the IBM PC that will make the power of 
the 8087 obvious. 

Microsoft Fortran does not have a 
double precision (64-bit) floating-point 
data type, so a true comparison could not 
be carried out. 

You might wonder what the effect 
will be on your BASIC programs if you 
plug an 8087 into your PC. Unfortu¬ 
nately, you won’t see any improvement. 
Even though Microsoft had some 40 
Kbytes of ROM to use for their runtime 
subroutines, they couldn’t find the space 
for logic that would check for the exis¬ 
tence of an 8087 in the system and ex¬ 


ploit it if available. There are rumors that 
when PC-DOS version 2.0 is released, it 
will require a new ROM set that will in¬ 
clude drivers for the numeric coprocessor. 

In the meantime. South Coast Data 
Sciences of Costa Mesa, California, has 
announced 8087 support libraries for the 
Fortran, COBOL, Pascal, and BASIC 
compilers. Their press releases imply that 
you must also buy a matched pair of 
8088 and 8087 chips (from SCDS, of 
course) and discard the 8088 that is 
currently in your PC. This is not true. 
Although some of the early engineering 
samples of the 8087 did have problems 
with timing and overheating, the current 
production 8087-3 will work correctly 
with any current production 8088 at 5 
MHz. 

16-Bit Toolbox, Installment #3 

This month’s subroutine is an integer 
square root using Newton’s Method. List¬ 
ing #1 is written in Intel 8086 assembly 
language and Listing #2 in Forth. Please 
note that the result is always rounded 
down , not to the nearest integer. This al¬ 
gorithm is the basis for the square root 
subroutine in most compiler run-time 
libraries. Interesting discussions can be 
found in Donald Knuth’s Art of Compu¬ 
ter Programming series or Kemighan and 
Plauger’s Elements of Programming Style. 

When used on a floating-point num¬ 
ber, a test for convergence is typically 
used after every iteration. When working 
on integers of limited magnitude, it is 
actually faster to just perform a fixed 
number of iterations that will be ade¬ 
quate for the largest possible argument, 
since the test for convergence requires an 
extra multiplication and division opera¬ 
tion. This square root routine will be used 
as a building block for a fast integer 
Chebyshev approximation of sine and co¬ 
sine in next month’s column. 


Operation 

Microsoft Fortran 

Forth with 8087 

(5000 iterations) 

32-bit floating point 

64-bit floating point 

multiply 

5.1 sec. 

3.3 sec. 

divide 

20.9 sec. 

3.4 sec. 

sine 

6 min. 59 sec. 

6.4 sec. 

square root 

5 min. 45 sec. 

2.3 sec. 


Figure 1. 



46 


Dr. Dobb’s Journal, Number 73, November 1982 

50T 





Newton’s Square Root 




Listing One 


title 

’Integer Square Root’ 




pagewidth 79 




■ 

cseg 





9 

; Integer Square Root 

by Newton’s Method 



» Ray 

Duncan, 

August 

15, 1982 



; Call 

with: 

AX = 

Argument 



; Returns: 

AX = 

Square root 



» 


Other registers preserved 

oooo 

3D0100 

5 

sqrt: 

cmp 

ax, 1 

; ex i t i -f argument 

0003 

7F01 

0006 

jg 

sqrt 1 

;less than two 

0005 

C3 


ret 



0006 

53 

sqrt1: 

push 

bx 

;save registers 

0007 

51 


push 

cx 

0008 

52 


push 

dx 


0009 

8BD8 


mov 

bx, ax 

;initial approximation: 

OOOB 

D1FB 


sar 

bx , 1 

;K <- X/2 

GOOD 

B91400 


mov 

cx, 20 

;set loop counter 

OOIO 

50 

sqrt2: 

push 

ax 

; save copy o-f X 

0011 

99 


cwd 


;extend to 32 bits 

0012 

F7FB 


idi v 

bx 

;next approximation: 

0014 

03D8 


add 

bx, ax 

;K <- (K+(X/K))/2 

0016 

D1FB 


sar 

bx, 1 


0018 

58 


pop 

ax 

; restore copy o-f X 

0019 

E2F5 

OOIO 

loop 

sqrt2 

;keep approximating 

OOIB 

8BC3 


mov 

ax, bx 

;copy answer to AX 

00 ID 

5A 


pop 

dx 

;then restore registers 

00 IE 

59 


pop 

cx 

00 IF 

5B 


pop 

bx 


0020 

C3 

» 

ret 


;return to caller 

END OF ASSEMBLY 

. NUMBER OF ERRORS: 

0. USE 

FACTOR: 0 7 . 

Listing 2 





Screen # 55 





0 < 

1 

Integer square root by Newton’s 

method 

04/08/82 ) 

A 

2 20 CONSTANT 

T 

SORT-#-ITER 




4 < 

n - 

square-root ) 




5 s 

SORT 

DUP 0< 




6 


IF . " Illegal argument" 

0 ERROR 

7 


THEN DUP 




8 


IF DUP 2/ 



9 


SQRT- 

-#-ITER 

0 


10 


DO 




11 



2DUP / 

+ 2/ 


12 


LOOP 




13 


SWAP 

DROP 



14 


THEN ; 




15 





End Listing 

Dt. Dobb’s Journal, Number 73, November 1982 

502 



47 



SOFTWARE REVIEW 


JRT Pascal: A Cheap Pascal Compiler 
Published by JRT Systems 
$29.95 

Circle No. 487 on Reader Service Card. 
Reviewed by Dave Cortesi 

“If it works, it’s a real bargain.” That 
was the typical reaction of everyone who 
heard that a full Pascal compiler could be 
had from JRT Systems of San Francisco 
for $29.95. I am a strong advocate of 
cheap software; few things gall me so 
much as software prices that are set as 
high as the market will bear, then justi¬ 
fied by claims of the high cost of sup¬ 
port (which never materializes), and pro¬ 
tected by paranoid locking schemes. I 
was prepared to give JRT Pascal a glow¬ 
ing review and to become an avid booster 
of JRT Systems. 

It really hurts to have to report that 
JRT Pascal is not a bargain. It imple¬ 
ments a highly non-standard version of 
the language for no very good reason. 
Considering the price, that could be for¬ 
given if it worked reliably. It does not. 

Let me address the issue of language 
standards first. The original description 
of Pascal (Pascal User Manual and Report, 
by Kathlene Jensen and Niklaus Wirth, 
Springer-Verlag, 1975) is quite definite 
on what the Pascal language consists of. 
It leaves a few academic loose ends, but 
by and large an implementor couldn’t ask 
for a clearer, better-organized descrip¬ 
tion of a language. 

Wirth’s definition omitted features 
that other people thought (rightly) were 
necessary in a general-purpose language. 
Almost every Pascal implementor has 
felt it necessary to add support for 

(1) varying-length strings of characters, 

(2) separate compilation of program mod¬ 
ules with later linking of modules, and 

(3) random access to files. Since there 
was no standard in these matters, every 
implementor did them in his own way. As 
a result, you just can’t write a transport¬ 
able Pascal program that uses any of these 
three features. But a program that ad¬ 
heres strictly to the language as de¬ 
scribed by Jensen and Wirth should be 
transportable. 

JRT Pascal supports strings, separate 
compilation, and random I/O in ways 
that are, as expected, incompatible with 
any other Pascal (any other that is listed 
in that excellent reference, The Pascal 
Handbook , Jacques Tiberghien, Sybex, 
1981, at any rate). But JRT Pascal not 
only supplements the standard language, 


it deviates from it in many ways. It al¬ 
lows the plus-sign to mean concatena¬ 
tion of strings, for example. It does not 
enforce Pascal strong typing; structured 
variables of differing lengths may be com¬ 
pared, and a structured type can be as¬ 
signed to another that is shorter or long¬ 
er. It rejects the keyword “packed” (it 
should be ignored if not implemented) 
and doesn’t recognize the standard type 
“text” as meaning “file of char.” Compil¬ 
er directives, rather than being hidden in 
specially-formatted comments, are ele¬ 
vated to the status of language keywords. 
That reserves a number of words that are 
not reserved words in standard Pascal. A 
program that declares a variable named 
“list” will fail to compile, for example. 

A particularly irritating deviation is 
the implementation of sequential I/O. 
Wirth’s scheme for I/O is elegant: a vari¬ 
able declared as a “file of type ” simply 
becomes a pointer to an object of that 
type. The standard procedure “get” 
makes the file variable point to the next 
item of that type in the file. It’s the high- 
level-language equivalent of memory- 
mapped I/O in hardware. JRT Pascal ig¬ 
nores Wirth and requires the programmer 
to use the “read” and “readln” proce¬ 
dures for files of every type. That makes 
Pascal I/O look more like Fortran or 
BASIC, which some might find comfort¬ 
ing. It also makes JRT Pascal programs in¬ 
compatible with standard Pascal com¬ 
pilers. 

Well, suppose that you don’t mind 
writing non-portable programs and are 
willing to take the compiler as just an¬ 
other Pascal-like applications language. 
How does it work? JRT Pascal is a partial 
compiler. You prepare a source program 
with your choice of text editors. The 
command JRTPAS2 invokes the compil¬ 
er. It reads the source, writes a listing and 
any error messages to the CP/M console, 
and writes a file of type .INT to disk. The 
.INT file contains code for a virtual ma¬ 
chine that is implemented by a run-time 
interpreter named EXEC. That program 
loads the intermediate-code file and exe¬ 
cutes it. 

For reasons that will become clear, 
I wasn’t able to make any performance 
tests of JRT-compiled programs. The 
compiler itself is a JRT-compiled pro¬ 
gram; it runs slowly compared to native- 
code programs but reasonably fast for 
an intermediate-code implementation. 
It compiles at a rate of about three lines 
per second. 


When it compiles at all, that is. What 
really damns this product is that the com¬ 
piler is very fragile; it falls apart at a 
touch. Lest you think I exaggerate, here 
is a brief log of my use of JRTPAS2. All 
the programs I tried it on were working 
ones that compiled correctly under a 
more expensive product. Program One 
caused JRT to bomb after about thirty 
lines with the run-time message “Array 
index too small” and EXEC’s dump of a 
failing program’s stack. Program Two 
provoked the compile error “Type 
identifier expected” after a line “type 
page=record. . .”. That message was fol¬ 
lowed by four identical messages about 
an “Invalid dynamic storage address,” 
and then the compiler aborted with 
“Array index too large.” Later I found 
that “page” is a reserved word in JRT 
Pascal — but this is not the way that I’d 
choose to notify the programmer of that 
fact. 

In Program Three, the “program” 
statement followed a comment block 
which began with “[” but ended with 
“*)”. The compiler said it couldn’t find 
the “program” statement. Then it entered 
a loop in which “invalid dynamic storage 
address” messages alternated with odd¬ 
sounding disk activity. I hastily mashed 
the system reset button, after which my 
system wouldn’t re-boot until I powered 
it down and up again. 

That scared me, so I left off compil¬ 
ing my own programs and turned to a set 
of the programs from the Jensen and 
Wirth book that I had on disk. I tried to 
compile seven of these; two of them 
(programs 11.3 and 11.5) compiled cor¬ 
rectly and ran. Program 11.5 takes key¬ 
board input one character at a time. It 
appeared from its behavior that when a 
program asks for a single character, 
EXEC reads an entire line from the key¬ 
board, gives the program the first byte, 
and throws the rest of the line away. 

The other five failed to compile. One 
had a variable (not a constant) named 
“list”; the compiler reacted with “Error 
in constant” and then aborted with run¬ 
time errors. Another used the perfectly 
standard declaration “type infile=text” 
which produced the same uninformative 
results. Another passed a function as a 
parameter of a procedure. JRT Pascal 
doesn’t support that, but doesn’t diag¬ 
nose it where it appears in the formal 
parameter list. It diagnoses an “Unknown 
variable name” when the parameter is 

(Continued on page 53) 


48 


Dr. Dobb’s Journal, Number 73, November 1982 

503 




BOOK REVIEW 


Teaching Your Computer To Talk 
by Edward R. Teja 
Published by TAB Books 
$15.95 hardback, $8.95 paperback 
Reviewed by Joseph B. Rothstein 

Voice I/O — the use of spoken words 
to interact with computers — is one of 
the industry’s “hot buttons” at the 
moment. Billion-dollar markets are fore¬ 
cast for speech-based products, both on 
the input and output sides. Business 
executives demand alternatives to the 
keyboard if they are to take computers 
into their inner offices and their hearts. 
Futurists predict a new wave of tech¬ 
nology, based on friendly interaction 
with intelligent, speaking and listening 
systems. And the military, of course, 
is watching and waiting while doing some 
experimenting of its own. 

For the newcomer to the field, the 
array of predictions, applications and 
devices may seem bewildering. Speech 
synthesis and voice recognition have been 
near the top of researchers’ “wish lists” 
since the earliest days of computing, but 
it seems like the wish has become reality 
practically overnight. It was just a couple 
of years ago that Texas Instruments in¬ 
troduced Speak and Spell; now, suddenly, 
there are talking bathroom scales, talking 
alarm clocks and talking calculators, be¬ 
sides a host of other talking toys and 
learning aids. 

Despite the giant strides made in 
recent years, the field is still wide open to 
the type of garage R & D which brought 
us microcomputers in the first place. A 
number of writers for the popular com¬ 
puter journals have recently sounded the 
death knell for individuals working nights 
and weekends in their basements and 
garages, citing big corporations and re¬ 
search institutions which have all but 
cornered the market on microcomputer 
research and development. But as one 
window closes, another opens. Voice 
technology may provide the means 
for hobbyists and experimenters to re¬ 
capture the early, heady days of the 
Altair, Microsoft BASIC and CP/M - 
while staking out a share of the profits, as 
those earlier entrepreneurs did. 

A new book from TAB, publishers of 
numerous tutorials on computers, ham 
radios and similar topics, may help place 
the subject in perspective and offer an 
opportunity for the computer hobbyist 
to enter this exciting and potentially 
rewarding field. Entitled Teaching Your 


50 

504 


Computer to Talk, by Edward R. Teja, it 
covers the historical context, scientific 
basis and application of speech synthesis 
and voice recognition technology. 

The author — an Associate Editor of 
EDN Magazine — softpedals speculation 
and prediction, concentrating instead on 
current applications, available hardware 
and microcomputer interfacing tech¬ 
niques. It’s a considered and well-focused 
approach, recommended for those who 
have at least some background in digital 
electronics. The emphasis is on hardware, 
with numerous schematics and circuit 
diagrams included. Software, however, is 
given scant treatment — only one listing 
for the Z-80 is offered — and while this 
may minimize dependence on a particular 
computer, it leaves some significant gaps 
which will have to be filled by the experi¬ 
menter. 

That caveat aside, the tutorial is a 
thorough and down-to-earth approach to 
a subject which too often carries an aura 
of sci-fi. A general survey and history of 
voice recognition and synthesis, while 
brief, establishes a context for the dis¬ 
cussion which follows. Similarly, a sec¬ 
tion covering the physics and biomechan¬ 
ics of speech finds a solid middle ground 
between boring those familiar with the 
subject and confusing those new to the 
field. 

The bulk of the text — and its great¬ 
est strength — is its analysis of a wide 
range of speech synthesis, voice recogni¬ 
tion and related hardware. The range of 
the discussion runs the gamut from such 
products as the Kurtzweil Computer 
Products Reading Machine costing many 
thousands of dollars (which can “read” 
aloud from printed material and is de¬ 
signed to aid the visually handicapped) to 
the $395 Votrax Audio 1 speech synthe¬ 
sis module for the Pet computer, targeted 
at the hobby and experimenter market, 
to a simple $70 interface from Percom 
Data Company which connects a TI 
Speak & Spell to a Radio Shack TRS-80 
computer. 

The product evaluations are concise 
and direct, stressing likely applications, 
interfacing techniques and cost. Each 
product is discussed in a level of detail ap¬ 
propriate to its usefulness to the experi¬ 
menter. Prices are given for each product 
considered at length, and the names and 
addresses of product manufacturers are 
included in a six-page appendix that is 
handy for ordering or reference. 


Both the phoneme synthesis and 
linear predictive coding (LPC) approaches 
are covered, with attention to the full 
range of speech related devices available, 
from chips — for example, the $100 
(quantity 100) TMS5200 LPC chip from 
Texas Instruments, combining dozens of 
subsystems in a single integrated circuit — 
to board-level modules and stand-alone 
devices such as the Model 4700, a fully- 
equipped recognition and response sys¬ 
tem from Centigram Corporation, priced 
at $3500. In this fashion, the experiment¬ 
er may choose the level of complexity 
and challenge appropriate to his or her 
interests, expertise and budget. 

If there is any real shortcoming to 
this text, it’s that it is almost too timely. 
In this fast-changing field, it’s likely that 
new hardware introductions, new prices 
and new applications will change the out¬ 
look for speech technology faster than 
any book can keep up with. This is a 
minor point, though, and one which it 
would be a pleasure to raise about many 
other such books. On the whole, the sur¬ 
vey of products is as complete and tho¬ 
rough as any experimenter has a right to 
expect. 

The implications of this technology 
are staggering, and anyone interested in 
the social impacts of computers would do 
well to consider how this emerging field 
will affect our business, personal and in¬ 
stitutional lives in the coming years. 
Other books and magazine articles cover 
this aspect of voice I/O more thoroughly 
than the nuts-and-bolts approach taken 
here. While there is tantalizing mention of 
talking robots, pilot guidance systems and 
interactive telephone directories, these 
barely scratch the surface of applications 
currently under development, much less 
those in the imagination stage. But this 
is just as well, for there are many sources 
of such surveys and speculations, some 
of them cited in the text and too-brief 
bibliography. 

Similarly, those with no hardware 
background, and those without previous 
exposure to voice-driven devices, may do 
best to look elsewhere first before tack¬ 
ling the projects outlined in this tutorial 
and reference. But the eager experiment¬ 
er, undaunted by schematics and anxious 
to plunge into an application field still in 
its infancy, would be hard-pressed to find 
a more comprehensive and valuable start¬ 
ing point than Teaching Your Computer 
To Talk. »»j 


Dr. Dobb’s Journal, Number 73, November 1982 



OF INTEREST 


by Michael Wiesenberg 


Hardware V Things 

PConnection, from Microperipheral, 
is an IBM PC modem card, a direct- 
connect, Bell 103/113 compatible mo¬ 
dem with autodial (Touch Tone or 
pulse), that answers automatically in both 
originate and answer modes. The card fits 
inside the PC cabinet, and costs $350. 
Reader Service No. 307. 

The Osborne 1 can now use Corvus 
Systems’ network and mass storage disk 
systems, in configurations of 6, 11, and 
20 megabytes. The Corvus Multiplexer 
local area network permits up to seven 
Osborne users to share up to 80 mega¬ 
bytes, in addition to printers and other 
peripherals. The disk systems for Osborne 
1 start at $3195, including interface card 
that plugs right into the IEEE-488 port, 
and software. Reader Service No. 317. 

Turn your TRS-80 model I or III 
into an IBM PC emulator with /uMERLIN 
from Micro Projects Engineering Co. The 
self-contained unit has an 8088, 8K of 
EPROM, and 64K of dynamic RAM (ex¬ 
pandable to 256K). The TRS-80 becomes 
a slave I/O processor for access to CRT, 
keyboard, disks, and I/O ports. Optional 
interval timer and priority interrupt 
controller chips allow later expansion 
to multitasking operating systems. 
/uMERLIN comes with CP/M-86; MS- 
DOS is coming early next year. This unit 
provides software compatibility with the 
PC, and costs $1195 and up. Reader 
Service No. 327. 

If you write a lot, as I do, you go 
through a lot of printer ribbons. Mac 
Inker from Computer Friends is an auto¬ 
matic printer ribbon reinker that permits 
virtually endless reuse of ribbons. Avail¬ 
able with many different colors of ink 
and cartridge loading stations for all 
printers, Mac Inker costs $54.95. Reader 
Service No. 337. 

Applications V Such 

A recent major study of CP/M word 
processors compared Spellbinder, from 
Lexisoft, Inc., with twelve other similar 
products for micros. In the study’s more 
than 100 categories. Spellbinder received 
over twice as many positive ratings as the 
average, and 10% more than its closest 
contenders, many of whose “extra” fea¬ 
tures could be obtained only for extra 
cost, but are standard on Spellbinder. Al¬ 
though Spellbinder has been around for 
awhile, it now comes with a new office 
and data management package. Spellbind¬ 
er is a full-screen editor that uses all the 


features of most letter-quality precision 
printers, typographic-quality printers, 
and dot-matrix printers. It uses special 
function keys on most terminals, offers 
help messages for most operations, man¬ 
ages files larger than memory, and exe¬ 
cutes command files. Their standard 
20,000-word spelling checker, Spellcheck, 
that can be expanded to the capacity of a 
complete disk, for example, can be 
operated as a system overlay with a 
command that returns control to Spell¬ 
binder. In addition to all the standard 
capabilities that you expect from a word 
processor, Spellbinder scrolls horizontally 
to accommodate lines of up to 160 char¬ 
acters. It word wraps onto variable and 
independently set left margins. It deletes 
or moves with one keystroke by charac¬ 
ter, word, line, multiple line, sentence, or 
paragraph. It has three kinds of hyphena¬ 
tion, breaking (splits at any of the hy¬ 
phens of “father-in-law”), nonbreaking 
(always keeps something like “Section 
A-l” together), and “soft” (appears only 
when that part of the word falls at the 
end of a line, as in “hyphen-ation”). 
Spellbinder prints to the screen or to disk 
instead of a printer if you wish, or right 
from memory without having to save to 
disk. You have complete dynamic control 
over the printer, with variable line spacing 
adjustable to 1 /48th inch, and true pro¬ 
portional spacing. And if you don’t like 
the widths Spellbinder assigns to charac¬ 
ters, you can change them. You can also 
change character spacing within lines. 
You can number pages at top or bottom, 
and use headers or footers or both, each 
with separate formats for even and odd 
pages. You can assign commands or any 
repetitive sets of keystrokes into a spe¬ 
cific single function-keystroke. The 
office management package includes 
forms creation and fill-in. The Spellbind¬ 
er disk comes with macros for mail 
merge, cue sorting, alphabetizing, and Zip 
Code sorting. You can print in multiple 
columns, each justified, and print in pat¬ 
terns, such as a document printed in 
the shape of a Christmas tree or a large 
circle. Math functions include column and 
row addition, decimal tabbing, columnar 
editing, and fixed-point arithmetic. All 
this goes for $495. Reader Service No. 
347. 

Can you run a program with over 
200K of code on an 8-bit CP/M system? 
MEGA/CPM from SysteMathica extends 
the nominal 64K address space by swap¬ 
ping program segments in and out of 


main memory with overlay management 
transparent to the user (and, they claim, 
to the CPU). MEGA/CPM requires no 
hardware or software modifications, suf¬ 
fers no speed degradation with external 
ROM/RAM, and, when disks are used, its 
speed is determined by the transfer rate 
of the disk controller. The CP/M 2.2 ver¬ 
sion costs $100; MEGA/CPM on HP 
series 80 is $150; MEGA/ISIS forISIS-II 
costs $190. Reader Service No. 357. 

Softworks C is the first available 
higher-level language for the TRS-80 
Model 16, Radio Shack’s 68000-based 
entry into the 16-bit market. Softworks 
Limited claims theirs is a complete im¬ 
plementation of the C language. It is 
based on the Whitesmith’s C compiler, 
and costs $950. Softworks also offers 
cross-compilers to develop Model 16 C 
programs on other systems. Reader Ser¬ 
vice No. 367. 

HP’s HP Plus program distributes and 
supports third-party software, including 
the Condor database management system 
for the HP 125. This DBMS uses the 125’s 
screen-labeled “softkeys” and editing 
keys. It writes files that can be read into 
the HPWORD/125 word-processing sys¬ 
tem (HP’s implementation of Lexisoft’s 
Spellbinder), and used by HPGRAPHICS/ 
125 graphics software. Condor uses 
menus to create databases, make entries 
and queries, manipulate data, and generate 
reports. It produces databases of up to 
32K entries, each with up to 127 fields. 
Condor Series 20-1 creates databases in 
minutes, extracts reports soon thereafter, 
and costs $295. Series 20-2 handles mul¬ 
tiple files, relating data among them, and 
projects, posts, and combines information 
from all files, and costs $595. The up¬ 
grade from 20-1 to 20-2 costs $350. 
Reader Service No. 377. 

Interested in C, Ada, and Lisp? 
SuperSoft offers a free 24-page brochure 
describing their implementations of those 
languages, and other goodies, including a 
virtual memory electronic spreadsheet 
called Scratchpad that never runs out of 
memory, and Disk-Edit, a screen-oriented 
disk editor that simultaneously displays 
programs in hexadecimal and ASCII. 
Reader Service No. 387. 

Altos offers a 70-page software 
guide, costing $5, for its ACS8000 8-bit 
and ACS8600 16-bit micros, including 
hundreds of packages running under 
CP/M, CP/M-86, MP/M, MP/M-86, and 
XENIX/UNIX. Reader Service No. 397. 

Two free catalogs of educational 


52 


Dr. Dobb’s Journal, Number 73, November 1982 

505 




software from many publishers for Apple, 
PET, TRS-80, and Atari are offered 
by Queue, Inc. One is for kindergarten 
through ninth grade, and the other for 
high school and college. Specify com¬ 
puter and grade level when writing. 
Reader Service No. 407. 

An upgrade of AmperSoft from 
Micro-SPARC, Inc., for Apple II with 
RAM card, moves the DOS onto the card, 
thus providing an extra 10K of usable 
program memory. It also offers new 
functions: &Print for BASIC’s Print 
Using; &Sort, a machine-language sort 
routine; &Store/Recall, storage and re¬ 
trieval of numeric arrays as binary files 
that take up half the space of, and are 
accessed up to 16 times faster than, stan¬ 
dard text files; &Matrix, for matrix oper¬ 
ations at machine-language speed; &FRE, 
for clearing memory of character strings 
in seconds; and &CLEAR, to clear mem¬ 
ory of arrays. The disk also includes 
hooks to the PLE, FID, MUFFIN, RE¬ 
NUMBER, and COPYA utilities to be 
used with the relocated DOS. This copy- 
able disk costs $49.95 at Apple dealers, 
or add $1.50 postage and handling to 
order from Micro-SPARC. Reader Service 
No.417. 

WSP FORTH for the IBM PC, from 
World Wide Software Publishers, is based 
on the fig-Forth standard. It comes with 
its own editor and utilities, and costs $75. 
Reader Service No. 427. 

Miscellany V Etc. 

The C Users’ Group, a non-profit or¬ 
ganization, has over 1200 members. You 
can join for $10 a year ($20 foreign), and 
get six issues of the newsletter and up¬ 
dates to registered purchasers of the BDS 
C compiler. CUG offers library disks in 
most formats for $4 to $8 each. Reader 
Service No. 437. 

SQ (Syntax Quarterly) is a magazine 
for users of the Timex-Sinclair (nee 
ZX81). Published by SYNTAX, the 
Timex-Sinclair newsletter, an SQ sub¬ 
scription is $15 for four issues, or one 
year of SQ plus twelve monthly issues 
of SYNTAX for $39. Reader Service 
No.447. 

The Software Author SIG on Compu¬ 
Serve is for freelance programmers and 
writers in the microcomputer field. It 
maintains an electronic bulletin board, 
conference facilities, and market report 
databases. Run by Saturday Software, the 
service is free. A CompuServe subscriber 
issues the command G PCS-117 from any 


prompt, or selects option 13 from the 
SIG’s menu on PCS-50. 

Each month, we get a wonderful 
publication called Privacy Journal that 
addresses the erosion of the average citi¬ 
zen’s privacy in the computer age. Usu¬ 
ally it contains nothing of direct interest 
to DDJ readers, but the July issue’s main 
article was about skinnydipping, “Right 
to Be Let Alone: Nude Swimming.” In 
a sidebar called “The Naked Program¬ 
mer,” Lee Baxandall, coordinator of the 
Free Beach Documentation Center (great 
name!), an organization that wants to 
open recreation sites to nude use, states 
that a “disproportionately large number 
of computer programmers are skinnydip- 
pers. It’s no coincidence that. . . many 
nude beaches [are] located near Silicon 
Valley,” because programmers and other 
DP folks practice “diverse life styles and 
are more tolerant of others’ practices.” 
The fact that his organization, The Natur- 
ists, has a great many computerists among 
its members has caused him to consider 
advertising in electronics industry trade 
publications. If you want to join pro¬ 
grammers and other Naturists, write to 
Box 132, Oshkosh, WI 94901. The July 
issue of Privacy Journal also contained an 
article warning about the ease of govern¬ 
ment surveillance of its citizens through 
credit cards. When credit cards are used 
for travel and entertainment, monitoring 
and curtailing the movements of free citi¬ 
zens becomes easier. A subscription to 
Privacy Journal is $79 ($95 overseas). 
They also publish Compilation of State 
and Federal Privacy Laws, an 80-page 
book, at $16. Reader Service No. 457. 

The Personal Computer Products 
Buyer’s Guide from Starware brings to¬ 
gether software and hardware for the IBM 
PC from a host of manufacturers. Star- 
ware offers a 10% discount for orders 
from them of any product in the guide, a 
six-month free hardware repair warranty, 
software support, and free phone advice. 
They also pay all shipping charges. Star- 
ware will send one issue free; a one-year 
subscription (12 issues) is $8. Any order 
also gets a free subscription. (They have 
a 20% royalty arrangement for software 
developers.) Reader Service No. 467. 

Among other projects, the San Diego 
Computer Society is trying to establish 
a format on 514-inch diskettes for inter¬ 
change of data between otherwise incom¬ 
patible machines and operating systems. 
The SDCS has eight special-interest sub¬ 
groups (SIGs), and members seem to own 


the spectrum of computer systems and 
are interested in all languages and operat¬ 
ing systems. They put out a classy news¬ 
letter, Personal Systems. Membership is 
$ 15 for the first year, and $ 10 thereafter. 
Reader Service No. 477. 


»»J 


(Continued from page 48) 

referenced. Two other programs put the 
compiler into a loop from which it hadn’t 
emerged after several minutes. 

JRT Pascal claims a lot of attrac¬ 
tive features, but there’s no point in going 
into them here. It carries a very attractive 
pricetag for its claimed features, but that, 
too, is irrelevant. Partly because of its 
many deviations from standard Pascal, 
but mainly because of its unreliability, I 
rate JRT Pascal as Not Acceptable. It is 
a product that could give “cheap” a bad 
name. After trying to use it, it is clear 
to me why its makers decided to lower its 
price. In my opinion they didn’t lower it 
far enough. __ 


Dr. Dobb’s Journal, Number 73, November 1982 
506 


53 


Clinic (Continued from page 9) 


a barely-controlled-impatience heuristic 
to it. When at one level it has tried every 
possible encoding for a letter and failed, 
and when all those failures collided with 
the same previously-hashed word, and 
when as a result of those trials no forward 
progress has been made over previous trial 
encodings, the program declares the 
blocking word to be a “problem.” It 
forces the algorithm to backtrack to the 
nearest point at which one of the letters 
of that word was encoded. This produced 
a significant speed-up in the cases where 
the program was already finding a solu¬ 
tion (it then found different solutions), 
but didn’t seem to help on those where it 
wasn’t already working. 

One set of keywords that the pro¬ 
gram did well on was a list of thirty-seven 
Pascal reserved words. It turned up a 
good encoding in just under a minute 
(Pascal/Z, 4MHz Z80 system). One en¬ 
coding is shown in Table 1. 

The whole subject of perfect hashing 
is one of those corners of systems pro¬ 
gramming that has the fascination of 
magic squares and other puzzles of recrea¬ 
tional mathematics. You may enjoy ana¬ 
lyzing the logic of our imperfect version 
of this particular algorithm. You can 
probably improve on it, or find a com¬ 
pletely new approach. »*j 


(Listing begins on page 56) 


Dr. Dobb’s Journal, Number 73, November 1982 


55 

507 



Hash ’n Pascal 

(Text begins on page 9) 
Listing I 

program perfect; 


{ This program reads a set of words from a file and attempts } 

( to find a perfect-hash encoding for them. The logic follows} 

{ that of Cook and Oldehoeft (SigPlan Notices, 9/82), but not } 

{ very closely. If a suitable hash-encoding is found, a report} 

{ is written to a file. This version compiles under PASCAL/Z } 

[ and runs under CP/M 2.2. Compiler dependencies are flagged } 

( in comments. Publication listing formatted by a modified } 

( version of a pretty-printer by P. Grogono, PZUG disk #17. } 

{ - ) 

const 

{ the algorithm shouldn't be applied to a set of more than 
45 or so words, but let's be optimistic..} 
maxwords = 90; 

{ the hash table size is 110 % of the count of words, 
indexed by letter-codes from 0..size-1. } 
maxcode = 99; 

{ length of the words in the set isn't very significant} 
maxchars = 16; 

type 

wordspan = l..maxwords; { indices over table of words } 
wordcnt = 0..maxwords; { counts of words } 
hashspan = 0..maxcode; { (max) range of valid hashcodes } 
codes = hashspan; { letter codes are hashcodes } 

letters = 0..25; [ uppercase ordinals less ord(A) } 

charspan = 1..maxchars; { indices over letters of a word } 
charcnt = 0..maxchars; { counts of letters in a word } 

wordrec = 

record ( word info as held in the table } 

key : record ( key for initial table order } 

LA, { initial/most-frequent letter } 

LZ ; letters; ( final/least-frequent letter } 

WL : charcnt { word's length } 
end; 

hashval : codes; ( tentative hash value } 
spelling : arrayCcharspan] of char 
end; 

var 

wordtab ; arrayCwordspan] of wordrec; 

numwords : wordcnt; { actual count of words from file } 
hashtab : arrayChashspan] of wordcnt- 

hoshmax : hashspan; { actual size of table, 110% numwords } 

census : arrayCletters] of integer;( frequency of use } 
double ; arrayCletters] of boolean;{ eg., E as in ELSE } 

encoding : arrayC letters] of codes; 

encoded ; arrayCletters] of boolean; { code assigned? } 
usedcode : arrayCcodes] of boolean; { letter assigned? } 

problem : boolean; { global flag for fast backtracking } 
probltr1, 

probltr2 : letters; { letters causing intragroup conflict } 
blockwrd : wordcnt; [ word that blocked a hash try } 
actdepth, { current recursion level } 

depth : integer; { deepest recursion level so far } 

OkSoFar ; boolean; { status of main procedure's work } 

procedure Initialize; 

var H ; hashspan; 

L : letters; 

C : codes; 

begin 

for H:=0 to maxcode do 
hashtabCH] := 0; 
for L:=0 to 25 do 
begin 

censusCL] : = 0; 
doubleCL] ;= false; 
encodingCL] := 0; 
encodedCL] := false 

end; 

for G:=0 to maxcode do 
usedcodeCC] := false; 
numwords := 0; 
hashmax ;= 0; 
problem := false; 
blockwrd := 0; 
actdepth ;= 0; 
depth := 0 
end; 

procedure ReadAll; 

{ Read all the keywords from the CP/M text file KEYWORDS into 
wordtab. Order them by their keys, mainly so that we can 
detect conflicts — words that have identical initials, 
finals, and lengths, like ORD and ODD. 

The format of the input file is : a word per line, uppercase, 
left-justified, no embedded blanks, no blank lines, no 
empty lines, no words of one letter or more than maxchars. 
NONE OF THESE REQUIREMENTS ARE CHECKEDl } 


var F ; text; 

W, X, Y ; wordcnt: 
stop : boolean; 
tw : wordrec; 

procedure ReadOnefvar R:wordrec); 

( Read one word from the file and install it. Also keep 
the census of letter-frequency and double-ended words } 
begin 

readln(F,R.spelling); 

R.key.WL := maxchars; 
while R.spelling[R.key.WL]=' ' do 
R.key.WL := pred(R.key.WL); 

R.key.LA := ord(R.spelling[i])-ord('A'); 

R.key.LZ := ord(R.spellingCR.key.WL])-ord('A'); 
Census[R.key.LA] := succ(CensusCR.key.LA]); 

CensusCR.key.LZ] := succ(CensusCR.key.LZ]); 
if R.key.LA=R.key.LZ then 
doubletR.key.LA] := true 

end; 

begin (ReadAll} 

reset('KEYWORDS',F) ; (PASCAL/Z dependent} 

W := 0; 

OkSoFar : = true; 

while (not eof(F)) and (W<maxwords) do 
begin 

W := succ(W); 

ReadOne(wordtab[W]); 
stop ;= false; 

X := W; 

repeat { insert latest word into position by key } 

Y := pred(X); 
if Y>0 then 

if wordtab[X].key < wordtab[Y].key then 
beg i n 

tw := wordtab[Y]; 
wordtab[Y] := wordtabCX]; 
wordtab[X] := tw; 

X := Y 

end 

else stop := true [ in position } 
else stop := true { at head of table } 
until stop; 
if (Y>0) then 

if wordtab[X].key=wordtab[Y].key then 
beg i n 

OkSoFar := false; 
writeln('Word ', 

wordtab[X].spelling, 
conflicts with ', 
wordtab[Y].spelling) 

onH 

else ( not a conflict } 
else ( at head of table, no conflict } 
end {while}; 
if (W>0) then 

begin 

numwords := W; 

hashmax := (W + round(W/i0.0))-i 
{ n.b. "W+round(W/10.0)" is the number of slots in the table; 

that less L is the maximum index over the table and also 
the modulus used in the hash function. The largest code 
that can be assigned is hashmax-1, because larger ones 
would just wrap around with the modulo function. } 
end 

else begin 

OkSoFar : = false; 

writeln('file KEYWORDS not found or empty.') 

end 

end{ReadAll}; 
procedure Reorder; 

{ Put the wordtab in the order described by Cook and Oldehoeft: 

(1) compute the frequency of the end-letters seen — this 
has been done in procedure ReadOne/ReadAll. 

(2) assign a large value to any letter that appears at both 
ends of single word, as E does in ELSE. 

(3) for each word, if letter 2 (LZ) precedes letter i (LA) 
in the ordering, interchange the letters. 

(4) using letter 2 as the key, sort the word table into 
descending order by letter frequency. 

The result of this order is that letters such as E in ELSE 
(which have less choice of hash positions) are encoded 
first. Next encoded are the most frequent letters (which 
are more likely to raise conflicts). 

Cook's and Oldehoeft's claim that the ordering also ensures 
that "letter L has been previously assigned a value" is 
clearly not true in every case (although it often will be); 
it is easy to imagine a set of keywords such that the end- 
letters of one keyword are disjoint from the end-letters of 
all other keywords. } 

var L : letters; 

W, Wl, W2 : wordspan; 

TL : letters; 

TW : wordrec; 

begin 

for L := 0 to 25 do 
if double[L] then 

censusCL] := census[L]+(numwords*2); 

(Continued on page 58) 


56 


Dr. Dobb’s Journal, Number 73, November 1982 




Hash ’n Pascal 

(Listing continued, text begins on page 9) 

for W := l to numwords do 
with wordtab[w].key do 

if census[LA]<census[LZ] then 


begin 


TL : = 

LA; 

LA :» 

LZ; 

LZ : = 

TL 

end; 



{ sort the table — no terribly quick sort is needed here 
as the backtracking code will easily dominate execution 
time regardless. } 

for WL :» i to numwords-i do 

for W2 := numwords downto Wi + i do 
if censusCwordtabCWl].key.LZ] < 
census[wordtab[W2].key.LZ] then 
begin 

TW := wordtab[Wi]; 
wordtabCWi] :=* wordtab[W2]y 
wordtab[W2] := TW 
end; 

end; 

P rocedure AssignCode(var C : codes; L s letters); 

Assign the first free code from C, to letter L } 
begin 

while usedcode[C] do 
C := succ(C); 
encodingCL] :» C; 
encoded[L] := true; 
usedcodeCC] := true; 
write( chr(8), chr(C+ord( ' A')) ) 

end; 

P rocedure FreeCode(C ; codes; L : letters); 

Back out of the assignment of code C to letter L ) 
begin 

encodedCL] := false; 
usedcode[C] := false; 
write(chr(8),'.') 

end; 


procedure TestProb(wi,w2 : wordspan) ; 

{ Check the group of words wordtab[wl..w2] for an internal 
conflict. An intra-group conflict exists when, for some 
pair of words, (encodingCLAi]+WLi) is identical to 
(encoding!! LA2 ]+WL2 ) . Since both words have the same LZ, 
no encoding of LZ will work. If a conflict exists, note 
it in global "problem" and note LAi, LA2 in globals 
probltrl/2. The main search routine will do a fast back¬ 
track to the point at which one of those was encoded. } 

var 

conflict : arrayCcodes] of wordcnt; 
cde : codes; 
wrd : wordspan; 


begin 

problem false; 
for cde := 0 to maxcode do 
conflict[cde] := 0; 
wrd := wi; 

while (not problem) and (wrd<*w2) do 
begin 

cde := encodingCwordtabCwrd].key.LA] + 
wordtab[wrd].key.WL; 
if conflictCcde] = 0 then 
begin 

conflictCcde] := wrd; 
wrd succ(wrd) 

end 

else 

problem := true 

end; 

if problem then 
begin 

probltrl ;= wordtabCwrd].key.LA; 
probltr2 := wordtabCconf1ictCcde]].key.LA 

end 

end; 

function TestGrp(wi, w2 : wordspan; c : codes): boolean; 

{ test the success of the code c for the second letter of 
the group of words wordtabCwl..w2]. ) 

var 

hash : hashspan; 
success : boolean; 


begin 

with wordtab[wi].key do 

hash := (encodingC LA] + WL c)mod hashmax; 
if hashtabChash]=0 then 
begin 

hashtab[hash] : = wi; 
wordtabCwi].hashval := hash; 
if wl<w2 then 
begin 

success := TestGrp(succ(wi),w2,c); 
if not success then 
hashtab[hash] := 0 

end 

else 

success := true 

end 

else 

begin 

blockwrd := hashtabChash]; 
success := false; 

end; 


TestGrp := success 

end; 

function Letter!(w : wordspan) : boolean; 

FORWARD; 

function TryHash(w : wordspan) : boolean; 

{ A group of one or more words, wordtabCw..?], have the same 
second letter. The first letters.of that group have all 
been given codes. Try to find an encoding of their common 
second letters that will yield a perfect hash. } 


ltr : letters; { the common second letter } 

cde : codes: { the current code for that letter } 

wrd, ( the first word of the group } 

grp : wordspan; { ..and the last J 

success : boolean; 

blocksme : wordcnt; 

solidblock : boolean; 

olddepth : integer; 

begin 

write('.'); { document recursion } 
actdepth := actdepth+i; 
if actdepth>depth then 
depth := actdepth; 
olddepth := depth; 
ltr := wordtab[w].key.LZ; 

{ identify the span of the group — the range of adjacent 
words with the same second letter. } 

grp := w; 

while (grp<numwords) 

and (ltr=wordtab[succ(grp)].key.LZ) do 
grp := succ(grp); 

{ find out if there are any intra-group conflicts, and 
if so, don't bother trying to encode the second letter } 

if 0>(grp-w) then 
TestProb(w,grp); 

if problem then 
success := false 
else if encodedCltr] then 
begin 

( the second letter of our group already has an 
encoding -- we don't have anything to say about 
it. Try the effect of that encoding and, if it 
works at this level, recurse to the next group. 

If we fail at a lower level, that second-letter 
encoding has to be changed, so back out to that 
level directly. ) 

cde := encodingCltr]; 
success := TestGrp(w,grp,cde); 
if success then f yippee 1 ) 
if grp=numwords then 
writeln('1') 

else { more groups to test } 
begin 

if encodedCwordtabCsucc(grp)].key.LA] then 
success := TryHash(succ(grp)) 

else 

success :=* Letter I ( succ( grp)); 
if not success then 
for wrd:=w to grp do 

hashtabCwordtabCwrd].hashval] := 0 

end 

end { of second-letter-has-encoding case } 

else 

begin 

{ Our group's second letter hasn't received a code. 

We know that our group of words can't conflict with 
each other. Now try encodings of the common letter-2, 
looking for one that doesn't conflict with previously 
hashed words. When we find one, we recurse to try 
the next group of words — if any.) 
cde := 0; 
blocksme :* 0; 


58 


Dr. Dobb’s Journal, Number 73, November 1982 




solidblock := true; 

repeat 

repeat { find a code that works for this group } 
AssignCode(cde,ltr); 
success ;= TestGrp(w,grp,cde); 
if not success then 
begin 

FreeCode(cde,ltr); 
cde := succ(cde) 

end 

until success or (cde>=hashmax); 
if success then 

if grp=numwords then [ yippee 1 ) 
writeln(' 1 ') 

else { more words to hash } 
begin 

if encoded[wordtab[succ(grp)].key.LA] then 
success := TryHash(succ(grp)) 

else 

success := Letter 1(succ(grp)); 
if not success then 

begin { back out of group encoding) 
FreeCode(cde,ltr); 
cde ;= succ(cde); 

for wrd:=w to grp do 

hashtab[wordtab[wrd].hashval] := 0; 
if blocksme=0 then 
blocksme := blockwrd 
else if blockwrd<>blocksme then 
solidblock := false 

end; 

if problem then 

{ A lower group has an intragroup conflict. 

If we caused it, turn the flag off and 
try another code. Else back out now.) 

if (ltr=probltr1) or (ltr=probltr2) then 
problem := false 

end 

else { no code works for our group ) 

until success {l perfect hash complete ) 

or problem {2 must back out to higher level ) 
or (cde>=hashmax);{3 no code worked for us } 
if (not success) and (not problem) 
and solidblock and (blocksme>0) 
and (depth=olddepth) {ie no progress) then 
begin 

problem := true; 

probltri. ;= wordtab[blocksme].key.LA; 
probltr2 := wordtab[blocksme].key.LZ 

end; 

end; 

write(chr(8)); 
actdepth := actdepth-i; 

TryHash := success 

end; 

function Letterl; { forward-declared above ) 

l The first letter of wordtab[w] has not been encoded. 

Try to find a code for it, using TryHash to check out 
the effect on the current group of words. The logic is 
much like that of TryHash, but simpler. ) 

var 

ltr ; letters; 
cde : codes; 
success ; boolean; 

begin 

write('.'); { document recursion ) 
ltr := wordtab[w].key.LA; 
cde ;= 0; 

repeat 

AssignCode(cde,ltr); 
success ;= TryHash(w); 
if not success then 
begin 

FreeCode(cde,ltr) ; 
cde ;= succ(cde) 

end; 

if problem then 

if (ltr=probltrl) or (ltr=probltr2) then 
problem := false 

until success {l perfect hash found below us) 

or problem {2 have to back out to higher level) 
or (cde>=hashmax); (3 no code works for our letter ) 

write(chr(8)); 

Letterl := success 


end; 

procedure ReportResults; 

{ Write an ASCII file documenting the perfect hash we found. 
Since the program might have been left to run overnight, 
prompt the user to remount the diskettes and wait for 
somebody to notice us before writing. ) 


var f : text; 

L : letters; 
H : hashspan 
W ; wordcnt; 
X : char; 


begin 

writeln('Press return when I can write a file...'); 
readln(X); 

rewrite('ENCODING',f); (PASCAL/Z DEPENDENT) 
writeln(f,'Letter encodings:'); 
for L := 0 to 25 do 
if encoded[L] then 

writelnf f,chr(L+ord('A')), 

encoding[L]: 2 ) ; 
writeln(f,'Hash values:'); 
for H := 0 to hashmax do 
begin 

write(f,H:2, = ') ; 

W := hashtab[H]; 
if W>0 then 

write(f,wordtab[w].spelling); 
writeln(f) 

end 

end; 

begin { main procedure ) 

Initialize; 

ReadAll; 

if OkSoFar then 
begin 

Reorder; 

OkSoFar := Letter 1(1); 
writeln; 

if not OkSoFar then 

writeln('Six years of computer time wasted...') 

end; 

if OkSoFar then 
ReportResults 

end. 

End Listing 


Dr. Dobb’s Journal, Number 73, November 1982 


59 

510 


#74 December 1982 $2.50 ($3.00 in Canada) 

Dr. Dobb’s Journal 


For Users of Small Computer Systems 


k. 



Small-C 
Compiler v.2 


Interrupts 
and CP/M 

for IBM’s PC: 

Custom Characters 
Lo-Res Color 
Graphics 

Vector Generation 
Algorithm 













































CONTENTS 


For Users of Small Computer Systems 

December 1982 Volume 7, Issue 12 


Editor - Marlin Ouverson 
Assistant Editor — Fritzi Lareau 
Contributing Editors - 

Dave Caulkins, Dave Cortesi, 

Ray Duncan, Hank Harrison, 

Gene Head, Michael Wiesenberg 
Marketing Director — Craig Harper 
Marketing Assistant - Beatrice Blatteis 
Advertising Director - Carl Landau 
Circulation Manager — Gloria Romanoff 
Circulation Assistants - 

Terri Marty, Linda Marohn 
Art Director — Clifford West 
Production Manager - Barbara Ruzgerian 
Production Assistant - Jane A. McKean 
Typesetter - Renny Wiggins 
Cover Illustration - A1 McCahon 


© 1982 by People’s Computer Company 
unless otherwise noted on specific articles. 
All rights reserved. 


Subscription Rates: $25 per year within the 
United States; $44 for first class to Canada 
and Mexico; $62 for airmail to other coun¬ 
tries. Payment must be in U.S. Dollars, 
drawn on a U.S. Bank. 

Writer’s Guidelines: All items should be 
typed, double-spaced on white paper. List¬ 
ings should be produced by the computer, 
using a fresh, dark ribbon on continuous 
white paper. Please avoid printing on perfo¬ 
rations. Payment is in contributor’s copies. 
Requests to review galleys must accompany 
the manuscript when it is first submitted. 
Authors may receive a copy of the complete 
writer’s guidelines by sending a self- 
addressed, stamped envelope. 

Donating Subscribers Contributing Sub¬ 
scriber: $50/year ($25 tax deductible). Re¬ 
taining Subscriber: $75/year ($50 tax de¬ 
ductible). Sustaining Subscriber: $ 100/year 
($75 tax deductible). Lifetime Subscriber: 
$1000 ($800 tax deductible). Corporate 
Subscriber: $S00/year ($400 tax deductible, 
receives five one-year subscriptions). 

Contributing Subscribers: Thomas H. 
Grohne, G. V. Elkins, Robert M. Connors, 
William J. McEown, Robert C. Luckey, 
Robert N. Stabler, DeWitt S. Brown, John 
B. Palmer, Burks A. Smith, Transdata Cor¬ 
poration, Mark Ketter, John W. Campbell, 
Friden Mailing Equipment, Howard E. 
Decker, Jim Wilson, Frank Lawyer, Chris 
Pettus, Paul Lutus, Ben Goldfarb, Rodney 
Black, Steven Weiss, Pat Phelan, John 
Brodie, James Fleming, Unison World, 
Thomas Davis, Jan Steinman, Ronald E. 
Johnson, G. Hunter, Kenneth Drexler, Real 
Paquin, Ed Malin, John Saylor, Jr., Ted A. 
Reuss III. Sustaining Subscribers: Pete 
Roberts, Steven Fisher Enterprizes. Life¬ 
time Subscriber: Michael S. Zick. 

Foreign Distributors UK & Europe: 

Hofacker-Verlag, Tegernseer Strass 18, D- 
8150 Holzkirchen, West Germany. Asia & 
Australia: ASCII Publishing Co. Ltd, 4F 
Segawa Building 5-2-2, Jingumae, Shibuya- 
ku, Tokyo 150, Japan. 


Articles 


16 Small-C Compiler, v.2 

by J. E. Hendrix 

The C programming language is still gaining momentum as a powerful alternative 
to assembly language. The public domain Small-C compiler published in DDJ 
was clearly a good subset, but was still a bare-bones compiler. This article intro¬ 
duces the greatly improved Small-C version two. The last half of the program list¬ 
ing will be published next month. 


54 Interrupts and CP/M 

by Alan Bomberger 

The problems of “type ahead” under CP/M have kept more than one programmer 
awake at night looking for a better solution. Author Bomberger illustrates the use 
of interrupts to provide fully-buffered console input which can be used by CP/M 
when needed. 


58 A Simple Vector-Generation Algorithm 

by Marek W. Michalski 

Anyone writing graphics routines must confront vector generation head-on. 
This paper deals with graphics displays for eight-bit microprocessors. He has tried 
to find a fast, hardware-independent algorithm and provides an illustration of its 
implementation. 

60 Fifth-Generation Computers 

by Richard Grigonis 

What will be the next evolutionary step for computers? What should it be? This 
contributor from the forward-looking Children’s Television Workshop takes an 
educated look into technology’s crystal ball. . . 


Departments 

9 Letters 

10 Editorial 

Two Years Before the Masthead 

11 16-Bit Software Toolbox 

Custom character sets and lo-res color graphics for IBM’s PC; 
hex and binary conversion. 

62 Dr. Dobb's Clinic 

Small-C I/O redirection and command-line arguments. 

66 Of Interest 


Dr. Dobb’s Journal (USPS 307690) is published twelve times per year by People’s Computer 
Company, Box E, 1263 El Camino Real, Menlo Park, CA 94025. Second class postage paid at 
Menlo Park, California 94025 and additional entry points. Address correction requested. 
Postmaster: send form 3579 to Box E, Menlo Park, California 94025 • 415/323-3111 


4 


Dr. Dobb’s Journal, Number 74, December 1982 






LETTERS 


File Transfer Bugs 

Dear Dr. Dobbs: 

I recently acquired a new 8” disk sys¬ 
tem to replace the 5” drives I have been 
using, and after a friend helped me trans¬ 
fer all my programs from the old disks 
to the new ones using a modem program, 
one of us said, “What we need is a pro¬ 
gram that transfers the whole disk auto¬ 
matically, instead of one program at a 
time.” The next day, when the August 
DDJ came, there it was - the SEND/' 
RECEIVE file transfer utilities by 
Lawrence Hughes. 

Since I have been using the MFT pro¬ 
gram of Mr. Hughes for some time, and I 
am sure that the SEND/RECEIVE utili¬ 
ties will be useful in the future, I thought 
that now would be a good time to write a 
note of appreciation for these programs 
being made available. Thanks a lot to 
both Mr. Hughes and DDJ. 

I think there are a couple of errors in 
the listing for the SEND program, how¬ 
ever. At the end of the routine “send:” 
just before “sendO:” there should be a 
“jmp send8” statement. Without this 
statement, the program tells you that no 
files were found, and then tries to send 
them anyway instead of aborting. 

The other error appears in the 
“send7” routine where the following 
code appears: 

deer m 
jmp sendO 
jmp sendx 

Obviously the second jump would 
never be executed. I believe that the 
first jump should be: 

jnz sendO 

As written, it appears to me that the pro¬ 
gram would continue to try to send files 
forever. 

Perhaps Mr. Hughes could comment 
on the correctness of these observations, 
as I have not really tested the program 
yet. 

Sincerely, 

Robert Wilcox 
920 N. Washington St. 
Owosso, MI 48867 

Issuing Forth 

People: 

My first issue of DDJ just came 
yesterday. I was delighted to find that 
you had a feature on Forth (issue #71). 

You have quite an impressive maga¬ 


zine — I should have gotten a subscrip¬ 
tion long ago. 

Regards, 

Dr. Alan D. Wilcox 
12211 Westwood Hills Dr. 
Herndon, VA 22071 


Sundries 

Marlin Ouverson, 

I’m in agreement with the public do¬ 
main principle. I think human progress is 
too important to be hampered by the in¬ 
efficiency of too much private (secret) 
enterprise. Luckily, the vast quantity of 
software should reduce its own price 
rapidly, just by virtue of there being so 
much. Though my agreement is largely 
political-style, I am also currently inter¬ 
ested in electronics and computers. 

The problem for me is that comput¬ 
ers are very complicated, as I discovered 
when at a store called Puter-Parts here in 
Seattle. The owner took a lot of time to 
help me program an EPROM 1 bought 
there at a reasonable price. I was really 
happy about his concept of thoroughly 
aiding even small customers, but embar¬ 
rassed by my inability to understand Z80 
machine language even by studying quite 
hard. There’s a krillion things you have to 
know! I wish him, and others who bring 
their knowledge into the public domain, 
success. 

Politically, I see the “vision” that 
there are gigantic benefits for all in the 
world when technology develops answers 
to social problems — the way technology 
can achieve those answers is by people 
knowing it and inventing the solutions. 

Thanks again for maintaining the hu¬ 
manitarian public-domain principle; 
when my ZX81 comes (if it ever does!) 
I’ll write you and tell the tricks and diffi¬ 
culties others might find useful. 

Sincerely, 

Jack Scott 
3 Enatai Drive 
Bellevue, WA 98004 


About JRT Pascal 

10-15-82 

Editor: 

You asked me to reply to the very 
critical and insulting Software Review of 
JRT Pascal by D. Cortesi in the Novem¬ 
ber DDJ. 

The hundreds of complimentary let¬ 
ters and Thank You notes I have received 
and the outstanding reviews published in 



Infoworld, Interface Age, and Creative 
Computing reflect the opinion of the 
overwhelming majority of JRT Pascal 
users. 

J RT Systems will do no further busi¬ 
ness with the People’s Computer Com¬ 
pany. 

James R. Tyson 
JRT Systems, Inc. 

P.O. Box 22365 
San Francisco, CA 94122 
P.S.: Please do not edit this reply. 

Editor's note: The following are the only 
two letters we have received (as of our 
deadline for this issue) which mention 
JR T Pascal. Both were received after our 
review of that product was completed but 
before the issue containing it was mailed; 
hence they did not affect our review, nor 
vice versa. 

Dr. Dobb’s Clinic 
Dear Mr. Cortesi: 

Since you are scraping the bottom of 
your mailbag, I would like to contribute 
the following complaint. 

The Pascal system that JRT Systems 
have been heavily promoting for the past 
several months for $29.95 is highly over¬ 
priced. By how much? Exactly $29.95. 
Why? JRT Pascal is unable to correctly 
multiply floating-point numbers in the 
form X.Y * 0.0, giving answers of X.Y 
instead of 0.0, as the enclosed listing re¬ 
veals. 

Sincerely, 

Andrew Omori 
4009 Chandler Blvd. 

Burbank, CA 91505 

(See listing page 70) 


Dear Dr. Dobb’s Chnic: 

I have an array of problems, discov¬ 
eries and hypotheses that I would like to 
air and see what returns. I should begin 
by saying that my system is a Z-80 CP/M 
system. It’s a single-board system with a 
Scull-Tek circuit board from Romac Com¬ 
puter Equipment of Naperville, Illinois. 
My problems revolve around two soft¬ 
ware products: JRT Pascal from JRT 
Systems (advertised in Dr. Dobb’s) and 
DDT from Digital Research. I should 
hasten to say that I am not convinced 
these products are at fault for my prob¬ 
lems. 

(Continued on page 70) 


Dr. Dobb’s Journal, Number 74, December 1982 


9 

513 



EDITORIAL 


Two Years Before the Masthead 


Nearly three years ago, Ron Cain used these pages 
to place a Small-C compiler in the public domain. It was 
many people’s introduction to C as such a reasonable alter¬ 
native to assembly language. Since then we have published 
many letters and articles detailing bug fixes, patches, and 
extensions — but mostly praise — for the compiler. 

DDJ is pleased to present in this issue a new version of 
the Small-C compiler. J. E. Hendrix developed it with the 
support of Ron Cain and a number of other DDJ subscrib¬ 
ers. Code written under version one should be compilable 
by this one; both are upwardly compatible with full C. By 
perusing the listing (which will be continued next month) 
and its accompanying article, many of you will note how 
Small-C has grown - but it is faster, too, and the programs 
it produces typically are smaller than previously. 

* * * 

This is the last issue for which I will serve as Dr. Dobb’s 
editor. Any regret at my decision to leave this post is tem¬ 
pered by pleasant recollections of my past two years in as¬ 
sociation with the best minds and friendliest people in 
microcomputing. 1 was hired half-willingly for an editorial 
position which I imagined would be as sterile as the silicon 
laboratories not far from our offices. What I found was just 
the opposite, a loose-knit clan of idealists, hackers, and 
professionals, brought together by their mutual drive to see 
powerful computers and software tools available to the 
average person. It has been a greater pleasure to work with 
them than I could have hoped for. 

Dr. Dobb’s Journal is very different from any other 
microcomputer publication, because of the extent of its 
commitment to the readers. DDJ has never been content to 
rest on the laurels of its considerable reputation, or to fill 
its pages with middle-of-the-road articles. Nor do we at¬ 
tempt to tell our readers what is important. We only pro¬ 
vide space where people and facts can speak for themselves. 
That sounds simple enough, but it became apparent very 
early during my stay here that the job would not be an easy 
one. 

Doc’s editor faces an enormous task, only part of 
which consists of filing through a bushel of press releases 
each month, digging elsewhere for as-yet-unannounced 
items, proofreading and more proofreading, all while seek¬ 
ing good programmers willing to put the fruit of their 
labors into the public domain. Fortunately, the DDJ read¬ 
ership itself is the best source of technical support and 
microcomputer expertise any editor could ask for. It is 
that, and not the sole efforts of any single individual, which 
provides the continuously high-quality contents. 

* * * 

Some exciting items already are planned for the next 
several issues. DDJ will be publishing Augusta, an Ada 


subset, in four installments. Ada (the name is a trademark 
of the U.S. Department of Defense) is going to be making 
some big waves, but the DoD has resisted approving any 
subsets of the language. The size of the full implementation 
causes most micros to shrivel with anxiety, so this will be 
your opportunity to get a head start at learning the lan¬ 
guage. Programs written in Augusta will be needed in DDJ, 
so don’t waste any time getting it up and running on your 
machines. 

The far-seeing people at Project Xanadu have some 
material lined up for Doc Dobb’s, too. In any dry season, 
the sparks of their creativity are sure to set brushfires in 
all directions. Those folks are bent on proving that no mat¬ 
ter how big the dream, it can be coded and installed on a 
computer. Keep an eye on their work — it’s fascinating. 

The DDJ colony of contributing columnists is lining 
up even more useful routines, bug fixes, patches and puzzle¬ 
ments for the coming year. The 16-bit Software Toolbox 
will continue providing useful routines for the 8086/88 and 
will add material for other processors, especially the 68000 
(and, if enough readers clamor for it, the Z-8000). The 
CP/M Exchange will still be promoting telecommunications 
and the RCP/M approach to downloading software, but will 
branch out to answer general questions and to provide tips 
about CP/M. The Clinic will keep titillating readers with its 
eclectic assortment of algorithms and other oddments. 

* * * 

We who have had some degree of involvement with 
DDJ and People’s Computer Company (PCC) modestly 
think of this publication as the lever which, with the slight¬ 
est degree of pressure, just might move the world a bit. 
By serving the high end of the technological spectrum, 
some of our efforts do find their way by mysterious means 
into products and services which help people. This happens 
when one of our readers who sees the true potential of 
computers, and some piece of software we publish, puts 
them together in new ways. 

Dr. Dobb's Journal is primed and ready for what the 
future brings. Microcomputers’ potential for humanitarian 
use is just beginning to be tapped in educational and re¬ 
creational settings, health care facilities, work environments 
and the home. More important, the old view of computers 
as untouchable pawns of the world’s power merchants has 
been replaced by the knowledge that they are only ma¬ 
chines, tools as accessible as any other, designed to serve 
people and, hopefully, to improve the quality of everyday 
life. 

Happy computing. 


- Marlin Ouverson 


10 

514 


Dr. Dobb’s Journal, Number 74, December 1982 




16-BIT SOFTWARE TOOLBOX 


by Ray Duncan 


Concerning Column Topics 

Several readers have already written 
to ask why “excessive” attention is being 
devoted to the Intel 8086/8088/8087 
microprocessor family. The main reason 
may be seen in Table 1, i.e., the Intel line 
has an overwhelming predominance of 
the 16-bit user base. The secondary rea¬ 
son, not unrelated to the first, is that 
until now most Z8000 and 68000 sys¬ 
tems sold have been expensive, integrated 
packages with proprietary software and 
not appropriate for the personal comput¬ 
ing market. These drawbacks are going to 
disappear rapidly for the 68000 as Cro- 
memco and Godbout begin to ship their 
new S-100 bus, 68000-based CPU boards 
and as Digital Research CP/M-68K be¬ 
comes widely available. I personally feel 
that time has already passed by the 
Z8000, mainly due to poor marketing 
strategy on the part of Zilog, but I 
would be very interested to hear counter¬ 
arguments. 

Custom Character Sets for the 
IBM PC 

Most owners of the IBM Personal 
Computer have heard rumors that its 
operating system permits installation of a 
user-defined character set for the video 
display. Like many of the other sophis¬ 
ticated features of the PC, this capability 
is alluded to here and there throughout 
the IBM Technical Manual but the pro¬ 
cedure is not spelled out in detail. In this 
column, I will explain the exact steps to 
follow to create a new video character 
font. I hope that, in return, readers will 
use these techniques to implement some 
useful collections of symbols and contrib¬ 
ute them back into the public domain via 
DDJ. 

Software-defined character sets can 
only be displayed using the color/graphics 
interface board in “graphics” mode. This 
is because the ASCII character codes are 
translated by software into bit patterns 
written directly into the video memory 
map. In contrast, when using the mono¬ 
chrome video interface or the color/ 
graphics display in “text mode,” the 
ASCII codes themselves are stored into 
the video memory buffer and are con¬ 
verted by the hardware into a pixel array 
according to the contents of a character 
generator PROM. Consequently, there is 
no way while in text mode for the user 
to affect the shape of a given character 
except by burning a new PROM and 
soldering it onto the interface board (not 


Di. Dobb’s Journal, Number 74, December 1982 


an approach that I would recommend). 

When the color board is in graphics 
mode, and the video driver is called with 
an ASCII character code to be displayed, 
it uses that code as an index into a bit 
table that is stored in memory. A text 
character is displayed as an 8 by 8 matrix, 
so each ASCII code corresponds to eight 
bytes in the table. The eight bits of each 
byte are equivalent to a horizontal line of 
eight pixels, the most significant bit cor¬ 
responds to the leftmost pixel of a group 
and the least significant bit to the right¬ 
most pixel. The byte with the lowest 
memory address corresponds to the top 
scan line of a character, and so forth to 
the eighth byte of a set (with the highest 
address) which maps onto the bottom 
scan line of the character. Some fancy 
conversion occurs when text is displayed 
in color graphics mode, where each pixel 
is two bits, but that need not concern us 
here since it is handled automatically by 
the resident routines. 

The bit table for the first 128 ASCII 
codes (00-7FH) is present as part of the 
ROM software of the PC, starting at ad¬ 
dress F000:FA6EH (FFA6EH). The dis¬ 
play patterns for these characters cannot 
be modified. However, IBM has left the 
upper 128 ASCII codes (80-FFH) vacant 
and the user can define these by creating 
a supplementary bit table. A dedicated 
pointer location in lower memory has 
also been provided so that you can tell 
the operating system’s video driver where 
to find your special bit map. Then the ap¬ 
plication software can switch back and 
forth between IBM’s character set and a 
custom character set simply by toggling 
the most significant bit of the ASCII 
mode. 

The general steps that must be fol¬ 
lowed to install a new character set are: 

1. Sit down with pencil, graph paper, 
and a bit eraser, and diagram out each of 
your desired characters in an eight by 
eight matrix (see Figure 1). Note that the 
IBM character set uses the bottom row 
and rightmost two columns of pixels as 
spacing; it’s a good idea to follow this 
convention so that the display will ap¬ 
pear uniform. 

2. Convert each of the character 
grids into the equivalent bit pattern, and 
thence into eight bytes of data (see Fig¬ 
ure 2). 

3. Assign each character to an ASCII 
code between 128 (80H)and 255 (0FFH), 
then insert the eight bytes for that char¬ 


acter into a table. Calculate the table 
starting address for a given character 
code as follows: 

Table offset = (ASCII code - 1 28)*8 

4. Using DEBUG, enter the complet¬ 
ed table (1024 bytes) into RAM, then 
write it into a disk file for safekeeping. 

5. So that it can be used by an ap¬ 
plication to generate a video display, get 
the bit table into RAM at a location that 
will not be destroyed by other programs 
(don’t get exasperated, I’m going to give 
you a way to do this). 

6. Place the offset address of your 
bit table in the location 0000.007CH 
(0007CH), and the segment address of 
the table into 0000:007EH (0007EH). 
This is referenced by the PC’s video 
driver when it needs to display an ASCII 
code in the range 80-0FFH. 

At first glance, step 5 above looks 
most difficult by far. However, reading 
the fine print in the DOS manual, we 
find that a facility is provided (using in¬ 
terrupt service 27H) to let a program ter¬ 
minate without freeing up its memory for 
use by subsequent programs. Thus, all 
we need is a little utility that will read 
a specified character generator bit table 
from a disk file into RAM, patch the 
dedicated vector location to point to the 
table, and notify the operating system as 
it exits that the memory containing the 
table must be reserved from use by other 
programs. The code for this utility, 
named “CLINK,” is provided in Listing 
# 1 . 

CLINK expects the user to supply 
the name of the character table file in the 
original command line, so that the de¬ 
fault file control block is properly set up 
by the operating system before CLINK 
begins executing. First the program tries 
to open the character file, and exits with 
an error message if the file does not exist. 
Next the bit table is read into an internal 
buffer; the file is expected to contain the 
full 1024 bytes even if you are not using 
all of the character codes. Finally, the 
operating system link address is set to 
point to the table buffer, the program dis¬ 
plays a success message, and then per¬ 
forms the special exit back to PC-DOS. 
The net amount of memory made un¬ 
available for use by other programs is 
about 1400 bytes. 

You will probably find it quickest to 
create the CLINK.COM file by entering 


11 

515 




the object code directly with DEBUG, 
therefore I have outlined the necessary 
steps in Listing #2. Once CLINK is in¬ 
stalled, loading a character table from 
disk into RAM and linking it to the oper¬ 
ating system is quite simple. For exam¬ 
ple: 

A>CLINK RUSSIAN.CHR 

character table loaded and linked. 

A > 

User Groups 

Joseph Boykin responded almost in¬ 
stantaneously to the first appearance of 
this column by advising us of the forma¬ 
tion of the Seattle Computer Products 
Users’ Group, which is intended to pro¬ 
mote sharing of knowledge and software 
between users of 8086/MS-DOS SCP 
microcomputers. The group intends to 
provide a dial-up bulletin board, diskettes 
of public domain software, and a periodic 
newsletter. Membership dues are stated to 
be $10.00 per year. For more informa¬ 
tion contact Frank Warren, 25190 
Cypress Ave. #213, Hayward, CA 94544. 

Other User Groups for 16-bit micro¬ 
computers are also invited to make their 
existence known by sending information 
to me c/o DDJ. 

Hex and Binary Interconversion 

Robert Blair of Walnut, California 
sent in a nice set of subroutines for Intel 
8086/88 that will allow conversion of an 
8-bit binary value into a hex ASCII string 
and vice versa (see Listing #3 and #4). 
This code will be very useful for display 
of data in debugger programs, disk file 
utilities, and the like. Such contributions 
really warm my heart. Please keep the 
listings coming! 

IBM PC Low-Res Color Graphics 

The following is reproduced verbatim 
from another windfall that arrived cour¬ 
tesy of John J. Seal of Franklin, Indiana. 

“On page 2-52 of the IBM PC Tech¬ 
nical Reference Manual is described a 
low-resolution 160 x 100 16-color graph¬ 
ics mode. This mode can be used to 
create graphics in which all 16 available 
colors are displayable simultaneously, as 
they are in text modes. Unfortunately, 
this mode is not supported by BASIC or 
by the character generators in the BIOS. 
The manual cryptically states that it 
‘requires a special memory map and set 
up to be defined later.’ 


“This is how it is done: 

“1. The 160 x 100 ‘graphics’ mode is 
actually a text mode! Set up the Color 
Graphics adaptor for 80 x 25 alpha color 
mode (not 40 x 25 as stated on page 2- 
59). 

“2. Set all the Character Codes (CC) 
in the display buffer to 0DEH. This char¬ 
acter is split vertically with ‘background’ 
on the left and ‘foreground’ on the right, 
thus giving 160 half characters across the 
width of the screen. 

“3. Set the 6845 CRT Controller to 
only display one-fourth of each row, i.e. 
two scan lines, but to display four times 
as many rows. This gives 100 quarter- 
characters from top to bottom. 

“4. The color of each pixel is con¬ 
trolled by the attribute bytes (AT) in the 



display buffer, two pixels per byte, just as 
in text mode. The high nibble specifies 
I,R,G,B for the background (left half) 
and the low nibble specifies I,R,G,B for 
the foreground (right half). 


“From this we can see that ‘special 
set up’ means selecting a non-standard 
text mode and ‘special memory map’ 
means presetting all the character codes 
in the display buffer. The ‘8000 byte 
Read/Write memory’ mentioned on page 
2-52 consists of all the odd-numbered 
bytes from B8000H to BBFFFH.” 

Mr. Seal also included a BASIC pro¬ 
gram (see Listing #5) which demon¬ 
strates how to set up the 160 x 100 16- 
color graphics mode, and a function for 
computing offsets into a display buffer 
based on X and Y coordinates. 


Bit pattern for character “A” from 
Figure 1: 

0 0 1 1 0 0 0 0 

0 11110 0 0 
110 0 110 0 
1 10 0 110 0 

1111110 0 
1 10 0 110 0 

1 10 0 110 0 

00000000 

which translates to the following eight 
data bytes which are inserted into the 
character table: 

30 H 
78 H 
CC H 
CC H 
FC H 
CC H 
CC H 
00 H 

Figure 2. 

Mapping the pattern shown in Figure 1 
into a set of eight data bytes for the 
character table. 


12 

516 


Dr. Dobb’s Journal, Number 74, December 1982 











Microprocessor 

Units 

% of market 

Intel 8086/88 

718,000 


78% 

Motorola 68000 

139,000 


15% 

Zilog Z-8000 

61,000 


7% 

Table 1. 



1981 Sales of various 16 

bit 

microprocessors. 



Highly Recommended Software 

One of the most pleasant surprises of 
the year is “PC-TALK,” a telecommunica¬ 
tions program for the IBM Personal Com¬ 
puter by Andrew Fluegelman. PC-TALK 
is written in BASIC and is designed for 
use with the Hayes Smartmodem, though 
it can easily be used with other direct - 
connect or acoustic modems too. The 
program is slick, friendly, reliable, and 
completely self-documenting via well- 
designed menus and on-line help files. 
Support is provided for automatic dialing, 
customized function key definitions, 
Compu-Serve and Source special proto¬ 
cols, and uploading/downloading of files. 
PC-TALK is a quantum leap in quality 
over the IBM Asynchronous Communica¬ 
tions Program. Distribution of the pro¬ 
gram is based on a novel concept called 
“Freeware,” wherein the user has the 
right to freely copy the program and pass 
it on. Send $25 to The Headlands Press 
Inc., P.O. Box 862, Tiburon, CA 94920. 

(Listing begins on page 14) 


Dr. Dobb’s Journal, Number 74, December 1982 


13 

517 









o 

•o 


5 £ 






~ S 


z 

w 

IL 

5 

0) 

X 

a C 

u 

4* 

w 

z 







8 £ 


; s ^ **» « 


S 2 S 


§§§§§l§8i§8 


s s 



'O 

g g 


CN 

s 


c 

•H 00 

-J fN 


<1 

U 

l/l * 
6 i/l 
QJ Qi 

£ r-, 

l/l Qi 
X 0» 
l/l c 
o <i 
L 

U l/l 


0i 

L 

TJ 
Ql Ql 
cn m 

t *+• 

L Ql 
L C 


£ 

o 

o 


cn g 

L Q CN 

r u 

*4- U - 

Ql Q 

X * 


£ 1 L 

L £ 


U U Ql 

6 Ql 


it Q. £ 

£ Ql 

£ 

L £ 

* L 

U 

It L Ql 

L £ 

in 

£ Ql £ 

o cn 

GMO 

U £ a 

£ 

G « 

C Ql 

!fl C 


.* 3 cn 

-J Ql 



o 

W) 

C3 


c 

O 

C/3 

*3) 

o> 

jO 

<D 

H 


Ql X 
^ Ql OI 

£ o» 0 / cn 

- A 111 L 

£ a u 0 


■ u 
i n 


v r 

c co 


c co c 
m *-• o 

£ L l/l 
* 0 L 
0 H- Ql 

-I ~ Z> 


0) 

c 

o 

O) 

c 

■Hi 

+* 

(0 


c 

Qi 

6 

cn 

Qi 

l/l 


_ Ql 
t £ 
~ l/l 
£ 

H Ql 

c ai 

•* L 


n 

U Ql 


3 

<t . 

* L 
Ql 01 
"O r 
U 

0» 

& c c 

U h qi 

* s & 

£••>•» 
Ql 
l/l 




L 

a 

Ql 

» cn 
■o <t 
Qi l/l 

PI l/l 


•* •* It 
It 

-* * -X 

u a c 
Qi 6 h 
£ 3 
u n 
•»••>£ 

Ql 

l/l 


I 

£ 5 


cn 

s 

i 

u 

£ CL 

x 0 
Ql £ 

C -x 
Ql U 
£ >t 
A £ 


Ql 

CP 

ID 

l/l 

l/l 


£ 

C 

it 

« n 


x l/l i/l x 

t £ Q| TJ 


in H- 

~ t J£ 0 l> o 

•> c *r 

■C r* >-• 'H x £ »i £ »h 

* cn t h 3 it cn <t CN 


^ £ L 
3 £ A 

A A £ U 
U Ql 1 h- it 

U1 CN 


Ql Ql <-• Qi 

l/l l/l * l/l 

*4» s*. n H» 

^ <i A X H- 

0 CN 0 £ o 

•> »£ ► 

x £ ~ x «r x 

£ t (N £ -h TD 


0 

a Ql 

0 £ 
A It 
A 
L 

0 . 
A L 
U It 

Qi £ 

> U 

cn t 

a q, 

c 

A 

Qi 0 
l/l A 


O 

CN 

► £ 
£ ~ 

<t CN 


0 O' 

- * £ 
X £ -h 


N X 

G it 


C 

I H* 

f 1 

l/l u 1 

X 

— Ifl A 
0/ 

» l/l 

l-l 

l/l X H- 
U £ Q r 


X X l/l X 


"O m CN £ it £ (0 CN 1 u 


> 

- 0 
C £ 
it A 
U Ql 
C Ql 
3 00 

Q 

rs 

X <f 

It -H 

CL <t 


3 3 3 
cr cr cr 
QJ Qi Qi 


£ 

U L H- 
' H- U ~ 


> > > > > A > > A > a 

§222 2 c ri N 22 c ° c 

e 6 « e 6 •* 0 -n 6 6 * f -* 


U 

o 


OOCOOOOCOO 

66-eees-gs 


oocbocofeo 


_ > > > > 
i i i s i 


G 

G 



CD CD G U 

L. -« G 00 


uQuin 

OCIUG 


U U UJ <1 

<T Q Q 

U Q <1 

in g g 

CO CO CD CO 

fflUON 

G G G 

O CN * *0 

O' III Q LL 

GOG 

G G O G 

G G G G 





O G O O 

O O O G 


G 

O 

oh 



Q-UNUff hOO'hUOCD 
^CNin«rin~CN>0GCNNu2 
JQfflMIifQdifOahS 
CDUOQUCniIiUCOCOUOQK)S 

b -r£;P? lUJ O{Ninrvt>UUJO(Nin0D 

^cNCNCNCNCNfnnnminflM**!*!? 

GGGGGGGGGGOGOOOOG 


l/l 

l/l 

Qi 

^ ♦* 

2 c 

2 * • 

t A £ 

x in 

U) Ql Q( 

Zv L 
oS • 

^ 6 A 

■»J It CN £ 

c L O 

■S?V? 

a l 4- « 
, a 3 > 
| £ it 

0 H» U Ql 
CO F» 
•« •» A .» 

Qi 

i/l 


0 

»£ 
X N 
T3 (N 


> £ 

8.5 


in 

G 

>0 N 

m cn 

<1 Q 
CO u 

<t Q 

* ^ 

G O 


Qi 

£ 


£ 

TJ 


r> o cn 
N O S 
o >0 <r 
CN >0 CN <0 
U. G <1 GO 
N 3 CN O 3 
UJ CD Q n 

<1 oo < 

<i no in 3 

S3£S 

O N N) o 

* ? 

o o 


14 

518 


Dr. Dobb’s Journal, Number 74, December 1982 








- £ 

A) 

£ 


ui 

u 

r 

a 

* 

L 

□» 


0 

u 

I 

O 


•fl 

£ 

a 


ft 

CN 


O L 
CD U 
fl 
a 

3 L 
TJ 

4J Ol 
01 - 
I/I u 


i fe 

• a 

i 

: i fl 
: -< v 
. ph o 
. 0 V 


V rt H H 

S U <fl u 

u u u 

I U X X -X 

I V w 

It k U 

I u > > > 


T3 -x 
Ol I/I 
>* 0 

fl a 

a u 
i/i c 

•X > 

•o I/I 


in Hi fl 

Oi E i/i L 

l gi Oi 

? m 

•flu 

L r-. Ifl u 

Ol Oi L <fl Oi <fl 

C 4- Ol -x a >—i 

•h *4- a u 3 a 

H 3 U 9lD 

ft <fl a h o 

C L l/l L V 

fl > fl 

U <fl ft 0 -ft 4J 

I/I ^ u -ft <0 Ol 

a i/i 

X it) i—i 4J i—< m 
fl -x -x Ol — L 

8 ft fl i/i «fl a 


: £ a* £ ^ 


CO K CO ^ CD U J u! S S « U 

sssssisiiiiiii 


Q) 0) 
0) 


(A 

fl) 


> 

il 

o> 


o .2 


ft 

A 


a <r o 
rs ^ n 
ill 


a 

w 

ft 

cn 



3 

G 


ft 

*6 

4 4 

_ 

UJ x 

a 


C 



GO 


Q 


« * 


a a 

a 



> 

0 



K) 

M 

N' N* 


a z 

a 

ft 



i/l 

I 


I 

Q 

Q Q Q 


K» 

X 

V 

X 

QJ 

ft 


* 




I •• 

P 

a 

0l 

X 


Q 


II 

ft 

ft ft 

ft 

G 4 

4 

z 

l/l 



•x (/) 


N 

D 

p 3 

3 

g a 



4- 

X 

3 

3 -1 


Q 

O 

o o 

O 00 □ Q 

□ 

•> 

H- 

ft 

5 

U 

0* 





m ft i 

ft 


0 

a 


•• 






i 4 


G 


cn 


•• 

GO 





4 0- 

»-< 

V. 

QJ 

a 

a 

G 

Q 



>o rs 

O 

II II N 

II 


+■» 

a 


8 000000000000000000000 
-NMflft^NBIhO-NK^ft'ONfflO'OH 


E 

cd 

ft 

IJD 


0) 


tlD d> *H 

C TD +-> 
•HOC 
£ C 0) 
ft 

>J ft ft 

ft o o 

d) d) <*-» 

> -r-3 

d> & x: 

O ft 

d> c 
N ft O 
•H d) <H 
•H ft 
01 C O 
•H d) CO 
ft 

•H £ T3 
C O C 
•H c (d 


— tuO 

^ c 

O d) 
O rH 


i—1 T3 
•H C 
ft id 

PiX 
P CQ 


G G * U Q 

CN CN -0 *0 G 

CN ft ft G ^ 

N-fl'ON'O 
ft U «■ <T ft 

>0 >0 >0 >0 >0 

<r cn uj a 

N >0 >0 >0 >0 

n ~ a - a • 

'O'O'O'OOI 
- <T U G O' <1 
•fl N <1 (N >0 G 

CN 

fs 


J c 

I CN 


a 

UJ 

9 

z 

5 

z 


a 

E 


cn 

<l 


O 

o 

> 

8 



i/i 


0) 

h. 

o 

■ 

> 

I- 

3 

G 



Oi 

a 

> 

a 

X 

H 

* 

z 

O) 

c 

K> OO 

OOI 1 

K. COM 


8 

o 

Ul 

z 

O) 

c 


■■■ 

(/) 

EBUG 
lOO 
lOO 
B: Ol 

2 

a x 
u a 

oooo 

0 

cx 

0000 

0 

ting 

z 

to 

o 

■ M 

Q Q 

a a a *• 

<r i i g i 

z a 

i i i 

G 
x —• 

a •• 

G x 

a x - 3 ft 0 A 

1 U .. 1 3 1 d 

5 

■ M 


£ ~ 

!Sl: 


Dr. Dobb’s Journal, Number 74, December 1982 


15 

519 


(Continued on top of page 14) I End Listing 




Small-C Compiler, v.2 


R on Cain stirred up considerable interest when he de¬ 
monstrated ( DDJ #45) how effective even a small 
compiler can be. Many people were inspired to adapt 
his compiler to their systems. My own implementation result¬ 
ed in Small-VM (DDJ # 61) which interfaces the compiler, and 
programs compiled by it, to North Star DOS. The Small-Shell 
command processor (DDJ #63) further enhanced this environ¬ 
ment, giving it even more of a UNIX flavor. 

I immediately used the compiler to create a set of utility 
programs based on the ones presented in the book Software 
Tools by B. W. Kernighan and P. J. Plauger. The original Small- 
C compiler was more than adequate for the task and clearly 
superior to the RATFOR language used in the book. But it 
was a bare-bones compiler, literally begging for improvement. 
It seemed, too, that a little effort devoted to code optimizing 
might yield valuable benefits. So, with encouragement from 
Ron Cain and the Doctor, I set out to produce a second ver¬ 
sion. Listing # 1 contains the results. 

I am in debt to Ron Cain, who presented the original com¬ 
piler for all to do with as they pleased and who provided much 
invaluable guidance for this project. In addition, Neal Block 
(P.O. Box 8829, Fountain Valley, CA 92708) was also very 
helpful by providing many specific suggestions relating to per¬ 
formance, generalizing the computer for use on machines of 
various word lengths, and approaches to implementing the new 
control structures. I hope before long to see him come forth 
with an assembler and linking loader written especially for 
Small-C. Finally, Dr. James Van Zandt (26 Shelton St., 
Nashua, NH 03062) suggested replacing the serial table 
searches with hash searches for greatly improved speed. 

Differences 

This version of the compiler differs from the original one 
in the following respects: 

1. Code optimization has been added. Programs are now 
typically 15 to 30 percent smaller than before. 

2. Data initialization is supported for global variables, arrays, 
and pointers. Uninitialized objects default to binary zero. 

3. Constant expressions are now evaluated at compile time. 
They may also be used as array dimensions, data initializers, 
and in “case” statements. 

4. The #ifdef, #ifndef, #else, and #endif statements are 
supported with nesting. 

5. The “extern” storage class is supported for global variable, 
array pointer, and function declarations. The effect is to de¬ 
clare them as external references to the assembler. 

6. A mechanism for passing an argument count to called 
functions is provided. 

7. The following new statements are now supported: 

a. for 

b. do/while 

c. switch/case/default 

d. goto 

by J. E. Hendrix 

Copyright © 1982 by J. E. Hendrix, Rt. 1, Box 74-B-l, 
Oxford, MS 38655. 


8. Lists of expressions are now premitted. 

9. The assignment operators |=, A =, &=, +=, -=, *=, /=, %=, 
»=, and «= are now supported. 

10. The logical operators || and && are supported. Testing 
proceeds left to right and ceases when the outcome is known. 

11. The operators ~ and ! are now supported. 

12. Local variables are now local to the block rather than the 
whole function. 

13. The back-slash escape sequences for character and string 
constants have been added (per DDJ #56). 

14. Some changes were made to accommodate the require¬ 
ments and features of Small-VM and the assembler and loader 
which I use (Allen Ashley’s PDS macro assembler and linking 
loader). They may be easily removed or modified to meet the 
requirements of your particular environment. 

a. Lower-case names are converted to upper case before 
being placed into the symbol table. Lower-case and 
upper-case symbols are thus synonymous. This feature is 
optional. 

b. Header and trailer code is automatically added to the 
output, enabling multi-file programs to be compiled 
and assembled separately (see DDJ #61 for details). 

C. Tabs are no longer generated in the output file. This 
feature is optional. 

15. The original compiler would generate a cascade of spuri¬ 
ous error messages, following a proper one. These have been 
eliminated by snuffing all but the first one in a simple state¬ 
ment; in practice this works well, since one diagnostic is usual¬ 
ly enough to make one evaluate an entire simple statement. 

16. The following fixes have been applied: 

a. The left- and right-shift routines of the arithmetic and 
logical library have been modified so that a shift of zero 
bits properly returns the original value (DDJ #52, pg. 7). 

b. Arguments no longer have to be typed in the same 
order as they appear in the function header (DDJ #52, 
pg. 20). A flaw in this patch has been corrected (DDJ 
#56, pg. 6). 

c. In its original form, Small-C did not always properly 
scale values involved in address arithmetic. DDJ #62 de¬ 
scribes this problem and gives the solution. 

d. The function syname will no longer accept symbols 
longer than eight characters. 

e. The global integer lastst is now zeroed at the beginning 
of each function so null functions will always generate a 
return. 

f. Comments terminated by “*/” at the beginning of a 
line are now handled correctly (DDJ #56, pg. 6). 

17. Literals are now dumped at the end of each function, per¬ 
mitting a smaller literal queue. Globals are defined at the point 
of their declaration, eliminating the function dumpglb. 

18. An optional hash search may be used on the macro table 
and the global part of the symbol table. The improvement in 
speed is tremendous, but a 48K system will not simultaneous¬ 
ly support this and all the new language features. So the new 
language statements and the hash search feature are compile- 


16 

520 


Dr. Dobb’s Journal, Number 74, December 1982 




time options, allowing users to pick and choose which features 
they prefer to support. 

New Features Explained 

The following comments describe some of the new fea¬ 
tures in greater detail: 

1. Code Optimizing 

Machine-independent optimizing was done by changing 
the expression analyzer, and machine-dependent optimizing 
was done by including an optional output (peephole) opti¬ 
mizer. The following techniques were used in the first case: 

a. Expressions, or partial expressions, which result in a 
constant value generate only a single immediate load in¬ 
struction. 

b. After generating code for the right side of a binary 
operator, if the secondary register was not used, the pre¬ 
cautionary push/pop of the left-side value is changed to a 
swap. But if the left-side value is a constant it is loaded di¬ 
rectly into the secondary register instead. 

c. Constants being added to or subtracted from integer 
pointers or array names are doubled at compile time 
rather than execution time. 

d. No testing code is generated for “if(const),” 
“while(const),” and “for(. . .; const; . . .)” statements. 
The compiler does not bother to delete code controlled 
by these statements when const is zero since that situation 
is most likely a program error; the #ifdef and #ifndef 
should be used to eliminate conditional code at compile 
time. 

e. Tests against zero (e.g., “while(i >= 0),” “if(abc() == 
0),” etc.) result in special inline code which is smaller and 
faster than the standard procedure of loading zero, per¬ 
forming a library call, then testing the returned value for 
1 or 0. 

f. Zero subscripts generate no code for adding to the 
array address or pointer value. 

g. Local variables are allocated all at one time when the 
first executable statement in a block is encountered. De¬ 
clarations are not allowed after that point except within 
inner blocks. 

h. Unnecessary jumps around statements controlled by an 
“else” are avoided. This is the case when a “return” or 
“goto” precedes the “else.” 

i. The function modstk now generates two swaps to pre¬ 
serve the primary register only on a “return” with an ex¬ 
pression. 

Machine-dependent optimization is done by two func¬ 
tions — putstk and peephole. Putstk now generates MOV 
A,L/STAX D rather than CALL CCPCHAR. Peephole is the 
output optimizer mentioned earlier. A staging buffer is used to 
hold the code generated by an expression. When the buffer 
is flushed, peephole scrutinizes the output, making changes as 
it sees fit. The output optimizer is a compile-time option since 
some may view this as something better suited to a separate 
utility program. I found it irresistible, however, to piggyback 
this simple function on the compiler; it makes for faster and 
easier optimized compiles. 

Two techniques are employed by peephole. First, integers 


being fetched from the top of the stack are obtained with a 
POP H/PUSH H sequence rather than the usual LXI H,O/DAD 
SP/CALL CCGINT sequence. Integers next to the top of the 
stack are fetched with a POP B/POP H/PUSH H/PUSH B se¬ 
quence. If an XCHG follows the fetch sequence then the de¬ 
sired operand is popped directly into the DE register pair. 
These techniques result in smaller, faster code; they are al¬ 
ways effective if the compiler contains peephole. 

The second technique involves replacing commonly oc¬ 
curring sequences of commands with calls to new entry points 
in the run-time library (Listing 3). This technique reduces 
program size at the expense of speed; it must be requested at 
run time to be effective. 

2. Passing Argument Counts 

When a function is called, a count of the number of argu¬ 
ments being passed is placed in the accumulator. This takes 
only two bytes. To fetch the count, the called function sim¬ 
ply assigns to a variable the value returned by the function 
CCARGC (upper case). That must be done first in the function 
since other operations may call certain run-time library rou¬ 
tines which destroy the accumulator. CCARGC is a new entry 
point in the run-time library; it simply redefines CCSXT 
which moves A to HL sign extended. That allows 127 argu¬ 
ments before going berserk. For obvious reasons, the compiler 
will not generate code to load an argument count for calls 
to CCARGC. Since many programs will not use the argument 
count feature, the compiler will skip it in programs containing 
the statement “#define NOCCARGC” (upper case). That re¬ 
duces program size and run time. 

3. Data Initialization 

Global variables, array elements, and pointers may be 
initialized just as in full C, except that symbols may not be 
used as initializers. When not initialized, globals default to 
zero. An equal sign must introduce initializers. 

Constant expressions may be used to initialize variables or 
array elements only. If the size of an array is not given, it is 
determined by the number of initializers present. Character 
constants with back-slash escape sequences are permitted. 
When multiple initializers are present, they must be enclosed 
in braces and separated by commas. If too few initializers are 
given, trailing elements are set to zero. If too many are given, 
an error message is issued. 

A quoted character string may be used to initialize only 
chracter arrays and pointers. In this case, a terminating zero 
byte is automatically generated. An array name will reference 
the first byte and a pointer will contain the address of the first 
byte. If no array size is given, it will be set to the length of the 
string plus one. If the string is longer than the stated size, the 
size is increased to match the string. 

One negative side effect of the zero default is that very 
large arrays generate many “DB 0,0,0,. . .” or DW 0,0,0,. . .” 
statements in the output. If this proves to be a problem in 
practice, a run-time option could be set up to sidestep the 
zero default. 

4. Local Declarations 

The original compiler would accept local declarations any¬ 
where within a function; and duplicate declarations produced 
errors. This version requires local declarations to appear first 
within a block and permits multiple declarations of the same 


18 


Dr. Dobb’s Journal, Number 74, December 1982 

52T 




symbol. The local part of the symbol table is now searched in 
reverse order so as to see the latest occurrence of a variable 
first. Upon leaving a block, the non-lable declarations occur¬ 
ring within it are stripped from the symbol table. Local de¬ 
clarations may not contain initializers. 

5. Goto Statement 

This statement was included with some reluctance. I see 
no compelling need for it, and I shudder to think of how easily 
its abuse camouflages the logic of a program. There are occa¬ 
sional situations, however, where it can prevent code redun¬ 
dancy without obscuring the logic. I included the “goto” 
largely because it is expected and also because it can prove in¬ 
valuable when converting existing programs to Small-C. 

There is one restriction in the use of the “goto” state¬ 
ment. Since local variables may be declared within any block, 
the compiler cannot know the level of the stack pointer at 
target labels which have not yet been defined; so it cannot ad¬ 
just the stack pointer before the branch. Not being able to 
find an efficient method of solving this dilemma, I chose 
to make block-locals (other than at the start of a function) 
and “goto” statements mutually exclusive within a given func¬ 
tion. 

6. Extern Storage Class 

The “extern” storage class may be specified with global 
declarations only. If the LINK option (see "Installation” 
below) is effective, such objects are defined as external refer¬ 
ences to the assembler and other globals are defined as entry 
points. If LINK is not effective, “extern” globals are not de¬ 
fined to the assembler and other globals are defined, but not as 
entry points. If “int” or “char” is not specified following “ex¬ 
tern” then “int” is assumed. 

The Standard I/O Library 

Listing #2 is the source code for the standard I/O library 
which interfaces Small-C programs to Small-VM. These func¬ 
tions are used for ASCII character-stream operations. They 
were designed to mimic the full C standard I/O library func¬ 
tions as closely as possible. I strongly urge all Small-C imple¬ 
mentors to follow suit. 

This implementation uses a carriage-return/line-feed se¬ 
quence to terminate lines, and a hex FF for end of file. Natur¬ 
ally, you will need to change these functions to work with 
your file format. 

These functions, the arithmetic and logical library (Listing 
#3), and Small-VM are made known to Small-C programs by 
assembly language code found in either of the files stdio.h or 
stdiol.h (Listings #4 and #5). One of these must be selected 
for inclusion into a program at its beginning. If stdio is select¬ 
ed, the program will reference copies of these modules at fixed 
locations in memory. If stdiol is selected, then “local” copies 
of these modules will be loaded and linked together with the 
program. These files also contain “#define . . .” statements 
which give values for certain commonly used constants; e.g., 
EOF, ERR, stdin, etc. 

A brief description of the standard I/O library functions 
follows; 

• fgetc(fd) int fd; (alias getc) 

Returns the next sequential character from the file indi¬ 
cated by fd (EOF for end-of-file or error). A null character 


or a hex FF (actually any value <= 0) indicates end-of-file. 
Control-D is also taken for end-of-file; this is the means of 
terminating keyboard input. If the character is a DEL it is 
changed to a backspace. If fd is an I/O port, the character is 
echoed to fd (or stderr if fd is stdin). Backspaces are not 
echoed. Incoming line-feed characters are ignored. 

• getchar() 

Same as fgetc(stdin). 

• fgets(string, size, fd) char *string;int size, fd; 

Reads up to size minus one characters into memory, start¬ 
ing at string, from file fd. A carriage-return terminates the 
input and is replaced with a null byte. Returns string for suc¬ 
cess, else NULL for end-of-file or an error. If fd is an I/O 
port, fgets obtains characters by calling fgetc which handles 
echoing and changes DEL characters to backspaces. Backspace 
characters cause a rubout of the previous character (if any) in 
the string; this echoes a backspace/space/backspace sequence. 
If fd is a disk file, a single call to CCREAD obtains the entire 
string. A call is first made to CCDELIM (a new entry point in 
Small-VM not reported in DDJ #61); this causes CCREAD to 
stop after transferring a carriage-return character. This is much 
faster than calling CCREAD for every character one at a time. 

• fputc(c, fd) char c; int fd; (alias putc) 

Writes the character, c, to the specified file. Returns the 
character itself on success, else EOF. If c is a carriage-return, 
then a line-feed is appended. 

• putchar(c) char c; 

Same as fputc(c, stdout). 

• fputs(string, fd) char *string; int fd; 

Writes characters beginning at string to the specified file 
until a NULL byte is encountered. The NULL is not written 
and a newline is not appended. Returns NULL for success, else 
EOF. 

• puts(string) char *string; 

Same as fputs(string, stdout), but appends a newline 
(carriage-return/line-feed sequence) to the output. 

• fopen(name, mode) char *name, *mode; 

Attempts to open the file indicated by the null-terminated 
character string at name. Mode points to a single-byte string 
indicating the open mode: 

“r” — read only 

“w” — write only 

“u” — update (read/write) 

If successful, fopen returns the fd value for the open file; 
otherwise, NULL. 

• fclose(fd) int fd; 

Closes the specified file. If the file is open for write only, 
and if it is a disk file, a hex FF (end-of-file flag) is written 
before closing. 

• fflush(fd) int fd; 

Forces any system-buffered changes out to the file. This 
function consists of a jump to CCFLUSH in Small-VM. 


20 

522 


Dr. Dobb’s Journal, Number 74, December 1982 



• exit(errorcode) int errorcode; (alias abort) 

Closes all open files, displays errorcode on the console (if 
non-zero), and returns to DOS. This function consists of a 
jump to CCEXIT in Small-VM. 

• unlink(name) char *name; 

Deletes the named file. Returns NULL on success, else 
ERR. This function consists of a jump to CCPURGE in 
Small-VM. 

• getarg(argnbr, str, sz, argc, argv) 

char *str; int argnbr, sz, argc, *argv; 

Obtains the command-line argument indicated by argnbr, 
moves it to str of maximum size sz, and returns the size of the 
field obtained. Argc, and argv must be the same values provid¬ 
ed to the function main when the program is started. If argnbr 
is zero, the program name is obtained. If it is one, the first 
argument following the program name is obtained and so on. 
If no parameter corresponds to argnbr, getarg sets str null and 
returns EOF. 

The Auxiliary Library 

The auxiliary library (Listing #6) is a collection of func¬ 
tions which augment the standard I/O library. They may be 
selected individually for inclusion into programs at com¬ 
pile time, or they may be loaded and linked as a group. Their 
descriptions follow: 

• abs(nbr) int nbr; 

Returns the absolute value of nbr. 

• dtoi(str, nbr) char *str; int *nbr; 

Converts the (possibly) signed decimal number in the 
character string at str to an integer in nbr and returns the 
length of the numeric field found. Dtoi stops when it finds the 
end of the string or any illegal numeric character. At most, a 
leading sign and five digits will be used. 

• itod(nbr, str, sz) int nbr, sz;char *str; 

Converts nbr to a signed (if negative) character string at 
str. Sz indicates the length of the string. The value is right 
justified and blank filled in str. The sign and possibly high- 
order digits are truncated if sz is too small. Returns str. If sz is 
greater than zero, a null byte is placed at strfsz—1 ]. If sz is 
zero, a search for the first null byte following str locates the 
end of the string. If sz is less than zero, all sz characters of 
str are used, including the last one. 

• itou(nbr, str, sz) int nbr, sz; char *str; 

Converts nbr to an unsigned decimal character string at 
str. Itou works just like itod except that the high-order bit or 
nbr is taken for a magnitude bit resulting in values from 0 to 
65535. 

• itox(nbr, str, sz) int nbr, sz; char *str; 

Converts nbr to a hexadecimal character string at str. Sz 
indicates the length of the string. The result is right justified 
and blank filled in the destination string. High-order digits 
are truncated if sz is too small. Returns str. If sz is greater than 
zero, a null byte is placed at str[sz-l ]. If sz is zero, a search 
for the first null byte following str locates the end of the 
string. If sz is less than zero, all sz characters of str are used, 


inluding the last one. 

• left (str) char *str; 

Left adjusts the character string at str. Starting with the 
first non-blank character and proceeding through the null 
terminator, the string is moved to address str. To obtain the 
left-adjusted ASCII character string representing the decimal 
value of an integer, code: 

left (itod(nbr, str, sz)) 

• printf(str, argl, arg2, . . ., argn) char *str; 

Converts the arguments (argl, arg2, . . ., argn) to charac¬ 
ter strings according to specifications contained in the control 
string at str. Str is required, but argl through argn are option¬ 
al. Printf operates exactly as described in The C Programming 
Language except that only the d, x, c, s, and u specifications 
are supported. 

• sign(nbr) int nbr; 

Returns -1,0 or +1 depending on whether nbr is less than, 
equal to, or greater than zero. 

• strcmp(strl, str2) char *strl, *str2; 

Returns -1, 0 or +1 depending on whether the string at 
strl is less than, equal to, or greater than the string at str2. 
Character-by-character comparisons are made from left to 
right according to the numeric value of the character codes. 
The first unequal match terminates the compare. Only if every 
character in strl matches the corresponding character in str2 
is a zero returned. Strl is considered greater than str2 if str2 
is equal but shorter than strl and vice versa. 

• utoi(str, nbr) char *str; int *nbr; 

Converts the unsigned decimal number represented by the 
character string at str to an integer in nbr and returns the 
length of the numeric field found in str. Utoi stops when it 
encounters the end of the string or any nondecimal character. 
Five digits at most will be used. 

• xtoi(str, nbr) char *str; int *nbr; 

Converts the hexadecimal number in the character string 
at str to an integer in nbr and returns the length of the hexa¬ 
decimal field found in str. Xtoi stops when it encounters a 
non-hexadecimal digit in str. Four digits at most will be used. 

Invoking The Compiler 

Two methods of obtaining run-time parameters are pro¬ 
vided. If your environment supports UNIX-like command line 
argument passing, then the needed parameters may be picked 
off the command line. In this case, three types of parameters 
may be given — file names, redirection specifications, and 
switches. The operating system should handle redirection 
specifications without passing them on to the program. 

By default, Small-C obtains its input from the standard 
input file (stdin). If a list of file names is given on the com¬ 
mand line, then instead of reading stdin, it reads the named 
files in the order listed. Any non-switch parameter is taken for 
a file name. Output always goes to the standard output file 
(stdout). 

Switches are preceded by a hyphen. The “-m” switch al¬ 
lows one to monitor progress by having the compiler write 

(Continued on page 31) 


22 


Dr. Dobb’s Journal, Number 74, December 1 982 

523 



V. 


_ O to o 
o > E lO 

»-• Tt 


--rsjf»)5f l r>'Or^QOOvO — rvjrn 


x rsj 
<: — 
«d 5 cn 

C LU LU 

-• 2 2 


Z3 0) 0) 

a c c 

c -H 

<D 0) 

* * X O O 

X * * * -<k 


a a> ai 

+j c c 

D —< —• 

O V, H-. 

0) 0) 
★ * X O T3 

X * * % % 


c siar 

re — z ► 

co co x c 

® 2 2 2 C 

T3 TUUUC 

w l/) < < < « 

< 3 5 x : 

O X 

V. 0) & <D » 

<-> *- C C C t 

TO 0) -»H --4 

e "D **-• *♦-. **-« ^ 

V- Qj 4) 8) ( 

* * X -Q X O t 

x * * % * % * « 


i\ H tj xi Or~-00>0 — <*\j no *f iTl CD -V _ rvif 


til 1 y Cj 

-Jp < f-* rr r—« lu c 

•— r- X 2 S a. cc — (Ou. f— 
ti.itui:ioxcc2<ic 
-’■ixu< U j r^^uQc 
fX ^—• «—• H-• i—• t—• i—• f—* »—• h-« i—* h—• 

1010(0101010(0101010(01010 

ttfCDQJSJdJUjQjjijiQjj)., 

ccccccccccccc 

4j<ua;aj<u(U(ua)aja)a)ajaj 
‘ O X "O X X X X t) T) "D T] T) T3 

'O — r\jro^.oor--co>o — c\j <x 
■ o _n in o o o o o n n o <3 o -o 


******\.,h.^ * 

x******* % * 


o ® 

w c 

o o 


e 


o 

X 


o 


• 

•—4 


o 


X 

V- 


<u 

-0 


r 

0 

■0 

c 

0) 


i 



X 


!73 


in 





v. 

• 




0) 

X 


00 


> 



S 



• 

in 

*jj 


V- 

“> 

c 

CO 


0) 


0 




X 





X 


co 


a 

> 


ic 


E 

— 

c 


• 

0 




H-t 

o 

+J 


-= 

QJ 


r 

0) 

— 

T3 

V 

O' 

Q 

oo 


1 



c 

u 

—4 

k. 

O 

4) 

u 

—« 

> 

k- 



1C 

a 

u 

CO 

•* 

E 

0 

IT 

.M 

a 

to 

a 

5 


XXX 

IT, * * * \ 

V \ C \ * 

\ * O u c a; * 

* — ai c r k. 

>■ \>4J-o — — a. a- 

\ * ^*^airo it viD 

/■ ° + 3 o u > it it 

* *- k it it »—i co 

a oicuv- It in _ 

IT NJ it u o - 0 ) T ■— W- 

^x-^XEtc — £4-»c^:r a- o' 

* F * ^ <r c mw*j ac 

— w. i- n r — - n — 

e > “£^ 0a,0 > ‘ k- * O .x 

t —. a . ^ 4 -j •ov-o) o c 

c <u o a cc o — o —* 

(C -M O u k- k- TO E 0: X 

^ r J ^ 5 O ^ 4 >£ Ittnr 

*-» Q. ■*-» c a> i c ai aw-. r —. 

ica, ^^.heoic *-> x s 

—<tnu —4— a; r e 

W X 10 0) X tO ■»-> 0 > 0) 

a; m-ifl f'w co ^ it l- 

- (Cl^ c c w 2 

IT3 —< •- (r r TO U .H r 0) 

Q.Q.O « E O-1 ifl E ao-. 

a; a) f ■ a> v_ i_ —. 

xu u c r r u it i 

*********** * * 

N-XXWXXn.XXx XX 

> 

-U CL! O ^ _u 

'- xi tr >20 

x <r — re | _ ^ x 

-Lia><f _j _j > <a 

^ — O x _J | < o x oj x: 

< 1 ^ 'J ’^ <■ 2 7 J i/; j a 7 

iJJiccssvccic a) a — 
a o -?.ii/iucaau c z> _j 


a 4)4413)411,14. DOjciifl, 

o £ « .5 .S £ 5, .5.5 S 5 c ® c c 

a>a)a;aia , aja.'a;aja>a; oj a 

X * *******.4»tt.***:S v ** ; 


* * * * * * \ 
X ***** * 


— XfO'T i£t O > 0C> o - f\ ro _n O' 


X > o - ry rn too 

-XX'\.'M(\irvjr\j 


OX U 
J * 1/1 D 


O' « > V_ 
Q.Q. O 
x tn 

in — -V >- 

4 ^ C l/l 

4-> O <C 
> O 4-> Q. 

X —• in O 

* * * * 

X X \ \ 


T5 5 UU 

■sr cl a_ cr 

ai a x m o: 

c cc JXtU 

X 1 1 4) 1 

o r c c c 

to —. -—. -^-. 

E H-. H-. H-. 

4 113 

* * \ o o o r 

X * * * 41 » % 

00 > O — r\j~-)- 

•X r\j rvj ^ ^o-o- 


— NL'x 

— cn lu — •> <- 
2 JJ CO co lU cn C i 
LUa<-ij_-5-i_^-S' 
Cxji<xv> 
-’hUCZCl/l/, 

i i i i 4) 1 i a; 
rccccccc 


1)1111111 
1 X'C'O'O'C'O'C'O'O 


XX C_J l 
1C IT c 

4-> 4-> _J 

EEOC 

O >N > X 2 

x in in — aj 


O C JO _J 

jjuic■ 

”'-<2 J-. 

><fO^<r 
O — 2 Z) — 3 
2 .0 X 2 CO . 

(C (1) <D a> 0) 

c c c c c 


4) 1 1 1 1 

* * X T3 T3 "D D -C ■ 

\***.%%<t^. 


^5^P 0 "^ Y ’ 7 - nCr ' x > 0 “^ ,, '^^o 

-T ^ *T *t X X O OO OO 


Dr. Dobb’s Journal, Number 74, December 1982 







& 

Ci. 

4-a 

X 

a 

a 

o 

"Q 

a 

a 

a 

o 

Sj 


■* 


\ in 
♦ k- 
O 
k. 

w k- 

k. O) 
0 > 


0 ) 

r. v- 
o 

c X 
O <C 
— k. 


— V) 

C £ 
O <T3 
E Q. 


\ 

* 


\ N 

a* + 
c 


z 

>- 

- Q 


r oi 

<D £ 

Q. H-t 


* £ X 
01 ID • 
Q.*j o - '*- 
IC E X 0) 
X > — £ 
W in —< 4- 
* * * — 


o — u ■»-< — a> 

id X id —• —' in - 

E C E a E 

* a; * * * a> 


*£-lXS 3 — — 
1 ID — — — 0) 0) 

T'x cr h- ch-. cr c c 
3 ex oi u — u — — 

» >s—' £ ID £ ID •—«<—i 
Tin — 4-ECEQ.E 


\ 

* 

\ O 

* £ 

E 

w >s 
a) in 


\ X 

I * c 


Wr k. 

♦ * v ID 

X 

ai a< k. u 

O cr C 
id id 


ID £ O 

01 

— 

£ 4- 




4-> ai 

4-> id a 

E 

U 

£ ^ 




o — c 

in 4-> 

ID 

4-> 





4~> o 

— 

C 

in 

CT£ 




o 

4-1 — ID 



C 




in O x 

D O U 

o 

O 

— o 




X X 

a.£ oi 

u 

u 

in u 

• 



c in 

4-1 E 4-1 

u 

u 

k. o 

<—1 * 


» » 

— U u 

£ >.— 

ID 

ID 

ID ID 

LU — 

• 

• — ■« 

O X X 

O in —• 

E 

E 

a e 

MM* 

— 

— X X 

a a a 





— in — 

LU 

X M M * 


♦ ♦ ♦ 

* 

* 

* * 

in x m 

M 

M — — — 

+ * * 

\W 

\ 

\ 

\ X 

lu in 

— 

— in in m 

\\\ 





O 3 x 

in 

in x x in 


X 




< >- < 

x z 

c z z X 


in 




1 —•in- 

in cj 

<-> — —< 


• < 




in -- 

< c 

< X X r- 

• 


oi O in in O' id 
c 

c c — c 

k- X 


a x x x —. 


— 4- 0 ) v- 


o — 

* £ 


C X 
— Q 


l- k- 
• X X 

a a 
x u 
—< o 
o 


C —* ■—' 
a) a> 
rr cr x 


* 

>- 
>. ID 
ID k- 


— O 
C £ 
£ E 
E >s 
>* in 


in 


in \ 

4J + 

c 

a> in 
F — 
0) (D 


O <-> 

X O 

o — 
OX 


i- in * 
id k. 
c o k- 
o 

£ ID X 
k- ID 

H-h O l— 

O Q. a> 

o a 
in O 
01 "O 

in ai T) 
in c a» 
01 ox 

k- — u 
n in +-> 
O C ID 
ID D E 


X \ O 

>v + 

£ 0 > 
X in 
C U —I 


\ r 

* a> 

>. 0 ) 
k. — 
4-* £ 
C ID 


k- * • 

O in % 


\ \ i 

* * 

x 

>S >s 4) 

v- k. £ 

4-> X c 

W c c — 

* * 0 ) 0 ) 


u > 


x x oi 


in 

in 

E in 


£ £ 




o 



O O 


01 



k. 

k. 

01 

01 X 




k. 



IT (C 

c 

k. 

O 


in 




£ 



IT 

ID 

c 

C £ 


01 


X 

♦ * 


in in 

o 

0 X 


c 

X 

in in 


£ 






£ 



ID 

Q. 

N \ 


— — 


X 


o 

— 

—* 

in in 





U 

O 

o 

O 


£ 

w- 




£ £ 

X 


X 



£ 

01 01 


01 



— 

— 

X 

X O 


ID 

O' 

V 

* •• 


o o 

u 

01 

01 

0 ) 

01 

ID 

k. k- 


— 



X 

X 


k. 


v4 

X 

k- 

•—■ — 


c 

E 

£ 

N 

£ 

<4-i 

£ £ 


—« 



ID 

ID 

k- 

k. U 


k. 

— 

O 

X X 



£ 

ID 

C 

— 

k- 

01 

£ £ 


£ 



X 

X 

X 

X ID 


(D 

—4 

X 

M M 


A A 

<4-. 

in 

— 

in 

X 

£ 

ID ID 


* 



in 

in 

a 

a e 


> 



— — 













X 







* 

* 

in in 


* * 

♦ 

* 

* 

* 

* 

* 

* * 

U 

♦ 

0 . 

z 

* 

* 

* 

* * 


* 

\ 

\ 

X X 

o 

\ s 

\ 

\ 

\ 

\\\ 


•—i 

N. 

— 


\ 

\ 

\ 

\ \ 





3 3 

H 







» 


3 


M 

X 




X 


• 


<r c 

£ 






• 

X 


< 


in 

1 





in 


— 


z z 

P 



» 

• 


01 

—4 


Z 


X 

o 





< 


rsi 


w — 

f— 


* 

— 

X 

- 

> 

£ 

• 

>~ 


< 

3 




• • 

X 



■ 01 0) 


oi * * * * 


r\j m 

. . k. V- ID ID 
O 4-> 4-> 4-> C C 
XX£Q.Q.Q.lflW 
ininouuuEin- 

* * * + * 


o o 
o— 
o o 
c c 


"D0i0)*4i®4-' »Q (—< U 

D-D N4Ji- XD C 

v. - ^ c -> u a) qich- 3e 4-. 4-. 

•h - r\j ^ m id d coioi * <n —. —< ai 

£ aaaai j j * £ oin ££ £ 

COOOOininininH-jHjc'i- 
01 * * — * 01 01 — 

% % % % % 


> O - f\iin t /I Or^xoO — Pvjro^r .n o co > o ■ 

— rsjrsjf\)f\jrsjrsjrvjrsir\jrsjr^-nrnnrornmrorn-^^- 


(M^^xiOr-aoDvO — rsin^-O-or^cD 
xinxi^rin 


» * • k. k- 

m in w. 4-» 4J >♦-. » 

U > 4- 4-J a Q. 01 ^ 4- 

O 0-4 £ 4-> o £ U — 

k-k-££— IDCID£ 
IDIDCI-*E4.EC 
* 01 * — 01 

% 


oO — fNjP r )'tXi'Or^oo>o — ojrn'ti£Or^oo>0 — r\j 
Xi'O-O'OO'O 0 0-0 OOr-r'r'r^r^f s ->r'N^cocOD 


00 

<N 

& 

cx 

o 

cx 


o 

c 


c 

o 

"a 

a 

•S 

a 


c o 

X 

01 4-1 

a o 
> c 

4-1 01 


NJ X 
— < 

UD 3 


>s ^4-4 


0 ) 01 
. O XJ 

4t % 


O — f\ ro 
LU Z 

H 


£ 
—1 C 
LU — 
CD T 
< < 
_J > 


>- E-« 

< Z 
X — 
X 3 

< a. 


in ai oi oi ai a: 

in c c c c c 

o — - 4 -. - — 

Q. v. 4- 4- 4-4 4-. 

oi ai ai a; ai 
* \ O T5 O £ O 


• U 0) 

: ai o 

> £ i- 
L- O 
) O 

• X 

: * o 

. O -4 


* * * * 


* v a_ 
— x 

O ^ 


_J X 
lu < H 
X X z 
< X) — 

J'JU 

01 01 


C — IM ro 

O 


U<2 
-1 — 3 X 
LU f— C LU 

23 < « U 
• X X 


I C/3 • 


: lu 


o 

a 


01 01 01 
c c c 


* * \ + O £ O 

\ * * \ % o * 


* \ 

. * * 


o 

o 


rsi *sj 

L0 ID 

<M tsj X MX 

LU —- C < 

in lo r— m ■— 

4f 5 i -D 5 

x in in in in 


: 0 ) —i a- 

i £ 01 £ ' 

it * % ^ 


4-> M 

ID X 

4-i X M X 

in C —■ < 

•—m3 
= COO 
oi 2 s j 

— a- oi ai 

x c c c 

J -H — — 

= 

01 01 01 
* V. £ £ £ 

.***%% 


^0-fijnti3 0i^X>0 — .'MX4j_0<3r^X>0 — OgX^XOr^-XO-O — fMX4TXOr-X>0 — fMf’l’JXlOMD^O 1 
X O o <5 OOO O-OO'O’^-: . i XXXXXXXXX>>>> >> >>> >0000000000—- 


: Oi 01 

1 £ £ ¥ 


ryinuic 


o — 

O _J 


M 

in x 
x < 

< 3 

H «-• 


r- co > o 

-rvj 


Dr. Dobb’s Journal, Number 74, December 1982 


29 

525 




‘ — O -LI UJ 

- ~ LXi 2 111 XJ NJ 

2 fsl \J _u NJ —. _ 

— 2 — ID in 

J 03 CO U to -U UJ 

3 •* 2 < 0 2 2 

!H O X U •—■ •—• 

- •— < <JJ 


QJ 0 ) 

a- > -*j 

13 ai C 

X o -4 3 

* F O 
O' U 

-C *-> c c 


in ♦-> 
2 D <D O 
W O C C 


c t: « * 


O H3 l- T) 

u —■ O) \ c 

U <D * D 

T L, O' O 

E C -*-> Q. 

— O) F 

qj v_ a >, o 

-c ■*-) a c 

-»-> a--« h-. 

x o c 

v- * m o> 

03 u 

Q) (C *J *J +J 

— -*->0 0 0 

u in c c c 


********* 

\\\\\\X\X 


N in (u 03 

* in 3 *j 

0) 03 —. 
COD-. 

o o a 

-« k- 03 
*-» a 03 4-> 

U 03 —< o 

C U D 
3 CL -C o 
•4- 2 


in 13 ic 03 
k- o: 03 x 

— C — 03 

■«- 0 ) O H- 


* * + * * * 

WW - \\ 


-OOr^OO^O — f\jf 


J O U O T3 

: c c c c 

< 03 

L » < % * 

• tf> •© r* cc 

' -O -O u> -f» 


* * X --4 03 

x * * % E 


' O' 0: ^ . 

uncc' 

03 —• — C 4 
03 03 03 ■> 

% e % i 


-J i a —i —i i 

* —J c o _!■«•<• 

) < u < _> o 

3 <-> 03 ♦ 03 1_) CJ 

: o E w 03 II II 

ii ii 0) it a) a> 

•ci—• h- rr c c 

' O 4-> — U - 03 

:o:c.i:T3 03-m 

■EOiCEQ-E—. 


03 X || 03 

> 03 — > || 

— £T 03 03 k- 

4-> 03 > —« *-> 

• u rr 03 a. a 


II - II Q. ~ 

ii ^ — cr — c — 

O'— — 20-4 — 

II L- || || || w- || —. c 

II in 03 03 — 0) k- 03 4-J — — 

ii a 0 ) 0 ) *-> o -n 4 _> +j u w c 


urTajaa ^n ao)0)*->o-n*_>4->D^ 
03 O' —< u CL k- >*- £" —4 —4 O C 00.0 Q. x 


I^Ul'HUlEUOJOJC'LV. 


o o d c in a 

O 2 CT-, 0J O 


?_^[TZ!^ O '!l; X> ?~^ rn ' T -* nOr ^ :c >O-rMr-w.n0f^C0>O-<\jr v WJ'tOf^CE 


Cl <o 


a 00 
<v 

E ~ 
o 3 


(Q op 

E * 

C 0 3 


T3 X C 

X 03 * 03 

* C -C 

c -C J 

C 03 03 
O U C — 
•h ID C I 
4-> 03 

o O' u a; 
c c in in 


j O in 

: % i x 

3 I 03 * 

- — o > 

a) 4) -h a 

■» X3 C 03 4-3 l/l 

n 03 O' & 0 ) 

-- — O' —< O' 

i in —i a) k- 

. in v- 03 

—< 03 O' 

- 03 C k. C 

3 > * -h O) O 

* 03 C — 

-H C +J 

L3 *-> 0) —« Q. U 

3XO O' E C 

- 0) 03 03 O D 

-> C —< £) U V-. 


03 £> 0 

Q. Cm 

> X m —< l 

* * O' u 

< 4-3 \ 

. o; m * -i x 

—• —< ip —• 

-< —< x c f 

> '4— DLL 

0) T3 0) 03 

' 4-3 —< c 4J 4-> 

■ D — — C C 

) Q.H-. —. 

: «-> O' 

< D H-. k. O 

Q —4 0) —< 4-3 


. H-. 03 ~4 03 03 

N H-« rsi N 

* I II 


♦ 

X 

+ 03 X 

■ox* 

o; O * X 

X) u 0 ) * 

c a) a 

U > U >. k. 

I — — 4-> 0) 

u r > 

F 03 4-3 '4— 
O' 0> T3 C D 

c in 03 jo 

—• m 4-» e 
in id in a; 4 -* 
V- c 

03 O'—* (C —< 
a c 4-> 

•h O in x 
0 ) m •*-> c 

—• in T3 0 ) 

■H T U J) 

£ Q. 03 *j O 
* 4-» D 4-» 

CCO 
O l)H 01 U 
L £ O X +3 
03 2 Cl 03 Q. 
N 

I O 03 4-> J* 

c >- 1 in l 

0 03 —4 03 0 

C N 4- —. 2 


*************** 

V N \ S \ S. V N N N X \ \ \\\\\ss\\\\\\\\ 


T> • a> . • • 

03 —4 > »*• *»Q> * » O' O •• 

V- 03 03 •£ £ £ xa 03 *(\ 4J • V- 03 • • Q. -4-> 

• • 03 > —< — «p 03 to -*j o • —• 4 -> 4 JDmo:— 44 ->o) 4 -. m — 

V-V- *—« 03 Q.U—4—I—. . in 43 Q.4- ►DDQ.O' 034-.XTl 43 43 k. 

4-303 *-C u—•—< C 4-3 4-> O' Q. O' O' E L-4~ aO.4-3—4—4 £ 03 0 in in 4-3 

Q. Q..C ua34-^ 1 'Dx-4a)inuuuv-0CCD-4 — — 4->u — 03 a 

CLOU C X in V. C—'£3 U 03 03 C OJ 03—4—4 O'*- 1 *- O-U O —. —4 — 


m — w — 

-X — - -X >- • 

C 4-3 ^ C C * 

03 in ^ 3 0) 

— TJ 4-* —:.x 

£ C C 0 ■ 

03 — 4-3 , 

4-3 - O 

• 0) — 03 

^ • O' ^ 03 

^ — 0 ' c 

r w c 

U 0) 4*4 

rc — ~C'-' 

E iT £T —. w 4 

o: 2 u 4- ; 

—• O' a- . 

03 •'O -4 

-'O ^ — 


(1) • w 4-3 D 

—< C3 >, E 

-4 - O £ ' 

r c 

2 O "C ^4 . I 

T3 o C ~ - 

O -H w I 

<0 4- -r - 

• ~ u 

— 4-3 

• w • 03 03 I 

— 0i — E E 

^ O'o: 

E C £ C 

>4-3 —. —. *4 

in in O' ' 
X> V- T3 -4 w . 

T3 0) C 4-> 

03 03 -44 2 

-4 <4- • O 

U — —4 


3 X C w 

• •— -4 U ^ . 

J —J E 03 w U 

- tn^v, c E CO- 

:d:o:—•—•U'OEV-.- 

• • T3 "O T3 03 T3 D U 
l^r C C C 4> OJ £3 tt) 

) O 0) 03 0) X 

^ 1) % % % 03 


^-4 0) 
w 0) —l •• 

• FO — — 
•>-03 1:'-' 

• in-4 2 c 

4 4-3 4-3 "D 03 

• x in 03 a 

4 ii o a.- a 

t C CL U D 


C W — 

Vm t« > ~ 

03 "C ^4 4-> 
4-3 03 T3 O' 


f' r )4f_flOr-~GO>0 — <X rr 34J’Xl'Of^X>0 — rsirn^rx»Or^-x>0 — rsjrn'Ta^'O 

®XXXJOXX>>>>>>>>>>0000000000—- 


CD>0-(\rn4t£l0MCD«0-fMn'Tin0Mr)>0- 

-<XfXfMrvjf\jrsjr\j(Mf\j<xrn'^rr)i r >r<3rOf v )rororo »r 


Dr. Dobb’s Journal, Number 74, December 1982 








(Continued from page 22) 

each function header line to the console. This switch is useful 
for isolating errors to the functions containing them. 

The switch “-a” causes the alarm (control-G to the con¬ 
sole) to sound when an error is reported. 

The switch “-p” causes the compiler to pause after 
reporting each error. A carriage-return from the keyboard 
continues processing. 

The switch “-1#” (# is a file descriptor in the range 1-9) 
instructs Small-C to list the source code on the file indicated. 
If file descriptor 1 (stdout) is specified, the listing is mixed 
with the normal output. In this case, a semicolon precedes 
each line of source code. No listing is produced if the switch 
is not given. 

Machine-independent and pop/push optimizing (described 
earlier) are always performed. The switch “-o” causes the 
output optimizer to further reduce program size at the ex¬ 
pense of execution speed. 

The “-b#” switch exists only if the compiler will not be 
used with a linking loader (see “Installation” below); i.e., pro¬ 
gram parts will be combined at assembly time rather than 
load time. It causes label numbering to begin following the 
value #. If # is zero (default) a complete program is being 
compiled. In this case, header and trailer code, designed to link 
the program with its environment, is appended to the program. 
A value of 1 means the first of a multi-part program is being 
compiled; header code only will be appended. A value between 
1 and 9000 identifies an intermediate part; in this case no code 
is appended to the output. A value of 9000 means the last 
part is being compiled; trailer code only will be appended. 
Values for # must be chosen to prevent clashes with labels 
generated in other parts of the program. 

The null switch or any undefined switch causes the 
compiler to exit after displaying the help line: 

usage: cc [file] . . . [-m] [-a] [-p] [-1#] [-o] [-b#] 

The alternative to command-line parameters is prompting. 
The operator is asked for the output file name and then for 
each of the run-time options. The final prompt is for an input 
file. At the end of that file, another input file is sought. A null 
response terminates the compile. 

Installation 

This version of Small-C may be compiled using the origi¬ 
nal compiler. First, however, you will need to make the 
following changes to your present compiler (if not already 
done). 

1. Apply the fixes mentioned earlier (item 16 under “Dif¬ 
ferences”). Fixes (c), (d), and (e) may be omitted. 

2. Install the change which allows the compiler to proper¬ 
ly handle back-slash escape sequences ( DDJ #56, pg. 6). 

3. Make whatever changes are required by your run-time 
environment. Be sure your system supports the Standard I/O 
Library functions “fgets,” “fputs,” and “fputc” (Listing #2). 
All input and output is through these functions. 

Note: The original compiler, in several instances, 

performed a “logical and” of 127 with a source byte. 

I have removed these operations preferring to let the 

input routine do it (if required at all). 


Then you should prepare a temporary copy of the new 
compiler as input to the first (using your present updated com¬ 
piler) of two compiles. This is done by deleting lines from the 
new compiler which cannot be handled by the present one or 
which are not desirable for your particular installation. 

Note: If you only have 48K of memory, you probab¬ 
ly will not be able to support all the new language 
statements, the code optimizer, and the hash search 
algorithm. I recommend dropping all of these except 
the optimizer at first, then adding features until your 
limit is reached. The new expression analyzer uses 
much more stack space than the old one, and each 
time embedded parentheses are encountered, the 
entire expression hierarchy must be traversed again 
from top to bottom, requiring about 400 more 
bytes. If you bomb off on such a statement, for lack 
of memory, try breaking down the statement into 
intermediate stages. 

Conditional compilation statements (#ifdef, #ifndef, 
#else, and #endif) are present in the source files to docu¬ 
ment which lines should be deleted and which ones should be 
retained. For the first compile, they must be deleted along 
with all inappropriate lines. Once a usable compiler has been 
generated, the temporary source files should be discarded and 
the newly generated compiler must be used to produce a 
second version from the full source files. This second compile 
(phase 2) is required because it will include statements which 
could not be compiled by the original compiler (phase 1). 

Several symbols are defined in the file “cc.def” for the 
purpose of controlling compiler options. If the action taken 
by the compiler is inappropriate when any of these symbols is 
defined, that symbol should be deleted or commented out. 
These symbols are described below: 

SMALL_VM compiles statements in the file cc41.c which 
cause header and trailer code appropriate for the Small-VM 
interface to be generated for each program compiled. 

Note: Small-VM entry points are called at a number 
of places in the compiler. They permit dynamic mem¬ 
ory allocation and operator interruption/resumption 
of compiler execution. All Small-VM calls are coded 
in upper case and begin with a “CC” prefix. For a de¬ 
scription of these functions see DDJ #61. If your 
run-time system supports either or both of these fea¬ 
tures, then you should adapt the applicable ones and 
discard the others. 

DYNAMIC compiles statements which dynamically allo¬ 
cate memory for various tables and arrays within the com¬ 
piler. If DYNAMIC is not defined, the tables and arrays are 
compiled directly into the compiler. This symbol also controls 
statements which call CCAVAIL whose primary purpose is to 
return the amount of free memory remaining, but is used here 
to verify that the machine stack and allocated memory do not 
overlap; the run aborts in that case. If serial table searching is 
used with dynamic memory allocation, then each new entry to 
the global symbol table is allocated separately. The table may 
grow until it overlaps the machine stack, producing an allo¬ 
cation error. 

(Continued on page 56) 


Dr. Dobb’s Journal, Number 74, December 1982 


II 

527 



c c 
o o 

E U 


w c r> 

03 LLI 
C >- 
—< II — 
—< 03 0) 
UJ- N 3 

N l. -h c 

• 0) E 
S Q. •-« 

—• Q. *-> C 
H 3 a O 
CL w o U - 


lO o m cd o O 
f^- r^- r~- r- X) 


c — 

—•in — 

hUJ 41 
x- >- 3 
U II C 

0) <X) —< 

a ui *j 

a 3 c 

D <0 O 

w a o - 


' rvj 

— a x 
*— E C 
03 3 <*3 
C C - 
-< U 
— 0) 
-X £ 

J*C L- O E 
z a> ~ 3 
— a a c 
-J a 6 ~ 

3D**-' 

a> x- 
T3 — 
c 


o> lu 
OM o 


^ Ov, O* 
m «) in- 
■O T3 
C x-. 


03 — 

TJ ~ 
+-> LU 
W Q 

•O 

r cr. 

c a 


3 O 
O A 


CL 

II 

E 

A 

it) — 


*-> 0) 0) 
3 a a 
a o o 

3 II —- 


^ tj a-o O 

-X O C E 


= 33 

•DC w Q. O 

|| — *-> *-> _H 

w- —* — a 3 

O {= x- £ o <D 

•*->11 0) o x- in 

**- —< 03 —< V- x-. —< 

c a — a> <- 
-« a 

—< j 


z — 


• a) 


o E 
-J - a w 3 

~ e a c 

^ m O e- 
03 -< U 3 x- 

■ tj — a a — - 
c r 


f'- in 
io lu - 
l- >- •. 


03 *-> 
A —• - 
C * 

c o: 
o e * 


U \ - 

c >- 

3 X I 




<u 


tj .c 

c * 


— a 
~ e 
a> o 
—« u 
• — a 


a — - 
a j* 

3 03 ID 
« in oi 
**- —• u 

*-* <D A - 


v) a \ 

U x ^ 
U >- 0 ) 
<l) x C 
II -H 
c II —. 

o - * 

0 ) W 

0 ) c w. 

W —» 0) 

3 -h a 
fc * a 


x^ 0) **-• 

~ ■*■> a-. 
- a a 

w E 3 0) 
ttl ifl 

—< L- X-. —< 

a a? 

A 


— i\ '’i t a o 

co oo ao ao ao oo 


MDO O- 
00 CD 00 CX > 


i\j no t in o 
> o > > > 


r- x > 
> o > 


g-?;sx£Sc:s2 0_iN ' r " r - r, ' o '' oo > o - ,N " vi ^^or~co>o-tM 

SSSSSSSl3 S 3 ^ ~ ~ ^ ~ ~ ^ ^ ^ ^ SI Ri £ R! Rj Si r; S rj Si R! Ri 3 


fn^^or-aoao 

^ n -n n ro "i ,-o rj 

cNfMf\jr\jf\jogf\jrsj 


W S' 


> a> 
od 

C3 

M O- 

c 

o 

CD 

# C 

*3) 

a> 

-D 


o 

■■■i 

a 

E 

o 

o 


a 

E 


XJ £ o 

o> 5 

3 - a 

C u 

+J iL 

C u u 

O - o 

O CD 

S ° 1 

!>•*-> o> 

•w 0) \- 

w *♦- a 

s * * 

CL, N i 


< -*J 

^ rc 
>• u 
in o 
* — 
in —* 
u ic 


o 

Q 


V- \ **- 
v. ♦ 

ID >s 
♦J C \ 

a 3 m * 
o a 
C 0> 0) 

\ c T» -C 

* -< o 
J in u 

0 ) in j4J 

tj id < 3 a 

0 3 0 3 

U ^ 1/1 I 
id in >. > 
O > <d o 
w- u ■—• —< 

4-J O l-I 

C 0) U Q) O 
■h in a> v. 


***** 

\W\\ 


T3 

0) 

c 

U ic 

c a 



1 V 

X 

-J 

o 

O 

c 

3 > i i H j 

—i in 
-J 



-J A 

o •*-> 

H 

a 

—< 
c 

0 

in _J • s < 
in _l z < n u 

< —i 

O (C 


X 

h* a 
a u 

< — 

H — 

•fH 

«D < Zl/)U 

£ 


in 

< ♦ 

in ii *• 



U5= > < II 

II 0 


< 

t— * 

II oo 

— 

0 ) 

o in ^ Q X A 

A -• 


X 

in — 

V- (D II 

o 

AC (D 

(C O 



II 0 ) 

X-> —< 4-J 

o 

a**-* i m ^ v. *j 

4-> 

X-t 

X-» X-. 

Lhx. 

ax- x 


c 

id oj a— 0 ) a; e 

OJ E 


—. 0 ) 

4-> —. -H 

A A <D 

00 


A A o A A A >s m >s* 

TJ 

X A 

a a tj 

—<—**-> 

c 

3 

ax-, x-. c **- x- in 

—• in \ 

C 

C x— 

o i c 

O O U 


-4 0 ) ■'■* 

0 ) 

X 

CD —< 

0 ) 


*-w 

CD 

(ft 

* % % % 

* 


^ *! 

=* 


• »- 

s 

■ M 

O O — (\ CD '*? A 

O r- co 

> 

o — 

r\j rn 'j 

A O r- 

— 1 

-1 

■<T A A A A A A A A A 

A 

o o 

O o o 

o o o 


a 

— 4-> 


^ 0 ) 
— T3 
a> —• 
v) in 
a *-> 
<D 3 

a o 


-< o 

<D —< 


T3 

o 


w - T! 
Q - — C 

- -C ^ w <D 

3 ^ u a 

^ — o C 

EuiCD**- 
in C E v- 

IC-C J 
O O T) (U ^ 

TJ T ID C O 





o A 






03 








C <D 



u = 



0 ) 







•*-» 

it n - 



^ —• a 

r 


u 







ID 

a> 



^ H ^ T 

CD 


L- 





*-> 



in —i 



O c — 3 

c 


o 





X 


m 

0 ) 



I—. r .—i 

_ 







0 ) 



TJ 0 ) 



• in e u x- 



o 


0 ) 


4-» 


> 

3 A 



s x- m c 

0 ) 


* 

o 


N 





—• ID 



C 0) ID —1 

TJ 


\ 

a 




4-» 


c 

U 



L- l_ ^ % 

% 





in 


3 


o 

c in 



Oi id r z 

z 






a 



—< c 



X— 4-> —I x- w 




ID 


4-> 


c 


• 

o 



x U A A A 



U 


c 








'X 0 ) 0 ) u u 

u 



03 






(D 

in x-j 



O Z -Q X - 1 •*-» 

*-> 



+J 




•—* 


> 

0 ) —i 



ii x- o id m 

CD 







—* 


0 ) 

c c 



II r TJ E E 

r 


•V 

^-i 


0 ) 


(D 






H-. o w w w 

—. 





ts] 





X-. H-. 



OD'i.'M, 

X- 



03 




in 


in 

0) <D 



0) ID -H —• -H 

-v-4 


m 

A 


m 


in 



TJ TJ 


■— 

— E 



-* 

•*-> 




0 ) 


A 




ID 0) 03 0) 

03 

0 ) 

c 



m 


o 


+J 




03 x' in in in 

m 

in 

«D 

a 


■*-> 


o 





•— 





E 




A 


4-> 



03 

—. — 0 ) 0 ) 0 ) 

a> 

0 ) n ^ 



^_, 


a 


c 



in 

A 




■6 


a 







v. 

5 






F 

* 

* 

* 

* 

* ♦ 

\ 

ID 




* 

* 

\ 

3 

\ 

* 

* 

* 

* * 

♦ 

a 





* 

* 

T> 

A o o x a o — 

(N 

(*) 

"t tO O px co o o 

- r\ n t n 

CMC 

fx* fx- 

px- 


f*- 

CD Q0 00 CO 

CD X CD CO 00 

D 

> 

> > > > > 

> > > 


O' 

O 


0 ) 


O 

(D 


a c in o • 
a 


-H H-. o **-• 0 ) 
*-> O —• (DU-''D- 
C II A T) TJ 

I'M 


(D 


> O — c\j nn 


« n on 


34 

528 


Dr. Dobb’s Journal, Number 74, December 1982 







bo 

c*. 


LU O 
N x 
— I 


c 

o 

3 

•S 

O 

<o 


• m 

11 l/) 3 
C LU C 
— 

—4 II 4-* 

0 ) c 

• NO 
r —. u 

E 

<X- -rH *-N 
01 4-> X 

N QZ 
~* C V 
10 II 


O >• 01 
Hi S C 

II -4 
a> ii —• 
N ~ * 
—* 01 ^ 
ECU 


N 1 


a * 


I >v-r u w 

•—< W 0) H-4 

- h ~ 4 J a -* - 

-X Q. — Q. Q. 

«D C ^ E 3 1 U 

0 ) D O « W «) 

u ^ U H-. -4 U 

U <D — Q. —< 0) D ' 

T3 C 
4-. J 


c -*-> 

—i in 


i—i 
0 3- 
■*j z a> 
Q. II 3 
-4 II C 
U — -h 
u — 4-> 

IO — c 
1 ) U O 
■Q C O 


4 x3 -I 
■ — 3 


—• —' <D 
-*-> * C 
in w 
-H U —4 


^ 4J E -4 - 

— a. 3 -v 
^ E c did 
ai O - in i> 
'*- —< U H- —* u 
—< —« O. —< 0) _D ' 
TJ -C 
C X 


m 

10 


-4 3 
-4 C 
a -4 

4-> 

• c 

O' o 
u u 


LU 

2 O'O 
— u — 

► J « OJ 
- !-*-> C 

: 3 a) 

J 5 O'-* 
uj w a. 

J 0) w 

3 X-. 
L»’Hh l 

: tj .c i 

4 4- J 




— r 4-> 


— c - 


3 w u — 


U LU 
0 ) Q 

c a 
a.' cr 
aa 

o LU 


LU 

>• - - 
II — c 


-*-> u 

3 0 in ^ u 

O £ <D —* 3 

—4 (C -~s 

~h -4 oi 
x- .x u ' 


—■ ai x 


• • LO 

O' O' c 
in in id 

E E w 
w w m 
+J 4J+J 

a 3 oi 
E O O' 
O in h- ' 
u 
a 


\\\\ 

* * + + 

ifiO N CD 

u u u u 


\ 

♦ 


\ 

* 

r\J 


* 

s 


uutd cr oi 4) o> 4-> +-» u—*"ou4-> 
O O C 0) C —< O'—< O' in in "O 0—4 

x ID id ID ic in 3 

E 

II II II II II II II II II II II II II II 

O-ryjnjiTlO'^XD'O-ryn 

oooooooooo-— — 

Q.Q.Q.Q.QQ.Q.Q.Q.Q.Q.Q. Q.'o. 

oooooooooooooo 


II II II II II 


D (L U U 

—• 0—4 O 

3 3 3 3 

II II II II II II II II II 


-fMn’Tin'OMi>0-f\inTr/i'or'CO>0 — ryr;4f l no(v.co>o-(\iro'j'^'Or^CDoO- , „ ^, v , - ^ w 

^ 5-nr»' : pj^ri-nonnooo'00'00'Oooorv.~>.r^ r ^.r^r^r^r>-i^-r-tx)(r)cococox)aDaococD > 

rvj f\j r\j r\j f\j rsj rsj rvj (\j oj r'jcsjrsjf\jc\j(Nif\jf\jr\jf\jf\j('\j(''jc\jc\jr\jr\jC'j('\jf\j rvj c\jf\j(‘\jpg( - \jrvjf\jf\jr\j('\je\jrvjp>jr\jrvj(''j(xjc'jr\j 


iNjrn 'J ,1 O ^ I) > O 


— O — r\ir' r Win'Or~ 00 >O — Cvj r-\ 

'-OOOOOOOOOO- 

in ^ ^ 

a r\j rvj r\jr\jr\jr\jc\jr\jr\jr\ir\jr\jc\jr\j 
o aaaaaaao.aaao.aa 
■*->00000000000000 


— rvjrn 4r^-OM3D>o-^n^Ln 
'>>>>>>(>>>000000 
rvj(MfMf\jr\j(Mr\j(Mr\jro<33ro>3<3 


0 ) — O 

O 01 II — 

w n II - j* 

O —< ■3— ID 

# in »< «- d 

T3 ♦ ~ — U 

4-J .* CL' 
3 II H- 

O JW —4 


> 

n 


a 

E 


O - 


in 


*-> •• 
c — 
3 — 

O -J w 
U J J 
~ O -1 

a. o 

> 01 


— o 


o 


i - -* 


• O a _ 

N -*-> -H O) 1-1 ■— T3 —5 

T> a c cd x: 

E — » C 

* \ D -4 0) 

* * O it =* 


— o 

I W 

I 

U —1 01 ~ ^ 01 

o w X) >- -* U 

•*-» — ai •*-> C X) ' 
inO-<3H-. 

H-. 3 —. O —• 



■o 

O 









2 01 

*5 






—4 

c 









— 3 




X 

X 


in 

■H 









-J C. 

X 



<■ 

•St 


4-» 

m 









■H 

U 



X 

X 



O 







•• 


• 4J 

X 

•» 


II 

II 


O 

«—4 







o 


01 c 

II 

X 


II 

II 



o 







2 


c o 

II 

O 



—. 


in 








II 


—4 u 


X 


r-^ 

1 —. 


"O 

O 







0) 


—4 

r—i 

1 


— 

— 


c 

c 







in 



_ 





— 

01 

s 



o 




3 


• X 

i—. 

(M 

X 

01 

01 




in 


II 




ID 


— 1 

01 

w 


c — 

c 

\ 

01 

u 

c 


c 




a 


♦ \ 

c 

01 

X 

—4 in — 

-r-i 

• 

—* 

o 

o 


ID 

•» 



ii 


■f II 

•^4 

c 

II 

—i LU 01 

_ _1 

\ 

—4 

u 

•«-4 

LU 


4-> 

LU 


u 



.—1 


V 

4 - >- 3 

w 


a 

u 

4-> 

2 

4-> 

3 

M 


O 


O'—• 

w 

—4 <D 

1 —I 

u II c 

u 

01 

E 

01 

a 

•—4 

X 

O 

•—4 


4-) 

•» 

U O 

u 

II 3 

rvj 

01 E —• 

01 

4-> 

O 

'—• 

o 

-J 

c 

■O 



—4 

01 

ID — 

01 

a c 

w 

a u 4-> 

a 

> 

u 

— 


1 

II 

4-» 

—« 

ii 

C 

C 4-1 01 

a 


01 

a id c 

a 

a 


a 

c 

o 

a in 

H 

01 

o 


01 C 

a 4-> 4J 

c 

3 -1 O 

3 

4-1 

> 

— E 

3 

5 

H— 

II 

a 

N 

E 

—< 

O'-* 

3 

in c 

—4 

^ ID u —> 



—• a- c 


* * \ • 

\ * * -- 


01 — 4-> —4 

T) ^ C II 

• .V --4 


I 3 

an- 


4 H-4 u 01 —* W 


4-> Ol+j— 4 (T3 c —4 -^4 ■— 


C0>0 — (NjrO’TXl'O r ^CD>0 — r\jrn^ 3-OI^-X>>0 — f M3'^inor^-CD>0 — 3 Of^ u>0 — Ojo r )4j- L 0sor~c0>0 — r\j(3\fLO O CD > O — fNJ 

oo — — — —— — — “ ~~ r ' J ^^ fNjrs, ^/^ rs,fNjrsJpr,rr,r ° r0r<irr)rnrr,r0rr),;, ‘^' ^ ^ ^ ^'^3inx»cr>Lr»x>x»x>xiO'0'0'0O'000'0'0P^r^r^ 


^i 

& 

o 

fc. 

o 

c 

o 


3 

.C 

K 


Dr. Dobb’s Journal, Number 74, December 1982 


35 

529 






\ 

* 

CV. 






CT 

3(5 


\ 

* 


¥ 

• 



in 




3- 

C 


T 




z - 


4-3 

O' 


•» 


4-3 

3 


E 



C 

n — 


c 

3- 




a 

«—J 


E 

•» 


O 

»—• j 


D 

T 


43 


u 

•» 


O 

4—- 


— 

f— c 


O 


X 

E 


O 

<— 


u 

- 


-4-3 

O 0- 


u 

4-3 

* 

IT 


—-4 

- 



ID 


O 

Z 3- 



C 


c 


^3 

43 


43 

E 


c 

O T 


O' 

O 

4-3 

in 



E 


X 

E 


13 

x a 


w. 

o 

c 

in 


• 

ID 



O 


'4-< 



T 

u 

D 




C 


T3 

u 



• c 




0 

Xi 


-4-3 



__i 



T 

|— 03 


4-3 

c 

u 

43 


in 

4-> 


D 

O 



z a 


— 

43 


T3 


O' 

C 


O 

c 


43 

— O 


c 

r 

O' 



3- 

43 


n 

5 


O 

o 


—H 


3- 

4-» 


T 

E 


in 




o 




T 

<—< 






3- 


O 

• c 


* 

■*» 

— 

D 


» 

O' 


• 

— O 


-4-3 

z r 


X 

X 

m ^ 

E 


O 

U 


c 

3- 







Q.L0 




T 


43 

— 3- 


T3 

«— 3-. 




E X 

— 


• 2 



U 

O 43 


43 

H O 



v_- 

£3 X 



O Q- 

*—4 


T 

II 


E 

O w. 




O 

43 


CO 

T 


a 

II — 


=3 

Z 3- 




» 

e 


• ♦ 

O' 



— O 


in 

O 43 



o 

4; 03 

T 


43 ^ 

03 


O' 

s II 


in 

X 



II 

E E 

C 


E 4-3 

—1 


c 

— II 

T 

T 




II 

C T 

in 


t in 

l—t 



£ — 

43 


•O 


•• 


C C 

in 


C O' 



m 

» - 

3- 

3- 

43 II 


CJ 

s 

in 



m 3- 

Z 


O 

3- • 

X 

43 

E H 




— m 

u 


m t 

•—■ 



4-* Z 


— 

T — 


-J 

s 

T ~ 

O 


^ ii 

u 


u 

CL'-' 


— 

C S 


f- 

—- 

O' 43 



E ^ 

o 



— X 

—4 

3- 

in ^ 


cc 

r. 

43 E 

■O 


X 4-3 

3- 

«• 

4-» 

U 

w 

T 

in r 


< 

u 

— eo 

c 


in in 

3- 


O 

0-4-3 

4-> 

43 

w 


1- - 

4-> 

C 

— 


-O O' 

43 

w 

c 

4) T 

in 


e r. 

•» 

to o 

T 

X E 

H— 

43 

O 3- 


in 


3- E 

X 


X O 

— 

II II 

E 

C X 

W 

m 

T T--h 



■*-. 

*-> 

c 

* 

in 4-3 

—' 

3- se 


t in 

H— 



4' 

C 

v4 

in 

43 

X 

"O T 

X 4-» 4-3 

43 

—- 

— 

43 


in 

T 





43 T3 E 

U 

cl in 

—4 

* H- 




.—i 


* 

'4-i 

•^4 


in id ^ 

4J 

U O' 

— 

X — 




43 O x 

---4 

— 


-H *4-1 

c 

O 3- 

X 











4) — 

43 

—* T 

2 











4-3 

Ml 4-3 

O' <n 

U O' 

<0 w. : 

II T ( 
- a— i 
o O 0! 
n •*-> —> 
a o> — 
w v- x 
u m i 


C in w x 

—• C in — 

x - c — 

-p v> 
> 4 - c H 4 -> 

O X 2 C 

O — c 
W Due 

43 w w ^ 

Q. ifl in O' 

XXO'O'3- 
4-» * 3- 3- T 

ID <D 

4-» 03 O O *4-. 

IC H3T O 
£ 

*2 U 

*-* 0 ) 
a - in — £ 

V- *-> no E 

t c - o 

— <D — s C 
U E — 4-3 

4) ^ c O' 

"O O' - — c 

u r s O 

u t 3- w u 

o> t x 2 

-in t x os 

D in u ■*-> w 

* Or id u 

XT ~ E O 

H P X ID U 

U ^ V- 

-*-* h-. a> 


E 

id a> a> 
in in 

„ « _ —. 
X X — 43 43 - 


a 

E 




43 — 


0.4-3 

C 


w a 
—< E 
O D 
O T3 - 


C 

o- C 


C T3 
— 41 
4-* E 


a 

>> 


* 0 

4) 03 
C *-> 


E O 

O x; 

U E 


X -J 

* ^3 


in — 

*-> DC 

c c 

4) > 

E II 
D —MJJ O 
O' 


= 0- 
* -* 

— s it X 

O — 4) * 

II U • U 

11 4 ) • x 


4- 


3- 43 


♦ 

X LU 


a c 4 -» 

4> in 1 

* T 43 T3 

43 * c 

E •*->-*-) 0) 

T — 43 — 

C X 

m in — 

in — h- j 

• ~ ^ c 


D v 
E X -o ■ 

in n 


43 


• Qj — 

E V. 

• 03 -*-> 

» c a 

— O' 

• 03 3- 

: O' 03 •> 

< 43 * 


c — 

T3 

d a. c no 
e a— 03 
j x*— — — 
in v ^ * 
11 ^ in 4) x 


~ ^ 43 • 


O S 

II * 

II s 

V ~ 

■*j x 


E r O X - 

03 — m £ o: 

C r C UJ 


43 —< — 

— (D 3- 

— O 2 

TO 43 
U — 3- 


* * * * * * * 


X o 

* o 


•*-' O' *-> 
► — 3- T 
* O o' 03 E 
43 ^ w 
V- —< H- 

'U ID — — — 

. c x x 
: — u X 


01 x w ^ z 

in u O' u 41 j) - 
4 > *-> x —I C 
— ID — CL 

— e * x: 11 

- - X J 


c 

— 03 
43 43 

e a 

T X 

in 

in h-. 
w o 
u 

o in 

■O — 

'■»' C T 

— 4-> 
-4-43 
43 II -O 
E 3, 

T 4-> "O 

c a t) 

— O' 03 
03 3- 


OO — fNiro^uO 0l^~C0>O— f\jr0Tj-X3Or^30 > O — r\jr0^r u oOO>XO>0 — r\jrn'»frj'iOr-C0>O — r\J 

Q0 > > > > > > > >>>0000000000 ---cvjrgcvjr\jp»ir\jr\jcMr\jr\jroro -n 

- —--xir\jpgr\jf\jr\jr\jr\jrNjf\jrNjrsjf\jfNjrvjf\ifMr\jfNjf\jr\jrsjr\jr'jfNjr\jr\jr\jr\jrNjrNjrNjrvj 


•"n ^ x •cr'-co>0— r\j<-0'T_nOr~CD>0— (MO 


O 

P 


a c 

X. E 


O' * 
*3 X 


Q. 4) 

X 3- 


43 S 
E - 
T r 
C w 

w x 

m u 

w 4-» 

E T 
X F 

in 

T3 

O 

T — ' 


■O n** Q0 
n -O X3 


o 

O' 


3 : — —« 


c a. a) 43 

3- II FX 

3-n» H) u 

*3 I C — 

43 — j m '♦“• — — 

v- — td m 03 r — 


— 43 
cr. e 


— = r. 


^ ^ >« 
— o: "c *-> 

s < 0 ) 


LU = CJ — 

H '—' II 13 » 

z n 11 43 03 

— U 0.-0 E 


43 — T3 4-» ■ 

: — v- — c id 


- £E >. II 

a 43 — 

- < w 


>s — o U 
4-» O — 

• CO — u 

u J* O 43 

O C H-> T3 

— *J 03 — — ^ 


(D E 4)^ ca 

— 43 —• —■ m CD 

w—|| 


43 — \ ^ — 


— ~ T3 in 

03 ^ 

— — L. E - 

T V * 

43 0) — in T 

• in in u T3 43 

— —< as t: v- 

03 43 TJ 03 X2 ' 


— 5 

x: 

s 


.c 

o 


• O T3 
> II II 
E 


T) »- 

r 


~ 03 w 

— = — n x: 

^ ^ E — U 

r : — in -*J 

II w X3 ~ T 

r XI w 4J E 

w u 03 — w 

- r. 4 -* — c h- 


■o 


- — E 


U ID ' 


10T3-E — '-4->EX: 

— W 4~> — T3 XT'-' i 

03 0.0 43 3- E H-. 

— 4-> 4-» w > 4-3 -— ■— 

4-> C — H-. 03 C «♦-. 

— — l/) 03 — 


! in DC 

UJ 

oS 


— a. 

* i 

o C 


X c 

* — 


E 

-O 


— 03 
— N 

a a 
» E E 

-O -0 


>0 — r\,ro<trx3'Of > ~co>0 — rsjro^rxior 

X» OOOOOOOO OOr^’ > -r»i>-n-<^r^.- 


a 3 > 0 -rMn'TXi 0 i^x>o-r\n-?£i' 0 ^cD>O-r\jn-<j Ll ior'X>O-fN( r )'j-inO r-co>o 
>*>*aoQOcoaoaoaocD®®ao>>>>>> >>>>0000000000--rsi 


Dr. Dobb’s Journal, Number 74, December 1982 


37 

531 


(Continued on top of page 36) I (Continued on next page 






J» Small-C Compiler, v.2 

(Listing continued, text begins on page 16) 
Listing One (Part two continued) 


E >v 

4 ) u 

4-> \ 4J 

«b * c 

\ 4> 

N * (0 —i \ 

* oj * o) 

4> (D X) O 

—• r <r —< a; 

<b O —• 0) 3 

-C -*-> T3 D CT 

<b O ib 

—* Pi . 4 _> —< 01 

—• O *-> 

Q. in Q. -*-> a) 

O O) O —« —« 

O 0 ) H-. O X 0 ) 

—* m -« —i 4> T3 

****** 

WWW 


C 0 ) V 
O O' 

—••Oil — 
VI *j - ^ 

in in — 
d t. r - 
i~ <b u a 
a a> w e 


CT—' 

0) * 

-H 1 
' 4 J -Q 

^ c -C 

"" * fb 

o 

O 


rr WX »0 CD > O — r\j 
--rvjryjrvj 


-C w ^ , 

H) •• h —( ; 

r —«a) <u > 

• - cr a a ; 

a * X <b ib ' 

j a> ix v ii +j v i 

> h*— —4 a) a> _ 

> T! to cr -■ rr rr i 

* £ - * -C ii n * 

' * *"* >*-w * — r\l i 

i-h>- 9j up r r i 

>4>w T3 T) O CT) lb * I 

L ^ C-«« C P- P-. -^i < 3 — 4—4 | 

0) O 

* % O 


~ ~ o 

«n ax 
a c — 

ib — Ccr 
— —• -j * — 
~ ~ w o ~ ~ 

--PlHW 

D 91 Cw (I 4 ) 
T 3 X) 4 ) CXa —i 
—• <b E * «b — 
w ^ 4 ) w -H .C 

a*-» ■*-» a-*-> * 
■* E m «b £ m —• 
O O •*-> D O 4 ) 
—> a in —) Q. T3 


t O r- CO O ( 
J t\i r\j f\i oj f 


)^'tnOP-CD>O—f\r0^r»O>-a0>O — fNjrn- 

• Z?~ — I2C2 — n un .n . 


u v- *-> v, 

*->■*-> c u. 

a a-« a) 

O' o +-> 

u O 4 ) 

(b (b a— m 


— ii a 

H «-> H 

co in co 



LU UJ u. 

cr 


a or z 

a 


H cd c 

X 

•» 

CO H u 

UJ 

w 

II CO H 

H 

1 - 

•*■» II CO 

io 

o 

mp n 

- ii 

c 

*j m p 

s pj 

H 

m •*-> m 

co m 

(O 

m m p 

< *-> 

II 

^ id m 

H m 

4 J 

- —* <b 

CO lb 


*i 

II 

4-> 

m 

IT lb 

pj 

1 m 

4 -> 

m 

ir 

P-> —< 

m 

i ib 

m 

4 -» 


m — 

ib 

< —i 

4 -> 

m 

•• 

<b ^ 


i •• 

m 

ib 


_ w 


i 

ib 

•—• 


— -p» 

•» 


—• 

•» 

r- 

*“S -- 


4 ) 

*• 


e 

W ^ 

w 




-»-> 

4 ) lb 

o 



L 


m h-* 

pj 

x: 

o 

0 


(b 4 ) 

o 


T 

H-. 

m 

u T? 

O' 

o 

O 

O 

O 

O O 

0 

T 3 

"0 

■o 

T 3 

■O T 3 

■0 



"" 


s " ^ 












s-s 






r- 

tm. 




O 

» 


lO 



• 

—' z 






rf *-> 




IO 

jC 

• —i 


4 ) 

fNJ 

- 

U 

s 2 

- 

’ ■— 1 

• 

s 

■*J 

4 / It 

o 

■H 

z 

l_ 


m >*- 

pj 

■C 

O 

o 


IC 4 ) 

o • 

5 

T 5 


m 

o P 

O'- 


w 


w 

1 . w 

w i 


IP 

W 

- 

II ^ 

A — 

U 1 

XL 
~ U 

x: 

u 

XI 

o 

r 

o 


r x: 

O 

X. 

u 


JZ QJ 

U £ 


X- -i_ 


.X N 

z *-> 

p-> 

pj 

pj 


pj 

pj 

-*-> 


4 -* lb 

3 d 

u 

u 

T> A 

p-> 

^ (b 

ib 

(b 

ib 

*T~ 

ib 

»b 

fb 


lb —4 


pj 

*-» 

4 ) 

m T) 

= E 

E 

F 

E 

CJ 

F 

E 

E 


E 0 


<C 

(b 

u C a 

"0 4 ) 

^ <C 

<C 

!b 

ib 

H 

lb 

<b 

(C 


(C "C 

o 

E 

E 

iDh E 

0 U. 

r w 


w 

cr w 





H 


II 

<b 

<b 

—•Co 

E fb 

U H-. 

H- C Pi 

C p- 

X 


p- 

p- 


Pi Ps 

II 



u O C 

M —< 

PJ 

— Q ~ 

LL -i 

CO 



. , 

o 


i. p-< 

v< 

4 ) •—* 

a u 

(b 

H 

H 

H 




t-. 


u 


1—4 s^ 

T) (Op* 

m 4 ) 

E 4 ) 

4 ! CO 4 ) 

CO 4 ) 

co 

4 ) 

4 ) 

4 } 

co 

a 4 > 




■w -H 

u T 3 

w m 

m 

m 

m 


m 

m 

m 


m m 


m ^ ~ m *-» 

c m ~ 4-i — 

••cm mm 
^ - r it c 

c ~ ~ o - ~ 

U- PC ^ II ~ w 

D fl) P 0»w u 

-*-> 4j r ir f a 

4 > u o —< m x 

UD UP ID 9 ) 

o o o u o o 

■O T3 "C U. -o o 

4 ) ^ ^ 


C r C ~ 

Uj< *"* 

3 9 )P = 

P 4 ) C'' E 

4 > u o ~ in 

u £ u : ib 

s x s •• % 


H P V. H-> 

in -« a> —< 

T5 T? 


****** \ . 
Vs ***** * 


'4)*^4>4>'^4)4)4)4>-'H 

tjt: T3 -o -o 

c p. C p« c ’ 

I 4) -*-1 4) c; 

% % % % % 


■'Ta'0r-ao>0 — rvim-sra 
_n _n n n n a a o -o o o a 

fMrsjr\jfMf\if\iivjrsif\jrgosjo^ 


■Oito^sO-or^co^O — rsjro'Tir»Or^-ao>o — xiDr* CD oO - r\jrr ) syaar > -x:»o — sr a a r'~ 

-<Nf\fMOjr\jcvjfMf\jf\jrvjrororOfOrnfOrnfOmf , 0'«T ^ ^ sj- ”=T ry rf 


Dr. Dobb’s Journal, Number 74, December 1982 






<N 


& 

Ci. 


a 

i 


O 

C 

o 

a 

.c 

c 

o 

O 


\ 

♦ 


■O 
T3 
fl3 


U — — 


CD — 0> \ 

| — -*J C - — 


T> 

C > D in - 

0) -« 


CO "Cf J 

f—« — ■—■ to 

to £ cr ii 

U * 4-> 

x- -*j u 
4) ■— ■*-> CD 

T) * c * 
x-. in in 
— o 
* o 

oo o o — 

r- >* ao co 


CD II — 

v- u cr = 

a> -*-> * w 

£ a— c 
i * d a; 
in uihji 
II II -4 o 
x i: +~> 
0) 0) * £ 
T3CD0) 
5 l T3 » 
in in <d c 


<D -i 


CM ■ 


£ 

CD * ■ 

~H \ • 

4-> * 

a> 


E X A 
CD A 4 

* ch 
i \ X z 
in — i 


— c 

*-» Q) 

k. O 

a 4-» 
x £ 
a) a; 

O 4) 


O' 

— II — 

O - £ ~ 
II — CTJ —- 
4-> II —< 4-J 
—« Cl) £ C 
3 > C 4) 
CD —< 0) E 
•*-. 4-j ^ a; 

a) o a. *-> 

£ <D E cr 
5 * 3 4-> 

in in *~>m 


— £ 
x c 
uu u 
O — 


k. O' o> x m 


a v- ■ 

o - 


m - 


in 

< — o> x-. ■ 

1 —< a> 

| w -Q 
i * £ 
l in J 


0 ) — 
O' — 

id O 


0) 

T? - 
5 *-* 
in —* 
~ H 
cl~ 
E X 
3 LU 

■~>o 


*-> rr 


4) 4-> 
— £ O 
X 5 CD 

a> in 5 


> *— 4-> <u 

■ —« in £ 

1 C —» X-< ■*-) 
0) 3 
£ O 


5 

3 

CD —< w J 4-> II 

h-. a> 4) m —« a> 
a> £ —« ii 3 > 

D m -h p m •- 
— * —< r. x x- 4-» 
m -*-> i a) a) u 
w w m —< c "O <d 
—I x- O 0) 5 * * 
c **h o. £ mm m 


0) £ 

c 


~ ID C O 3 

— * * l- •*-> 

ii in in c D 

in ~ w a) v- - 

cd x- v, 

U —< ^4 

O 

TJ 


-*-> ♦ 

X 4-1 
0) X — 
C 4) -~* 

i c = 
in l - 
+ m r 

—< V- C 
m Q. ai 
£ x .* 
(D 0) O 


—' ID 
3 * ' 
id m i 


0 — 0 ) 

c = £ 

: - l 

= m 

U V-' W 

O C -I 
u a> a) 
x n 

0) O CD 

•*-> —4 

a) £ -*-> 

» m 4 ) m 
—<0)0 
a) c a*- 


D!^^£J5^22^ o '” rgr0 , ?^''Or^coD»0-c\rnv u no>co>0-f\n^ L00r-CD>0 — r\ J rn^^or-co>0—fNj 

COCOCOOOCOXXJCO 0»0» ^ 3> O' O' O' •>>’>0000000000-— — — — — — — — (MfM<MrMfMCM>'M<MiMCM£ f ’ r > f ' r > 

— -— f MfMfMfNCNfMrsjrsjojf\jrvjr^(Mogrvjrgr\jf\jfMrvjrvj(M(Nr\jC'jcojrvjrsjr\jCMrvjcvjr\j 


V. * CD 

O a; —< 
w- E 

k. — ID £ 

0) — C (D 
rn £ 

- II m : 

C O w w 
(-» u o> k. 

C A o E O 

—< ID U 
H O O C V- 

CO — O' C E 0) 

~ O X - 

>*-« o c a) m a) 

I)-*-)'-' m v_ m w 

"O o x-< -h x-. —4 m 

x-O'-^D-^OJC'-' 

-< O 

% T5 

or-xoo—rvj 
cnncnnmrn.'n^'t %r 

fMfMCMCMc\jcsjr\jrMr\jrsi 


II O 
-* II 
= O' 


+ \ m 

* * c 


\ 

♦ 


m 

(V 


£ 

ID 

U 

ID 


ID 

U 

o 

-< \ 

* 

0) 

u c 

ID 0) 

—< a 
u O 
0) 

TD —< 


O 

C 


0) 

> 

0/ 


X 

ID 

E 


* 

\ 


\ s 


r 

c 


o 

a 

E 

O 

o 


£ 



a—< a u o 
m > m o ii 

o cc u —< T5 

> m ii n D 

id * a u i. 

m m O id 
v- o —< -4 

4J id > > u 

C £ CD CD O' 

•'■< u in m T3 


— o 

JC c 

u ^ s 

4-> V- — 

CD — V- ^ 
E x-< O id 
•» w o V- 0) 
Q. 0)V-U 

E 0) w 0) £ 
U—cx- 
C —< —< 

♦ £ 

♦ 5 


\ 

* 


C —< 
0) CD 


*D—i —i 


0) 


0) 


0) 4-) 

m o) 
O —• 
o —i a> 
■OUT} 

•♦c * * 

\ \ \ 


co — 

*—•*•■■< C\J 
— J k- 

— V- 4-> 

k+j m a 
4 -> a ii u - 


CD -X H 

4J 4-> C - 

m mo 
*T3H 
o) a o to 

m e E 

—■ u li X- 


E H 
X'Z: k. 

m lu 4J 

4-> o a 
X •—■ u 
D •—* 

C k. 0) 

- II 4-> —< 

CM Q. — 

U U £ 

4-> — J " 

ax- 

u —* 


I Uk U J 


\ 

* 


\ — 
•♦c £ 
ID 
m •'-< 

—i k. 
O CD 
£ > 
E 

>K 0) 

m k. 

(D 

CD U 
O 0) 
O ID 


u — 

O I 


\ CD 

* X- \ 

♦ 

£ £ X 
U U ♦ cx- 

c c 

CD CD 4-> 0) 

k- u c m 

£ £ 0 ) —< 

F 0) 

0) "O 0) • 

m c 4^ . ■ 

—I ID ID • 


* m —< —i 


a 

E 

3 


O 
!—• 
to 

II 


\ 4) 

+ m \ 
3 * 
—i CD 
0) —■ —■ 
£ U 0) 
ID £ 
—i r id 

0) —i 

0) m 


0) k- • 
£ Q. 0) 
CD X 3 


4) 0) X. 

O' O'-* 


2 

DC 

Z3 


O 

4-J £ 4-> 

C C 

a id a 

* * * 

\W 


• — ~ 4) = £ 

j «-■ to m x-. id 

) —4 LLI —I -< -4 

3 4) >- 4) = x-. 

4 £ - = w 

.CD * ~ ' 


4-> £ 4-> 

i 0) ID C - 


O'- 


4) ID 


—i 4) 

CL £ - 

1 E CD C 


E E m 4-) 3 
, _ w a) id m 4-> 
DU4J'' * 0 4) 

J CD m ID \ Q. k. - 

: —< 4) 4-» x-. 

. h_ 4-> m — 


CD 3 — 

-HH 4J 

4-j c m 4J 

4) o 4-> m 

O'H m 4-> 

ii to id m 

<M —< (D 

£'*-'- -4 


— CM 

£ £ 


£ 4) £ 

CD E CD 
—< 4) —I 

X_ 4-> 4-> 4-> 

-4 m id m 

£ O 4-) o 

c a m cl- 

4) 


• O'—!) 

4-) X- O' 

v m D'' m 

C £ — 4-» 

— o + in 

^ O 4) 4-> 
k. V- —I 4) 
q. 4 -» in « in 
X C £ £ 

4) -4 O * 

O 

£ 


i>o-i\n'titor'co oO — cMrn^£Or-co>o — cM r o , ^£>cf^'Coc>'0 — (M^'j/io^i^o — r\in'ji'i'Or'C0>o — (MnT l ri'Or s 'Doo-fNj 

££■£££££££ D00'0'00'00£ OO>-r^r-r^r^(^-r-^-r^.-^00XXX£XX£XX>>O'>>>'X>>>OoOOOoOOOO- 


00 

t>0 

a 

KX 


Cl. 

o 


c 

o 

<li 

3 

•S 

6 


Dr. Dobb’s Journal, Number 74, December 1982 


39 

533 





c 

3E 

=3 


(\i P\j 

U J 

— fN 
(M r\j 
u u 
o u 

03 03 
T) TJ 
D 3 


— rsi ro 

O O O 


— O 
X II 
X II 


-CD 
0) (D 

w « 

>>DO 
X —• II 
C — II •• 

X X ~ 

— - 5 O - 

c — x 

^ «J 4) ^ U 

— — 10 **4 O'* 


«0 c 

M U 
— C 3 


C — 0) 


o 

X 

& 

>H 


0) 

E — 

<c 

C = 
10 X 

* 03 


-C 0) 
u TJ 


~ TJ 
0) (D 
E 0) 
(0 U 
C — 
tO <0 


— fMnt.noNcoo.o-fMn 


03 u — 

E O * 

<c u c 

CUD 
— 03 -“l*- 


lO <3 co o 


O' 

c 


o 

Q 


u — 

<TJ O 
X H 
u n 


V) X 

— o 
C *j 
03 (0 

.* E 
O — 


3 
~ E 


> O 
—< u 
TJ U 
03 0> 


O 

H 


X 

U 03 

E - 

03 U 

c *-> 

03 (0 Q. 

E — U 
«c 3: x 
c If) o c 
to < u u 
— X «D D 

-C 0) 4-3 
—« ^ 10 03 
O 03 — U 
T3 -Du 
C H-. — 


o. 03 a 

DEO 
—« <0 — 

- O' c e 

D lO >, 

—J v —■ V) 

O cr •*-> 

u 03 X 

a -*-» u 03 
c a -*-> c c 
H u 10 II 
to — 03 U 
|| 0) — 4-3 

i—i v- a <*-. 

<D 4-3 —. —« O «■*>. — 4 

10 ax X 

* c 


03 


03 


0) 03 

E to — 


c * ~ 

tO \ 


u a 

4-» U UJ 

a 3E 


I 


U - H U 

IT3 — or ♦ 

x < e 

o I f— I (0 

to c 

u U to u 

•^4-3 A 4-3 <— 4-> 

03 X X CT X 

E O U O 03 O 

(C O 4-3 u - 

c —< a ii 4-3 n o 


to 

— N 


to 


ec u c 

03 4-» — 4J u 

O U —I X 4-1 Q. 3 

—< 4-3 — O — U — 4-» 

x ax 03 

c u 5 u - 


U 4-3 

a 

• o 

U -4 
•*-» -k 


a d 

O' — 

— (T 


<0 "" E 

> U to 

- 4-3 C 

* a a to 
a >, x — 

>»4-» — x 

4J O' — 

-■o'*# 

TJ — M C 

— II — 

• H-t 

• 03 U II 
03 6 4-> CM 

E (TJ a U x 

(T3 C U 4-3 LO 
c to 4-3 a< 

to + a u x 

— O' — 

E U —I H-, <4-. 

>s <0 — — 03 

to X h— x 

Xu— H-. 

TJ — 


o 

f 

JU 


— X 

o 

o oo 

II : 

II — C 

u u u 

4-» O D 

a u 4-3 

U U 03 

- 0) V./ 


o-fNjn'T/>o> 

rsjrsjOjrsjpgr\jrgr\i 


Q0>0— rsjroTj-X O r*~ ao o O — r\j cn 
rgrvjroro<' r >''O r Ocn<xrocorn»yTr'<TTt 


'JiPOMD^O - fNinv^ONCO > o — CM (X 4T in 

in -O O O O O O 


M 


_ 

■ 


■3 

> 

u 

on 

u 

3 


CQ 

a 

_C 

’■C 

ft. 

c 

3 

0 

0 

1/5 

0 

o 


s 

o 

a 

‘on 

o 

42 

-4-3 

E 

0 

■*- 

X 

03 

— 

u. 

CO 

a- 

o 

o 

T3 

03 

3 

.s 

■*— 

0 

c 

o 

■ 

c 

0 

0 ) 


y 

c 

(Q 

00 

c 


E 

u 

2 

</> 

J 

□ 



N 

* 

\ 

* — 

0 > 

x u x 

* 4-> fO 

a — 
c 

03 ^ 4-» 
a 4-3 — 
O to X 

03 

to a 
a a o 

O 4-3 

o c 
— (Da 

03 f 

O — 3 
C U —1 


\ 

* 

X 

* — 

0 ) 

X U x 

* 4-3 (0 

a — 
c 

03 _* a 

a 4-3 o x 

o to o * 


to a 
a d o 

O 4-> 

o c 

-iDa 

o « | 

c u —> 


E 

to 

(C 


to 

(0 





•4 






— 

U 






4-3 





%— 

a 




to 

— 

— 




UJ 

03 

i 




>• 

X 

u 





(TJ 

4-> 




• 

— — 

a 




03 

TJ 





E 

— X 

0 ) 




(TJ 

\ <D 

> 



u 

- C 

4* W 

(TJ 



4-» 

u to 

\ 

to 



a 

4-» tO 

H 03 — 

w 



— 

a- 

II X 

a 



0 ) 

— 0 ) 

— «c c 

E 


—* 

> - 

II E 

— — U 

3 

•4 


(TJ ~ 

U (TJ 

X 4-3 D 

X 

o 


to — 

4-3 C 

U 10 4-3 



— 

* to 

a e 

O 0 0) 

03 

c 

■—< 


—• > 

a u ^ 

to 

u 

0 ) 

u c 

0 ) (0 

H- 

— 

3 

X 

(TJ (0 

> — 

— 

03 — 

4-» 

(TJ 

X — 

(D'U 



0 ) 


U X 

to — 



u 

o 







TJ 


X UJ 
< rsl 


—i: 
LU ‘ 


E X 
ro < 
C -J 


o - 

II — 
II c 
— z 


— UJ x c 

TJ Q "O — 

— C *— (D 4-3 

— — il 03 

'4— U U o 

— || 4-3 4-3 w 

— u a a 


x 

(TJ > 

T) - 

T) 

tD 


to 

— UJ 

o > 

H 

— II—* 

— — O 

~ 4-» U 

— to a 4-3 
C T? X to 
u C 0 ) T) 
D 03 O O 
4-> — X E - 
O H- 

u — 

O 

TJ 


s 

E - 

03 — 
' in 4-» 


— a — 
£ioh 
5 0 — 

T) S X 

(TJ — UJ 

(DUO 

— U 4J 3C 

- ii a — 

u u — u 

^ X 4-3 w 4-3 

— a a ^ a 

^ ¥ — 4-3 — 

(tj — to a 

0) 4-3 X E 

U C «u O 3 

x — — e — 3 ^ 



0 ) 

TJ 

O 

E 

v 

u 

(TJ 

E 

* 

X 


a> — •» 


— a — 
x to a 
5 0 0 
TJ 3C O 
<0 — -J 
0) U O 


— - ii a — 
u u — u 

4-3 4-> w 4-3 

a a nc a 

— ♦ — 4-> — 



4-> — to a 

C 4-3 X E 
0 C 'M O 3 
U — — E 
0 
X 




o 

T) 


( v )*t/io^a)>0-f\jn'rjJor'CD>o-(\inM , JJO^xoo-(\( ,v J^jTor^co>o-(\n7JTOr^co>o 

'T T ’T rr rf rf x X X X X X X X X X OX'O'OOO'OOOOf^r^Nr^l— r'r'N>^c03)33BXJ0C0DC0lD> 

csj(\j(>j(Ni(>j(>jrsjr^rtjf\r\jrNjojr\j(>|(>jryr\irsj(>jcsjrvjrsirN4<Njrsirxojcvjr^c^r\ic\ogcsjrvjr\jrvjr\jrvjr\jrNjrvjf\i(\i<NirsjrNi 


(C 


X 


3 

a 


to 
(0 
TJ 
c 

0) - D 
% -* O 
r <d 
— 0) • 

► X U 0) 

' u D C 

' 4-3 — 

j m 4 h 44 

: E o — - - 

4 — 03 4-3 — || 

4 — D — 0) 

i'Z'H ° zi’S 


— (Mn-^xor-cochO 

ogfM(Xcvjogc\f\jrsif\j(x 


42 

534 


Dr. Dobb’s Journal, Number 74, December 1982 




\ 

* 


\ 

- + 


*-> >S 

Q. V- 
O O 
F 

I d> 


V- c —. 


O - 

-4 LO 

to lO 
f\J 
<D o(3 

C 

X d> 

C ♦ 
0 ) V- 

TJ X 
L- X 
O <T3 

X * 

O 


x 

x 


■ < ♦ ^ .. 


o 

— jC 
CC F 
-J >> 

C if) 
o 

2 —< 

LU ro 

£ 

II O 

U A«- 

— oo 


z a u u 

>• D O 3 

Q ^ C +-> 

O C d) 

^ w qj w. ^ 


a*- 

—< U -H - 

X X 


CO — 

1 O 
O X 
C E 
-J >. - 
C vi ^ 

2 LU 
LU —< Q 
'-TOC 

O O 
A O 2 
— 2 
U = LU 

4J w w 

a c +-> 
u o u 
o u o 

' -H »- A 

v- 0 ) ro - 


— ••rood a> 

x a -4 e 

-t >. u - f\| (0 

II 4J || d> L- C 


Q. — II — Z +-> 

o s— —• to —< a 
—« 2 lu if) ro o 

* LU Q. < > 

II Q >- —I — II 

L- — H O 4-> 

4-J ^ C <"0 

a UV-V-—L. 

U 4J 4-> 4~> 4-» 4-> 

aacLra 
u u u a u 


3(3 (M * 
W- * 
II +J 
II Q. I 


V) 

* 

~ X 
C to 
ro < 
— x 


—• 0 ) 
X X 
x < 4 - 


4-> II 4 

a i 
u rvj i 
P L( 
CL *-> | 

o a i 

—' u - 
~ * - 


*-> •» 

CL fNJ 
U L- 


l~ U 

-*-> a> 

CL 

x c 
— o 

O' -4 


a. m — u -< 

o ^ ro 

L < Q 

II +J 2 L 1(1 

Q->- 4-3 U 

rvj V- Q CL d) 

U 4-> O' O' 

4-> 2'*-> —< 4-. s 

d) Q. O' d) - -4 > 

W u —« X H-» * X ' 

-4 * * H-. -4 \ C 

d) -4 d) 


X ♦ 

U -f 

>s +■ •» 

~ U >s >s 

>4) L L 

X u c 4-» 4-> 

LO 4-3 d) C C 

< C d) d> 

X d) II * 

w c 

»4 E >di L 

d) >.Lh 3 

X W 4-> -4 -*-> 

C 4-> C X d) 

4 — x a: X L. -- 


L- d) 

d) D 

o a 

d) d) 


4-> >> 

d) x 

O"- 


ro -4 -4 


i 

► U I 

L- X C ~ 

X T) d)H 

O ro -4 

ro - w c 

- »4 * d) L 


X I 
X I 
ro c 


Or^x>0-r>jn-? l nor 

00'00r'-r s -r'-r'-r-»r^-r'~r 


CD > O — fNin 'T /I O 33 >0-f\l fr )^in0r^X O O — fNJf0^rX>0^-00>0 — r\j ro tt O 

r'-r'-ao.xaoaoaocojoaaoaooooooooooooooooooooo —-- 


('-co^o — f\i<o-5rx*o.~^ao > o 

—-(\l(\jc\ir\jr\jr\jr\jf\jr\ir\jx 


• rv. 

ro — 


4-> 4-> 

a c 
u z 

+ O 


L- 

a 

a 


<L> 



cl ro 

c a 

* 


• 0j 

ax 
4 -. c 


ro —i —• 


v- < 
ro 2 
x >- • 

OCX 


•VJ «Nj — 

(O — LU 

a to vj 

I—* LU •—■ 

sc to 

•>- «r X 2 

tO — LO LJ 

-io<< 
X — X s 
roro — 


LU L 

u M r 
rsj — . 
— to t 
to l 


-******\-^4,-4 

— fMPO'SJ-XXr-OO >0— r\jro^riO- 


• • d) d) 

I C 4-. *-> Q"+- C 4- O C C 4-> O"*- c **4 
v-d)Erod)u-4u-4-4d>Erod)U-4 

) d)'n>v4->'cro'oro—i—<tn>-+->xrox 

4-> m to 4 - ec e a e —i in in 4 - ec 

\X-4*-*t-4*d)*-H*d) -4 <u 

■*(d)% « « « 


a ro ■ 
x c 


C 2 

o — 

4C -I 

s 

— d- 

o c 

u —4 — 4 ro u ro 

ro — -4 ~o —< c 4 -j 
E a e c ro — 4 in 


4-> 2 
C >- 
— C 


l * a 
) cr 
MMC J 

4-> — * 


c 4 - i_ a o' c >■ 


d) — tj 
in o x c 
— X c ^ 




• > C ' 

• X d) 4-4 ( 

4-» ro -4 
d —< a c i 
a L. i 

C X d) I 

44 c in *-> < 


rsl 

S 


d) V- d) -4 

X d) d) x 

4 - 4-» a c 

. -4 X d) 


C0>O-f\rn'7nOr-X>O-O0n'7a'lC''X>O-(\ro'JXiOp-QD>O-fMro^OOr^X oo 

-rsjrsjrvirvjrvjrsjrsjrvjrvjrvjrororoxxxxxxx^T^r^-^^^^-^-^^ri^oxxxxox xo 


t3 

.C 

4--4 

c 

o 

u 


Dr. Dobb’s Journal, Number 74, December 1982 


43_ 

535 


on top of page 42) I (Continued on next page) 





o 


^ in 
O w 
li ^ #j 
II u 
■C o o 
U 0) U 
w Q. 

w Ol (D 


g -c C UJ 

" - C 3 H 

J- — 3 <\l 

C* w • +j 

O c ~x £ 

Jr — x < 5. 

a c c* c 

„ <D XX 

* a n z 

o o h •—« •» 

—> ^ — rvj •• C ^ 

*0 X C *-» » ^ 111 lii 

C \~ r a) .*-» h ii 

* aj3ac-c — *> 

N « <-> C -. c (\ 3 

i dwh 3*j a „ 

*" i ” “-2 «-> w «> a.-. oc 

a-- *j me v, t 

r3T- rt C^CDO«D ^ Q. 3 

„ J a H OH--, QJ 3 a) 

r* 

cc u^£ ^ 

c I 

C O) 


r u - -h 

: * v, ^ ^ 

r ^ ~ ^ a 

c ^ Q. —I II 

■« H-. 4) -H w 

f _ 2 ~ u 0) 

7 r. <T3 > — 

= ^ 7? ^ ^ E a>a) 

^ D ^ > aw V- TD -H 3 

J-.E f ® ^ 1,1 10 c ac 

‘ t! ^•''cinvi ^ ^ 4_> 

o ?rr - we 

° E f ^ H I h_ n 


3OOOOoOooo2>2 l NJi0 l 2CS?2; f ' , '' ,7 - ri,or '®O'O — nj 


•ry2^£O^“0>O-rx J ^q. u - lO ^ 0D 

— “ — ““ , N , V‘'a<Ni\cgrvf\f\f 


^ <u 
^ 00 

CQ 

3 

_C 

vi Q- 


ki C 

— 

o 

4) ° 

mi ^ 

o 

Cl 

a 

a f 

£ 

e £ 

— 

C x 

eg 

0 

— 

O 

w <u 

3 

0 

c 

O S 

0 

1 C 
™ 2 

<0 M 

0) 

c 

■M 

C -S 


c - 

M 

<o e 

■Ml 

-J 





a 

e 


o 

w- 


a 

u ^ 


II 



3 

ox 


II 



H 

H < 



*“* 



—> -5 


-C 

r 

»-* 


^ X 

•» 

u 

u a 

0) 

•—i 

— 5 

o 

*• w 

w UJ 

in 

0) 

0) < 

II — 

^ 1C 

c a 

<0 

E 

E Z 


w r. 

ic a 

u 

H3 

<C V 


in a 

w r> 

3 

e a: 

C 

— c 


in E C id *-« ^ h— 
ID ID +J COwO-'-* 0> ■*•« 

+-> CC—•H-.llXT’C 

E -H£ *H ^ J Hh 

* * \ >, 

N * * in % 


1 w o» u 

H- ED 

<C *J 

C 0) 


— (N^^Ln Ofwoooo — r\jrn^in>or^co>o—rsin^.n 

r Dl y )' r )l r l , ' r )l Y )l r )l , lrn^ ^ Tj - rf rf -rf Tj 


■o r- co > 
n in x» .n 


O — rvj rn ^ 
•O <3 O O O 


* * \ <D 

X * * O' 


.^'or-aooo- 
O o o o o n r 


0) —• — 
a *J ~ — 

IT3 C w ~ 

4-» l~ O —• 
in a u c - 
. o 
a 


x > o — 

r- — X X 


a C 3 3 
— o o 
* * \ w- 
s * + a 

fM^O^X^Op-XO* 

IXXXXC0XXX 


Dr. Dobb’s Journal, Number 74, December 1982 





Dr. Dobb’s Journal, Number 74, December 1982 


45 

537 





’ - -O E 

r °°s i 

l. IlOw 

' (T — 

-C W II H-. 
I U N V 'H 


A <U —. ■ 

* ~ O — j 

w E ^ || * 


V- X ■*-> — 

<V *-» <D W o 

n x c z 

U 0 ) 0 ) w c 

c r* U u 
^ D m O 3 

U O'*-* U 4J 
—■ <T3 to V- <x> 

a- *-> ^ a; u - 


0>O-t\n^j)^fs.Q3^o — rvj 
f\if\i<\i<\jr\,r\jrvjc\ic\jr\4CY(\jr\jr\j 


n in o r- ao 

^ n -n n n 

<M r\j (\ oj r\j rsj 


> O — rvj ( 
r>g oj og r\j f 


-~o~ £5= - —i5 ^ 

J -v.C'nr^-^ C.OTj'OO W "DO t * £ r h- 

° ^ ^ c C H-. U C V. * ^ is 

° O * * 6 % £ g 

■^'r->i?j;ipS'rIJiloriS?!§o' 2 oo' 28 oo 22 — -H omuo-i 


> 01 
s? 


n o 

t; 

0 s 

012 


CO 2P 

El 


o — - O 

II U * W 

ii o ic r 

-C U. 0) u 

U W. U. Q 

^ a> _o —' <u 















o 





II 




v*' 

II 





*«■* 





•—. 




— « 

s 




N 

\ 




* 

N 




V 

II 




II 

II 




II 

r 




-C 

u 




u 

c 




c 

w 

M. 



>-• 

afl •• 

-V 

•• 



« ^ 

03 




\ — 

05 



> 

* w 

u 



\ 

v Q. - 

£3 

n 


N 

HE ~ 


U 

•• 

II 

HO w 


O' 


II 

-c n a) 

«*_ 

w 

> 

r 

o c 

0 

n 

po 

u 

*» w -rt 

0 ) 

u 



— 

—. 

a 

- £ 


CU'-'UO)'*- 

<*_ 

0 ) 

^ u 

'*-. 

w a) ^ in —• 

-«-H 

0 ) 

— a 

• 9 -i 

a-i «*-. 


-V — 

-C 05 


E — 0) 



O 0) 

05 

d r 



O'* 

in £ J 









0 ) 




a -< ■ 

^ E ( 
D 0) 

13 V) . 


i v ~ M 

^ ~ 0) 

i w r e : 


ii o 
u <u n r. 

~ in m i - 


0) -J — 0) 

a> n ^ c 

-* A O —' •» 

U w —« ^ 

0> *-* £T ao 

in a u ii — 

—* a a <d a 

<u ~ a> c e 

h-« a> —< o 
-• j-: —■ o " 


f <u - - 

03 E ^ C 

C 03 ~ V- 

- E C — 3 

* >—i —» *J 

• m -h o) 

| w ^ v_ 

c H-. 


n o I s * cd >0-nif f i^,noMD>o- 
>>>>> 0000000000 —■ 


■ ao > o — f 

-<M P\j < 


'>x>o-Piin^noi^cDo>o-t\n'j-no^cD 
If\f\f\li2 r, 1[2 rnn ' r,fnnrnn,f,r <T ^ <T t ^ 


> O — fNJ rn 

t n n n n 


46 

538 


Dr. Dobb’s Journal, Number 74, December 1982 





C ai 
O 4J 
>s 

£> *- 
43 •*-> --4 

-■c r t) 
—• o c - 

O —« 0) 

o % * 


L- 4-3 - 

43 W O' 
X ~ in 

4-> u E 

— in 

• 43 4-> 

v- -or 

. u r- «*-. o 


w D-h 
C l X -> 
J O 
• O' A 
in ^ ^ Q. 
E E <D v. 
^ V- V) V 


(TV--' 

x: - - a 

u (\ a - ^ 

♦ —• a 


-< = ft 

• n ♦ / ft 

O' * ♦ / * 

in * \ ft 

E - — = = 

W ^ a; W W 


o c x 6 O 
l. —■ i —« m' 


CT4-> O + ^, y 

a; c n x 

u M * 


in •» 

^ m <u 

cr .. _ 

a> -u o —i 

»- c „ r 

«-* — ^ 2 


r- ao > o 

33 X 30 > 

r\i f\j rvj r\j 


— rvjr05j-r»'0.‘^X>O — c\jroiTXi'Or^cD>0— rvjrn^- i r>0f^-X>0— CMtx^ir»0r^X>0 — r\ ) m'Ta'3 0r^X>0— rvjrn^ l rio.' > -® >0 


C 4) 

U —* 4) 

43 -h £ 

E X « 


43 --> O 

EL. L. 

43 *-> U 

c a 43 

in u E 

E N s ■ 


X ~ L- 

U w X 4-> 

CTX < in 

u * 

— O'O o 
< l. 
W o * u 
43 43 II <0 


V- 4 ; 43 

4-> E E - 

Q. «3 w ^ 
U C CT U 
43 m U 43 
E ~ 43 E 


c 

U 

E 

4-> 

E A E 

o 

-*-> V 




o 

c 


43 

E CM 4-> 43 

Li 




in 



E 



4) 


c 

43 43 


- u 

43 

4-> 

•vH 

4-> L. = 


a l- 

•• 

X 


H-. 

V- 


E 

43 V- a u 

4-> V- 

•• 


•» 

ft 

•» 


43 


u 

U 

43 

Li 

E E 

•» 

’ 3 

E 

3 

X 

3 4-3 w 


O 4-* 

O 

in 



3 


43 

C 4_) u 4-> 

a-4-) 

o 

43 

u 

n 



C 


43 

4-3 


3 


o 

, *J 

w 

Q. 

ft 

a a l. 


43 a 


< 


X 4J 


C 

m cl ft in 

u a 


E 


u 



in 

•» 

E 

in 

vi 

4-> 

43 43 


43 

4-» 

v-' 

»— 

w O o 

o 

E u 

c 

X 


o 

4> 


in 

ft U w m 

w o 

c 

43 

» 

w 

C 


■w 

o 

w 

43 

X 

43 

—i V—i 

c 

Li ^ 

C 

43 

a; 

41 IT U 


— 43 

l. 



u 

U 


•»— 

II 43 ^ 

w 

u 

C 


4) 

U 


<J 

II 

43 



L. ^ 

vi >vi 

L. 


■H 

—< '*-■ 

—4 

— E L- 

u 

cr e 

3 

>*-. 


43 



X 

i_ --- 

4-. H- 

3 

in 

•» 


3 


fC 


__, 

H-* 



X X 

3 


» 4-» 43 

•H -H 

vi 

v4 w 43 

43 

U 

+J 

43 


4) 

C 


o 

® V-H-H 

•H -H .—. 

4-3 


4-3 O 

■-i 


43 

E 

u 

Vi 

.-i 



5 J-s 

4-» 


3 w 

x o x 

x <♦- 

F 

43 >*- 

43 

X 


m 

o 


u 

x ax 


43 

X 

C II 

X 

4' 

m 

X 

43 

X 





43 


a—■ 

* c 

* 


-*-> 

E -h 

L. —v 

H— 





43 

U U 3 


L. 

in 


2 

L- -x 


c 

E 

2 





L. 


43 

43 



3 



•t-4 

♦ 

* 

♦ 

\ 

43 




43 




43 











% 



a 



* 

\ 

* 

* 

ft 

m 




X 





H-i 









~ v. m ^ -4 — E V- U CTE 3 *- 43 XT V- 1 - 3 in — —<3 (c * —. X X! 3 ■*-. 

^.O 4) '•"H 4) 4-» 43 -4 —-« .^ -r* >-* 43 4) U— *■> 4) 43 C U Q V -h h h <h a iJ v^+jO-P 4) E u —« —* i * ^ *-> —i 

h x '«- r w rDrr^ f 43 h-« 43 x in o l. x a x 43 x c y x 4 .' in "o 43 x 430 

Q -— 4 * C 3 * Vi 4^ E u -- •*-. 43 O U J L- in —. —. X i_ C E 5 L, «*» C 

® « 3 -r* ft ft ft \ 43 43 D — 43 

'ra3 0>CD>0-(\fn'Ti3 OMD^O - rsjrn^j- i3OMDO.O-C\n’J-/»Or'C0D'O-(\rn'TXU)r^C0>O-<M' y 3 , f-3 0>C>0 - f\J fO ’T XI O CO 

C3ii n/iiiui OoO OOO Oooo^r^r^r^r- ^rvr^r^r^aoaoxcocD»cooo®ao>'>>>>>>>>>ooooooOOOO--— 

— — - — —-— — — —--— —--— — —-— CNCMOjCNirvjfNjCNjCNOjCNjrMCNjCljCMPijCVirsjrsiru 


Dr. Dobb’s Journal, Number 74, December 1982 








P P 

to to 

P p 
W P 

o 

p p 

C O ' 
ib h-. —* 

P TO 


P TO O 

o 


—• >- 

to o to 


p p 
TO in * 
-P It 0) 

C TO \ E 
CO -P U 
O - P in 
■h w 0) 4) : 

in in +j ro 
w a) in o 

ai p -h ^ p 

p a O' p <d 
a x 


X <D P ' 
TO 


o = 


in .p 4-> p > p p m 

i l l I I l I I 

O—rvnTj-iri'Or^ 

lT3rOCD<T3<T7 (TJfniT> 
>>>>>>>> 


*********\ 

\********* 


io«o - r\jrntrio^cD!>o- 
p p — . 


o 

II 


— o 

, c in 

1 3 P 


: \ .* 
: * in 


. q.p p _ 

> o in ••-Dai 

) ■* TO •O'-' •—* C 

l p ii o> a ^ 

> p in —. it p 

• p p p ^ —« 

re c p p 

h£ J 


- a Q. in ii 
- 0 ) o 

O' P 


0 p in a 

3 

~ p p 0 

O 

a.c — p 

a 

E .C "O 

0 

3 P 

p 

n — 

■p 


■H^CDdMillO 
P P 0) C£ - D£- 
'-^D'-TOTO'—TO — C 
P OP'— ' P «—< ■ P 

•h a in ap in p —« c 
oceincinop 

TOP 03000 >TO 
- m "O o a o a—< p- 

to 




\ 

♦ 


p 0 

P 

>v 

.. 

» 

TO _D 





O 


0 


•• 


II 


E 

> 


w _, 

C 


TO 


~o P P 

c 

p in p 


—< 

> TO 





P 


p 




r—> 


O 



_< 

O 


> 


P U P c 

TO 

to in 0 

O' 

TO 

P p 





P 


P 


—- 


no 


P 



TO 



__1 

V** 

TO TO TO TO 

P 

P TO 

c 

> 

C P 




•» 





w 


__1 


P 

» 


> 

in 




P P P 

m 

c p in 


a 

TO C 

•» 








«—1 





_ 



a 


» 

M. 

TO —• c in 

c 

0 p in 

c 

0 

TO 




w 

U 


0 


TO — 


TO 


P 

p 


w 

E 

TO 

P 

--1 

-< P c 

0 

u P TO 

— 

p 

» 

r—1 




c 


c 


P ~ 

•• 

> 


3 



p 

3 

> 


_ 

D C O O 

u 

TO TO P 

0 

p 

«—t • 

TO 

•—• 


TO 

3 


3 


TO P 




O 

X 


in 


TO 

TO 

r —4 

to —• a 0 


in p 



TO P 

> 



P 

H—» 


Pi 


—« TO 

P 

II 


a 

TO 


c 



P 

TO 

p 

p 

c p 

p 


> TO 


'"N 


TO 

P 


P 


P —< — 

TO 



0 


•* 

0 

* 



> 

P P H-. 

O p O TO 

TO 

0 

a—i 




r-H 

in 


in 

** 

to a 

.—1 

CVJ 


p 

» 


u \ 

P 

» 


—' O O -n 




c 

0 a 

* 

P 

•» ^ 

P 

TO 


TO 


r> 0 —• 

P 

w 


p 

U 

--I 



TO 

P 


0 

TO 

P TO 

in 

3 

p 0 

P 

P 


TO 

P 


p 

, —1 

II P TO 

C 

r—H 

•» 


c 

TO 


M- 

5 



JD to to to 

3 

TO U O' 

E 

p 

p p 

--t 

in 

0 ) ~ 

O' 




TO P P > 

TO 

TO 


>> 

3 

> 

r—1 


O 

O 

P 

e a a 3 

—1 

3 C TO 

P 

p 

p 

TO 

a n 0 

II 

» 

in 

» 

> 

to ^ a 

—- 

> 



P 


no 

_ 

r-i 

a 

■*—4 

>> >N >S P 

TO 

P 3 P 

TO 

in 


-C 

0 

-H || 

- P 


p 

p 

-« •H O 

•-* 

•—l •• 

C 

p 

P 



P 


0 

0 ) 


in o .s 

a) O 

P Q.H- 

o - 

* + X P 
\ * + P 


—< — — P 


+ * \ - 
X * * 


(\nvr>nOMDaO - r\jno-<rPOr'-X>>0 — njnO'J-p'Of^-COOO — (Njrotj-uO'OO-COOO — f\J no 'T P O f- CO 
--c\jrNjrvj<\ic\]r\jr\jr\jr\jr\jnononononoronononono<r^r'<r-<t , T^}-'*r' , 3-''3-''tPPPPPPPPP 


TO O •• *-» 

> II "> "> 

—• II ■—I p •• 


- p 
• p 

p p • 
p in p 
in Q.H- 
a o o 

O * Cl. 

— o 


— • p > 

(D PPH 

— —« in 

P\J 0) Q. «D 
'-'.COO 
TO • 


in to 

Q. N 

o — 

w m 

CL CL 

• o o 


> — a to 

—< TO O > ~ X Q. 
O'-P >-TOE 

• ex ^ c 3 

^ 3 TO *-* TO J2 

—* C -X —"L-. 

p a— — 

C II P p P 


O O - ojro-^J-iO 

n o o -o -o o o o 


>N 

p 

o 

TO 

p 

TO 

c 


Cl 

■ 

> 

B9(W 

a 

E 

o 

o 

o 

■ 

« 

E 

<0 


VO 


0) 

00 

a 

a 

s 

o 

CZ) 

.e 

*00 

-4-» 

X 

<D 


T3 

a> 

=3 

%-> 

c 

o 

o 

c 


no 

<u 

o 

c 

G 

o 

o 

<0 

a> 

•— 


C3 

On 


— E P 

>> TO 

• in c 


— U C 

—’ TO TO 


0 

P O 

p p P 

in in E 

3 >, 

m 

— E in 

c 

p * * * 
\ -n + 

‘■*3 


« 


J 

p td in p 
no no P no 1 


_V 
TO TO 
TO TO 


cr — 

TO •• — 

— p 

^ P -V c 
in — p 
■ in ii a 3 

! -X ^ E p 

C 3 TO 

> TO £ P- 


TO 


o 


a 

o 


*3 p 

~ a 


CL 

O P ~ — 

P TO TO 

^ Q. N N 

— in in 

\ o cl a 

TO O O « 

A — P + + - 

O p p p 

p ii in p p ( 

in — ii a a i 


< P - c — 

- — p TO 

> in n •— c 

« w TO ^ TO P 

' - in II a—< d 

JX E —' P 

C D C TO 

) P TO £ X P ' 


•* •• « TO TO • 

■ --- — '^'O-HNN'-'w 

» O •• II -k —. + -K 

i — ii '— —' to '— in m *— — 

• ax- n to a a^ 

lOTOTO'-'-'-*—'OOP 

"ov to m 

l p c c •—• a r ap 

ITO—*TO—'050—' 

' r a—« r. 

: u O £ J 


p p 
to in 


- r 

p c 


* + t 


'•C0>O-l\o^££r'C03'O- 

£in£££££ , ££'0'000 O OOO O'O — CU CD TO COO 03 03 CD UJ CO > 


O — oj m ^ £ o md O' O - r\jrn’TiO'Or~ao>o — f\jfO-^ino 
coooooooocdcocococo>>>>> >>>>>0000000 

TO TOO ro no TOTOTOTOTOTOTOTOTOTOTOTOTOTOTO ^ ^ ^ ^ ■^r 


^ £: -< 
u jc 

- - J 

— TO ^ 


—. 5 
-C 

5 


r- co > 

Ooo 


48 

540 


Dr. Dobb’s Journal, Number 74, December 1982 


opindex=op l ndex+opoff 



\ X 
* 03 

o 


\ 

♦ 


X 

c 

o 


s: 

o 

5J 


a 

o 


a 

o 


r\j x 

03 03 


= o 
U O C 

03 

4-3 3- 03 
W 03 X 

—• a—• 

O' O 111 •» 


O' CT W 
• (0 ID C- 
^ «-H —I O ' 


in - 


4J 

X C 
-* O 


0) X 
DO)* 
—I C X 
03 0) -h 
O' 03 
0) > 


•*-> u 

—< 03 

n 

T? in 


- % 


in 


o n 

U D 

I •» in 

c — II 
o +-> n 

c 3-. ^ 
03 <u 


X 




3- 





03 






03 


» 



■K 

■*c 

* 

03 


4-> 


* 


03 

* 

> 

* 


U 

V 



V 


* 

4-> a 

, 










r-i 


» 


03 




03 


-*-> 

•» 


-*-> 


CT 




5 


03 3- 

•• 

4-> 


\ 

s 

> 

—i 

•—1 


s. 


> 

\ 

r—i 

\ 


o 

<—• 



V 

• 

\ 

cn O 

r—i 




<-• 






*3 

«—4 

03 


n 




* 


c 

+j 


in 


03 




o 


d: •-< 

4-3 

in 





03 

n 




—4 





4-. 




■—« 

X 


— 




•* 

0 






<—> 

(D 

3- 


c 




o 



3- 




4-> 




.—1 


03 

3-. 

»5 





> 

u 






r~* 

— 


03 





•—4 


* - - 

> 

> 



D 






X 

> 

0 






.—1 



03 




in 






- r. 

03 





• 

—4 

V 




» 


o 



X 

X 




03 


x ~ 


,—1 



in 






•—. 

r—i 

4-. 


a 







-*-> 


» 


3- 




o 


CM 

4-> 

* 




3- 


V 




V- 


II 

»-* 


— 

^4 



X 

> 


T3 

w 

W 


CT 

li 






—i 

■— 

0) 


o 

•» 



o 


—( 



03 






4-* 


U * 


03 




-r-i 


«—» 






II 

TS 

•» 

03 

03 



—I 

.—i 


03 "D 

4-3 

4-3 


03 

n 






03 

u 

X 


—• 

o 



-*-> 


03 

* 


3- 


0) 






03 CM 

* 

3- 




03 

o 





03 


1—> 

r, 

X 

CT 

> 



03 

'— 


> 03 

in 

in 

•» 

3- 

3- 






> 

r-i 

— 


a 






> 



O 


r-t 




03 


a i-. 


o 




JC. 

II 

_ 




n 



CD 

+ 

(D 

.—i 



> 

a 


-4 || 




0) 

03 






r—i 

03 

03 


o 

c 



03 


.—i 

» 


H-h 


u 




O' 


O 03 

» 





—' 

II 

■—1 




— 


1—. 

II 

a 

4-3 

— 



—-4 

o 


— II 

4-3 

4-> 

— 

r—i 

a 






II 

U 

CT 

o 

v_^ 

3- 






03 








r 


a 

03 

03 




— 

1 

03 




— 

X 

X 

II 

in 

in 

X 




a 


a i- 


r—i 

a. 

n 

o 






<—< 

II 

03 

11 

CM 

D 



c 


• 

3- 


r 

.—i 





~3 


• o 

3- 

c 




03 


> 




03 

<—< 

i—1 

3- 

u 

3- 

4-3 



4-> 

4-3 


O 03 

0 

c 

03 

D 







X 

■— 1 

4-3 

■—' 

03 

+-* 



D 


3- 

O 



0) 





.—i 


3- 

O 


•• 

•» 

<—< 

CT 

___ 

r—i 




CT 

X 

03 

03 

ii 

03 

m 


— 1 

in 

u 


a a 

X 

X 

£ 

O 

4-. 





— 

•—< 

■^r 

in 

X 

(T 

Q3 



.—i 


-H 



— 

> 

X 

•» 



a 


03 - 

>*-< 


— 

o 

X 

C 

—i 

— 




c 

r-i 

> 

a 

a 

0) 

c 



c 

03 


-*-> o 



in 

o 

—4 






—4 

■—4 

3- 

«—• 

C 

3- 



a 


03 

03 



_ 

_ _1 






a v- 

03 

03 

II 

II 


D 

03 

X 




D 

03 

r-i 

o 

in 

—i 

o 


03 

o 

b 


3- — 

4_ 

4- 









03 

r-i 

(D 

r—i 

D 







r. 


O' 

w 

«—1 




>N 


O O' 

o 

CT 

•—> 

<—• 

.—i 

r-i 

> 

4-> 



— 

—< 

> 

W 

w 

u 

u 

u 


in 

u 

in 

.—- 

03 — 

-r—i 

•H 





s 



3- 

> 

03 

0> 

03 

—\ 

03 



X 


—- 

* 

M- 

CD 

3- 

03 

c 



3- 


— a 

+ 

03 

in 

r- 

03 

a 

~-i 

in 


•— 

a 

a 

—i 

4- 

4- 





—1 



03 

E V. 










03 

<—4 

> 

~-i 

> 

Q. in 



3-. 


— 



4-* 

•rH 

> 

u 



0) 


CM o 


-*-> 

•—< 

>—■ 

> 

— 

— 

c 



in 

— 

— 

**—1 

•^4 





03 



*-n in 

in -4 










a 

— 

—4 

u 

—i ■ 


r—< 



O' 


03 

3- 


in 

03 

.—i 

D 



c 


03 

3- 

in 

.—c 

.—i 



H-i 

O 


03 

D 

4— 

4i 










—4 











o 

4-« 





03 



c 


O 

03 

+J 

+-> 

a 

-— 

-*-> 





CT 4-> 

03 

4-3 

0) 

0) 

'—- 

-r-i 

1 

u 


in 

a 

-r-i 

-ri 










03 












-4-4 










c. 

jC 

c 

03 

ii 


03 



JO 


c c 

-C 

03 

> 

> 

H—* 





.—i 
























4-4 











2 

U 


in 


•r-i 

3- 

.—, 




3 -r-< 

u 

in 



■r-i 





03 

































* 

\ 

.—1 








■K 

* 

\ 

.—1 










































\ 

■♦c 

■♦c 

a 








\ 

* 

+ 

a 







































cc 3> 

o — 

CM CO 

'T 

O 

■o 

r- 

CD 

> 

o 

_ 

CM 

n 

'T u> 

<3 

r~ 

X > 

Q 

_ 

CM 




o 

r- 

X 

> 

o 

— 

X 

X 


X 

■o 


X 

o 

o 

— 

2 

3 

4 

X O 


X 

o 

o 

_ 

X 

X 


X 

■o 

I-- 

X 

■> 

o 

o o o 

r- 

r- r- 

• 






CO 

CO 

CO 

CO 

CC CO 

X 

X 

X X 

> 

> 

> 

> 

> 

> 

> 

> 

> 

> 

o 

o 

CJ 

o 

O 

o 

O 

o 

o 

o 

z 

z 

~ z z 

_ Z 

~ 

z 

z 

X 

X 

X 

X 

X 

X 

X 

X 

X 

X 



c 

u 

D 

4-> 

CD 

3- 


— 03 

c c - - 

U —* 

D —» — 03 

■»J e in a) 

a; it in J- 

3- II 0) x 

a; o — 

03 c O 

in —•3-0 

—< —* Q. 03 

03 — 03 — 

'*—• 3-« '*—• 

-h a -~s 


O — X X ■>0- X O P- 


in —< 

T3 03 O — ► 

C £ 4-3 U ~ 
03 03 T3 a> — 
H 0)T'D 

*-> a> -*-> c 

* CD C ~ •'-* 


_* O - ~ - 

-*-> cro^oo 
in o; +-> Q 4-> 03 
-4 OE-h C 


03 * 

5 - 
m — 
O 


o - 

ro ' 

4-3 — — 

in r r? a; - 

3- U > 4-3 •* 

03 CT —' >- 

a: T3 £) ' 

—< 03 • ' 


, £ - 
03 ~ 


CT *— • w w ^ 4-3 

» Q) +J +J QJ 

CT' — —• C E * D 


0--HV 

0> E T3 1 


V- c 
a e 
> 


ID E - - 


3 •■ in o — 

« — r o.— 

— a 4-> +j 
a> 3- O' 


D 

O 


C3 

Cu 


E 

C 

CJ 


o 

o 




r. >~ 
o c 


03 


CO “v] 
LU CO 
O CO 


03 * 


a 
. o 


C <4- O' CT CT CTH-. a c 
V.0>a34->Q>(C4->-'4_C3~ - 

03 T? -*-3 —< in -P -H r -< 03 JZ 

d v. in —< —i in —< c O'-*-* u 

. x -h * * a; cd * x 

a> ^ * a> 


c o * ~ 

03 ■DC — 


in in 
O 

a 


> ~ D 


c • 


CT 


— C - 03 Q. D 03 

>- 3- -*-> O 4-> +-> 
C in O >p in vi 
1-13 DJD XPP 


3- C 0) 


03 


* * \ 
\ * + 


I C O in 


— — O — E in 


a — ^ 


: "c a) — 1 

CTX - 
X 

• * 0) 

• » E 

• — — E ' 

: a> o c 

3 X 03 

CT • - 


• O - 

Q. Q> 


CT E x 


► 4-» *0) 

* in ~ 3 - 

• T3 — 

>0 3 - 

3 E O • ■ 


— » ♦ ^ 


C — 
3 - X 
03 X 


- — -T3 - - 

— — 03 ' 

E — E ' 

O 03 E i 
u 0"4' 


X o ■*-> m 

O 03 O 03 

i e c a -*-> 


— XX^XOP-X>0 — CNjco-q-nO' 


•C0>O — C\JrO'3-_n O^C0>O — O > 0) > O - rsjfO'^rn'OI^-aOD'O — rvjro-o- 

— — r\jr\jrMf\ir\jrsjr\ir\ir\jr\j'oroco rr ) rr 3 'OcO' 0 , ~ 0 ' 0 'TO‘ 0 ' , 7 ’ , T'cr^T'^' , T r T_ 0 ^>-ri- 0 ^ 


00 


bo 

C3 

CL 


O 


cx 

o 


K 

O 

^3 

^3 

3 

C 





Dr. Dobb’s Journal, Number 74, December 1982 


49 

541 


page) 








N 


\ 

* 


—• C —• C 

w U —v. 

— d cm □ 

— -*-> — *-> 

l_ 0) V- 0) 

—• •*+ u* 


♦ ~ -H o 

♦ n m * •• 

- 5 — > C U O 

u V- -H u c 

*-> r -• T3 D -H c 

a u a) a> -*j w v_ 

— * •»-> X 0 ) 0 ) a □ 

M (V — C l~ O) -*-» 

E '+-• *-> o> 

+■» <0 ~ nm in l~ - 

c x: *- 

—< U w-4 


— o 

II 

s II 

I -* 

I — 

= I'D — 

x: -h w «. 

U w O 
4-> f’O (C 

<o — > c 

e v- — i. 

w ^ -o 3 

V. 0) 0) 4-> 

xr 0 ) a> 

C V-- 

Q) H-. 


^ > — O' cr 
»- <0 •• fo <0 
- > h- 


4-> W 

— njn cm ii — 

O E — UJ O 

w v- — in —• 


i — —. 

= — «o * - 

^ (T > : «j( 

x: > — w > . 

u -h i x: —•' 

u w 

(0 ro II — 4J n 

e — o <o — ' 

~ F U 


-<^ C ^ C - TJ- C — —< 

W- ’*-• 0) ^ X •—I U '*-• 0)— — V- H- QJ . 

~ r! =? era. — d — r — — d — x: 

E (t3-4-> 0) fC -*-» — O' *T3 -*-» 

O '♦— > '*-« 0) 0) V« C '*-• J» '*-• QJ 0) '*-« 0) > 0) Qj H_ y 

o <u -h V-^ m < a) —• —< v_ —■* w —. c —• v_ in -h - 

T3 T3 -o T3 —• —. 

'*-• C 0) '*-• C qj 0) 

0) *-i 0) 


V- ~ 06 

O -4-* — 

— a— — 

—• II w (TJ 
I5 "hU 

> cm (TJ O 
—•—>—« 
II —< —. O' 
* ^ <0 ~ 

-*-> > ^ * 


r* 00 O O — rsjro-^ — f\jro^TX''Or~GO>0- 
xiLnxiO'OOO'O —■ 

CNjr\ir\jr\jr\ir\jr\jr\j 


•fMO^xior'(Do k o-(\0'tinor^cD>0-f\rn^ i vor'CO^o-f\:rn'fXi'Or'OOa.o-(\fn'TXi'Or^CD >0 


a ^ 

■ 

> o 

00 

CO 

Q- 

ki C 

O ° 

c 

a B ™ *Sb 

q> 

c f 

C x 

O a 

O H3 

o! 


o 0) 

" C 




\ 


\ 








♦ 


♦ 





—- 










CM 



V- 


w. 








O 


o 





<0 



-*-> 


4J 





> 



<0 


<0 








u 


v~ 








0) 


0) 








a 


a 





*—4 



o 


o 





<0 










> 



0) 


0) 

u. 




,—1 



r 


x: 





w 

'v' 


♦j 


4-» 





♦-> 






o 




—I 



>s 


V 

II 




D 





H-i 

II 




in 

o 


-r-l 


«4 





0) 

II 


•*-> 


•*-> 

CM 




w. 

II 


c 


c 

w« 



N 




0) 


0) 

CM 



* 

*-N 

rvj 


T3 


T3 

*"H 



¥ 






•*-< 

(0 




T3 

(M 





> 



CM 

T3 

—4 




* 

>—t 




ir 

0) 


\ 


\ 

w 



>s 

ii 

> 





a0 



r 

il 

~-1 





— 




u 






H 



> 

0) 





•• 

2 



•rH 

a 

«— 


•• 



•—< 



T3 

o 

o 


U 


V- 

O 




W 

II 


0) 


0) 

^ II 



* 

- - 

II 


a 


a 

II 



* 




0 


0 

<-» •—i 


•• 


X 

rsi 


ii 


— ii 

X CM 




D 






D — 

•» 

— 


in 

—4 


o 


^ <3 

in —• 


—. 

•» 

il 

fO 

w 

—• 


(\ w 

II <T3 

w 

4-> 


II 

> 

u 



V- -4 

II > 

a m 

w 

V- 

—1 

0) 

<c 


0) <c 

V. —< 

ic 

c 

V- 

0) 


a > 

0) 

a > 

0) w 

J 

o 

in 

a 

w 

o —* 

in 

o — ^ 

a— 

in 

u 

(0 ^ 

o 

0) H-. 





O 




w 

in ■«-• 



0) 


^-s w 






2 = a 


xrxxxxxxrxxxxxx-rxx 

O'O'O'O'O'O'O'O'O'O'O'O'O'O'O'O'O' 

uw.v-w.v,^w.v-k-uw.uul!uul! 

• II II II II A V 

U--< 00 N — VAVAAV + | 

0) 

a 

•0)4)0) 0)0)0)0)0)0)0)0)0)0)0)00) 


-•cccccccccccccccc 

C*)*J*)*)4)V+J4)+)+)4Jp*J*)*Jp 

•»hO)0)0)Q)0)0)0)Q)0)0)0)0)0)0)0)0) 

UV.UUW.UW.UW.W.UW.W.UW.V. 


: v-v-t; cto) o) o) •*-> ■*-> >*c 

|) O O C 0) C —• O'-H O' V) W T3 O ^ < ( 

• x <T3 co <t3 a: tn x T3 £ 

II II II II II II II N II II II II II f II I 

► II II It II II II II II II II II II II H H I 

IV.k.UUUUV-l.V.UUV-Ul.W'l 

L0)0)0)0)0)0)0)0)0)0)0)0)0)0)0)( 

ooooooooooooooo! 


H-« H—. H-. H-. H-. H-« H-« > 


0)0) 0)Q)0)0)0)Q)0)0)Q)0)0)0)0)0) 

inwwiflininifliflinwwwi/iinviin 


- U T3 X X! 
U O C T> O 
O X ID (0 |/| 

- II II II II II 

0) 0) 0) 0) 0) 

<r a a a a a 

► — o o o o o 


P -3 

hm £ 

in e 


0 ) 0 ) 0 ) 0 ) 0 ) 0 ) 00 ) 


0 ) 0 ) 0 ) 0 ) 0 ) 0 ) 0 )' < 


C - to ~ 

O — > — - -4 

o ao — ‘o 

s/ w v ro II > 

C -4 ~ W 4J -4 

o 10 u ^ W II 

■H > -H ID C -• 

I/I h 01 > O D 

in C. -+ o > 

V 4J w w * a < 

W. C H-* H- 

a 


u <D > *■ 

—« 0) > —4 «-« " 

10 a—« w S : 

>0 4J II I 

—* - in -- < 

• n C s : 

4J U O ~ > 

C B-H u X. 

—< — o o 

OJ X- v . 
w r-, (0 

^ (0-n E 

—t > 0) — ^ ■ 

«0 —« CT^ ' 

> • c m • 

-* ^ 3 > 

— 4J a — 

V. C II H- 

■H •H ^ 


rvjn'Tinor^ao^o — /%jrn‘<tx>or-co>o 

'T -T *T ^ ^ ^ D 


— r\Jf^^XlOr-C0>O— rsjrn-^an'O^CCOO — fMrO’T in or* CO 

^nnnn^innnooooooooo or^r^r-r^r- 


>O-nirnt^Or'Q0>O- 

*-®CDCCXOO®COGOCOX>> 


Dr. Dobb’s Journal, Number 74, December 1982 






\ 

* 


* 


'T V 

f\j r\j 


in in 

c c 
o o 


o 

T3 


03 O 

> -f 03 
—• = — > C 
'-'—O'-'k- 
’f -C II T) D 

- U II 0) 4J 

V- *j JU 0 ) 0 ) 

■H It) w c k. - 

-C ^ -H 


—• <N I —• r\j 

03 a = — re a 

> A « > A 

~ x w - —. ~ 

rsj u « o r\j 

U ■—1 o 03 — > C U —< O 

C(C E O —« k. 0)0) 

-*>C ^ II T) 3 T) > C 

—•»- H-. II <D *J ~ —4 k. 

Q. ~ 33 « V 0) (U Q.w 3 

' <D U -*-> ^ C k. — <D U 4J 

0) 0) 0) H-. *-> C <V 

WTJ k^. in —< k- - 


k. —* W m —> 


* X 

J * 


-e _ 


w m >~- 


*-* ^ c — — ~ c 

03 C •» k- U 03 

= — U 0)0 *-» 4-J U 

“ O = — 0.0.= 

= II - - 0 C 


03 U*-> k- —< — || -r* w 

> a ic id ^ 11 ^ ti 

-4 • * e > in .c —< -4 

u IDH 

* U k. II C ~ > .T 

— id ak. id --1 * 

k- C iZ !!-»-> —• H— 


.C k. 
u +-> 
■*j a 

03 ~ 
E h^ 


O ^ 
k. C 
k. D 


T3 3 
a: 4 -> 
0 ) 0 ) 


0 ) 

.c - 


0 ) 


LU 


O - 

k. O 


■ in in 0 ) •< - 


r - 

*5 o 

— n 

0) r-, 

On 

03 — 
4 -» rsj 
in —• 


O — o. 

O — — 0 ) •<t H 
• v. n id i\ k ~ 

O C — +-» -4 4-> ^ 

^0)f\jino3Q.a)w 
<M si H k > « Id ~0 

0) 003 03 -4 H-, —1 -0 

c> *-> > <u ^ * as 0 : 

C T3 -h -h V. 

D a. '-- u —< 

—< 0) H-. 

o. c — 


k. — 


o •—• 

II LU 
— CL 
OvJ >- 

•— H 

03 k. 

> 4 -> 

—< a 

11 11 

o - 


a~ 

— T3 — — 

a> H~ TJ —* —• 

in —i 03 — 03 03 

-H > > 

0) —< —I 


y> , A^rt , 5n« II SA 0 ^^ rr, ' T ^ 0,V ®' >0 “ r ' ,,,1 ' Tu ''' 0p '® >0 “ (,v ‘ nr '' , ^' 0|v ®^0'' i\' v l'j.OOMD>0“ ro .n <3 r^QOOO — INjrO'TiO 
<3000 OOoo>or^n>^r^r'h‘r'r^p^r'OCOJ)a)CD(Da)®cocoO'>D>o>oo>0« >0030000000—- 


c*. 

o 


*2 > T3 
- - O 
E T3 E 
II N H 


in in — 

03 03 O 

II N H 


k. k. k. k. 

os o> 0 ) a; os a: 
aaaaao. 
000000 


s = = II II — 

n 11 11 a v z 

* > X A V H 


r £ 

O U 
4 -> 4 -> 


.c .c r: x ^ 

0000 

♦j ♦_> *j 


03 03IC030)03k.^«—• O 

EEEEFEO 0) 

— WWWWW4-) — > C 
V, H- 4~ H-. 0)O—« k- 

k II T3 O 
II 0 ) -*-» 

0)0)0)0>fl)Q)0).k£0)0) 

ininminminin^ c k- - 

00 ) 0 ) 0 ) 0 ) 0 ) 0 )^ 


—. — ^ 0) 

— k- w 3 

— 0) .c —• 
—• Q. in 03 

ID O 3 > 

> — a k- - 


•* 



rsj 





•» 

•» 














03 







—< 



> 





03 

(0 

03 



—4 





> 

> 

> 








_4 

>-4 

-H 



• 










—4 


•• 



« 

• 

• 



03 


— 



4T 

in 

— 



> 


rvj 



k. 

k. 

03 










> 





03 



0 ) 

0 ) 




• 


> 



x: 

i3 




— 


*-4 





• 



U 


w 



» 

• 

— 



— 


0) 



0 

— 

U 



0) 


33 





•— 



X 


—4 




» 

0) 





03 



— 

— 0 

XL 



• 


> 








k. 


k. 





• 



0) 



•• 


— 0 

— 0 

u 



a 


— 

•—> 


w cr 

w a> 

0) 



0 


— 

in 


—< 0) 

-4 c 

a 






w_ 


03 

03 

0 — 


— 

• 


—4 

r\J 


> • 

> • 

— 


— 

u 


03 

-4 


~4 = 

~-4 = 

» w 


—4 

0) 


> 

03 


-- 

o& 

k. a 


03 

a 


—4 

> 


4J -- 

*-> ^ 

0) 0 


> 

0 



—1 


c = 

C = 

a a 


—4 



— 

II 

■» 



0 


w 

rvj 


k. 

—• 

— 

E 

E 



— 0) 

0) 


>4 

in 

-4 



rvj k. 


k- 33 

O' 


ID 


03 — 

— ^ 

— ^1 

0) 0) 


0) —• 

c 


£ 

—1 

> O 

-4 in 

—* w 

O' a 


a 03 

D 


w 

03 

-4 

03 

03 

c 0 


0 > 

—« 

0) 

•4-* 

> 

~ C 

> C 

> C 

D ~ 


~ k- 

a— 

m 

■^4 

—4 —. 

0) k- 

-4 k- 

-4 k. 


0) 






k- 33 

33 

D 

a —< — 

in 



a> 



— O 4-> 

O 4J 

4t 4J 








•*-> 0) 

k. 0) 

k. 0) 


0) 






in k- —s 

-4 k- — 

-4 k.. 









0) 

0) 










X 



03 * 



-*-> w 

C 0) 
•-* O' 

c 

o 


a 

03 

> c 

—* k. 

33 

k. 0) 

u — 

0 ) 




03 * 



C 0) 
O' 


D 

a 

03 

> c 

—« k- 

^ 33 
+j 

k, 0) 
k. — 

0 ) 

r. 


v- 





f ^< v )'t J n<3r'XOO-ryjrn'TiflOr'Q0>O' , “f\J' r )'I/lOMX)D'O-(M-"n , TinOf v C0!>O-(\ 

>>>>>>>>OoOOOOOOOO— --— —-rvjrvjfMojr\jr\jr\jrsjrgr\jnornio 

— — —-f\jrvjcs)<MCMrsjrMf\jf\jf\jfNC\jrgrvjr\jojrvjf\jcMPgr\jcsjrsic\jcsifNjr«jrvjrgf\jfMrNjrg 


o 'Ti3'0r'CD>O-r\n'Jin 

r\jrsj(Mrsjr\jr\jojrvjrMf\jrvjf\jf\j 


cr-X>0— fNJO'Tano 
^ «T J3i3 j3 i3in/) u n 
r\jrsicsjfvjfMfMr\jfMCsjr\jr\j 


C 

O 


cu 

3 

.R 


cr 



Dr. Dobb’s Journal, Number 74, December 1982 


51 

543 


of page 50) I (Continued on next page) 








\ 

* 


\ 

* 


' —< 4) > 

' - w > —( - 

• <u —* - — c 

« w 3 — 0) V- 

j r —. j— x s 

1 i/i m oi a o *j 

« o > a o -*-> 4) 

■ au o am U' 


o > 

E —i - 


— A 

—« rvj 
fc — —• 

> —• 4) 

•—• «3 > 

w > — 

4) — — 

3 <D 

—* U l- 

■* 4) 41 O 

> Q. -*-> 

U O W- 


0) — 

O'70 


43 — 0) C 

a — L- 

C O'"-. 

• — M-. 10 

— •—(DC — 

4) 03 £) 4) — 

£ > * V- ~ 

03 —< 43 4) 

— u a — 

— P 41- h 

*J C£»-£ 
ui — u — i 
4) 


4> 

— £> 

— 03 — 

— > 4, 

■*-* — O' 

4- w (T 

4) 41 4-> 

4-> D <0 

in - 4. 

>0 4) 43 
> 4) 

* U —* 

4) O 
4- — 

O ~ — 

4) 41 S 

-Q > - - 

iflH: v 
^ ^ — 43 
4) — .C 4) 
O' X O X 

4) — 4-> £) 

♦J 41 41 
W £ F 4) 


4) n 


10 


O in _ 

4i 41 
X V- _C 

4i "C 41 

a T3 — 

C rr 


41 41 
.D £3 
41 43 


4) ^ 

r ^ . 


- > 


o o o —< o •*■» ( 


a a a 

E EE 

3 3 3 


4) ^ - 
O' 4: • 
w O' - 
a 4? c 
E 4-> £ 
3 in : 


a a 

E E 
3 3 


: in O 
w c — 

C O * C 
01 U 01 u 
-* 4-3 

O * O 4J 

4-* \ 41 

T3 41 4- 

4i n — 

4> ^ w -N ^ 

c 01 — —. 

O^r 4i 
^ — 43 — £j 

in <0 *j -i n) 

C •—< 10 43 —< 

41 — 4- > w „ 

U 4J 43 — Q. 3 

43 > 41 w £ +j 

< CL — — H-. o 4) 

> —* w w u-nu. 


41 43 
O' 4- 
43 41- 


O C0043000+J 

L- 4-4^4-414-4-4-10 

4i 4)4)41— 41414)4) 

N MIMKUNNN4-1 


41 — qi - 

—• 41 O' -*-• 0) O'* 
O' O' 3 > 


* * II II II II II 


\ \ II II ll 


II II II II II 


II II II II II II 


4- 4- 4. 4. U 

41 41 4) 4) 41 41 4) 

a a a a a a a 

o o o o o o o 


a a 
o o 


—' 43 «— 


I —, —, -H ^ -H 

41 4)4)4)41414)41 

t> 10 10 10 10 10 10 10 (0 


a 4) 
E £ 

■*~i 4) 
«-> rr 
10 43 
41 4-» 


4141414)41414)—. i 


Or-CD > O — r\jrn^xi'0r-00>0 — 

r\l c\j c\j c\j r*) r^i f^) f*) f*) r') r-> "O ro rn «j xr xj- x? xj rj- -O O Xl <0 O O OO OOO OoSl 


4) 

—• V- 

43-0 

> 4-> H- 
w 10 41 

V- c £ 
a o * 
x u 

41 V. 

-*-> 4-> 4) 
in C£ 
c — u 
o 


X — 

03 —i •• 
*-> 43 — 
10 > O 


oi in l 

V- c o 

O O'*- 
>*-. U 4) 
4) *3 £ 

■C — ~ 

0(3 C 4) 

^ O O' 
41—43 
O' 10 4-i 
43 10 to 
4-J 4) U 

inu m 
4-1 a 4i 

4) X —• 
10 4) U 


fNjroir.oor-B>o - r\j ro xi o ao : 

■r-f—O'r^r'-r^-r^r'-noooaocoToaoaoaoaor 


M s 
■ 

> 


00 

03 

a 

s 

o 


a> 

■ MB 

a 

E 
o 

O TD 
0) 
3 

o 


oo 

OJ 

JO 

-*-* 

X 


E 

M 


.2 

-I 


T) 





CJ 


•» ^ 



3 


^ 22 



r* 


O (-. 





W CJ 



4— 


c z 



3 


O 3 



O 


— a 


V- 

CJ 


4J || 


4-> •» 


— 

u — 


ao 



c — 

•v 

>- ii 

3 

— 

3 H 


c — 

o 


4- Z 

o 

o o 


- 

—. LU — 

W 

•-4 «—< 


*-» 

Q- 

c 

4-1 — 


: 

43 — — 

o 

O 43 

55 

w 

U -- 03 


C > 

co 

r 

V- > 

4-> 

D — 

a. 

u 

— 4-> •—« 

o 

'*- II 


4 -j o a~ 

c 



c 
o 
o 

(Q oo 


0) 

c 

O 

0) 

c 


43 II —-41 

E II H-. 3 ' 

^ W- — —( - 

V. 4-1 43 - 

— a 4) > 

- in V- 

0 ) H- — 


— o 

43 — 


^ 1-J 


3 II — 

4-1 II —^ 

0 ) — u 

V- f— 4-1 

z a- 
— UJ w O 
O O 10 
II — 10 c 
|| w o> u 
V. U V- 3 
4-> 4-> T3 4-1 

a a T3 0 ) 

' — ~ 43 V- «■ 


S ^ 41 

a in e 

CD LU 43 
-J >- C 
v 10 

V *10 


or^eo>0—r\ir--wxi'Or'~coDvO- 



4-1 



— 

— 



E U t—• 



H — 

4-1 








- 



43 0 Z - 

•» 

~ X k- z o 

a 

z a 

•» 


— 



—< 

— 


—4 

C —* LU — 

o 

V- 4-1 4-1 LU II 



O 





43 

- 


43 

10 73 Q w 


x a an — 


Q — 





s 

> 



> 

in C — x 

c 

a it n 

_ — 



c 




—' 

—• 



— 

~ — C — L- 

u 


• .__ 





—( •» 


- 

—• 

4) 

JS4 


4) '*-«[—• L- 4) 

D 

o o — 

u — 

—i 



•* 




- 

-X 


» 

e ii o 4 -> a 

o — — 

4-> (T3 




V 

> 4-> 


r 

V- 

o 

c 

o 

43 x o a X 

4) 

—i —i —. 

a > 


a > 



— a 


u 

— 

4-» 

X 


C 4-1 t— w 41 

1 - — 

4-> 43 43 



—..—, 


c 


•» 

4-1 

4) 

■c 

D 

4-1 

e aio 



H— 


H-. 



> 


43 

X 

41 

4-1 

c 

>sw — 


O'— — 

—i 




D 

V- L- 


b 

II 

0 ) 

41 

■—4 

10 

H— 






4-> 

43 43 

4-> 

w 

-V 

C 

U 

4-» 








4) 

E r 

C H- 




□ 4- 73 

T3 






V- — 

— U 

— 

— 




a 

— 

C 







1 - 







--4 

4) 







a 







% 

% 






X> <3 

r-* ao > o 

— 

rvj 

00 

* u"» 

OM) > O — 

f\j n ^ 

£ION 

00 > o — 



^ ’f 'f £1 

XI X^ 

XI 

X» XI XI XI XI x» o o 

o o o 

o o o 

O O t^> r- 

r- ^ 

r- 


c: 



> - 

f—. 

a qL 




< — 

4) O 

a ii 

~ 3 


LU 

a 

a lu 
a a 

E Z 

43 Z> 

< ii 
ii — 

lu a 


>- 

< >- 

c u. 

.. f— 

a it 


H 

II H 

10 II 

— 2 

>- n 

(— 

M 

II — 


H> LU 

f— — 

z 

1- 

— X 

— — x 

Z Q 


£3 h* 4-1 •» LU • — 

c — z ao Q — 

V- O' LU II II *—■ L-. c 

3 DQ--W*J u 

4-i c — o — w- a 3 

41 w-^-4->w4-> 

V- h- u —* — a— 4) 


4-1 ^ — — — 


— an- 


n 01 s1 co > o — f\jo3 ^ 
i'-r^r^r-r-cox)coaox) 


52 

544 


Dr. Dobb’s Journal, Number 74, December 1982 




S3 

T3 

0> 

3 

.3 

■*-* 

c 

o 

u 


o 

II 


■M 6 • 
W E 
C 

o 


— ^ in 

» ^ x 

* — TJ 
TO) —« 

> «D E 
: E E 

) E —« ^ Qi 

I -< Q. 

I - - O 


* - 
\ 


> cm u 

~ TD 0> - 

cm a> O 
4-> E •*-» 
in E D —i 
C O C — 
O 


> 

—• CO — 
^ > - 


^ in in 
u a ct 

<U w w 


^ Or^ CD 

> > > o 


^ o 
> o 


— CM rr) 
O O O 


i ^ <c ai o —< — 

—■ 4-> 


—< E ' 
~ E I 

* — I 


>S 

' c r 


0 ) — l~ 

<u T> O 


i -n a> a) 


c 

• — o u >*-. 

« E II ~ 

j in — <o 

* — w E a) 

• ^ C «) - Ifl 

> ■*-> E --H —< 0) 

) c ii .c 

: -H ^ X 


o o 


C * 

U 2* 


O JZ ~ 

II u ^ 

II w I 

-N U 

— £-< II 

V U V- .V 

<D ^ a> 

a> u e — 

V- -h 3 ifl •» •* 

£ U C O — 

0 ) w c II 

<t' E — — C 

in D a> E O i_ 

— C — — D 

0) ^ _ 4-> 


a 

* 


■*-> - a. 

a — w 

w w i_ 

in O 4-* •• 
in <u m 

(D E 4J w 

U E □ —< 
O -« 0 C - 


■*-» *5 
a -V 
u — 


> — — 


^-O-O^XOO— rvjrn'TuTi'C 
OOOOOO- 


c D 

c <D 

r»oooO — rsjn^^or^aooo—og^rriO'Or^cooo — rsjro^no,-^. 

~ ^/MOJCMfMCMCMCMCMlMCO.'OfO'Orn'v 1 rv 1 ~r,- n -v W f ^ ^ 


<0 V- •—■ 

11 +J o 
— a — 
o - 

ii h- r. ♦ id 

m s ♦ > 


ao o o 
^ o 


— r\j ro 

-O -O lO -O .ft 


O > CO o 
£>-0-0.0 


G. 

£ 


O 

£ 


>S O' 

■C c 

ID -h 


\ 


\ 


\ ♦ 

U * 

•D ^ 
n •*-> Q- 
<C C CO 
0! * 
r e it 
i/i D O' 
3 O' U 
Q. U (D 


U ID 
•*-> > 
a —. . 
~ u c 
in 

in — 

Qj — 

u —« 

* TJ iD * 
TJ > 

ID —< 


m — 

u 

F - 

>. 0.0 — < 

in ii ii o i 

•O'-'— I 

TJ O — C i 

. fD 1 —• ■—■ V- I 

II —■ —• Z3 I 

V- <C «D +J I 

-*-» > > <D 

a—• —« w- •— ' 


V. V- c c 


O D O 

tj a. u 


'-'***-* 
^ \ \ \ Q 




• a> c Q. 


4-> O 
CL U 


W U 

-C +J ^ 

in Q. 


O in —ov- 

•H O' » « || *J 

4-» u o ~ II m 

u id ii in 

c c \n n < 

D O' C 

H-. +-> l_ <D ' 

•—* C <D ■—< H 

— — C £} - 


— C - 
w OC 

4-J —• | 

in m i 
T3 m i 


a- 

< >4-. x H- 
^ < 0) - 


< — 

o — 

O LLJ 

s S 


3E L- C 

-<*J** + 

— z a— a 

s + w w »n 

—» w. —< ^ o 

= 4-> —«-*-> w 

^ o. <o in m 

C w O —< -u 

Qj O" —» in 

0) ^ <0 TJ 
O L- W. U O 

4-> -*-> •*-> E 
TO in Q. 0) II 

. ii ^ ^ i/i a 

a> h-. h- —• in 

C —< -* a; u -- 


— c 


^ > — CVJ 


c 

£ 


in > > d 

Q) w w 4J 
4-> H-. >*-• 0) 
—< — —« L- - 

. n 

X) 


CM ^3 
fD O 


— O 
4} • CM II 


— O — CM 
CM CM CM CM 

CM ID ID (D 
—< > > > 

> II II II 

~ O — CM 


* * \ 4) 


-« ~ —< ^ in - 
□ . 
in a) 


<u <d 
a > 
o —* 


-O'Or-cooO — cMfO'TiOOr'-aooo — fM<o^^<5r-aooo — f\in^£0^coo.o - <m n't — cMOtifi'O^cooiO- 

CD D CO CDX > >00>'>0>>>0000000000 -cm /M CM CM r\| — - 

-—-—-rsiCMCMCMCMCMCMCMCMCMCMCMCMCMCMCMCMCMCMCMCMCMCMCMCM 


CM fO 'T -O O O CO O O — CM CO ’ 
-(MCM CM CVJ ( 


bn 


•3 


Q. 

o 

Cl. 

o 

c 

Q> 

^3 


3 


*— 





Dr. Dobb’s Journal, Number 74, December 1982 


53 

545 







Interrupts and CPIM 


H ow many times have you waited 
impatiently to enter that last com¬ 
mand before heading to the dinner 
table? Computer systems without buf¬ 
fered input can be frustrating to use. This 
article illustrates the use of interrupts to 
provide fully buffered console input to 
CP/M (i.e., “type ahead”). 

Interrupts provide a mechanism for 
external signals to alter the function of a 
computer. Control is accomplished be¬ 
cause an interrupt causes the computer to 
execute instructions in an order different 
from the order specified by the program¬ 
mer. Although many microcomputer 
mainframes have provisions for inter¬ 
rupts, most operating systems (in particu¬ 
lar CP/M) do not make use of interrupts 
and may, in fact, be designed to make the 
use of interrupts difficult. I have a North- 
Star Horizon and wanted to use inter¬ 
rupts to control the console input. With 
proper modifications to the BIOS this 
would allow me to type data during pro¬ 
gram execution with the data being buf¬ 
fered in the memory of the computer 
until needed by either CP/M or my appli¬ 
cations. 


Z80 Interrupts 

The Z80 and 8080 CPUs share a 
common interrupt mode; it is this mode I 
will discuss here. In this mode, an inter¬ 
rupt signal causes one of eight RST in¬ 
structions to be processed by the CPU as 
its next instruction, regardless of which 
instruction is next in the normal flow of 
the program. The correct RST instruction 
is determined by hardware logic external 
to the CPU and depends on the particular 
interrupt line on the SI00 bus that is ac¬ 
tive. The RST instruction causes the CPU 
to CALL a fixed location in the memory 
of the computer. RST 0 causes a CALL 
to location 0, RST 1 causes a CALL to 
location 8 and so forth. All interrupts can 
be disabled under program control 
through the use of a D1 instruction. This 
instruction causes all interrupts to be ig¬ 
nored by the CPU until an El instruction 
is executed and is used by programs when 
they cannot be interrupted (such as tim¬ 
ing loops). 


by Alan Bomberger 

Alan Bomberger, 3721 Starr King Circle, 
Palo Alto, CA 94306. 


There are several important consider¬ 
ations for programs written to run with 
interrupts enabled and for interrupt sub¬ 
routines. Programs written for an inter¬ 
rupt environment must have extra stack 
space available for use by the interrupt 
subroutine and must not have any timing 
or sequence-dependent code that is not 
protected by a DI-EI sequence. This lat¬ 
ter condition extends beyond mere tim¬ 
ing loops because the programmer must 
remember that the interrupt routine may 
completely alter the status of the com¬ 
puter and even cause a restart of the oper¬ 
ating system. A particular example of this 
problem will be illustrated later. 

Interrupt subroutines must be writ¬ 
ten with great care. Unless it is the specif¬ 
ic purpose of an interrupt routine to 
cause a radical change in the flow of a 
program (such as causing a restart), no 
register or status information may be 
changed by the interrupt subroutine un¬ 
less it is restored before the routine exits. 
Because interrupts are not synchronized 
with the executing program, it must be 
assumed that the interrupt will occur at 
the worst possible moment; when all 
registers and status bits are important to 
the executing program. 

The Problem 

I wanted to have an interrupt routine 
to input all data from the console of the 
computer and to buffer this input in 
memory until the console read functions 
were called by the application or the 
operating system. This part of the prob¬ 
lem proved to be easy. A small buffer 
(128 bytes) is allocated in the BIOS 
region of the CP/M system and an inter¬ 
rupt subroutine uses this buffer in a 
circular fashion (when all 128 bytes are 
used, the first byte is reused). The Jump 
vector in the BIOS is altered so that the 
STATUS and INPUT addresses pass con¬ 
trol to new subroutines in the interrupt 
handler. 

The NorthStar Horizon can be modi¬ 
fied via “jumpers” to cause an interrupt 
when console keys are struck. However, 
this interrupt, unlike the timer interrupt, 
cannot be independently disabled via 
software. Any time interrupts are enabled 
and the correct “jumper” is in place, the 
console will cause an interrupt. The timer 
interrupt has an independent control, via 
logic on the motherboard, that makes it 
possible for applications to turn it on and 
off without affecting other interrupts. 
Even though CP/M and the BIOS system 


allow interrupts in general, the timer in¬ 
terrupt is not specifically enabled unless 
an application program enables it. Since 
this control is not available for console 
interrupts, typing at the console would 
always cause an interrupt even if no ap¬ 
plication was ready to handle the inter¬ 
rupt. The NorthStar DOS system runs 
with interrupts enabled and, if the con¬ 
sole interrupt “jumper” were added, I 
would have to modify the NorthStar DOS 
system to understand console interrupts. 

It was for this reason that 1 chose to 
use the timer interrupt to simulate con¬ 
sole interrupts. Each time the timer in¬ 
terrupt occurs the console is “polled” for 
input, and if a key has been struck the 
character is read into the buffer. The 
timer interrupt can still be used to time 
events and the console can still be read in 
the normal fashion without interrupts, 
so no changes need be made in the 
NorthStar DOS system. 

The Design 

Three new functions are provided by 
the interrupt-driven console routines. 
The first is buffered input (“type a- 
head”), the second is a fast abort (reboot 
of CP/M) and the third provides for flush¬ 
ing the input buffer. Each time a charac¬ 
ter is read it is checked to see if it is a 
Control-C. When a Control-C is detected 
the input buffer is cleared and a JMP 0 in¬ 
struction is executed to cause a warm 
boot of CP/M. With this feature a pro¬ 
gram that gets stuck in a loop can be 
terminated without reaching around the 
back of the NorthStar for the RESET 
switch. When the input character is an 
ESC, all input but the ESC is removed 
from the buffer, and the ESC alone is 
left for the application or operating sys¬ 
tem to read. 

Two pointers are kept by the console 
routines, and these two pointers control 
the flow of data into and out of the circu¬ 
lar buffer. An input pointer is increment¬ 
ed every time a character is put into the 
buffer. When this pointer reaches the end 
of the buffer it wraps around to the be¬ 
ginning. An output pointer is increment¬ 
ed every time a character is read from the 
buffer, and it; too, wraps to the beginning 
when it reaches the end. The STATUS 
subroutine compares the two pointers 
and returns a status of “no character 
present” when the pointers are the same, 
and a status of “character present” when 
the pointers are different. Both pointers 
wrap around, and it is possible to get a 


54 

546 


Dr. Dobb’s Journal, Number 74, December 1982 



false status if exactly 128 characters are 
typed in advance of any read and to lose 
data if more than 128 characters are 
typed in advance. 

An initialization routine that sets up 
the interrupt address at location 0020 
and enables the timer interrupts is called 
during the cold boot. 

Problems 

Many computers, in particular the 
NorthStar Horizon, do not have DMA 
(direct memory access) disk controllers. 
This means that disk I/O takes place via 
some CPU instructions that must occur 
at a fixed rate. Any variation in the rate 
these instructions are executed will cause 
erroneous data transfers to and from the 
disk. For this reason, interrupts are dis¬ 
abled during data transfers. The North- 
Star disk controller requires that the 
BIOS wait until the correct sector is un¬ 
der the read heads, and interrupts must 
be disabled during this time so that the 
data transfer can begin immediately after 
the correct sector is detected. If inter¬ 
rupts were enabled during this period it is 
possible that data at the beginning of the 
sector might be missed. 

Characters typed during periods 
when interrupts are disabled are lost and 
it is desirable to minimize the length of 
these “dead” periods. If interrupts are 
disabled for no longer than a single disk 
revolution, as described above, there is 
little trouble, but if interrupts are also 
disabled during disk seeks, many typed 
characters can be lost. This was the case 
in the version of BIOS that I received as 
part of my CP/M package. This problem 
is solved only with a complete rewrite of 
the BIOS. An important aspect of inter¬ 
rupt programming must be considered in 
this rewrite, and I will take some time to 
explain it. 

With many disk controllers it is the 
responsibility of the software to keep 
track of the seek position of the disk 
drive heads. A position counter is incre¬ 
mented each time the heads are stepped 
towards the hub and decremented each 
time the heads are stepped away from the 
hub. A comparison of the desired track 
position and the counter value determines 
the direction the heads must be stepped 
and the number of steps that must be 
made. It is important that the heads are 
always at the position indicated by the 
counter, for if they aren’t, data will be 
read from the wrong track. If interrupts 
are allowed during all of the seek process, 


Dr. Dobb’s Journal, Number 74, December 1982 


the head position and the counter be¬ 
come asynchronized when a Control-C is 
detected by the input interrupt routine 
between the time that the counter is up¬ 
dated and the time that the heads are 
stepped to their new position. Interrupts 
must be disabled during these two opera¬ 
tions to ensure that they both happen 
together. If interrupts are enabled after 
each step operation, characters may be 
typed while the heads are moving. 

Many applications (including the 
CCP of CP/M) test the status of the con¬ 
sole during execution and alter their func¬ 
tion if a character is typed. CCP aborts 
any command it is executing if a charac¬ 
ter is typed. This would entirely defeat 
the purpose of “type ahead,” so CCP 
must be altered. Since I am using a spe¬ 
cial version of CCP written for the Z80 
and have the source, I was able to modify 
CCP and eliminate this problem. Other 
applications posed other problems. The 
text editor I use assumes that any charac¬ 
ters typed while it is computing (rewrit¬ 
ing the screen or searching for strings) 
should be discarded; the effect is to have 
every other character used as input with 
alternate characters being discarded. 
Several hours were spent locating the 
offending code and patching it out with 
DDT. The CP/M assembler discards any 
typed character when it exits, and the ef¬ 
fect is that one character is lost if any 
typing is done while ASM executes. 1 
have not attempted to locate this prob¬ 
lem. 

Other programs routinely discard any 
input typed while they are executing. 
This annoying problem is solved only by 
habitually beginning any typed-ahead 
commands with Control-X. The Control- 
X, if read by the BDOS, causes the cur¬ 
rent line to be deleted and is harmless. 

The worst problem is posed by an 
application that uses several of the RST 
instructions to execute subroutines. 
When this application is loaded, all of the 
locations from 0010 to 003F are over¬ 
written and the next timer interrupt 
causes random branches in the applica¬ 
tion program. I have implemented special 
entry points in the BIOS to change the 
mode of operation of the console to 
interrupt-drive or standard. 

Conclusions 

I undertook a grand experiment to 
see if CP/M is flexible enough to allow 
buffered input. The results of this experi¬ 
ment are useful in that they illustrate 


many of the problems that must be con¬ 
sidered when programming in an inter¬ 
rupt environment. I am using my buf¬ 
fered input BIOS as the standard on my 
NorthStar Horizon, and I am completely 
satisfied with its behavior. The listing in¬ 
cluded here is for the console interrupt 
routine, console input and status portions 
of the BIOS. 

(Listing begins on page 57) 


55 

547 



(Continued from page 31) 

POLL compiles statements which poll the console for 
operator interruptions while the compiler is running. 

CMD_LINE compiles statements which obtain the run¬ 
time options from the command line. The Standard I/O Li¬ 
brary function getarg (Listing #2) obtains requested command¬ 
line arguments. It may require modification to work with your 
system. If CMD_LINE is not defined, then the compiler will 
prompt for each option. 

PDS includes statements which identify files containing 
relocatable code for the second, third, and fourth parts of the 
compiler. These are unique to the PDS assembler/loader. 

LINK implies that compiler output will be used with a re¬ 
locatable assembler and linking loader. It compiles statements 
for declaring “extern” globals as external references and all 
other globals as entry points. In this case, multi-part programs 
cannot be combined at assembly time and the beginning 
label option (“-b#” switch) is not available. 

COL causes labels in the output to be terminated by a 
colon. 

TAB causes a character having the numeric value defined 
for TAB to be placed immediately before op codes in the out¬ 
put. Without TAB, nothing is inserted before op codes. 

UPPER compiles statements which cause symbols placed 
into the symbol table to be converted to upper case. If your 
assembler does not require this, then disable the definition of 
UPPER. 

PHASE2 refers to compile runs using this compiler. It 
causes lines which could not be handled by the original com¬ 
piler to be included and alternate, old-style, lines to be ex¬ 
cluded. 

SEPARATE implies that the compiler is to be com¬ 
piled in parts rather than all together. In this case, separate 
compile runs should be directed to each of the files ccl-.c, 
cc2.c, cc3.c, and cc4.c. These, in turn, include subordinate 
files; e.g., ccll.c, ccl2.c, and ccl3.c (for part 1). If this sym¬ 
bol is missing, then ccl.c includes all of the subordinate files, 
and the files cc2.c, cc3.c, and cc4.c are not used. 

NOCCARGC is a run-time option telling the compiler not 
to generate code for passing argument counts to called func¬ 
tions. This results in smaller, faster programs when it is known 
that there will be no calls to the run-time routine CCARGC. 

HASH causes the compiler to employ a hash-search algo¬ 
rithm for macros and global symbols. Otherwise a serial search, 
requiring less memory, will be used. 

Four symbols permit the user to determine which, if any, 
of the new language statements are to be supported by the 
compiler. Leaving them out may be required in order to make 
the compiler small enough to compile itself in one gulp on a 
48K machine. 

STDO controls the “do” statement. STFOR controls the 
“for” statement. STSWITCH controls the “switch,” “case,” 
and “default” statements. STGOTO controls the “goto” state¬ 
ment. These defines also associate a numeric value with each 
statement; the compiler uses this to determine if the last 
statement in a function is a “return.” 

OPTIMIZE causes the peephole optimizer to be included. 


Availability 

This version of Small-C is copyrighted as a revision to 
Ron Cain’s original work. It is, nevertheless, available to the 
general public for use without formal restrictions. Take it, use 
it, copy it, modify it, and give it away as you please. If you 
capitalize on it for profit, I ask only that you compensate the 
principal authors in a manner that seems fair to you. Machine- 
readable copies are available on North Star and 8-inch single¬ 
density CP/M diskettes. CP/M versions contain just the source 
code as listed here and are available for $25. DOS versions with 
Small-VM, Small-Shell, and documentation cost $45. My 
software tools (written in Small-C for use with Small-VM) are 
also available, with documentation, for $45. 

I will be happy to work with DDJ to establish a distri¬ 
bution scheme designed to make this compiler generally avail¬ 
able at a nominal cost. If you can assist by adapting it to 
other operating systems, then let me know or write DDJ. 

Editor’s Note: Due to the popularity of DDJ back issues, 
especially ones pertaining to Small-C, those which are refer¬ 
enced in this article have been sold out, and are not available 
for purchase. They will be made available in annual DDJ 
bound volumes. 

(Listing begins on page 28) 


56 

548 


Dr. Dobb’s Journal, Number 74, December 1982 


Interrupts and CPIM 

(Text begins on page 54) 


u 4J o a a 

QJ QJ 3 T) T) 

in a a qj h h a 

'+■ 0 4-* I/I H H E 11 

H- k. 3 it 3 3 3 111 0 

0 a 0 L D D A Ifl C 


in X) 

3 V C +1 £ 

4J 3 n o r 3 o d 

in a O *j u it o ao a E 

AC » 3 * » (DC* 3 - 

W -4 T) T3 0 I ll 3 D i) O « *0 0 IQ 


a a 

a -p o o 

e a c r u in 

-s o •*■«-< o O 

* (N - N ► 
IDOIO •B'O '•'0 


r in s- o 

o c c 

<»■ 0 0 A 

O U U >0 T) 

* ► • - m 

t 4) 3 I 3 O 


4J C A 

a in « o 

o c c 

U 0 0 A 

O U U >0 TJ 

r « » » Qj 
«4)DIDO 


in in c 

3 4J -4 ‘*4 

a 3 in in 

<B a o o 
+1 c in m 

in - a a 


>0 O' 

■f ♦ 

A A 

O O 

o o 

(N M C 

o in o o 4J 

+ 3 4 4J -H -H 

in a in 3 a c 

o « o a m h 

•ri 4J -r4 C U» H 

n u D 'H 3 u 


A 

r-i in in h > 3 a l h «q > a 

It N 3>^T3x0»B0cau> 4J 0 *4 Q| £3 X) 

U -> aETJ^^EUCl-rtU-nE ID E I L 3 3 


•-4 HI 'H H ■*« +1 •H +J 41 

>*• X£ > 3 > 3 Hi 

E UIh HI E 0 E 0 L 


*4 A «i --4 -i-t A 
> 3 X X X A 01 
E 0hh„3 L 


•-H 4-1 -f4 .4 p< 4-1 

> 3 X X X £3 Qj 

E 0 rl H H 3 L 


O' a □» a o» •-< 
L E L E k. It 
0 -n 0 -1 0 u 


in 

a 


4J 

3 



u 





O' 










A 



01 

4J 







A 

c 

k. 









a 

l. 


in 

u> 



in 




■p4 

*4 

Qj 









3 

HI 


ai 




in 

k. 



E 

c 

+j 







k. 


L 

A 


L 

Ql 

l 


Ql 

Ql 



--4 

c 

c 







Ql 


L 

U 



k. 

Ql 


L 

A 



pH 

•-4 

-4 k. 

E 






A 


Oi 

•t 

m 

Ql 

0 

>4- 


TJ 

C 

k. 



CP 

0 QJ 

\ 




L 


A 

cr 

4-< 

k_ 

3 

k. 

6 

•4- 


T3 

-4 

QJ 

a 

k. 

QJ 

a a 

CL 




QJ 


3 

c 

c 

3 

44 

Ql 


3 


it 

4J 0 

A 

t 

QJ 

X3 

u 

U 




H- 


A 

<4 


A 

t 

A 

Ql 

XI 



Qi a 

c 

k. 

TJ 


A t 



U 


*4- 



c 


U 

4J 


6 



L 

in 

H 

z 

C 

0 

3 k. 

k. 




3 


0 

c 

Ql 

m 

O 0 

«+. 


0 

A Z 

0 


3 

A 

a »t 

0 


p-< 


X) 

A 

A 

-4 


«+. 


c 

in 

0 

A 


A Ql 

a 

A 



C A 

H- 


0 



•4 

QJ C 

CP 

A 

■n 

-X 

p, 



6 


0 C 


-4 

)-< 

A 

■n U 



L 

r 

A 


a *4 

Ql 

it 


u 

x 

Ql 

Ql 

M 

QJ 


a 


pH 

QJ 




4-< 

A 

in 

A 

t 

13 

m 

Ql 

at 

A 

> 

in 

Sf. 

> 

Ql Ql 

E 

QJ 

H 

m 

A A 

in 


c 

0 

<t 

0 

U 4-i 



01 

x 

0 

<B 

t 


it 

A A 

3 

QJ 

4-1 

QJ 

Qj QJ 

it 

in 

0 

0 

E 

0 

in 3 

0 

13 

m 

u 

c 

in 

A 

0 

in 

A A 

A 

in 

ui 

L 

in o> 

E 

L 

u 

XI 

in 

XI 

qj a 

A 


U L L, 
QJ U Hi 
1 . c x x 

U -4 A A 


- C A 

k- 0 A ~ O A 

Z A A U £3 O U O A O A A 

1 n N c •• C ► - CDC' CN 

OK) O m I I -1 3 3 Ql 3 3 i0 O h t h T( O 


A C 

r 1/1 0 n 

n « i u 4-1 xi z 

-4 a in * 3 cm 

O 10 O £ « 0 01 h O 


A A 

AC A 

A -h O 

3 - 

0 A E t 


m **4 in h 1 m h > 3 a l - -< 

-4 3CCN3xT33>0iB0Cau> 
TJ a -4 IB n a aE 6T3 a H U n E 


•r4 N »t t It a 

a C k_ A A 6 

u x m in -n 


•h n in h 10 10 l ij a 

ac3xk.4JC4J0 

u •-» a -4 x in "4 in a 


> a -4 a a a 

00 > 3 0 h m 

E a e 0 a qj l 


in h a -4 n it a 

T3 x E > C k. Ql 

<-4 i-4 L) E L X L 


Dr. Dobb’s Journal, Number 74, December 1982 



A Simple 

Vector Generation Algorithm 


Editor’s note: Regular readers of DDJ know that we rarely 
publish articles of this nature without accompanying source 
code. It is our opinion that an exemplary listing can often do 
as much, or more, to convey a point as the best of documen¬ 
tation. Unfortunately, we have been unable to reach Mr. 
Michalski at his Poland address. He signed his original cover 
letter “Sincerely, permanent reader of DDJ. " We sincerely 
hope he is just that. — MDO 

M icroprocessors are cheap devices, very useful for con¬ 
trolling processes. Drawing pictures and characters 
is the main task of the graphics display. The micro¬ 
computer can be used to generate vectors from given coordi¬ 
nates of the endpoints, viz. generate all points between two 
given endpoints in such a way that the the vector seems to 
have good continuity and linearity. 

In the first part of this paper we shall try to find a simple 
and fast algorithm for vector generation — useful for micropro¬ 
cessor computations. In the second part we shall give an exam¬ 
ple of its implementation for 8-bit microprocessors. 

Description of the Algorithm 

Let (x s ,y s ) and (x f ,y f ) denote two given endpoints of a 
vector. Any arbitrary endpoint (x,y) G R 2 belongs to this vec¬ 
tor if it satisfies the following formula: 


m 

Ay 

y-Vs = A^ (x_Xs) and 

x s <x < x f Ax =£ 0 

or 

Ax 

x ' x -"A7 (y - y s ) 

y s <y <y f Ay^o 

where Ax := x f - x s , Ay := y f - y s 

First, let us consider the vector generation when: 


/1 / Ax>0 and 
/2/ Ax > Ay. 

Ay > 0, 

Our considerations would be similar 

in the other seven cases 


corresponding to different signs of Ax and Ay as well as re¬ 
lations between their absolute values. 

Let us try to transform the formula /i/ to an equivalent 
one. According to /1 / we have: 

(y-y s )Ax = (x-x s ) Ay and x s <x<x f 

Coordinates of all points are integer numbers so: y-y s = k and 
x-x s = m where k = 0,1,.. ,,Ay and m = 0,1,. . ,,Ax. This 
gives: 

/ii/ kAx-mAy = 0 

For good linearity and continuity of the vector we con¬ 
struct the sequence of the points {(Xj.yj)} j=0 , Ax where: 

x 0 = x s ,. .. ,X i = X i ., + 1 ,...,Xf 

y 0 = y s .---.yi = yi-i +e i>--- e i =°. 1 


by Marek W. Michalski 


Marek W. Michalski, Technical University of Warsaw, Institute 
of Mathematics, 1 Jedn. Robot. Sq., Warsaw, Poland. 


and jejJ. is defined in the following way: 


0 if |Fj(0)| < I Fj( 1 )| 
1 otherwise 


where F o (e)=0, Fj(e) = Fj_,(e j _ 1 )-eAx + Ay e=0,l and i=0, 
1,. . .,Ax. This means that for every m, m=0,l,. . ,,Ax we 
want to find such an integer k that the absolute value of the 
expression kAx-mAy is minimal. Figure 1 shows the flow¬ 
chart of the algorithm for the above case. Similar algorithms 
can be written for the other cases. 

The algorithm is hardware independent. Machine-specific 
code will deal simply with incrementing/decementing by 1, 
adding and comparing two numbers, and branching and mark¬ 
ing the points onto the display. The algorithm can be used for 
every microcomputer system with a CRT as an input/output 
device. 



Figure 1. 

The flowchart of the algorithm. 


58 

550 


Dr. Dobb’s Journal, Number 74, December 1982 






Implementation 

The algorithm was implemented for microcomputers 
based on the 8-bit microprocessor MC6800. Due to the nature 
of the displays, the values of the coordinates of the display 
space were integers and limited to the range: 0<x<22FH 
and 0<y<lAFH. Data were sent from the host computer 
to our microcomputer every 20 ms. The algorithm generated 
vectors between two consecutive transfers of data for almost 
all cases — so only a small buffer was needed. 

Generally, the vector generation program was written 
in the following way: 

Step 1. Choosing the case by examination of the signs of Ax 
and Ay and the relation between their absolute values, 
Step 2. Generation of the vector according to the described 
algorithm. 

Using the HP1611A Logic State Analyzer the time inter¬ 
vals of the longest generated vectors were measured. The time 
intervals were as follows: 

Vector no. 1 2 3 4 5 6 

Time (ms) 36.3 36.4 23.8 22.6 23.8 22.7 


Acknowledgement 

I would like to thank Dr. G. Hamano and Mr. M. Noguchi 
for their fruitful advice on technical matters during my work 
at Matsushita’s Wireless Laboratory in Osaka. 


(000,1 AF) vector no. 5 (22F.1AF) 



Figure 2. 

Vector graphics test pattern. The vector test generator 
produces a six-segment rectangle with the diagonals at 
the extremes of the display space. In the figure, hexa¬ 
decimal coordinates of the endpoints are shown in 
parentheses. 


Dr. Dobb’s Journal, Number 74, December 1982 


59 

551 








uuvoi essay 

5th Generation Computers 


I f one were to walk into a Computer- 
land store in 1992, what could one ex¬ 
pect to be able to purchase? 

The fifth generation computer of the 
early 1990s will not be a mainframe in 
the conventional sense; rather, it will be 
a “supermicro.” It will be based upon a 
64-bit main microprocessor running 
about 110 megahertz with a 32-bit 
microprocessor for I/O. Both will still be 
made of silicon, incidentally, though by 
1992 gallium arsenide circuits should be 
spreading throughout the industry. 

Notice how I have not mentioned 
using an array of 16- or 32-bit micro¬ 
processors functioning simultaneously, 
simply because I do not see the problem 
of distributed array processing as having 
been solved by 1990. Although Illiac IV 
was a spectacular early achievement in 
using a large array of processors in 
parallel, the von Neumann architecture 
will nevertheless be with us for some time 
to come. Distributed array processing 
should definitely appear by the year 
2000, though, in which case a language 
similar to Ada (which is itself a descen¬ 
dant of Concurrent Pascal) will be in 
vogue, since such languages are in theory 
capable of controlling a number of dif¬ 
ferent processors “simultaneously.” 

The fifth generation computer will 
have 4.096 megabyte EEPROM memory 
chips, with a total of a little over 32 
megabytes of internal storage. Bubble 
memories could be used instead, though 
if they do become popular they will 
probably be of Japanese manufacture. 
IBM has been working on a computer 
(to be ready in 1985 or thereabouts) 
utilizing a Josephson Junction processor 
and 15 megabytes of bubble memory. 
The machine will be of incredibly small 
size: a cube about 15 centimeters on a 
side, but the entire device must be cooled 
to superconducting temperatures, which 
will require support equipment about 
the size of a desk. 

External storage will be in the form 
of optical laser disks capable of recording 
through some kind of diffraction process. 
The disks will be small (not larger than 
10 inches in diameter), easily transpor¬ 
table, and will have a capacity of between 

by Richard Grigonis 

Richard Grigonis, Children’s Television 
Workshop, One Lincoln Plaza, New York, 
NY 10023. 


10,000 and 15,000 megabytes. Since the 
more advanced artifical intelligence pro¬ 
grams of the early 1990’s will exhaust 
even 32 megabytes of memory, a fast 
virtual memory system will be developed 
utilizing these optical storage disks. 

The display will be flat, wide-screen, 
and in color, and probably based upon 
Langmuir-Blodgett film technology. 
They shall be wide enough to display a 
menu and two or three sections of a pro¬ 
gram across the width of the display 
while editing in data processing, or three 
or four standard 8-1/2 x 11 inch pages 
simultaneously while doing word process¬ 
ing. The editor used on the programs will 
be powerful enough to do both data pro¬ 
cessing and word processing, and will 
probably be some kind of EMACS/ 
WYLBUR/Yale Editor hybrid with a little 
Xerox “mouse” replacing the cursor 
direction keys. 

Voice entry will be available as an 
option, but it will still take up an inordi¬ 
nate amount of processing time, power 
and memory. Voice entry will be popu¬ 
lar among unskilled word processor per¬ 
sonnel and older executives. However, 
programmers may never get the knack of 
dictating large systems software (to say 
the least) and it will be difficult to pry 
them away from the control offered by a 
standard keyboard with a fast, command- 
driven editor. 

Specially designed, flexible, motor¬ 
ized chairs will be offered to place the 
operator at the correct height and dis¬ 
tance from the keyboard. Some of the 
more elaborate models will be offered as 
a sort of peripheral with larger computers 
so that the computer, keyboard, display 
and chair will be built into a single 
framework, giving the device the appear¬ 
ance of a wide-screen flight simulator. 

The biggest revolution will come in 
terms of software. “Actor-based” lan¬ 
guages such as Smalltalk will allow pro¬ 
grams to alter themselves to the user’s 
wishes. If various present-day languages 
were embedded in such an actor language, 
then strange, new, customized languages 
for specific purposes could be generated 
on demand, merely by the user having a 
“conversation” with the larger host 
Al/actor program. Pascal’s inferior string 
and file handling capabilities, for exam¬ 
ple, could be improved by instructing the 
host actor language to start with a Pascal 
“foundation,” then importing a few func¬ 
tions (actors) from SNOBOL 4 and 
COBOL. 


This language of the future will be 
close to its own operating system (like 
C and Forth), will have no “reserved” 
words, will be extensible, and the lan¬ 
guage’s own procedures will be as acces¬ 
sible to its programs as its data structures, 
a la LISP. 

The language will have extremely 
high-level subroutines resembling natural 
English, and a program’s self-alterations 
as a result of communicating with a large 
number of users (its “learning” process, 
if you will) will allow natural language 
processing to finally come of age. We will 
be on the verge of attaining what I. J. 
Good in the early 1960s called the “ultra- 
intelligent machine.” 

This actor-based language will pro¬ 
bably be embedded not in one of the 
LISPs per se, since LISP will have to be 
given some kind of structured treatment 
for the optimum usage of the optical vir¬ 
tual memory disk system. I think the lan¬ 
guage closest to what I have in mind is 
something called LISP/ALGOL, which 
was developed at the University of 
Grenoble back in the 1960s. 

By the early 1990s, the advanced, 
compact hardware and artificial intelli¬ 
gence software described will start to be 
incorporated within robots. Then we’U 
probably let the machines themselves 
design really new sixth generation equip¬ 
ment ! 


60 

552 


Dr. Dobb’s Journal, Number 74, December 1982 



DR. DOBB’S CLINIC 


by Jan-Henrik Johansson, Guest Intern 


Argc and Argv for Small-C 

After having worked for some time 
with UNIX at my office and with The 
Code Works 1 " 1 version of Small-C at 
home, I started to feel that, although use¬ 
ful, Small-C nevertheless lacked some fea¬ 
tures I regularly used on UNIX. One was 
the capability to define standard input 
and output at the moment I run my pro¬ 
gram rather than at the moment(s) I 
wrote it. Another equally important one 
is the capability to pass arguments to the 
program from the command line. 

Although most implementations of C 
actually support these two features, the 
Small-C package distributed by The Code 
Works for CP/M does not include them 
(they have more expensive versions that 
do, however). I guess there are many of 
you out there who use Small-C and may 
therefore be interested in the programs in 
Listing 1 (page 64) which gives your 
Small-C both of these features. The pro¬ 
grams are written in Small-C and fit the 
CP/M package distributed by The Code 
Works without any changes, but they 
should run with very few changes on 
other operating systems. You only have 
to know where your operating system 
puts your command-line buffer. 

Command-line Syntax 

When you invoke your program, 
standard input and/or output is redirect¬ 
ed by redirection instructions given any¬ 
where, and in any order, on the command 
line. To be more precise: to redirect 
stdin, enter “<” followed by the file¬ 
name of your CP/M file, or by the device 
number of the peripheral device you want 
to assign. Device number 0 is the console; 
device number 1 is the printer. If the file 
or the device does not exist you will re¬ 
ceive an error message and the program 
will terminate. To redirect output, enter 
“>” followed by the filename or the de¬ 
vice number. If the file does not exist, it 
will be created; otherwise, it will be writ¬ 
ten over. 

Any character strings in the com¬ 
mand line not preceded by “<” or by 
“>” are considered arguments. They are 
stored by the program for later use. One 
or several spaces are delimiters. The pro¬ 
gram accesses these arguments using the 
getargQ function. In short, the command¬ 
line syntax is: 

progname [< stdin] [~>stdout] 
[argument 1] ... 


Accessing the CP/M Command Line 

The routine setargsQ (lines 34-113 
in Listing 1) contains the code which 
accesses the CP/M command-line buffer 
and interprets it (all in Small-C!). The 
format of the CP/M command-line buffer 
is: a one-byte counter followed by as 
many bytes holding the command line, 
starting with the first space after the pro¬ 
gram name and ending with the last 
character preceding the carriage return. 
The CP/M buffer is usually located at 
80H (128 decimal). The variable “count” 
points to it (line 44 in Listing 1). Notice 
that CP/M does not retain the name of 
the program you invoked. In my view, 
this is rather unfriendly; in any case, it 
does not match the UNIX C convention 
that argument 0 should contain the name 
of the invoked program. In order to make 
the numbering of the command-line 
arguments compatible with UNIX and 
make my programs more portable, I de¬ 
cided to provide an asterisk as argument 0 
(line 47 in Listing 1). 

Accessing the Arguments 

In The C Programming Language by 
Kernighan and Ritchie, the processing of 
command-line arguments is described in 
the following way (page 110): “When 
MAIN is called to begin execution, it is 
called with two arguments. The first (con¬ 
ventionally called argc) is the number of 
command-line arguments the program 
was invoked with; the second (argv) is a 
pointer to an array of character strings 
that contain the arguments, one per 
string.” To make argc and argv the argu¬ 
ments of main() would require a change 
to the Small-C compiler; fortunately 
there is a simpler way. It is sufficient to 
make them, together with stdin and 
stdout, external. Pointers to pointers are 
not allowed in Small-C, so argv is simply 
an integer array, the values of which are 
pointers to the individual arguments. To 
finally get to the arguments in a Small-C 
program, you call getargO, whose inter¬ 
face is described in Figure 1. 

An Example 

Figure 2 is a complete example show¬ 
ing how to use setargQ and getargO. 
Instead of calling setargQ from mainQ as 
in the example, the call could be made 
from CCGO in c801ib so you would not 
have to remember to initialize. Also, 
getarg.c could of course be added directly 


62 


Dr. Dobb’s Journal, Number 74, December 1982 

553 



to c801ib. Notice, by the way, that CP/M gives your arguments 
back in upper-case only. Notice also that your output routines 
(fputc in Figure 2) must know about stdin and stdout — this 
is where the redirection finally takes place! BVj 

(Listing begins on page 64) 


getargQ function: 

n = getarg(i,s,l,argc,argv) 

n EOF or a pointer to the found argument string 
i is the number of the desired argument 

s string into which getarg will return the argument 

1 maximum length of string to be returned 
argc total number of arguments 
argv array of pointers to arguments 


Figure 1. 

The interface to the getarg function. 


A> 

A>type testgeta.c 
•include getarg.c 
main () { 

int i ; 

char tc, sC203; 
setargs(); 
i *0; 

whi1e(getarg(i♦ ♦, a, 20, argc, argv) !* EOF) < 
fputc(CR, stdout); 
c*s; 

while(tc) fputc(tc++, stdout); 

> 

> 

fputc(c, fd) char c; int tfd; i 

if(fd *= CONSOLE) putchar<c); 
else if(fd ** PRINTER) syslout(c); 
else putc <c, fd); 
return NULL; 

> 

syslout(c) char c; i 
cpm(5, c); 

if(c-*CR) cpm <5, 10); 

> 

•include b:c801ib 


A>testgeta >1 send this to the printer 

t 

SEND 

THIS 

TO 

THE 

PRINTER 


Figure 2. 

A demonstration of the use of setargs, getargs, and 
1/0 redirection. 


Dr. Dobb’s Journal, Number 74, December 1982 
554 







W ft UJ 

U 01 _J - 

« k_ o * 

£L £ W *h 

W WZ* 

- o 

N U ~ U U 

I 1 H 

M> O C 
L ft •> h L 

*J pH "O 4J 

a u v a 

+ m n m m 

+ A ~ 

•* k. 4- 

w L V -h 

liv a 

-< a « 4 

h ~ ~ « 

£ 4 - 4 - -h 

Z -h -h Hi 


<x ♦ ai i 
a. ■*■ G sv 

(n h 4 

*-< — c — 

N tl Jf O, 

£ _J w 

V ft D C II 
•« L C Z 11 II 

in VH- II a 

uj a n o c 

>■ «* -H 4> H 

II v U IT] 

L t t C V 

o .«ph e h ui 

L Oh <8 TJ ~ 

k- II A C *» 4- 

. ai r>, H z 4- in -h 


I * ui qc 

uj u _i UJ 

** U ft O ~ H 

v <i l in * z 

0. A Z - 

in ^ o * £ 

- u a. 

H U ~ N II H 

^ I V. V I V 

in O 3 3 

~ k. 4 * 0 L 0 

■> *J -h TJ £ TJ 

a a m *j a -*j 

* 4- H H Ml «• in 

•f A w 

II *» L 4- 

N ~ k. -P H 

tv a 

k_ i—« a *• oi 

v -H ~ mi 

a i f h- ph 

■> *» Z -H -H || 


u «-i ai £ c n « 

<14- g u « g in 

a. ♦ m w u t ui 

in h c ^ k. o 

uj .*4- 4 = 4- I 

N 4 _J N -' *■»£'■' '■' L 
•■GJCOUMO 
I D ll II V +J 4J L 

L C Z a H 3 3 3 L 

v f ii o v a a a 4 ^ 

a n^. 3 

« h II O 

w u V ^ 

4 01 3V 

G 0 Ml 
O h ft TJ w 

H A C V 4- 

•h z fin.H 


\ m in 4- « 

«* CT n _| 

L H u J 

v m - in d 

C II O' Z 

II ^ L L H 

G U -P 4 r-i 

3 o> a 4- 

O' k. + 

k. ft ♦ ~ n 

4 ui 4- II ui 

> U -< in 

«* O' O' h O' 

N, L k. A L 

4 4 Z 4 i 


O'OhNM 

in >0 >o >0 >0 


t l (3'5 f ): 1 5 t !l OHNM<in ' flN ® (, ' o ' <Ntt ^ in ' 0 ^ CD& ‘ OHN ^^i0'nMDa‘OHNK)<in^MDa'OHNK)ir 

•O>O>O>O«O«Oh*NNNNNf^NNN0(DaDODa)lDDDQ)a)a)(hO‘O‘a‘lhO‘a‘O‘(ha‘OOOOOOOOOO^*-'-*-'^ 

<1 


x r= 
o a. 
H £ 
^ o 


T) 

4 

L 

L 

UJ 





•P 


3 

13 

-1 

>« 

TJ 

■» 

V 

m 

a> 

•U 


O 

m (J 

C 

-1 

Pft M k 


II 

4 

pk 

in 

n 4i 

4 

-I 

UJ 4 

« 

-* N 

L 

-J 

z 

in in 

G 

D 

^ U 3 H 

L 

> H 


1 

o 

(N 4 

G 

Z 

<X C 1 

L 

O' Ml 


2 

u 

Ui H 

0 

N 

~ (L h 

01 

U 

U 

z » 

II 

4 « 

u 

n 

u in v l 

TJ 

4 4J 

o» 

II »"• 

L 

G 


«H 

4^ C +* 

4 j 

•> C 

k. 

N H 

L 

4 • 

E 

Ui 

* M 0 a 

in 

U H 

4 

n i_i 

4 

C L 

0. 

.. m 

4 N U «• 

» 

o> 


H k. 

TJ •• 

4- V 

u 

4J O' 

pH w 


41 s 

w u 

C 1 

<8 ^ 









p n 

L •• 

M 



Ui 

Ui 

■P 




■V* 

a: 


a 

c 

L 





k. 

4- 





o - 

in m 

V o 

m in 





L 

m 




in 

UJ 

» 

M 

** 3 






v +J 

H 



(N 





3 - 

p ** 





■V 

N 




ii 

»- 

n 


v O 






a 




n 


uj o: 

<i 

m 

0 UJ 

4 

C 


•» 

4 

in 

n 

.p 



•V Z 

o 

p 

•P u 

■p 


in 



kp ** 

4 

pH O 




_l UJ 

_j 

_J 

TJ > 

N k. 



r-i 



H 

+ 



3 

PH 

CD 

■V 

pH « 

K 


O' 



4J w 

in 

1 -H 


n uj 


O 1 - 

a 

<l 

+j O’ 

■Pi flj 

— 


C 

■H 

4- 

Ui 

+ 



0 

£ 

IP Ui 

c 

•• + + 

«* 


k. 



a 4 - 


-J 

O 

PH u 

J 

in z 

•—i 

PH 

in l 

m a 



UJ 

m 

■H 

m 

-H ^ _J 

,p 


TJ 

U. 

l - in 

3 

CD V L 

ft 




ip 


4 

u. -J in 


<x 

-J 

z ~ 

(T 

ir 

u 

- u 

o 


> 




J 

in 


*J 

II 

0 O' 

0 

N C V 

II 


ii 

l 

3 

+ 


O D UJ O X £L 

UJ 

o o: 

UJ 

UJ 

« 

in 



O' 




D 



in 

4J 

L L 

u 



n 


Z 

u* 


UJ Z > 

Z 

u in m 

u a. 

in 

in 

c * 

• » L 

V 


L 




Z 

c 


n 

m 

l •> m 

** 

II 0 II 

o 


o 

Pi 

II 










H u 

C C V 



no 

ft 



II 

L 

w 

c 

■ pH 

4 H 


■P u u 

UI 


Ui 

Ii 

L 

ft 


4 QJ Hi 

4 

4 4 

4 

4 4 

4 

4 

T) O' 

- in 

c 

■« 

II 

^H 



r-i 

3 

in 

• pH 


L 

L 

C II *J 

ui 

•p 

> 

u 

0 

pH 


c c c 

L 

C C 

C 

c c 

c 

c 

L 

cr +j » — 


o 

k. 

■H 



•H 

+J 

O' 

TJ 

T) 

V V u 

U 

3 l in 

0 >CN 

O' O' 

L 

-pi 


•H H -Pt 

■H 

•|H H 

H 

•H H 

•H 

•H 

in m 

L C h 

4- 

II 

*J 

£ 



UI 

4 

u 

4J 

■M 

C C £ 

£ 

0 4J TJ 

L 

U 

L 

L 

L 

£ 


4- 4- H- 

4- 

4- 4- 

4- 

4- 4- 

4- 

4- 


TJ h L 

•H 

•H 

in 

Z 



in 



in 

in 

H Pi U 

U 

u a pH 

t 


ft 

ft 

ft 

Z 


4 QJ HI 

4 

4 4 

ft 

4 4 

4 

4 

■p +> 

+J fl V 






















TJ p TJ 

U 

TJ TJ 

u 

V T3 

TJ 

TJ 

c c 

4 H C 









4 














^NK)4 , in'0N0DI>O^lNK)4‘in'0NCD0'O^lN 


inONCDlhO^M n- m'OMDO'OH(NfO<rin>OMllO'0-tNK)'itin'OMD5‘OH(NH4in>OMD 

ph^phphphnncn (M MiMMiNiNronnioKJKjnKjfon^r^i-^^^^^^^-ininininininMiinin 


64 


Dr. Dobb’s Journal, Number 74, December 1 982 

555 


ur iNIbHEST 


by Michael Wiesenberg 


Of PAC RAT and Other Hardware 

H-1000 from Technical Micro Sys¬ 
tems Inc. is a Z-80/8086 upgrade for 
the H89/Z89. It replaces the CPU, re¬ 
quiring no modifications, with a software- 
selectable 2 and 4 MHz clock and an 8 
MHz 8086. In Z-80 mode, the H-1000 
runs all present Heath/Zenith HDOS, 
CP/M-80, or Pascal software; in 8086 
mode, it is compatible with Zenith’s 
Z-100 and the IBM PC with MSDOS, 
CP/M-86, or both. The board comes with 
128K RAM, expandable to 1 megabyte. 
A RAM disk emulator copies an entire 
disk into RAM for instant access. For 
$1495 you get the board, five input/ 
output slots, diagnostic software, and 
MSDOS or CP/M-86. Multi-user and 
multi-task operating systems are also 
available. Reader Service No. 469. 

Six megabytes of on-line random ac¬ 
cess storage, with removable cartridges, 
for $480? PAC RAT from DAMCO is a 
random access rape drive that uses two in¬ 
expensive (they say, though they quote 
no price) removable magnetic tape car¬ 
tridges. The package is the same size and 
shape as a minifloppy drive, with stan¬ 
dard minifloppy power requirements and 
controller interface so it can plug right 
into existing systems. You’ll have to pro¬ 
vide a box for the unit, and mount it 
yourself, and you may have to add a fan, 
depending on its orientation. Transfer 
time is 250,000 bits per second, latency 
is typically 400 milliseconds, and random 
access 740 milliseconds. Reliability speci¬ 
fications, they state, are “unknown at 
this time.” Reader Service No. 431. 

Hand-held computers can be given 
the capabilities of much larger systems 
with the DataShuttle Peripheral from F/A 
Technology (formerly Friends Amis), de¬ 
velopers of the HHC Hand-Held Comput¬ 
er System marketed by Panasonic and 
Quasar. The DataShuttle is a “sleeve” 
that fits around an HHC, and provides up 
to 40K non-volatile CMOS RAM, 96K 
ROM, a direct-connect modem with 
automatic dialing, an acoustic coupler, 
real-time clock, a cassette tape controller, 
RS-232 and parallel ports, Forth and 
BASIC compilers and interpreters, and 
word processing software. Peripherals in¬ 
clude an EPROM burner, bar code read¬ 
er, portable printers, and TV adapter. 
System prices start at $380. Reader Ser¬ 
vice No. 441. 

Don’t throw away that wornout 
printer ribbon! The Ink-A-New company 
will re-ink your cartridge for free (offer 


66 

556 


good until January 15) if you purchase a 
custom-designed Ink-A-New Cartridge 
Re-Inker for $22.50 plus $2.50 p&h. 
Since cartridges are not standard in de¬ 
sign and dimensions, they need your old 
one to custom build a Rube Goldberg- 
like gadget through which you hand 
crank ribbons when their ink begins to 
fade, permitting virtually endless reuse of 
ribbons. They offer a three-week money- 
back guarantee on the $22.50, and you 
can still keep the re-inked cartridge. 
Reader Service No. 449. 

Softer Wares 

CP/M has not thus far been available 
for Radio Shack’s hard disk, but Aton 
International has changed that by intro¬ 
ducing ATON CP/M 2.2 for TRS-80 
Models II and 16. Partitioning can subdi¬ 
vide the hard disk into logical drives that 
simulate multiple drives, permitting back¬ 
ing up onto unused parts of the same 
disk. Data can also be backed up onto a 
different hard disk, or files as large as 8 
megabytes can be backed up onto multi¬ 
ple floppies. Either TRSDOS or CP/M 
can be booted up, so that application pro¬ 
grams formatted for either can be stored 
on the same hard disk, or ATON CP/M 
can bootstrap directly from the hard 
disk. The software costs $279; present 
ATON CP/M owners can upgrade to hard 
disk format for $125. Reader Service 
No. 428. 

Digital Marketing offers Active Trace 
for M BASIC. Its SCOPE facility provides 
real-time information about running pro¬ 
grams. Like MBASIC’s TRON (trace on) 
facility, it displays line numbers, but also 
displays variables with their current 
values as encountered. Optionally, specif¬ 
ic variables and program sections can be 
isolated for analysis. VREF cross refer¬ 
ences all variables, and GOREF cross ref¬ 
erences all GOTO and GOSUB state¬ 
ments. The documentation includes infor¬ 
mation on programming techniques to 
minimize errors and make them easier to 
find, and details on how to find the er¬ 
rors. Active Trace normally costs $125, 
but contact them for their special price 
to be offered during December only. 
Grammatik, the word processing facility 
that goes far beyond spelling dictionaries 
by actually checking your grammar and 
writing style and looking for overuse and 
misuse of certain key phrases, is also avail¬ 
able for $150. Reader Service No. 435. 

Third-party software for the IBM 
Personal Computer can be reasonably 


priced. Info-Sort from Info-Pros is a 
sort/select package they claim to be the 
fastest available. Reading and sorting one 
thousand 64-byte records on a 6-byte 
character key takes under 20 seconds. 
This assembly-language utility runs under 
PC-DOS (i.e., MSDOS) or interfaces with 
applications, and uses a control file to 
add or modify sort/select parameters. 
Keys (up to nine) can be strings, integers, 
and single- or double-precision numbers. 
The output can be a sorted copy of the 
input, a file or relative record numbers of 
the sorted input, or an index file that 
contains the sorted keys with the relative 
record number of each. Up to 64K of 
records, each with a length up to IK, can 
be sorted, in ascending or descending 
order. Up to eight logical conditions can 
be used to include or omit records, and 
as many as 999 records can be skipped. 
Your IBM PC needs 64K, PC-DOS, one 
drive, an 80 x 25 monitor, and BASIC 
(for the demonstration and to modify 
control files). $145. Reader Service 
No.445. 

InterLync, from Starside Engineer¬ 
ing, is a terminal emulator and file trans¬ 
fer package for the IBM PC. It communi¬ 
cates with mainframes, CP/M systems, 
APL timesharing systems, etc. Files 
sent to and received from CP/M comput¬ 
ers and bulletin board systems use the 
“Xmodem” block transfer protocol, or 
you can configure in may ways an ETX/ 
ACK line-oriented protocol. Baud rates 
are 110 to 9600, data words are seven or 
eight bits, with even, odd, or no parity. 
InterLync is controlled through various 
screens by the PC’s programmable func¬ 
tion keys. An APL option can be ordered 
to replace the graphics character PROM 
on either PC video board, and character - 
to-key mapping can be switched between 
ASCII and APL with one keystroke. 
You’ll need 128K, one drive, and an asyn¬ 
chronous communications port. The stan¬ 
dard version costs $100; add $75 for the 
APL option. Reader Service No. 465. 

Three Forths 

COLOR-FORTH, by Hoyt Stearns 
Electronics, for the TRS-80 Color Com¬ 
puter has a RAM version that requires 
16K of RAM, and a ROM version that 
works with 4K of RAM, and can be in¬ 
stalled in a disk controller or in a ROM 
cartridge. It comes with an editor and 
utilities. COLOR-FORTH has a trace fea¬ 
ture, handles interrupts, maintains the 


Dr. Dobb’s Journal, Number 74, December 1982 



CPU carry flag for extended math, and 
supports bit manipulation, graphics, 
sound, task multiplexing, fast math, auto¬ 
repeat keys, control keys, disk and tape 
control, and links to BASIC routines. The 
RAM version is $58.95, while $123 gets 
you ROM plus RAM version. Reader Ser¬ 
vice No. 471. 


FORTH-32, from Quest Research, is 
a complete software development system 
for the IBM PC. It uses 16- and 32-bit 
addressing modes; the interpreter 
“knows” at run time which mode was 
compiled. Sixteen bits are sufficient for 
programs that reside within 64K bytes; 
32-bit addressing is used for larger pro¬ 
grams. FORTH-32 is fig-FORTH com¬ 
patible. For $100, the package includes 
base language, segment-sensing compiler, 
mixed-mode addressing interpreter, multi- 
mode verbs (reserved words), case state¬ 
ment, package builder utility, 8086 as¬ 
sembler, decompiler, screen editor, de¬ 
bugger, DOS interface, and graphics. A 
floating-point package that includes soft¬ 
ware for 8087 floating-point library and 
an 8087 assembler compatible with the 
8086 assembler costs $50. Reader Ser¬ 
vice No. 457. 


fig-FORTH-79, from Mark Manning, 
is fig-FORTH with double-number stan¬ 
dard extensions for any 6502 system that 
uses Micro Technology Unlimited’s 
CODOS. It comes with an editor, 6502 
assembler, and utility screens, on 8-inch 
single-sided double-density disk for 
$145, or on cassette without the inter¬ 
face to CODS, for any 6502 system that 
reads either KIM or MOS Technology 
Standard recording formats, for $38. 
Reader Service No. 453. 


One FORTRAN 

Nevada FORTRAN for CP/M, from 
Ellis Computing, is both a subset and 
superset of ANSI 1966 FORTRAN. Ex¬ 
tensions include IF . . . THEN . .. ELSE, 
TRACE debugging, COPY, seven-dimen¬ 
sional arrays, and random access to files. 
The compiler generates 8080 machine 
code on any CP/M system with a mini¬ 
mum of 32K. The diskette and 165 pages 
of documentation run $199.95. Reader 
Service No. 439. 


TRACE, THUG, RAMS, and 
Other User Groups 

TRACE, the Toronto Region Associ¬ 
ation of Computer Enthusiasts, a non¬ 
profit organization, publishes a monthly 
newsletter mailed free to members. Mem¬ 
bership is $13 a year. TRACE just joined 
forces with THUG (the Toronto Heath 
Users Group). TRACE appears to be for 
users of all microcomputers. Write to 
TRACE, Box 6922, Station “A”, 
Toronto, Ontario M5W 1X6. 

RAMS, the Rochester Area Micro¬ 
computer Society, offers a monthly news¬ 
letter, Memory Pages, with membership, 
which runs from October to September, 
for $7.50, or $4 after April. RAMS regu¬ 
larly schedules experts from computer 
companies to speak and demonstrate new 
equipment. The entire group meets 
monthly, and CP/M and North Star “sub¬ 
groups” meet between times. Rochester 
Area Microcomputer Society, Box 90808, 
Rochester, NY 14609. 

Membership in The Northwest Com¬ 
puter Society is for personal and small 
business computer users in the Puget 
Sound area, and includes in its yearly $ 12 
dues a subscription to The Northwest 
Computer News, a professional-looking 
paper also sold on newsstands. Northwest 
Computer Society, Box 31495, Seattle, 
WA 98103. 

The CSRA Computer Club of Augus¬ 
ta, Georgia, holds meetings open to the 
public the third Thursday of each month. 
$12 yearly dues include a monthly news¬ 
letter. CSRA Computer Club, Box 284, 
Augusta, GA 30903. 

The Amateur Computer Group of 
New Jersey is a non-profit educational 
corporation for users of all micros. The 
$14 yearly membership includes a sub¬ 
scription to the monthly ACG-NJ News. 
Amateur Computer Group of New Jer¬ 
sey, Box 319, South Bound Brook, NJ 
08880. 


Dr. Dobb’s Journal, Number 74, December 1982 


67 

557 



Letters (Continued from page 9) 


It all got started when I was playing 
around with the graphing routine pro¬ 
vided with JRT Pascal. When I attempted 
to use it my system would “hang.” By 
“hang” I mean nothing seemed to be 
happening. I used the trace facility of 
JRT Pascal to isolate the problem to a 
file close within the graphing routine. 

I tried file operations, including open 
and close, with other user programs and 
had no problem. So, I proceeded to try 
to isolate the problem further with DDT. 

When I attempted to use DDT I dis¬ 
covered another problem. The sequence 
of commands was as follows: 

DDTEXEC.COM to load the JRT 
Pascal Executive 

[PROGRAM.INT to identify user 
program 

G to commence 

execution 


When the executive attempted to open 
the user program file to load it into the 
system, the system would hang again. 

Then I decided to try to determine 
whether this new problem was related to 
JRT Pascal or not. So, I tried DDT with 
a dump utility as follows: 

DDT DUMP.COM 

1DUMP.COM 

G 

The results were the same. When the 
dump program attempted to open and 
read itself the system hung. 

From these experiences I hypothe¬ 
sized that I had two problems, one with 
JRT Pascal and one with DDT, or I had 
one problem with the operating system. 
I proceeded to attempt to trace instruc¬ 
tion execution to isolate the problem still 
further. 

1 soon relearned that DDT does not 
trace BDOS or BIOS, and that is where 
the system hangs. I learned of a method 


for getting DDT to trace BDOS execu¬ 
tion. I put a RST 7 instruction at a strate¬ 
gic location in the BDOS. When this in¬ 
struction is executed, DDT breakpoints. 
Then tracing can be done. However, more 
problems arose to cloud the issue. 

I had difficulty with RET instruc¬ 
tions. It seems that DDT would not re¬ 
turn to the proper instruction or the sys¬ 
tem would hang if I traced through a 
RET. I examined the stack and made 
another befuddling discovery. DDT 
messes it all up. I hypothesize that DDT 
puts trap addresses on the stack so it can 
regain control after a RET. I don’t know 
for sure, though. Anyway, I discovered 
for sure that I could not trace through a 
RET. 

I also discovered, by the way, that 
DDT will not allow overwrite of the stack 
with the “F” command. I tried this in 
a moment of desperation to see whether 
I had problems writing to memory at that 
location. No go. I could zap bytes on 
both sides of it, but not in it. 

Next I chose to disassemble code and 
insert RST 7 instructions at the return 
locations from RET instructions and at 
jump instructions. Then I would give 
DDT the command to go. It would break¬ 
point, and I could examine the situation. 
If the system did not hang, I would pro¬ 
ceed in the same manner through the 
next stretch of code. 

Eventually, I isolated the hang-up 
to a small section of code in the BIOS. 
Since the BIOS is in ROM, I could not 
breakpoint in the BIOS, but I did put 
enough clues together to isolate the hang¬ 
up to a very small section which included 
the Z-80 El, INI instructions and, at the 
end, a RETI instruction. Since the INI 
and RETI instructions are not 8080 in¬ 
structions, I reasoned that they, espe¬ 
cially the RETI, may cause a problem for 
DDT, but I don’t know for sure. 

Another tiling I don’t know is how 
this problem relates to the problem with 
JRT Pascal, if it does. 

So, why did I write? And what do I 
want? Well, I don’t hold out a lot of hope 
for finding the answers to my close prob¬ 
lem with JRT Pascal or my problem with 
DDT, but maybe someone could at least 
enlighten me on the inner workings and 
methods of DDT. Who knows, maybe 
the real answer will pop up. 

Of specific interest to me is what 
DDT does to the stack, what happens to 
RET instructions when tracing BDOS 


AXJRTPAS2 MULTIPLY 

JRT Pascal 

ver 2.1 

Copyright 1982 JRT Systems 

0000 0001 

JXTRACE 

0003 0002 


0006 0003 

PROGRAM MULTIPLY( OUTPUT ); 

0009 0004 

{ 5 September 1982 } 

000F 0005 

VAR TEMP,TEMPO : REAL; 

0015 0006 

BEGIN 

0025 0007 

TEMP 0.0; 

002E 0008 

TEMPO 0; 

004C 0009 

WRITELN( 'TEMP - '.TEMP ); 

00A5 0010 

WRITELNC '2.0*TEMP - ',2.0 * TEMP,' 2.0*0.0 - ',2.0 * 0.0 ); 

00FE 0011 

WRITELN( 'TEMP*2.0 - '.TEMP * 2.0,' 0.0*2.0 - ',0.0 * 2.0 ); 

0155 0012 

WRITELNC '2.0*TEMP0 - ',2.0*TEMP0,' TEMP0*2.0 - ',TEMP0*2.0 ); 

017E 0013 

WRITELNC '2*0 - ',2*0,' 0*2 - ',0*2 ); 

01DB 0014 

WRITELNC '3.0*0.0 - ',3.0*0.0,' 0.0*3.0 - ',0.0*3.0 ); 

0238 0015 

WRITELNC '4.0*0.0 - ',4.0*0.0,' 0.0*4.0 - ',0.0*4.0 ); 

0295 0016 

WRITELN( '5.0*0.0 - ',5.0*0.0,' 0.0*5.0 - ',0.0*5.0 ); 

02F2 0017 

WRITELNC '3.5*0.0 - ',3.5*0.0,' 0.0*3.5 - ',0.0*3.5 ); 

034F 0018 

WRITELNC '4.3*0.0 - ',4.3*0.0,' 0.0*4.3 - ',0.0*4.3 ); 

03AC 0019 

WRITELNC '5.8*0.0 - ',5.8*0.0,' 0.0*5.8 - ',0.0*5.8 ); 

No errors detected 

Module size » 948 dec bytes 

End of compile for MULTIPLY 

A>EXEC MULTIPLY 

Exec ver 

2.1 

TEMP =• 0 


2.0*TEMP = 

2 2.0*0.0 - 2 

TEMP*2.0 * 

0 0.0*2.0 - 0 

2.0*TEMP0 

- 2 TEMP0*2.O - 0 

2*0 - 0 

0*2 - 0 

3.0*0.0 - 

3 0.0*3.0 - 0 

4.0*0.0 - 

4 0.0*4.0 - 0 

5.0*0.0 - 

5 0.0*5.0 * 0 

3.5*0.0 - 

3.5 0.0*3.5 - 0 

4.3*0.0 - 

4.3 0.0*4.3 - 0 

5.8*0.0 - 

5.8 0.0*5.8 - 0 

Program termination 


70 

558 


Dr. Dobb’s Journal, Number 74, December 1982 




(I suppose the answer is that it shouldn’t 
be done), and what it does with Z-80 
instructions in the go mode and in the 
trace mode (I suspect there’s a differ¬ 
ence). 

If you or your readers can supply 
any of this or related information, I 
would appreciate it. Thanks for your 
interest. 

Sincerely, 

Monte Schmiege 
707 Kilbourn Ave. 

West Bend, WI 53095 




72 


Dr. Dobb’s Journal, Number 74, December 1982 

559 





Index 


This is an index to articles and programs, though some letters have also been included. References are of the 
form bound volume number /page number. The processor type or format, where relevant, follows the entry 
in brackets. Items are listed by author(s), processor type, and program type. Cross references are noted in 
parentheses following the entries. References separated by a comma are connected in some way; those separated 
by a semicolon are completely distinct. This is a cumulative index for Dr. Dobb's Journal bound volumes 
5 through 7. 


Volume 5 - 1980 


Volume 6 — 1981 


Volume 7 — 1982 


January. 

.41 

January. 

.51 

January. 

.63 

February. 

.42 

February. 

.52 

February. 

.64 

March. 

.43 

March. 

.53 

March. 

.65 

April . 

.44 

April. 

.54 

April. 

.66 

May. 

.45 

May. 

.55 

May. 

.67 

June/July. 

.46 

June. 

.56 

June. 

.68 

August. 

.47 

July. 

.57 

July. 

.69 

September. 

.48 

August. 

.58 

August. 

.70 

October. 

.49 

September. 

.59 

September. 

.71 

November/ December. 

.50 

October. 

.60 

October. 

.72 



November. 

.61 

November. 

.73 



December. 

.62 

December. 

.74 


1802 

cross assembler [CP/M] 5/432 
Elf 5/122 
2716 

EPROM programmer [M-80] 6/189-190 
6502 

assembler for the 6502 6/369-373 
byte-count routine 6/83 
improved timing 7/111 -112 
opcodes for analysis [BASIC/ PET] 6/96-97 
reader response 6/185 
6800 

cross assembler [CP/M] 5/432 
video display program 5/439 
6809 

multi-byte opcodes 6/279 

Tiny BASIC for the 6809, Santa Barbara 6/202-203 
68000 

cross assembler 7/427-438, 7/488-498 
interfacing to an AIM 65 7/8-12, 7/29-31 
mnemonics 7/449-453 
multi-6800s 7/244-247 
multi-tasking kernel 7/15 
8080 (see also Z80) 6/187 

/8086 cross assembler 7/156-164 

/Z80 indirect addressing 5/289; 5/394 

and CP/M 5/396 

and Z80 5/289; 5/394 

fast fourier transform 5/164 


8080 (conid.) 

memory chip tester 6/533-534 
North Star DOSMOVER 6/124 
Pidgin 7/116 
PILOT 5/82 

registers in 47 bytes 5/173 
Small-C compiler 5/176 
translator system (to Z80) 5/216 
unaltered 5/42 
variations 5/173 
Z80 

cross assembler for 8080/Z80 6/230-234 

editor, assembler, disassembler in XL package 6/36^40 

8086 (see also 8080) 

FORTH assembler 7/61 
trig 7/462-464 

8087 7/361-363 
8813 

polymorphic math functions 5/125 
9 or 16 bits? [Opcode design] 5/373 
9900 5/46; 5/108 


Acoustic coupler 5/351 
Adams, E. 6/514 
Addendum 

Newbury, S. 5/395 
Addition trick 5/125 


561 






































Addressing, indirect 
6502 5/333 

8080/Z80 5/289; 5/394 
Adler, R. 5/443 
ADM-3A 5/56 

Adven-80, adventure development system 6/468-473 
AIM 65/68000 interface 7/8-12, 7/29-31 
Airy, B. 6/6, 6/7, 6/11 

Algorithm to convert integer date [MP/M] 6/201 
Algorithms 5/130; 5/169; 5/207; 5/264; 5/350 
FORTH 6/148-149 
numerical 7/309 
vector generation 7/550-551 
Allison, D. 5/73; 5/169; 5/207; 5/264; 5/350 
Alpha listing H-8 5/104 
ALS-8 to CP/M conversion 5/24; 5/261 
Animal 5/350 
Apple 

user interface 5/267 
Apple II 

file system. Tiny 6/240-241 
program renumbering 5/67 
ROM byte-finder 5/243 

Argum—A C command line processor 7/331-347 
Arrays 

cassette I/O routine [BASIC] 6/150-152 
FORTH 5/242 
North Star 5/40 
Artificial intelligence 6/419 
“Thinking” program, ERGO 6/100 
Artificial intelligence language, LISP 6/526-530 
Assemblers 

6800 + 1802 cross assembler [CP/M] 5/432 

assembler for the 6502 [FORTH] 6/369-373 

cross assembler for the 8080/Z80 6/230-234 

editor, assembler, disassembler in XL package 6/36-40 

EDITOR/ASSEMBLER PLUS 6/123 

FORTH 8086 7/61-33, 7/72-85 

table driven 5/59; 5/171 

Z80, subroutines 5/159 


Bach, S. 5/243; 5/267 
Balcom, O. 5/39 

Barker, L. 5/42; 5/173; 5/205; 5/222; 5/268; 5/309 
Barnhart, J. 7/388 
BASIC 5/42 

arrays, cassette I/O routine 6/150-152 
BASIC-FORTH 6/427^428 
branches 7/101-103 
IBM PC BASIC 7/278 
LLL BASIC 7/248 
memory dump 5/260 
memory management 7/500 
MIN and MAX definition 6/312 
North Star 

cross-reference 5/147; 5/151; 5/339; 5/382 
debugging concatenated programs 6/64 
DOSMOVER 6/124 
patches 5/40; 5/171 

small VM development, portable software 6/492-495 
statement generator 5/418 
string arrays 5/40 
terminal programs for 6/487 
text editor input routine 6/42-43 
time keeping in microcomputers 6/287-289 
two column display 5/259 
PET 

analysis 6502 opcodes 6/96-97 
speed reading using a computer 
POKE and PEEK, BASIC version 3.2 enhancement 6/62 


BASIC (conid.J 
Poly 88 5/141 

polynomial evaluation 6/146-147 
Rubik’s cube simulator 6/291-292 
structured 5/201 
time delay circuit design 6/197 
Tiny BASIC 5/201; 5/356 

Tiny BASIC for the 6809, Santa Barbara 6/202-203 
bugs 6/419 

ZX80 Sinclair 6/60-61 
BASIC-FORTH [FORTH] 6/427^428 
BASIC-Plus 6/45 
Bassett, S. 6/148 
Bender, A. 5/209 
Bender, A.L. 7/116 
Bentley, J. 5/130 
Bertollo, D. 5/348 
Binary to decimal 5/73 
conversion routine 6/271 

reader’s improvements 6/422 
Blum, R. 7/302 
Blessing, R. 6/487 
Bokelman, R. 5/126 
Bolton, B. 6/330 

Bomberger, A, 7/86, 7/175, 7/546 

Borochoff, R. 5/126 

Brodgen, W. 6/237 

Bronstein, M. 5/122 

Brown, A. 5/443 

Brown, D. 5/67 

Bugs 

Small-C 5/83 
SAM 76’s CP/M 5/83 
Bulletin boards 7/224-225 
Byte 

ROM byte-finder [Apple II] 5/248 
Byte-count routine [6502] 6/83 
Byte manipulation and pointers [Fortran] 6/103 

C language (see also Small-C compiler) 5/15; 5/176; 5/191 
command line processor 7/331-347 
cross reference generator 7/266-270 
time functions 6/330-331 
C, Small (see Small-C) 

C, Tiny (see Tiny-C) 

Caeser, A. 5/309 
Cage, T. 6/124 
Cain, R. 5/176; 5/312 
Calculators 5/392 
Calendar routines 6/313, 6/516 
Card shuffling 6/356 
Carter, J. 5/159; 5/267 
Cason, R. 5/127 
Cassette interface 5/13 

Caulkins, D. 5/230; 5/284; 6/63,6/95; 7/145 
CBASIC-2 

DB.BAS package file maintenance 6/80 
CDOS 5/25/394 
Chamkis, J. 7/188, 223 
Check digits 7/171-172 
Checksums 7/302-303 
CLOAD magazine, Inc. 6/122 
Colley, W. 5/432 
COMAL-80 [CP-M] 6/235-236 
as an interpreter 6/235 
Compal-80 6/102 

Compiler writing tool, META 4 language 6/321 
implementing an M4 interpreter 6/329 
M4 language 6/ 325 
META 4 language 6/322 


562 



Compilers 

META II 5/169 

Runic: An interactive, extensible compiler [FORTH] 
7/106-108, 7/184-186 
Small-C 5/176; 5/312; 7/520-546 
error run-time library routine 6/53 
bug fixes and enhancement 6/228 
cross-compiler implementation 6/66-67 
programming 6/ 504-507 
Tincmp, compiler for Pidgin 6/284-286 
Computer conferencing 6/429-431 
Conley, W. 5/352 
Connell, J. 7/486 
Conversion 

binary to decimal conversion routine 6/271 
file conversion, H-8 text editor to CP/ M 6/239 
submit file comments 6/200, 6/415 
Conversion routines 

ASCBIN and BINASC [8086 assembly language] 
7/413-414 

Conversions / converters 
ALS-8 to CP/M 5/24 
Binary to decimal 5/73 
CP/M to UCSD Pascal 5/367 
Core, G. 5/443 
Coroutines 7/3-5, 7/26 
Corrections 

Barker, L. 5/309 
Keay’s table 5/41 
Parsons, R. 5/83 
Silverston, S. 5/172 

Cortesi, D. 6/200, 6/271, 6/312, 6/414, 6/422, 6/520; 7/6, 

7/101,7/152, 7/197, 7/237, 7/278, 7/280, 7/329, 7/373, 
7/424, 7/471,7/503 
COSMAC 5/282 
CP/M 5/11; 7/277, 7/317 
6800 + 1802 cross assembler 5/432 
ALS-8 to CP/M file converter 5/24; 5/261 
bug [SAM 76’sCP/M] 5/83 
and CDOS5/29; 5/394 
COMAL-80 6/235-236 
DDT, circumventing 6/200 
downloading modem with MBOOT3 7/454-461 
DUMP utility readability enhancement 6/93 
file conversion, H-8 text editor to CP/M 6/239 
game 5/406 

Hardcopy device driver program 5/341 

interrupts 7/ 546-549 

keyboard input definition 6/194-196 

linking to Morrow’s cassette interface 5/13 

NEW USER 7/217-222 

OSI’sCP/M 5/205 

PEN 5/34 

print utility 7/256-265 
QU1TIF 7/373-376 

SCRIBE IX, word processing package 6/220-222 
software 5/4; 5/32 
submit file comments 6/200 
table-driven assembler 5/59 

text editor WORD-MASTER with the Compal-80 6/102 
tiny interpreter [CP/M flavored C] 5/15 
to UCSD Pascal file conversion 5/367 
Z80, 8080, and CP/M 5/396 
ZDM debugger 6/186 
CP/M-86 

vs. MS DOS 7/280-291 
vs. PC-DOS 7/501 
Crimmins, J. 7/314 
Crockett, T. 5/79 
Crockford, D. 7/93 


Cross assembler for 8080/Z80 [8080/Z80] 6/230-234 
XASM-86 features 6/232 
Z-88 project 6/ 230 
Cross assemblers 5/432 
68000 7/427-438, 7/488^198 
8080/8086 7 156-164 
Cross reference generator [C] 7/266-270 
Culleton, J. 5/125; 5/352 

DaCosta, F. 5/39 
Daetwyler, D. 7/256 
Darling. M. 5/445 

Database design [FORTH] 6/398—401 
Davis, D. 6/126 

DB.DBAS package file maintenance [CBASIC-2] 6/80 

DDT, circumventing [CP/ M] 6/200 

Dea, R. 5/216 

Deane, R. 5/242; 5/434 

Debuggers 

DDT, circumventing 6/200 
ZDM debugger for CP/M users 6/80-81 
Debugging concatenated programs [BASIC/North Star] 6/64 
Decompiler [FORTH] 6/403 
Demas, J. 6/36 
Design 

algorithm 5/130 
opcode 5/373 
Diablo 5/268 

Digital systems DDOS 5/127 
Displays 
6800 5/439 
North Star 5/259 
Dobyns, B. 6/178 
Documentation 5/426 
Double density system 5/339 
Douds, C. 5/127 
Drexler, K. 5/439 

DUMP utility readability enhancement [CP/M] 6/93 
implementation 6/227 
Dump/Dumping 
BASIC 5/260 

Duncan, R. 6/69, 6/140, 6/187, 6/403; 7/61, 7/292, 7/361, 
7/413, 7/417, 7/501, 7/515 
Dye, J. 5/309; 5/444 

Ecklein, D. 5/394 

Editors (see also Screen editors. Text editors) 
editor, assembler, disassembler in XL package [8080/Z80] 
6/ 36-40 

EDITOR ASSEMBLER PLUS [TRS-80] 6/123 

program editors, reassessment of 237-238 

screen editor. MINCE 6/178 

screen-oriented editors 6/383 

text editor input routine [BASIC] 6/42-43 

text editor WORD-MASTER with the Compal-80 6/102 

underline modification 6/126 

ZX80 Sinclair 6/60-61 

Electronic phone book [PCNET project] 6/63, 6/87, 6/133, 
6/176 
Elf 5/268 

Elizondo, F. 5/261 

Embedding wide characters within an ordinary line 6/515 
Emery, G. 7/59 
Enhancements 
ADM-3A 5/56 
entry points 5/267 
equations, differential 5/392 
Errata of computer programming 5/244 
Errors 5/309; 5/349; 5/446 


563 



Faulkner, D. 6/15 
Favitta, M. 6/80 

Fibonacci number sequence [FORTH] 6/9, 6/91 
Fiddes, L. 5/394 

Fifth generation computers 7/552 
File comparator [Z80] 6/15 
File conversion (see Conversion) 

H-8 text editor to CP/M [conversion] 6/239 
File system, Tiny [Apple II] 6/240-241 
File transfer 5/375 
File transfer utilities 7/355-360 
Flashwriter 1 5/406 
Floppy disk test [Z80] 6/140-145 
Foreign language trainer 5/423 
Formatter, TI 9900 5/46; 5/108 
FORTH 5/242; 5/434 
8086 assembler 7/61-63, 7/72-85 
algorithms 6/148-149 
assembler for the 6502 6/369-373 
BASIC-FORTH 6/427-428 
database design 6/398-401 
decompiler 6/403 
description 6/411-413 
Fibonacci numbers 6/9 
Fibonacci numbers sequence 6/91 
FORTH as language and environment 6/381-382 
formal definition 7/64-71 
floating-point package 7/377-385 
overview 6/6, 6/12 

construction of program-like commands 6/8 
metamorphic changes by concatenation of characters 
6/10 

primitives 6/7 

reader response 6/137, 6/185 
use by novices 6/12 
variables stack 6/7 

parameterized command concept 6/54-59 
reader response 6/186 
philosophy of 6/363-368 

software development methodology 6/364 
software tools 6/367 
programming style 7/386-387 
recursion 7/ 59—60 
relocating loader 7/388-292 
screen editor for H-19 7/393-397 
screen-oriented editor 6/383 
string routines 6/51 
Z8000 FORTH 7/398^12 
FORTH as a language and environment [FORTH] 
6/381-383 

FORTH description 6/411-413 
Fortran 

byte manipulation and pointers 4/103 
Small-C cross-compiler implementation 6/66-67 
Frampton, H. 5/24 
Franz, M. 7/106, 7/184 
Freed, E. 6/103 
Funkhouser, R.K. 7/313 
Fusfield, R. 5/168 
Fusina, L. 7/8 


Gabrielson, M. 5/443 
Gale, W. 6/240, 6/282, 6/321 
Gale, W.A. 7/476 
Games, CP/M 5/406 
Gammell, J. 5/40 
Garcia, L. 5/418 
Gaugler, G. 5/345; 5/423 
Gelles, A. 5/85 


Gibson, T. 5/201 
Gintis, H. 7/439 
Glenn, G. 7/248 
Glitch 5/222 

Go: utility command under CP/ M 5/11 

Gordon, H. 5/324; 5/373; 5/395; 6/6, 6/54 

Gordon, H.T. 7/309 

Gramer, J. 5/125 

Granuzzo, C. 7/8 

Graphics 

Flashwriter I [CP/M] 5/406 

microprocessor-assisted system 5/79 
Graphics, IBM PC 7/292-301 
Greenlaw, D. 6/88 
Grigonis, R. 7/552 
Guthery, S. 5/201 


H-8 computer 6/239 
Hacking 6/510-514 
Halfant, M. 7/316 
Hallem, R. 6/149 
Hallen, R. 5/34 
Hamlin, C.L. 7/241, 7/304 
Hamlin, G. 5/70 

Hardcopy device driver programs [CP/M] 5/341 
Hardware reviews 

Hayes Stack Smartmodem 7/231 
Sinclair ZX81 7/188 
Universal Data Systems 103LP 7/145 
Hardware simulator 7/241-243, 7/304-308 
Harris, D. 6/63, 6/177 
Harris, K. 6/363 
Hashing 7/471 
Hatfield. J. 6/122 
Haydon, G. 6/398 

Head, G. 5/222; 6/80; 6/220; 7/95, 7/143, 7/217, 7/454 
Heath 

H-8 5/104; 5/287; 7/109-110, 7/122-123, 7/152-153 
H-14 5/201; 5/332; 5/395 
H-19 7/329 
Hemminger, C. 5/309 
Henderson-Gragg, R. 7/231 
Hendrix, J. 6/492 
Hendrix, J.E. 7/20,7/520 
Hex keyboard 5/122 
Hightower, M. 6/127 
Hinds, J. 6/202 
Hoffman, R. 146 
Holtrichter, J. 5/339 
Horizon [Interfacing H-14] 5/395 
Howell, J. 5/173; 5/266; 5/396 
Hudson, G. 5/259 
Hudson, L. 5/40; 5/382 
Hudson, R. 5/356 
Hughes, L. 5/375; 7/355 

Hypotenuse approximation on integer values 6/200 
reader input 6/312, 6/359, 6/520 


IBM PC 7/237 
BASIC 7/278 

custom character sets 7/515-519 
graphics 7/292-301 
Improvements to: 

Apple user interface 5/276 
CP/M and CDOS 5/394 
Zant's modular programming 5/266 
Indirect addressing [8080 and Z80 5/289] 5/333 
Ingerman, P.Z. 7/172 


564 



Installation, Phantom-deselect 5/42 
Interface 
Apple 5/67 

CP/M linked to Morrow’s cassette interface 5/258 
H-14 to Horizon 5/395 
Wh 14 printer to serial POR 5/443 
Interpreter 
LISP 5/268 
Tiny 5/15 


James, J. 6/429 
James, J.S. 7/202 
Jamieson, C. 5/83 
Johnson, D. 5/84 
Johnson, J. 6/514 
Johnson, R. 5/171 
Johnson, S. 5/197 


Kalish, M. 6/122 
Kan, M. 7/211, 7/348 
Kanefsky, R. 6/514 
Keay, C. 5/41 
Kernigham, B. 5/191 
Keyboard, Hex 5/122 

Keyboard input definition [CP/M] 6/194-196 
theory 6/195 

Keyplus integrated utility 5/309 
Kildall, G. 5/2 

Knippenberg, H. 5/260; 6/197 
Knuth, D. 5/88; 5/244 
Konopik, N. 5/234; 5/332 
Kossow, A. 7/244, 7/427 
Kruse, R. 5/272; 5/395 
Kudlac, S. 6/514 


Language register 6/3 

Languages (see also individual names) 

C 5/191 
foreign 5/423 
META II 5/142 

syntax-oriented compiler writing language 5/142 
Las Vegas super slot 5/406 
Lawrence, J. 6/45 
Laxen, H. 6/383 
Lesk, M. 5/19! 

LET processor [LLL BASIC] 7/248-255 
Lindenschmitt, G. 5/84 
LISP (see artificial language) 

LISP, interpreter 5/268 
Listing, H-8 5/104 
Loeliger, R. 6/381 
Logic 5/348 
Long, W. 5/371 
Loughman, W. 5/431 
Love program 5/345 
Lucky, R. 5/171; 5/309 
Lunsford, D. 5/172 


M4 interpreter 6/329 
M4 language 6/325 
M-80 

2716 EPROM programmer 6/189-190 
Maclaughlin, J. 5/446 
Maggs, P. 6/127 

Mailing list label printer [SLIC] 6/149 
Martin, T. 5/443 


Math functions [8813] 5/125 
Mathematical typography 5/88 
Maurer, W. 5/333; 5/445 
Maurer, W.D. 7/111, 7/449 
MCALL-C 5/395 
McGaw, J. 5/125 
Measurement standards 7/93-94 
Memory chip tester [8080] 6/533-534 
Memory dump [BASIC] 5/260 
Memory test [Z80] 6/69 
Memory-mapped video displays 6/16 
META 4 (see Compiler writing tool) 

Michalski, M.W. 7/550 
Microchess 5/126 

Microprocessors (see individual names) 

Microsoft 5/222 

Miller, E. 6/189 

Miller, W. 5/13 

Mills, J. 6/230; 7/156 

MIN and MAX definition [BASIC] 6/312 

extended to other functions 6/354 
MINCE, screen editor 6/178 
MITS DOS disk to disk copy routine 5/209 
Mnemonics [68000] 7/449-453 
Modems 

downloading with MBOOT3 [CP/M] 7/454-461 

program for [FORTH] 7/202-207 
Modular programming 5/266 
Monitor MON 3 [TRS-80] 6/122 
Monitors 

Elf tiny 5/268 

SYM-1 5/324 
Monroe, A.J. 7/377 
Moore, F. 5/426 
Morrow, G. 5/13 
Moss, W. 5/104 
MOVIT 5/431 
MP/M 

algorithm to convert integer date 6/201 
MS DOS vs. CP/M-86 7/280-291 
Multiple file transfer 5/375 
Munro, J. 5/443 


N-LOGS 5/400; 6/53, 6/281 
Naess, O. 5/364 
Networks 5/226; 5/230; 5/257 
Newberry, S. 5/42; 5/125 
N1BASM 5/371 
Nichol, R. 6/123, 6/526 
Nicholson, L.K. 7/91 
North Star (see BASIC; Horizon) 

DOS 6/36, 6/270 
DOS MOVER [8080] 6/124 
terminal programs for 6/487 
North Star Horizon 
connection to Epson printer 7/208-210 
timer routine 7/86-90 
North Star VOS 7/20-23, 7/25-28 
Number language [N-LOGS] 5/400 


Oliver, J. 5/39 

Odette, L. 7/398 

Opcode design 5/373 

Operating systems (see individual names) 

OSI 5/205 

Output [COSMAC 1861] 5/282 
Ouverson, M. 7/224 



Palmer, J. 6/60, 6/194 

PAN protocol revision [PCNET project] 6/63 
Parameterized command concept [FORTH] 6/54-59 
access 6/55 

conditional-jump primitive 6/57 
data structures 6/55 
notation 6/54-55 
reader response [FORTH] 6/186 
status-register 6/56 
Pascal 5/75; 5/127; 5/367 
card shuffling 6/356 
“upside” down, nature of 6/4 
Patches 

POKE and PEEK, BASIC version 3.2 enhancement 6/62 
Patches, North Star DOS 5/40 
Pattern classifications 7/114-115, 7/124-126 
PC-DOS vs. CP/M-86 7/501 
PCNET 5/230; 5/284 
PCNET project 6/172 

electric phone book 6/63, 6/87, 6/133, 6/176 
PAN protocol revision 6/63 
PCNET protocol 6/63, 6/177 
PDP-1802 hardware simulator 7/241-243, 7/304-308 
Pehoushek, J. 6/291 
Pelle, M. 5/235 
PEN 5/34 

Performance evaluation 7/348-354 
Personal Computer Networks (see PCNET) 

PET 5/127 
Peter, K. 6/514 
Pfafman, F. 5/42 
Phelan, C 5/309 
Phillips, T. 5/443 

Philosophy of FORTH [FORTH] 6/363-368 
PHIMON subroutines 6/15 
Phone dialer 5/84 
Pidgin 6/321 

for 8080 [CP/M] 7/116-121, 7/127-140 
tests 7/476-485 

tincmp, compiler for Pidgin 6/284-286 
Z80 macro-assembly implementation 7/439-449 
Pidgin, systems programming languages 6/282-284 
PILOT 5/82 

Pocket computer, Radio Shack 6/88 
POKE and PEEK, BASIC version 3.2 enhancement [BASIC] 
6/62 

alternative patch 6/228 
Poly 88 BASIC 5/141 
Polymorphic 8813 math functions 5/125 
Polynomial evaluation [BASIC] 6/146-147 
Portable software development, Small VM 6/492-495 
Price, G.H. 5/282 
Print utility [CP/M] 7/256-265 
Printer [H-14] 5/332 
Printers 

printer toggle installation in North Star DOS 5.2 6/270 
Probes, logic 5/348 

Program editors, reassessment of [editors] 6/237-238 
Programmers 

2716 EPROM programmer 6/189-190 
Programming 

Artificial Intelligence language, LISP 6/526-530 
BASIC 5/341 

BASIC-FORTH 6/427-428 
C and Tiny C 5/201 
C language 5/191 
CP/M 5/341 

changing SPI to CP/M 5/32 
errata 5/244 

pastimes and pleasures 5/37; 5/285; 5/330 


Programming (contd.) 

Pidgin, systems programming language 6/282-284 
Small-C programming 6/504-507 
time functions 6/330-331 
Zant’s modular programming 5/266 
Programs 
6800 5/439 

68000 cross assembler 7/429-438, 7/488-498 
68000/AIM interface 7/29-31 
8080/8086 cross assembler 7/156-164 
8086 trig 7/463-464 

8086 assembler [FORTH] 7/61-63, 7/72-85 
adventure development system, Adven-80 6/468-473 
assembler for the 6502 6/369-373 
BASIC-FORTH 6/427^428 
C command line processor 7/331-347 
COMAL-80 6/235-236 
compiler writing tool, META 4 6/321 
conversion routines [ASCBIN and BINASC] 7/414 
CP/M 5/406 

CP/ M + CDOS compatability 5/29 
cross assembler for 8080/Z80 6/230-234 
cross-reference generator [C] 7/266-270 
custom character sets [IBM PC] 7/518-519 
debugging concatenated programs 6/64 
decompiler 6/403 

downloading modem [CP/ M] 7/454-461 
DUMP utility readability enhancement 6/93 
file comparator 6/15 

file conversion, H-8 text editor to CP/M 6/239 

file system, Tiny 6/240-241 

file transfer utilities 7/355-360 

floppy disk test 6/140-145 

FORTH floating-point 7/381-385 

FORTH screen editor 7/395-397 

FORTH style examples 7/387 

H-8 front panel 7/122-123, 7/113 

Hash ’n Pascal 7/508-510 

keyboard input definition 6/194-196 

LET processor [LLL BASIC] 7/248-255 

love program 5 / 345 

mailing list label printer 6/149 

memory test [Z80] 6/69 

modem program [FORTH] 7/202-207 

multi-tasking kernel [68000] 7/5 

NEW USER [CP/M] 7/217-222 

Newton’s square root 7/ 502 

North Star DOSMOVER 6/124 

North Star-to-Epson connection 7/208-210 

pattern classification 7/124-126 

performance evaluation 7/348-354 

Pidgin 7/441 449.7/477-485 

Pidgin, systems programming language 6/282-284 

portable screen-oriented editor 7/32-51 

print utility [CP/M] 7/256-265 

QUITIF [CP/M] 7/373-376 

relocating loader [FORTH] 7/390-392 

Rubik’s Cube simulator 6/291-292 

screen-oriented editor 6/383 

Small-C compiler 7 / 520—546 

Small-C for the 9900 7/316-322 

Small-C Diskdoc 7/165-171 

Small-C programming 6/504-507 

Small Shell 7/20-23, 7/25-28 

speed reading using a computer 6/95 

spelling checker 7/177-183 

system clock 7 / 211 -216 

terminal programs for North Star 6/487 

timer routine [Horizon] 7/88-90 

user interface to Apple II 5/267 


566 



Programs (contd.) 
video graphics [IBM PC] 7/292-301 
wildcards [UNIX] 7/473-475 
Z8000 FORTH 7/401-412 
Protocol 5/234 
Pugh, T. 5/234 
Purdin, T. 5/151 


Quick-key 5/418 
Quinn, C. 5/39 


Radio Shack (see TRS-80) 

Radio Shack pocket computer 6/88 

Raeside, D. 5/121 

Raeside, D.E. 7/114 

Ragsdale, W. 6/369 

RAMcard with RAMdrive 7/462 

Ream, E.K. 7/13 

Reentrant formatter [TI9900] 5/108 
Register/storage [8080] 5/173 
Rennard, R. 5/444 
Ritchie, D. 5/191 
Rohde, A. 6/150 

ROM byte-finder [Apple II] 5/243 
Roth, R. 6/504 
Routines 
alternate 5/445 

arrays, cassette I/O routine 6/150-152 
binary to decimal conversion routine 6/271 
byte manipulation and pointers 6/103 
calendar routines 6/313 
database design 6/398-401 
DUMP utility readability enhancement 6/93 
MITS DOS disk to disk copy 5/209 
polynomial evaluation 6/146-147 
Small-C cross-compiler implementation 6/66-67 
text editor input routine 6/42-43 
text editor WORD-MASTER with the Compal-80 6/102 
Rowland, D. 5/269 

Rubik’s Cube simulator [BASIC] 6/291-292 
Rubin, S. 5/349; 6/100 
Rules 5/309 

Runic: An interactive, extensible compiler [FORTH] 
7/106-108, 7/184-186 
Runtime library [Small-C] 5/312 


S.D. board 5/257 
SAM 76 5/83 

Santa Barbara (see Tiny BASIC for the 6809) 

Saunders, W. 5/395 
Scargill, P. 6/468 
Schorre, D. 5/142 
Scientific computer 5/400 
Scott, J. 5/443; 6/238 
Screen editors 6/178 
FORTH screen editor 7/393-397 
MINCE 6/178 
addendum 6/227 

extended with Amethyst 6/181-182 
portable screen-oriented editor 7/13-19, 7/27-28 
Screen-oriented editor 6/102 
[FORTH] 6/383 

SCRIBE IX, word processing package [CP/M] 6/220-222 

Serial port 5/425 

Shoemaker, D.C. 7/109, 7/187 

Shoer, L. 7/208 

Silverston, S. 5/172 


Simons, K. 5/400 
Sinclair BASIC 6/61 
Sinclair ZX81 

building 7/486-487 
direct video input 7/223 
Sippy, L. 5/425 
Sjowail, T. 5/367 

Skjellum. A. 5/11; 5/289; 6/16, 6/102, 6/423; 7/331, 7/472 
SLIC 

mailing list label printer 6/149 
Small-C 
8080 5/176 
for 9900 7/316-322 
programming 6/504-507 
repair maintenance utility 7/165-171 
runtime library 5/324 
Small-C compiler 5/312; 7/520-546 
bug fixes and enhancements 6/228 
error run-time library routines [compiler] 6/53 
modification 6/465 

Small-C cross-compiler implementation [Fortran] 6/66-67 
bug correction 6/67 
bugs 6/228, 6/277 
update 6/104 

Small Shell 7/20-23, 7/25-28 
Small systems and monitors 5/324 
Small VM development, portable software [BASIC/North 
Star] 6/492-495 
Smart, B. 6/270 
Smith. B. 5 267 
Smith. D. 5/443 
Smith. G. 6/42, 6/64 
Smith, W. 5/240 
Softky, S. 6/100 
Software 
CP M 5/4; 5,445 
software market 5/309 
Software reviews 

CLOAD Magazine, Inc. 6/122 

COMMWHIZ 7/226 

DB.BAS package file maintenance 6/80 

editor, assembler, disassembler in XL package 6/36-40 

EDITOR/ASSEMBLER PLUS 6/123 

JRT Pascal 7/503 

monitor MON 3 6/122 

PIE 7/187 

screen editor, MINCE 6/178 

SCRIBE IX, word processing package 6/220-222 

the WORD 7/143 

the Working FORTH Learning System 7/417 
utility package. Disk Keyplus 6/122 
Volkswriter 7/313 
Write-On 7/314 

ZDM debugger for CP/M users 6/80-81 
ZEN 7/95 
Solntseff, N. 7/386 
Sonderstrup. S. 6/235 
Source-text area, extended 5/371 
Speech synthesizer interface [TRS-80] 6/127-129 
Speed reading using a computer [BASIC/PET] 6/95 
using ED and PIP in CP/ M 6/186 
Spelling checker [CP/M] 7/175-183 
SPI formatted programs 5/32 
Sprenkle, J. 5/279 

SR-52 programmable calculator 5/392 

Statement generator [North Star] 5/418 

Stewart, H. 5/445 

STOIC [North Star disk] 5/55 

Stowe, T. 5/287 

String arrays [North Star] 5/40 


567 



String routines [FORTH] 6/51 

Submit file comments [CP/M conversions] 6/200, 6/415 
Subroutines [Z80 assembler] 5/159 
SYM-I 5/324 

Symbol table alpha listing [H-8] 5/104 
Syntax-oriented compiler writing language 5/142 
System Clock 7/211-216 


Table driven assember 5/59; 5/171 
Taylor, J.L. 7/266 

Tektronix 4010 simulator [Z80] 6/423-425 
Terminal parameters [Pascal] 5/75 
Terminal programs for North Star [North Star] 6/487 
Testing binary integer for single 1-bit 6/414 
Text editor 

input routine [BASIC/North Star] 6/42-43 
WORD-MASTER with the Compal-80 [CP/M] 6/102 
Text editors 7/91-92 
Thagard, N.E. 7/248 

“Thinking” program, ERGO [artificial intelligence] 6/100 
documentation 6/319 
Thompson, B. 5/223 
TI 9900 5/45; 5/108 
T1 PMX5/46; 5/108 
Time functions (C language) 6/330-331 
Time-delay circuit design [BASIC] 6/197 
small error 6/420 

Time-keeping in microcomputers [BASIC/North Star] 
6/287-289 
Timin, M. 6/411 

Tincmp, compiler for Pidgin 6/284-286 
Ting, C.H. 6/427; 7/64 
Tiny BASIC (see BASIC) 
for the 6809, Santa Barbara [6809] 6/202-203 
Tiny interpreter 5/15 
Tiny monitor [Elf] 5/268 
Top-down 5/352; 5/443 
Translator [8080 to Z80] 5/216 
TRS-80 5/441 

EDITOR/ASSEMBLER PLUS 6/123 
Monitor MON 3 6/122 
synthesizer interface 6/127-129 
utility package, Disk Keyplus 6/122 
Turing machine simulation [programs] 6/45 
Typography, mathematical 5/88 


UCSD Pascal (see Pascal) 

Underline modification 6/125 
Universal language 6/45 
UNIX, Expanded wildcards 7/472-475 
Utilities 

command under CP/M 5/11 

file transfer 7/355-360 

multiple file transfer 5/375 

NEW USER [CP/M] 7/217-22 

print [CP/M] 7/256-265 

Small-C repair/ maintenance 7/165-171 


Utility package. Disk Keyplus [TRS-80] 6/122 


Van Buer, D. 5/59; 5/171; 5/268 
Van Iderstine, T. 6/62 
Vector generation algorithm 7/550 
VDM-1 6/124 
Video display RAM 5/439 
Video drivers [Z80] 6/16-17 
time-dependent coding 6/93 
Vocabulary trainer 5/423 


Wakerley, J. 5/56 

Walters, N. 5/46; 5/108 

Warner, J. 5/29 

Wasserman, P, 5/172 

Wegner, K.F. 7/114 

Wetherell, C, 5/37; 5/77; 5/285; 5/330 

Wexler, S. 5/309; 6/122 

WH 14 printer 5/425 

Whitlock, H. 6/96 

Wilcox, R. 5/82 

Wildcards [UNIX] 7/472^475 

Willoughby, S. 5/341 

Woodhull, A.S, 7/393 

Woods, P. 6/66, 6/104 

Word processing package (see SCRIBE IX) 


X-Ref tool [North Star] 5/339 


Yakush, S. 5/392 
Yates. D. 6/287 


Z80 (see also 8080) 
assembler 5/159 
circuit (H-8) 5/287 
file comparator 6/15 
floppy disk test 6/140-145 
indirect addressing 5/289; 5/394 
memory test 6/69 
power increase 5/172 
tektronix 4010 simulator 6/423 
translator system from 8080 5/216 
video drivers 6/16-17 

Z80 macro-assembly implementation 7/439- 449 
Z80 microprocessor, use and misuse 6/187-188 
Z8000 FORTH 7/398 -412 
Zant, R. 5/266 

ZDM debugger for CP/ M users [Z80] 6/80-81 
inline assembler [CP/ M] 6/186 
Zeiger, M. 5/32 
ZSID bug and patch 6/519 
ZX 65 5/272; 5/395 
ZX80, Sinclair [BASIC] 6/60-61 
reader response 6/137, 6/229 


568 






































































. 















The Dr. Dobbs Series 

I he People’s Computer Company 


“There’s more creativity, wild ideas, and raw enthusiasm here per page than you are 
likely to find anywhere else in the personal computing press.” Creative Computing 


Dr. Dobb’s Journal, Volume 1 

Chronicles the advent of the microcomputer era in 1976. Always pertinent for bit crunching 
and byte saving, home-brew computer projects, and the technical history of home 
computing. Topics include: Tiny BASIC, the first words on CP/M, Speech Synthesis, 
Floating Point Routines, 6502 Disassembler for the Apple, and much more. #5475, paper, 
368 pages. 

Dr. Dobb’s Journal, Volume 2 

The small computer emerges as a powerful tool for the modern age in these issues from 
1977. Topics include: Lawrence Livermore Lab’s BASIC, Dr. Starkweather’s PILOT, Using 
a Modem, String Handling Techniques, Ciphers, Turtle Graphics, micro utilities, and 
much more. #5484, paper, 480 pages. 

Dr. Dobb’s Journal, Volume 3 

Explores the foundations of the mass market computer industry in 1978. Topics include: 
Programming in BASIC, PILOT, and Pascal, RAM Memory Testers, Apple utility 
programs, S-100 Bus Standard, STRUBAL: A Structured BASIC Compiler, and much 
more. #5490, paper, 480 pages. 

Dr. Dobb’s Journal, Volume 4 

Heralds the widespread acceptance of the microcomputer in America. Innovative ideas and 
articles guide the reader through the age of discovery in 1979. Topics include: Selecting 
Business Software, Microcomputer Speech and Music, Information Networks, interfacing 
techniques, and much more. #5491, paper, 480 pages. 

Dr. Dobb’s Journal, Volume 5 

Focuses on the technological promise of the modern microcomputer and the creative 
challenge facing programmers in 1980. Topics include: The revolutionary impact of CP/M, 
C programming and the UNIX operating system, survey of computer networks, software 
portability, introduction to FORTH, compiler writing, and much more. #5492, paper, 

464 pages. 

Dr. Dobb’s Journal, Volume 6 

The microcomputer enters the mainstream-these issues assess the revolutionary impact of 
microcomputers on the individual and on our society in 1981. Topics include: Computer 
Conferencing, The Power of FORTH, 8- and 16-Bit Technology, Rubik’s Cube Simulator, 
An Adventure Game Development System, and much more. #5493, paper, 576 pages. 

Dr. Dobb’s Journal, Volume 7 

Examines the potential of powerful 16-bit micros including the birth of the IBM PC in 1982. 
Topics include: In-depth coverage of FORTH, 68000, 8088 programming, C software tools, 
utilities for CP/M including a spelling checker, using bulletin boards, and more. #5494, 
paper, 592 pages. 


00 

HAYDEN BOOK COMPANY 

a division of Hayden Publishing Company, Inc. 
Hasbrouck Heights, New Jersey 


ISBN 0-8104-5494-7 
















