Встроенная сборка C ++ пытается скопировать символ из строки в регистр - PullRequest
0 голосов
/ 25 мая 2019

У меня есть назначение в C ++ для чтения файла в строковую переменную, которая содержит цифры (без пробелов), и с помощью встроенной сборки программе необходимо суммировать цифры строки.Для этого я хочу выполнить цикл до конца строки (NULL) и каждую итерацию копировать 1 регистр (то есть 1 цифра) в регистр, чтобы я мог использовать сравнение и вычитание по нему.Проблема в том, что каждый раз вместо копирования символа в регистр копируется случайное значение.

Я использую Visual Studio для отладки.Переменная Y - это строка, и я пытаюсь скопировать каждую итерацию цикла текущего символа в регистр AL.

    // read from txt file
string y;
cout << "\n" << "the text is \n";
ifstream infile;
infile.open("1.txt");
getline(infile, y);
cout << y;
infile.close();

    // inline assembly
_asm
{
    mov edx, 0          // counter
    mov ebx, 0
    mov eax, 0
loop1:  
    movzx AL, y[ebx]
    cmp AL, 0x00
    jz finished
    sub AL, 48          // convert ascii to number, assuming digit
    add edx, eax        // add digit to counter
    add ebx, 1          // move pointer to the next byte
    loop loop1
finished:
    mov i, edx
}

Например, предположим, что Y равен «123», и это первая итерация цикла,ebx равно 0. Я ожидаю, что y [ebx] будет указывать на значение 49 ('1'), и действительно в отладке я вижу, что значение y [ebx] равно 49. Я хочу скопировать указанное значение в регистр, поэтому, когда я использую инструкцию:

movzx AL, y [ebx]

Я ожидаю, что регистр AL изменится на 49 ('1'), но вместо этого значение изменится на нечто случайное, напримерв последнем сеансе отладки оно изменилось на 192 ('А').

1 Ответ

1 голос
/ 25 мая 2019

y - блок управления объектом std::string. Вы хотите получить доступ к его данным строки C.

Синтаксис встроенного ассемблера MSVC довольно дерьмовый, поэтому нет способа просто запросить указатель на это в регистре. Я думаю, что вы должны создать новую переменную C ++, как char *ystr = y.c_str();

Эта переменная C является указателем , который необходимо загрузить в регистр с помощью mov ecx, [ystr]. Прямой доступ к байту объектного представления ystr даст вам байты указателя.

Кроме того, ваш текущий код использует инструкцию loop, которая медленная и эквивалентна dec ecx/jnz. Но вы не инициализировали ECX, и ваше условие завершения цикла основано на нулевом терминаторе, а не на счетчике, который вы знаете до первой итерации. (Если вы не спросите у std::string его длину).

Здесь нет никаких причин использовать инструкцию loop. Поместите test al,al / jnz loop1 в конец вашей петли, как обычный человек.

...