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

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

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 18.11.2023, 17:06   #1
young programmer
Новичок
Джуниор
 
Регистрация: 18.11.2023
Сообщений: 2
По умолчанию Поиск подстроки входящей в обратном порядке в строку и вывод её позиции на консоль.

Помогите пожалуйста не пойму где ошибка.
Код:
format PE console
entry start
 
include 'A:\Assembler\include\win32a.inc'
 
section '.idata' import data readable
library kernel, 'kernel32.dll', \
        msvcrt, 'msvcrt.dll'
import kernel, \
       ExitProcess, 'ExitProcess'
import msvcrt, \
       printf, 'printf', \
       gets,'gets',\
       strlen,'strlen', \
       getchar, '_fgetchar', \
       scanf,'scanf'
section '.data' data readable writeable      ; секция данных
 
MESSAGE db "Enter string %d",13,10,0
RESULT_1 db "Contains from %d",13,10,0
RESULT_2 db "Doesn't contain",13,10,0
BUF_STR_1 db 250 dup(0)
BUF_STR_2 db 250 dup(0)
LEN_1 dd 0
LEN_2 dd 0
POS dd 0
LEN_SUB dd 0
 
section '.code' code readable executable     ; секция кода
 
start:                                       ; точка входа в программу
    
    ; ввод строк с консоли
    ccall [printf], MESSAGE, dword 1
    ccall [gets], BUF_STR_1
    ccall [printf], MESSAGE, dword 2
    ccall [gets], BUF_STR_2
    
    ; нахождение длин строк
    ccall [strlen], BUF_STR_1
    mov [LEN_1], eax
    ccall [strlen], BUF_STR_2
    mov [LEN_2], eax
    ; нахождение длины подстроки
    mov ecx, 0
    mov esi, BUF_STR_2
get_substring_length:
    lodsb            ; загрузить байт из BUF_STR_2 в al и увеличить esi
    or al, al        ; проверить, не достигнут ли конец подстроки
    jz end_substring_length  ; если достигнут, завершить цикл
    inc ecx          ; увеличить счетчик длины подстроки
    jmp get_substring_length ; продолжить цикл для остальных символов подстроки
end_substring_length:
    mov [LEN_SUB], ecx  ; сохранить длину подстроки

    ; поиск подстроки в обратном порядке
    mov edi, BUF_STR_1  ; указатель на начало строки
search_substring:
    mov eax, [LEN_1]  ; поместить длину строки в eax
    dec eax          ; уменьшить длину на 1
    std              ; установить флаг направления для обратного перемещения
    mov esi, BUF_STR_2  ; указатель на начало подстроки
    mov ecx, [LEN_SUB]  ; поместить длину подстроки в ecx
    repne scasb      ; найти подстроку в строке в обратном порядке
    jne substring_not_found  ; если не найдено, перейти к выводу "не найдено"
    mov ebx, [LEN_SUB]  ; поместить длину подстроки в ebx
    add eax, ebx      ; добавить длину подстроки к индексу, по которому была найдена подстрока
    mov [POS], eax    ; сохранить позицию найденной подстроки
    jmp substring_found  ; перейти к выводу "найдено"
substring_not_found:
    mov [POS], -1     ; сохранить -1, если подстрока не найдена
substring_found:

    ; вывод результата на консоль
    cmp [POS], -1      ; проверить, найдена ли подстрока
    jne substring_found_output
    ccall [printf], RESULT_2  ; если не найдена, вывести "Doesn't contain"
    jmp end_program
substring_found_output:
    ccall [printf], RESULT_1, [POS]  ; если найдена, вывести "Contains from %d"
end_program:
    ccall [getchar]
    ccall [ExitProcess], 0  ; выход из программы
Изображения
Тип файла: png 7hETZ.png (5.2 Кб, 26 просмотров)
young programmer вне форума Ответить с цитированием
Старый 18.11.2023, 19:43   #2
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

