SO I am working on writing an inline assembly function in c that reverses that contents of a string and puts the reversed string in a new character array, but I am getting extra characters added to the end of my reversed string.
int main(int argc, char **argv) {
char *new_str;
char old_str[20] = "Hello, World!";
mystrrev(new_str, old_str, strlen(old_str));
printf("New string: %s\n", &new_str);
return 0;
}
Assembly function
char *mystrrev(char *dest, const char *src, int size) {
int d0, d1, d2, d3;
__asm__ (
"add %%ebx, %%esi\n\t" /*Move to end of string*/
"std\n\t" /*Decrement esi after load*/
"lodsb\n\t" /*Load esi into al*/
"sub $1, %%ebx\n\t"
"mov %%al, %%cl\n\t" /*mov contents of al to cl*/
"1:\tstd\n\t" /*Begin loop, decrement esi after load*/
"lodsb\n\t" /*Load esi into al*/
"cld\n\t" /*Clear flg*/
"stosb\n\t" /*Store al in edi*/
"sub $1, %%ebx\n\t" /*subtract 1 from strlenght counter*/
"cmp $0, %%ebx\n\t" /*Compare ebx to 0*/
"jne 1b\n\t"
"mov %%ecx, %%edi\n\t" /*Add null terminating char to new str*/
: "=&S"(d0), "=&D"(d1), "=&a"(d2), "=&b" (d3) /*output*/
/*** &S --> ESI, &D --> EDI, &a --> eax ***/
: "0" (src), "1" (dest), "3" (size) /*input*/
: "memory"); /*clobber registers*/
return dest;
}
In this case Hello, World! gets printed out [!dlroW, olleH] but there are extra characters added at the end and I cannot figure out why.
Any thoughts??
The
instruction does not write anything to memory; it just copies a zero into the register
%ediitself. The correct syntax for a memory write, if I remember correctly, is something likeBut it is really pointless to meticulously store the zero terminator in
%clduring the copying, because you know it’s going to be a zero anyway. So justought to work just as well.
(Also, but unrelated, the string instructions are actually slower than equivalent combinations of separate load/store and increment/decrement operations. At least this used to be the case around the 486 or early Pentium era, and it would surprise me if it’s not still true — especially if you need to manipulate the direction flag each time anyway).
((Also also, it appears to be rather pointless to declare output variables for everything that you don’t use anyway. What’s the point of that. Even if you need to hardcode the use of
eaxfor the string instructions, simply listing"eax"in the clobber list is immensely clearer than forcing it into a dummy output variable)).