Skip to content

Commit 7c97947

Browse files
committed
Initial commit
0 parents  commit 7c97947

File tree

5 files changed

+807
-0
lines changed

5 files changed

+807
-0
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Lab1-ProgrammingLanguages
2+

lib.inc

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
section .text
2+
3+
4+
; Принимает код возврата и завершает текущий процесс
5+
6+
exit:
7+
mov rax, 60 ; 'exit' syscall number
8+
syscall
9+
ret
10+
11+
; Принимает указатель на нуль-терминированную строку, возвращает её длину
12+
13+
string_length:
14+
xor rax, rax
15+
.main_loop:
16+
cmp byte[rdi + rax], 0
17+
je .end
18+
inc rax
19+
jmp .main_loop
20+
.end:
21+
ret
22+
23+
; Принимает указатель на нуль-терминированную строку, выводит её в stdout
24+
25+
print_string:
26+
call string_length
27+
mov rsi, rdi
28+
mov rdx, rax
29+
mov rax, 1 ; 'write' syscall number
30+
mov rdi, 1 ; stdout descriptor
31+
syscall
32+
ret
33+
34+
; Принимает код символа и выводит его в stdout
35+
36+
print_char:
37+
xor rax, rax
38+
push rdi
39+
mov rsi, rsp
40+
pop rax
41+
mov rdx, 1
42+
mov rax, 1 ; 'write' syscall number
43+
mov rdi, 1 ; stdout descriptor
44+
syscall
45+
ret
46+
47+
; Переводит строку (выводит символ с кодом 0xA)
48+
49+
print_newline:
50+
mov rdi, 0xA
51+
call print_char
52+
ret
53+
54+
; Выводит беззнаковое 8-байтовое число в десятичном формате
55+
; Совет: выделите место в стеке и храните там результаты деления
56+
; Не забудьте перевести цифры в их ASCII коды.
57+
58+
print_uint:
59+
xor rcx, rcx
60+
xor rdx, rdx
61+
mov rbx, 10 ; divider to get digits
62+
mov rax, rdi
63+
.stack_filling:
64+
xor rdx, rdx
65+
div rbx ; next digit
66+
add rdx, '0' ; offset to save ascii-code
67+
push rdx
68+
inc rcx
69+
test rax, rax ; loop while rax has content
70+
jnz .stack_filling
71+
.print_from_stack:
72+
pop rdx
73+
mov rdi, rdx
74+
push rcx ; save reg value before calling
75+
call print_char
76+
pop rcx
77+
dec rcx
78+
test rcx, rcx ; loop while rcx > 0
79+
jnz .print_from_stack
80+
xor rbx, rbx ; respect convention :)
81+
ret
82+
83+
; Выводит знаковое 8-байтовое число в десятичном формате
84+
85+
print_int:
86+
or rdi, rdi ; set flags
87+
jns .end ; if number is positive just print it!
88+
push rdi ; else add '-'
89+
mov rdi, '-'
90+
call print_char
91+
pop rdi
92+
neg rdi
93+
.end:
94+
jmp print_uint
95+
ret
96+
97+
; Принимает два указателя на нуль-терминированные строки, возвращает 1 если они равны, 0 иначе
98+
99+
string_equals:
100+
call string_length
101+
mov r8, rdi
102+
mov r9, rax
103+
mov rdi, rsi
104+
call string_length
105+
cmp r9, rax ; compare lengths
106+
jne .not_equals
107+
mov rcx, 0
108+
mov rsi, r8
109+
.char_loop:
110+
cmp rcx, r9
111+
je .equals
112+
mov al, byte[rsi + rcx]
113+
mov dl, byte[rdi + rcx]
114+
cmp al, dl ; compare each chars
115+
jne .not_equals
116+
inc rcx
117+
jmp .char_loop
118+
.not_equals:
119+
xor rax, rax ; false
120+
ret
121+
.equals:
122+
mov rax, 1 ; true
123+
ret
124+
125+
; Читает один символ из stdin и возвращает его. Возвращает 0 если достигнут конец потока
126+
127+
read_char:
128+
xor rax, rax
129+
xor rdi, rdi
130+
push 0
131+
mov rdx, 1 ; length
132+
mov rsi, rsp ; descriptor
133+
syscall
134+
pop rax
135+
ret
136+
137+
; Принимает: адрес начала буфера, размер буфера
138+
; Читает в буфер слово из stdin, пропуская пробельные символы в начале, .
139+
; Пробельные символы это пробел 0x20, табуляция 0x9 и перевод строки 0xA.
140+
; Останавливается и возвращает 0 если слово слишком большое для буфера
141+
; При успехе возвращает адрес буфера в rax, длину слова в rdx.
142+
; При неудаче возвращает 0 в rax
143+
; Эта функция должна дописывать к слову нуль-терминатор
144+
145+
read_word:
146+
xor rcx, rcx
147+
push rdi ; save regs values before calling
148+
push rsi
149+
push rcx
150+
.spaces_skip_loop:
151+
call read_char
152+
cmp rax, 0x20
153+
je .spaces_skip_loop
154+
cmp rax, 0x9
155+
je .spaces_skip_loop
156+
cmp rax, 0xA
157+
je .spaces_skip_loop
158+
.main_loop:
159+
pop rcx ; get regs values after calling
160+
pop rsi
161+
pop rdi
162+
test rax, rax ; check overflow
163+
jz .end
164+
cmp rax, 0x20 ; check spaces again :(
165+
je .end
166+
cmp rax, 0x9
167+
je .end
168+
cmp rax, 0xA
169+
je .end
170+
mov [rdi + rcx], al
171+
inc rcx ; counter
172+
dec rsi
173+
jz .end
174+
push rdi ; save regs values before calling
175+
push rsi
176+
push rcx
177+
call read_char
178+
jmp .main_loop
179+
.end:
180+
test rsi, rsi ; check rsi = 0?
181+
jnz .success ; overflow
182+
xor rax, rax
183+
ret
184+
.success:
185+
mov byte[rdi + rcx], 0
186+
mov rax, rdi
187+
mov rdx, rcx
188+
ret
189+
190+
; Принимает указатель на строку, пытается
191+
; прочитать из её начала беззнаковое число.
192+
; Возвращает в rax: число, rdx : его длину в символах
193+
; rdx = 0 если число прочитать не удалось
194+
195+
parse_uint:
196+
xor rax, rax
197+
xor rcx, rcx
198+
mov rbx, 10 ; divider to get digits
199+
.read_digit:
200+
xor r8, r8
201+
mov r8b, byte [rdi + rcx]
202+
sub r8, '0' ; set offset for ascii-code
203+
cmp r8, 0
204+
jl .end ; no-digit char found
205+
cmp r8, 9
206+
jg .end ; no-digit char found
207+
mul rbx
208+
add al, r8b ; save current digit
209+
inc rcx
210+
jmp .read_digit
211+
.parse_error:
212+
mov rdx, 0
213+
ret
214+
.end:
215+
xor rbx, rbx ; respect convention :)
216+
cmp rcx, 0
217+
je .parse_error ; line started with not a digit char
218+
mov rdx, rcx
219+
ret
220+
221+
; Принимает указатель на строку, пытается
222+
; прочитать из её начала знаковое число.
223+
; Если есть знак, пробелы между ним и числом не разрешены.
224+
; Возвращает в rax: число, rdx : его длину в символах (включая знак, если он был)
225+
; rdx = 0 если число прочитать не удалось
226+
227+
parse_int:
228+
cmp byte [rdi], '-'
229+
jne parse_uint
230+
inc rdi ; case with neg number
231+
call parse_uint
232+
neg rax
233+
inc rdx
234+
ret
235+
236+
237+
; Принимает указатель на строку, указатель на буфер и длину буфера
238+
; Копирует строку в буфер
239+
; Возвращает длину строки если она умещается в буфер, иначе 0
240+
241+
string_copy:
242+
call string_length ; check overflow
243+
cmp rax, rdx
244+
jge .overflow
245+
xor rax, rax
246+
xor rdx, rdx
247+
.copy_next:
248+
mov dl, [rdi + rax]
249+
mov [rsi + rax], dl
250+
test dl, dl ; if string length = 0 then goto end
251+
je .end
252+
inc rax
253+
jmp .copy_next
254+
.overflow:
255+
xor rax, rax
256+
.end:
257+
xor rdx, rdx ; respect convention :)
258+
ret

0 commit comments

Comments
 (0)