ASM-TRAINING/getinput/echo.asm

86 lines
3.6 KiB
NASM
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

; Выведет строку, которую ты ввел, память под строку выделяется динамически на куче
format PE console
entry start
include '%FASMINC%\WIN32A.INC'
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
get_string_stdin dd _get_string_stdin ; dt - 4 байта - размер адреса
section '.code' code readable executable
start:
invoke printf, usage
invoke printf, req
invoke get_string_stdin
invoke printf, resp, eax
pop ebx
pop eax
invoke free, eax
invoke getch
invoke ExitProcess, 0
; Функция, считывающая строку любой длины из консоли
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
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'