so the pointer is the essential thing
you need to build a cpu and with that
you can actually build a cpu and get
your instructions for memory because you
can point to them you can get your data
because you can point to them but if
you've got something else you can you
can be really clever you can build
things that are quite cool and the other
thing is this idea of a subroutine
let's just think about what a program is
a program is a set of instructions that
are going to execute or a routine for
doing something so your routine is just
the instructions you're going to execute
to do something that might be to say
calculate fibonacci it might be to add
numbers together it might be to sort of
play the latest game and you could write
that as just one long sequence of
instructions perhaps with the odd loop
that would jump back and so on and you
could do that in assembly in c in java
and c sharp in objective c whatever
language you want to choose
certainly have a procedural object or
you sort and write your whole program
out in one go but if that's all you got
your prone becomes long
you might be able to jump between
different points which can help but you
often find you're writing the same bit
of code
time and time again so let's say you
want to just print a character out and
that might be done on some machines by
writing to a certain location in memory
use a pointer and write to it now
if you have to write that code lots and
lots of times
you're going to get pretty bored of
writing it it's going to be the same
thing so it's boring to write
chances are you're typing the same code
again you're going to get bored of
writing it so you're more likely to make
a mistake so you're more likely to
introduce bugs
and so
it doesn't work so the way we do a loop
in
assembler is we
say jump to this location and we jump
back to a different point and it'll
execute the same bits of code time and
again in a loop the pointer it says go
to this point we add an offset or remove
an offset and we jump back to that point
or we set it to an exact value doesn't
matter which depending on the machine
so we can create loops and we can also
jump to other bits of code now the idea
of the subroutine
is
when you
want to do something say like print a
character rather than writing it many
times you write it once and you put it
somewhere in memory and you know the
address of where it is or you have
something that points to it the address
and then whenever you want to print
something
rather than putting the code in again
you just put an instruction that says
jump
to that part of the code that prints
something out
and so you have your main routine which
is say
doing whatever it is you want to do and
then you have lots of these sub routines
or smaller routines that are going to do
parts of it that you just jump to when
you need to print a character or read a
character or access the floppy disk or
whatever it is you want to do
update your opengl game so you just jump
to these subroutines
oh and then you've got an interesting
problem how do you get back
from that subroutine because you could
you could say well okay i'll get to the
end of the instructions and i just say
okay i've got here how do i get back
well it's easier the first one so i'll
just jump back to the next instruction
but then you call it again and you end
up and you jump back up to the wrong
place so how do you get around that
issue that how do you know where to get
back to can i try and guess come on i
need to try and guess so in the
subroutine do you write in look at such
and such a register as to see where to
go back to
so that's one way but what do you need
to do first uh initialize that
register yeah so you say okay i'm going
to jump from the main routine
to the subroutine now you can't just use
a normal jump there because that doesn't
remember where you've got to go back to
so you have a special type of jump
which as well as jumping also memorizes
the address or a pointer to the next
instruction
now just as you said if you've got
something like an arm chip in something
like the archimedes or the raspberry pi
then that
will store that return address as it's
called in another register so it'll copy
it
where it's got to go to into another
register you execute that code
and then you just set the instruction
point or the program counter to have the
same value that's in that other register
and jump you're back and you carry on
executing there
so you build your cpu to allow that now
there's problems with that because if
you want to implement something like
recursion you have a function which
calls a subroutine and that subroutine
is going to call itself so if you do
that you lose the original bit of code
is that right well you lose the original
return address so so straight away we've
gone into a never-ending loop you've
gone into an ever-ending loop or so it
gets messy and the problem crashes and
things go wrong what most cpus do on
something like the army you implement
yourself because it's the way the arm
chip works and that's fine
is you store
that
return address
in memory via a pointer so rather than
having a register that contains the
return address you can have a register
and it's usually done on the stack using
the stack pointer that actually points
to somewhere in memory where you store
that return address and then when you
get another one you can move on to
another bit of memory and store that on
there and then you can wind back up the
stack
to get the return addresses if i
remember professor brailsford's video
well enough the last thing on the stack
is the first kind of place you go to
then that would kind of come off the
stack pop off this yeah i'm remembering
it yeah that's right um and pop off the
stack and then give you access to where
the next pointer is so if you think
about it you sort of think you can
imagine just put piling pieces of paper
on top of each other post it notes you
take the top posting note off and then
it tells you to go back and the next
time it takes you and so until you end
up with the one that gets you back into
the main routine so some cpus like the
x86 family that started off with the
8088 will do that automatically so that
when you make that special jump to the
subroutine
they will store the return address on
the stack for you
others like the arm chip
require you to store it and register and
then you have to put it on the stack if
you want to do it's just the
architecture these horses for courses it
doesn't make any real difference so
that's depending on how many
instructions the instructions yeah it's
just it's just the design
you think well actually
you're making your chips more complex by
automating that whereas actually if we
just
let the program we're doing it because
sometimes you don't need to do that so
you can make your program faster with
those leaf subroutines as they tend to
be known and so once you've got that
technology either part via software or
part via
the hardware and you can move it between
the two as much as you like
then you can use the subroutine to make
the code easier to write and from that
you can build functions in c procedures
methods and objects all implement in an
object-oriented language are all
implemented in that way they're using
that idea of the subroutine so when you
call them
they store the return address
and execute the code and then they have
some mechanism to get back from that
return address to what get back from the
end of subroutine via the return address
to where
you carry on now the clever thing is how
they originally came up with that idea
because the original cpu something like
edsac back in the late 40s early 50s
didn't support subroutines in hardware
and yet a chap called david wheeler was
able to create what was called the
wheeler jump which he used to implement
the very first subroutines now this is
really clever
but absolutely nightmarish and i should
put up a disclaimer do not try this at
home
because it used what's called
self-modifying code so let's get rid of
that so let's use some sort of
pseudo-arm code and we've got some
instructions that are going off and then
we're going to jump to a subroutine
we'll call it sub and then we're going
to carry on here and then so we'd have
our subroutine somewhere off in memory
and it would have the instructions it
would need to execute and then at some
point you're going to get to a point
here where you're going to return that's
the way most things are structured
now we had jumps and things on edsack
but that's all we had so we could have a
jump here that would get back so we'd
have a branch here that would say branch
and let's just give it a label back but
we don't know where back is because we
don't know that until we actually call
it so if we know where the subroutine is
and because when we write the code we
know how many instructions there are
here we can work out where in memory
this branch back instruction is going to
be branch two back and so this is where
the clever bit happens what david
wheeler did was say okay before we make
this branch or jump to the subroutine
we're going to put in instructions here
which and we're using some really
clunky pseudo code modify
jump back
so you had code that modified itself as
it was running
and it would alter this instruction
to remove back there and put in let's
just call it
return
and modify that to be return
and then a bit later on we call it again
so we'd modify the jump here
what if i jump back
call the sub routine we branch to it and
then
we would carry on here and we'd call
this let's call it fred and so we
replace return here with the address of
fred so that's now pointing to fred so
that when the subroutine is called it
executes and then jumps back to the
right place so as long as you've got the
ability to jump to an address in your
cpu and the ability to modify memory
by
monkeying around using a pointer
you could implement a subroutine even
though the cpu didn't have any support
for it now
this is what's called self modifying
code because as the program is running
it is changing itself as it is running
if you get this wrong the problem
crashes and bad things happen so that's
not something you want to do for the fan
of heart which is why this technology is
then moved into the cpu and implemented
in hardware for the same reason it's
something we're going to do a lot of so
let it be implemented once and we reuse
it in the same way that we gonna do lots
of things in our program so we make a
subroutine to do that and rather this is
so common we put it into the hardware
because we're going to use it or at
least some sort of hardware support
for it and of course the way modern cpus
have got with caches and things in there
self modifying code doesn't work
properly anyway because they're not
true von neumann machines
based on my pre-trained network i'm
going to produce 5000 characters of
random text and let's see what it looks
like
so we'll just boot up for a minute and
then it will run
it's pretty quick once it gets going
there we go
so you can see we've got comments we've
got replies at first glance it looks
plausible when you actually read into
the comments they're very bizarre so
this guy by blockythwap now that might
be a real person