Что нужно изменить в функции на assembler-е, чтобы удаляло пробелы в начале и в конце строки
Формулировка задачи:
изменить в функции assembler,чтобы удаляло пробелы в начале и в конце строки,а то удаляет только повторяющиеся пробелы
#include "stdafx.h" #include <stdio.h> #include <locale.h> #include <string.h> #include <time.h> #include <iostream> using namespace std; char* si(char* str, char* res) { int j = 0; int i; for (i = 0; i < strlen(str); i++) { if (str[i] == ' ') { if (j == 0) continue; if (str[i + 1] == ' ') continue; } res[j] = str[i]; j++; } i = strlen(res); // подсчет длины строки if (res[i - 2] == ' ') res[i - 2] = '\0'; return res; } char* assembler(char* str, char* res) { int str_len = strlen(str); _asm { mov ecx, str_len //Заносим длину первой строки mov edi, str //Заносим первую строку mov esi, res //Заносим вторую строку m1 : mov al, byte ptr[edi] //Первый символ первой строки inc edi // увеличиваем значение на 1 mov byte ptr[esi], al //Первый символ второй строки inc esi // увеличиваем значение на 1 dec ecx // уменьшаем счетчик cmp al, ' ' // сравниваем jne m2 // переход если(al) = ' ' repe scasb // поиск пробелов je m2 // переход к m2 dec edi // уменьшаем счетчик inc ecx // увеличиваем значение на 1 m2 : test ecx, ecx jnz m1 // переход если ecx=ecx mov byte ptr[esi], 0 // хранение в 8 бит } return res; } int main() { setlocale(LC_ALL, ""); char str[101] = ""; // ввод строки char res[101] = ""; // вывод строки printf("Введите строку:"); fgets(str, 101, stdin); long int time1 = 0, time2 = 0; // c++ time1 = clock(); for (int k = 1; k < 1000000; k++) si(str, res); time2 = clock(); cout << "Время выполнения 1000000 итераций на Си: " << time2 - time1 << "ms" << endl; cout << res << endl; // assembler time1 = clock(); for (int k = 1; k<1000000; k++) assembler(str,res); time2 = clock(); cout << "Время выполнения 1000000 итераций на ассемблере: " << time2 - time1 << "ms" << endl; cout << res << endl; system("pause"); return 0; }
Решение задачи: «Что нужно изменить в функции на assembler-е, чтобы удаляло пробелы в начале и в конце строки»
textual
Листинг программы
//#include "stdafx.h" #include <stdio.h> #include <locale.h> #include <string.h> #include <time.h> //#include <iostream> //using namespace std; char* si(char* str, char* res) { int j = 0; int i; for (i = 0; i < strlen(str); i++) { if (str[i] == ' ') { if (j == 0) continue; if (str[i + 1] == ' ') continue; } res[j] = str[i]; j++; } i = strlen(res); // подсчет длины строки if (res[i - 2] == ' ') res[i - 2] = '\0'; return res; }; char* trim(char* _str, char* _res) { __asm { xor ecx,ecx mov al,cl mov edi, dword ptr [_str] mov esi, edi // ещё пригодится dec ecx // ECX = -1 repne scasb not ecx sub edi,2 // в ECX - длина str, EDI->на последний символ в строке std mov al, 0x20 // пробел repe scasb // в ECX длина str без хвостовых пробелов mov edi, esi // EDI-> на начало _str cld repe scasb inc ecx //в ECX длина str без начальных и хвостовых пробелов mov esi, edi dec esi //ESI->на первый непобельный символ mov edi, dword ptr [_res] rep movsb xor al,al stosb }; return _res; }; int main() { //setlocale(LC_ALL, ""); char str[101]; // ввод строки char res[101]; // вывод строки long int time1 = 0, time2 = 0; int k; printf("Введите строку:"); gets(str); // c++ time1 = clock(); for (k = 1; k < 1000000; k++) si(str, res); time2 = clock(); printf("Время выполнения 1000000 итераций на Си: %d ms\n\r%s|\n\r", time2 - time1,res); // assembler time1 = clock(); for (k = 1; k<1000000; k++) trim(str,res); time2 = clock(); printf("Время выполнения 1000000 итераций на ассемблере: %d ms\n\r%s|\n\r", time2 - time1,res); getch(); return 0; };
Объяснение кода листинга программы
- Функция
si
принимает два аргумента: указатель на исходную строкуstr
и указатель на результирующую строкуres
. - В функции используется цикл
for
, который проходит по всем символам строкиstr
. - Если текущий символ является пробелом и предыдущий символ также является пробелом, то текущий символ пропускается.
- Если текущий символ не является пробелом, он копируется в результирующую строку
res
. - После цикла
for
подсчитывается длина результирующей строкиres
. - Если последний символ результирующей строки является пробелом, он заменяется на символ конца строки
\0
. - Функция
trim
принимает два аргумента: указатель на исходную строку_str
и указатель на результирующую строку_res
. - В функции используется ассемблерный блок, который выполняет следующие действия:
- Используется операция
xor ecx,ecx
, чтобы установить начальное значение регистраecx
равным 0. - Регистр
al
устанавливается равным значению регистраcl
, чтобы обеспечить корректную работу операцииrepne scasb
. - Устанавливается начальное значение указателя на строку
_str
в регистреedi
. - Регистр
ecx
уменьшается на 1, чтобы обеспечить корректную работу операцииrepne scasb
. - Операция
repne scasb
используется для поиска первого непобедимого символа в строке_str
. - Регистр
ecx
инвертируется, чтобы обеспечить корректную работу операцииsub edi,2
. - Устанавливается начальное значение указателя на результирующую строку
_res
в регистреedi
. - Регистр
ecx
увеличивается на 1, чтобы обеспечить корректную работу операцииrep movsb
. - Регистр
al
устанавливается равным символу пробела0x20
, чтобы обеспечить корректную работу операцииrep stosb
. - Операция
rep stosb
используется для удаления начальных и хвостовых пробелов в результирующей строке_res
. - Устанавливается начальное значение указателя на первый непобедимый символ в строке
_str
в регистреesi
. - Регистр
ecx
уменьшается на 1, чтобы обеспечить корректную работу операцииrep movsb
. - Операция
rep movsb
используется для копирования оставшейся части строки_str
в результирующую строку_res
. - Регистр
al
устанавливается равным символу конца строки\0
, чтобы обеспечить корректную работу операцииstosb
. - Операция
stosb
используется для добавления символа конца строки\0
в конец результирующей строки_res
.
- Используется операция
- В функции
main
используется функцияgets
для считывания строки от пользователя. - Используется функция
clock
для измерения времени выполнения. - В цикле
for
выполняется 1 000 000 итераций функцииsi
илиtrim
. - После каждой итерации функции
si
илиtrim
вызывается функцияclock
для измерения времени выполнения. - Выводится время выполнения и результирующая строка.
- В конце программы вызывается функция
getch
для получения нажатия клавиши от пользователя. - Программа возвращает 0, чтобы указать успешное выполнение.