Цитата:
Сообщение от young programmer Посмотреть сообщение
не пойму где ошибка.
приведите пример,
какие должны быть входные данные, и что в результате нужно получить.
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Старый 18.11.2023, 22:47   #3
young programmer
Новичок
Джуниор
 
Регистрация: 18.11.2023
Сообщений: 2
По умолчанию

R71MT,Вот входные данные и код переписал,но работает некорректно.Хотя если закоментить std и sub edx,1 то начинает работать.Сделал как-то методом тыка поняв что не сравнивает оно верно.Если поняли почему оно так распишите пожалуйста).Еще вопросик если входная строка такая: input_string db 'Heorl world', 0.Как сделать чтобы выводило все позиции??.
Код:
format PE console                            ; 32-разрядная консольная программа WINDOWS EXE
entry start                                  ; точка входа
 
include 'A:\Assembler\include\win32a.inc'
 
section '.idata' import data readable        ; секция импортируемых функций
 
library kernel,'kernel32.dll',\
        msvcrt,'msvcrt.dll'
 
import  kernel,\
        ExitProcess,'ExitProcess'
 
import  msvcrt,\
        printf,'printf',\
        getchar,'_fgetchar'
 
section '.data' data readable writeable      ; секция данных
 
 input_string db 'Hello world', 0
 substring db 'lro', 0
 pos dd 0
 MESSAGE db "Position: %d", 0
 
section '.code' code readable executable     ; секция кода
 
start:
         xor esi, esi;регистр для указателя на строку
         xor edi, edi;регистр для указателя на подстроку
         xor ecx, ecx;регистр для подсчета длины подстроки
         xor edx, edx;регистр для подсчета длины строки
         mov esi, input_string  ; загружаем в esi нулевой элемент строки
         mov edi, substring ; загружаем в edi нулевой элемент подстроки
         mov edx, 11;Количество элементов в строке
         std
         add esi, 10
 
    loop_last_start:
        mov ecx, 3;длина подстроки
        rep cmpsb;повторяем пока ecx > 0 (пока символ и каждый последующий символ строки совпадает с символом подстроки цикл продолжается)
        jne not_found;если попали на символ которого не содержит подстрока то
        sub edx, 1;
        ccall [printf], MESSAGE , edx
        ccall [getchar]
        cmp edx,0;Сравниваем 2 числа
        je exit;Если дошли до нулевого элемента строки то переходим в метку exit
        jmp loop_last_start;Если не дошли до нулевого элемента продолжаем цикл
 
     not_found:
        mov [pos],-1;Если подстрока не входит в строку выводим -1
        mov edi, substring;Помещаем в регистр edi указатель на начало подстроки
        dec edx;Идем далее по строке справа налево
        cmp edx, 0;
        je exit_not_found;если edx = 0,то переходим к метке exit_not_found
        jmp loop_last_start;Иначе продолжаем цикл
 
     ;если нет вхождений
     exit_not_found:
        xor eax,eax;Очищаем регистр для дальнейшего использования
        mov eax,[pos];кладем в регистр значение переменной pos(-1)
        ccall [printf],MESSAGE,eax;выводим в сообщении регистр
        ccall [getchar];
        stdcall [ExitProcess], 0
 
     ;если есть вхождение
     exit:
        stdcall [ExitProcess], 0
Изображения
Тип файла: png 2023-11-18_20-24-34.png (4.7 Кб, 23 просмотров)
Тип файла: png 2023-11-18_20-34-19.png (6.7 Кб, 0 просмотров)
young programmer вне форума Ответить с цитированием
Старый 19.11.2023, 09:15   #4
R71MT
Участник клуба
 
Аватар для R71MT
 
Регистрация: 16.06.2011
Сообщений: 1,428
По умолчанию

