----------------------------
title : ENTER (Intel x86/64 assembly instruction)
cat_title : ENTER
ref_title : ENTER
published : 2020-09-01
path : /X86-64 명령어 레퍼런스/E
publish_date: 2020-09-01
----------------------------


#@ ENTER

**Make Stack Frame for Procedure Parameters**

```lec-info
아래 표를 해석하는 방법은 [x86-64 명령어 레퍼런스 읽는 법](/316) 글을 참조하시기 바랍니다.
```

|**Opcode**|**Instruction**|**Op/ **\newline{}**En**|**64-Bit **\newline{}**Mode**|**Compat/**\newline{}**Leg Mode**|**Description**|
|----------|---------------|------------------------|-----------------------------|---------------------------------|---------------|
|C8 iw 00|`ENTER` \tooltip{imm16}{2 바이트 짜리 명시적 데이터. -32,768 부터 32,767 까지의 정수를 표현한다. } 0 |II|Valid|Valid|Create a stack frame for a procedure.|
|C8 iw 01|`ENTER` \tooltip{imm16}{2 바이트 짜리 명시적 데이터. -32,768 부터 32,767 까지의 정수를 표현한다. } 1 |II|Valid|Valid|Create a stack frame with a nested pointer for a procedure.|
|C8 iw ib|`ENTER` \tooltip{imm16}{2 바이트 짜리 명시적 데이터. -32,768 부터 32,767 까지의 정수를 표현한다. } \tooltip{imm8}{1 바이트 짜리 명시적 데이터 (immediate value). imm8 의 경우 부호 있는 정수를 의미하며, -128 부터 127 까지의 값을 표현할 수 있다. 참고로 만일 imm8 이 1 바이트 보다 큰 피연산자를 가지는 명령어와 사용될 경우, 명시적 데이터는 부호를 유지한채 해당 크기로 확장이 된다. (쉽게 말해 0b11000000 은 0b11111111 11000000 로 확장되며 0b00110000 은 0b00000000 00110000 으로 확장된다.)} |II|Valid |Valid|Create a stack frame with nested pointers for a procedure.|
### Instruction Operand Encoding


|Op/En|Operand 1|Operand 2|Operand 3|Operand 4|
|-----|---------|---------|---------|---------|
|II|iw|imm8|NA|NA|
### Description


Creates a stack frame (comprising of space for dynamic storage and 1-32 frame pointer storage) for a procedure. The first operand (imm16) specifies the size of the dynamic storage in the stack frame (that is, the number of bytes of dynamically allocated on the stack for the procedure). The second operand (imm8) gives the lexical nesting level (0 to 31) of the procedure. The nesting level (imm8 mod 32) and the OperandSize attribute determine the size in bytes of the storage space for frame pointers.

The nesting level determines the number of frame pointers that are copied into the "display area" of the new stack frame from the preceding frame. The default size of the frame pointer is the StackAddrSize attribute, but can be overridden using the 66H prefix. Thus, the OperandSize attribute determines the size of each frame pointer that will be copied into the stack frame and the data being transferred from SP/ESP/RSP register into the BP/EBP/RBP register.

The `ENTER` and companion `LEAVE` instructions are provided to support block structured languages. 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.

If the nesting level is 0, the processor pushes the frame pointer from the BP/EBP/RBP register onto the stack, copies the current stack pointer from the SP/ESP/RSP register into the BP/EBP/RBP register, and loads the SP/ESP/RSP register with the current stack-pointer value minus the value in the size operand. For nesting levels of 1 or greater, the processor pushes additional frame pointers on the stack before adjusting the stack pointer. These additional frame pointers provide the called procedure with access points to other nested frames on the stack. See "Procedure Calls for Block-Structured Languages" in Chapter 6 of the Intel(R) 64 and IA-32 Architectures Software Developer's Manual, Volume 1, for more information about the actions of the `ENTER` instruction.

The `ENTER` instruction causes a page fault whenever a write using the final value of the stack pointer (within the current stack segment) would do so.

In 64-bit mode, default operation size is 64 bits; 32-bit operation size cannot be encoded. Use of 66H prefix changes frame pointer operand size to 16 bits.

When the 66H prefix is used and causing the OperandSize attribute to be less than the StackAddrSize, software is responsible for the following:

*  The companion `LEAVE` instruction must also use the 66H prefix,

*  The value in the RBP/EBP register prior to executing "66H ENTER" must be within the same 16KByte region of the current stack pointer (RSP/ESP), such that the value of RBP/EBP after "66H ENTER" remains a valid address in the stack. This ensures "66H LEAVE" can restore 16-bits of data from the stack.


### Operation

```info-verb
AllocSize <- imm16;
NestingLevel <- imm8 MOD 32;
IF (OperandSize = 64)
    THEN 
          Push(RBP); (* RSP decrements by 8 *)
          FrameTemp <- RSP; 
    ELSE IF OperandSize = 32
          THEN 
                Push(EBP); (* (E)SP decrements by 4 *)
                FrameTemp <- ESP; FI;
    ELSE (* OperandSize = 16 *)
                Push(BP); (* RSP or (E)SP decrements by 2 *)
                FrameTemp <- SP; 
FI;
IF NestingLevel = 0
    THEN GOTO CONTINUE;
FI;
IF (NestingLevel > 1) 
    THEN FOR i <- 1 to (NestingLevel - 1)
          DO 
                IF (OperandSize = 64)
                      THEN
                            RBP <- RBP - 8;
                            Push([RBP]); (* Quadword push *)
                      ELSE IF OperandSize = 32
                            THEN
                                  IF StackSize = 32
                                        EBP <- EBP - 4;
                                        Push([EBP]); (* Doubleword push *)
                                  ELSE (* StackSize = 16 *)
                                        BP <- BP - 4;
                                        Push([BP]); (* Doubleword push *)
                                  FI;
                            FI;
                      ELSE (* OperandSize = 16 *)
                            IF StackSize = 32
                                  THEN
                                        EBP <- EBP - 2;
                                        Push([EBP]); (* Word push *)
                                  ELSE (* StackSize = 16 *)
                                        BP <- BP - 2;
                                        Push([BP]); (* Word push *)
                            FI;
                      FI;
    OD;
FI;
IF (OperandSize = 64) (* nestinglevel 1 *)
    THEN
          Push(FrameTemp); (* Quadword push and RSP decrements by 8 *)
    ELSE IF OperandSize = 32
THEN 
                Push(FrameTemp); FI; (* Doubleword push and (E)SP decrements by 4 *)
    ELSE (* OperandSize = 16 *)
                Push(FrameTemp); (* Word push and RSP|ESP|SP decrements by 2 *)
FI;
CONTINUE:
IF 64-Bit Mode (StackSize = 64)
    THEN
                RBP <- FrameTemp;
                RSP <- RSP - AllocSize;
    ELSE IF OperandSize = 32 
          THEN
                EBP <- FrameTemp;
                ESP <- ESP - AllocSize; FI;
    ELSE (* OperandSize = 16 *)
                BP <- FrameTemp[15:1]; (* Bits 16 and above of applicable RBP/EBP are unmodified *)
                SP <- SP - AllocSize;
FI;
END;
```
### Flags Affected


None.


### Protected Mode Exceptions

#### #SS(0)
* If the new value of the SP or ESP register is outside the stack segment limit.

#### #PF(fault-code)
* If a page fault occurs or if a write using the final value of the stack pointer (within the current stack segment) would cause a page fault.

#### #UD
* If the LOCK prefix is used.

### Real-Address Mode Exceptions

#### #SS
* If the new value of the SP or ESP register is outside the stack segment limit.

#### #UD
* If the LOCK prefix is used.

### Virtual-8086 Mode Exceptions

#### #SS(0)
* If the new value of the SP or ESP register is outside the stack segment limit.

#### #PF(fault-code)
* If a page fault occurs or if a write using the final value of the stack pointer (within the current stack segment) would cause a page fault.

#### #UD
* If the LOCK prefix is used.

### Compatibility Mode Exceptions



Same exceptions as in protected mode.


### 64-Bit Mode Exceptions

#### #SS(0)
* If the stack address is in a non-canonical form.

#### #PF(fault-code)
* If a page fault occurs or if a write using the final value of the stack pointer (within the current stack segment) would cause a page fault.

#### #UD
* If the LOCK prefix is used.
