Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.06.2022, 23:01   #1
Kronos913
Форумчанин
 
Регистрация: 10.02.2021
Сообщений: 603
По умолчанию Где ошибка? Очистка строки от лишних символов

Суть задачи:
Есть строка
И есть строка-фильтр

Нужно удалить из строки все элементы, которые есть в строке-фильтре:

Но почему-то только первый символ фильтруется, а дальше все переносится в новую строку без разбору
Код:
type
  String255=string[255];
Код:
Function FilterStr255(const StrIn, StrFilter: string255):string255;
var
  b, d, i, f1, f2, r: LongWord;
asm
  mov b, ebx
  mov d, edi
  mov i, esi

  mov ebx, Result
  mov r, ebx

  mov esi, StrIn
  mov edi, StrFilter

  mov eax, 0
  mov al, [esi]
  cmp al, 0
    ja @Go

  mov [ebx], al
  jmp @Exit1

  @Go:
  add eax, esi
  mov f1, eax {Ïðàâûé êðàé StrIn}

  mov eax, 0
  mov al, [edi]
  add eax, edi
  mov f2, eax  {Ïðàâûé êðàé StrFilter}

  @Start:
  mov eax, f1
  cmp esi, eax
    je @Final
  {Begin}
    inc esi
    mov cl, [esi]

    mov edi, StrFilter
    mov edx, f2

    @Begin2:
      cmp edi, edx
        je @end2

      inc edi
      mov al, [edi]

      cmp al, cl
        je @Start
      jmp @Begin2
    @end2:
    inc ebx
    mov [ebx], cl

    jmp @Start
  {End}
  @Final:
  mov ecx, r

  sub ebx, ecx
  mov [ecx], bl

  @Exit1:
  mov ebx, b
  mov edi, d
  mov esi, i
end;
Kronos913 вне форума Ответить с цитированием
Старый 21.06.2022, 23:26   #2
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Может лучше использовать для строк строковые команды.
Код:
Function FilterStr255(const StrIn, StrFilter: string255):string255;
var
  f: string255;
begin
  push ebx
  push esi
  push edi

  lea ebx, [f]
  mov eax, $03020100
  mov edi, ebx
  mov ecx, 64

@fill:
  stosd
  add eax, $04040404
  loop @fill

  xor eax, eax
  mov esi, StrFilter
  lodsb
  mov ecx, eax
  jecxz @no_filter

@make:
  lodsb
  mov [ebx + eax], ah
  loop @make

  mov edi, Result
  mov esi, StrIn
  lodsb
  stosb
  mov ecx, eax
  mov edx, edi
  jecxz @no_filter

@filter:
  lodsb
  xlatb
  test al, al
  jz @skip
  stosb

@skip:
  loop @filter
  sub edi, edx
  mov eax, edi
  mov [edx - 1], al

@no_filter:
  pop edi
  pop esi
  pop ebx
end;

Последний раз редактировалось macomics; 21.06.2022 в 23:39.
macomics вне форума Ответить с цитированием
Старый 22.06.2022, 00:14   #3
Kronos913
Форумчанин
 
Регистрация: 10.02.2021
Сообщений: 603
По умолчанию

Я уже не пойму этих приколов ассемблера - просматриваю код, вроде ошибок нет, но работает неправильно

Поменял местами два оператора (которые можно, по идее, в любом порядке использовать) - заработало
Kronos913 вне форума Ответить с цитированием
Старый 22.06.2022, 01:58   #4
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Для того, чтобы точно понять что происходит, при отладке стоит открывать окно Ассемблера (Вид->Отладка->Ассемблер), а не пользоваться редактором и точками останова.
В редакторе всегда написан текст, а в окне Ассемблера уже преобразованный код обратно в текст. Что позволяет точно находить просчеты.
macomics вне форума Ответить с цитированием
Старый 22.06.2022, 02:35   #5
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

macomics, а что у вас за компилятор? А то у меня в Дельфи 7 пришлось чуть-чуть ваш код менять, так как параметры передавались через регистры (fastcall), соответственно, к моменту использования уже оказывались подпорчены. А еще почему-то наивно переписанный алгоритм отрабатывает в 13 раз быстрее (может быть где-то ошибся, но результат работы совпадает):
Код:
type
  String255 = string[255];

var
  s1, s2: integer;

Function FilterStr255(const StrIn, StrFilter: string255):string255;
var
  f: string255;
asm
  push ebx
  push esi
  push edi

  push StrIn
  push Result
  push StrFilter

  mov eax, s1
  inc eax
  mov s1, eax

  lea ebx, [f]
  mov eax, $03020100
  mov edi, ebx
  mov ecx, 64

@fill:
  stosd
  add eax, $04040404
  loop @fill

  xor eax, eax
  pop esi // mov esi, StrFilter
  lodsb
  mov ecx, eax
  jecxz @no_filter_2pop

@make:
  lodsb
  mov [ebx + eax], ah
  loop @make

  pop edi // mov edi, Result
  pop esi // mov esi, StrIn
  lodsb
  stosb
  mov ecx, eax
  mov edx, edi
  jecxz @no_filter

