Horstmann Labs

You need to submit a TAR file containing two files: hw21.c and hw22.c. You must solve both problems using inline assembly, and not C, using the outline provided.

Each ... denotes some number of lines of code, not necessarily a single line.

  1. [8 points] Write a program that inverts the 4 bytes of a 32-bit integer and prints out the original and inverted number. For example,

./hw21 1234567890

prints

0x499602d2

0xd2029649

Follow this outline:

#include <stdio.h>

#include <stdlib.h>

 

int m;

int n;

 

int main(int argc, char* argv[])

{

   m = atoi(argv[1]);

   printf("0x%x\n", m);

   __asm__ ("

    movl m, %eax

    andl ...

    shrl ...

    movl %eax,%ecx

    movl m, %eax

    andl ...

    shrl ...

    orl %eax,%ecx

    ...

    ...

    movl %ecx, n

");

   printf("0x%x\n", n);

   return 0;

}

Note: On Windows, you need to prefix variable names inside the __asm__ section with a _.
Note: On Linux, do not use ebx!
Note: To express a hex constant, use $0x..., e.g. $0xCAFE

  1. [8 points] Write a program that receives three inputs from the command line and prints the largest of the three inputs. For example, if the program is executed as

./hw21 123 456 234

the output should be

The maximum is 456

Follow this outline:

int x;

int y;

int z;

int m;

 

int main(int argc, char* argv[])

{

   x = atoi(argv[1]);

   y = atoi(argv[2]);

   z = atoi(argv[3]);

   __asm__ ("

    movl x, %eax

    cmpl y, %eax

    jl ybigger

    ...

    ...

    jmp done

ybigger:

    ...

    ...

    movl %eax, m

done:

");

   printf("Maximum = %d\n", m);

   return 0;

}

 

./hw31 11 34 54 23 22 10 103 25

prints

The maximum is 103

Use the following outline. Fill in as many instructions as necessary at the . . .. Remember: Use _ before global variables inside the __asm__ block in Windows. Only use eax, ecx, edx

#include <stdio.h>

#include <stdlib.h>

 

int a[10];

int m;

 

int main(int argc, char* argv[])

{

   /* move the command-line arguments into a */

   int i;

   for (i = 0; i < argc - 1 && i < 10; i++)

      a[i] = atoi(argv[i + 1]);

   /*

      in the assembly block below,

      eax = current maximum

      ecx = array index

   */

 

   __asm__ ("

    movl a, %eax

    xorl %ecx, %ecx

loop:

    incl %ecx

    cmpl $10, %ecx

    jge done

    . . .

    jmp loop

done:

    movl %eax, m

");

   printf("Maximum = %d\n", m);

   return 0;

}

./hw32 13

prints

array starts at 0x402004

match found at 0x402018

match found at 0x402024

Note: You will get different addresses. But the differences between the array start and the matches should be the same.
Use this outline:

#include <stdio.h>

#include <stdlib.h>

 

int a[10] = { 2, 3, 5, 7, 11, 13, 17, 19, 13, 19 };

 

int main(int argc, char* argv[])

{

   int x = atoi(argv[1]);

   int i;

   int *p;

 

   x = atoi(argv[1]);

   p = a;

   printf("array starts at %p\n", p);

 

   for (i = 0; i < 10; i++)

   {

      /* use only p, *p inside here, not a or i */

      . . .

   }

 

   return 0;

}

Use only the pointer variable p inside the loop, no other variable. This is an exercise in pointers.

  1. Write a program that contains a function to find the first match of a number in an array, and returns a pointer to the match. Use this outline:

2.           #include <stdio.h>

3.            

4.           int a[10] = { 2, 3, 5, 7, 11, 13, 17, 19, 13, 19 };

5.            

6.           /**

7.              Finds the first match of a number in an array

8.              @param a an array

9.              @param n the number of elements in the array

10.          @param x the number to match

11.          @return the location of the first match, or NULL if

12.          there is no match.

13.       */

14.       int* find(int* a, int n, int x)

15.       {

16.          . . .

17.       }

18.        

19.       /**

20.          Prints all elements of an array

21.          @param a an array

22.          @param n the number of elements in the array

23.       */

24.       void print(int* a, int n)

25.       {

26.          int i;

27.        

28.          for (i = 0; i < n; i++)

29.          {

30.             printf("%d ", *a);

31.             a++;

32.          }     

33.          printf("\n");

34.       }

35.        

36.       int main()

37.       {

38.          int x;

39.          int* q;

40.        

41.          printf("Enter x:\n");

42.          scanf("%d", &x);

43.          q = find(a, 10, x);

44.          if (q != NULL) *q = 0;

45.          print(a, 10);

46.       }

That is, your program should accept an input from stdin and search for that value in the array a. Then it should set the found value to 0 and print the array. If no match was found, the original array is printed.
Sample run: (user input in green)

./hw41

Enter x:

13

2 3 5 7 11 0 17 19 13 19

  1. Write a program that reads two strings from stdin, concatenates them, and counts how many times the resulting string contains the substring "is". Use the strcpy, strcat, and strstr functions.
    Sample run: (user input in green)

48.       ./hw42

49.       Enter first string:

50.       missi

51.       Enter second string:

52.       ssippi

53.       2

 

The answer is 2 because the concatenated string has two occurrences of is: mississippiUse this outline:

#include <stdio.h>

#include <string.h>

 

int main()

{

   char a[21];

   char b[21];

   char c[41];

   char* p;

   int count;

 

   printf("Enter first string:\n");

   scanf("%20s", a);

   printf("Enter second string:\n");

   scanf("%20s", b);

 

   /* concatenate strings into c */

 

   . . .

   p = c;

   count = 0;

   while (p != NULL)

   {

      /* call strstr ... */

      . . .

   }

   printf("%d\n", count);

   return 0;

}

  1. Write the main function of the following program entirely in assembly. First call printf to prompt the user, then call scanf to read the user input, then call strrev to reverse the string, then call printf to print the reversed string. One sample call is supplied; you need to supply the remaining three. Example program run:
2.           ./hw51
3.           Enter a string:
4.           Hello
The reverse is: olleH

Use this program outline:

#include <stdio.h>
 
char original[81];
char reversed[81];
char fmt1[17] = "Enter a string:\n";
char fmt2[5] = "%80s";
char fmt3[20] = "The reverse is: %s\n";
 
/**
   Computes the reverse of a string
   @param a the address of an array of characters to reverse
   @param b the address of the array into which to place the
   reversed string
*/
void strrev(char a[], char b[])
{
   char* p = a;
   while (*p != 0) p++;
   while (p > a)
   {
      p--;
      *b = *p;
      b++;      
   }
   *b = '\0';
}     
 
int main(int argc, char* argv[])
{
   __asm__("
 . . .
 pushl $original
 pushl $fmt2
 call scanf
 addl $8, %esp
 . . .
");
}

As usual, add _ in Windows.

  1. For the second program, write the strrev function in assembly.
6.           #include <stdio.h>
7.            
8.           char original[81];
9.           char reversed[81];
10.        
11.       /**
12.          Computes the reverse of a string
13.          @param a the address of an array of characters to reverse
14.          @param b the address of the array into which to place the
15.          reversed string
16.       */
17.       void strrev(char a[], char b[])
18.       {
19.          __asm__("
20.          . . .
21.       ");
22.       }     
23.        
24.       int main(int argc, char* argv[])
25.       {
26.          printf("Enter a string:\n");
27.          scanf("%80s", original);
28.          strrev(original, reversed);
29.          printf("The reverse is: %s\n", reversed); 
30.       }