Hello, my name is Stephan, and in this lecture we will learn about the instruction types and we will
also analyze this code.
And in computer programming we use instructions to tell the computer what to do.
Two important instructions mentioned here are L.
A a load effective address and m of which is mu.
So these instructions helps us work with data stored in memory.
So when we use the data, when we use the LDA instruction with a memory location like B num, we are
essentially loading the address of the memory location into a register called Rax and think of Rax as
a temporary storage container that the computer's processor can use.
So if we want to get the memory address of Rax, we can use l e a but if we want to, if we want the
actual data value stored at the memory address, we can use MOV when we use MOV.
If we put square braces here around binom, we get the data value itself and not the address.
And as you can see here, I added comments here.
When we use the square brackets with move and rax load the value stored at the memory address stored
in binom into Rax and.
So.
Uh, let's actually in this context here.
Racks Racks is 64 bit register.
So this means it can hold eight bytes of data.
So the data is stored in specific way called little endian.
So where the rightmost byte smallest part of the value is stored in the lowest memory address.
So in the case we are mainly interested in the smallest part of racks which is called a L.
So this holds just one byte of data and that's the part we want to use when we need to store or manipulate
small values.
So sometimes we want to start with a clean slate.
In register.
To do this, we use XOR instruction to set a register to zero and in this case it is used like here
XOR racks racks here.
And.
And after that we use the.
We also use the restore the value of RSP from Rbp, which is clean up the stack frame.
And to avoid.
And also when we move the data between memory and registers, we need to be careful about the size of
the data.
For example, move P over here.
Yeah, it's actually.
Yes.
Move.
Beaver.
Aw, yeah.
Move by Rex Moves.
Eight bytes from rags to the memory location.
Beaver.
So this might be more than we.
More than you intend.
And potentially overwriting other important data in memory.
And to avoid overwriting unintended data, you can use move p r a l instead.
So this moves just one byte value in a l to the memory location beaver leaving the rest of the data
untouched and Indian ness on the value representation here.
So when reading data from memory like for example text one the computer stores the data in little endian
notation.
So this means the smallest part of the value stored at the lowest memory address.
And you can use l e a to load memory addresses.
It makes your code more understandable since it's clear that you are dealing with addresses and it it
can also be faster for some calculations.
However, in this context, the l e a won't be used for calculations.
So now what we're going to do is.
And we will make this program.
So there's an output for this program.
We will use the debugger to step through each instructions.
CSM is helpful here, but we define some variables of different sizes, including an array of five double
words filled with zeros.
As you can see here.
So we also define some items in sections BS.
Now look in your debugger for a span, the stack pointer, it's a very high value.
And.
And here the stack pointer refers to an address in high memory.
So the stack in an area in memory used for temporarily storing data and the stack will grow as more
data is stored in it and it will grow in the downward direction from higher addresses to lower addresses.
So the stack pointer RSP here like this will decrease every time you put data on the stack.
So we will discuss the stack in a separate section of our course.
But remember already that the stack is placed somewhere in high memory.
Now we will debug this program here by clicking on debug and as you can see, it's started.
So if you can't see this right tab here, in order to see it here, you need to go to debug and click
on Show Register.
You can also use the control R to show this register tab on the right side of your screen now.
That sit here.
So here we use this l l a no l e a instruction, which means, as I explained here in this lecture load
effective address to load the memory address of Benham here.
To load the memory address of Bynum into Rex.
We can obtain the same result with MV without the square braces around Bynum.
So if we use square braces like this with mov instruction like we used here.
Right.
Uh, we are loading the value and not the address at Benham interacts.
But we are not loading.
Only Benham interacts.
But because the Rax is 64 bit or eight byte register and more bytes are loaded into Rax and our Benham
is the rightmost byte in Rax here, which is, as I explained here, this is little endian and here
we are only interested in the register as so you when you require rax to contain only only the value
of one, two, three, you will first have to clear rax like for example.
Here.
Like X or with x?
With x or.
Actually, we need to stop the program from debugging here and we will continue again.
So as I said, like if you want to react to contain only value one, two, three, you need to.
Uh, clear the racks with X or x or Rex.
Rex.
And that's it.
And you can also use instead of.
Like using the.
Instead of using the move racks being on like this, you can use.
L Aw, Yeah.
Instead of using this, actually, instead of writing this.
Yeah.
You instead of using this, you can use move.
Al.
And.
Be in braces.
And be careful about the sizes of data you are moving to and from memory.
Look, for instance, let's actually turn this.
Here.
Look, for instance, in move PVR racks.
With this instruction, we are moving the eight bytes in racks to the address bar.
If you only intended to write one, two, three two beaver, you can check with your debugger that you
overwrite another seven bytes in memory so you can choose it.
Choose type D for beaver in the CSM memory window and this can introduce nasty bugs in your program.
To avoid that, replace the instructions with move Beaver a l i as I explained here so.
Let's actually try this debug this here.
And as you can see here we are seeing registers, hacks and infos on our register table.
And now what we're going to do is we will use the sample command this as main and.
As you can see, we are also seeing the symbol here.
So now we will use the red elf at the command line.
Remember that we asked NSM to assemble using the Elf command like with this debugging settings here.
But let's actually let's go to terminal here.
And compile this with make file here.
And also we will generate the elf.
Here on the list as well.
So we will go to here We are in exabytes.
Actually, we had a.
Britain the.
Make file in another project so we can copy it.
Just.
Parsley.
So we will just change the kicking to exabyte exabytes.
Will be easy here.
Search and replace.
Kicking to.
Bytes and replace.
Now save it.
Don't save.
Now open the terminal here.
Make.
Make here.
And as you can see here, our program is created.
Now, if we run this, we will not get an output, but we will not get any error here because our programs
works like a butter.
And what we're going to do is we will use red elf.
Red elf file header and memory.
Now, not memory exabytes here.
Exabytes.
And that's it here.
And you will get some general information about your executable memory here.
The executable exabytes here.
And look at the entry point address here.
40 1020.
That is the memory location of the start of our program.
So between the program entry and the start of the code, as shown, um, as we will see on the GDB.
Port, 1190.
There is some overhead right here.
We had 40, 11, 90 and 40.
Ten, 20 and.
That's actually also use the this as a main.
Yeah.
This is here gdb.
LZ.
Yeah.
Uh, GDP.
Exabytes.
This as main.
And here for 1110.
Is it true for us?
Um, let actually.
Now here, our starting point of our program is 4011.
Ten, right?
And.
We're going to try this with Rudolph.
Our entry entry point is 40 1020, and there's some overhead in our program, and the heater provides
us with additional information about the operating system and the executable code as well here, operating
system.
And we have the size of the section headers and so on.
And Rudolph is convenient for exploring a binary executable as well, which you can use the symbols
parameter and we will grab the main from it.
So red elf symbols.
Exabytes and we will use pip here.
Grep.
Main.
And there we have it.
For the symbols mean.
So with grep we specify that we are looking for all lines with the word main in it.
So here you can see the main function starts at 40 1110.
Um.
And.
As we saw in GDB.
Port.
1110.
Right.
And in this example.
We need to look in the symbols table for every occurrence of the label start.
So we see start of section data and BSS.
Which is and the start of the program.
We can also see the start of the program as well with our red symbols, but with grep command in order
to see that, we will use the start and.
Yeah, that's it here.
As you can see here, we have start data, start here.
These are the start point.
Let's actually compare them with our.
1020.
We are still not on the entry point.
Yes.
Here and start our entry point actually corresponds here.
Now we need to also see what we have in memory with the instruction here.
Now in order to again.
We will use the tail plus ten and we will use sort minus key to are here.
And this instruction ignores some lines that are not interesting to us right now.
So we sort on the second column, the memory address in reverse order.
As you can see, some basic knowledge of Linux commands comes handy and the start of the program is
at some low address and the start of the main.
Is that?
Part of the main is.
Sexually see it here?
We actually.
So it improves here.
Yeah.
Start with the main is 4011.
Ten.
Right.
And look look for the start of the section data here in this for ten, 20, 40 in data starts with for
1020 with the address of all this variable and the start section of B s.
We also saw that here.
Note here.
Start 40, 40, 39, and with the address reserved for its variables as well.
So now let's summarize our findings here.
So we found we found at the beginning of this lecture that the stack is in high memory, which we saw
this with RSP here.
RSP here.
And with Rudolph, we found that the executable code is at the lower side of memory and on top of the
executable code we have section data.
And on top of that, on on top of the section data, we have section B, s.
S here.
But in this here, we as you know, we are using the reverse order here.
And.
And this high memory can grow and it grows in the downward direction toward Section BS and the available
free memory between the stack and the other section is called Heap H, a heap, and the memory in the
section that is assigned at runtime.
So you can easily check that.
And now.
Well, let's actually go here.
And in this case, as you can see here, we have QR risk reserved variables here.
And we.
Let's actually change this to.
Uh, 33 of oops.
Not this for.
Let's change 3 to 3000 and you will.
Actually, we need to stop this for.
Sorry for here.
So if we change 3 to 3000 and save the program, make again.
And, uh, sorry, we had some error here.
I think we messed with the code here.
Yes.
And why we have zero here, we will change 3 to 3000.
And we will make again.
And as you can see, it's compiled now.
Now we rebuild the program with make.
And now let's look the size again here LA.
And as you can see, it's.
Here.
And we will use the try this with Rudolph again the same command.
And as you can see here, the size here is significantly, significantly changed.