程序代写代做代考 assembly assembler x86 X86-64Assembly Language – Part 3: assembler directives, first programs, arithmetic instructions, stack

X86-64Assembly Language – Part 3: assembler directives, first programs, arithmetic instructions, stack
Required Reading: Computer Systems: A Programmer’s Perspective, 3rd Edition Chapter 3, Section 3.5 through 3.5.4 (inclusive)
CSE 2421


Allows a name to be assigned to the assembly language source code file.

• .section
This makes the specified section the current section.

.rodata

Specifies that the following data is to be placed in the read only memory portion of the executable

• .text
Changes or sets the current section to the text (or code) section
Assembler directives (“pseudo-ops”)
• .file
• .data
• Changes or sets the current section to the data section


Needed by the linker to identify the label as one associated with a function, as opposed to data

Needed by the linker to identify the size of the text for the program
Assembler directives (continued)
• .globl
• A directive needed by the linker for symbol resolution: followed by
name of function • .type
• .size
• Note: labels (for functions or data) in assembly language source code are followed by a colon.


Places the given value, (0x prefix for hex, no prefix for decimal) in memory, encoded in 2 bytes

Data size assembler directives
• • •
What if I want to “declare” static class variables??? In the .data or .rodata section of your program use: .quad value

.long value
• Places the given value, (0x prefix for hex, no prefix for decimal) in memory,

encoded in 4 bytes .word value

.byte value
Places the given value, (0x prefix for hex, no prefix for decimal) in memory,

.string
• Places the given value, (0x prefix for hex, no prefix for decimal) in memory, encoded in 8 bytes
encoded in 1 byte
• Specifies that the characters enclosed in quotation marks are to be stored in memory, terminated by a null byte

First X86 program
.file “first.s” .section .rodata .data
.align 8
main:
pushq %rbp
movq %rsp, %rbp
Array: .quad 0x6f .quad 0x84 .globl main
movq $55,%rdx movq %rdx, %rbx movq $Array, %rax movq %rbx,8(%rax) movq (%rax),%rcx
.type main, @function .text
leave
ret
.size main, .-main
5

Second X86 program
.file “second.s” .section .rodata .data
.align 8
main:
pushq %rbp
movq %rsp, %rbp
Array: .quad 0x6f .quad 0x84 .quad 0x55 .quad 0x44 .globl main
movq $55,%rdx movq %rdx, %rbx movq $0x33, %r8 movq $Array, %rax movq %rbx,8(%rax) movq %r8, 24(%rax) movq %rax,(%rax) movq (%rax),%rcx
.type main, @function .text
leave
ret
.size main, .-main
6

Some Arithmetic Operations
• Two Operand Instructions:
add sub imul mul sal sar shr xor and or
Src,Dest Src,Dest
#Dest = Dest + Src #Dest = Dest Src
Format
Computation
Src,Dest Src,Dest
#Dest = Dest * Src #Dest = Dest * Src
signed multiply unsigned multiply
Src,Dest Src,Dest Src,Dest
#Dest = Dest << Src #Dest = Dest >> Src #Dest = Dest >> Src
Also called shlq Arithmetic (fills w/copy of sign bit)
Src,Dest Src,Dest
#Dest = Dest ^ Src #Dest = Dest & Src
Src,Dest
• Watch out for argument order!
• Except for mul, no distinction between signed and
#Dest = Dest | Src
Logical (fills with 0s)

Arithmetic Operation Examples
Format
Computation
addq %rax,%rcx addl %eax, %ecx
# %rcx = %rax + %rcx # %rcx = %eax + %ecx
subw %ax, %cx subb %al, %cl
# %cx = %cx %ax # %cl = %cl – %al
imulq %rax,%rcx imull %eax, %ecx
# %rcx = %rcx * %rax # %ecx = %ecx * %eax
sarw $3, %cx
andl 0x0f0f0f0f, %ecx # %ecx = %ecx & 0x0f0f0f0f
# %cx = %cx >> 3

Some Arithmetic Operations
• One Operand Instructions
inc Dest dec Dest neg Dest not Dest
#Dest = Dest + 1 #Dest = Dest 1
#Dest = Dest #Dest = ~Dest
• See book for more instructions (Figure 3.10)
• Obviously, each of these instructions must use the appropriate suffix based on the Destination size

