Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ENTER and LEAVE in Assembly?

I was reading The Art of Assembly Language (Randall Hyde, link to Amazon) and I tried out a console application in that book. It was a program that created a new console for itself using Win32 API functions. The program contains a procedure called LENSTR, which stores the length of string in the EBP register. The code for this function is as follows:

LENSTR PROC ENTER 0, 0 PUSH  EAX ;---------------------- CLD MOV   EDI, DWORD PTR [EBP+08H] MOV   EBX, EDI MOV   ECX, 100 ; Limit the string length XOR   AL, AL REPNE SCASB ; Find the 0 character SUB   EDI, EBX ; String length including 0 MOV   EBX, EDI  DEC   EBX ;---------------------- POP   EAX LEAVE RET   4 LENSTR ENDP 

Could you explain the usage of the enter and leave commands here?

like image 692
devjeetroy Avatar asked May 02 '11 15:05

devjeetroy


People also ask

What is enter in assembly?

The ENTER instruction (when used) is typically the first instruction in a procedure and is used to set up a new stack frame for a procedure. The LEAVE instruction is then used at the end of the procedure (just before the RET instruction) to release the stack frame.

What is leave in assembly?

Description. The leave instruction reverses the actions of an enter instruction. leave copies the frame pointer to the stack point and releases the stack space formerly used by a procedure for its local variables. leave pops the old frame pointer into (E)BP, thus restoring the caller's frame.

What does RETQ do in assembly?

The retq instruction pops the return address from the stack into the destination %rip , thus resuming at the saved return address.


1 Answers

Enter creates a stack frame, and leave destroys a stack frame. With the 0,0 parameters on the enter, they're basically equivalent to:

; enter push ebp mov ebp, esp  ; leave mov esp, ebp pop ebp 

Although it's not used in the code you posted, enter does support doing a bit more than the simple push/mov combination shown above. The first parameter to enter specifies an amount of space to allocate for local variables. For example, enter 5, 0 is roughly equivalent to:

push ebp mov ebp, esp sub esp, 5 

Enter also supports languages like Pascal that can use nested functions/procedures:

procedure X;     procedure Y;     begin         { ... }     end begin    { ... } end 

In a case like this, Y has access not only to its own local variables, but also to all variables local to X. These can be nested to arbitrary depth, so you could have a Z inside of Y that had access to its own local variables, and the variables of Y and the variables of X. The second parameter to enter specifies the nesting depth, so X would use enter Sx, 0, Y would use enter Sy, 1 and Z would use enter Sz, 2 (where Sx, Sy and Sz signify the size of variables local to X, Y and Z respectively).

This would create a chain of stack frames to give Z access to variables local to Y and X, and so on. This becomes fairly non-trivial if the functions are recursive, so an invocation of Z can't just walk up the stack to the two most recent stack frames--it needs to skip across stack frames from previous invocations of itself, and go directly back to stack frames for the lexical parent function/procedure, which is different from its caller in the case of recursion.

This complexity is also why C and C++ prohibit nested functions. Given the presence of enter/leave, they're fairly easy to support on Intel processors, but can be considerably more difficult on many other processors that lack such direct support.

This also at least helps explain one other...feature of enter--for the trivial case being used here (i.e., enter 0, 0) it's quite a bit slower than the equivalent using push/mov.

like image 63
Jerry Coffin Avatar answered Sep 28 '22 02:09

Jerry Coffin