Compare commits
7 Commits
labs/cours
...
labs/06
| Author | SHA1 | Date | |
|---|---|---|---|
| b559db2cc1 | |||
| 8fe6e0ba63 | |||
| f57aa67887 | |||
| eb85d6dd9a | |||
| 68c5f8388b | |||
| 0fff8ca9d1 | |||
| a2ac5eedcc |
@ -2,3 +2,12 @@
|
||||
|
||||
## Подпрограммы, программные прерывания и особые случаи
|
||||
|
||||
### АХТУНГ
|
||||
|
||||
**НАСТОЯТЕЛЬНО РЕКОМЕНДУЮ НЕ ЗАГРУЖАТЬ КОД ИЗ ЭТОЙ ЛАБЫ**. Дело в том, что Linux считает прерывания его личной заботой и поэтому как правило сам отвечает за их обработку. Для того, чтобы сделать прикол из лабы с подменой таблицы векоторов прерываний необходимо написать модуль ядра.
|
||||
|
||||
Для тех, кто в танке, это означает следующее: **ЕСЛИ Я ОШИБСЯ ХОТЬ ГДЕ-ТО (А Я ВЕРОЯТНЕЕ ВСЕГО ГДЕ-ТО ОШИБСЯ), ВАШЕЙ СИСТЕМЕ МОЖЕТ ПРИЙТИ ПИЗДА. И ОЧЕНЬ БЫСТРО**
|
||||
|
||||
## Теперь для смелых
|
||||
|
||||
Милицын препод лояльный, поэтому было принято решение не грохать в лоб системную таблицу, а расширить ее своими прерываниями. Делается это в основном при помощи `request_irq`, в который передается куча инфы о прерывании
|
||||
|
||||
69
06-subroutines-interruptions/fuck-system.c
Normal file
69
06-subroutines-interruptions/fuck-system.c
Normal file
@ -0,0 +1,69 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/desc.h>
|
||||
|
||||
// Смотрим у производителя процессора номер прерывания
|
||||
// деления на ноль (я сижу на x86-64, а этот номер зависит от архитектуры процессора)
|
||||
#define ZERODIV_NR 0x00
|
||||
|
||||
extern void store_idt(struct desc_ptr *storage);
|
||||
|
||||
static void example_handler(void)
|
||||
{
|
||||
pr_warn("entered the handler");
|
||||
return;
|
||||
}
|
||||
|
||||
static int __init fuck_system(void)
|
||||
{
|
||||
pr_info("start to fuck system");
|
||||
|
||||
struct desc_ptr newidtreg;
|
||||
struct desc_ptr oldidtreg;
|
||||
gate_desc *oldidt, *newidt;
|
||||
|
||||
pr_info("nessesary variables created");
|
||||
// Выделяем память под 256 прерываний
|
||||
unsigned long new_page = __get_free_page(GFP_KERNEL);
|
||||
if (!new_page)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
pr_info("new page allocated");
|
||||
store_idt(&oldidtreg);
|
||||
pr_info("IDT register stored");
|
||||
newidtreg.address = new_page;
|
||||
newidtreg.size = oldidtreg.size;
|
||||
newidt = (gate_desc *)newidtreg.address;
|
||||
memcpy(newidt, oldidt, newidtreg.size);
|
||||
pr_info("IDT register saved in backup");
|
||||
|
||||
pack_gate(
|
||||
(newidt + ZERODIV_NR),
|
||||
GATE_INTERRUPT,
|
||||
(unsigned long) example_handler,
|
||||
0,
|
||||
0,
|
||||
__KERNEL_CS
|
||||
);
|
||||
pr_info("packed new gate");
|
||||
|
||||
load_idt(&newidtreg);
|
||||
pr_info("loaded new interrupts");
|
||||
int x = 1 / 0; // триггерим прерывание деления на ноль
|
||||
pr_info("return from interrupt");
|
||||
load_idt(&oldidtreg);
|
||||
free_page(new_page);
|
||||
pr_info("Unloaded everything");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit unfuck_system(void)
|
||||
{
|
||||
pr_info("start to unfuck system");
|
||||
}
|
||||
|
||||
module_init(fuck_system);
|
||||
module_exit(unfuck_system);
|
||||
MODULE_LICENSE("GPL");
|
||||
8
06-subroutines-interruptions/low-level-asm.asm
Normal file
8
06-subroutines-interruptions/low-level-asm.asm
Normal file
@ -0,0 +1,8 @@
|
||||
global store_idt
|
||||
|
||||
section .text
|
||||
|
||||
store_idt: ; rdi - указатель
|
||||
sidt [rdi]
|
||||
ret
|
||||
int3
|
||||
@ -1,379 +0,0 @@
|
||||
global _start
|
||||
|
||||
%define NAME_SIZE 64
|
||||
%define BUFF_SIZE 1024
|
||||
|
||||
section .bss
|
||||
name resb NAME_SIZE
|
||||
buffer resb BUFF_SIZE
|
||||
|
||||
section .data
|
||||
buffer_tail dq buffer
|
||||
iseof db 0
|
||||
|
||||
;strings
|
||||
E_open_file db `Something went wrong while opening file\n`
|
||||
|
||||
section .text
|
||||
read:
|
||||
push rcx
|
||||
push r11
|
||||
mov rax, 0
|
||||
syscall
|
||||
pop r11
|
||||
pop rcx
|
||||
ret
|
||||
|
||||
write:
|
||||
push rcx
|
||||
push r11
|
||||
mov rax, 1
|
||||
syscall
|
||||
pop r11
|
||||
pop rcx
|
||||
ret
|
||||
|
||||
namecmp:
|
||||
.LFB6:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
mov -8[rbp], rdi
|
||||
mov -16[rbp], rsi
|
||||
jmp .L2
|
||||
.L6:
|
||||
mov rax, -8[rbp]
|
||||
movzx edx, BYTE [rax]
|
||||
mov rax, -16[rbp]
|
||||
movzx eax, BYTE [rax]
|
||||
cmp dl, al
|
||||
je .L3
|
||||
mov eax, 0
|
||||
jmp .L4
|
||||
.L3:
|
||||
add QWORD -8[rbp], 1
|
||||
add QWORD -16[rbp], 1
|
||||
.L2:
|
||||
mov rax, -8[rbp]
|
||||
movzx eax, BYTE [rax]
|
||||
test al, al
|
||||
je .L5
|
||||
mov rax, -16[rbp]
|
||||
movzx eax, BYTE [rax]
|
||||
test al, al
|
||||
jne .L6
|
||||
.L5:
|
||||
mov eax, 1
|
||||
.L4:
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
openfile:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
sub rsp, 32
|
||||
mov -24[rbp], rdi
|
||||
mov rax, -24[rbp]
|
||||
mov esi, 0
|
||||
mov rdi, rax
|
||||
mov eax, 2
|
||||
syscall
|
||||
mov -4[rbp], eax
|
||||
cmp DWORD -4[rbp], 0
|
||||
jns .L8
|
||||
mov rdi, 1
|
||||
mov rsi, E_open_file
|
||||
mov rdx, 40
|
||||
call write
|
||||
mov edi, 1
|
||||
mov rax, 60
|
||||
mov rdi, 1
|
||||
syscall
|
||||
.L8:
|
||||
mov eax, -4[rbp]
|
||||
leave
|
||||
ret
|
||||
|
||||
fill_buffer:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
sub rsp, 32
|
||||
mov -20[rbp], edi
|
||||
mov rdx, [buffer_tail]
|
||||
lea rax, [buffer]
|
||||
sub rdx, rax
|
||||
mov eax, 1024
|
||||
sub rax, rdx
|
||||
mov -8[rbp], rax
|
||||
mov rdx, -8[rbp]
|
||||
mov eax, -20[rbp]
|
||||
lea rcx, [buffer]
|
||||
mov rsi, rcx
|
||||
mov edi, eax
|
||||
call read
|
||||
mov -16[rbp], rax
|
||||
cmp QWORD -16[rbp], 1023
|
||||
ja .L11
|
||||
mov BYTE [iseof], 1
|
||||
.L11:
|
||||
lea rdx, [buffer]
|
||||
mov rax, -16[rbp]
|
||||
add rax, rdx
|
||||
mov [buffer_tail], rax
|
||||
nop
|
||||
leave
|
||||
|
||||
ret
|
||||
|
||||
find_second_word:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
mov -8[rbp], rdi
|
||||
jmp .L13
|
||||
.L14:
|
||||
add QWORD -8[rbp], 1
|
||||
.L13:
|
||||
mov rax, -8[rbp]
|
||||
movzx eax, BYTE [rax]
|
||||
cmp al, 32
|
||||
jne .L14
|
||||
add QWORD -8[rbp], 1
|
||||
mov rax, -8[rbp]
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
find_fullname_end:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
lea rax, [buffer]
|
||||
mov -8[rbp], rax
|
||||
jmp .L17
|
||||
.L20:
|
||||
add QWORD -8[rbp], 1
|
||||
.L17:
|
||||
mov rax, -8[rbp]
|
||||
movzx eax, BYTE [rax]
|
||||
cmp al, 10
|
||||
jne .L18
|
||||
mov rax, -8[rbp]
|
||||
movzx eax, BYTE [rax]
|
||||
test al, al
|
||||
jne .L19
|
||||
.L18:
|
||||
lea rax, [buffer+1024]
|
||||
cmp -8[rbp], rax
|
||||
jb .L20
|
||||
.L19:
|
||||
lea rax, [buffer+1024]
|
||||
cmp -8[rbp], rax
|
||||
jne .L21
|
||||
mov eax, 0
|
||||
jmp .L22
|
||||
.L21:
|
||||
mov rax, -8[rbp]
|
||||
.L22:
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
pop_fullname:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
sub rsp, 32
|
||||
mov eax, 0
|
||||
call find_fullname_end
|
||||
add rax, 1
|
||||
mov -16[rbp], rax
|
||||
lea rdx, [buffer]
|
||||
mov rax, -16[rbp]
|
||||
sub rax, rdx
|
||||
mov -24[rbp], rax
|
||||
mov QWORD -8[rbp], 0
|
||||
jmp .L24
|
||||
.L25:
|
||||
mov rdx, -16[rbp]
|
||||
mov rax, -8[rbp]
|
||||
add rax, rdx
|
||||
movzx eax, BYTE [rax]
|
||||
lea rcx, [buffer]
|
||||
mov rdx, -8[rbp]
|
||||
add rdx, rcx
|
||||
mov BYTE [rdx], al
|
||||
mov rdx, -16[rbp]
|
||||
mov rax, -8[rbp]
|
||||
add rax, rdx
|
||||
mov BYTE [rax], 0
|
||||
add QWORD -8[rbp], 1
|
||||
.L24:
|
||||
mov eax, 1024
|
||||
sub rax, -24[rbp]
|
||||
cmp -8[rbp], rax
|
||||
jb .L25
|
||||
mov rax, [buffer_tail]
|
||||
mov rdx, -24[rbp]
|
||||
neg rdx
|
||||
add rax, rdx
|
||||
mov [buffer_tail], rax
|
||||
nop
|
||||
leave
|
||||
|
||||
ret
|
||||
|
||||
preprint db `count: `
|
||||
postprint db `\n`
|
||||
|
||||
print_count:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
sub rsp, 32
|
||||
mov -24[rbp], rdi
|
||||
mov edx, 8
|
||||
mov rax, preprint
|
||||
mov rsi, rax
|
||||
mov edi, 1
|
||||
call write
|
||||
jmp .L27
|
||||
.L28:
|
||||
mov rcx, -24[rbp]
|
||||
mov rdx, -3689348814741910323
|
||||
mov rax, rcx
|
||||
mul rdx
|
||||
shr rdx, 3
|
||||
mov rax, rdx
|
||||
sal rax, 2
|
||||
add rax, rdx
|
||||
add rax, rax
|
||||
sub rcx, rax
|
||||
mov rdx, rcx
|
||||
mov eax, edx
|
||||
add eax, 48
|
||||
mov BYTE -1[rbp], al
|
||||
mov rax, -24[rbp]
|
||||
mov rdx, -3689348814741910323
|
||||
mul rdx
|
||||
mov rax, rdx
|
||||
shr rax, 3
|
||||
mov -24[rbp], rax
|
||||
lea rax, -1[rbp]
|
||||
mov edx, 1
|
||||
mov rsi, rax
|
||||
mov edi, 1
|
||||
call write
|
||||
.L27:
|
||||
cmp QWORD -24[rbp], 0
|
||||
jne .L28
|
||||
mov edx, 1
|
||||
mov rax, postprint
|
||||
mov rsi, rax
|
||||
mov edi, 1
|
||||
call write
|
||||
nop
|
||||
leave
|
||||
|
||||
ret
|
||||
|
||||
get_name:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
sub rsp, 40
|
||||
mov -40[rbp], rdi
|
||||
lea rax, [buffer]
|
||||
mov rdi, rax
|
||||
call find_second_word
|
||||
mov -24[rbp], rax
|
||||
mov rax, -24[rbp]
|
||||
mov -8[rbp], rax
|
||||
jmp .L30
|
||||
.L31:
|
||||
add QWORD -8[rbp], 1
|
||||
.L30:
|
||||
mov rax, -8[rbp]
|
||||
movzx eax, BYTE [rax]
|
||||
cmp al, 32
|
||||
jne .L31
|
||||
cmp QWORD -8[rbp], 0
|
||||
jne .L32
|
||||
mov eax, -1
|
||||
jmp .L33
|
||||
.L32:
|
||||
mov QWORD -16[rbp], 0
|
||||
jmp .L34
|
||||
.L35:
|
||||
mov rdx, -24[rbp]
|
||||
mov rax, -16[rbp]
|
||||
add rax, rdx
|
||||
mov rcx, -40[rbp]
|
||||
mov rdx, -16[rbp]
|
||||
add rdx, rcx
|
||||
movzx eax, BYTE [rax]
|
||||
mov BYTE [rdx], al
|
||||
add QWORD -16[rbp], 1
|
||||
.L34:
|
||||
mov rdx, -24[rbp]
|
||||
mov rax, -16[rbp]
|
||||
add rax, rdx
|
||||
cmp rax, -8[rbp]
|
||||
jb .L35
|
||||
mov eax, 0
|
||||
.L33:
|
||||
leave
|
||||
ret
|
||||
|
||||
_start:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
sub rsp, 96
|
||||
mov -84[rbp], edi
|
||||
mov -96[rbp], rsi
|
||||
mov rax, -96[rbp]
|
||||
add rax, 8
|
||||
mov rax, [rax]
|
||||
mov rdi, rax
|
||||
call openfile
|
||||
mov -12[rbp], eax
|
||||
mov edx, 64
|
||||
lea rax, [name]
|
||||
mov rsi, rax
|
||||
mov edi, 0
|
||||
call read
|
||||
mov QWORD -8[rbp], 0
|
||||
mov QWORD -80[rbp], 0
|
||||
mov QWORD -72[rbp], 0
|
||||
mov QWORD -64[rbp], 0
|
||||
mov QWORD -56[rbp], 0
|
||||
mov QWORD -48[rbp], 0
|
||||
mov QWORD -40[rbp], 0
|
||||
mov QWORD -32[rbp], 0
|
||||
mov QWORD -24[rbp], 0
|
||||
.L39:
|
||||
mov eax, 0
|
||||
call find_fullname_end
|
||||
test rax, rax
|
||||
jne .L37
|
||||
mov eax, DWORD -12[rbp]
|
||||
mov edi, eax
|
||||
call fill_buffer
|
||||
.L37:
|
||||
lea rax, -80[rbp]
|
||||
mov rdi, rax
|
||||
call get_name
|
||||
lea rax, -80[rbp]
|
||||
lea rdx, [name]
|
||||
mov rsi, rdx
|
||||
mov rdi, rax
|
||||
call namecmp
|
||||
test eax, eax
|
||||
je .L38
|
||||
add QWORD -8[rbp], 1
|
||||
.L38:
|
||||
mov eax, 0
|
||||
call pop_fullname
|
||||
mov rdx, [buffer_tail]
|
||||
lea rax, [buffer]
|
||||
cmp rdx, rax
|
||||
jne .L39
|
||||
mov rax, -8[rbp]
|
||||
mov rdi, rax
|
||||
call print_count
|
||||
mov eax, 0
|
||||
leave
|
||||
ret
|
||||
@ -1,134 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define BUFF_SIZE 1024
|
||||
#define NAME_SIZE 64
|
||||
#define STDIN 0
|
||||
#define STDOUT 1
|
||||
|
||||
typedef unsigned long long u64;
|
||||
|
||||
char name[NAME_SIZE];
|
||||
char buffer[BUFF_SIZE];
|
||||
char* buffer_tail = buffer; // points on first free symbol
|
||||
|
||||
char iseof = 0;
|
||||
|
||||
int namecmp(char* name1, char* name2)
|
||||
{
|
||||
for (; *name1 && *name2; name1++, name2++)
|
||||
{
|
||||
if (*name1 != *name2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int openfile(char* filename)
|
||||
{
|
||||
int file = open(filename, O_RDONLY);
|
||||
if (file < 0)
|
||||
{
|
||||
puts("Something went wrong while opening file\n");
|
||||
exit(1);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
void fill_buffer(int filedesc)
|
||||
{
|
||||
const size_t tofill = BUFF_SIZE - (buffer_tail - buffer);
|
||||
u64 bytes_read = read(filedesc, buffer, tofill);
|
||||
if (bytes_read < BUFF_SIZE)
|
||||
{
|
||||
iseof = 1;
|
||||
}
|
||||
buffer_tail = buffer + bytes_read;
|
||||
}
|
||||
|
||||
char* find_second_word(char* start)
|
||||
{
|
||||
for (; *start != ' '; start++);
|
||||
return ++start;
|
||||
}
|
||||
|
||||
char* find_fullname_end()
|
||||
{
|
||||
char* end = buffer;
|
||||
for (; (*end != '\n' || *end == 0)
|
||||
&& end < buffer + BUFF_SIZE; end++);
|
||||
if (end == buffer + BUFF_SIZE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
void pop_fullname() // pops from buffer
|
||||
{
|
||||
char* end = find_fullname_end() + 1;
|
||||
u64 fullname_len = end - buffer;
|
||||
size_t i = 0;
|
||||
for (; i < BUFF_SIZE - fullname_len; i++)
|
||||
{
|
||||
buffer[i] = end[i];
|
||||
end[i] = 0;
|
||||
}
|
||||
buffer_tail -= fullname_len;
|
||||
}
|
||||
|
||||
void print_count(u64 count)
|
||||
{
|
||||
write(STDOUT, "count: ", 8);
|
||||
while (count)
|
||||
{
|
||||
char digit = (count % 10) + '0';
|
||||
count /= 10;
|
||||
write(STDOUT, &digit, 1);
|
||||
}
|
||||
write(STDOUT, "\n", 1);
|
||||
}
|
||||
|
||||
int get_name(char* accumulator)
|
||||
{
|
||||
char* start = find_second_word(buffer);
|
||||
char* end = start;
|
||||
for (; *end != ' '; end++);
|
||||
if (!end)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
for (size_t i = 0; &start[i] < end; i++)
|
||||
{
|
||||
accumulator[i] = start[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int filedesc = openfile(argv[1]);
|
||||
read(STDIN, name, sizeof(name)/sizeof(name[0]));
|
||||
// fgets(name, sizeof(name)/sizeof(name[0]), stdin);
|
||||
size_t count = 0;
|
||||
char namebuff[NAME_SIZE] = {0, };
|
||||
do
|
||||
{
|
||||
if (!find_fullname_end())
|
||||
{
|
||||
fill_buffer(filedesc);
|
||||
}
|
||||
get_name(namebuff);
|
||||
if (namecmp(namebuff, name))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
pop_fullname();
|
||||
} while (buffer_tail != buffer);
|
||||
print_count(count);
|
||||
return 0;
|
||||
}
|
||||
@ -1,467 +0,0 @@
|
||||
.file "main.c"
|
||||
.intel_syntax noprefix
|
||||
.text
|
||||
.globl name
|
||||
.bss
|
||||
.align 32
|
||||
.type name, @object
|
||||
.size name, 64
|
||||
name:
|
||||
.zero 64
|
||||
.globl buffer
|
||||
.align 32
|
||||
.type buffer, @object
|
||||
.size buffer, 1024
|
||||
buffer:
|
||||
.zero 1024
|
||||
.globl buffer_tail
|
||||
.section .data.rel.local,"aw"
|
||||
.align 8
|
||||
.type buffer_tail, @object
|
||||
.size buffer_tail, 8
|
||||
buffer_tail:
|
||||
.quad buffer
|
||||
.globl iseof
|
||||
.bss
|
||||
.type iseof, @object
|
||||
.size iseof, 1
|
||||
iseof:
|
||||
.zero 1
|
||||
.text
|
||||
.globl namecmp
|
||||
.type namecmp, @function
|
||||
namecmp:
|
||||
.LFB6:
|
||||
.cfi_startproc
|
||||
push rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
mov rbp, rsp
|
||||
.cfi_def_cfa_register 6
|
||||
mov QWORD PTR -8[rbp], rdi
|
||||
mov QWORD PTR -16[rbp], rsi
|
||||
jmp .L2
|
||||
.L6:
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
movzx edx, BYTE PTR [rax]
|
||||
mov rax, QWORD PTR -16[rbp]
|
||||
movzx eax, BYTE PTR [rax]
|
||||
cmp dl, al
|
||||
je .L3
|
||||
mov eax, 0
|
||||
jmp .L4
|
||||
.L3:
|
||||
add QWORD PTR -8[rbp], 1
|
||||
add QWORD PTR -16[rbp], 1
|
||||
.L2:
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
movzx eax, BYTE PTR [rax]
|
||||
test al, al
|
||||
je .L5
|
||||
mov rax, QWORD PTR -16[rbp]
|
||||
movzx eax, BYTE PTR [rax]
|
||||
test al, al
|
||||
jne .L6
|
||||
.L5:
|
||||
mov eax, 1
|
||||
.L4:
|
||||
pop rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE6:
|
||||
.size namecmp, .-namecmp
|
||||
.section .rodata
|
||||
.align 8
|
||||
.LC0:
|
||||
.string "Something went wrong while opening file\n"
|
||||
.text
|
||||
.globl openfile
|
||||
.type openfile, @function
|
||||
openfile:
|
||||
.LFB7:
|
||||
.cfi_startproc
|
||||
push rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
mov rbp, rsp
|
||||
.cfi_def_cfa_register 6
|
||||
sub rsp, 32
|
||||
mov QWORD PTR -24[rbp], rdi
|
||||
mov rax, QWORD PTR -24[rbp]
|
||||
mov esi, 0
|
||||
mov rdi, rax
|
||||
mov eax, 0
|
||||
call open@PLT
|
||||
mov DWORD PTR -4[rbp], eax
|
||||
cmp DWORD PTR -4[rbp], 0
|
||||
jns .L8
|
||||
lea rax, .LC0[rip]
|
||||
mov rdi, rax
|
||||
call puts@PLT
|
||||
mov edi, 1
|
||||
call exit@PLT
|
||||
.L8:
|
||||
mov eax, DWORD PTR -4[rbp]
|
||||
leave
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE7:
|
||||
.size openfile, .-openfile
|
||||
.globl fill_buffer
|
||||
.type fill_buffer, @function
|
||||
fill_buffer:
|
||||
.LFB8:
|
||||
.cfi_startproc
|
||||
push rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
mov rbp, rsp
|
||||
.cfi_def_cfa_register 6
|
||||
sub rsp, 32
|
||||
mov DWORD PTR -20[rbp], edi
|
||||
mov rdx, QWORD PTR buffer_tail[rip]
|
||||
lea rax, buffer[rip]
|
||||
sub rdx, rax
|
||||
mov eax, 1024
|
||||
sub rax, rdx
|
||||
mov QWORD PTR -8[rbp], rax
|
||||
mov rdx, QWORD PTR -8[rbp]
|
||||
mov eax, DWORD PTR -20[rbp]
|
||||
lea rcx, buffer[rip]
|
||||
mov rsi, rcx
|
||||
mov edi, eax
|
||||
call read@PLT
|
||||
mov QWORD PTR -16[rbp], rax
|
||||
cmp QWORD PTR -16[rbp], 1023
|
||||
ja .L11
|
||||
mov BYTE PTR iseof[rip], 1
|
||||
.L11:
|
||||
lea rdx, buffer[rip]
|
||||
mov rax, QWORD PTR -16[rbp]
|
||||
add rax, rdx
|
||||
mov QWORD PTR buffer_tail[rip], rax
|
||||
nop
|
||||
leave
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE8:
|
||||
.size fill_buffer, .-fill_buffer
|
||||
.globl find_second_word
|
||||
.type find_second_word, @function
|
||||
find_second_word:
|
||||
.LFB9:
|
||||
.cfi_startproc
|
||||
push rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
mov rbp, rsp
|
||||
.cfi_def_cfa_register 6
|
||||
mov QWORD PTR -8[rbp], rdi
|
||||
jmp .L13
|
||||
.L14:
|
||||
add QWORD PTR -8[rbp], 1
|
||||
.L13:
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
movzx eax, BYTE PTR [rax]
|
||||
cmp al, 32
|
||||
jne .L14
|
||||
add QWORD PTR -8[rbp], 1
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
pop rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE9:
|
||||
.size find_second_word, .-find_second_word
|
||||
.globl find_fullname_end
|
||||
.type find_fullname_end, @function
|
||||
find_fullname_end:
|
||||
.LFB10:
|
||||
.cfi_startproc
|
||||
push rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
mov rbp, rsp
|
||||
.cfi_def_cfa_register 6
|
||||
lea rax, buffer[rip]
|
||||
mov QWORD PTR -8[rbp], rax
|
||||
jmp .L17
|
||||
.L20:
|
||||
add QWORD PTR -8[rbp], 1
|
||||
.L17:
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
movzx eax, BYTE PTR [rax]
|
||||
cmp al, 10
|
||||
jne .L18
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
movzx eax, BYTE PTR [rax]
|
||||
test al, al
|
||||
jne .L19
|
||||
.L18:
|
||||
lea rax, buffer[rip+1024]
|
||||
cmp QWORD PTR -8[rbp], rax
|
||||
jb .L20
|
||||
.L19:
|
||||
lea rax, buffer[rip+1024]
|
||||
cmp QWORD PTR -8[rbp], rax
|
||||
jne .L21
|
||||
mov eax, 0
|
||||
jmp .L22
|
||||
.L21:
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
.L22:
|
||||
pop rbp
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE10:
|
||||
.size find_fullname_end, .-find_fullname_end
|
||||
.globl pop_fullname
|
||||
.type pop_fullname, @function
|
||||
pop_fullname:
|
||||
.LFB11:
|
||||
.cfi_startproc
|
||||
push rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
mov rbp, rsp
|
||||
.cfi_def_cfa_register 6
|
||||
sub rsp, 32
|
||||
mov eax, 0
|
||||
call find_fullname_end
|
||||
add rax, 1
|
||||
mov QWORD PTR -16[rbp], rax
|
||||
lea rdx, buffer[rip]
|
||||
mov rax, QWORD PTR -16[rbp]
|
||||
sub rax, rdx
|
||||
mov QWORD PTR -24[rbp], rax
|
||||
mov QWORD PTR -8[rbp], 0
|
||||
jmp .L24
|
||||
.L25:
|
||||
mov rdx, QWORD PTR -16[rbp]
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
add rax, rdx
|
||||
movzx eax, BYTE PTR [rax]
|
||||
lea rcx, buffer[rip]
|
||||
mov rdx, QWORD PTR -8[rbp]
|
||||
add rdx, rcx
|
||||
mov BYTE PTR [rdx], al
|
||||
mov rdx, QWORD PTR -16[rbp]
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
add rax, rdx
|
||||
mov BYTE PTR [rax], 0
|
||||
add QWORD PTR -8[rbp], 1
|
||||
.L24:
|
||||
mov eax, 1024
|
||||
sub rax, QWORD PTR -24[rbp]
|
||||
cmp QWORD PTR -8[rbp], rax
|
||||
jb .L25
|
||||
mov rax, QWORD PTR buffer_tail[rip]
|
||||
mov rdx, QWORD PTR -24[rbp]
|
||||
neg rdx
|
||||
add rax, rdx
|
||||
mov QWORD PTR buffer_tail[rip], rax
|
||||
nop
|
||||
leave
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE11:
|
||||
.size pop_fullname, .-pop_fullname
|
||||
.section .rodata
|
||||
.LC1:
|
||||
.string "count: "
|
||||
.LC2:
|
||||
.string "\n"
|
||||
.text
|
||||
.globl print_count
|
||||
.type print_count, @function
|
||||
print_count:
|
||||
.LFB12:
|
||||
.cfi_startproc
|
||||
push rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
mov rbp, rsp
|
||||
.cfi_def_cfa_register 6
|
||||
sub rsp, 32
|
||||
mov QWORD PTR -24[rbp], rdi
|
||||
mov edx, 8
|
||||
lea rax, .LC1[rip]
|
||||
mov rsi, rax
|
||||
mov edi, 1
|
||||
call write@PLT
|
||||
jmp .L27
|
||||
.L28:
|
||||
mov rcx, QWORD PTR -24[rbp]
|
||||
movabs rdx, -3689348814741910323
|
||||
mov rax, rcx
|
||||
mul rdx
|
||||
shr rdx, 3
|
||||
mov rax, rdx
|
||||
sal rax, 2
|
||||
add rax, rdx
|
||||
add rax, rax
|
||||
sub rcx, rax
|
||||
mov rdx, rcx
|
||||
mov eax, edx
|
||||
add eax, 48
|
||||
mov BYTE PTR -1[rbp], al
|
||||
mov rax, QWORD PTR -24[rbp]
|
||||
movabs rdx, -3689348814741910323
|
||||
mul rdx
|
||||
mov rax, rdx
|
||||
shr rax, 3
|
||||
mov QWORD PTR -24[rbp], rax
|
||||
lea rax, -1[rbp]
|
||||
mov edx, 1
|
||||
mov rsi, rax
|
||||
mov edi, 1
|
||||
call write@PLT
|
||||
.L27:
|
||||
cmp QWORD PTR -24[rbp], 0
|
||||
jne .L28
|
||||
mov edx, 1
|
||||
lea rax, .LC2[rip]
|
||||
mov rsi, rax
|
||||
mov edi, 1
|
||||
call write@PLT
|
||||
nop
|
||||
leave
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE12:
|
||||
.size print_count, .-print_count
|
||||
.globl get_name
|
||||
.type get_name, @function
|
||||
get_name:
|
||||
.LFB13:
|
||||
.cfi_startproc
|
||||
push rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
mov rbp, rsp
|
||||
.cfi_def_cfa_register 6
|
||||
sub rsp, 40
|
||||
mov QWORD PTR -40[rbp], rdi
|
||||
lea rax, buffer[rip]
|
||||
mov rdi, rax
|
||||
call find_second_word
|
||||
mov QWORD PTR -24[rbp], rax
|
||||
mov rax, QWORD PTR -24[rbp]
|
||||
mov QWORD PTR -8[rbp], rax
|
||||
jmp .L30
|
||||
.L31:
|
||||
add QWORD PTR -8[rbp], 1
|
||||
.L30:
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
movzx eax, BYTE PTR [rax]
|
||||
cmp al, 32
|
||||
jne .L31
|
||||
cmp QWORD PTR -8[rbp], 0
|
||||
jne .L32
|
||||
mov eax, -1
|
||||
jmp .L33
|
||||
.L32:
|
||||
mov QWORD PTR -16[rbp], 0
|
||||
jmp .L34
|
||||
.L35:
|
||||
mov rdx, QWORD PTR -24[rbp]
|
||||
mov rax, QWORD PTR -16[rbp]
|
||||
add rax, rdx
|
||||
mov rcx, QWORD PTR -40[rbp]
|
||||
mov rdx, QWORD PTR -16[rbp]
|
||||
add rdx, rcx
|
||||
movzx eax, BYTE PTR [rax]
|
||||
mov BYTE PTR [rdx], al
|
||||
add QWORD PTR -16[rbp], 1
|
||||
.L34:
|
||||
mov rdx, QWORD PTR -24[rbp]
|
||||
mov rax, QWORD PTR -16[rbp]
|
||||
add rax, rdx
|
||||
cmp rax, QWORD PTR -8[rbp]
|
||||
jb .L35
|
||||
mov eax, 0
|
||||
.L33:
|
||||
leave
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE13:
|
||||
.size get_name, .-get_name
|
||||
.globl main
|
||||
.type main, @function
|
||||
main:
|
||||
.LFB14:
|
||||
.cfi_startproc
|
||||
push rbp
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset 6, -16
|
||||
mov rbp, rsp
|
||||
.cfi_def_cfa_register 6
|
||||
sub rsp, 96
|
||||
mov DWORD PTR -84[rbp], edi
|
||||
mov QWORD PTR -96[rbp], rsi
|
||||
mov rax, QWORD PTR -96[rbp]
|
||||
add rax, 8
|
||||
mov rax, QWORD PTR [rax]
|
||||
mov rdi, rax
|
||||
call openfile
|
||||
mov DWORD PTR -12[rbp], eax
|
||||
mov edx, 64
|
||||
lea rax, name[rip]
|
||||
mov rsi, rax
|
||||
mov edi, 0
|
||||
call read@PLT
|
||||
mov QWORD PTR -8[rbp], 0
|
||||
mov QWORD PTR -80[rbp], 0
|
||||
mov QWORD PTR -72[rbp], 0
|
||||
mov QWORD PTR -64[rbp], 0
|
||||
mov QWORD PTR -56[rbp], 0
|
||||
mov QWORD PTR -48[rbp], 0
|
||||
mov QWORD PTR -40[rbp], 0
|
||||
mov QWORD PTR -32[rbp], 0
|
||||
mov QWORD PTR -24[rbp], 0
|
||||
.L39:
|
||||
mov eax, 0
|
||||
call find_fullname_end
|
||||
test rax, rax
|
||||
jne .L37
|
||||
mov eax, DWORD PTR -12[rbp]
|
||||
mov edi, eax
|
||||
call fill_buffer
|
||||
.L37:
|
||||
lea rax, -80[rbp]
|
||||
mov rdi, rax
|
||||
call get_name
|
||||
lea rax, -80[rbp]
|
||||
lea rdx, name[rip]
|
||||
mov rsi, rdx
|
||||
mov rdi, rax
|
||||
call namecmp
|
||||
test eax, eax
|
||||
je .L38
|
||||
add QWORD PTR -8[rbp], 1
|
||||
.L38:
|
||||
mov eax, 0
|
||||
call pop_fullname
|
||||
mov rdx, QWORD PTR buffer_tail[rip]
|
||||
lea rax, buffer[rip]
|
||||
cmp rdx, rax
|
||||
jne .L39
|
||||
mov rax, QWORD PTR -8[rbp]
|
||||
mov rdi, rax
|
||||
call print_count
|
||||
mov eax, 0
|
||||
leave
|
||||
.cfi_def_cfa 7, 8
|
||||
ret
|
||||
.cfi_endproc
|
||||
.LFE14:
|
||||
.size main, .-main
|
||||
.ident "GCC: (Debian 14.2.0-6) 14.2.0"
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
@ -1,292 +0,0 @@
|
||||
global _start
|
||||
|
||||
%define STDIN 0
|
||||
%define STDOUT 1
|
||||
%define STDERR 2
|
||||
%define RD_ONLY 00
|
||||
|
||||
%define FILE_BUF_SIZE 1024
|
||||
|
||||
section .data
|
||||
buffer_tail_ptr dq file_buffer ; stores pointer to the end of the buffer for file
|
||||
is_eof db 0 ; indicates if file ended
|
||||
count dq 0 ; сколько имен нашлось
|
||||
|
||||
section .bss
|
||||
name resb 128
|
||||
real_name_len resb 1
|
||||
name_size equ $-name
|
||||
|
||||
file_descriptor resq 1
|
||||
file_buffer resb FILE_BUF_SIZE
|
||||
|
||||
section .text
|
||||
|
||||
%macro PRINT_STR 1
|
||||
jmp %%run ; we define data right in code. It's not good, but ok for prototype
|
||||
%%string db %1
|
||||
%%string_len equ $-%%string
|
||||
%%run:
|
||||
mov rax, 1
|
||||
mov rdi, STDOUT
|
||||
mov rsi, %%string
|
||||
mov rdx, %%string_len
|
||||
syscall
|
||||
%endmacro
|
||||
|
||||
%macro MPUSH 1-*
|
||||
%rep %0
|
||||
push %1
|
||||
%rotate 1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
%macro MPOP_R 1-*
|
||||
%rotate -1
|
||||
%rep %0
|
||||
pop %1
|
||||
%rotate -1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
is_alpha: ; dl - symbol in ascii
|
||||
xor al, al
|
||||
cmp dl, 'A'
|
||||
jl .exit
|
||||
cmp dl, 'z'
|
||||
jg .exit
|
||||
; dl < 'Z' or dl > 'a'
|
||||
cmp dl, 'Z'
|
||||
jl .true
|
||||
cmp dl, 'a'
|
||||
jg .true
|
||||
jmp .exit
|
||||
.true:
|
||||
mov al, 1
|
||||
.exit:
|
||||
ret
|
||||
|
||||
fill_buf: ; read bytes from file to buffer
|
||||
MPUSH rdi, rsi, rcx, r11, rdx
|
||||
mov rdi, [buffer_tail_ptr]
|
||||
call buffer_left
|
||||
mov rdx, rax
|
||||
mov rax, 0
|
||||
mov rdi, [file_descriptor]
|
||||
mov rsi, [buffer_tail_ptr]
|
||||
; mov rdx, FILE_BUF_SIZE
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl file_read_error
|
||||
add [buffer_tail_ptr], rax
|
||||
cmp rax, FILE_BUF_SIZE
|
||||
jg .exit
|
||||
mov byte [is_eof], 1
|
||||
.exit:
|
||||
MPOP_R rdi, rsi, rcx, r11, rdx
|
||||
ret
|
||||
|
||||
read_name: ; ask user for name he is searching for
|
||||
MPUSH rax, rdi, rsi, rdx, rcx
|
||||
mov rax, 0
|
||||
mov rdi, STDIN
|
||||
mov rsi, name
|
||||
mov rdx, name_size
|
||||
syscall ; returns number of read bytes
|
||||
cmp rax, 0
|
||||
jl read_error
|
||||
test rax, rax
|
||||
jz no_name_error ; if no bytes were read
|
||||
mov [real_name_len], al
|
||||
; if user didn't end output with CTRL+D, there will be one extra symbol
|
||||
mov dl, [name + rax - 1]
|
||||
call is_alpha ; check if last symbol is alpha
|
||||
test al, al
|
||||
jnz .exit
|
||||
; if last symbol is \n or something simmilar, erase it
|
||||
xor rdx, rdx
|
||||
mov dl, byte [real_name_len]
|
||||
mov byte [name + rdx - 1], 0 ; clear last char if non alpha
|
||||
dec byte [real_name_len]
|
||||
.exit:
|
||||
MPOP_R rax, rdi, rsi, rdx, rcx
|
||||
ret
|
||||
|
||||
are_names_equal: ; takes first fullname from buff and compares
|
||||
MPUSH rcx, rsi, rdi
|
||||
; jump to second word
|
||||
mov rdi, file_buffer
|
||||
mov rcx, FILE_BUF_SIZE
|
||||
mov al, ' '
|
||||
repne scasb ; Теперь мы указываем на символ второго слова
|
||||
mov r8, rdi ; store for later
|
||||
repne scasb ; Ищем второй пробел, чтобы определить границы второго слова
|
||||
dec rdi ; Нашелся второй пробел. убавляем 1 чтобы указывать именно на него
|
||||
sub rdi, r8 ; len
|
||||
mov rax, rdi
|
||||
cmp al, [real_name_len]
|
||||
jnz .false ; if lenghts are different - already false
|
||||
mov rdi, r8 ; return to pointer on second word
|
||||
mov rsi, name
|
||||
xor rcx, rcx
|
||||
mov cl, [real_name_len]
|
||||
repe cmpsb
|
||||
jnz .false
|
||||
.true:
|
||||
mov rax, 1
|
||||
jmp .exit
|
||||
.false:
|
||||
mov rax, 0
|
||||
.exit:
|
||||
MPOP_R rcx, rsi ,rdi
|
||||
ret
|
||||
|
||||
buffer_left: ; counts free part of buffer
|
||||
push rdi
|
||||
mov rax, FILE_BUF_SIZE
|
||||
sub rdi, file_buffer
|
||||
sub rax, rdi
|
||||
pop rdi
|
||||
ret
|
||||
|
||||
pop_from_addr: ; frees buffer from one name until \n, takes 1 addr
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
MPUSH rdx, rax
|
||||
sub rsp, 24
|
||||
mov [rbp-24], rdi ; char* start
|
||||
call buffer_left
|
||||
mov [rbp-16], rax ; * count
|
||||
mov QWORD [rbp-8], 0 ; i
|
||||
;loop
|
||||
.loop:
|
||||
; read byte from start[i]
|
||||
mov rdx, [rbp-24]
|
||||
mov rax, [rbp-8]
|
||||
add rax, rdx
|
||||
mov al, [rax]
|
||||
; place to buffer[i]
|
||||
mov rdx, [rbp-8]
|
||||
add rdx, file_buffer
|
||||
mov [rdx], al
|
||||
; move zero to read position
|
||||
mov rdx, [rbp-24]
|
||||
mov rax, [rbp-8]
|
||||
add rax, rdx
|
||||
mov byte [rax], 0
|
||||
inc qword [rbp-8]
|
||||
; .cond:
|
||||
mov rax, [rbp-8]
|
||||
cmp rax, [rbp-16]
|
||||
jb .loop
|
||||
; update buffer_tail_ptr
|
||||
mov rax, [rbp-24]
|
||||
sub rax, file_buffer
|
||||
sub [buffer_tail_ptr], rax
|
||||
add rsp, 24
|
||||
MPOP_R rcx, rax
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
free_fullname:
|
||||
MPUSH rcx, rdi, rax
|
||||
mov rcx, FILE_BUF_SIZE
|
||||
mov rdi, file_buffer
|
||||
mov al, `\n`
|
||||
repne scasb
|
||||
call pop_from_addr
|
||||
MPOP_R rcx, rdi, rax
|
||||
ret
|
||||
|
||||
_start:
|
||||
; --parse command_line arguments
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
; --check if there is any args
|
||||
mov rax, [rbp + 8]
|
||||
cmp rax, 2
|
||||
jl no_filepath
|
||||
; --if argument specified, try to read path
|
||||
mov rdi, [rbp + 8*3]
|
||||
mov rax, 0x2 ; open file
|
||||
mov rsi, RD_ONLY
|
||||
xor rdx, rdx
|
||||
syscall ; filepath already should be in rdi
|
||||
mov [file_descriptor], rax
|
||||
cmp rax, 0
|
||||
jl file_open_error
|
||||
; --asking user what name we are looking for
|
||||
PRINT_STR `Input name you are looking for: `
|
||||
call read_name
|
||||
; -- find number of occurenses. HARDEST PART
|
||||
.fill_buff_prefix:
|
||||
call fill_buf
|
||||
.name_cmp_loop:
|
||||
mov rdi, name
|
||||
call are_names_equal
|
||||
test rax, rax
|
||||
jz .no_increment
|
||||
inc qword [count]
|
||||
.no_increment:
|
||||
call free_fullname
|
||||
; iseof && buffer_tail_ptr == file_buffer
|
||||
mov rax, [buffer_tail_ptr]
|
||||
cmp rax, file_buffer
|
||||
jne .name_cmp_loop
|
||||
mov al, [is_eof]
|
||||
test al, al
|
||||
jz .fill_buff_prefix
|
||||
;formatted output
|
||||
mov rax, 1 ; write
|
||||
mov rdi, STDOUT
|
||||
mov rsi, name
|
||||
mov rdx, [real_name_len]
|
||||
syscall
|
||||
PRINT_STR " ............... "
|
||||
; printing number
|
||||
mov rax, [count]
|
||||
mov rbx, 10
|
||||
xor rcx, rcx
|
||||
.number_converting_loop:
|
||||
xor rdx, rdx
|
||||
div rbx
|
||||
; push 1 byte to stack
|
||||
add dl, '0' ; convert to ascii
|
||||
dec rsp
|
||||
mov [rsp], dl
|
||||
inc rcx
|
||||
test rax, rax
|
||||
jnz .number_converting_loop
|
||||
mov rax, 1
|
||||
mov rdi, STDOUT
|
||||
mov rsi, rsp
|
||||
mov rdx, rcx
|
||||
syscall
|
||||
PRINT_STR `\n`
|
||||
jmp exit
|
||||
|
||||
read_error:
|
||||
PRINT_STR `Error while reading the name\n`
|
||||
jmp exit
|
||||
|
||||
no_name_error:
|
||||
PRINT_STR `No propper name given\n`
|
||||
jmp exit
|
||||
|
||||
file_open_error:
|
||||
PRINT_STR `Failed to open the file\n`
|
||||
jmp exit
|
||||
|
||||
file_read_error:
|
||||
PRINT_STR `Error while reading the file\n`
|
||||
jmp exit
|
||||
|
||||
no_filepath:
|
||||
PRINT_STR `You haven't specified a file to read from\n`
|
||||
jmp exit
|
||||
|
||||
exit:
|
||||
mov rax, 60
|
||||
mov rdi, 0
|
||||
syscall
|
||||
|
||||
Reference in New Issue
Block a user