2

I am trying to write some inline assembly into C. I have two arrays as input, what I need is to copy one element in array1 into array2, and the following is what I have at the moment:

asm (
 "movl %0,%%eax;"
 "movl %1,%%ebx;"
 "movl (%%eax),%%ecx;"
 "movl %%ecx,(%ebx);"

 "xor %%ecx,%%ecx;"
 "movl 4(%%eax),%%ecx;"
//do something on %ecx
 "movl %%ecx,4(%ebx);"  //write second
 :
 :"a"(array1),"b"(array2)
);

Why do I get a segmentation fault?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
user200340
  • 3,301
  • 13
  • 52
  • 74
  • 1
    Let the parser work, stop adding the HTML pre tag -- you are dropping the highlighting that SO does. – Jed Smith Nov 01 '09 at 00:26
  • 4
    Are you just copying one element from an array into another array? That doesn't seem like the kind of thing assembly optimisation is going to help with. – Carl Norum Nov 01 '09 at 00:29
  • 2
    You should add a little more detail about why you want to do this in assembly, or you'll just get lots of "why bother?" answers. – Mark Bessey Nov 01 '09 at 00:42
  • Can you tell which line is giving you the segmentation fault? – boiler96 Nov 01 '09 at 04:22

3 Answers3

8

Your inline assembler code is broken. You can't directly use EAX and EBX without adding them to the clobber list. Otherwise the compiler does not know which registers have been modified.

It is very likely that one of the registers that you've modified contained something damn important that later caused the segmentation fault.


This code will copy one element from array1 to array2:

asm (
 "movl (%0), %%eax \n\t" /* read first dword from array1 into eax */
 "movl %%eax, (%1) \n\t" /* write dword into array2
 : /* outputs */
 : /* inputs */ "r"(array1),"r"(array2)
 : /* clobber */ "eax", "memory"
);

A better version with proper register constraints would drop the hard coded EAX like this:

int dummy;
asm (
 "movl (%1), %0 \n\t"
 "movl %0, (%2) \n\t"
 : /* outputs, temps.. */ "=r" (dummy) 
 : /* inputs */           "r"(array1),"r"(array2)
 : /* clobber */          "memory"
);

Btw - In general I have the feeling that you're not that familiar with assembler yet. Writing inline-assembler is a bit harder to get right due to all the compiler magic. I suggest that you start writing some simple functions in assembler and put them into a separate .S file first.. That's much easier..

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Nils Pipenbrinck
  • 83,631
  • 31
  • 151
  • 221
  • Thank, This is exactly what i need. i only know some MIPS32 and MIPS64 instructions,this is my first time to write inline assembly. Btw, I think movl instruction in AT&T is movl source,destination so read first dword from array1 into eax should be "movl (%0), %%eax \n\t" is it right? – user200340 Nov 01 '09 at 21:12
  • Could be.. I always try to avoid this AT&T Syntax.. The intel syntax is imho much cleaner.. – Nils Pipenbrinck Nov 02 '09 at 00:48
  • Yes, AT&T syntax is `source`, `dest` - I've made that minor correction. – caf Nov 02 '09 at 05:13
  • 1
    Just for the record, using either of those in a loop would be correct but total garbage for performance, especially for data hot in cache. The compiler couldn't unroll with addressing modes like `4(%rdi)` because your asm constraints force it to materialize the exact pointer values in registers ([Looping over arrays with inline assembly](https://stackoverflow.com/q/34244185)). And most importantly, you're only copying 4 bytes at a time, not 16 or 32 with XMM or YMM regs! Even `rep movsd` (fast-strings microcode) will be better than 4-byte-at-a-time for any but the smallest arrays. – Peter Cordes Aug 08 '20 at 01:00
3

Your best option is C code:

target_array[target_idx] = source_array[source_idx];

This avoids segmentation faults as long as the indexes are under control.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

what about memcpy ?

Illarion Kovalchuk
  • 5,774
  • 8
  • 42
  • 54