Creating a c file that creates an assembly file that multiplies by constant

0

this question is a follow up to: Finding an efficient shift/add/LEA instruction sequence to multiply by a given constant (avoiding MUL/IMUL) I'm learning assembly and I encountered this exercise: I need to write a c file that receives as argument (argv[1]) an integer number that is a constant that we should multiply by, and the c file creates an assembly file that multiplies some parameter x (received in %rdi) in that constant. It should be efficient in terms of lines of assembly code and follow these rules:

1) if k is 0,1,-1 no need to multiply (obviously)
2) if k is 3,5,9 I then need to replace the multiplication command in LEA.
3) if k is 3*2^n, 5*2^n, 9*2^n then I need to replace the multiplication command in LEA and shifting.
4) all other cases suppose to work also of course.

The automatic checker tells me my code is not efficient enough for some reason although it does produce the right results (at least from what I've checked) so can anyone please help me and tell me how to reduce the assembly lines in the file that is created by my code?

My code:

#include <stdio.h>
#include <stdlib.h>
#include<stdbool.h>
#include<math.h>

int charToInt(const char * c);
unsigned charToUnsigned(const char * c);

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

  char *p;
  FILE * fPtr;
  fPtr = fopen("mult.s", "w");

  fputs( ".section .text\n", fPtr );
  fputs( ".globl   mult\n", fPtr );
  fputs( "mult:  \n", fPtr );

  int k = charToInt(argv[1]);
  if (k == 0) {
    fputs("\txor\t%eax,%eax\n", fPtr);
  } else if (k == 1) {
    fputs("\tmov\t%edi,%eax\n", fPtr);
  } else if (k == -1) {
    fputs("\tmov\t%edi,%eax\n", fPtr);
    fputs("\tneg\t%eax\n", fPtr);
  }
  else if(k==3)
  {
    fputs("\tleal\t(%edi,%edi,2),%eax\n", fPtr);
  }
  else if(k==5)
  {
    fputs("\tleal\t(%edi,%edi,4),%eax\n", fPtr);
  }
  else if(k==9)
  {
    fputs("\tleal\t(%edi,%edi,8),%eax\n", fPtr);
  } else {
    int count_zeros = __builtin_ctz(k);//check the number of zeros
    int arg = k >> count_zeros;
    if (arg == 3){
      fputs("\tleal\t(%edi,%edi,2),%eax\n", fPtr);
      fputs("\tshl\t$", fPtr);
      fprintf(fPtr, "%d,", count_zeros);
      fputs("%eax\n", fPtr);
    }
    else if (arg == 5){
      fputs("\tleal\t(%edi,%edi,4),%eax\n", fPtr);
      fputs("\tshl\t$", fPtr);
      fprintf(fPtr, "%d,", count_zeros);
      fputs("%eax\n", fPtr);
    }
    else if (arg == 9){
      fputs("\tleal\t(%edi,%edi,8),%eax\n", fPtr);
      fputs("\tshl\t$", fPtr);
      fprintf(fPtr, "%d,", count_zeros);
      fputs("%eax\n", fPtr);
    } else {
      fputs("\txor\t%eax, %eax\n", fPtr);
      int l = 0;
      int i;
      for(i=0; i<32;i++)
      {
        l = k >> i;
        l = l & 0x00000001;

        if (l == 1) {
          if (i==0)
          {
            fputs("\tmov\t%edi,%eax\n", fPtr);
          }
          if(i>0 && i<31)
          {
            fputs("\tmov\t%edi,%edx\n", fPtr);
            fputs("\tshl\t$", fPtr);
            fprintf(fPtr, "%d,", i);
            fputs("%edx\n", fPtr);
            fputs("\tadd\t%edx, %eax\n", fPtr);
          } else if (i == 31){
            fputs("\tmov\t%edi,%edx\n", fPtr);
            fputs("\tshl\t$", fPtr);
            fprintf(fPtr, "%d,", i);
            fputs("%edx\n", fPtr);
            fputs("\tsub\t%edx, %eax\n", fPtr);
          }
        }

      }
    }

  }

  fputs("\t\tret\n", fPtr);
  fclose(fPtr);

  return 0;
}
unsigned charToUnsigned(const char * c) {
  char p = *c;
  unsigned arg = 0;
  while (p) {
    arg = arg * 10 + (p - '0');
    c++;
    p = *c;
  }
  return arg;
}

int charToInt(const char * c) {
  return (*c == '-') ? -charToUnsigned(c+ 1) : charToUnsigned(c);
}

Test code to run:

#include <stdio.h>
extern int mult(int);
int main ()
{
    int k, x;
    printf ("Enter k and x: ");
    scanf ("%d %d", &k, &x);
    printf("\nUsing k * x:\n");
    printf ("%d * %d = %d\n", k, x, k * x);
    printf("\nUsing mult(%d):\n", x);
    printf ("%d * %d = %d\n", k, x, mult(x));
    return 0;
}

Thanks!

assembly
x86-64
asked on Stack Overflow Dec 13, 2019 by Blur • edited Dec 13, 2019 by Jester

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0