Lab 1 ECE L 273

Download Report

Transcript Lab 1 ECE L 273

Lab 1
ECE L 273
Overview of ECE L 273
http://www.parl.clemson.edu/ullab/ece272/ece272.html
http://www.clemson.edu/ces/departments/ece/resources/ECE273Lab.html
• Lab 1 – Introduction
– Required tools
• Lab2 – Assignment Statements
– Basic Assembly Language Syntax
• Lab3 – Control Statements
– Loops, Branching
• Lab4 – Addressing modes
– Arrays and Pointers
• Lab5 – Subroutines and Stack
• Lab6 – Subroutine Parameters
Structure
• Lab assignment due after every 2 weeks.
– 70% of the grade
• In-Lab test during in-between weeks.
– 15% of the grade
• Final Exam
– 15% of the grade
Development Environment
• Dual Boot
– Install Linux on your laptop on a different hard
disk partition
• Virtualization Software
– Run Linux using either VMware or VirtualBox on
(Windows/MacOS)
– http://www.clemson.edu/ces/departments/ece/r
esources/virtualmachine.html
• Remote Access
– http://www.parl.clemson.edu/ullab/security.html
Assembly Language
• Programmer Perspective (Optimizing code)
– Write most of the code in High Level Language like
C or C++ for example.
– Profile the code and identify which parts are
executed most often and need to be optimized.
– Rewrite that part of code in low level language
(Assembly) to make it run faster.
• Compilers
– Compilers translate high-level language to lowlevel language.
Example of use of Assembly Code
#include <stdio.h>
int main(int arg, char **argv)
{
char buffer[256];
do {
int i = 0;
printf ("Enter a string terminated with a newline\n");
do {
buffer[i] = getchar();
} while (buffer[i++] != '\n');
buffer[i-1] = 0;
/* asum() is the * function * implemented in * assembly */
i = asum(buffer);
if (i) {
printf ("ascii sum is %d\n", i);
continue;
}
} while(1);
return 0;
}
.global asum
.type asum,@function
asum:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $0, -4(%ebp)
.L2:
movl 8(%ebp),%eax
cmpb $0,(%eax)
jne .L4
jmp .L3
.L4:
movl 8(%ebp),%eax
movsbl (%eax),%edx
addl %edx,-4(%ebp)
incl 8(%ebp)
jmp .L2
.L3:
movl -4(%ebp),%eax
jmp .L1
.L1:
movl %ebp, %esp
popl %ebp
ret
• Tools
– Editors (vi, emacs, pico)
– Compilers (gcc – GNU Compiler Collection)
– Assembler (as – GNU Assembler)
– Debugger (gdb – GNU Debugger)
• Typical Steps
– Write (C driver program, Assembly functions).
– Compile & Assemble.
– Link.
– Execute.
– Debug (if required).
drv.c
asm.s
drv.c
asm.s
COMPILATION
gcc -c -o drv.o drv.c
as -o asm.o asm.s
drv.o
LINKING
asm.o
COMPILATION
And
LINKING
gcc -o myprog drv.c asm.s
gcc -o myprog asm.o drv.o
myprog
Run the program: .\myprog
myprog
Documentation
http://www.parl.clemson.edu/ullab/documentation.html
• Headers
– Program Headers
– Procedure Headers
• Naming Convention
– Variables and subroutine names
• Comments
– Uncommented code will not be accepted
– Comments must relay purpose of the code and
not just verbalize them.
Program Header
//////////////////////////////////////////////////////////////////////////////////////////////
// ECE 273 Lab
//
// NAME:
Firstname Lastname
//
// SECTION:
Four (12:20 - 2:20) M
//
// DATE DUE: Feb. 1, 1998
//
// FILENAME: somefile.extension
//
// PROJECT:
Lab Assignment #1
//
// PURPOSE: This assembly program calculates the //
//
ASCII sum of the characters passed to //
//
it as a character array.
//
////////////////////////////////////////////////////////////////////////////////////////////
filename
This should simply contain the name of the file in which this header is residing.
project
Should contain the name of the overall project.
purpose
Should briefly explain the what this program does.
Program headers are included once per assignment at the top of the document.
Procedure Header
//////////////////////////////////////////////////////////////////////////////////////
// PROCEDURE: ProcedureName
//
// PARAMETERS: Listing of parameters
//
// RETURNS:
Listing of data that gets returned //
// DESCRIPTION: What this procedure does
//
/////////////////////////////////////////////////////////////////////////////////////
procedure
Actual call name of the procedure. Use mixed case to emphasize procedure
names like GetString instead of get_string.
parameters
Describe the registers or data passed into this procedure from the calling procedure.
returns
List any data being sent to the calling procedure upon termination of this procedure.
description
This should explain in detail the function of this procedure. Don't explain exactly
how the procedure performs what you claim it can do, just explain what it does.
How should be expressed in the procedure in comments.
If a C program has only main, then there is no need for a procedure header.
This is the only case when this is allowed simply because main is self explanatory.
Naming Convention
.
constants
Constants should be all capitalized, such as NULL, PI, or
CR.
procedure
names
Procedure names should use mixed case whenever
possible, such as GetString, Sum, or ComputeAvg.
local variables
Local variables should be all lower case, such as sum,
count, total, or value
globals
Globals should be proceeded by a _, such as _TRYTYPE,
_BUFFER, or _STARTVALUE.
Lab 2
ECE L 273
Goal
• Write Assembly Language code to evaluate
expressions like:
int a,b,c,d,e;
a = ((b + c) - (d + e)) - 10;
• Learn about:
– Variables
– Registers
– Assembly instructions.
Assembly Language Programming
• Program = Data + Control Instructions
• Instructions can perform only one
computation at a time. For example:
– ADD : Add two numbers
– MOV: Move data from one location to another
– CMP: Compare two values
• Data
– Registers
– Memory
Functional Abstraction
Registers
Memory
ALU
Format of Instructions
label: mnemonic operand1, operand2 /* comment*/
Example
movl
%eax,
%ebx
• Label
– Is used to indicate address of instruction
– It is optional. Not every instruction needs to have it.
• Mnemonic
– Specifies the instruction or command
• Operand1, Operand2
–
–
–
–
Identify the data on which the instruction operates
Not all instructions have both the operands.
Operand1 is the Source and Operand2 is the Destination.
Atleast one operand has to be a register.
• Comment
– Is used optionally to convey the meaning associated with the instruction
Data - Registers
These eight registers are available
for storing operands and pointers.
Data – Memory (variables)
int a = 10;
Assembler
Directive
Variable
Name
.comm a,
movl $10,
Constant
Value
Number of
bytes
4
a
a:
Variable
Name
.int
Data
Type
10
Initialization
Value
Datatypes
• Byte (8 bits)
a: .char ‘s’
movb a, %bl
addb $10, %bl
• Word (16 bits)
a: .short 10
movw, a, %bx
subw $10, %bx
• Long (32 bits)
a: .int
100
movl
a, %ebx
mull
%ebx
Expression Evaluation
• a = ((b + c) - (d + e)) - 10;
– Evaluate ( b + c )
• Store result in Register (EAX)
– Evaluate ( d + e)
• Store result in another Register (EBX)
– Evaluate ( b + c ) – (d + e )
• Subtract EBX from EAX
• Store result by overwriting EAX
– Evaluate ( b + c ) – (d + e ) – 10
• Subtract 10 from EAX
• Store result by overwriting EAX
– Store result back to variable a
movl
addl
b,
c,
%eax
%eax
movl
addl
d,
e,
%ebx
%ebx
subl %ebx, %eax
subl
$10, %eax
movl %eax,
a
Multiplication
a:
b:
movl
mull
.int
.int
a,
10
20
16bit
=
8bit
*
8bit
32bit
=
16bit
*
16bit
64bit
=
32bit
*
32bit
%eax
b
Implicitly
specified
Explicitly
specified
Implicitly
specified
Division (Quotient & Remainder)
a:
b:
.int
.int
movl $0,
movl a,
divl
10
20
%edx
%eax
IMPORTANT
b
Output 1
Implicitly
specified
Implicitly
specified
Output 2
Implicitly
specified
Assignment
int digit1, digit2, digit3;
int diff;
int sum;
int product;
int remainder;
Implement using Assembly Programming
dodiff() {
diff = (digit1 * digit1) + (digit2 * digit2) - (digit3 * digit3);
}
dosumprod() {
sum = digit1 + digit2 + digit3;
product = digit1 * digit2 * digit3;
}
doremainder() {
remainder = product % sum;
}
Template
.globl dodiff
.type dodiff, @function
.globl dosumprod
.type dosumprod, @function
.globl doremainder
.type doremainder, @function
dodiff:
dosumprod :
doremainder :
/* prolog */
pushl %ebp
pushl %ebx
movl %esp, %ebp
/* prolog */
pushl %ebp
pushl %ebx
movl %esp, %ebp
/* prolog */
pushl %ebp
pushl %ebx
movl %esp, %ebp
/* put code here */
/* put code here */
/* put code here */
/* epilog */
movl %ebp, %esp
popl %ebx
popl %ebp
ret
/* epilog */
movl %ebp, %esp
popl %ebx
popl %ebp
ret
/* epilog */
movl %ebp, %esp
popl %ebx
popl %ebp
ret
Assignment – Due in 2 weeks
Lab 3
ECE L 273
Goal
• Write Assembly language instructions similar
to following Control Statements:
int a, b;
if (a > b)
{
... code block 1 ...
} else
{
... code block 2 ...
}
int i;
for (i = 0; i < 100; i++)
{
... code block 1 ...
}
int i;
do
{
... code block 1 ...
} while(--i);
Control Statements
• Without control statements all the assembly
instructions are executed sequentially (one after
the other)
• Non-trivial programs require
– Conditional execution of code
– Repetitive execution of same part code
• Typical control structures available in High level
languages are
– If-else
– For loop
– switch
Control Structures in Assembly
• Control structures are not directly available in
assembly language programming
• Support for implementing the control
structures is provided using
– special register (EFLAGS),
– side-effects,
– conditional jumps (jle, jng, …)
EFLAGS
• EFLAGS is a 32-bit register with specific
meaning assigned to bits within it. A bit within
this register represents status of a flag.
• Example Flags:
– CF: Carry/Borrow
– PF: Parity
– ZF: Zero Flag
– SF: Sign Flag
Side Effects and EFLAGS
• When an assembly instruction is executed, the
result value determines what flags are set in
EFLAGS register (side effects).
– If the result is zero, ZF is set to 1
– If the result is negative, SF is set to 1
– And so on …
• These changes are considered side effects as
EFLAGS is not explicitly specified as operand for
the assembly instructions.
• Conditional jumps use side effects to determine
which path within the program should be taken.
Example
if ( a > b )
{
c = 10;
}
d = 20;
Causes Side-Effect
by setting flags
like ZF or SF in
EFLAGS
Checks the
EFLAGS
and decides
whether or not to
jump to
instruction at label
lbl_skip.
If the jump
doesn’t take place
then the
immediately
following
instruction in
executed
movl a, %eax
cmpl b, %eax
jng
lbl_skip
movl $10, c
lbl_skip: movl $20, d
if-else construct
Option 1 is preferred as it maintains the statement sequence as in it’s C equivalent.
Also, it is easier to write nested if-else statements with option1.
if ( a > b )
{
s1
s2
}else
{
s3
s4
}
s5
s6
Option 1
movl a, %eax
cmpl b, %eax
jng lbl_else
s1
s2
jmp lbl_more
lbl_else: s3
s4
lbl_more: s5
s6
Option 2
movl a, %eax
cmpl b, %eax
jg lbl_if
s3
s4
jmp lbl_more
lbl_if:
s1
s2
lbl_more: s5
s6
if ( a > b )
{
s1
s2
if (c > d)
{
s3
s4
}
s5
s6
}else
{
s7
s8
}
s9
s10
Nested if-else
First, write code for the
outermost if-else structure
movl a, %eax
cmpl b, %eax
jng lbl_else
.
.
.
jmp lbl_more
lbl_else: s7
s8
lbl_more: s9
s10
Next, fill in the code for the
nested part.
s1
s2
movl c, %eax
cmpl, d, %eax
jng lbl_nest
s3
s4
lbl_nest: s5
s6
For loop
Step1
Step2
Step4
Step1
for ( i = 0;
i < 100;
{
s1
s2
Step3
}
s3
s4
i++ )
movl $0, i
lbl_for:
cmpl $100, i
jnl lbl_more
s1
Step3
s2
inc i
jmp lbl_for
lbl_more: s3
s4
Step2
Step4
loop statement
int i;
do
{
s1
s2
} while( --i );
s3
s4
movl i, %ecx
lbl_do:
s1
s2
loop lbl_do
lbl_more: s3
s4
Only %ecx can
be used as
counter register
Every time loop instruction is
executed, %ecx is auto-decremented
by 1 (one).
The loop breaks when %ecx reaches zero.
Assignment – Due in 2 weeks
Lab 4
ECE L 273
Goal
• Write Assembly language instructions for
handling Arrays and Pointers:
int a[10];
int i = 2;
main()
{
a[0] = 10;
int a[10];
int *ap;
int i = 3;
main()
{
ap = &(a[0]);
a[4] = 20;
ap[3] = 50;
a[i] = 30;
ap[i] = 60;
}
}
Pointers - Review
• Pointer – A variable which contains memoryaddress of another variable.
int x = 1, y = 2;
int *ip;
ip = &x;
y = *ip;
x 7
Addr=100
y 2
Addr=104
ip 100
Addr=108
x 7
Addr=100
y 7
Addr=104
ip 100
Addr=108
Address Arithmetic
Address = 100
Address = 100
Address = 100
char a[10];
short a[10];
int a[10];
char *pa = &a;
short *pa = &a;
int *pa = &a;
pa = pa + 1;
pa = pa + 1;
pa = pa + 1;
Address increments by 1.
pa = 101
Address increments by 2.
pa = 102
Address increments by 4.
pa = 104
Addressing Modes
• Immediate
• Indexed
• Register
• Register Indirect
• Direct
• Base-Indexed
Immediate and Register
Immediate Addressing Mode
Register Addressing Mode
• movl $4, %eax
• movl %eax, %ebx
Data value itself is known at
compile time
Location (Register) of
Data value is known at
compile time
Direct Addressing Mode
C Code
Equivalent Assembly Code
int a[10];
.comm a 40
Address of a is same as
address of a[0]
int i = 2;
i: .int 2
a[0] = 10;
movl $10, a
a[4] = 20;
movl $20, a + 16
Address of a and
Address a + 16 are
known at compile
time.
Indexed Addressing Mode
“ i ” is a
variable and
it’s value
need not be
known at
compile
time.
Address
of a[i] is not
known
during
compilation;
it has to be
calculated at
runtime.
C Code
Equivalent Assembly Code
int a[10];
.comm a 40
int i = 2;
i: .int 2
a[i] = 30;
movl i, %edi
movl $30, a(, %edi, 4)
Two step process:
1. Use %edi as index register
2. Identify address of data as: a + (%edi * 4)
Base Address
Offset in bytes
Register Indirect Addressing
• The address of data is specified in the register
%ebx
int *p;
main()
{
*p = 40;
}
.comm p, 4
int arr[10];
movl arr, %ebx
arr[2] = 20;
movl $20, 8(%ebx)
movl p, %ebx
movl $40, (%ebx)
Identify address of data as: %ebx + 8
Base Indexed Addressing
• Address = BaseAddress + Index*sizeofdata
• BaseAddress is specified by %ebx
• Index is specified by either %esi or %edi
int *ap;
int i;
.comm ap, 4
.comm i, 4
main()
{
ap[i] = 60;
}
movl ap, %ebx
movl i, %edi
movl $60, (%ebx, %edi, 4)
Two step process:
1. Use %edi as index register
2. Identify address of data as: %ebx + (%edi * 4)
Recap
• Immediate
– movl $4, %eax
• Register
– movl %eax, %ebx
• Direct
– movl %eax, a
– movl %eax, a+16
• Indexed
– movl $30, a(, %edi, 4)
• Register Indirect
– movl $40, (%ebx)
• Base-Indexed
– movl $60, (%ebx, %edi, 4)
Assignment – Due in 2 weeks
ECE L 273
Lab 5
Goal
• Write Subroutines in Assembly Language
• Handle Local Variables
subadd ()
{
int a;
a = 10;
a = a + 20;
}
subadd: pushl %ebp
movl %esp, %ebp
subl
$4,
%esp
movl
addl
$10,
$20,
movl
popl
%ebp, %esp
%ebp
ret
-4(%ebp)
-4(%ebp)
Functions And Subroutines
• Help write modular programs
• Pascal, Fortran, Ada
– Function -> returns a value
– Subroutine -> does not return any value
• C
– No distinction made between function and
subroutines
• Assembly subroutine call example
– call subadd
Call Vs Jmp
• Any program label can be a subroutine
• Any label you can “jmp” to can be “call”ed as
subroutine
• Difference
– When you “call” a subroutine, the “return addr” is
saved on a Stack
– After “ret” is executed, the program returns to the
instruction immediately after the “call”
Stack – Push and Pop operation
PUSH
POP
Return Address
96
100
104
108
200
204
208
.
.
.
220
call subadd
mov %eax, %ebx
Push return address (104) onto
the stack and jump to subroutine
subadd at address 200.
subadd:
ret
Pop return address from stack
and start executing from
address 104.
Local Variables
• Allocated on the stack
– Stack Frame
• Recursion
– Each instance of the recursion creates its own
stack frame
• Stack Frame
– Base => %ebp
– Top => %ebp + Total Bytes for Local Variables
Stack Frame – Local Variables
subadd ()
{
int a;
a = 10;
a = a + 20;
}
4 bytes for
local variable
“a”
Stack Frame
%esp
a
%ebp old
Save calling
function’s Stack
Frame base
subadd:
pushl %ebp
movl
subl
%esp, %ebp
$4,
%esp
Establish base of current
Stack Frame
Allocate memory for
local variables. Stack
Frame is created.
movl
addl
$10,
$20,
-4(%ebp)
-4(%ebp)
movl
%ebp, %esp
popl
%ebp
%ebp
ret
Deconstruct “Stack
Frame”. De-allocate
local variables.
Restore calling
function’s Stack
Frame base
Nested Calls
-
Stack Growth
Return Address
of “doubleit”
Return Address
of “main”
main
doubleit
halfit
Assignment – Due in 2 weeks
ECE L 273
Lab 6
Goal
• Pass Parameters to Subroutines
subRtn()
{
int a, b;
a = 10;
b = doubleit(a);
}
doubleit(int num)
{
return 2*num;
}
doubleit: pushl %ebp
movl %esp, %ebp
#Access parameter num
movl 8(%ebp), %eax
mull
$2
movl
popl
ret
%ebp, %esp
%ebp
Parameter Passing
• Registers
– Arguments passed using agreed-upon registers
– Restricted due to number of available registers
• Stack
– Any number and any size arguments
– Caller pushes parameters onto stack before calling
subroutine
– Callee uses offset from %ebp to access
parameters
Using Registers
foo:
pushl %ebp
movl %esp, %ebp
movl
a,
%eax
#Use %eax to pass parameter
call
bar
movl
%ebp, %esp
popl
%ebp
ret
extern int a, b;
foo()
{
bar(a);
}
bar(int p1)
{
b = b + p1;
}
bar:
pushl %ebp
movl
%esp, %ebp
#Use %eax for a
addl
%eax, b
movl
%ebp, %esp
popl
%ebp
ret
Using Stack
extern int a, b, c, d, e;
foo()
{
// Parameters are
// pushed in reverse
// order
e = bar(a, b, c, d);
}
bar()
int p1, p2, p3, p4;
{
return (p1+p2)*(p3+p4);
}
foo:
pushl %ebp
movl %esp, %ebp
#Push parameters on
#stack
pushl d
pushl c
pushl b
pushl a
call
bar
#Remove parameters
#from stack
addl
16,
%esp
#extract return value
movl %eax, e
movl
popl
ret
%ebp, %esp
%ebp
bar:
pushl
movl
pushl
%ebp
%esp, %ebp
%ebx
movl
addl
movl
addl
mull
8(%ebp), %eax
12(%ebp), %eax
16(%ebp), %ebx
20(%ebp), %ebx
%ebx
popl
movl
popl
ret
%ebx
%ebp, %esp
%ebp
Stack – With Parameters
bar:
pushl
movl
pushl
%ebp
%esp, %ebp
%ebx
(%esp)
(%ebp)
%ebx
old %ebp
movl
addl
movl
addl
mull
8(%ebp), %eax
12(%ebp), %eax
16(%ebp), %ebx
20(%ebp), %ebx
%ebx
8(%ebp)
12(%ebp)
16(%ebp)
20(%ebp)
popl
movl
popl
ret
%ebx
%ebp, %esp
%ebp
retAddr_foo
a
b
c
d
older %ebp
Ret Address
Return Value
• Usually using register %eax
• Some languages like C and Modula allow
complex types to be returned.
• Return value is pushed onto the stack and a
pointer is returned in an agreed-upon register.
Assignment – Due in 2 weeks