Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use pop and ret in MASM

I have recently started learning x86 Assembly using the MASM language.

I am using the Udemy course "x86 Assembly Language From Ground Up" by Isreal Gbati to learn.

The code below is from a lesson in the course, (It's not code that I came up with). This function is called by main in a C program. Here it is:

#include <stdio.h>
#include <stdlib.h>

extern int AdderASM(int a, int b, int c);

int main(void)
{
    int a = 17;
    int b = 11;
    int c = 14;
    int sum = AdderASM(a, b, c);

    printf("A = %d\n", a);
    printf("B = %d\n", b);
    printf("C = %d\n", c);

    printf("SUM FROM ASSEMBLY FUNCTION = %d\n", sum);

    return 0;
}

And here is the assembly:

.386
.model flat, c

.code

AdderASM    PROC

            PUSH EBP             
            MOV EBP, ESP        

            MOV EAX, [EBP+8]     
            MOV ECX, [EBP+12]   
            MOV EDX, [EBP+16]   

            ADD EAX, ECX        
            ADD EAX, EDX        

            POP EBP

            RET

AdderASM    ENDP
            END

I don't understand the following:

When we use pop, from what I understand is kind of like using free() in C. Correct me if I am wrong

So why are we only using pop on the EBP register? Shouldn't we pop the ECX and EDX registers as well?

I know that in a C function, pointers that are allocated memory by malloc() need to be freed before the end of the function. The registers used are all general purpose 32 bit registers, but EBP has a special use as a stack-frame pointer. Is this why it needs to be freed?

Also, I understand that ret is used at the end of the procedure, but how do we know that this function is returning a value at all?

To better explain my question, here is the same function written in C:

int AdderClang(int a, int b, int c)
{
    return a + b + c;
}

If I only put return; Instead of return a + b + c; I don't know exactly what would happen but it wouldn't be the intended result. We can also tell that this C function returns an int because it tells us that in the declaration.

All of this may be explained later in the course, and I'm sure the answers to my questions are simple. However, I am trying to go slowly to make sure I understand what I am doing. And yes, I know that Assembly is not C, so comparing the 2 languages like I have may not be the right approach, but I am learning Assembly to better understand the memory management stuff in C.

Thank you all for your time!

like image 682
RobotMan Avatar asked Jul 18 '19 08:07

RobotMan


1 Answers

When we use pop, from what I understand is kind of like using free() in C.

That's not really the case. push x copies x on the top of the stack, and moves the stack pointer so that the new top is below the pushed value (remember that on x86, the stack grows downwards in memory). pop x does the opposite: copies the top of the stack into x, and then moves the stack pointer so that the new top is above the popped value (i.e. the value is removed from the stack).

Effectively, the pseudo-C equivalent would be this:

void push(int x) {
  --esp;
  *esp = x;
}

void pop(int *x) {
  *x = *esp;
  ++esp;
}

Therefore, pop ebp does not mean "clean the ebp register", but it means "pop a value from the stack and store it in the ebp register." Since we previously pushed ebp, this is just reverting it as part of ending our function.


Also, I understand that ret is used at the end of the procedure, but how do we know that this function is returning a value at all?

You could say that in assembler world, every function is returning a value. The calling convention specifies how values are returned. On x86, the return value is stored in the eax register. So ret jumps to where the function was called from, and whatever is in eax at that time is what the caller gets as the return value. That's why the function computes the sum in eax, so that it's right where the caller will expect it.

Again, in pseudo-C, you could imagine a normal C return statement is implemented kind of like this:

void return(int x) {
  eax = x;
  ret;
}
like image 159
Angew is no longer proud of SO Avatar answered Oct 25 '22 20:10

Angew is no longer proud of SO