C - Division from scratch
It is unclear what toolchain do you use and what is target processor. However, I can guess about performance degradation. pow function usually works with floating point values. Moreover, most probably power with negitive exp will also use division.
I compiled following code with ARM gcc 8.2 with -O3 flag:
#include &lt;math.h&gt;

int idiv(int a, int b) {
    return a * (pow(b, -1));
}

int idiv2(int a, int b) {

    return a/b;
}

I've got following assebly listing:
idiv:
        push    {r4, r5, r6, lr}
        mov     r6, r0
        mov     r0, r1
        bl      __aeabi_i2d
        mov     r2, r0
        mov     r3, r1
        mov     r0, #0
        ldr     r1, .L4
        bl      __aeabi_ddiv
        mov     r4, r0
        mov     r0, r6
        mov     r5, r1
        bl      __aeabi_i2d
        mov     r2, r0
        mov     r3, r1
        mov     r0, r4
        mov     r1, r5
        bl      __aeabi_dmul
        bl      __aeabi_d2iz
        pop     {r4, r5, r6, pc}
.L4:
        .word   1072693248
idiv2:
        push    {r4, lr}
        bl      __aeabi_idiv
        pop     {r4, pc}

From assebly code the reson of performance problems is obvious. And we still dependent on ABI.
If you want to have code that uses only assebly instructions? then you can implement integer division with &quot;shift and subtract&quot;. Or you can google for some open source implementation of it. For example I found one here. Here is slightly modified example from here:
void unsigned_divide(unsigned int dividend,
             unsigned int divisor,
             unsigned int *quotient,
             unsigned int *remainder )
{
  unsigned int t, num_bits;
  unsigned int q, bit, d;
  int i;

  *remainder = 0;
  *quotient = 0;

  if (divisor == 0)
    return;

  if (divisor &gt; dividend) {
    *remainder = dividend;
    return;
  }

  if (divisor == dividend) {
    *quotient = 1;
    return;
  }

  num_bits = 32;

  while (*remainder &lt; divisor) {
    bit = (dividend &amp; 0x80000000) &gt;&gt; 31;
    *remainder = (*remainder &lt;&lt; 1) | bit;
    d = dividend;
    dividend = dividend &lt;&lt; 1;
    num_bits--;
  }

  /* The loop, above, always goes one iteration too far.
     To avoid inserting an &quot;if&quot; statement inside the loop
     the last iteration is simply reversed. */
  dividend = d;
  *remainder = *remainder &gt;&gt; 1;
  num_bits++;

  for (i = 0; i &lt; num_bits; i++) {
    bit = (dividend &amp; 0x80000000) &gt;&gt; 31;
    *remainder = (*remainder &lt;&lt; 1) | bit;
    t = *remainder - divisor;
    q = !((t &amp; 0x80000000) &gt;&gt; 31);
    dividend = dividend &lt;&lt; 1;
    *quotient = (*quotient &lt;&lt; 1) | q;
    if (q) {
       *remainder = t;
     }
  }
}  /* unsigned_divide */

#define ABS(x)  ((x) &lt; 0 ? -(x) : (x))

void signed_divide(int dividend,
           int divisor,
           int *quotient,
           int *remainder )
{
  unsigned int dend, dor;
  unsigned int q, r;

  dend = ABS(dividend);
  dor  = ABS(divisor);
  unsigned_divide( dend, dor, &amp;q, &amp;r );

  /* the sign of the remainder is the same as the sign of the dividend
     and the quotient is negated if the signs of the operands are
     opposite */
  *quotient = q;
  if (dividend &lt; 0) {
    *remainder = -r;
    if (divisor &gt; 0)
      *quotient = -q;
  }
  else { /* positive dividend */
    *remainder = r;
    if (divisor &lt; 0)
      *quotient = -q;
  }

} /* signed_divide */

You can take any, verify it and optimize it according to your needs. Generalized functions are usually more complicated than specialized.