141 lines
3.0 KiB
NASM
141 lines
3.0 KiB
NASM
global _start
|
|
|
|
section .data
|
|
buff times 32 db 0
|
|
buffend:
|
|
count dq 0
|
|
|
|
section .text
|
|
default rel
|
|
|
|
_start:
|
|
call read_text
|
|
|
|
lea rsi, [rel buff] ; поставить указатель на начало буфера
|
|
call read_num
|
|
|
|
call print_num_to_buf
|
|
|
|
mov rdx, [count]
|
|
call write_text
|
|
|
|
mov rax, 60
|
|
mov rdi, 0
|
|
syscall
|
|
|
|
; Функция читает текст в буффер
|
|
; Регистры не изменяет
|
|
read_text:
|
|
push rax
|
|
push rdi
|
|
push rsi
|
|
push rdx
|
|
|
|
mov rax, 0 ; sys_read
|
|
mov rdi, 0 ; stdin
|
|
lea rsi, [rel buff] ; адрес буфера
|
|
mov rdx, 256 ; количество байт
|
|
syscall
|
|
mov [count], rax
|
|
|
|
pop rdx
|
|
pop rsi
|
|
pop rdi
|
|
pop rax
|
|
ret
|
|
|
|
; Функция выводит buff
|
|
; In:
|
|
; - RSI - начало буфера
|
|
; - RDX - размер буфера
|
|
; Регистры не изменяет
|
|
write_text:
|
|
push rax
|
|
push rdi
|
|
push rsi
|
|
push rdx
|
|
|
|
mov rax, 1 ; sys_write
|
|
mov rdi, 1 ; stdout
|
|
syscall
|
|
mov [count], rax
|
|
|
|
pop rdx
|
|
pop rsi
|
|
pop rdi
|
|
pop rax
|
|
ret
|
|
|
|
|
|
; Функция читает число из stdin
|
|
; Out: RAX
|
|
read_num:
|
|
push rbx
|
|
push rcx
|
|
xor rbx, rbx ; обнулить регистр для символов
|
|
xor rax, rax ; обнулить аккумулирующий регистр
|
|
mov rcx, 10 ; множитель для сдвига
|
|
|
|
lea rdi, [rel buff] ; rdi - конец данных
|
|
add rdi, [count]
|
|
|
|
.while:
|
|
cmp rsi, rdi ; сначала проверяем границы, чтобы не читать за пределами
|
|
jge .return
|
|
|
|
mov bl, [rsi] ; прочитать текущий символ
|
|
|
|
cmp bl, 0xA ; если конец строки (\n) - закончить
|
|
je .return
|
|
cmp bl, 0 ; если null (\0) - закончить
|
|
jz .return
|
|
cmp bl, ' ' ; если пробел - закончить
|
|
jz .return
|
|
|
|
and bl, 0x0F
|
|
add rax, rbx
|
|
inc rsi
|
|
jmp .while
|
|
|
|
.return:
|
|
pop rcx
|
|
pop rbx
|
|
ret
|
|
|
|
|
|
; Функция выводит число в buff
|
|
; In: RAX
|
|
; Out: RSI - указатель на начало строки
|
|
print_num_to_buf:
|
|
lea rsi, [buffend]
|
|
dec rsi
|
|
|
|
mov rdi, rsi ; сохранить последний адрес
|
|
mov byte [rsi], 0 ; вписать нуль
|
|
dec rsi
|
|
mov byte [rsi], 0xA ; вписать перенос строки
|
|
dec rsi
|
|
mov byte [rsi], '0'
|
|
|
|
test rax, rax
|
|
jz .return
|
|
|
|
mov rcx, 10 ; десятичный делитель
|
|
|
|
.while:
|
|
xor rdx, rdx
|
|
test rax, rax
|
|
jz .break
|
|
div rcx
|
|
or dl, 0x30
|
|
mov [rsi], dl
|
|
dec rsi
|
|
jmp .while
|
|
.break:
|
|
inc rsi
|
|
.return:
|
|
sub rdi, rsi
|
|
inc rdi
|
|
mov [count], rdi
|
|
ret
|