Hello, this is Dr. Miller, and this
is Episode six point four of
assembly today
we're going to talk about creating a
function and then running a debugger
on that function.
So creating functions.
So to define a function, we
basically need two things.
The first thing is a label and that
is the name of the function
and then a return at the end.
And then in order to execute
the function, we use
the call instruction.
So Call says that we are going to
start executing a function.
What it's going to do is it's going
to push the return address of the
next instruction onto the top of the
stack and then it's going to start
executing that function.
So to do that, it jumps to the
address of the function.
And then EIP is set to that function
address and that's how it starts.
Executing yippy always points
to our current instruction.
And then when the function is all
done, we'll issue the return
instruction.
And so that will pop off the address
that's on the top of the stack and
set EIP to it and then continue.
So you can see this will save that
next instruction that we want to
execute and then this will restore
it when we are all done.
And today, we're going to do a
little bit of debugging just so that
we can see exactly how
the system works.
So exactly how the stack is related
to the function and the current
instruction, it's going to be
executed.
So I think that the GEF or
Jeff type of framework
for Gbps is really nice.
And so if you Google G.F.,
you will find it.
Here is a link to the GitHub page
and then on their page they
have how you can execute a script to
just install it by default.
And so this is the command
that I ran inside of my terminal
in order to get it installed.
And so once you do that, then you
can continue.
So today we're going to create a
simple function.
And so the function is called clear
X.
All it does is move
zero into X and then return.
So you see that we have a label here
that has a name and then a colon
and then we have this is the body
of our function moves X
and then we're going to do a return.
And then instead of our main, we're
going to call this function.
And then when we're all done, we'll
go ahead and we can print up
registers. And I have a couple
different examples that will go
through.
So let's get that started.
All right,
so go ahead and edit our file
and what we're going to do here is
we're going to put a few commands in
in order to help us visualize
the stack.
So I'm going to copy a couple of
things and push them onto the stack.
So I move feed beef into
X and then I'll go ahead and push
that on top of the stack and then
move.
Beef, beef,
push that onto the top of the stack
and then I'm going to end up calling
my function, so.
That's the name of my function
now, if we notice inside of my
program, I actually have already
a function ASRM underscore
main, that's the name of our
function. And at the end it has a
return.
And we'll talk about enter and leave
later on.
But that's a function.
All right. So generally, what
you want to do is you want to have a
function start and then end
and then you define
additional functions.
So I'm going to come down here and
define my function.
So I have a label which is
a string followed by a colon,
and then do what I want to do, move
the X zero
and I'll do a return.
And then if we recall from previous
lectures, right, I pushed two things
on to the top of the stack, and so I
need to clear off the stack here.
So that should I
have four for each one of these,
and so four times two is eight, so
I have to add eight TSB.
All right, so now we should be
ready.
And when we run it, it's not going
to do anything,
but that's OK.
We're going to run it in the debuggers.
So we're going to see exactly how
this works.
So the debugger is called the Ganu
debugger or GDB.
So we'll go ahead and execute that
key DB and then
we give it the name of the program
that we want to debug.
And so this example is six
point four
be.
So if you've run
the gaff script that I put in the
previous one, you'll see G.F.
here and an arrow pointer
and so here we can run a couple of
different commands.
So probably the simplest one is to
set a breakpoint.
So B is to set a breakpoint.
And the function that I want to set
a breakpoint is as an underscore
main, and that is our main function.
We can see it has a label.
We could also put one it in the
clear X.
That's also a function.
So now that we've set breakpoints,
we can start running our program
and this is where we're GEF really
works well. So if I type are in
order to run.
Now we're going to see in here and
the reason I made my terminal so
small is that we can get all of this
stuff on the screen.
So if we see up here, we can
see that we have registers.
So this is showing us what all of
the registers that we have inside of
our program. So we've got X, X,
EXP, SBP,
Ayda IP and then our flags
so we can see all of our registers
as they currently are.
We can see the stack.
So on the stack you will see
the very top is what's pointed to
by ESP.
And so as we push things, you'll see
stuff move down the stack
and then we can see the code.
So this is where we're exactly
we're running.
And so we're at ASRM Main
and it stopped at ASRM main plus
four. So this is the next
instruction that's going to get
executed when we execute this
function.
And we've got a couple of different
commands, so we've got step
instruction in next and step
construction, so ESSI
or step instruction means do the
next instruction and
if there's a function call, go into
that function call.
Whereas next instruction will.
Will.
Step into that and so
we'll see the difference here in a
little bit.
So I'm just going to use step
instruction to see
each one of these, and if I hit
enter, it'll do the previous come
in, so I'm just going to step each
instruction.
So here we can see we got moving
and then feed beef.
And so we should see a change
here when we execute that command.
So now we can see that X is feed
beef.
And so now it's going to do a push.
So you should see that X should go
on top of the stack.
Right, so now we can see E.S.P
is pointing to feed beef,
so now that feed beef is on top
of the stack.
Now here we're going to copy beef
beef, anti-tax.
So now he has both beef
and now this should get copied to
the top of the stack and then feed
beef will move down.
OK, so now if I
did at this point, right, we've put
on those two items on top of our
stack and then we're ready to call
our function and we can see
that the GEF is trying
to show us what our function look
like. Normally a function as more
than just two instructions.
This one only has two.
So we're only going to see these.
And then this stuff here is going to
be garbage. That is not really
instructions because the return is
going to exit from that.
And so here if I did
next instruction, it would
step over that.
Call me when you get to see what
happens, but we're going to use
step instruction or go to the
next one. And if it's a call, go
into that call function.
So we are going to see the return
address. So the address of
the next instruction.
So after Assim underscore
main plus 17, the next instruction
is going to get executed and I can
scroll up and we should be
able to see the next instruction.
Is this one right here?
It is the ad ESP
eight and its value
is eighty, forty
eight.
Forty six.
So that is the value that's going to
get pushed on set because that's the
next instruction that we want to
execute from what we're at right
now.
So I'll go ahead and do step
instruction. We should see
that we will enter this function and
then that return address is going to
get pushed on top of the stack.
So now if we look, we can see that
that number that I just said earlier
is pushed on top of the stack and
there's an extra zero because it's
got to fill all eight bits.
And so now we're in our function.
Our function is going to move zero
into X and then it's going to
return. And so it's going to pop
this off of the stack and then we
will be running that other
instruction. So right now, we're in
the function as it shows
here. Clear X.
So I'll go ahead and step.
So now.
Yak's has got to
zero because that's what our
function is going to do at this
point, we're ready to do a return.
So we're going to go back to our
azem main.
We're going to go back to this
address right here.
So this will get popped off of the
stack.
So now we can see X is zero, which
is where you are, we wanted our
function to do, and again,
the top of the stack is beef, beef
and then feed beef right in reverse
order that we push them on.
And so now if we step,
we can see that those disappeared
because we added our ATP
and now ESP points to where it
originally pointed when our
functioning started.
And so we ended up with the result
of X being zero, which is what
we wanted to do inside of our
function.
We had moved other values in there.
And so now we're all done.
So far, all done. We can hit C to
continue and it'll continue running
the program until it exits
and says the program exited.
Normally
you quit.
All right.
So today, we talked about creating a
function and then using our debugger
on the function so we could kind of
understand what happens when you
call a function, what happens to the
stack, what gets added to the stack
when you do a call instruction and
what happens when you do a return
instruction?
So looking forward, we're going to
look at more complicated functions.
All right, so we're going to add
some parameters
to it. We're going to also talk
about how do we save registers
so that way they don't get
clobbered.
And then we'll talk about recursive
functions.
If you have questions, you can email
me at millirems, at Juniata Aidoo,
and you can find me on Twitter at
Milhouse 30.