Код:
.586
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
include masm32.inc
include msvcrt.inc
includelib user32.lib
includelib masm32.lib
includelib kernel32.lib
includelib msvcrt.lib
.data
inph dd 0 ;хэндл чтения консоли
outh dd 0 ;хэндл записи консоли
rw dd 0 ;количество прочитанных/записанных байт
num dd 0
msg1 db 'Input string: ',0
msg2 db 'Input symbol: ',0
msg3 db 'Result: ',0
msg4 db 'Symbol not found.',0
msg5 db 'Num: ',0
fmt db '%d',0 ;строка форматирования
str1 db 1000 dup (0)
str2 db 100 dup (0)
char db 4 dup (0)
.code
_start:
invoke AllocConsole ;выделяем консоль
invoke GetStdHandle,STD_INPUT_HANDLE ;получаем хэндл чтения
mov inph,eax ;сохраняем его
invoke GetStdHandle,STD_OUTPUT_HANDLE ;получаем хэндл записи
mov outh,eax ;сохраняем его
lea eax,msg1 ;nput string
call puts ;вывести сообщение
lea eax,str1 ;вводимая строка
mov ecx,200 ;ее длина
call gets ;ввести строку
lea eax,msg2 ;Input symbol:
call puts ;вывести сообщение
lea eax,char ;вводимый символ
mov ecx,4 ;длина с запасом
call gets ;ввести символ
lea eax,msg5 ;Num:
call puts ;вывести сообщение
lea eax,str2 ;вводимая строка
mov ecx,100 ;ее длина
call gets ;ввести строку
invoke crt_sscanf,offset str2,offset fmt,offset num ;преобразовать вторую строку в число
lea esi,str1 ;введенная строка
mov ah,char ;искомый символ
xor ebx,ebx ;количество символов перед первыв вхождением заданного
;поиск первого вхождения символа
lp:
lodsb ;взять очередной символ
test al,al ;если конец строки
jz fin ;то вывод результата
cmp al,ah ;если искомый символ
jz fin1 ;то закончить цикл
inc ebx ;уаеличить кол-во символов до первого вхождения
jmp lp ;переход на сделующий символ
fin:
lea eax,msg4 ;результирующая строка
call puts ;вывести сообщение что символ не найден
jmp ex ;Выход
fin1:
dec esi ;в esi адрес первого вхождения символа
mov eax,esi ;вычислить
sub eax,offset str1 ;кол-во символов
mov ebx,eax ;до найденного (ebx)
mul num ;умножить на кол-во повторений
test eax,eax ;если 0
jz ex1 ;то закончить
add eax,offset str1 ;новое начало части строки
mov edi,eax ;после повторений
invoke lstrlen,esi ;длина переносимой части
invoke crt_memmove,edi,esi,eax ;сдвинуть строку, освободив место для вставки повторений
mov ecx,esi ;запомнить начало строки
;переворот символов
lea edi,[ecx-1] ;edi - адрес последнего символа переворачиваемой части
lea esi,str1 ;esi - адрес первого символа переворачиваемой части
;переворот части строки
mov edx,ebx ;сохранить кол-во переворачиваемых символов
mov ebp,esi ;и их начало
cmp ebx,1 ;если один символ
jz sk ;то переход
shr ebx,1 ;разделить длину слова на 2
lp1:
lodsb ;взять очередной символ с начала
xchg [edi],al ;поменять его с символом с конца
xchg [esi-1],al
dec edi ;следующий с конца
dec ebx ;уменьшить кол-во оставшихся символов
jnz lp1 ;продолжать пока не 0
sk:
cmp num,1 ;если один раз
jz ex1 ;то закочить
dec num ;иначе уменьшить кол-во повторений
mov edi,ecx ;адрес куда вставлять повторения
lp2:
mov esi,ebp ;адрес добавляемой строки
mov ecx,edx ;ее длина
rep movsb ;добавить в конец новой строки
dec num ;уменьшить кол-во оставшихся добавлений
jnz lp2 ;продолжить пока не 0
ex1:
lea eax,msg3 ;Result:
call puts ;вывести сообщение
lea eax,str1 ;результирующая строка
call puts ;вывести сообщение
ex: lea eax,char
mov ecx,1 ;Задержка перед закрытием
call gets
invoke ExitProcess,0 ;выход
;Вывод строки в консоль
;в EAX - адрес строки
puts:
push ecx
push edx
push eax ;сохраняем адрес строки
invoke lstrlen,eax ;получаем ее длину
pop edx ;восстанавливаем адрес
invoke WriteConsole,outh,edx,eax,ADDR rw,0 ;вывод строки
pop edx
pop ecx
ret ;выход из подпрограммы
;ввод строки с консоли
;в EAX - адрес принимающего буфера
;в ECX - количество читаемых символов
gets:
push ecx
push edx
push eax ;сохраняем регистры
push ecx
invoke ReadConsole,inph,eax,ecx,addr rw,0 ;ввод строки
pop ecx ;восстанавливаем регистры
pop eax
gm1:cmp [eax], byte ptr 13 ;если возврат катерки
jz gm2 ;то закончить поиск
inc eax ;следующий символ
dec ecx ;уменьшить количество оставшихся
jnz gm1 ;продолжать пока не 0
test ecx,ecx ;если нашли возврат катерки
jnz gm2 ;то переход
dec eax ;если не нашли, то вернуться к коследнеиу символу
gm2:mov [eax],byte ptr 0 ;и установить признак конца строки
pop edx
pop ecx
ret ;выход из подпрограммы
end _start
end