| CompOrg Spring 2004 Lab |
|   CompOrg Home   |   p1   |   p2   |   p3   |   p4 |
This lab involves making changes to IA32 assembly language programs, compiling, testing and debugging the resulting code.
Exercise 1: factorial subroutine
Write an assembly language factorial subroutine. Here is C code and the corresponding assembly to get you started:
| p1.s | p1.c |
.file "p1.c" .text .globl factorial .type factorial,@function factorial: pushl %ebp movl %esp, %ebp movl $0, %eax leave ret .Lfe1: .size factorial,.Lfe1-factorial .section .rodata .LC0: .string "%d! = %d\n" .align 32 .LC1: .string "You have to give me a number!\n" .text .globl main .type main,@function main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax subl %eax, %esp cmpl $1, 8(%ebp) jle .L3 subl $12, %esp movl 12(%ebp), %eax addl $4, %eax pushl (%eax) call atoi addl $16, %esp movl %eax, -4(%ebp) subl $4, %esp subl $8, %esp pushl -4(%ebp) call factorial addl $12, %esp pushl %eax pushl -4(%ebp) pushl $.LC0 call printf addl $16, %esp jmp .L4 .L3: subl $12, %esp pushl $.LC1 call printf addl $16, %esp .L4: movl $1, %eax leave ret .Lfe2: .size main,.Lfe2-main |
#include <stdio.h>
int factorial(int x) {
return(0); /* This needs to be written in assembly! */
}
int main(int argc, char **argv) {
int num;
if (argc>1) {
num = atoi(argv[1]);
printf("%d! = %d\n",num,factorial(num));
} else {
printf("You have to give me a number!\n");
}
return(1);
}
|
Exercise 2: Strings and a strlen subroutine
Write an assembly language subroutine that returns the length of a string. Some issues:
The address of the first byte will be passed to the subroutine (this is the only parameter).
The number of non-null bytes is the length (the null does not count!).
The suffix 'b' on many IA32 instructions indicates that the instruction operands are each a single byte. There are single byte registers available (%al, %ah are part of %eax, %bl, %bh are part of %ebx, etc). Here are some examples of instructions that deal with bytes:
movb (%eax),%bl # move from address in eax to bl
cmpb $0,(%eax) # compare the byte at address in eax to 0
addb %ah, %al # add ah and al
Try to minimize the number of assembly instructions that will be executed to determine the length of the string!
Below is some C code that might help you test your code (gcc -S to generate assembly):
| p2.c |
#include <stdio.h>
int mystrlen(char *s) {
return(0); /* you need to write this in assembly */
}
int main(int argc, char **argv) {
int num;
if (argc>1) {
printf("length is %d\n",mystrlen(argv[1]));
} else {
printf("You have to give me something!\n");
}
return(1);
}
|
Exercise 3: Arrays
Write an assembly language subroutine that returns the sum of all integers in an array of int. Some issues:
The address of the array (the address of the first int in the array) will be passed to the subroutine as the first parameter (ebp+8), and the number of ints in the array is the second parameter (ebp+12)
In general you compute the address of any array element as the base address (the address of the first element in the array) plus the index times the size of each element. For int you can assume the size is 4.
For this particular subroutine you don't really need to compute the address of each element independently, you can just use a "pointer" (register that holds the address of the next element) and increment it by 4 each time through the loop
Below is some C code that might help you test your code (gcc -S to generate assembly):
| p3.c |
#include <stdio.h>
int asum(int *p,int len) {
return(0); /* you need to write this in assembly */
}
int main(int argc, char **argv) {
int nums[] = { 1,2,3,4,3,2,1 };
printf("Sum is %d\n",asum(nums,sizeof(nums) / sizeof(int)));
return(1);
}
|
Exercise 4: Speed and code size
Write an assembly language subroutine that reverses an array of ints. Prizes awarded in two categories: speed and code size. Code size is measured as the number of instructions in the reverse subroutine (including all standard subroutine overhead).
Below is some test code. The numbers to beat (using the below test code on monte) are:
| Code size: | 13 lines |
|---|---|
| User time: | 0.730 seconds (on monte) |
| p4.c |
#include <stdio.h>
void reverse(int *p,int len) {
/* write this in assembly */
}
#define SIZE 1000
#define LOOPS 1000000
/* expects either a 't or 'l' on the command line
t runs a test (prints the array before and after)
l runs a measureable loop
*/
int main(int argc, char **argv) {
int nums[SIZE];
int i;
for (i=0;i<SIZE;i++) nums[i]=i;
if (*argv[1] == 't') {
printf("Before: ");
for (i=0;i<SIZE;i++) printf("%d ",nums[i]);
printf("\n");
reverse(nums,SIZE);
printf("After: ");
for (i=0;i<SIZE;i++) printf("%d ",nums[i]);
printf("\n");
} else if (*argv[1] == 'l') {
for (i=0;i<LOOPS;i++) {
reverse(nums,SIZE);
}
} else {
printf(" use t to test, l to loop\n");
}
return(1);
}
|