diff --git a/docs/Intel manual.pdf b/docs/Intel manual.pdf new file mode 100644 index 0000000..a7a13c4 Binary files /dev/null and b/docs/Intel manual.pdf differ diff --git a/nasm.code-workspace b/nasm.code-workspace index 7309cb0..6e71d7c 100644 --- a/nasm.code-workspace +++ b/nasm.code-workspace @@ -9,9 +9,12 @@ { "path": "even_odd" }, + { + "path": "repeat_str" + }, { "path": "docs" - } + }, ], "settings": { "debug.allowBreakpointsEverywhere": true, diff --git a/repeat_str/.vscode/launch.json b/repeat_str/.vscode/launch.json new file mode 100644 index 0000000..85d5a02 --- /dev/null +++ b/repeat_str/.vscode/launch.json @@ -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" + } + ] +} \ No newline at end of file diff --git a/repeat_str/.vscode/tasks.json b/repeat_str/.vscode/tasks.json new file mode 100644 index 0000000..d8c37ad --- /dev/null +++ b/repeat_str/.vscode/tasks.json @@ -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 + }, + } + ] +} \ No newline at end of file diff --git a/repeat_str/repeat_str.asm b/repeat_str/repeat_str.asm new file mode 100644 index 0000000..8de4892 --- /dev/null +++ b/repeat_str/repeat_str.asm @@ -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 +