This page is a supplement to homework 4.
make
.s
file) for each C-- file.
.o
) files.
file).
.o
you just produced.
For the supplied test programs, you simply link them alone,
because they supply the __start
symbol where execution
actually begins.
For programs that expect execution to start at main
,
you must link with some "prologue".
The prologue variants are described next.
In a nutshell, the prologue is where execution actually begins. In
Cebollita, all the prologue does is call your program using a jal
instruction. How does it know the name of your program, which it needs
to include in the jal
instruction? By definition (of C--,
and C, and C++, and Java) your program starts executing at main
-
you must supply a function named main
to have a linkable
C-- (or C/C++) program.
The prologue simply does a jal main
,
and when you link the prologue with your program the right thing happens.
When your main finishes, it does a standard procedure return. That brings execution back to the prologue. At that point it issues whatever commands are required to terminate the "process" -- the running instance of the program.
In Cebollita, we have the prologue so that we don't have to rely on every
programmer putting the correct instruction sequence at the end of their
main routine to terminate the process.
The linker expects there to be a prologue, so it
sets the entry point of the .exe
file at
a speial symbol, i.e.,
not main
.
In particular, the linker expects to find that one
of the .o
files supplied to it contains the definition of the
symbol __start
.
So, if you don't include a prologue when you link, the linker will report
an error.
It turns out there are multiple versions of the prologue. There have to be, because there are multiple ways to terminate the process. The "real way" is to invoke the operating system, asking it to terminate. The problem is that there isn't always an operating system around to ask. In particular, in this assignment there is no operating system. You build a processor, you load a bare executable into memory, you set the PC to 0, and you tell your machine to start exectuing. No operating system anywhere in sight.
On the other hand, the Cebollita simulator itself provides an operating system (sort of), and in the next assignment you'll expand your processor implementation, adding what is required to run an operating system. That next machine will then run a little OS we wrote.
So, the upshot is that there are three different prologues, for three different situations.
.text .global main main: add $t3, $t2, $t1 haltYou won't have
jal
implemented,
so you won't be able to use a real prologue to link with this.
However, __start
is not defined, causing the linker to complain.
One way to solve this problem is to link with
cebollita\apps\prologue-standalone.s
:
# The null prologue, which leaves the user-written code at PC=0 # but satisifies the linker by having a __start: symbol .text .global __start __start:That satisfies the linker, but doesn't create any instructions at all.
Alternatively (and equivalently, in terms of the .exe
that is produced), you can just create the symbol __start
in your .s
file and not link with any prologue:
.text .global __start __start: add $t3, $t2, $t1 halt
main
function, because that's where execution starts. And, suppose you're
pretty sure you have jal
and all the other instructions working.
You can link your C-- program with prologue-noos.s
(supplied in the files section at the end of the homework 4 writeup):
# The Cebollita ISA simulator's loader has set things up so that on entry: # $gp = size of text segment # $sp = text size + data size + heap size + stack size - 4 # $pc = entry point (presumably __start here!) .text .global __start __start: jal main haltNote that it uses the Halt instruction to stop, so doesn't need an OS.
# The Cebollita ISA simulator's loader has set things up so that on entry: # $gp = size of text segment # $sp = text size + data size + heap size + stack size - 4 # $pc = entry point (presumably __start here!) .text .global __start __start: jal main ori $v0, $0, 10 # exit syscall
make
make for-standalone
and make for-os
. Those commands caused some more commands
to be executed that "remembered" which prologue to use in
the future. Then when you did something like make fact
,
that remembered information (which was stored in a file) was looked up,
and the correct prologue used in the link step.
That's all that was going on.
make
for the standalone case.
(You could also modify make
to know about
prologue-noos.s
,
which it doesn't now, but that would require a relatively sophisticated
understanding of make
.)
You can also (or instead) just issue the commands required to build
individually. For example,
$ cebasm myTestProg.s $ ceblink --output myTestProg.exe prologue-standalone.o myTestProg.oor when you're nearly done
$ cebcc myTestProg.c $ cebasm myTestProg.s $ ceblink --output myTestProg.exe prologue-noos.o myTestProg.o