0

I have to write some asm("code") in C using CodeBlocks. I need to increment input value 'a' by one and then power the result like this a * a * a. Where incrementing and power value a*a is easy, the another power powers the result of previous power. For ex. 2 * 2=4 then 4 * 4=16 My current code:

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


int main(){
short int a,b;
scanf("%hu",&a);
asm("mov %1, %%ax\n\t"
    "inc %%ax\n"
    "mul %%ax\n"
    "mov %%ax, %0"
    :"=r" (a)
    :"r" (a), "r" (b)
    );
    printf("%d\n", a);
    return 0;
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Side note: *Always* check the result of scanf to know if input has been valid (`if(scanf(...) == n)` where `n` is the number of parameters scanned, in your case 1). – Aconcagua Jun 13 '21 at 09:58
  • This is really inefficient (wasted `mov` instructions instead of just asking for the input in AX with `"+a"(a)`). And you don't tell the compiler that you modified AX (missing an `"ax"` clobber). – Peter Cordes Jun 13 '21 at 09:59
  • 1
    And there's no reason to use 16-bit operand-size: even if you only want the low 16 bits eventually, you can use 32 bit operand size without any problem. And you don't need widening `mul` that writes to DX:AX (or EDX:EAX), if you don't need the (E)DX high half result. So you can use `imul %1, %0` after copying to the register the compiler wants the result in. That should make it even more obvious how to multiply again by the original value. (Although if you need `(a+1) * (a+1) * (a+1)`, you'll need to keep `a+1` somewhere, so you need one clobber or a dummy output or RMW operand.) – Peter Cordes Jun 13 '21 at 10:00
  • In any case, 16 bit is too small to hold result of most input. Is it your intention to drop the more significant bytes? Otherwise you might prefer 32 bit (likely `int` on your system) or even 64 bit (`long` on linux or `long long` on both linux and windows). You'd have to prefix your registers with `e` (32 bit) or `r` (64 bit). – Aconcagua Jun 13 '21 at 10:29
  • You will need to implement a loop in between `inc` and `mul`, comparing `b` to 0 and on equality jump (`je`) to a label in front of the final `mov`, then after the multiplication decrement `b` and jump unconditionally (`jmp`) back to your loop label in front of the comparison. – Aconcagua Jun 13 '21 at 10:46

1 Answers1

0

Not the best or simplest or cleanest way but this works for me. It add 1 to input value and then do power the value 2 times.

#include <stdio.h>
#include <stdlib.h>
int main(){
int a, b,c=1;
scanf("%i",&a);
asm( "addl %%ebx, %%eax;" : "=a" (a) : "a" (a) ,  "b" (c) );
asm( "imul %%ebx, %%eax;" : "=a" (b) : "a" (a) ,  "b" (a) );
asm( "imul %%ebx, %%eax;" : "=a" (b) : "a" (a) ,  "b" (b) );
printf("%d\n", b);
return 0;
}