Você está na página 1de 11

CS220

March 5, 2007
Recursion
unsigned long factorial (unsigned long i) .globl factorial
{ .type factorial, @function
factorial:
unsigned long f=1; pushl %ebp
if (i != 0) movl %esp, %ebp
subl $4, %esp
f=i * factorial(i-1);
movl $1, -4(%ebp)
return f; cmpl $0, 8(%ebp)
} je done
movl 8(%ebp), %eax
decl %eax
pushl %eax
call factorial
addl $4, %esp
factorial (3) = 3 * factorial(2)
imull 8(%ebp), %eax
= 3 * (2 * factorial(1)) movl %eax, -4(%ebp)
= 3 * (2 * (1 * factorial(0))) done:
movl -4(%ebp), %eax
= 3 * (2 * (1 * 1)))
leave
=6 ret
EAX saves returned value
.size factorial, .-factorial
.section .rodata
main(){ .LC0:
.string "%u\n"
unsigned long i=0; .text
.globl main

i=factorial(5); main:
.type main, @function

pushl %ebp
printf("%u\n", i); movl %esp, %ebp
subl $4, %esp
} movl $0, -4(%ebp)
pushl $5
call factorial
addl $4, %esp
movl %eax, -4(%ebp)
pushl -4(%ebp)
pushl $.LC0
call printf
addl $8, %esp
leave
ret
.size main, .-main
Printf
int printf( const char *format [, argument]... );

Writes to the standard output (stdout) a


sequence of data formatted as the format
argument specifies. After the format parameter,
the function expects at least as many additional
arguments as specified in format.

More details at this link:


http://www.cplusplus.com/reference/clibrary/cstdio/printf.html
Printf format specifiers
%c The character format specifier.
%d The decimal integer format specifier.
%i The decimal integer format specifier (same as %d).
%f The floating-point format specifier.
%e The scientific notation format specifier.
%E The scientific notation format specifier.
%g Uses %f or %e, whichever result is shorter.
%G Uses %f or %E, whichever result is shorter.
%o The unsigned octal format specifier.
%s The string format specifier.
%u The unsigned integer format specifier.
%x The unsigned hexadecimal format specifier.
%X The unsigned hexadecimal format specifier.
%p Displays the corresponding argument that is a pointer.
%% Outputs % itself.
Printf format
%[flags][width][.precision][length]specifier
Flags:
- Left justify.
0 Field is padded with 0's instead of blanks.
+ Sign of number always O/P.
blank Positive values begin with a blank.
# Various uses:
%#o (Octal) 0 prefix inserted.
%#x (Hex) 0x prefix added to non-zero values.
%#X (Hex) 0X prefix added to non-zero values.
%#e Always show the decimal point.
%#E Always show the decimal point.
%#f Always show the decimal point.
%#g Always show the decimal point trailing
zeros not removed.
%#G Always show the decimal point trailing
zeros not removed.
Examples
#include <stdio.h>
int main()
{
printf ("Characters: %c %c \n", 'a', 65);
printf ("Decimals: %d %d\n", 1977, 650000);
printf ("Preceding with blanks: %10d \n", 1977);
printf ("Preceding with zeros: %010d \n", 1977);
printf ("Some different radixes: %d %x %o %#x %#o \n", 100, 100, 100, 100, 100);
printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);
printf ("Width trick: %*d \n", 5, 10);
printf ("%s \n", "A string");
return 0;
}

Output:

Characters: a A
Decimals: 1977 650000
Preceding with blanks: 1977
Preceding with zeros: 0000001977
Some different radixes: 100 64 144 0x64 0144
floats: 3.14 +3e+000 3.141600E+000
Width trick: 10
A string
Using Printf in Assembly
.LC0:
.string "eax: 0x%.8X\tebx: 0x%.8X\tecx: 0x%.8X\tedx: 0x%.8X\n"
.LC1:
.string “total is %d\n“
total:
.long 333

pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
pushl $.LC0
call printf
addl $20, %esp

pushl total
pushl $.LC1
call printf
addl $8, %esp
Variable argument functions
• Printf can take variable arguments.
• How does it do?
– char * format determines number and type of
variables
• How to do it in your own function?
– Must have first argument fixed
– First argument provides information about all
other arguments
Variable Parameters in C
#include <stdio.h>
#include <stdarg.h> #include <stdarg.h>

int sum( int num, ... ) { type va_arg( va_list argptr, type );
int answer = 0; void va_end( va_list argptr );
va_list argptr;
va_start( argptr, num ); void va_start( va_list argptr, last_parm );
for( ; num > 0; num-- ) {
answer += va_arg( argptr, int );
} typedef char* va_list;
va_end( argptr );
return answer; #define va_start(list) list = (char*)&va_alist
}
#define va_end(list)

int main( void ) { #define va_arg(list, mode)\

int answer = sum( 4, 4, 3, 2, 1 ); ((mode*) (list += sizeof(mode)))[-1]


printf( "The answer is %d\n", answer );
return 0 ;
}
How to do it in assembly?
.text .section .rodata
.globl sum .LC0:
.type sum, @function .string "The answer is %d\n"
sum: .text
pushl %ebp .globl main
movl %esp, %ebp .type main, @function
subl $4, %esp main:
pushl %ecx pushl %ebp
pushl %edx movl %esp, %ebp
movl $0, -4(%ebp) subl $8, %esp
movl 8(%ebp), %ecx pushl $1
next: pushl $2
cmpl $0, %ecx pushl $3
jle done pushl $4
movl 8(%ebp, %ecx, 4), %edx pushl $4
addl %edx, -4(%ebp) call sum
decl %ecx addl $20, %esp
jmp next pushl %eax
done: pushl $.LC0
popl %edx call printf
popl %ecx addl $8, %esp
movl -4(%ebp), %eax movl $0, %eax
leave leave
ret ret
.size sum, .-sum .size main, .-main

Você também pode gostar