Advertisement
ayangd

memcpyrev.c

Dec 23rd, 2019
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.40 KB | None | 0 0
  1. void* memcpyrev(void* dest, void* src, int n) {
  2.     // All instructions can be googled by searching "x86 <instruction name>"
  3.     asm (   // Instructions are meant for x86 cpus, not x86_64.
  4.         "movl %0, %%edi\n\t"
  5.         "movl %1, %%esi\n\t"
  6.         "movl %2, %%ecx\n\t"
  7.         "decl %%ecx\n\t"
  8.         "addl %%ecx, %%edi\n\t"
  9.         "addl %%ecx, %%esi\n\t"
  10.         "incl %%ecx\n\t"
  11.         "std\n\t"
  12.         "rep movsb\n\t"
  13.         "cld\n\t"
  14.         "incl %%edi\n\t"
  15.         "movl %%edi, %%eax" // return
  16.         : // No output
  17.         : "g" (dest), "g" (src), "g" (n) // Inputs
  18.         : "%eax", "%ecx", "%esi", "%edi" // Clobbered registers
  19.     );
  20.     /*
  21.     // Move variables from stack to registers for fast execution, since using registers for instruction is faster than fetching the value from memory again and again.
  22.     // edi = destination register, esi = source register, ecx = count register
  23.     register void* dest_reg = dest, src_reg = src, count = n;
  24.     // Decrease count for pointer correction
  25.     count--;
  26.     // Move the source and destination pointer to the end of the copying memory block
  27.     dest_reg += count;
  28.     src_reg += count;
  29.     // Increase count to fix the counting
  30.     count++;
  31.     // Set the direction flag so that the string instruction moves the pointer backward
  32.     // asm ("std\n");
  33.     // This is where the optimization goes
  34.     for (;count != 0; count--) {    // rep instruction prefix substitution
  35.         *dest_reg = *src_reg;   // movsb string instruction substitution
  36.         dest_reg--;
  37.         src_reg--;
  38.     }
  39.     // rep means do the string instruction (movsb) repeatedly until ecx (count) is 0. Each execution decreases ecx (count) by 1
  40.     // movsb means move (copy) the value from the source memory to destination memory, byte by byte.
  41.     //  But on each execution, increase/decrease the source and destination pointer by 1, according to the direction flag.
  42.     //  If direction flag is set (1), the pointers decreases.
  43.     //  If direction flag is cleared (0), the pointers increases.
  44.     // Note that the rep instruction is not affected by the direction flag.
  45.     // The code above will do a lot of work while the assembly version will work quickly, and when compiled, the assembly version will be smaller.
  46.  
  47.     // Clear the direction back so everything else will work as usual again.
  48.     // asm ("cld\n");
  49.     // Fix the destination register
  50.     dest_reg++;
  51.  
  52.     // Return the destination pointer
  53.     return dest_reg;
  54.     // This is converted as:
  55.     // eax = dest_reg;
  56.     // where eax is an accumulator register, usually used to store function return value.
  57.     */
  58. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement