сборка Linux перевернуть строку - PullRequest
1 голос
/ 15 сентября 2011

Так что я работаю над написанием встроенной функции сборки в c, которая переворачивает это содержимое строки и помещает перевернутую строку в новый массив символов, но я получаю дополнительные символы, добавленные в конец моей перевернутой строки. *

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;
}

Функция сборки

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;
    }

В этом случае Hello, World! распечатывается [! dlroW, olleH], но в конце добавляются дополнительные символы, и я не могу понять, почему. Есть мысли ??

1 Ответ

1 голос
/ 15 сентября 2011

The

mov %ecx, %edi       /*Add null terminating char to new str*/

инструкция ничего не записывает в память; он просто копирует ноль в сам регистр %edi. Правильный синтаксис для записи в память, если я правильно помню, что-то вроде

movb %cl, (%edi)

Но на самом деле бессмысленно тщательно хранить нулевой терминатор в %cl во время копирования, потому что вы знаете, что в любом случае это будет ноль. Так что просто

movb $0, (%edi)

должен работать так же хорошо.

(Кроме того, но не связанные, строковые инструкции на самом деле медленнее, чем эквивалентные комбинации отдельных операций загрузки / сохранения и увеличения / уменьшения. По крайней мере, так было в 486 или в начале эпохи Pentium, и это меня удивило бы если это все еще не так - особенно если вам все равно нужно манипулировать флагом направления каждый раз).

((Кроме того, представляется также бессмысленным объявлять выходные переменные для всего, что вы не используете в любом случае. В чем смысл этого. Даже если вам нужно жестко кодировать использование eax для строковых инструкций простое перечисление "eax" в списке clobber гораздо яснее, чем принудительно вводить его в фиктивную выходную переменную)).

...