Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How an assembly language works?

I am learning assembly and I have this assembly code and having much trouble understanding it can someone clarify it?

Dump of assembler code for function main:
0x080483ed <+0>:    push   ebp
0x080483ee <+1>:    mov    ebp,esp
0x080483f0 <+3>:    sub    esp,0x10
0x080483f3 <+6>:    mov    DWORD PTR [ebp-0x8],0x0
0x080483fa <+13>:   mov    eax,DWORD PTR [ebp-0x8]
0x080483fd <+16>:   add    eax,0x1
0x08048400 <+19>:   mov    DWORD PTR [ebp-0x4],eax
0x08048403 <+22>:   leave  
0x08048404 <+23>:   ret

Until now, my understood knowledge is the following:

Push something (don't know what) in ebp register. then move content of esp register into ebp (I think the data of ebp should be overwritten), then subtract 10 from the esp and store it in the esp (The function will take 10 byte, This reg is never used again, so no point of doing this operation). Now assign value 0 to the address pointed by 8 bytes less than ebp.

Now store that address into register eax. Now add 1 to the value pointed by eax (the previous value is lost). Now store the eax value on [ebp-0x4], then leave to the return address of main.

Here is my C code for the above program:

int main(){

int x=0;
int y = x+1;
}

Now, can someone figure out if I am wrong at anything,and I also don't understand the mov at <+13> it adds 1 to the addrs ebp-0x8, but that is the address of int x so, x no longer contain 0. Where am I wrong?

like image 454
Tamim Addari Avatar asked Nov 28 '22 01:11

Tamim Addari


2 Answers

first of all, push ebp and then mov ebp, esp are two instructions that are common at the beggining of a procedure. ESP register is an indicator for the top of the stack - so it changes constantly as the stack grows or shrinks. EBP is a helping register here. First we push content of ebp on stack. then we copy ESP (current stack top adress) to ebp - that is why when we refer to other items on the stack, we use constant value of ebp (and not changing one of esp).

 sub esp, 0x10 ; means we reserve 16 bytes on the stack (0x10 is 16 in hex) 

now for the real fun:

 mov    DWORD PTR [ebp-0x8],0x0 ; remember ebp was showing on the stack
                                ; top BEFORE reserving 16 bytes.
                                ; DWORD PTR means Double-word property which is 32 bits.
                                ; so the whole instruction means
                                ; "move 0 to the 32 bits of the stack in a place which 
                                ; starts with the adress ebp-8.
                                ; this is our`int x = 0`

 mov    eax,DWORD PTR [ebp-0x8] ; send x to EAX register.
 add    eax,0x1`                ; add 1 to the eax register
 mov    DWORD PTR [ebp-0x4],eax ; send the result (which is in eax) to the stack adress
                                ; [ebp-4]
 leave                          ; Cleanup stack (reverse the "mov ebp, esp" from above).
 ret                            ; let's say this instruction returns to the program, (it's slightly more
                                ; complicated than that)

Hope this helps! :)

like image 172
Simon Avatar answered Dec 05 '22 06:12

Simon


0x080483ed <+0>:    push   ebp
0x080483ee <+1>:    mov    ebp,esp

Setting up the stack frame. Save the old base pointer and set the top of the stack as the new base pointer. This allows local variables and arguments within this function to be referenced relative to ebp (base pointer). The advantage of this is that its value is stable unlike esp which is affected by pushes and pops.

0x080483f0 <+3>:    sub    esp,0x10

On the x86 platform the stack 'grows' downwards. Generally speaking this means esp has a lower value (address in memory) than ebp. When ebp == esp the stack has not reserved any memory for local variables. This does not mean it is 'empty' - a common usage of a stack is [ebp+0x8] for instance. In this case the code is looking for something on the stack which was previously pushed on prior to the call (this could be arguments in the stdcall convention).

In this case the stack is extended by 16 bytes. In this case more space is reserved than necessary for alignment purposes:

0x080483f3 <+6>:    mov    DWORD PTR [ebp-0x8],0x0

The 4 bytes at [ebp-0x8] are initialised to the value 0. This is your x local variable.

0x080483fa <+13>:   mov    eax,DWORD PTR [ebp-0x8]

The 4 bytes at [ebp-0x8] are moved to a register. Arithmetic opcodes can not operate with two memory operands. Data needs to be moved to a register first before the arithmetic is performed. eax now holds the value of your x variable.

0x080483fd <+16>:   add    eax,0x1

The value of eax is increased so it now holds the value x + 1.

0x08048400 <+19>:   mov    DWORD PTR [ebp-0x4],eax

Stores the calculated value back on the stack. Notice the local variable is now [ebp-0x4] - this is your y variable.

0x08048403 <+22>:   leave  

Destroys the stack frame. Essentially maps to pop ebp and restores the old stack base pointer.

0x08048404 <+23>:   ret 

Pops the top of the stack treating the value as a return address and sets the program pointer (eip) to this value. The return address typically holds the address of the instruction directly after the call instruction that brought execution into this function.

like image 38
Mike Kwan Avatar answered Dec 05 '22 06:12

Mike Kwan