@filter:
  lodsb
  xlatb
  test al, al
  jz @skip
  stosb
@skip:
  loop @filter

  sub edi, edx
  mov eax, edi
  mov [edx - 1], al
  jmp @no_filter

@no_filter_2pop:
  pop eax
  pop eax

@no_filter:
  pop edi
  pop esi
  pop ebx
end;

Function FilterStr255_2(const StrIn, StrFilter: string255):string255;
var
  i, j: Byte;
  f: string255;
begin
  Inc(s2);
  f := '';
  for i := 1 to Length(StrFilter) do
    f[Ord(StrFilter[i])] := '!';
  j := 1;
  for i := 1 to Length(StrIn) do
    if f[Ord(StrIn[i])] <> '!' then
    begin
      Result[j] := StrIn[i];
      Inc(j);
    end;
  SetLength(Result, j - 1);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  c1, c2, c3: Int64;
  i: integer;
  r1, r2, a, b: String255;
begin
  a := 'abcd';
  b := 'abc';
  s1 := 0;
  s2 := 0;
  QueryPerformanceCounter(c1);
  for i := 1 to 100000 do
    r1 := FilterStr255(a, b);
  QueryPerformanceCounter(c2);
  for i := 1 to 100000 do
    r2 := FilterStr255_2(a, b);
  QueryPerformanceCounter(c3);
  ShowMessage(
    r1 + sLineBreak +
    IntToStr(s1) + ' ' + IntToStr(c2 - c1) + sLineBreak +
    r2 + sLineBreak +
    IntToStr(s2) + ' ' + IntToStr(c3 - c2)
  );
end;
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 22.06.2022 в 02:37.
BDA вне форума Ответить с цитированием
Старый 22.06.2022, 05:18   #6
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Код:
type
  String255 = string[255];

var
  s1, s2: integer;

Function FilterStr255(const StrIn, StrFilter: string255):string255;
var
  f: string255;
asm
  push ebx
  push esi
  push edi

  push StrIn
  push StrFilter
  push Result

  mov eax, s1
  inc eax
  mov s1, eax

  lea ebx, [f]
  mov eax, $03020100
  mov edi, ebx
  mov ecx, 64

@fill:
  stosd
  add eax, $04040404
  loop @fill

  xor eax, eax
  pop edi
  pop esi
  pop edx
  lodsb
  mov cl, al
  jecxz @no_filter

@make:
  lodsb
  mov [ebx + eax], ah
  loop @make
  mov esi, edx
  lodsb
  mov cl, al
  stosb
  mov edx, edi
  jecxz @no_filter

@filter:
  lodsb
  xlatb
  test al, al
  jz @skip
  stosb

@skip:
  loop @filter
  mov [edi], cl
  mov ecx, edi
  sub ecx, edx
  mov [edx - 1], cl

@no_filter:
  pop edi
  pop esi
  pop ebx
end;
У меня компилятор встроен в форум. Так набрал.

Цитата:
Код:
Function FilterStr255_2(const StrIn, StrFilter: string255):string255;
var
  i, j: Byte;
  f: string255;
begin
  Inc(s2);
  f := ''; // Это не очищает строку, а присваивает ей два байта 0 в символ длины и #0 - терминатор. Остальные 254 символа остаются нетронутыми. Как минимум поставьте FillChar
  for i := 1 to Length(StrFilter) do
    f[Ord(StrFilter[i])] := '!';
  j := 1;
  for i := 1 to Length(StrIn) do
    if f[Ord(StrIn[i])] <> '!' then
    begin
      Result[j] := StrIn[i];
      Inc(j);
    end;
  SetLength(Result, j - 1);
end;
А инициализировать строку f не хотите. Чтобы как у меня было. Или фиг с ним.

Последний раз редактировалось macomics; 22.06.2022 в 05:41.
macomics вне форума Ответить с цитированием
Старый 22.06.2022, 13:43   #7
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
У меня компилятор встроен в форум.
Круто
Цитата:
Сообщение от macomics Посмотреть сообщение
Это не очищает строку
Значит просто повезло, что отработало с одинаковым результатом. Поставил FillChar(f, SizeOf(f), 0);, стало в 5 раз быстрее (вместо 13), чем ассемблер.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 22.06.2022, 15:33   #8
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Цитата:
Сообщение от BDA Посмотреть сообщение
стало в 5 раз быстрее (вместо 13), чем ассемблер.
А можно посмотреть на содержимое окна Ассемблер у вас (FilterStr255_2).
У меня на Lazarus/FreePascal добавляется к Ассеблерному варианту еще длиннющий блок создания строк Result и f с вызовами дополнительных конструкторов.
Что удивительно, но в такой же функции на Pascal этих конструкторов нету. Возможно из-за применения SetLength или других функций.

Последний раз редактировалось macomics; 22.06.2022 в 15:38.
macomics вне форума Ответить с цитированием
Старый 22.06.2022, 15:43   #9
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,285
По умолчанию

