15.4. The Output Unit

Of course, every decent program should have output, and ours is no exception. Our output routines included the Emit functions. The code for the corresponding output unit is shown next:

unit Output;

interface
procedure Emit(s: string);      { Emit an instruction }
procedure EmitLn(s: string);    { Emit an instruction line }

implementation
const TAB = ^I;

{ Emit an Instruction }
procedure Emit(s: string);
begin
        Write(TAB, s);
end;


{ Emit an Instruction, Followed By a Newline }
procedure EmitLn(s: string);
begin
        Emit(s);
        WriteLn;
end;

end.

Note

Notice that this unit has no initialization clause, so it needs no begin-block.

Test this unit with the following main program:

program Test;
uses WinCRT, Input, Output, Scanner, Parser;
begin
        WriteLn('MAIN:");
        EmitLn('Hello, world!');
end.

Did you see anything that surprised you? You may have been surprised to see that you needed to type something, even though the main program requires no input. That's because of the initialization in unit Input, which still requires something to put into the lookahead character. Sorry, there's no way out of that box, or rather, we don't _WANT_ to get out. Except for simple test cases such as this, we will always want a valid lookahead character, so the right thing to do about this "problem" is … nothing.

Perhaps more surprisingly, notice that the TAB character had no effect; our line of "instructions" begins at column 1, same as the fake label. That's right: WinCRT doesn't support tabs. We have a problem.

There are a few ways we can deal with this problem. The one thing we can't do is to simply ignore it. Every assembler I've ever used reserves column 1 for labels, and will rebel to see instructions starting there. So, at the very least, we must space the instructions over one column to keep the assembler happy. . That's easy enough to do: Simply change, in procedure Emit, the line:

Write(TAB, s);

by:

Write(' ', s);

I must admit that I've wrestled with this problem before, and find myself changing my mind as often as a chameleon changes color. For the purposes we're going to be using, 99% of which will be examining the output code as it's displayed on a CRT, it would be nice to see neatly blocked out "object" code. The line:

SUB1:   MOVE    #4,D0

just plain looks neater than the different, but functionally identical code,

SUB1:
 MOVE #4,D0

In test versions of my code, I included a more sophisticated version of the procedure PostLabel, that avoids having labels on separate lines, but rather defers the printing of a label so it can end up on the same line as the associated instruction. As recently as an hour ago, my version of unit Output provided full support for tabs, using an internal column count variable and software to manage it. I had, if I do say so myself, some rather elegant code to support the tab mechanism, with a minimum of code bloat. It was awfully tempting to show you the "prettyprint" version, if for no other reason than to show off the elegance.

Nevertheless, the code of the “elegant” version was considerably more complex and larger. Since then, I've had second thoughts. In spite of our desire to see pretty output, the inescapable fact is that the two versions of the MAIN: code fragment shown above are functionally identical; the assembler, which is the ultimate destination of the code, couldn't care less which version it gets, except that the prettier version will contain more characters, therefore will use more disk space and take longer to assemble. but the prettier one not only takes more code to generate, but will create a larger output file, with many more space characters than the minimum needed. When you look at it that way, it's not very hard to decide which approach to use, is it?

What finally clinched the issue for me was a reminder to consider my own first commandment: KISS. Although I was pretty proud of all my elegant little tricks to implement tabbing, I had to remind myself that, to paraphrase Senator Barry Goldwater, elegance in the pursuit of complexity is no virtue. Another wise man once wrote, "Any idiot can design a Rolls-Royce. It takes a genius to design a VW." So the elegant, tab-friendly version of Output is history, and what you see is the simple, compact, VW version.