More Arithmetic Examples
• One Operand Instructions
incq %rax decl %eax negw %ax notb %al
# %rax = %rax + 1 # %eax = %eax 1
# %ax = %ax
# %al = ~%al

}
Register
Use(s)
Arithmetic Expression Example (z+x+y)*((x+4)+(y*48))
long arith(long x, long y, long z) {
long t1, t2, t3, t4, t5, rval;
arith: leaq addq leaq salq leaq imulq ret
(%rdi,%rsi), %rax %rdx, %rax
# t1 = x+y
# t2 = z + t1
t1 = x+y;
t2 = z+t1;
t3 = x+4;
t4 = y * 48; t5 = t3 + t4; rval = t2 * t5; return rval;
# %rdx = 3y $4, %rdx # %rdx * 16
Interesting Instructions
%rsi %rdx %rax %rdx %rcx
• • •
leaq: address computation salq: shift arithmetic left imulq: signed multiply
Argument z t1, t2, rval t4
t5
• But, only used once
(%rsi,%rsi,2),%rdx
4(%rdi,%rdx), %rcx %rcx, %rax
# x + t4 + 4 # t2=t2*t5
%rdi
Argument x Argument y

X86 program stack
• The program stack is divided conceptually into frames.
• Each procedure or function (main and any functions called from main or from another function) has its own part of the stack to use, which is called its stack frame.
• The stack frame goes from the stack address pointed to by %rbp in that procedure, this is called the frame (or base) pointer, to %rsp, which points to the top of the stack while the procedure is running.
• This implies that the address pointed to by %rbp is different in different procedures: %rbp must be set when the procedure is entered.

X86 Stack
Stack “Top”
%rsp
• Stack top address always held in register %rsp
• • Stack grows towards lower addresses • •
Increasing Addresses
• Where is %rbp??? • That depends…☺
Stack “Bottom”

Uses of the stack in X86-64
• Save the caller’s %rbp (frame pointer) before setting our own frame pointer;
• Before calling another function, to preserve values needed;
• To pass parameters to another function (if there are more than 6 parameters to pass);
• To store the return address when a call instruction is executed.
• If we need more temp data than available registers, (i.e. automatic, block scope variables)

Put something on the stack
•pushX source, where X is the suffix q or the suffix w
•What it does:
•Decrement %rsp by number of bytes specified by opcode

Take something off the stack
•popX destination, where X is the suffix q or the suffix w
•Read the number of bytes specified by

Function calls and returns
• To use function calls and returns in our X86 program, we have to manage the program stack and program registers correctly.
• Two different aspects to this:
• Maintain the stack pointer, frame pointer and associated data in relation to each function call and return. (The OS initializes these values upon system start.)
• Place appropriate values in “some” registers as expected by a calling or caller function. More on this later.

Setting up the program stack
• In X86 programs, for each function, you must set up the stack frame in your assembly language source code.
• There are three things to do:
• At the start of a function:
1. Set %rbp to point to the bottom of the current stack frame.
2. Set %rsp to point to the top of the stack (the same address as the stack bottom initially).
• At the end of a function:
3. Restore %rbp and %rsp to what they were before the function was called (we will see how to do this below)

Call instruction
• call Dest
• Dest is a label which has been placed in the assembly language
source code at the address of the procedure to be called. • call instruction does 2 things:
1. the address of the instruction immediately after the call instruction is pushed onto the stack (that is, the return address is pushed), and
2. the Dest (remember it’s an address) is assigned to the PC (%rip) register.
• This means that, when the called function begins execution, the return address to the calling function is the last thing that has been pushed onto the stack.

System Stack
Lower Addresses
call Swap_it

Before executing the call instruction
%rsp
Some stack value
Higher Addresses

System Stack
Lower Addresses
call Swap_it

After executing the call instruction
%rsp
Caller Ret Address 8 byte value
Some stack value
Higher Addresses
%rip Address of Swap_it

Setting up our stack frame
Part 1:
pushq %rbp # Save caller’s base pointer
movq %rsp, %rbp # Set my base pointer
Put these two instructions at the beginning of your function before any other statements!
* Notice that, since %rbp equals %rsp, the stack is empty. * We are now ready to use the stack!
Part 2:
leave # set caller’s stack frame back up
Put this statement directly before the ret instruction in any function in your program.

System Stack
Lower Addresses
Swap_it:
pushq %rbp
movq %rsp, %rbp

After pushq %rbp : %rsp
Caller’s %rbp 8 byte value
Caller Ret Address 8 byte value
Higher Addresses

System Stack
Lower Addresses
Swap_it:
pushq %rbp
movq %rsp, %rbp

After movq %rsp, %rbp: %rsp
Caller’s %rbp 8 byte value
%rbp
Caller Ret Address 8 byte value
Higher Addresses

Cleaning up our stack frame
• leave
• Sets stack pointer to the base frame address
• Pops what is at top of stack into %rbp (this adds 8 bytes to %rsp)
• Prepares the stack for return instruction • Syntax
leave
• leave – equivalent to: movq %rbp,%rsp
popq %rbp
• Don’t use both leave and movq/popq in same program • nasty result.

System Stack
Lower Addresses
Swap_it:
pushq %rbp
movq %rsp, %rbp …
leave equivalent to: movq %rbp,%rsp
popq %rbp ret
When we are getting ready to finish up:
Caller’s %rbp 8 byte value
%rsp %rbp
Caller Ret Address 8 byte value
Higher Addresses

System Stack
Lower Addresses
Swap_it:
pushq %rbp
movq %rsp, %rbp …
leave equivalent to: movq %rbp,%rsp
ret
popq %rbp
%rsp
Caller’s %rbp 8 byte value
Caller Ret Address 8 byte value
Higher Addresses

Return instruction
• ret
• The ret instruction does 2 things:
1. the address of the instruction immediately after the call instruction that got us here is popped from the stack, and
2. that address is assigned to the PC (%rip) register.

System Stack
Lower Addresses
Swap_it:
pushq %rbp
movq %rsp, %rbp …
leave equivalent to: movq %rbp,%rsp
%rip
ret
popq %rbp
Caller Ret Address 8 byte value
%rsp
Caller’s %rbp 8 byte value
Caller Ret Address 8 byte value
Higher Addresses

System Stack
Lower Addresses
call Swap_it

After executing the call instruction
%rsp
Caller Ret Address 8 byte value
Some stack value
Higher Addresses