section .text
global _start
_start:
mov eax,s ;куда вводить
mov ecx,32 ;макс длина строки
call instr ;ввод строки
mov esi,s ;введенная строка
mov ebx,0 ;кол-во найденных полных квадратов=0
lp1:
;поиск начала очередного числа
mov al,[esi] ;прочитать очередной символ
cmp al,0 ;если конец строки
jz fin1 ;то закончить
cmp al,' ' ;если не пробел
jnz m1 ;то переход
inc esi ;следующий символ
jmp lp1 ;продолжить поиск начала числа
m1:;нашли очередное число в введенной строке
mov edi,0 ;сумма=0
mov eax,0 ;обнулить eax
lp2:;поиск конца числа
mov al,[esi] ;прочитать очердной символ
cmp al,0 ;если конец строки
jz m2 ;то закончить обработку числа
cmp al,' ' ;если пробел
jz m2 ;то закончить обработку числа
cmp al,'9' ;если это не цифра,
jnbe m5 ;то пропускаем
cmp al,'0' ;если это не цифра,
jb m5 ;то пропускаем
sub al,'0' ;получаем цифровое значение
shl edi,1 ;умножаем сумму на 10
add eax, edi
shl edi, 2
add edi, eax ;прибавляем текущее значение
m5: inc esi ;следующий символ
jmp lp2 ;продолжить поиск конца числа
m2: ;в edi находится значение очередного числа
mov ecx,0 ;значение предполагаемого корня=0
lp3:
mov eax,ecx ;значение предполагаемого корня
mul eax ;возводим в квадрат
cmp eax,edi ;сравниваем с значением очередного числа
ja lp1 ;если квадрат больше, то это число точно не полный квадрат, перейти
jnz m3 ;если не равны, то пробовать следующий предполагаемый корень
inc ebx ;если равны, увеличить кол-во найденных полных квадратов
jmp lp1 ;поиск следующего числа в строке
m3: inc ecx ;пробовать следующий предполагаемый корень
jmp lp3 ;продолжить проверку на полный квадрат
fin1: mov eax,ebx ;кол-во найденных полных квадратов
call printdec ;вывести его на консоль
mov eax, 1 ;ф-я завершения
xor ebx, ebx ; errno
int 0x80 ;выход
;вывод числа на консоль
;eax - число
printdec:
push ecx ;сохраняем регистры
push edx
push ebx
push esi
push edi
mov edi,buf ;куда преобразовывать в строку
mov ebx,10 ;основание системы
xor ecx,ecx ;в eсх будет количество цифр в десятичном числе
@@m1a: xor edx,edx
div ebx ;делим число на степени 10
push edx ;и сохраняем остаток от деления(коэффициенты при степенях) в стек
inc ecx ;увеличиваем количество десятичных цифр числа
test eax,eax ;после делия остался 0?
jnz @@m1a ;если нет, продолжаем
@@m2a: pop eax ;взять из стека цифру цисла
add al,'0' ;преобразовываем цифру в ASCII символ
stosb ;сохраняем в буфер
loop @@m2a ;все цифры
mov al,0
stosb ;добавить признак завершения строки
mov eax,buf ;строка с результатом
call outstr ;вывод числа, преобразованного в строку
pop edi
pop esi
pop ebx ;восстанавливаем регистры
pop edx
pop ecx
ret ;выход из подпрограммы
;вывод строки на экран
;eax - адрес ascii строки
outstr: push eax ;сохранить регистры
push ebx
push ecx
push edx
mov ecx,eax ;запомнить адрес строки
xor edx,edx ;кол-во символов в строке
strlp: cmp byte [eax], 0 ;если текущий символ 0
jz strex ;то закончить подсчет
inc eax ;следующий символ
inc edx ;увеличить кол-во символов в строке
jmp strlp ;подсчитать все символы
strex: mov eax,4 ;sys_write
mov ebx,1 ;stdout
int 0x80 ;вывести
pop edx ;восстановить регистры
pop ecx
pop ebx
pop eax
ret
;ввод строки с клавиатуры
;eax - адрес ascii строки
;ecx - максимальная длина строки
;Возвращает
;eax - реальная длина строки
instr: push ebx ;сохранить регистры
push ecx
push edx
lea edx,[ecx+1]
mov ecx,eax ;запомнить адрес строки
mov eax,3 ;sys_read
mov ebx,0 ;stdin
int 0x80 ;ввести
mov byte [ecx+eax],0
pop edx ;восстановить регистры
pop ecx
pop ebx
ret
section .data
segment .bss
s resb 128 ;вводимая строка
buf resb 32 ;буфер для выводимой строки-числа