Breakout, the game the course builds in HiSoft C, running on the Tatung Einstein: coloured brick rows, the bat and the ball on a black court
← Back to Courses
module
6

What The Compiler Makes

Introduction

Every time the compiler finishes, it prints seven lines of numbers and you have been ignoring them. They are worth a minute, because they answer three questions you will otherwise keep asking - what the compiler actually did, why a one-line program is ten thousand bytes, and why the disc is filling up so fast.

The Map

Compile the smallest program there is:

main()
{
}
0:HC EMPTY.C
HiSoft-C Compiler V1.35 Copyright (C) 1985
Line File
MEMORY MAP    Start  End
Runtimes      0100  11FF
Code          1200  1205
Initialisers  1206  1209
Fixed Data    EC00  EC00
Smallest #data 0x1213
0:

Read it as a picture of memory, from 0100 upward, in hexadecimal.

  • Runtimes, 0100 to 11FF. Four thousand three hundred and fifty-two bytes that come before anything you wrote: the code that starts your program, talks to the disc operating system, prints characters, does multiplication and division, and cleans up at the end. It is the same in every program, and every program pays it.
  • Code, 1200 to 1205. Your program. Six bytes, for a main that does nothing: enough to begin and return.
  • Initialisers, 1206 to 1209. The starting values of any global variables you gave values to (S10). Four bytes of housekeeping here, and more when there are any.
  • Fixed Data, EC00 to EC00. Your global variables themselves, and the library's, filled downward from EC00, which is where the disc operating system begins. None in this program, so the area is empty.
  • Smallest #data, 0x1213. The lowest address the program's data could begin at - just past the code - and a hint for a compiler directive the course does not use.

Everything between Smallest #data and Fixed Data is free for the program to use while it runs: the stack, where the variables of running functions live, and any memory it asks for (S21). In the empty program that is very nearly the whole machine.

Now S4's hello world:

Code          1200  1320
Initialisers  1321  1324
Fixed Data    EBE3  EC00

Your one line of C has become 289 bytes of code, and Fixed Data has grown by 29. Most of that is not your line. Take both #include lines out of HELLO.C and compile it again and you get Code 1200 1224 - 36 bytes - and it still runs, because printf is built into the compiler (S8). The 250-odd bytes between are what STDIO.H and ?STDIO.LIB? bring in whether you use them or not: the library's own housekeeping.

That is cheap, and it is cheap because of the question marks. Write the last line as #include STDIO.LIB instead, with no ?, and put it at the top, and the map says Code 1200 250C: 4,876 bytes, the whole library compiled in, strlen and malloc and all the rest, whether you called them or not. With the ?, the compiler reads the library looking only for the functions your program has already used, and compiles those. Which is why the line goes last: anything called below it is not found.

So the numbers HC prints are worth a glance each time. A program that grows by a line grows by a few bytes; one that starts using a library function grows by that function.

On The Disc

0:DIR EMPTY.*
0: EMPTY   .C   : EMPTY   .COM
8k Size, 64k Free, 190k Total
0:DIR HELLO.*
0: HELLO   .C   : HELLO   .COM
8k Size, 64k Free, 190k Total

Every program is two files, and XtalDOS hands out disc space two kilobytes at a time, so even a three-line .C takes 2K. The .COM is the runtime plus the code, 6K for either of these - the 4,352 bytes of runtime are most of it, and the next 2K step is a long way off. (Hello world with the whole library compiled in, as above, is a 10K .COM and 12k Size.)

The course disc started with 72K free, which is nine programs or so; BREAKOUT.COM, the finished game, is on it already and is 10K of the rest. The .COM is the file to erase. You can make it again with one command; the .C is your work.

0:ERA HELLO.COM
0: HELLO   .COM?

XtalDOS asks; press Y, and it says Erased. DIR HELLO.* now shows 2k Size and the 6K back in the free column.

One more thing about DIR. When the disc has more files than fit on the screen, DIR stops when the screen is full and waits for a key - and takes whatever you press as that key, including the first letter of the next command you were about to type. Press SPACE, wait for 0:, then type.

Seeing What It Compiles

You can have the compiler show you every line as it reads it. Put #list+ on the command line before the file:

HC #list+ HELLO.C

The library's own source scrolls past first - STDIO.LIB opens with a comment giving its version, 1.3, and its date, 31 October 1985 - with a running line count that reaches 720, and then your eight lines, and then the map. The whole library goes past even though only the functions you used are compiled: ? decides what is compiled, not what is read. It is how you will read the library later (S23). Without #list+, only the names of the files go past, under Line File.

The Code

main()
{
}

Starting from

Typed as EMPTY.C and saved; HC EMPTY.C.

What you should see

The map above: Code 1200 1205 and Fixed Data EC00 EC00. Then EMPTY at the prompt runs it, and nothing at all happens, which is right.

Change One Thing

  • Add the two #include lines to EMPTY.C and compile it again, still with nothing in main. How big is Code now, and what does that tell you about what the two lines cost?
  • Change HELLO.C's last line to #include STDIO.LIB - no question marks. Compile it and look at Code and at DIR HELLO.*. Then put the question marks back.
  • Erase HELLO.COM, then type HELLO. What does XtalDOS say?
  • Type DIR after each step of the cycle and watch the Size and Free numbers change.

Exercises

6.1 Using DIR, work out how many kilobytes of the course disc the compiler, the editor and the four library files take between them.

6.2 From the two maps above, say how many bytes hello world's Code is bigger than the empty program's, in decimal.

Worked solutions are in Appendix II.

When It Goes Wrong

SymptomCause
DIR stopped and the next command you typed has vanishedThe pause took your first keystroke as "continue". Press SPACE at the pause and wait for the prompt.
The disc is fullErase .COM files you do not need; the .C files make them again.
#list+ scrolls too fast to readIt does. It is for counting, and for the reader's .LIB files, which S23 opens in the editor instead.

Summary

The map is the program in memory: 4,352 bytes of runtime, then your code, then initialisers, with the top at Fixed Data. ?STDIO.LIB? compiles in only the library functions used above it; without the ? the whole library comes in. Each program is two files and 8K of disc; erase the .COM when you need room, and press SPACE when DIR pauses. #list+ shows every line the compiler reads.

Next

S7, When It Goes Wrong - the compiler's error messages, the trick of pressing E, and the mistakes that produce no message at all.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.