How To Move A Value From The Stack To A Register Arm Assembly
x86 Assembly Guide
Contents: Registers | Memory and Addressing | Instructions | Calling Convention
This is a version adapted past Quentin Carbonneaux from David Evans' original document. The syntax was changed from Intel to AT&T, the standard syntax on UNIX systems, and the HTML code was purified.
This guide describes the basics of 32-chip x86 assembly language programming, covering a pocket-size but useful subset of the available instructions and assembler directives. In that location are several different assembly languages for generating x86 auto code. The one we will employ in CS421 is the GNU Assembler (gas) assembler. We will uses the standard AT&T syntax for writing x86 associates lawmaking.
The total x86 instruction gear up is large and complex (Intel'due south x86 educational activity prepare manuals incorporate over 2900 pages), and we practise not comprehend it all in this guide. For instance, in that location is a 16-fleck subset of the x86 education set up. Using the 16-bit programming model can be quite complex. Information technology has a segmented memory model, more restrictions on register usage, and then on. In this guide, nosotros will limit our attention to more modernistic aspects of x86 programming, and delve into the instruction set up simply in plenty particular to get a basic experience for x86 programming.
Registers
Modernistic (i.east 386 and across) x86 processors have eight 32-scrap general purpose registers, every bit depicted in Effigy 1. The register names are mostly historical. For example, EAX used to be called the accumulator since information technology was used by a number of arithmetics operations, and ECX was known as the counter since information technology was used to hold a loop index. Whereas about of the registers have lost their special purposes in the modern instruction set, by convention, ii are reserved for special purposes — the stack pointer (ESP) and the base arrow (EBP).
For the EAX, EBX, ECX, and EDX registers, subsections may be used. For example, the least significant ii bytes of EAX can be treated equally a 16-chip register called AX. The to the lowest degree significant byte of AX can be used as a single eight-scrap register called AL, while the nearly significant byte of AX can be used every bit a unmarried eight-bit register chosen AH. These names refer to the same physical register. When a two-byte quantity is placed into DX, the update affects the value of DH, DL, and EDX. These sub-registers are mainly hold-overs from older, sixteen-bit versions of the instruction set. However, they are sometimes convenient when dealing with data that are smaller than 32-bits (e.k. 1-byte ASCII characters).
Figure i. x86 Registers
Memory and Addressing Modes
Declaring Static Data Regions
You can declare static data regions (analogous to global variables) in x86 assembly using special assembler directives for this purpose. Data declarations should be preceded by the .data directive. Post-obit this directive, the directives .byte, .short, and .long tin can be used to declare one, 2, and iv byte data locations, respectively. To refer to the accost of the data created, we tin can label them. Labels are very useful and versatile in assembly, they requite names to retentivity locations that will be figured out later by the assembler or the linker. This is similar to declaring variables by name, merely abides by some lower level rules. For example, locations declared in sequence will be located in memory next to one some other.
Instance declarations:
.data var: .byte 64 /* Declare a byte, referred to equally location var, containing the value 64. */ .byte 10 /* Declare a byte with no label, containing the value 10. Its location is var + ane. */ x: .curt 42 /* Declare a ii-byte value initialized to 42, referred to every bit location x. */ y: .long 30000 /* Declare a iv-byte value, referred to as location y, initialized to 30000. */
Unlike in loftier level languages where arrays can have many dimensions and are accessed by indices, arrays in x86 associates linguistic communication are simply a number of cells located contiguously in retentivity. An array tin can be declared by just listing the values, equally in the starting time example below. For the special case of an array of bytes, string literals can exist used. In example a large area of memory is filled with zeroes the .zilch directive tin exist used.
Some examples:
s: .long 1, 2, 3 /* Declare three four-byte values, initialized to one, 2, and three.
The value at location southward + 8 volition be 3. */barr: .zero 10 /* Declare 10 bytes starting at location barr, initialized to 0. */ str: .string "hello" /* Declare vi bytes starting at the address str initialized to
the ASCII character values for hullo followed by a nul (0) byte. */
Addressing Retentiveness
Modern x86-compatible processors are capable of addressing up to 232 bytes of retentivity: memory addresses are 32-$.25 broad. In the examples above, where we used labels to refer to memory regions, these labels are really replaced by the assembler with 32-bit quantities that specify addresses in retention. In add-on to supporting referring to retention regions by labels (i.e. constant values), the x86 provides a flexible scheme for computing and referring to memory addresses: upward to two of the 32-scrap registers and a 32-fleck signed constant tin exist added together to compute a retentiveness address. One of the registers can be optionally pre-multiplied by 2, four, or 8.
The addressing modes tin can be used with many x86 instructions (we'll depict them in the adjacent section). Here nosotros illustrate some examples using the mov instruction that moves information between registers and retentivity. This teaching has 2 operands: the offset is the source and the second specifies the destination.
Some examples of mov instructions using address computations are:
mov (%ebx), %eax /* Load iv bytes from the retentivity accost in EBX into EAX. */ mov %ebx, var(,1) /* Motion the contents of EBX into the 4 bytes at retention address var.
(Note, var is a 32-bit constant). */mov -4(%esi), %eax /* Move 4 bytes at memory address ESI + (-four) into EAX. */ mov %cl, (%esi,%eax,1) /* Move the contents of CL into the byte at accost ESI+EAX. */ mov (%esi,%ebx,4), %edx /* Move the 4 bytes of information at address ESI+4*EBX into EDX. */
Some examples of invalid address calculations include:
mov (%ebx,%ecx,-i), %eax /* Can but add together register values. */ mov %ebx, (%eax,%esi,%edi,i) /* At most 2 registers in address computation. */
Operation Suffixes
In general, the intended size of the of the data particular at a given memory address can be inferred from the assembly lawmaking instruction in which it is referenced. For example, in all of the above instructions, the size of the memory regions could be inferred from the size of the annals operand. When we were loading a 32-bit register, the assembler could infer that the region of memory nosotros were referring to was 4 bytes wide. When we were storing the value of a one byte register to retentiveness, the assembler could infer that nosotros wanted the address to refer to a single byte in memory.
However, in some cases the size of a referred-to memory region is ambiguous. Consider the instruction mov $ii, (%ebx). Should this pedagogy move the value 2 into the unmarried byte at address EBX? Possibly information technology should move the 32-bit integer representation of 2 into the 4-bytes starting at address EBX. Since either is a valid possible interpretation, the assembler must be explicitly directed every bit to which is correct. The size prefixes b, w, and l serve this purpose, indicating sizes of 1, ii, and 4 bytes respectively.
For example:
movb $ii, (%ebx) /* Move ii into the single byte at the address stored in EBX. */ movw $two, (%ebx) /* Motion the 16-scrap integer representation of 2 into the ii bytes starting at the address in EBX. */ movl $ii, (%ebx) /* Movement the 32-chip integer representation of two into the 4 bytes starting at the address in EBX. */
Instructions
Automobile instructions generally autumn into three categories: data motility, arithmetic/logic, and control-flow. In this department, we will look at important examples of x86 instructions from each category. This section should not be considered an exhaustive list of x86 instructions, but rather a useful subset. For a consummate list, come across Intel'south instruction set reference.
Nosotros utilize the following notation:
<reg32> Any 32-scrap register (%eax, %ebx, %ecx, %edx, %esi, %edi, %esp, or %ebp) <reg16> Any sixteen-bit register (%ax, %bx, %cx, or %dx) <reg8> Any 8-bit register (%ah, %bh, %ch, %dh, %al, %bl, %cl, or %dl) <reg> Whatever annals <mem> A memory address (e.g., (%eax), 4+var(,1), or (%eax,%ebx,1)) <con32> Any 32-fleck immediate <con16> Whatever 16-scrap immediate <con8> Whatever viii-bit immediate <con> Any viii-, 16-, or 32-fleck immediate
In assembly linguistic communication, all the labels and numeric constants used every bit immediate operands (i.e. non in an address calculation like 3(%eax,%ebx,8)) are e'er prefixed by a dollar sign. When needed, hexadecimal notation can be used with the 0x prefix (e.g. $0xABC). Without the prefix, numbers are interpreted in the decimal basis.
Data Movement Instructions
mov — Motion
The mov instruction copies the information particular referred to past its first operand (i.e. register contents, memory contents, or a abiding value) into the location referred to by its second operand (i.e. a register or memory). While register-to-register moves are possible, straight retention-to-memory moves are not. In cases where retention transfers are desired, the source retention contents must outset exist loaded into a register, and then can exist stored to the destination retentivity address.Syntax
mov <reg>, <reg>
mov <reg>, <mem>
mov <mem>, <reg>
mov <con>, <reg>
mov <con>, <mem>
Examples
mov %ebx, %eax — copy the value in EBX into EAX
movb $5, var(,one) — store the value 5 into the byte at location var
push — Push on stack
The button instruction places its operand onto the top of the hardware supported stack in retentiveness. Specifically, push first decrements ESP past iv, so places its operand into the contents of the 32-chip location at address (%esp). ESP (the stack arrow) is decremented past push button since the x86 stack grows down — i.due east. the stack grows from high addresses to lower addresses.Syntax
push button <reg32>
push button <mem>
button <con32>Examples
push button %eax — push button eax on the stack
push var(,1) — push the 4 bytes at accost var onto the stack
popular — Pop from stack
The popular instruction removes the four-byte data element from the top of the hardware-supported stack into the specified operand (i.e. annals or memory location). It showtime moves the 4 bytes located at retention location (%esp) into the specified register or retention location, and so increments ESP by four.Syntax
Examples
popular <reg32>
pop <mem>
popular %edi — pop the pinnacle element of the stack into EDI.
pop (%ebx) — pop the top element of the stack into memory at the four bytes starting at location EBX.
lea — Load effective accost
The lea instruction places the accost specified past its first operand into the register specified by its second operand. Note, the contents of the memory location are not loaded, only the constructive address is computed and placed into the register. This is useful for obtaining a pointer into a memory region or to perform uncomplicated arithmetics operations.Syntax
lea <mem>, <reg32>
Examples
lea (%ebx,%esi,8), %edi — the quantity EBX+8*ESI is placed in EDI.
lea val(,1), %eax — the value val is placed in EAX.
Arithmetic and Logic Instructions
add together — Integer addition
The add together didactics adds together its two operands, storing the result in its second operand. Note, whereas both operands may exist registers, at most one operand may be a memory location.Syntax
add <reg>, <reg>
add <mem>, <reg>
add <reg>, <mem>
add <con>, <reg>
add <con>, <mem>
Examples
add together $10, %eax — EAX is ready to EAX + x
addb $x, (%eax) — add 10 to the unmarried byte stored at memory accost stored in EAX
sub — Integer subtraction
The sub instruction stores in the value of its second operand the effect of subtracting the value of its first operand from the value of its second operand. Equally with add together, whereas both operands may be registers, at virtually one operand may exist a memory location.Syntax
sub <reg>, <reg>
sub <mem>, <reg>
sub <reg>, <mem>
sub <con>, <reg>
sub <con>, <mem>
Examples
sub %ah, %al — AL is set up to AL - AH
sub $216, %eax — subtract 216 from the value stored in EAX
inc, december — Increase, Decrement
The inc instruction increments the contents of its operand by 1. The dec instruction decrements the contents of its operand past one.Syntax
inc <reg>
inc <mem>
dec <reg>
december <mem>Examples
dec %eax — subtract one from the contents of EAX
incl var(,1) — add one to the 32-fleck integer stored at location var
imul — Integer multiplication
The imul education has ii basic formats: two-operand (first ii syntax listings above) and three-operand (last ii syntax listings above).The ii-operand class multiplies its two operands together and stores the consequence in the 2nd operand. The issue (i.due east. second) operand must exist a register.
The three operand form multiplies its 2nd and third operands together and stores the event in its last operand. Once again, the result operand must be a register. Furthermore, the offset operand is restricted to being a abiding value.
Syntax
imul <reg32>, <reg32>
imul <mem>, <reg32>
imul <con>, <reg32>, <reg32>
imul <con>, <mem>, <reg32>Examples
imul (%ebx), %eax — multiply the contents of EAX by the 32-chip contents of the retentivity at location EBX. Store the effect in EAX.
imul $25, %edi, %esi — ESI is set up to EDI * 25
idiv — Integer division
The idiv instruction divides the contents of the 64 bit integer EDX:EAX (synthetic by viewing EDX as the most meaning four bytes and EAX as the least significant four bytes) by the specified operand value. The caliber result of the division is stored into EAX, while the residuum is placed in EDX.Syntax
idiv <reg32>
idiv <mem>Examples
idiv %ebx — split up the contents of EDX:EAX by the contents of EBX. Place the quotient in EAX and the remainder in EDX.
idivw (%ebx) — split up the contents of EDX:EAS by the 32-bit value stored at the memory location in EBX. Place the quotient in EAX and the remainder in EDX.
and, or, xor — Bitwise logical and, or, and exclusive or
These instructions perform the specified logical operation (logical bitwise and, or, and exclusive or, respectively) on their operands, placing the effect in the first operand location.Syntax
and <reg>, <reg>
and <mem>, <reg>
and <reg>, <mem>
and <con>, <reg>
and <con>, <mem>
or <reg>, <reg>
or <mem>, <reg>
or <reg>, <mem>
or <con>, <reg>
or <con>, <mem>
xor <reg>, <reg>
xor <mem>, <reg>
xor <reg>, <mem>
xor <con>, <reg>
xor <con>, <mem>
Examples
and $0x0f, %eax — clear all but the final 4 bits of EAX.
xor %edx, %edx — prepare the contents of EDX to zero.
not — Bitwise logical not
Logically negates the operand contents (that is, flips all fleck values in the operand).Syntax
non <reg>
not <mem>Instance
not %eax — flip all the bits of EAX
neg — Negate
Performs the two's complement negation of the operand contents.Syntax
neg <reg>
neg <mem>Instance
neg %eax — EAX is set to (- EAX)
shl, shr — Shift left and right
These instructions shift the bits in their first operand's contents left and right, padding the resulting empty bit positions with zeros. The shifted operand can exist shifted upward to 31 places. The number of bits to shift is specified by the 2nd operand, which can be either an 8-fleck abiding or the annals CL. In either case, shifts counts of greater and then 31 are performed modulo 32.Syntax
shl <con8>, <reg>
shl <con8>, <mem>
shl %cl, <reg>
shl %cl, <mem>shr <con8>, <reg>
shr <con8>, <mem>
shr %cl, <reg>
shr %cl, <mem>Examples
shl $1, eax — Multiply the value of EAX by 2 (if the most significant bit is 0)
shr %cl, %ebx — Store in EBX the floor of outcome of dividing the value of EBX by 2 n where north is the value in CL. Caution: for negative integers, information technology is different from the C semantics of partition!
Control Flow Instructions
The x86 processor maintains an instruction arrow (EIP) register that is a 32-scrap value indicating the location in memory where the current instruction starts. Normally, information technology increments to point to the side by side educational activity in retentivity begins after execution an instruction. The EIP annals cannot exist manipulated directly, merely is updated implicitly past provided control flow instructions.
We use the notation <label> to refer to labeled locations in the programme text. Labels tin can exist inserted anywhere in x86 assembly code text by entering a label proper noun followed by a colon. For case,
mov 8(%ebp), %esi begin: xor %ecx, %ecx mov (%esi), %eax
The 2d instruction in this code fragment is labeled brainstorm. Elsewhere in the lawmaking, we can refer to the memory location that this pedagogy is located at in memory using the more convenient symbolic proper noun begin. This label is just a convenient style of expressing the location instead of its 32-fleck value.
jmp — Jump
Transfers program control flow to the pedagogy at the retention location indicated by the operand.Syntax
jmp <label>Example
jmp begin — Jump to the instruction labeled begin.
jcondition — Provisional bound
These instructions are conditional jumps that are based on the status of a prepare of condition codes that are stored in a special register called the machine status give-and-take. The contents of the machine condition discussion include information nearly the last arithmetics operation performed. For example, one bit of this discussion indicates if the terminal result was zero. Some other indicates if the last upshot was negative. Based on these condition codes, a number of provisional jumps can be performed. For instance, the jz instruction performs a jump to the specified operand label if the upshot of the final arithmetic performance was goose egg. Otherwise, control proceeds to the next didactics in sequence.A number of the conditional branches are given names that are intuitively based on the terminal operation performed being a special compare instruction, cmp (see beneath). For example, conditional branches such every bit jle and jne are based on first performing a cmp functioning on the desired operands.
Syntax
je <label> (jump when equal)
jne <label> (jump when not equal)
jz <characterization> (jump when concluding issue was aught)
jg <label> (jump when greater than)
jge <characterization> (spring when greater than or equal to)
jl <label> (spring when less than)
jle <characterization> (jump when less than or equal to)Case
cmp %ebx, %eax jle washedIf the contents of EAX are less than or equal to the contents of EBX, spring to the characterization done. Otherwise, continue to the adjacent instruction.
cmp — Compare
Compare the values of the two specified operands, setting the condition codes in the machine status discussion appropriately. This pedagogy is equivalent to the sub instruction, except the effect of the subtraction is discarded instead of replacing the first operand.Syntax
cmp <reg>, <reg>
cmp <mem>, <reg>
cmp <reg>, <mem>
cmp <con>, <reg>Example
cmpb $10, (%ebx)
jeq loopIf the byte stored at the memory location in EBX is equal to the integer constant 10, jump to the location labeled loop.
call, ret — Subroutine call and return
These instructions implement a subroutine call and return. The call teaching offset pushes the electric current lawmaking location onto the hardware supported stack in memory (see the push button pedagogy for details), and then performs an unconditional spring to the code location indicated past the characterization operand. Different the unproblematic jump instructions, the call instruction saves the location to return to when the subroutine completes.The ret educational activity implements a subroutine render mechanism. This pedagogy showtime pops a code location off the hardware supported in-retention stack (meet the pop instruction for details). It then performs an unconditional jump to the retrieved code location.
Syntax
call <label>
ret
Calling Convention
To allow separate programmers to share code and develop libraries for utilize by many programs, and to simplify the employ of subroutines in general, programmers typically adopt a common calling convention. The calling convention is a protocol about how to phone call and return from routines. For example, given a prepare of calling convention rules, a programmer need non examine the definition of a subroutine to determine how parameters should be passed to that subroutine. Furthermore, given a set of calling convention rules, high-level language compilers tin can be fabricated to follow the rules, thus allowing mitt-coded assembly language routines and high-level linguistic communication routines to call i another.
In practice, many calling conventions are possible. We will depict the widely used C linguistic communication calling convention. Post-obit this convention volition let you to write assembly linguistic communication subroutines that are safely callable from C (and C++) lawmaking, and will also enable you to call C library functions from your assembly language code.
The C calling convention is based heavily on the use of the hardware-supported stack. It is based on the push, pop, phone call, and ret instructions. Subroutine parameters are passed on the stack. Registers are saved on the stack, and local variables used by subroutines are placed in memory on the stack. The vast majority of loftier-level procedural languages implemented on virtually processors have used like calling conventions.
The calling convention is broken into two sets of rules. The starting time set of rules is employed by the caller of the subroutine, and the second set of rules is observed by the writer of the subroutine (the callee). It should be emphasized that mistakes in the observance of these rules quickly consequence in fatal program errors since the stack volition be left in an inconsistent country; thus meticulous care should be used when implementing the call convention in your ain subroutines.
Stack during Subroutine Phone call
[Cheers to James Peterson for finding and fixing the bug in the original version of this effigy!]
A good style to visualize the operation of the calling convention is to draw the contents of the nearby region of the stack during subroutine execution. The paradigm in a higher place depicts the contents of the stack during the execution of a subroutine with three parameters and three local variables. The cells depicted in the stack are 32-chip wide memory locations, thus the memory addresses of the cells are 4 bytes apart. The kickoff parameter resides at an offset of 8 bytes from the base of operations pointer. Above the parameters on the stack (and below the base pointer), the call instruction placed the return address, thus leading to an actress 4 bytes of offset from the base of operations pointer to the first parameter. When the ret pedagogy is used to return from the subroutine, it will bound to the return address stored on the stack.
Caller Rules
To make a subrouting phone call, the caller should:
- Before calling a subroutine, the caller should salve the contents of certain registers that are designated caller-saved. The caller-saved registers are EAX, ECX, EDX. Since the called subroutine is allowed to modify these registers, if the caller relies on their values later the subroutine returns, the caller must push button the values in these registers onto the stack (so they can be restore after the subroutine returns.
- To pass parameters to the subroutine, push them onto the stack before the call. The parameters should be pushed in inverted guild (i.eastward. last parameter kickoff). Since the stack grows downwardly, the showtime parameter will be stored at the lowest address (this inversion of parameters was historically used to allow functions to be passed a variable number of parameters).
- To call the subroutine, employ the call pedagogy. This instruction places the return address on top of the parameters on the stack, and branches to the subroutine code. This invokes the subroutine, which should follow the callee rules beneath.
After the subroutine returns (immediately following the call instruction), the caller tin can expect to find the return value of the subroutine in the annals EAX. To restore the automobile country, the caller should:
- Remove the parameters from stack. This restores the stack to its state before the call was performed.
- Restore the contents of caller-saved registers (EAX, ECX, EDX) by popping them off of the stack. The caller can assume that no other registers were modified by the subroutine.
Instance
The code beneath shows a function call that follows the caller rules. The caller is calling a function myFunc that takes three integer parameters. First parameter is in EAX, the second parameter is the constant 216; the third parameter is in the memory location stored in EBX.
push button (%ebx) /* Button last parameter commencement */ push $216 /* Button the second parameter */ push %eax /* Push button showtime parameter terminal */ call myFunc /* Telephone call the part (presume C naming) */ add $12, %esp
Note that subsequently the call returns, the caller cleans up the stack using the add instruction. We have 12 bytes (iii parameters * iv bytes each) on the stack, and the stack grows down. Thus, to go rid of the parameters, we can simply add 12 to the stack arrow.
The result produced by myFunc is now available for use in the register EAX. The values of the caller-saved registers (ECX and EDX), may take been inverse. If the caller uses them after the telephone call, it would accept needed to save them on the stack earlier the call and restore them afterwards it.
Callee Rules
The definition of the subroutine should adhere to the post-obit rules at the beginning of the subroutine:
- Push the value of EBP onto the stack, and then copy the value of ESP into EBP using the following instructions:
push %ebp mov %esp, %ebp
This initial action maintains the base pointer, EBP. The base arrow is used by convention as a point of reference for finding parameters and local variables on the stack. When a subroutine is executing, the base of operations pointer holds a copy of the stack pointer value from when the subroutine started executing. Parameters and local variables will always be located at known, constant offsets away from the base arrow value. We push the erstwhile base pointer value at the kickoff of the subroutine so that we tin later restore the advisable base pointer value for the caller when the subroutine returns. Remember, the caller is not expecting the subroutine to alter the value of the base pointer. We then move the stack pointer into EBP to obtain our indicate of reference for accessing parameters and local variables. - Next, allocate local variables past making infinite on the stack. Recall, the stack grows down, so to make space on the top of the stack, the stack pointer should be decremented. The amount past which the stack arrow is decremented depends on the number and size of local variables needed. For example, if three local integers (4 bytes each) were required, the stack pointer would need to exist decremented by 12 to brand infinite for these local variables (i.e., sub $12, %esp). Equally with parameters, local variables will exist located at known offsets from the base of operations pointer.
- Adjacent, relieve the values of the callee-saved registers that will be used past the part. To relieve registers, push them onto the stack. The callee-saved registers are EBX, EDI, and ESI (ESP and EBP will also be preserved by the calling convention, but demand non be pushed on the stack during this stride).
After these 3 actions are performed, the body of the subroutine may proceed. When the subroutine is returns, it must follow these steps:
- Get out the return value in EAX.
- Restore the old values of any callee-saved registers (EDI and ESI) that were modified. The register contents are restored by popping them from the stack. The registers should be popped in the inverse order that they were pushed.
- Deallocate local variables. The obvious way to practice this might exist to add the appropriate value to the stack arrow (since the infinite was allocated by subtracting the needed amount from the stack pointer). In practice, a less error-decumbent way to deallocate the variables is to move the value in the base of operations pointer into the stack arrow: mov %ebp, %esp. This works because the base pointer always contains the value that the stack pointer contained immediately prior to the allocation of the local variables.
- Immediately earlier returning, restore the caller'due south base arrow value past popping EBP off the stack. Think that the first affair we did on entry to the subroutine was to push the base of operations arrow to save its former value.
- Finally, return to the caller past executing a ret pedagogy. This instruction will find and remove the appropriate return accost from the stack.
Note that the callee'southward rules fall cleanly into two halves that are basically mirror images of ane some other. The first half of the rules use to the beginning of the function, and are commonly said to define the prologue to the function. The latter half of the rules apply to the cease of the function, and are thus usually said to define the epilogue of the part.
Example
Here is an example function definition that follows the callee rules:
/* Start the lawmaking section */ .text /* Define myFunc equally a global (exported) role. */ .globl myFunc .type myFunc, @function myFunc: /* Subroutine Prologue */ push %ebp /* Save the old base pointer value. */ mov %esp, %ebp /* Set the new base arrow value. */ sub $4, %esp /* Make room for one iv-byte local variable. */ push %edi /* Save the values of registers that the function */ push %esi /* will modify. This function uses EDI and ESI. */ /* (no need to save EBX, EBP, or ESP) */ /* Subroutine Torso */ mov 8(%ebp), %eax /* Movement value of parameter ane into EAX. */ mov 12(%ebp), %esi /* Move value of parameter 2 into ESI. */ mov 16(%ebp), %edi /* Motion value of parameter 3 into EDI. */ mov %edi, -4(%ebp) /* Move EDI into the local variable. */ add %esi, -four(%ebp) /* Add together ESI into the local variable. */ add -4(%ebp), %eax /* Add the contents of the local variable */ /* into EAX (last result). */ /* Subroutine Epilogue */ pop %esi /* Recover register values. */ pop %edi mov %ebp, %esp /* Deallocate the local variable. */ pop %ebp /* Restore the caller's base pointer value. */ ret
The subroutine prologue performs the standard actions of saving a snapshot of the stack pointer in EBP (the base pointer), allocating local variables by decrementing the stack arrow, and saving annals values on the stack.
In the body of the subroutine nosotros can run into the use of the base of operations pointer. Both parameters and local variables are located at abiding offsets from the base of operations arrow for the elapsing of the subroutines execution. In particular, we observe that since parameters were placed onto the stack earlier the subroutine was called, they are always located beneath the base of operations pointer (i.e. at higher addresses) on the stack. The first parameter to the subroutine can always be plant at retentivity location (EBP+8), the second at (EBP+12), the third at (EBP+16). Similarly, since local variables are allocated after the base pointer is set, they always reside in a higher place the base arrow (i.e. at lower addresses) on the stack. In detail, the first local variable is e'er located at (EBP-four), the second at (EBP-8), and then on. This conventional use of the base pointer allows usa to quickly identify the utilize of local variables and parameters within a function body.
The role epilogue is basically a mirror epitome of the function prologue. The caller'southward annals values are recovered from the stack, the local variables are deallocated by resetting the stack pointer, the caller'south base arrow value is recovered, and the ret instruction is used to return to the appropriate lawmaking location in the caller.
Credits: This guide was originally created past Adam Ferrari many years ago,
and since updated past Alan Batson, Mike Lack, and Anita Jones.
It was revised for 216 Leap 2006 by David Evans.
Information technology was finally modified by Quentin Carbonneaux to utilize the AT&T syntax for Yale's CS421.
How To Move A Value From The Stack To A Register Arm Assembly,
Source: https://flint.cs.yale.edu/cs421/papers/x86-asm/asm.html
Posted by: pollardcolon1983.blogspot.com
0 Response to "How To Move A Value From The Stack To A Register Arm Assembly"
Post a Comment