Цитата:
Сообщение от young programmer Посмотреть сообщение
Если поняли почему оно так распишите пожалуйста)
вот вариант с вводом строки и подстроки.
Строка сохраняется в буфере как обычно, а подстроку нужно сохранить наоборот - для этого используем посимвольный ввод. Теперь ставим указатели в конец строк, и взводим флаг направления DF=1 (обратный шаг). Префикс инструкции 'cmpsb' должен быть условным 'repe', что подразумевает немедленный останов при несовпадении. Инструкция 'jcxz' сразу после 'cmpsb' проверяет регистр CX, и если он нуль, значит строки совпали:

Код:
format  pe console
entry   start
include 'win32ax.inc'
;//------------------
.data
buff1   rb  128
buff2   rb  128
len1    dd  0
len2    dd  0
cycle   dd  0
;//------------------
.code
start:  cinvoke  printf,<' String...:  ',0>
        cinvoke  gets,buff1                  ; строка в буфере(1)
        cinvoke  printf,<' SubString:  ',0>  ; ввод подстроки

        mov      edi,buff2+127   ; указатель в конец буфера(2)
@inp:   cinvoke  getche          ; посимвольный ввод
        cmp      al,13           ; это Enter?
        jz       @stop           ; да - выйти из цикла
        mov      byte[edi],al    ; иначе: сохранить символ в EDI
        dec      edi             ; позиция в буфере -1
        inc      [len2]          ; считаем длину подстроки
        jmp      @inp            ; на повтор..

@stop:  cinvoke  strlen,buff1    ; получить длину строки,
        mov      [len1],eax      ; запомнить её
        sub      eax,[len2]      ; получить длину цикла
        inc      eax             ; ...(коррекция)
        mov      [cycle],eax     ; запомнить её

        mov      esi,buff1       ;
        add      esi,[len1]      ; указатель на конец строки
        mov      edi,buff2+127   ; указатель на конец подстроки
        std                      ; ставим обратный шаг справа/налево
@find:  push     edi             ; запомнить линк на конец подстроки
        mov      ecx,[len2]      ; длина цикла для cmpsb
        repe     cmpsb           ; сравнить строки!
        jcxz     @okey           ; выйти, если совпало по всей подстроке
        pop      edi             ; иначе: восстановить указатель
        dec      [cycle]         ; цикл -1
        jnz      @find           ; повторить, если не нуль..
        cld                      ; конец цикла - восстановить шаг

        cinvoke  printf,<10,' --------------------',\
                         10,' Substring not found!',0>
        jmp      @exit

@okey:  pop      edi             ; регистр остался в стеке
        cld                      ; флаг DF=0 (прямой шаг)
        mov      eax,[cycle]     ; получить позицию (оффсет в строке)
        add      eax,[len2]      ; коррекция
        cinvoke  printf,<10,' ------------------------',\
                         10,' Found! Offset: %d',\
                         10,' String lenth : %d',0>,eax,[len1]  ; можно показать и длину строки

@exit:  cinvoke  getche          ; клавиша
        cinvoke  exit,0          ; Game over!

;//--------------------
section '.idata' import data readable
  library  msvcrt, 'msvcrt.dll'
  import   msvcrt, printf,'printf',exit,'exit',strlen,'strlen',getche,'_getche',gets,'gets'
Изображения
Тип файла: png cmpsb.png (7.0 Кб, 19 просмотров)
Нашедшего выход - затаптывают первым..
R71MT вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поиск подстроки входящей в обратном порядке в строку a-dimochka Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 3 03.01.2022 14:20
Как записать число в строку в обратном порядке? Almagawar Помощь студентам 1 26.03.2016 22:42
Вывод из БД в обратном порядке Parallelogram PHP 10 22.05.2014 07:35
Вывести строку в обратном порядке(ассемблер) untiy16 Помощь студентам 1 25.12.2013 08:49
заданную строку записать в обратном порядке Defa4ka Помощь студентам 1 13.05.2009 11:50