macomics, вот:
Код:
Unit1.pas.167: begin
00452704 53               push ebx
00452705 56               push esi
00452706 57               push edi
00452707 55               push ebp
00452708 81C400FFFFFF     add esp,$ffffff00
0045270E 8BF1             mov esi,ecx
00452710 8BDA             mov ebx,edx
00452712 8BF8             mov edi,eax
Unit1.pas.168: Inc(s2);
00452714 FF05985B4500     inc dword ptr [s2]
Unit1.pas.169: FillChar(f, SizeOf(f), 0);
0045271A 8BC4             mov eax,esp
0045271C 33C9             xor ecx,ecx
0045271E BA00010000       mov edx,$00000100
00452723 E88407FBFF       call @FillChar
Unit1.pas.170: for i := 1 to Length(StrFilter) do
00452728 8A13             mov dl,[ebx]
0045272A 84D2             test dl,dl
0045272C 7610             jbe +$10
0045272E 8D4301           lea eax,[ebx+$01]
Unit1.pas.171: f[Ord(StrFilter[i])] := '!';
00452731 33C9             xor ecx,ecx
00452733 8A08             mov cl,[eax]
00452735 C6040C21         mov byte ptr [esp+ecx],$21
00452739 40               inc eax
Unit1.pas.170: for i := 1 to Length(StrFilter) do
0045273A FECA             dec dl
0045273C 75F3             jnz -$0d
Unit1.pas.172: j := 1;
0045273E B001             mov al,$01
Unit1.pas.173: for i := 1 to Length(StrIn) do
00452740 8A17             mov dl,[edi]
00452742 84D2             test dl,dl
00452744 7621             jbe +$21
00452746 8D4F01           lea ecx,[edi+$01]
00452749 8BF9             mov edi,ecx
Unit1.pas.174: if f[Ord(StrIn[i])] <> '!' then
0045274B 8A0F             mov cl,[edi]
0045274D 33DB             xor ebx,ebx
0045274F 8AD9             mov bl,cl
00452751 803C1C21         cmp byte ptr [esp+ebx],$21
00452755 740B             jz +$0b
Unit1.pas.176: Result[j] := StrIn[i];
00452757 33DB             xor ebx,ebx
00452759 8AD8             mov bl,al
0045275B 8D2C1E           lea ebp,[esi+ebx]
0045275E 884D00           mov [ebp+$00],cl
Unit1.pas.177: Inc(j);
00452761 40               inc eax
Unit1.pas.178: end;
00452762 47               inc edi
Unit1.pas.173: for i := 1 to Length(StrIn) do
00452763 FECA             dec dl
00452765 75E4             jnz -$1c
Unit1.pas.179: SetLength(Result, j - 1);
00452767 33D2             xor edx,edx
00452769 8AD0             mov dl,al
0045276B 4A               dec edx
0045276C 8BC6             mov eax,esi
0045276E E81505FBFF       call @SetLength
Unit1.pas.180: end;
00452773 81C400010000     add esp,$00000100
00452779 5D               pop ebp
0045277A 5F               pop edi
0045277B 5E               pop esi
0045277C 5B               pop ebx
0045277D C3               ret 
0045277E 8BC0             mov eax,eax
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 22.06.2022, 16:11   #10
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Так и думал.
Цитата:
Сообщение от BDA Посмотреть сообщение
Код:
00452708 81C400FFFFFF     add esp,$ffffff00
Вот так он выделяет строку, а у меня такая же фигня, но только в Pascal версии. Ассемблерная выделяет строку непонятно где через конструкторы
Код:
080A0AD3 8da424e8fcffff           lea    -0x318(%esp),%esp
080A0ADA 8945fc                   mov    %eax,-0x4(%ebp)
080A0ADD 8955f8                   mov    %edx,-0x8(%ebp)
080A0AE0 894df4                   mov    %ecx,-0xc(%ebp)
080A0AE3 8b4dfc                   mov    -0x4(%ebp),%ecx
080A0AE6 8d85f4fdffff             lea    -0x20c(%ebp),%eax
080A0AEC baff000000               mov    $0xff,%edx
080A0AF1 e89accfbff               call   0x805d790 <fpc_shortstr_to_shortstr> ; Result
080A0AF6 8b4df8                   mov    -0x8(%ebp),%ecx
080A0AF9 8d85f4fcffff             lea    -0x30c(%ebp),%eax
080A0AFF baff000000               mov    $0xff,%edx
080A0B04 e887ccfbff               call   0x805d790 <fpc_shortstr_to_shortstr> ; f
...
macomics вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Удаление лишних символов optimi Microsoft Office Excel 12 03.08.2016 08:28
Удаление лишних символов из Memo NSV Общие вопросы Delphi 10 23.11.2012 08:38
удаление лишних символов Den1zzkkk0 SQL, базы данных 2 27.01.2012 13:27
удаление из строки лишних символов maxefficiently Общие вопросы Delphi 2 01.03.2011 08:53
Вывод без лишних символов Billy Spleen Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 14 26.01.2010 12:47