|
|||
10. substract_stringНа вход ничего не принимает, работает с буферами first_number и second_number. На выходе кладёт в rdx флаг результата операции: 0, если результат разности больше нуля, 1 — в обратном случае. В computation_result кладётся число-строка — результат вычета.
Описание работы: Вычисляется длина буферов first_number и second_number и складывается в r10 и r11 соответственно. Регистр r12 отвечает за текущую длину строки, используется для динамического увеличения результата: когда на очередной итерации мы получаем локальное вычисление разности, мы дописываем эту число-строку в computation_result, а затем со сдвигом 1 дописываем r12 символов из condensator. На очередном шаге цикла, проверяем, что уменьшаемое (вычитаемое) не закончилось и вытаскиваем нужный нам байт и кладём его в регистр rax (rbx), в противном случае в эти же регистры пишем «0», после чего отмечаем в регистре r14 (r13), что вычитать больше не из чего (нечего). После чего вызываем метод substact_simple и сразу записывается результат в computation_result, аналогичным с add_string способом. Повторяем всё перечисленное, пока есть из чего и что вычитать. Как только вычитать и уменьшать нечего, проверяется флаг rdx. Если он 0 — выравниваем computation_result слева и метод заканчивает работу, в противном случае строится ближайшая степень десятки, которая больше, чем то, что лежит в данный момент в computation_result, причём без выравнивания: это важно. После чего степень десятки кладётся в first_number, computation_result — в second_number и метод вызывает сам себя. Результат работы рекурсивно вызванного метода, с установленным флагом rdx в «1» будет нужным ответом. По окончании работы, метод обнуляет все буферы, с которыми он работал.
; | input ; first_number ; second_number ; | output ; computation_result ; rdx = sign substract_string: push rax push rbx push rcx push r10 push r11 push r12 push r13 push r14 xor r10, r10 xor r11, r11 xor rbx, rbx xor r13, r13 xor r14, r14 mov rax, first_number call get_length_number mov r10, rax dec r10 mov rax, second_number call get_length_number mov r11, rax dec r11 xor rdx, rdx xor r12, r12 . compute: inc r12 . first_equal: cmp r10, 0xffffffffffffffff jne. first_char mov rax, '0' cmp r14, 1 je. second_equal inc r14 jmp. second_equal . first_char: push rbx mov rbx, first_number mov al, byte [rbx + r10] pop rbx dec r10 . second_equal: cmp r11, 0xffffffffffffffff jne. second_char mov rbx, '0' cmp r13, 1 je. recieve_result inc r13 jmp. recieve_result . second_char: push rax mov rax, second_number mov bl, byte [rax + r11] pop rax dec r11 . recieve_result: call substract_simple . save_old: push rsi push rdi mov rcx, r12 mov rdi, condensator mov rsi, computation_result rep movsb pop rdi pop rsi . move_new: push rsi push rdi mov rdi, helper stosq mov rcx, 1 mov rdi, computation_result mov rsi, helper rep movsb pop rdi pop rsi . compilation: push rsi push rdi mov rcx, r12 mov rdi, computation_result inc rdi mov rsi, condensator rep movsb pop rdi pop rsi . check_for_end: push r13 add r13, r14 cmp r13, 2 je. end_addinng pop r13 jmp. compute . end_addinng: pop r13 cmp rdx, 0 je. close jmp. negative_result . negative_result: push rsi push rdi mov rax, first_number call clean_buffer inc r12 mov rax, r12 dec r12 call building_ten_degree mov rax, second_number call clean_buffer mov rcx, r12 mov rdi, second_number mov rsi, computation_result rep movsb mov rax, computation_result call clean_buffer call substract_string mov rdx, 1 pop rdi pop rsi . close: . clean_buffers: mov rax, condensator call clean_buffer mov rax, helper call clean_buffer mov rax, first_number call clean_buffer mov rax, second_number call clean_buffer call buffer_equalizer pop r14 pop r13 pop r12 pop r11 pop r10 pop rcx pop rbx pop rax ret
11. cut_left На вход принимает в регистре rax указатель на буфер-источник, из которого будет производиться копирование, в регистре rbx буфер-цель, куда будет копироваться часть число-строки. В регистре rcx — количество символов, которое должно в итоге оказаться справа. На выходе ничего не возвращает.
Описание работы:
; | input ; rax = pointer on source segmented buffer ; rbx = pointer on target segmented buffer ; rcx = count byte in right ; | output ; empty cut_left: push rdx push r8 push r9 push rsi push rdi mov r8, rax mov r9, rbx mov rax, rbx call clean_buffer xor rbx, rbx xor rdx, rdx mov rax, r8 call get_length_number cmp rax, rcx jg. cut jmp. zero_left . cut: sub rax, rcx mov rcx, rax mov rdi, r9 mov rsi, r8 rep movsb jmp. close . zero_left: mov rax, '0' mov rdi, r9 stosb . close: pop rdi pop rsi pop r9 pop r8 pop rdx ret
12. cut_right На вход принимает в регистре rax указатель на буфер-источник, из которого будет производиться копирование, в регистре rbx буфер-цель, куда будет копироваться часть число-строки. На выходе ничего не возвращает.
Описание работы:
; | input ; rax = pointer on source segmented buffer ; rbx = pointer on target segmented buffer ; rcx = count bytes ; | output ; empty cut_right: push rdx push r8 push r9 push rdi push rsi mov r8, rax mov r9, rbx mov rax, rbx call clean_buffer xor rbx, rbx mov rax, r8 call get_length_number cmp rcx, rax jg. simple_shift sub rax, rcx add r8, rax mov rdi, r9 mov rsi, r8 rep movsb jmp. close . simple_shift: mov rdi, r9 mov rsi, r8 mov rcx, rax rep movsb . close: pop rsi pop rdi pop r9 pop r8 pop rdx ret
13. multiply_string На вход принимает два параметра: в rax лежит указатель на буфер, в котором находится число-строка, которую требуется умножить на 10 в степени, которая указана в регистре rbx. На выходе ничего не возвращает. Изменяет число-строку, которая находилась по адресу, указанному в rax.
Описание работы: Вычисляется длина пришедшей число-строки, находящейся в буфере. После чего происходит сдвиг указателя вставки на полученное число байт. После этого rbx раз справа дописывается «0».
; | input ; rax = pointer on buffer ; rbx = degree of ten ; | output ; empty multiply_string: push rdx push rsi push rdi mov rdi, rax mov rdx, rbx xor rbx, rbx call get_length_number add rdi, rax mov rax, '0' . multiply: cmp rdx, 0 je. close dec rdx stosb jmp. multiply . close: pop rdi pop rsi pop rdx ret
14. decide_pointer На вход принимает один аргумент, а так же напрямую работает с буфером recursion_depth. Единственный аргумент — rax, содержит в себе указатель на сегментированный буфер. На выходе в rax возвращает указатель на сегмент из буфера-источника.
Описание работы: Из recursion_depth загружается байт, который говорит о текущей глубине рекурсии. Затем этот байт умножается на размер одной ячейки сегментного буфера: закреплён за константой SIZE, равен 64. После чего к принимаемому в rax адресу добавляется полученный сдвиг, после чего метод завершает работу.
; | input ; rax = pointer on segmented-buffer ; recursion_depth ; | output ; rax = pointer on cell of segmented-buffer decide_pointer: push rbx push rcx push rsi mov rcx, rax xor rax, rax mov rsi, recursion_depth lodsb mov rbx, 64 mul rbx add rcx, rax mov rax, rcx pop rsi pop rcx pop rbx ret
15. parse_input На вход ничего не принимает, работает с буфером input_expression. На выходе ничего не возвращает, кладёт результат разбиения input_expression в P1_x и P1_y.
Описание работы: Вычисляется длина до ближайшего пробела, после чего кусок строки вычисленной длины копируется в P1_x. Затем указатель сдвигается на 3 байта: символы « * » и от них вычисляется длина до конца строки. Остаток строки заносится в P1_y.
; | input ; input_expression ; | output ; P1_x[0] ; P1_y[0] parse_input: push rax push rbx push rcx push rdx xor rbx, rbx mov rax, input_expression . next_iter: cmp [rax + rbx], byte'' je. first_string inc rbx jmp. next_iter . first_string: mov rcx, rbx mov rdi, P1_x mov rsi, input_expression rep movsb add rbx, 3 add rsi, 3 mov rax, input_expression call get_length_number dec rax . second_string: mov rcx, rax mov rdi, P1_y rep movsb pop rdx pop rbx pop rcx pop rdx ret 16. to_string_converter На вход принимает в качестве аргумента регистр rax, в котором хранится байт, который необходимо перевести в вид число-строки. На выходе возвращает число-строку, находящуюся в rax.
Описание работы: Очищается вспомогательный буфер helper. После чего идёт последовательное целочисленное деление на 10 до тех пор, пока это возможно (пока делимое не становится равным 0), остаток от деления кладётся в стек. Потом из стека всё последовательно изымается и складывается в буфер helper. Если на вход нам попалось число 0, то метод отработает корректно. После содержимое буфера перекладывается в rax, сам буфер очищается.
; | input ; rax = number ; | output ; rax = equality number-string to_string_converter: push rbx push rcx push r8 push rdx push rdi push rsi mov rbx, rax mov rax, helper call clean_buffer xor rcx, rcx xor r8, r8 mov rax, rbx mov rbx, 10 . next_iter: cmp rax, 0 je. zero_checker xor rdx, rdx div rbx add rdx, '0' push rdx inc r8 jmp. next_iter . zero_checker: cmp r8, 0 jne. build mov rax, '0' jmp. close . build: cmp r8, 0 je. ending mov rdi, helper add rdi, rcx pop rdx mov rax, rdx stosb dec r8 inc rcx jmp. build . ending: xor rdx, rdx mov rsi, helper lodsq mov rbx, rax mov rax, helper call clean_buffer mov rax, rbx . close: pop rsi pop rdi pop rdx pop r8 pop rcx pop rbx ret
17. to_number_converter На вход принимает в регистре rax число-строку. На выходе возвращает в rax преобразованное число.
Описание работы:
; | input ; rax = number-string ; | output ; rax = number to_number_converter: push rbx push rcx push rsi push rdx mov rbx, rax mov rax, helper call clean_buffer mov rax, rbx mov rdi, helper stosq xor rbx, rbx mov rax, helper call get_length_number mov rcx, rax mov rbx, 10 mov rax, 1 push rcx . create_degree: cmp rcx, 0 je. continue dec rcx mul rbx jmp. create_degree . continue: pop rcx mov rbx, rax mov rax, 0 mov rsi, helper . next_iter: cmp rcx, 0 je. close push rax push rdx xor rdx, rdx mov rax, rbx mov rbx, 10 div rbx mov rbx, rax pop rdx pop rax dec rcx push rax xor rax, rax lodsb sub rax, '0' mul rbx mov rdx, rax pop rax add rax, rdx jmp. next_iter . close: push rax mov rax, helper call clean_buffer pop rax pop rdx pop rsi pop rcx pop rbx ret
18. multiply_numbers На вход принимает в качестве аргументов rax и rbx: в них находятся число-строки дли перемножения На выходе возвращает в регистре rax число-строку — результат произведения
Описание работы: Используя ранее реализованные to_string_converter и to_number_converter, метод преобразует число строки в числа, перемножает их, и преобразует назад в число-строку.
; | input ; rax = first number-string ; rbx = second number - string ; | output ; rax = multiply number-string multiply_numbers: push rcx push rdx call to_number_converter mov rcx, rax mov rax, rbx call to_number_converter mul rcx call to_string_converter pop rdx pop rcx ret
|
|||
|