How to Read a Character Input X86 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 lawmaking was purified.
This guide describes the nuts of 32-flake x86 assembly language programming, covering a small but useful subset of the bachelor instructions and assembler directives. There are several unlike assembly languages for generating x86 machine code. The one we will use in CS421 is the GNU Assembler (gas) assembler. We will uses the standard AT&T syntax for writing x86 assembly lawmaking.
The full x86 educational activity set is large and complex (Intel's x86 didactics set manuals comprise over 2900 pages), and nosotros do non cover it all in this guide. For instance, there is a 16-bit subset of the x86 educational activity ready. Using the 16-bit programming model tin can be quite circuitous. Information technology has a segmented memory model, more restrictions on register usage, then on. In this guide, nosotros will limit our attending to more modernistic aspects of x86 programming, and delve into the educational activity set only in enough detail to get a basic feel for x86 programming.
Registers
Mod (i.e 386 and across) x86 processors have eight 32-bit general purpose registers, as depicted in Figure 1. The annals names are mostly historical. For example, EAX used to exist called the accumulator since information technology was used past a number of arithmetic operations, and ECX was known as the counter since information technology was used to concord a loop index. Whereas virtually of the registers accept lost their special purposes in the mod instruction set, by convention, two are reserved for special purposes — the stack pointer (ESP) and the base pointer (EBP).
For the EAX, EBX, ECX, and EDX registers, subsections may exist used. For example, the to the lowest degree meaning 2 bytes of EAX tin can exist treated as a xvi-scrap register called AX. The least significant byte of AX can be used as a single viii-scrap register called AL, while the most pregnant byte of AX can exist used as a single eight-scrap 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, 16-chip versions of the instruction prepare. However, they are sometimes convenient when dealing with data that are smaller than 32-$.25 (e.grand. one-byte ASCII characters).
Figure 1. x86 Registers
Retentiveness and Addressing Modes
Declaring Static Data Regions
You can declare static data regions (analogous to global variables) in x86 associates using special assembler directives for this purpose. Data declarations should exist preceded by the .data directive. Following this directive, the directives .byte, .short, and .long can be used to declare one, two, and four byte data locations, respectively. To refer to the address of the data created, we can label them. Labels are very useful and versatile in assembly, they give names to memory locations that will be figured out later past the assembler or the linker. This is similar to declaring variables by name, but abides by some lower level rules. For example, locations declared in sequence will exist located in memory side by side to one another.
Example 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 ten. Its location is var + one. */ x: .short 42 /* Declare a two-byte value initialized to 42, referred to every bit location x. */ y: .long 30000 /* Declare a 4-byte value, referred to every bit location y, initialized to 30000. */
Unlike in high level languages where arrays can accept many dimensions and are accessed past indices, arrays in x86 associates language are merely a number of cells located contiguously in memory. An array can exist declared past just listing the values, every bit in the first example below. For the special case of an array of bytes, cord literals can be used. In instance a large expanse of retentiveness is filled with zeroes the .aught directive can be used.
Some examples:
s: .long 1, ii, 3 /* Declare iii 4-byte values, initialized to 1, 2, and 3.
The value at location southward + 8 volition exist iii. */barr: .zero ten /* Declare 10 bytes starting at location barr, initialized to 0. */ str: .string "hello" /* Declare 6 bytes starting at the address str initialized to
the ASCII character values for hello followed past a nul (0) byte. */
Addressing Retentiveness
Modern x86-compatible processors are capable of addressing upwardly to 232 bytes of retentiveness: retention addresses are 32-$.25 wide. In the examples to a higher place, where we used labels to refer to memory regions, these labels are actually replaced by the assembler with 32-scrap quantities that specify addresses in retention. In add-on to supporting referring to memory regions by labels (i.e. constant values), the x86 provides a flexible scheme for calculating and referring to retentivity addresses: upward to ii of the 32-bit registers and a 32-bit signed constant can be added together to compute a memory address. One of the registers tin can be optionally pre-multiplied by 2, iv, or 8.
The addressing modes can be used with many x86 instructions (we'll describe them in the next department). Here we illustrate some examples using the mov teaching that moves data betwixt registers and retentiveness. This pedagogy has two operands: the first is the source and the second specifies the destination.
Some examples of mov instructions using address computations are:
mov (%ebx), %eax /* Load 4 bytes from the memory address in EBX into EAX. */ mov %ebx, var(,1) /* Move the contents of EBX into the 4 bytes at memory address var.
(Note, var is a 32-bit abiding). */mov -iv(%esi), %eax /* Move iv bytes at memory accost ESI + (-4) into EAX. */ mov %cl, (%esi,%eax,1) /* Motion the contents of CL into the byte at accost ESI+EAX. */ mov (%esi,%ebx,4), %edx /* Move the 4 bytes of data at accost ESI+iv*EBX into EDX. */
Some examples of invalid address calculations include:
mov (%ebx,%ecx,-1), %eax /* Can simply add register values. */ mov %ebx, (%eax,%esi,%edi,one) /* At most 2 registers in address ciphering. */
Functioning Suffixes
In general, the intended size of the of the data item at a given retentiveness address tin can be inferred from the assembly code pedagogy in which it is referenced. For example, in all of the above instructions, the size of the memory regions could exist inferred from the size of the register operand. When we were loading a 32-bit register, the assembler could infer that the region of memory we were referring to was four bytes wide. When we were storing the value of a one byte annals to memory, the assembler could infer that we wanted the accost to refer to a unmarried byte in retention.
Nonetheless, in some cases the size of a referred-to memory region is ambiguous. Consider the pedagogy mov $2, (%ebx). Should this didactics move the value ii into the unmarried byte at address EBX? Maybe it should move the 32-bit integer representation of 2 into the 4-bytes starting at address EBX. Since either is a valid possible estimation, the assembler must exist explicitly directed equally to which is right. The size prefixes b, w, and l serve this purpose, indicating sizes of i, two, and 4 bytes respectively.
For case:
movb $2, (%ebx) /* Move two into the unmarried byte at the address stored in EBX. */ movw $2, (%ebx) /* Move the 16-chip integer representation of 2 into the 2 bytes starting at the address in EBX. */ movl $2, (%ebx) /* Move the 32-bit integer representation of 2 into the 4 bytes starting at the address in EBX. */
Instructions
Automobile instructions generally fall into 3 categories: data movement, arithmetic/logic, and control-menstruation. In this section, nosotros volition look at important examples of x86 instructions from each category. This department should non be considered an exhaustive list of x86 instructions, merely rather a useful subset. For a complete list, see Intel's educational activity set reference.
We use the following notation:
<reg32> Any 32-bit register (%eax, %ebx, %ecx, %edx, %esi, %edi, %esp, or %ebp) <reg16> Any xvi-flake register (%ax, %bx, %cx, or %dx) <reg8> Any eight-bit register (%ah, %bh, %ch, %dh, %al, %bl, %cl, or %dl) <reg> Whatever register <mem> A memory address (e.one thousand., (%eax), 4+var(,one), or (%eax,%ebx,1)) <con32> Whatsoever 32-bit immediate <con16> Any 16-bit immediate <con8> Any viii-flake firsthand <con> Whatever 8-, sixteen-, or 32-fleck immediate
In assembly language, all the labels and numeric constants used as firsthand operands (i.e. not in an address calculation like 3(%eax,%ebx,viii)) are always prefixed by a dollar sign. When needed, hexadecimal notation tin can be used with the 0x prefix (eastward.one thousand. $0xABC). Without the prefix, numbers are interpreted in the decimal basis.
Data Movement Instructions
mov — Move
The mov teaching copies the data item referred to past its first operand (i.e. register contents, memory contents, or a constant value) into the location referred to by its second operand (i.e. a register or memory). While register-to-register moves are possible, direct retention-to-memory moves are not. In cases where memory transfers are desired, the source retentiveness contents must outset be loaded into a register, then tin be stored to the destination retentiveness 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(,1) — shop the value five into the byte at location var
push — Push button on stack
The button education places its operand onto the height of the hardware supported stack in retention. Specifically, button kickoff decrements ESP past 4, and then places its operand into the contents of the 32-bit location at address (%esp). ESP (the stack arrow) is decremented by button since the x86 stack grows down — i.due east. the stack grows from high addresses to lower addresses.Syntax
push <reg32>
push <mem>
push <con32>Examples
push %eax — push eax on the stack
push var(,1) — push the 4 bytes at address var onto the stack
popular — Pop from stack
The pop instruction removes the four-byte data element from the tiptop of the hardware-supported stack into the specified operand (i.e. register or memory location). It offset moves the four bytes located at retentivity location (%esp) into the specified register or retention location, then increments ESP past 4.Syntax
Examples
pop <reg32>
pop <mem>
pop %edi — popular the top element of the stack into EDI.
pop (%ebx) — pop the superlative element of the stack into memory at the four bytes starting at location EBX.
lea — Load effective accost
The lea instruction places the address specified by its starting time operand into the register specified by its 2d operand. Notation, the contents of the memory location are not loaded, just the effective accost is computed and placed into the register. This is useful for obtaining a pointer into a retentiveness region or to perform simple arithmetic 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 — Integer addition
The add instruction adds together its ii operands, storing the effect 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 together <mem>, <reg>
add <reg>, <mem>
add <con>, <reg>
add <con>, <mem>
Examples
add $10, %eax — EAX is gear up to EAX + 10
addb $10, (%eax) — add 10 to the single byte stored at memory address stored in EAX
sub — Integer subtraction
The sub educational activity stores in the value of its 2nd operand the event of subtracting the value of its first operand from the value of its second operand. As with add, whereas both operands may exist registers, at most one operand may be 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 to AL - AH
sub $216, %eax — subtract 216 from the value stored in EAX
inc, dec — Increment, Decrement
The inc education increments the contents of its operand by 1. The dec didactics decrements the contents of its operand by one.Syntax
inc <reg>
inc <mem>
dec <reg>
dec <mem>Examples
dec %eax — subtract one from the contents of EAX
incl var(,1) — add 1 to the 32-bit integer stored at location var
imul — Integer multiplication
The imul instruction has two bones formats: ii-operand (outset two syntax listings in a higher place) and iii-operand (final ii syntax listings above).The ii-operand form multiplies its two operands together and stores the result in the second operand. The effect (i.e. second) operand must exist a register.
The 3 operand form multiplies its second and third operands together and stores the result in its final operand. Again, the event operand must be a annals. Furthermore, the first operand is restricted to being a constant 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-bit contents of the memory at location EBX. Store the issue in EAX.
imul $25, %edi, %esi — ESI is set to EDI * 25
idiv — Integer division
The idiv educational activity divides the contents of the 64 bit integer EDX:EAX (constructed past viewing EDX equally the most pregnant four bytes and EAX as the least meaning iv bytes) by the specified operand value. The quotient result of the division is stored into EAX, while the remainder is placed in EDX.Syntax
idiv <reg32>
idiv <mem>Examples
idiv %ebx — divide the contents of EDX:EAX past the contents of EBX. Place the quotient in EAX and the remainder in EDX.
idivw (%ebx) — carve up the contents of EDX:EAS by the 32-scrap value stored at the memory location in EBX. Identify the quotient in EAX and the residual in EDX.
and, or, xor — Bitwise logical and, or, and sectional or
These instructions perform the specified logical operation (logical bitwise and, or, and exclusive or, respectively) on their operands, placing the upshot 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 concluding 4 bits of EAX.
xor %edx, %edx — set the contents of EDX to zero.
non — Bitwise logical non
Logically negates the operand contents (that is, flips all bit values in the operand).Syntax
non <reg>
not <mem>Example
not %eax — flip all the $.25 of EAX
neg — Negate
Performs the two'due south 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 starting time operand's contents left and correct, padding the resulting empty bit positions with zeros. The shifted operand can be shifted up to 31 places. The number of bits to shift is specified by the 2d operand, which can be either an eight-scrap constant or the register 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 $one, eax — Multiply the value of EAX past ii (if the well-nigh significant bit is 0)
shr %cl, %ebx — Shop in EBX the floor of outcome of dividing the value of EBX by ii northward where north is the value in CL. Caution: for negative integers, it is unlike from the C semantics of division!
Control Flow Instructions
The x86 processor maintains an educational activity pointer (EIP) register that is a 32-bit value indicating the location in retention where the current instruction starts. Commonly, it increments to bespeak to the next instruction in memory begins after execution an didactics. The EIP register cannot exist manipulated directly, merely is updated implicitly by provided control menstruation instructions.
We use the notation <characterization> to refer to labeled locations in the program text. Labels tin be inserted anywhere in x86 assembly code text by inbound a label name followed by a colon. For example,
mov 8(%ebp), %esi brainstorm: xor %ecx, %ecx mov (%esi), %eax
The 2d instruction in this code fragment is labeled begin. Elsewhere in the lawmaking, we tin can refer to the memory location that this instruction is located at in memory using the more convenient symbolic name begin. This characterization is just a user-friendly manner of expressing the location instead of its 32-flake value.
jmp — Jump
Transfers program command flow to the instruction at the retentiveness location indicated by the operand.Syntax
jmp <label>Example
jmp brainstorm — Jump to the educational activity labeled begin.
jstatus — Provisional bound
These instructions are conditional jumps that are based on the status of a set up of condition codes that are stored in a special annals called the machine condition give-and-take. The contents of the machine status word include data virtually the last arithmetic operation performed. For example, 1 bit of this word indicates if the terminal issue was cypher. Another indicates if the last consequence was negative. Based on these condition codes, a number of conditional jumps can exist performed. For example, the jz instruction performs a jump to the specified operand label if the result of the terminal arithmetic operation was zero. Otherwise, control proceeds to the next instruction in sequence.A number of the conditional branches are given names that are intuitively based on the last operation performed being a special compare instruction, cmp (see below). For example, conditional branches such as jle and jne are based on showtime performing a cmp operation on the desired operands.
Syntax
je <label> (jump when equal)
jne <characterization> (jump when not equal)
jz <label> (jump when last result was zero)
jg <label> (jump when greater than)
jge <label> (jump when greater than or equal to)
jl <characterization> (spring when less than)
jle <label> (leap when less than or equal to)Instance
cmp %ebx, %eax jle doneIf the contents of EAX are less than or equal to the contents of EBX, bound to the label done. Otherwise, proceed to the adjacent instruction.
cmp — Compare
Compare the values of the two specified operands, setting the condition codes in the car status give-and-take appropriately. This instruction is equivalent to the sub instruction, except the result of the subtraction is discarded instead of replacing the showtime 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 render
These instructions implement a subroutine phone call and return. The call instruction first pushes the current code location onto the hardware supported stack in memory (come across the push instruction for details), and so performs an unconditional spring to the code location indicated past the label operand. Unlike the uncomplicated leap instructions, the telephone call instruction saves the location to return to when the subroutine completes.The ret instruction implements a subroutine return mechanism. This instruction first pops a lawmaking location off the hardware supported in-retention stack (come across the popular instruction for details). It so performs an unconditional spring to the retrieved code location.
Syntax
phone call <label>
ret
Calling Convention
To allow split programmers to share code and develop libraries for use past many programs, and to simplify the use of subroutines in general, programmers typically adopt a common calling convention. The calling convention is a protocol most how to call and return from routines. For example, given a set of calling convention rules, a programmer need not examine the definition of a subroutine to determine how parameters should exist passed to that subroutine. Furthermore, given a set of calling convention rules, high-level language compilers can be fabricated to follow the rules, thus allowing mitt-coded assembly linguistic communication routines and high-level linguistic communication routines to call one some other.
In practise, many calling conventions are possible. We will describe the widely used C language calling convention. Following this convention will allow you to write assembly language subroutines that are safely callable from C (and C++) code, 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, 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 high-level procedural languages implemented on most processors have used similar calling conventions.
The calling convention is broken into two sets of rules. The first prepare of rules is employed by the caller of the subroutine, and the 2d set of rules is observed by the writer of the subroutine (the callee). Information technology should be emphasized that mistakes in the observance of these rules apace result in fatal program errors since the stack will be left in an inconsistent state; thus meticulous intendance should be used when implementing the call convention in your ain subroutines.
Stack during Subroutine Call
[Thank you to James Peterson for finding and fixing the problems in the original version of this figure!]
A proficient manner to visualize the operation of the calling convention is to describe the contents of the nearby region of the stack during subroutine execution. The image above 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 retention locations, thus the memory addresses of the cells are 4 bytes apart. The offset parameter resides at an showtime of eight bytes from the base arrow. To a higher place the parameters on the stack (and beneath the base of operations pointer), the phone call instruction placed the return address, thus leading to an actress 4 bytes of offset from the base arrow to the first parameter. When the ret instruction is used to return from the subroutine, information technology will jump to the return accost stored on the stack.
Caller Rules
To make a subrouting call, the caller should:
- Earlier 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 chosen subroutine is allowed to alter these registers, if the caller relies on their values after the subroutine returns, the caller must push the values in these registers onto the stack (and so they can be restore later the subroutine returns.
- To pass parameters to the subroutine, push them onto the stack before the telephone call. The parameters should be pushed in inverted order (i.e. last parameter first). Since the stack grows down, the showtime parameter will be stored at the lowest accost (this inversion of parameters was historically used to allow functions to be passed a variable number of parameters).
- To call the subroutine, use the call teaching. This instruction places the return accost on top of the parameters on the stack, and branches to the subroutine code. This invokes the subroutine, which should follow the callee rules below.
After the subroutine returns (immediately following the call pedagogy), the caller can expect to detect the render value of the subroutine in the annals EAX. To restore the car state, the caller should:
- Remove the parameters from stack. This restores the stack to its country before the call was performed.
- Restore the contents of caller-saved registers (EAX, ECX, EDX) past popping them off of the stack. The caller can presume that no other registers were modified by the subroutine.
Example
The code beneath shows a function phone call that follows the caller rules. The caller is calling a office myFunc that takes three integer parameters. First parameter is in EAX, the 2d parameter is the constant 216; the third parameter is in the memory location stored in EBX.
push (%ebx) /* Push terminal parameter first */ push $216 /* Push the 2nd parameter */ push %eax /* Push first parameter final */ call myFunc /* Call the function (assume C naming) */ add $12, %esp
Notation that after the phone call returns, the caller cleans upward the stack using the add instruction. Nosotros have 12 bytes (3 parameters * four bytes each) on the stack, and the stack grows down. Thus, to get rid of the parameters, we can simply add 12 to the stack pointer.
The event 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 changed. If the caller uses them later the call, it would accept needed to salve them on the stack before the call and restore them after it.
Callee Rules
The definition of the subroutine should adhere to the following rules at the first of the subroutine:
- Push button the value of EBP onto the stack, and then copy the value of ESP into EBP using the post-obit instructions:
push %ebp mov %esp, %ebp
This initial action maintains the base pointer, EBP. The base of operations pointer is used by convention every bit a point of reference for finding parameters and local variables on the stack. When a subroutine is executing, the base pointer holds a copy of the stack pointer value from when the subroutine started executing. Parameters and local variables volition always be located at known, constant offsets away from the base pointer value. We push the old base pointer value at the kickoff of the subroutine then that we tin can subsequently restore the appropriate base pointer value for the caller when the subroutine returns. Call back, the caller is not expecting the subroutine to change the value of the base pointer. We and so movement the stack pointer into EBP to obtain our signal of reference for accessing parameters and local variables. - Next, allocate local variables by making infinite on the stack. Call up, the stack grows downwardly, and then to brand infinite on the top of the stack, the stack arrow should be decremented. The amount by which the stack pointer is decremented depends on the number and size of local variables needed. For example, if iii local integers (4 bytes each) were required, the stack pointer would demand to be decremented past 12 to make space for these local variables (i.e., sub $12, %esp). Equally with parameters, local variables will be located at known offsets from the base pointer.
- Next, salvage the values of the callee-saved registers that will be used past the office. To save registers, push them onto the stack. The callee-saved registers are EBX, EDI, and ESI (ESP and EBP will also be preserved past the calling convention, simply need not be pushed on the stack during this footstep).
Afterward these three deportment are performed, the trunk of the subroutine may proceed. When the subroutine is returns, it must follow these steps:
- Get out the render 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 exist popped in the inverse social club that they were pushed.
- Deallocate local variables. The obvious fashion to practice this might be to add the appropriate value to the stack pointer (since the infinite was allocated past subtracting the needed amount from the stack pointer). In practice, a less error-prone style to deallocate the variables is to move the value in the base arrow into the stack pointer: mov %ebp, %esp. This works because the base pointer always contains the value that the stack arrow independent immediately prior to the allocation of the local variables.
- Immediately before returning, restore the caller's base of operations arrow value by popping EBP off the stack. Retrieve that the get-go thing we did on entry to the subroutine was to push the base arrow to relieve its one-time value.
- Finally, return to the caller by executing a ret pedagogy. This instruction will detect and remove the appropriate render address from the stack.
Annotation that the callee'due south rules fall cleanly into two halves that are basically mirror images of ane another. The start half of the rules utilize to the beginning of the function, and are ordinarily said to ascertain the prologue to the part. The latter one-half of the rules apply to the end of the part, and are thus normally said to ascertain the epilogue of the function.
Example
Here is an example function definition that follows the callee rules:
/* Commencement the lawmaking section */ .text /* Define myFunc every bit a global (exported) office. */ .globl myFunc .blazon myFunc, @function myFunc: /* Subroutine Prologue */ push %ebp /* Save the old base pointer value. */ mov %esp, %ebp /* Set the new base pointer value. */ sub $4, %esp /* Make room for one 4-byte local variable. */ push %edi /* Save the values of registers that the function */ push button %esi /* will change. This function uses EDI and ESI. */ /* (no need to save EBX, EBP, or ESP) */ /* Subroutine Trunk */ mov 8(%ebp), %eax /* Move value of parameter one into EAX. */ mov 12(%ebp), %esi /* Move value of parameter ii into ESI. */ mov xvi(%ebp), %edi /* Move value of parameter 3 into EDI. */ mov %edi, -4(%ebp) /* Move EDI into the local variable. */ add %esi, -four(%ebp) /* Add ESI into the local variable. */ add -4(%ebp), %eax /* Add the contents of the local variable */ /* into EAX (final effect). */ /* Subroutine Epilogue */ pop %esi /* Recover register values. */ popular %edi mov %ebp, %esp /* Deallocate the local variable. */ popular %ebp /* Restore the caller'southward base arrow value. */ ret
The subroutine prologue performs the standard deportment of saving a snapshot of the stack pointer in EBP (the base pointer), allocating local variables by decrementing the stack pointer, and saving annals values on the stack.
In the trunk of the subroutine nosotros can run into the apply of the base of operations pointer. Both parameters and local variables are located at constant offsets from the base pointer for the duration of the subroutines execution. In particular, nosotros find that since parameters were placed onto the stack before the subroutine was called, they are always located below the base pointer (i.e. at college addresses) on the stack. The first parameter to the subroutine can always be plant at retention location (EBP+8), the 2nd at (EBP+12), the third at (EBP+sixteen). Similarly, since local variables are allocated after the base pointer is gear up, they always reside above the base arrow (i.e. at lower addresses) on the stack. In item, the first local variable is always located at (EBP-4), the 2d at (EBP-eight), then on. This conventional apply of the base pointer allows us to quickly place the use of local variables and parameters within a function body.
The function epilogue is basically a mirror image of the office prologue. The caller'due south register values are recovered from the stack, the local variables are deallocated past resetting the stack pointer, the caller'south base pointer value is recovered, and the ret teaching is used to return to the appropriate code location in the caller.
Credits: This guide was originally created by Adam Ferrari many years ago,
and since updated past Alan Batson, Mike Lack, and Anita Jones.
It was revised for 216 Spring 2006 by David Evans.
It was finally modified past Quentin Carbonneaux to utilise the AT&T syntax for Yale's CS421.
Source: https://flint.cs.yale.edu/cs421/papers/x86-asm/asm.html
0 Response to "How to Read a Character Input X86 Assembly"
Post a Comment