section .data
prompt1 db "Введите первое число: ", 0
prompt2 db "Введите второе число: ", 0
result_msg db "Сумма: ", 0
newline db 10, 0
buffer times 256 db 0
num1 times 32 db 0 ; Максимум 32 байта для первого числа
num2 times 32 db 0 ; Максимум 32 байта для второго числа
sum times 32 db 0 ; Результат сложения
section .bss
N resb 1 ; Размер чисел в байтах (1-32)
section .text
global _start
_start:
; Получаем размер чисел N от пользователя
mov rax, prompt1
call print_string
call read_hex_byte
mov [N], al
; Проверяем корректность N (1-32)
cmp al, 1
jl exit_program
cmp al, 32
jg exit_program
; Читаем первое число
mov rax, prompt1
call print_string
movzx rcx, byte [N]
mov rdi, num1
call read_hex_number
; Читаем второе число
mov rax, prompt2
call print_string
movzx rcx, byte [N]
mov rdi, num2
call read_hex_number
; Складываем числа
movzx rcx, byte [N]
call add_numbers
; Выводим результат
mov rax, result_msg
call print_string
movzx rcx, byte [N]
mov rsi, sum
call print_hex_number
; Новая строка
mov rax, newline
call print_string
exit_program:
mov rax, 60 ; sys_exit
xor rdi, rdi ; код возврата 0
syscall
; ============================================
; Процедура сложения двух чисел
; Вход: RCX = размер чисел в байтах
; num1, num2 - складываемые числа
; Выход: sum = num1 + num2
; ============================================
add_numbers:
push rcx
push rsi
push rdi
xor rsi, rsi ; Индекс байта
clc ; Сбрасываем флаг переноса
.add_loop:
mov al, [num1 + rsi]
mov bl, [num2 + rsi]
; Сложение с учетом переноса
adc al, bl
mov [sum + rsi], al
inc rsi
loop .add_loop ; Уменьшает RCX и повторяет если не 0
pop rdi
pop rsi
pop rcx
ret
; ============================================
; Чтение шестнадцатеричного числа
; Вход: RCX = количество байтов
; RDI = указатель на буфер для числа
; ============================================
read_hex_number:
push rcx
push rdi
push rsi
; Читаем строку
mov rax, 0 ; sys_read
mov rdi, 0 ; stdin
mov rsi, buffer
mov rdx, 256
syscall
; Конвертируем hex строку в число
mov rsi, buffer
mov rdx, rdi ; Сохраняем указатель на выходной буфер
; Пропускаем пробелы
.skip_spaces:
lodsb
cmp al, ' '
je .skip_spaces
cmp al, 10 ; Новая строка
je .done
cmp al, 13 ; Возврат каретки
je .done
dec rsi ; Возвращаемся к первому символу
; Определяем, отрицательное ли число
mov al, [rsi]
cmp al, '-'
jne .parse_positive
; Отрицательное число
inc rsi ; Пропускаем минус
call parse_hex_string
call negate_number
jmp .done
.parse_positive:
call parse_hex_string
.done:
pop rsi
pop rdi
pop rcx
ret
; ============================================
; Парсинг шестнадцатеричной строки
; Вход: RSI = указатель на строку
; RCX = размер числа в байтах
; RDX = указатель на буфер результата
; ============================================
parse_hex_string:
push rcx
push rdx
push rbx
mov rdi, rdx
add rdi, rcx
dec rdi ; RDI указывает на последний байт буфера
; Очищаем буфер
mov rdx, rdi
.clear_buffer:
mov byte [rdx], 0
dec rdx
cmp rdx, rdi
jge .clear_buffer
xor rbx, rbx ; Счетчик считанных символов
.read_char:
lodsb ; Загружаем символ из строки
; Проверяем конец строки
cmp al, 0
je .parse_done
cmp al, 10 ; Новая строка
je .parse_done
cmp al, 13 ; Возврат каретки
je .parse_done
cmp al, ' ' ; Пробел
je .parse_done
; Преобразуем символ в число
call char_to_hex
cmp al, 0xFF
je .invalid_char
; Сдвигаем текущее значение и добавляем новое
push rcx
mov rcx, 4 ; Сдвигаем на 4 бита
.shift_buffer:
push rdi
mov rdx, rdi
sub rdx, rcx
inc rdx
.shift_loop:
mov bl, [rdx]
shl bl, 4
mov [rdx], bl
inc rdx
cmp rdx, rdi
jle .shift_loop
pop rdi
; Добавляем новый полубайт
mov bl, [rdi]
or bl, al
mov [rdi], bl
pop rcx
inc rbx
cmp rbx, rcx ; Проверяем, не превысили ли размер
jl .read_char
.parse_done:
pop rbx
pop rdx
pop rcx
ret
.invalid_char:
; В случае ошибки возвращаем 0
mov rdi, rdx
mov byte [rdi], 0
jmp .parse_done
; ============================================
; Преобразование символа в шестнадцатеричное число
; Вход: AL = символ
; Выход: AL = число (0-15) или 0xFF при ошибке
; ============================================
char_to_hex:
cmp al, '0'
jl .invalid
cmp al, '9'
jg .check_upper
sub al, '0'
ret
.check_upper:
cmp al, 'A'
jl .invalid
cmp al, 'F'
jg .check_lower
sub al, 'A' - 10
ret
.check_lower:
cmp al, 'a'
jl .invalid
cmp al, 'f'
jg .invalid
sub al, 'a' - 10
ret
.invalid:
mov al, 0xFF
ret
; ============================================
; Инверсия числа (дополнительный код)
; Вход: RCX = размер числа в байтах
; RDI = указатель на число
; ============================================
negate_number:
push rcx
push rsi
mov rsi, rdi
add rsi, rcx
dec rsi ; RSI указывает на последний байт
; Инвертируем все биты
.not_loop:
not byte [rsi]
dec rsi
cmp rsi, rdi
jge .not_loop
; Добавляем 1
mov rsi, rdi
mov byte al, 1
.add_one_loop:
add byte [rsi], al
jnc .done_negate
mov al, 1
inc rsi
cmp rsi, rdi
add rsi, rcx
dec rsi
jle .add_one_loop
.done_negate:
pop rsi
pop rcx
ret
; ============================================
; Вывод шестнадцатеричного числа
; Вход: RCX = размер числа в байтах
; RSI = указатель на число
; ============================================
print_hex_number:
push rcx
push rsi
push rdi
; Проверяем знак числа
mov al, [rsi + rcx - 1]
test al, 0x80 ; Проверяем старший бит
jz .print_positive
; Отрицательное число
push rcx
push rsi
; Копируем число во временный буфер
mov rdi, buffer
rep movsb
pop rsi
pop rcx
; Выводим минус
mov byte [buffer], '-'
mov rax, buffer
call print_string
; Преобразуем в дополнительный код
mov rdi, rsi
call negate_number
dec rcx ; Уже вывели минус
.print_positive:
mov rdi, rsi
add rdi, rcx
dec rdi ; RDI указывает на последний байт
; Пропускаем ведущие нули
.find_first_nonzero:
cmp byte [rdi], 0
jne .print_hex
dec rdi
cmp rdi, rsi
jge .find_first_nonzero
; Все нули - выводим "0"
mov byte [buffer], '0'
mov byte [buffer + 1], 0
mov rax, buffer
call print_string
jmp .done_print
.print_hex:
; Преобразуем байт в два hex символа
mov al, [rdi]
mov bl, al
shr al, 4
call hex_to_char
mov [buffer], al
mov al, bl
and al, 0x0F
call hex_to_char
mov [buffer + 1], al
mov byte [buffer + 2], 0
mov rax, buffer
call print_string
dec rdi
cmp rdi, rsi
jge .print_hex
.done_print:
pop rdi
pop rsi
pop rcx
ret
; ============================================
; Преобразование числа 0-15 в символ hex
; Вход: AL = число (0-15)
; Выход: AL = символ hex
; ============================================
hex_to_char:
cmp al, 10
jl .digit
add al, 'A' - 10
ret
.digit:
add al, '0'
ret
; ============================================
; Чтение одного байта в hex
; Выход: AL = прочитанное число
; ============================================
read_hex_byte:
push rsi
push rdx
mov rax, 0 ; sys_read
mov rdi, 0 ; stdin
mov rsi, buffer
mov rdx, 3 ; Максимум 2 символа + новая строка
syscall
; Конвертируем hex в число
mov rsi, buffer
xor rax, rax
.read_digit:
mov dl, [rsi]
cmp dl, 10 ; Новая строка
je .done_read
cmp dl, 13 ; Возврат каретки
je .done_read
call char_to_hex
cmp al, 0xFF
je .invalid_input
shl rax, 4
add al, [rsi]
inc rsi
jmp .read_digit
.invalid_input:
xor al, al
.done_read:
pop rdx
pop rsi
ret
; ============================================
; Вывод строки
; Вход: RAX = указатель на строку
; ============================================
print_string:
push rsi
push rdx
push rdi
mov rsi, rax
mov rdx, 0
.strlen_loop:
cmp byte [rsi + rdx], 0
je .strlen_done
inc rdx
jmp .strlen_loop
.strlen_done:
mov rax, 1 ; sys_write
mov rdi, 1 ; stdout
syscall
pop rdi
pop rdx
pop rsi
ret
c2VjdGlvbiAuZGF0YQogICAgcHJvbXB0MSAgICBkYiAi0JLQstC10LTQuNGC0LUg0L/QtdGA0LLQvtC1INGH0LjRgdC70L46ICIsIDAKICAgIHByb21wdDIgICAgZGIgItCS0LLQtdC00LjRgtC1INCy0YLQvtGA0L7QtSDRh9C40YHQu9C+OiAiLCAwCiAgICByZXN1bHRfbXNnIGRiICLQodGD0LzQvNCwOiAiLCAwCiAgICBuZXdsaW5lICAgIGRiIDEwLCAwCiAgICBidWZmZXIgICAgIHRpbWVzIDI1NiBkYiAwCiAgICBudW0xICAgICAgIHRpbWVzIDMyIGRiIDAgICAgOyDQnNCw0LrRgdC40LzRg9C8IDMyINCx0LDQudGC0LAg0LTQu9GPINC/0LXRgNCy0L7Qs9C+INGH0LjRgdC70LAKICAgIG51bTIgICAgICAgdGltZXMgMzIgZGIgMCAgICA7INCc0LDQutGB0LjQvNGD0LwgMzIg0LHQsNC50YLQsCDQtNC70Y8g0LLRgtC+0YDQvtCz0L4g0YfQuNGB0LvQsAogICAgc3VtICAgICAgICB0aW1lcyAzMiBkYiAwICAgIDsg0KDQtdC30YPQu9GM0YLQsNGCINGB0LvQvtC20LXQvdC40Y8KCnNlY3Rpb24gLmJzcwogICAgTiAgICAgICAgICByZXNiIDEgICAgICAgICAgIDsg0KDQsNC30LzQtdGAINGH0LjRgdC10Lsg0LIg0LHQsNC50YLQsNGFICgxLTMyKQoKc2VjdGlvbiAudGV4dAogICAgZ2xvYmFsIF9zdGFydAoKX3N0YXJ0OgogICAgOyDQn9C+0LvRg9GH0LDQtdC8INGA0LDQt9C80LXRgCDRh9C40YHQtdC7IE4g0L7RgiDQv9C+0LvRjNC30L7QstCw0YLQtdC70Y8KICAgIG1vdiByYXgsIHByb21wdDEKICAgIGNhbGwgcHJpbnRfc3RyaW5nCiAgICBjYWxsIHJlYWRfaGV4X2J5dGUKICAgIG1vdiBbTl0sIGFsCiAgICAKICAgIDsg0J/RgNC+0LLQtdGA0Y/QtdC8INC60L7RgNGA0LXQutGC0L3QvtGB0YLRjCBOICgxLTMyKQogICAgY21wIGFsLCAxCiAgICBqbCBleGl0X3Byb2dyYW0KICAgIGNtcCBhbCwgMzIKICAgIGpnIGV4aXRfcHJvZ3JhbQogICAgCiAgICA7INCn0LjRgtCw0LXQvCDQv9C10YDQstC+0LUg0YfQuNGB0LvQvgogICAgbW92IHJheCwgcHJvbXB0MQogICAgY2FsbCBwcmludF9zdHJpbmcKICAgIG1vdnp4IHJjeCwgYnl0ZSBbTl0KICAgIG1vdiByZGksIG51bTEKICAgIGNhbGwgcmVhZF9oZXhfbnVtYmVyCiAgICAKICAgIDsg0KfQuNGC0LDQtdC8INCy0YLQvtGA0L7QtSDRh9C40YHQu9C+CiAgICBtb3YgcmF4LCBwcm9tcHQyCiAgICBjYWxsIHByaW50X3N0cmluZwogICAgbW92enggcmN4LCBieXRlIFtOXQogICAgbW92IHJkaSwgbnVtMgogICAgY2FsbCByZWFkX2hleF9udW1iZXIKICAgIAogICAgOyDQodC60LvQsNC00YvQstCw0LXQvCDRh9C40YHQu9CwCiAgICBtb3Z6eCByY3gsIGJ5dGUgW05dCiAgICBjYWxsIGFkZF9udW1iZXJzCiAgICAKICAgIDsg0JLRi9Cy0L7QtNC40Lwg0YDQtdC30YPQu9GM0YLQsNGCCiAgICBtb3YgcmF4LCByZXN1bHRfbXNnCiAgICBjYWxsIHByaW50X3N0cmluZwogICAgbW92enggcmN4LCBieXRlIFtOXQogICAgbW92IHJzaSwgc3VtCiAgICBjYWxsIHByaW50X2hleF9udW1iZXIKICAgIAogICAgOyDQndC+0LLQsNGPINGB0YLRgNC+0LrQsAogICAgbW92IHJheCwgbmV3bGluZQogICAgY2FsbCBwcmludF9zdHJpbmcKICAgIApleGl0X3Byb2dyYW06CiAgICBtb3YgcmF4LCA2MCAgICAgICAgICAgICAgICAgOyBzeXNfZXhpdAogICAgeG9yIHJkaSwgcmRpICAgICAgICAgICAgICAgIDsg0LrQvtC0INCy0L7Qt9Cy0YDQsNGC0LAgMAogICAgc3lzY2FsbAoKOyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQo7INCf0YDQvtGG0LXQtNGD0YDQsCDRgdC70L7QttC10L3QuNGPINC00LLRg9GFINGH0LjRgdC10LsKOyDQktGF0L7QtDogUkNYID0g0YDQsNC30LzQtdGAINGH0LjRgdC10Lsg0LIg0LHQsNC50YLQsNGFCjsgICAgICAgbnVtMSwgbnVtMiAtINGB0LrQu9Cw0LTRi9Cy0LDQtdC80YvQtSDRh9C40YHQu9CwCjsg0JLRi9GF0L7QtDogc3VtID0gbnVtMSArIG51bTIKOyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQphZGRfbnVtYmVyczoKICAgIHB1c2ggcmN4CiAgICBwdXNoIHJzaQogICAgcHVzaCByZGkKICAgIHhvciByc2ksIHJzaSAgICAgICAgICAgICAgICA7INCY0L3QtNC10LrRgSDQsdCw0LnRgtCwCiAgICBjbGMgICAgICAgICAgICAgICAgICAgICAgICAgOyDQodCx0YDQsNGB0YvQstCw0LXQvCDRhNC70LDQsyDQv9C10YDQtdC90L7RgdCwCiAgICAKLmFkZF9sb29wOgogICAgbW92IGFsLCBbbnVtMSArIHJzaV0KICAgIG1vdiBibCwgW251bTIgKyByc2ldCiAgICAKICAgIDsg0KHQu9C+0LbQtdC90LjQtSDRgSDRg9GH0LXRgtC+0Lwg0L/QtdGA0LXQvdC+0YHQsAogICAgYWRjIGFsLCBibAogICAgbW92IFtzdW0gKyByc2ldLCBhbAogICAgCiAgICBpbmMgcnNpCiAgICBsb29wIC5hZGRfbG9vcCAgICAgICAgICAgICAgOyDQo9C80LXQvdGM0YjQsNC10YIgUkNYINC4INC/0L7QstGC0L7RgNGP0LXRgiDQtdGB0LvQuCDQvdC1IDAKICAgIAogICAgcG9wIHJkaQogICAgcG9wIHJzaQogICAgcG9wIHJjeAogICAgcmV0Cgo7ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Cjsg0KfRgtC10L3QuNC1INGI0LXRgdGC0L3QsNC00YbQsNGC0LXRgNC40YfQvdC+0LPQviDRh9C40YHQu9CwCjsg0JLRhdC+0LQ6IFJDWCA9INC60L7Qu9C40YfQtdGB0YLQstC+INCx0LDQudGC0L7Qsgo7ICAgICAgIFJESSA9INGD0LrQsNC30LDRgtC10LvRjCDQvdCwINCx0YPRhNC10YAg0LTQu9GPINGH0LjRgdC70LAKOyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpyZWFkX2hleF9udW1iZXI6CiAgICBwdXNoIHJjeAogICAgcHVzaCByZGkKICAgIHB1c2ggcnNpCiAgICAKICAgIDsg0KfQuNGC0LDQtdC8INGB0YLRgNC+0LrRgwogICAgbW92IHJheCwgMCAgICAgICAgICAgICAgICAgIDsgc3lzX3JlYWQKICAgIG1vdiByZGksIDAgICAgICAgICAgICAgICAgICA7IHN0ZGluCiAgICBtb3YgcnNpLCBidWZmZXIKICAgIG1vdiByZHgsIDI1NgogICAgc3lzY2FsbAogICAgCiAgICA7INCa0L7QvdCy0LXRgNGC0LjRgNGD0LXQvCBoZXgg0YHRgtGA0L7QutGDINCyINGH0LjRgdC70L4KICAgIG1vdiByc2ksIGJ1ZmZlcgogICAgbW92IHJkeCwgcmRpICAgICAgICAgICAgICAgIDsg0KHQvtGF0YDQsNC90Y/QtdC8INGD0LrQsNC30LDRgtC10LvRjCDQvdCwINCy0YvRhdC+0LTQvdC+0Lkg0LHRg9GE0LXRgAogICAgCiAgICA7INCf0YDQvtC/0YPRgdC60LDQtdC8INC/0YDQvtCx0LXQu9GLCi5za2lwX3NwYWNlczoKICAgIGxvZHNiCiAgICBjbXAgYWwsICcgJwogICAgamUgLnNraXBfc3BhY2VzCiAgICBjbXAgYWwsIDEwICAgICAgICAgICAgICAgICAgOyDQndC+0LLQsNGPINGB0YLRgNC+0LrQsAogICAgamUgLmRvbmUKICAgIGNtcCBhbCwgMTMgICAgICAgICAgICAgICAgICA7INCS0L7Qt9Cy0YDQsNGCINC60LDRgNC10YLQutC4CiAgICBqZSAuZG9uZQogICAgCiAgICBkZWMgcnNpICAgICAgICAgICAgICAgICAgICAgOyDQktC+0LfQstGA0LDRidCw0LXQvNGB0Y8g0Log0L/QtdGA0LLQvtC80YMg0YHQuNC80LLQvtC70YMKICAgIAogICAgOyDQntC/0YDQtdC00LXQu9GP0LXQvCwg0L7RgtGA0LjRhtCw0YLQtdC70YzQvdC+0LUg0LvQuCDRh9C40YHQu9C+CiAgICBtb3YgYWwsIFtyc2ldCiAgICBjbXAgYWwsICctJwogICAgam5lIC5wYXJzZV9wb3NpdGl2ZQogICAgCiAgICA7INCe0YLRgNC40YbQsNGC0LXQu9GM0L3QvtC1INGH0LjRgdC70L4KICAgIGluYyByc2kgICAgICAgICAgICAgICAgICAgICA7INCf0YDQvtC/0YPRgdC60LDQtdC8INC80LjQvdGD0YEKICAgIGNhbGwgcGFyc2VfaGV4X3N0cmluZwogICAgY2FsbCBuZWdhdGVfbnVtYmVyCiAgICBqbXAgLmRvbmUKICAgIAoucGFyc2VfcG9zaXRpdmU6CiAgICBjYWxsIHBhcnNlX2hleF9zdHJpbmcKICAgIAouZG9uZToKICAgIHBvcCByc2kKICAgIHBvcCByZGkKICAgIHBvcCByY3gKICAgIHJldAoKOyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQo7INCf0LDRgNGB0LjQvdCzINGI0LXRgdGC0L3QsNC00YbQsNGC0LXRgNC40YfQvdC+0Lkg0YHRgtGA0L7QutC4Cjsg0JLRhdC+0LQ6IFJTSSA9INGD0LrQsNC30LDRgtC10LvRjCDQvdCwINGB0YLRgNC+0LrRgwo7ICAgICAgIFJDWCA9INGA0LDQt9C80LXRgCDRh9C40YHQu9CwINCyINCx0LDQudGC0LDRhQo7ICAgICAgIFJEWCA9INGD0LrQsNC30LDRgtC10LvRjCDQvdCwINCx0YPRhNC10YAg0YDQtdC30YPQu9GM0YLQsNGC0LAKOyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpwYXJzZV9oZXhfc3RyaW5nOgogICAgcHVzaCByY3gKICAgIHB1c2ggcmR4CiAgICBwdXNoIHJieAogICAgCiAgICBtb3YgcmRpLCByZHgKICAgIGFkZCByZGksIHJjeAogICAgZGVjIHJkaSAgICAgICAgICAgICAgICAgICAgIDsgUkRJINGD0LrQsNC30YvQstCw0LXRgiDQvdCwINC/0L7RgdC70LXQtNC90LjQuSDQsdCw0LnRgiDQsdGD0YTQtdGA0LAKICAgIAogICAgOyDQntGH0LjRidCw0LXQvCDQsdGD0YTQtdGACiAgICBtb3YgcmR4LCByZGkKLmNsZWFyX2J1ZmZlcjoKICAgIG1vdiBieXRlIFtyZHhdLCAwCiAgICBkZWMgcmR4CiAgICBjbXAgcmR4LCByZGkKICAgIGpnZSAuY2xlYXJfYnVmZmVyCiAgICAKICAgIHhvciByYngsIHJieCAgICAgICAgICAgICAgICA7INCh0YfQtdGC0YfQuNC6INGB0YfQuNGC0LDQvdC90YvRhSDRgdC40LzQstC+0LvQvtCyCiAgICAKLnJlYWRfY2hhcjoKICAgIGxvZHNiICAgICAgICAgICAgICAgICAgICAgICA7INCX0LDQs9GA0YPQttCw0LXQvCDRgdC40LzQstC+0Lsg0LjQtyDRgdGC0YDQvtC60LgKICAgIAogICAgOyDQn9GA0L7QstC10YDRj9C10Lwg0LrQvtC90LXRhiDRgdGC0YDQvtC60LgKICAgIGNtcCBhbCwgMAogICAgamUgLnBhcnNlX2RvbmUKICAgIGNtcCBhbCwgMTAgICAgICAgICAgICAgICAgICA7INCd0L7QstCw0Y8g0YHRgtGA0L7QutCwCiAgICBqZSAucGFyc2VfZG9uZQogICAgY21wIGFsLCAxMyAgICAgICAgICAgICAgICAgIDsg0JLQvtC30LLRgNCw0YIg0LrQsNGA0LXRgtC60LgKICAgIGplIC5wYXJzZV9kb25lCiAgICBjbXAgYWwsICcgJyAgICAgICAgICAgICAgICAgOyDQn9GA0L7QsdC10LsKICAgIGplIC5wYXJzZV9kb25lCiAgICAKICAgIDsg0J/RgNC10L7QsdGA0LDQt9GD0LXQvCDRgdC40LzQstC+0Lsg0LIg0YfQuNGB0LvQvgogICAgY2FsbCBjaGFyX3RvX2hleAogICAgY21wIGFsLCAweEZGCiAgICBqZSAuaW52YWxpZF9jaGFyCiAgICAKICAgIDsg0KHQtNCy0LjQs9Cw0LXQvCDRgtC10LrRg9GJ0LXQtSDQt9C90LDRh9C10L3QuNC1INC4INC00L7QsdCw0LLQu9GP0LXQvCDQvdC+0LLQvtC1CiAgICBwdXNoIHJjeAogICAgbW92IHJjeCwgNCAgICAgICAgICAgICAgICAgIDsg0KHQtNCy0LjQs9Cw0LXQvCDQvdCwIDQg0LHQuNGC0LAKICAgIAouc2hpZnRfYnVmZmVyOgogICAgcHVzaCByZGkKICAgIG1vdiByZHgsIHJkaQogICAgc3ViIHJkeCwgcmN4CiAgICBpbmMgcmR4CiAgICAKLnNoaWZ0X2xvb3A6CiAgICBtb3YgYmwsIFtyZHhdCiAgICBzaGwgYmwsIDQKICAgIG1vdiBbcmR4XSwgYmwKICAgIGluYyByZHgKICAgIGNtcCByZHgsIHJkaQogICAgamxlIC5zaGlmdF9sb29wCiAgICAKICAgIHBvcCByZGkKICAgIAogICAgOyDQlNC+0LHQsNCy0LvRj9C10Lwg0L3QvtCy0YvQuSDQv9C+0LvRg9Cx0LDQudGCCiAgICBtb3YgYmwsIFtyZGldCiAgICBvciBibCwgYWwKICAgIG1vdiBbcmRpXSwgYmwKICAgIAogICAgcG9wIHJjeAogICAgCiAgICBpbmMgcmJ4CiAgICBjbXAgcmJ4LCByY3ggICAgICAgICAgICAgICAgOyDQn9GA0L7QstC10YDRj9C10LwsINC90LUg0L/RgNC10LLRi9GB0LjQu9C4INC70Lgg0YDQsNC30LzQtdGACiAgICBqbCAucmVhZF9jaGFyCiAgICAKLnBhcnNlX2RvbmU6CiAgICBwb3AgcmJ4CiAgICBwb3AgcmR4CiAgICBwb3AgcmN4CiAgICByZXQKICAgIAouaW52YWxpZF9jaGFyOgogICAgOyDQkiDRgdC70YPRh9Cw0LUg0L7RiNC40LHQutC4INCy0L7Qt9Cy0YDQsNGJ0LDQtdC8IDAKICAgIG1vdiByZGksIHJkeAogICAgbW92IGJ5dGUgW3JkaV0sIDAKICAgIGptcCAucGFyc2VfZG9uZQoKOyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQo7INCf0YDQtdC+0LHRgNCw0LfQvtCy0LDQvdC40LUg0YHQuNC80LLQvtC70LAg0LIg0YjQtdGB0YLQvdCw0LTRhtCw0YLQtdGA0LjRh9C90L7QtSDRh9C40YHQu9C+Cjsg0JLRhdC+0LQ6IEFMID0g0YHQuNC80LLQvtC7Cjsg0JLRi9GF0L7QtDogQUwgPSDRh9C40YHQu9C+ICgwLTE1KSDQuNC70LggMHhGRiDQv9GA0Lgg0L7RiNC40LHQutC1CjsgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KY2hhcl90b19oZXg6CiAgICBjbXAgYWwsICcwJwogICAgamwgLmludmFsaWQKICAgIGNtcCBhbCwgJzknCiAgICBqZyAuY2hlY2tfdXBwZXIKICAgIAogICAgc3ViIGFsLCAnMCcKICAgIHJldAogICAgCi5jaGVja191cHBlcjoKICAgIGNtcCBhbCwgJ0EnCiAgICBqbCAuaW52YWxpZAogICAgY21wIGFsLCAnRicKICAgIGpnIC5jaGVja19sb3dlcgogICAgCiAgICBzdWIgYWwsICdBJyAtIDEwCiAgICByZXQKICAgIAouY2hlY2tfbG93ZXI6CiAgICBjbXAgYWwsICdhJwogICAgamwgLmludmFsaWQKICAgIGNtcCBhbCwgJ2YnCiAgICBqZyAuaW52YWxpZAogICAgCiAgICBzdWIgYWwsICdhJyAtIDEwCiAgICByZXQKICAgIAouaW52YWxpZDoKICAgIG1vdiBhbCwgMHhGRgogICAgcmV0Cgo7ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Cjsg0JjQvdCy0LXRgNGB0LjRjyDRh9C40YHQu9CwICjQtNC+0L/QvtC70L3QuNGC0LXQu9GM0L3Ri9C5INC60L7QtCkKOyDQktGF0L7QtDogUkNYID0g0YDQsNC30LzQtdGAINGH0LjRgdC70LAg0LIg0LHQsNC50YLQsNGFCjsgICAgICAgUkRJID0g0YPQutCw0LfQsNGC0LXQu9GMINC90LAg0YfQuNGB0LvQvgo7ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Cm5lZ2F0ZV9udW1iZXI6CiAgICBwdXNoIHJjeAogICAgcHVzaCByc2kKICAgIAogICAgbW92IHJzaSwgcmRpCiAgICBhZGQgcnNpLCByY3gKICAgIGRlYyByc2kgICAgICAgICAgICAgICAgICAgICA7IFJTSSDRg9C60LDQt9GL0LLQsNC10YIg0L3QsCDQv9C+0YHQu9C10LTQvdC40Lkg0LHQsNC50YIKICAgIAogICAgOyDQmNC90LLQtdGA0YLQuNGA0YPQtdC8INCy0YHQtSDQsdC40YLRiwoubm90X2xvb3A6CiAgICBub3QgYnl0ZSBbcnNpXQogICAgZGVjIHJzaQogICAgY21wIHJzaSwgcmRpCiAgICBqZ2UgLm5vdF9sb29wCiAgICAKICAgIDsg0JTQvtCx0LDQstC70Y/QtdC8IDEKICAgIG1vdiByc2ksIHJkaQogICAgbW92IGJ5dGUgYWwsIDEKICAgIAouYWRkX29uZV9sb29wOgogICAgYWRkIGJ5dGUgW3JzaV0sIGFsCiAgICBqbmMgLmRvbmVfbmVnYXRlCiAgICBtb3YgYWwsIDEKICAgIGluYyByc2kKICAgIGNtcCByc2ksIHJkaQogICAgYWRkIHJzaSwgcmN4CiAgICBkZWMgcnNpCiAgICBqbGUgLmFkZF9vbmVfbG9vcAogICAgCi5kb25lX25lZ2F0ZToKICAgIHBvcCByc2kKICAgIHBvcCByY3gKICAgIHJldAoKOyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQo7INCS0YvQstC+0LQg0YjQtdGB0YLQvdCw0LTRhtCw0YLQtdGA0LjRh9C90L7Qs9C+INGH0LjRgdC70LAKOyDQktGF0L7QtDogUkNYID0g0YDQsNC30LzQtdGAINGH0LjRgdC70LAg0LIg0LHQsNC50YLQsNGFCjsgICAgICAgUlNJID0g0YPQutCw0LfQsNGC0LXQu9GMINC90LAg0YfQuNGB0LvQvgo7ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CnByaW50X2hleF9udW1iZXI6CiAgICBwdXNoIHJjeAogICAgcHVzaCByc2kKICAgIHB1c2ggcmRpCiAgICAKICAgIDsg0J/RgNC+0LLQtdGA0Y/QtdC8INC30L3QsNC6INGH0LjRgdC70LAKICAgIG1vdiBhbCwgW3JzaSArIHJjeCAtIDFdCiAgICB0ZXN0IGFsLCAweDgwICAgICAgICAgICAgICAgOyDQn9GA0L7QstC10YDRj9C10Lwg0YHRgtCw0YDRiNC40Lkg0LHQuNGCCiAgICBqeiAucHJpbnRfcG9zaXRpdmUKICAgIAogICAgOyDQntGC0YDQuNGG0LDRgtC10LvRjNC90L7QtSDRh9C40YHQu9C+CiAgICBwdXNoIHJjeAogICAgcHVzaCByc2kKICAgIAogICAgOyDQmtC+0L/QuNGA0YPQtdC8INGH0LjRgdC70L4g0LLQviDQstGA0LXQvNC10L3QvdGL0Lkg0LHRg9GE0LXRgAogICAgbW92IHJkaSwgYnVmZmVyCiAgICByZXAgbW92c2IKICAgIAogICAgcG9wIHJzaQogICAgcG9wIHJjeAogICAgCiAgICA7INCS0YvQstC+0LTQuNC8INC80LjQvdGD0YEKICAgIG1vdiBieXRlIFtidWZmZXJdLCAnLScKICAgIG1vdiByYXgsIGJ1ZmZlcgogICAgY2FsbCBwcmludF9zdHJpbmcKICAgIAogICAgOyDQn9GA0LXQvtCx0YDQsNC30YPQtdC8INCyINC00L7Qv9C+0LvQvdC40YLQtdC70YzQvdGL0Lkg0LrQvtC0CiAgICBtb3YgcmRpLCByc2kKICAgIGNhbGwgbmVnYXRlX251bWJlcgogICAgZGVjIHJjeCAgICAgICAgICAgICAgICAgICAgIDsg0KPQttC1INCy0YvQstC10LvQuCDQvNC40L3Rg9GBCiAgICAKLnByaW50X3Bvc2l0aXZlOgogICAgbW92IHJkaSwgcnNpCiAgICBhZGQgcmRpLCByY3gKICAgIGRlYyByZGkgICAgICAgICAgICAgICAgICAgICA7IFJESSDRg9C60LDQt9GL0LLQsNC10YIg0L3QsCDQv9C+0YHQu9C10LTQvdC40Lkg0LHQsNC50YIKICAgIAogICAgOyDQn9GA0L7Qv9GD0YHQutCw0LXQvCDQstC10LTRg9GJ0LjQtSDQvdGD0LvQuAouZmluZF9maXJzdF9ub256ZXJvOgogICAgY21wIGJ5dGUgW3JkaV0sIDAKICAgIGpuZSAucHJpbnRfaGV4CiAgICBkZWMgcmRpCiAgICBjbXAgcmRpLCByc2kKICAgIGpnZSAuZmluZF9maXJzdF9ub256ZXJvCiAgICAKICAgIDsg0JLRgdC1INC90YPQu9C4IC0g0LLRi9Cy0L7QtNC40LwgIjAiCiAgICBtb3YgYnl0ZSBbYnVmZmVyXSwgJzAnCiAgICBtb3YgYnl0ZSBbYnVmZmVyICsgMV0sIDAKICAgIG1vdiByYXgsIGJ1ZmZlcgogICAgY2FsbCBwcmludF9zdHJpbmcKICAgIGptcCAuZG9uZV9wcmludAogICAgCi5wcmludF9oZXg6CiAgICA7INCf0YDQtdC+0LHRgNCw0LfRg9C10Lwg0LHQsNC50YIg0LIg0LTQstCwIGhleCDRgdC40LzQstC+0LvQsAogICAgbW92IGFsLCBbcmRpXQogICAgbW92IGJsLCBhbAogICAgc2hyIGFsLCA0CiAgICBjYWxsIGhleF90b19jaGFyCiAgICBtb3YgW2J1ZmZlcl0sIGFsCiAgICBtb3YgYWwsIGJsCiAgICBhbmQgYWwsIDB4MEYKICAgIGNhbGwgaGV4X3RvX2NoYXIKICAgIG1vdiBbYnVmZmVyICsgMV0sIGFsCiAgICBtb3YgYnl0ZSBbYnVmZmVyICsgMl0sIDAKICAgIAogICAgbW92IHJheCwgYnVmZmVyCiAgICBjYWxsIHByaW50X3N0cmluZwogICAgCiAgICBkZWMgcmRpCiAgICBjbXAgcmRpLCByc2kKICAgIGpnZSAucHJpbnRfaGV4CiAgICAKLmRvbmVfcHJpbnQ6CiAgICBwb3AgcmRpCiAgICBwb3AgcnNpCiAgICBwb3AgcmN4CiAgICByZXQKCjsgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KOyDQn9GA0LXQvtCx0YDQsNC30L7QstCw0L3QuNC1INGH0LjRgdC70LAgMC0xNSDQsiDRgdC40LzQstC+0LsgaGV4Cjsg0JLRhdC+0LQ6IEFMID0g0YfQuNGB0LvQviAoMC0xNSkKOyDQktGL0YXQvtC0OiBBTCA9INGB0LjQvNCy0L7QuyBoZXgKOyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpoZXhfdG9fY2hhcjoKICAgIGNtcCBhbCwgMTAKICAgIGpsIC5kaWdpdAogICAgCiAgICBhZGQgYWwsICdBJyAtIDEwCiAgICByZXQKICAgIAouZGlnaXQ6CiAgICBhZGQgYWwsICcwJwogICAgcmV0Cgo7ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Cjsg0KfRgtC10L3QuNC1INC+0LTQvdC+0LPQviDQsdCw0LnRgtCwINCyIGhleAo7INCS0YvRhdC+0LQ6IEFMID0g0L/RgNC+0YfQuNGC0LDQvdC90L7QtSDRh9C40YHQu9C+CjsgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KcmVhZF9oZXhfYnl0ZToKICAgIHB1c2ggcnNpCiAgICBwdXNoIHJkeAogICAgCiAgICBtb3YgcmF4LCAwICAgICAgICAgICAgICAgICAgOyBzeXNfcmVhZAogICAgbW92IHJkaSwgMCAgICAgICAgICAgICAgICAgIDsgc3RkaW4KICAgIG1vdiByc2ksIGJ1ZmZlcgogICAgbW92IHJkeCwgMyAgICAgICAgICAgICAgICAgIDsg0JzQsNC60YHQuNC80YPQvCAyINGB0LjQvNCy0L7Qu9CwICsg0L3QvtCy0LDRjyDRgdGC0YDQvtC60LAKICAgIHN5c2NhbGwKICAgIAogICAgOyDQmtC+0L3QstC10YDRgtC40YDRg9C10LwgaGV4INCyINGH0LjRgdC70L4KICAgIG1vdiByc2ksIGJ1ZmZlcgogICAgeG9yIHJheCwgcmF4CiAgICAKLnJlYWRfZGlnaXQ6CiAgICBtb3YgZGwsIFtyc2ldCiAgICBjbXAgZGwsIDEwICAgICAgICAgICAgICAgICAgOyDQndC+0LLQsNGPINGB0YLRgNC+0LrQsAogICAgamUgLmRvbmVfcmVhZAogICAgY21wIGRsLCAxMyAgICAgICAgICAgICAgICAgIDsg0JLQvtC30LLRgNCw0YIg0LrQsNGA0LXRgtC60LgKICAgIGplIC5kb25lX3JlYWQKICAgIAogICAgY2FsbCBjaGFyX3RvX2hleAogICAgY21wIGFsLCAweEZGCiAgICBqZSAuaW52YWxpZF9pbnB1dAogICAgCiAgICBzaGwgcmF4LCA0CiAgICBhZGQgYWwsIFtyc2ldCiAgICBpbmMgcnNpCiAgICBqbXAgLnJlYWRfZGlnaXQKICAgIAouaW52YWxpZF9pbnB1dDoKICAgIHhvciBhbCwgYWwKICAgIAouZG9uZV9yZWFkOgogICAgcG9wIHJkeAogICAgcG9wIHJzaQogICAgcmV0Cgo7ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Cjsg0JLRi9Cy0L7QtCDRgdGC0YDQvtC60LgKOyDQktGF0L7QtDogUkFYID0g0YPQutCw0LfQsNGC0LXQu9GMINC90LAg0YHRgtGA0L7QutGDCjsgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KcHJpbnRfc3RyaW5nOgogICAgcHVzaCByc2kKICAgIHB1c2ggcmR4CiAgICBwdXNoIHJkaQogICAgCiAgICBtb3YgcnNpLCByYXgKICAgIG1vdiByZHgsIDAKICAgIAouc3RybGVuX2xvb3A6CiAgICBjbXAgYnl0ZSBbcnNpICsgcmR4XSwgMAogICAgamUgLnN0cmxlbl9kb25lCiAgICBpbmMgcmR4CiAgICBqbXAgLnN0cmxlbl9sb29wCiAgICAKLnN0cmxlbl9kb25lOgogICAgbW92IHJheCwgMSAgICAgICAgICAgICAgICAgIDsgc3lzX3dyaXRlCiAgICBtb3YgcmRpLCAxICAgICAgICAgICAgICAgICAgOyBzdGRvdXQKICAgIHN5c2NhbGwKICAgIAogICAgcG9wIHJkaQogICAgcG9wIHJkeAogICAgcG9wIHJzaQogICAgcmV0