repeat_str
This commit is contained in:
BIN
docs/Intel manual.pdf
Normal file
BIN
docs/Intel manual.pdf
Normal file
Binary file not shown.
@@ -9,9 +9,12 @@
|
||||
{
|
||||
"path": "even_odd"
|
||||
},
|
||||
{
|
||||
"path": "repeat_str"
|
||||
},
|
||||
{
|
||||
"path": "docs"
|
||||
}
|
||||
},
|
||||
],
|
||||
"settings": {
|
||||
"debug.allowBreakpointsEverywhere": true,
|
||||
|
||||
29
repeat_str/.vscode/launch.json
vendored
Normal file
29
repeat_str/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(lldb) Launch x64",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/repeat_str",
|
||||
"cwd": "${workspaceFolder}/build",
|
||||
"preLaunchTask": "asm64",
|
||||
},
|
||||
{
|
||||
"name": "(gdb) Launch x64",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/repeat_str",
|
||||
"cwd": "${workspaceFolder}/build",
|
||||
"preLaunchTask": "asm64",
|
||||
},
|
||||
{
|
||||
"name": "(gdb+gcc) Launch x64",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/build/repeat_str",
|
||||
"cwd": "${workspaceFolder}/build",
|
||||
"preLaunchTask": "asm64+gcc"
|
||||
}
|
||||
]
|
||||
}
|
||||
53
repeat_str/.vscode/tasks.json
vendored
Normal file
53
repeat_str/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "asm64",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"builddir=${workspaceFolder}/build;",
|
||||
"mkdir -p $builddir;",
|
||||
"rawfilename=$builddir/repeat_str;",
|
||||
"nasm -gdwarf -f elf64 -o $rawfilename.o ${workspaceFolder}/repeat_str.asm;",
|
||||
"ld -g -o $rawfilename $rawfilename.o;"
|
||||
],
|
||||
"problemMatcher": {
|
||||
"pattern": {
|
||||
"regexp": "error"
|
||||
}
|
||||
},
|
||||
"presentation": {
|
||||
"focus": true,
|
||||
"panel": "dedicated",
|
||||
"reveal": "silent",
|
||||
"clear": true
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "asm64+gcc",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"builddir=${workspaceFolder}/build;",
|
||||
"mkdir -p $builddir;",
|
||||
"rawfilename=$builddir/repeat_str;",
|
||||
"nasm -gdwarf -f elf64 -o $rawfilename.o ${workspaceFolder}/repeat_str.asm;",
|
||||
"gcc -o $rawfilename $rawfilename.o;"
|
||||
],
|
||||
"problemMatcher": {
|
||||
"pattern": {
|
||||
"regexp": "error"
|
||||
}
|
||||
},
|
||||
"presentation": {
|
||||
"focus": true,
|
||||
"panel": "dedicated",
|
||||
"reveal": "silent",
|
||||
"clear": true
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
130
repeat_str/repeat_str.asm
Normal file
130
repeat_str/repeat_str.asm
Normal file
@@ -0,0 +1,130 @@
|
||||
global _start
|
||||
|
||||
section .data
|
||||
buff times 256 db 0
|
||||
buffSize dq $-buff
|
||||
count dq 0
|
||||
|
||||
section .text
|
||||
default rel
|
||||
|
||||
_start:
|
||||
lea rsi, [buff]
|
||||
lea rdi, [count]
|
||||
mov rdx, [buffSize]
|
||||
call read_text
|
||||
|
||||
mov al, 0xA
|
||||
lea rdi, [buff]
|
||||
mov rcx, [count]
|
||||
repne scasb
|
||||
|
||||
; Теперь rdi указывает на символ после \n
|
||||
; Вычисляем длину строки: rdi - buff
|
||||
lea rax, [buff]
|
||||
sub rdi, rax
|
||||
mov [count], rdi ; Сохраняем длину строки в count
|
||||
|
||||
; rsi уже установлен на buff + длина строки, т.е. на числе
|
||||
mov rsi, rax
|
||||
add rsi, rdi
|
||||
mov rdx, 256
|
||||
call read_num
|
||||
|
||||
mov rcx, rax
|
||||
jrcxz .return
|
||||
.while:
|
||||
lea rsi, [buff]
|
||||
mov rdx, [count]
|
||||
call write_text
|
||||
loop .while
|
||||
|
||||
.return:
|
||||
mov rax, 60
|
||||
mov rdi, 0
|
||||
syscall
|
||||
|
||||
|
||||
; Функция читает текст в буффер
|
||||
; In:
|
||||
; - RSI - указатель на буффер
|
||||
; - RDI - указатель на адрес для сохранения длины
|
||||
; - RDX - длина буффера
|
||||
; Регистры не изменяет
|
||||
read_text:
|
||||
push rax
|
||||
push rdi
|
||||
|
||||
|
||||
mov rax, 0 ; sys_read
|
||||
mov rdi, 0 ; stdin
|
||||
syscall
|
||||
|
||||
pop rdi
|
||||
mov [rdi], rax
|
||||
|
||||
pop rax
|
||||
ret
|
||||
|
||||
; Функция выводит buff
|
||||
; In:
|
||||
; - RSI - начало буфера
|
||||
; - RDX - размер буфера
|
||||
; Регистры не изменяет
|
||||
write_text:
|
||||
push rcx
|
||||
push rax
|
||||
push rsi
|
||||
push rdx
|
||||
|
||||
mov rax, 1 ; sys_write
|
||||
mov rdi, 1 ; stdout
|
||||
syscall
|
||||
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rax
|
||||
pop rcx
|
||||
ret
|
||||
|
||||
|
||||
; Функция читает число из буфера
|
||||
; In:
|
||||
; - RSI - указатель на буффер
|
||||
; - RDX - длина буффера
|
||||
; Out:
|
||||
; - RAX - число
|
||||
read_num:
|
||||
push rbx
|
||||
push rcx
|
||||
xor rbx, rbx ; обнулить регистр для символов
|
||||
xor rax, rax ; обнулить аккумулирующий регистр
|
||||
mov rcx, 10 ; множитель для сдвига
|
||||
|
||||
mov rdi, rsi
|
||||
add rdi, rdx
|
||||
|
||||
.while:
|
||||
cmp rsi, rdi ; сначала проверяем границы, чтобы не читать за пределами
|
||||
jge .return
|
||||
|
||||
mov bl, [rsi] ; прочитать текущий символ
|
||||
|
||||
cmp bl, 0xA ; если конец строки (\n) - закончить
|
||||
je .return
|
||||
cmp bl, 0x0 ; если null (\0) - закончить
|
||||
jz .return
|
||||
cmp bl, ' ' ; если пробел - закончить
|
||||
jz .return
|
||||
|
||||
mul rcx
|
||||
and bl, 0x0F
|
||||
add rax, rbx
|
||||
inc rsi
|
||||
jmp .while
|
||||
|
||||
.return:
|
||||
pop rcx
|
||||
pop rbx
|
||||
ret
|
||||
|
||||
Reference in New Issue
Block a user