Хелпикс

Главная

Контакты

Случайная статья





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 — количество символов, которое должно в итоге оказаться справа.

На выходе ничего не возвращает.

 

Описание работы:
Буфер-цель очищается. После происходит оценка длины число-строки источника, в случае, если есть что копировать — копирует. Если нет — вставляет в целевой буфер «0».

 

; | 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 преобразованное число.

 

Описание работы:
Очищается вспомогательный буфер helper. В него загружается число-строка из rax. Далее происходит вычисление длины этой число-строки. Потом строится подходящая степень десятки и сохраняется в rbx. После этого начинается побайтовое чтение из буфера. Байт вытаскивается, уменьшается на символ «0», умножается на подходящую степень, а далее складывается с полученным ранее результатом. После чего буфер очищается и метод завершает свою работу.

 

; | 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

 



  

© helpiks.su При использовании или копировании материалов прямая ссылка на сайт обязательна.