Есть задание "Образовать строку из исходной, повторив 1-й и элемент 1 раз, 2-й элемент 2 раз, 3 и элемент – 3 раза и тд." на с++ с ассемблерными вставками. написал программу:
#include <iostream>
using namespace std;
void readName(char a)
{
cout << a;
}
int main()
{
char mass[7] = "stroka";
char a='a';
int len = 6;
__asm
{
mov esi, -1
mov ebx, 1
mov ecx, 0
go:
inc esi
inc ecx
jmp m1
cmp esi, len
jne go
m1 :
mov al, mass[esi]
push ax
call readName
inc ebx
cmp ebx, ecx
jne m1
mov ax, 1
}
system("pause");
return 0;
}
код должен работать по аналогии с кодом на с++:
char str[] = "stroka";
int k=1;
string newStr;
for (int i = 0; i < strlen(str); i++) {
for (int j = 0; j < k; j++) {
newStr += str[i];
}
k++;
}
но почему-то зацикливается на выведении первого символа. Помогите, пожалуйста) P.S. все делал в vs 2019
Для начала основы: пользовательский код может изменять регистры eax
, edx
, ecx
, а все остальные регистры, если изменяются, должны восстановить свои прежние значения. Отсюда две ваших ошибки
esi
, ebx
printName
не изменит ваши регистрыЕсли эти две ошибки исправить и немного подрихтовать код, то получится так
#include <iostream>
using namespace std;
void __cdecl printChar(char a)
{
cout << a;
}
int main()
{
char mass[7] = "stroka";
__asm
{
pushad // сохраняем все регистры в стек
pushfd // сохраняем регистр флагов в стек
lea esi, mass // загружаем в esi указатель на первый символ
cld
mov ebx, 1 // текущий индекс символа
push eax // зарезервировали место в стеке
go:
lodsb // загружаем текущий символ в al
test al, al // если загрузили \0,
jz exit_ // то выходим
mov edi, ebx // в edi счетчик текущего символа
mov [esp], eax // а сам символ в стек
loopChar:
call printChar
dec edi // уменьшили счетчик
jz endChar // если счетчик = 0, то вышли из цикла
jmp loopChar // в цикле выводим символ
endChar:
inc ebx // увеличили текущий индекс
jmp go // повторили операцию
exit_:
pop eax // не забыли достать символ из стека
popfd // восстановили регистр флагов
popad // восстановили регистры
}
system("pause");
return 0;
}
В коде много бессмыслицы, но сразу можно заметить:
Вызов функции readName
будет разрушать содержимое некоторых регистров. В частности ecx
. Поэтому ваши надежды на то, что содержимое ecx
сохранится, необоснованы.
В чем вообще заключется идея цикла
m1 :
...
cmp ebx, ecx
jne m1
?
Вы сами внутри этого цикла ничего не меняете: ни ebx
, ни ecx
. Почему вы ожидаете, что этот цикл когда-то закончится?
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Пишу класс для работы с матрицамиУказатель и кол-во строк и столбцов сокрыто, это понятно