2025-02-15 20:09:06 +03:00
|
|
|
|
; Выведет строку, которую ты ввел, память под строку выделяется динамически на куче
|
2025-02-15 19:37:34 +03:00
|
|
|
|
format PE console
|
|
|
|
|
entry start
|
|
|
|
|
include '%FASMINC%\WIN32A.INC'
|
|
|
|
|
|
2025-02-16 15:02:56 +03:00
|
|
|
|
section '.data' data readable writeable
|
|
|
|
|
usage db \
|
|
|
|
|
'This is a test echo program written in FASM,', \
|
|
|
|
|
' outputting to you the string you entered.', 10, \
|
|
|
|
|
'Works with strings of any length!', 10, 10, 0
|
|
|
|
|
req db 'TEXT: ', 0
|
|
|
|
|
resp db 10, 'ECHO: %s', 10, 'Press any button to exit: ', 0
|
|
|
|
|
|
|
|
|
|
section '.funcs' data readable writeable
|
|
|
|
|
; считывание пользовательской строки любого размера из stdin
|
2025-02-16 15:07:50 +03:00
|
|
|
|
get_string_stdin dd _get_string_stdin ; dt - 4 байта - размер адреса
|
2025-02-15 19:37:34 +03:00
|
|
|
|
|
|
|
|
|
section '.code' code readable executable
|
|
|
|
|
start:
|
|
|
|
|
invoke printf, usage
|
|
|
|
|
invoke printf, req
|
2025-02-16 15:02:56 +03:00
|
|
|
|
invoke get_string_stdin
|
2025-02-16 13:56:35 +03:00
|
|
|
|
invoke printf, resp, eax
|
2025-02-16 14:12:00 +03:00
|
|
|
|
pop ebx
|
|
|
|
|
pop eax
|
2025-02-16 13:56:35 +03:00
|
|
|
|
invoke free, eax
|
|
|
|
|
invoke getch
|
|
|
|
|
invoke ExitProcess, 0
|
|
|
|
|
|
|
|
|
|
; Функция, считывающая строку любой длины из консоли
|
2025-02-16 15:02:56 +03:00
|
|
|
|
proc _get_string_stdin
|
|
|
|
|
.start:
|
|
|
|
|
push ebp ; указатель на начало стека в ebp
|
|
|
|
|
mov ebp, esp ; новый epb - esp
|
|
|
|
|
invoke malloc, 2 ; аллоцирую изначально 2 байта под символ и нуль-терминатор
|
|
|
|
|
pop ebx ; двойку убираю со стека
|
|
|
|
|
mov ebx, eax ; адрес строки будет в ebx
|
|
|
|
|
push 2 ; емкость
|
|
|
|
|
push 0 ; длина строки
|
|
|
|
|
.next_char:
|
|
|
|
|
pop eax ; длина
|
|
|
|
|
pop ecx ; емкость
|
|
|
|
|
inc eax ; увеличиваю длину на 1
|
|
|
|
|
cmp eax, ecx ; если длина = емкость
|
|
|
|
|
je .realloc_memory ; реаллоцирую память
|
|
|
|
|
push ecx ; новая емксоть в стек
|
|
|
|
|
push eax ; новая длина в стек
|
|
|
|
|
jmp .continue ; иначе продолжаю программу
|
|
|
|
|
.realloc_memory:
|
|
|
|
|
shl ecx, 1 ; удваиваю емкость
|
|
|
|
|
push ecx ; новая емксоть в стек
|
|
|
|
|
push eax ; новая длина в стек
|
|
|
|
|
invoke realloc, ebx, ecx
|
|
|
|
|
pop ebx
|
|
|
|
|
pop ecx
|
|
|
|
|
mov ebx, eax ; в ebx новый адрес данных
|
|
|
|
|
.continue:
|
|
|
|
|
invoke getche ; считываю символ с клавиатуры
|
|
|
|
|
cmp al, 13
|
|
|
|
|
je .end ; Если Enter, завершаем ввод
|
|
|
|
|
mov edx, eax ; символ из eax в edx
|
|
|
|
|
pop eax ; берем новую длину
|
|
|
|
|
mov [ebx + eax - 1], dl ; сохраняю считанный символ в выделенной памяти
|
|
|
|
|
mov byte [ebx + eax], 0 ; добавляю нуль-терминатор
|
|
|
|
|
push eax
|
|
|
|
|
jmp .next_char ; след итерация
|
|
|
|
|
.end:
|
|
|
|
|
mov eax, ebx ; ответ в eax
|
|
|
|
|
mov esp, ebp ; восстанавлиает указатель указатель на вершину стека вызывающей функции
|
|
|
|
|
pop ebp ; восстанавливает указатель на начало стека вызывающей функции
|
|
|
|
|
ret ; возвращение управления
|
|
|
|
|
endp
|
2025-02-15 19:37:34 +03:00
|
|
|
|
|
|
|
|
|
section '.idata' import data readable
|
|
|
|
|
library \
|
|
|
|
|
msvcrt, 'msvcrt.dll', \
|
|
|
|
|
kernel32, 'kernel32.dll'
|
|
|
|
|
import msvcrt, \
|
|
|
|
|
malloc, 'malloc', \
|
|
|
|
|
realloc, 'realloc', \
|
|
|
|
|
free, 'free', \
|
|
|
|
|
printf, 'printf', \
|
|
|
|
|
getche, '_getche', \
|
|
|
|
|
getch, '_getch'
|
|
|
|
|
import kernel32, \
|
|
|
|
|
ExitProcess, 'ExitProcess'
|