section .data
usage db "Usage: ./caesar {input_file} {output_file} {shift}", 10, 0
len_usage equ $ - usage
error_open_in db "Error: Cannot open input file.", 10, 0
len_error_open_in equ $ - error_open_in
error_open_out db "Error: Cannot open output file.", 10, 0
len_error_open_out equ $ - error_open_out
section .bss
bytes_read resd 1
buffer resb 1024
buffer_size equ 1024
section .text
global _start
_start:
; В _start стек выглядит так:
; [esp]: argc
; [esp+4]: argv[0] (имя программы)
; [esp+8]: argv[1] (input_file)
; [esp+12]: argv[2] (output_file)
; [esp+16]: argv[3] (shift)
mov eax, [esp] ; argc
cmp eax, 4 ; Проверяем, что argc == 4
je process_args ; Если да, продолжаем обработку аргументов
; Вывод использования программы
mov eax, 4 ; sys_write
mov ebx, 1 ; stdout
mov ecx, usage ; Адрес строки
mov edx, len_usage ; Длина строки
int 0x80 ; Вызов ядра
jmp exit ; Завершаем программу
process_args:
mov ebx, [esp+8] ; argv[1]: input_file
mov ecx, [esp+12] ; argv[2]: output_file
mov edx, [esp+16] ; argv[3]: shift
; Открыть входной файл
mov eax, 5 ; sys_open
mov esi, ebx ; input_file
xor edi, edi ; O_RDONLY
int 0x80
cmp eax, 0 ; Проверка ошибки
jl error_open_input
mov ebx, eax ; Сохраняем дескриптор входного файла
; Открыть выходной файл
mov eax, 5 ; sys_open
mov esi, ecx ; output_file
mov edi, 577 ; O_WRONLY | O_CREAT | O_TRUNC (577 = 0x241)
mov ebp, 0666 ; Права доступа
int 0x80
cmp eax, 0 ; Проверка ошибки
jl error_open_output
mov ecx, eax ; Сохраняем дескриптор выходного файла
; Получить сдвиг
sub edx, '0' ; Преобразуем ASCII в число
and edx, 31 ; Ограничиваем диапазон от 0 до 31
read_loop:
; Чтение из входного файла
mov eax, 3 ; sys_read
mov edi, ebx ; Дескриптор входного файла
mov esi, buffer ; Буфер для чтения
mov edx, buffer_size ; Размер буфера
int 0x80
cmp eax, 0 ; EOF или ошибка
jle close_files
mov dword [bytes_read], eax
; Обработка данных
mov esi, buffer ; Указатель на буфер
mov edi, buffer ; Указатель на запись
mov ecx, dword [bytes_read] ; Количество прочитанных байт
process_char:
lodsb ; Загружаем байт из [esi]
cmp al, 'A'
jb skip_char
cmp al, 'Z'
jbe upper_case
cmp al, 'a'
jb skip_char
cmp al, 'z'
ja skip_char
lower_case:
sub al, 'a'
add al, dl ; Применяем сдвиг
xor ah, ah ; Подготовка для модульного деления
mov bl, 26 ; Алфавит латинских строчных букв
div bl ; Делим на 26
add al, 'a'
jmp store_char
upper_case:
sub al, 'A'
add al, dl ; Применяем сдвиг
xor ah, ah ; Подготовка для модульного деления
mov bl, 26 ; Алфавит латинских прописных букв
div bl ; Делим на 26
add al, 'A'
jmp store_char
skip_char:
jmp next_char
store_char:
stosb ; Сохраняем обработанный символ в [edi]
next_char:
loop process_char ; Переходим к следующему символу
; Запись данных в выходной файл
mov eax, 4 ; sys_write
mov ebx, ecx ; Дескриптор выходного файла
mov ecx, buffer ; Буфер для записи
mov edx, dword [bytes_read] ; Количество байт для записи
int 0x80
jmp read_loop
close_files:
; Закрытие файлов
mov eax, 6 ; sys_close
mov ebx, ebx ; Закрыть входной файл
int 0x80
mov eax, 6 ; sys_close
mov ebx, ecx ; Закрыть выходной файл
int 0x80
exit:
mov eax, 1 ; sys_exit
xor ebx, ebx ; Код выхода 0
int 0x80
error_open_input:
mov eax, 4 ; sys_write
mov ebx, 1 ; stdout
mov ecx, error_open_in ; Сообщение об ошибке
mov edx, len_error_open_in ; Длина сообщения
int 0x80
jmp exit
error_open_output:
mov eax, 4 ; sys_write
mov ebx, 1 ; stdout
mov ecx, error_open_out ; Сообщение об ошибке
mov edx, len_error_open_out ; Длина сообщения
int 0x80
jmp exit
c2VjdGlvbiAuZGF0YQogICAgdXNhZ2UgZGIgIlVzYWdlOiAuL2NhZXNhciB7aW5wdXRfZmlsZX0ge291dHB1dF9maWxlfSB7c2hpZnR9IiwgMTAsIDAKICAgIGxlbl91c2FnZSBlcXUgJCAtIHVzYWdlCgogICAgZXJyb3Jfb3Blbl9pbiBkYiAiRXJyb3I6IENhbm5vdCBvcGVuIGlucHV0IGZpbGUuIiwgMTAsIDAKICAgIGxlbl9lcnJvcl9vcGVuX2luIGVxdSAkIC0gZXJyb3Jfb3Blbl9pbgoKICAgIGVycm9yX29wZW5fb3V0IGRiICJFcnJvcjogQ2Fubm90IG9wZW4gb3V0cHV0IGZpbGUuIiwgMTAsIDAKICAgIGxlbl9lcnJvcl9vcGVuX291dCBlcXUgJCAtIGVycm9yX29wZW5fb3V0CgpzZWN0aW9uIC5ic3MKICAgIGJ5dGVzX3JlYWQgcmVzZCAxCiAgICBidWZmZXIgcmVzYiAxMDI0CiAgICBidWZmZXJfc2l6ZSBlcXUgMTAyNAoKc2VjdGlvbiAudGV4dAogICAgZ2xvYmFsIF9zdGFydAoKX3N0YXJ0OgogICAgOyDQkiBfc3RhcnQg0YHRgtC10Log0LLRi9Cz0LvRj9C00LjRgiDRgtCw0Lo6CiAgICA7IFtlc3BdOiBhcmdjCiAgICA7IFtlc3ArNF06IGFyZ3ZbMF0gKNC40LzRjyDQv9GA0L7Qs9GA0LDQvNC80YspCiAgICA7IFtlc3ArOF06IGFyZ3ZbMV0gKGlucHV0X2ZpbGUpCiAgICA7IFtlc3ArMTJdOiBhcmd2WzJdIChvdXRwdXRfZmlsZSkKICAgIDsgW2VzcCsxNl06IGFyZ3ZbM10gKHNoaWZ0KQoKICAgIG1vdiBlYXgsIFtlc3BdICAgICAgICAgICAgICA7IGFyZ2MKICAgIGNtcCBlYXgsIDQgICAgICAgICAgICAgICAgICA7INCf0YDQvtCy0LXRgNGP0LXQvCwg0YfRgtC+IGFyZ2MgPT0gNAogICAgamUgcHJvY2Vzc19hcmdzICAgICAgICAgICAgIDsg0JXRgdC70Lgg0LTQsCwg0L/RgNC+0LTQvtC70LbQsNC10Lwg0L7QsdGA0LDQsdC+0YLQutGDINCw0YDQs9GD0LzQtdC90YLQvtCyCgogICAgOyDQktGL0LLQvtC0INC40YHQv9C+0LvRjNC30L7QstCw0L3QuNGPINC/0YDQvtCz0YDQsNC80LzRiwogICAgbW92IGVheCwgNCAgICAgICAgICAgICAgICAgIDsgc3lzX3dyaXRlCiAgICBtb3YgZWJ4LCAxICAgICAgICAgICAgICAgICAgOyBzdGRvdXQKICAgIG1vdiBlY3gsIHVzYWdlICAgICAgICAgICAgICA7INCQ0LTRgNC10YEg0YHRgtGA0L7QutC4CiAgICBtb3YgZWR4LCBsZW5fdXNhZ2UgICAgICAgICAgOyDQlNC70LjQvdCwINGB0YLRgNC+0LrQuAogICAgaW50IDB4ODAgICAgICAgICAgICAgICAgICAgIDsg0JLRi9C30L7QsiDRj9C00YDQsAogICAgam1wIGV4aXQgICAgICAgICAgICAgICAgICAgIDsg0JfQsNCy0LXRgNGI0LDQtdC8INC/0YDQvtCz0YDQsNC80LzRgwoKcHJvY2Vzc19hcmdzOgogICAgbW92IGVieCwgW2VzcCs4XSAgICAgICAgICAgIDsgYXJndlsxXTogaW5wdXRfZmlsZQogICAgbW92IGVjeCwgW2VzcCsxMl0gICAgICAgICAgIDsgYXJndlsyXTogb3V0cHV0X2ZpbGUKICAgIG1vdiBlZHgsIFtlc3ArMTZdICAgICAgICAgICA7IGFyZ3ZbM106IHNoaWZ0CgogICAgOyDQntGC0LrRgNGL0YLRjCDQstGF0L7QtNC90L7QuSDRhNCw0LnQuwogICAgbW92IGVheCwgNSAgICAgICAgICAgICAgICAgIDsgc3lzX29wZW4KICAgIG1vdiBlc2ksIGVieCAgICAgICAgICAgICAgICA7IGlucHV0X2ZpbGUKICAgIHhvciBlZGksIGVkaSAgICAgICAgICAgICAgICA7IE9fUkRPTkxZCiAgICBpbnQgMHg4MAogICAgY21wIGVheCwgMCAgICAgICAgICAgICAgICAgIDsg0J/RgNC+0LLQtdGA0LrQsCDQvtGI0LjQsdC60LgKICAgIGpsIGVycm9yX29wZW5faW5wdXQKICAgIG1vdiBlYngsIGVheCAgICAgICAgICAgICAgICA7INCh0L7RhdGA0LDQvdGP0LXQvCDQtNC10YHQutGA0LjQv9GC0L7RgCDQstGF0L7QtNC90L7Qs9C+INGE0LDQudC70LAKCiAgICA7INCe0YLQutGA0YvRgtGMINCy0YvRhdC+0LTQvdC+0Lkg0YTQsNC50LsKICAgIG1vdiBlYXgsIDUgICAgICAgICAgICAgICAgICA7IHN5c19vcGVuCiAgICBtb3YgZXNpLCBlY3ggICAgICAgICAgICAgICAgOyBvdXRwdXRfZmlsZQogICAgbW92IGVkaSwgNTc3ICAgICAgICAgICAgICAgIDsgT19XUk9OTFkgfCBPX0NSRUFUIHwgT19UUlVOQyAoNTc3ID0gMHgyNDEpCiAgICBtb3YgZWJwLCAwNjY2ICAgICAgICAgICAgICAgOyDQn9GA0LDQstCwINC00L7RgdGC0YPQv9CwCiAgICBpbnQgMHg4MAogICAgY21wIGVheCwgMCAgICAgICAgICAgICAgICAgIDsg0J/RgNC+0LLQtdGA0LrQsCDQvtGI0LjQsdC60LgKICAgIGpsIGVycm9yX29wZW5fb3V0cHV0CiAgICBtb3YgZWN4LCBlYXggICAgICAgICAgICAgICAgOyDQodC+0YXRgNCw0L3Rj9C10Lwg0LTQtdGB0LrRgNC40L/RgtC+0YAg0LLRi9GF0L7QtNC90L7Qs9C+INGE0LDQudC70LAKCiAgICA7INCf0L7Qu9GD0YfQuNGC0Ywg0YHQtNCy0LjQswogICAgc3ViIGVkeCwgJzAnICAgICAgICAgICAgICAgIDsg0J/RgNC10L7QsdGA0LDQt9GD0LXQvCBBU0NJSSDQsiDRh9C40YHQu9C+CiAgICBhbmQgZWR4LCAzMSAgICAgICAgICAgICAgICAgOyDQntCz0YDQsNC90LjRh9C40LLQsNC10Lwg0LTQuNCw0L/QsNC30L7QvSDQvtGCIDAg0LTQviAzMQoKcmVhZF9sb29wOgogICAgOyDQp9GC0LXQvdC40LUg0LjQtyDQstGF0L7QtNC90L7Qs9C+INGE0LDQudC70LAKICAgIG1vdiBlYXgsIDMgICAgICAgICAgICAgICAgICA7IHN5c19yZWFkCiAgICBtb3YgZWRpLCBlYnggICAgICAgICAgICAgICAgOyDQlNC10YHQutGA0LjQv9GC0L7RgCDQstGF0L7QtNC90L7Qs9C+INGE0LDQudC70LAKICAgIG1vdiBlc2ksIGJ1ZmZlciAgICAgICAgICAgICA7INCR0YPRhNC10YAg0LTQu9GPINGH0YLQtdC90LjRjwogICAgbW92IGVkeCwgYnVmZmVyX3NpemUgICAgICAgIDsg0KDQsNC30LzQtdGAINCx0YPRhNC10YDQsAogICAgaW50IDB4ODAKICAgIGNtcCBlYXgsIDAgICAgICAgICAgICAgICAgICA7IEVPRiDQuNC70Lgg0L7RiNC40LHQutCwCiAgICBqbGUgY2xvc2VfZmlsZXMKICAgIG1vdiBkd29yZCBbYnl0ZXNfcmVhZF0sIGVheAoKICAgIDsg0J7QsdGA0LDQsdC+0YLQutCwINC00LDQvdC90YvRhQogICAgbW92IGVzaSwgYnVmZmVyICAgICAgICAgICAgIDsg0KPQutCw0LfQsNGC0LXQu9GMINC90LAg0LHRg9GE0LXRgAogICAgbW92IGVkaSwgYnVmZmVyICAgICAgICAgICAgIDsg0KPQutCw0LfQsNGC0LXQu9GMINC90LAg0LfQsNC/0LjRgdGMCiAgICBtb3YgZWN4LCBkd29yZCBbYnl0ZXNfcmVhZF0gOyDQmtC+0LvQuNGH0LXRgdGC0LLQviDQv9GA0L7Rh9C40YLQsNC90L3Ri9GFINCx0LDQudGCCnByb2Nlc3NfY2hhcjoKICAgIGxvZHNiICAgICAgICAgICAgICAgICAgICAgICA7INCX0LDQs9GA0YPQttCw0LXQvCDQsdCw0LnRgiDQuNC3IFtlc2ldCiAgICBjbXAgYWwsICdBJwogICAgamIgc2tpcF9jaGFyCiAgICBjbXAgYWwsICdaJwogICAgamJlIHVwcGVyX2Nhc2UKICAgIGNtcCBhbCwgJ2EnCiAgICBqYiBza2lwX2NoYXIKICAgIGNtcCBhbCwgJ3onCiAgICBqYSBza2lwX2NoYXIKCmxvd2VyX2Nhc2U6CiAgICBzdWIgYWwsICdhJwogICAgYWRkIGFsLCBkbCAgICAgICAgICAgICAgICAgOyDQn9GA0LjQvNC10L3Rj9C10Lwg0YHQtNCy0LjQswogICAgeG9yIGFoLCBhaCAgICAgICAgICAgICAgICAgOyDQn9C+0LTQs9C+0YLQvtCy0LrQsCDQtNC70Y8g0LzQvtC00YPQu9GM0L3QvtCz0L4g0LTQtdC70LXQvdC40Y8KICAgIG1vdiBibCwgMjYgICAgICAgICAgICAgICAgIDsg0JDQu9GE0LDQstC40YIg0LvQsNGC0LjQvdGB0LrQuNGFINGB0YLRgNC+0YfQvdGL0YUg0LHRg9C60LIKICAgIGRpdiBibCAgICAgICAgICAgICAgICAgICAgIDsg0JTQtdC70LjQvCDQvdCwIDI2CiAgICBhZGQgYWwsICdhJwogICAgam1wIHN0b3JlX2NoYXIKCnVwcGVyX2Nhc2U6CiAgICBzdWIgYWwsICdBJwogICAgYWRkIGFsLCBkbCAgICAgICAgICAgICAgICAgOyDQn9GA0LjQvNC10L3Rj9C10Lwg0YHQtNCy0LjQswogICAgeG9yIGFoLCBhaCAgICAgICAgICAgICAgICAgOyDQn9C+0LTQs9C+0YLQvtCy0LrQsCDQtNC70Y8g0LzQvtC00YPQu9GM0L3QvtCz0L4g0LTQtdC70LXQvdC40Y8KICAgIG1vdiBibCwgMjYgICAgICAgICAgICAgICAgIDsg0JDQu9GE0LDQstC40YIg0LvQsNGC0LjQvdGB0LrQuNGFINC/0YDQvtC/0LjRgdC90YvRhSDQsdGD0LrQsgogICAgZGl2IGJsICAgICAgICAgICAgICAgICAgICAgOyDQlNC10LvQuNC8INC90LAgMjYKICAgIGFkZCBhbCwgJ0EnCiAgICBqbXAgc3RvcmVfY2hhcgoKc2tpcF9jaGFyOgogICAgam1wIG5leHRfY2hhcgoKc3RvcmVfY2hhcjoKICAgIHN0b3NiICAgICAgICAgICAgICAgICAgICAgIDsg0KHQvtGF0YDQsNC90Y/QtdC8INC+0LHRgNCw0LHQvtGC0LDQvdC90YvQuSDRgdC40LzQstC+0Lsg0LIgW2VkaV0KCm5leHRfY2hhcjoKICAgIGxvb3AgcHJvY2Vzc19jaGFyICAgICAgICAgIDsg0J/QtdGA0LXRhdC+0LTQuNC8INC6INGB0LvQtdC00YPRjtGJ0LXQvNGDINGB0LjQvNCy0L7Qu9GDCgogICAgOyDQl9Cw0L/QuNGB0Ywg0LTQsNC90L3Ri9GFINCyINCy0YvRhdC+0LTQvdC+0Lkg0YTQsNC50LsKICAgIG1vdiBlYXgsIDQgICAgICAgICAgICAgICAgICA7IHN5c193cml0ZQogICAgbW92IGVieCwgZWN4ICAgICAgICAgICAgICAgIDsg0JTQtdGB0LrRgNC40L/RgtC+0YAg0LLRi9GF0L7QtNC90L7Qs9C+INGE0LDQudC70LAKICAgIG1vdiBlY3gsIGJ1ZmZlciAgICAgICAgICAgICA7INCR0YPRhNC10YAg0LTQu9GPINC30LDQv9C40YHQuAogICAgbW92IGVkeCwgZHdvcmQgW2J5dGVzX3JlYWRdIDsg0JrQvtC70LjRh9C10YHRgtCy0L4g0LHQsNC50YIg0LTQu9GPINC30LDQv9C40YHQuAogICAgaW50IDB4ODAKICAgIGptcCByZWFkX2xvb3AKCmNsb3NlX2ZpbGVzOgogICAgOyDQl9Cw0LrRgNGL0YLQuNC1INGE0LDQudC70L7QsgogICAgbW92IGVheCwgNiAgICAgICAgICAgICAgICAgIDsgc3lzX2Nsb3NlCiAgICBtb3YgZWJ4LCBlYnggICAgICAgICAgICAgICAgOyDQl9Cw0LrRgNGL0YLRjCDQstGF0L7QtNC90L7QuSDRhNCw0LnQuwogICAgaW50IDB4ODAKCiAgICBtb3YgZWF4LCA2ICAgICAgICAgICAgICAgICAgOyBzeXNfY2xvc2UKICAgIG1vdiBlYngsIGVjeCAgICAgICAgICAgICAgICA7INCX0LDQutGA0YvRgtGMINCy0YvRhdC+0LTQvdC+0Lkg0YTQsNC50LsKICAgIGludCAweDgwCgpleGl0OgogICAgbW92IGVheCwgMSAgICAgICAgICAgICAgICAgIDsgc3lzX2V4aXQKICAgIHhvciBlYngsIGVieCAgICAgICAgICAgICAgICA7INCa0L7QtCDQstGL0YXQvtC00LAgMAogICAgaW50IDB4ODAKCmVycm9yX29wZW5faW5wdXQ6CiAgICBtb3YgZWF4LCA0ICAgICAgICAgICAgICAgICAgOyBzeXNfd3JpdGUKICAgIG1vdiBlYngsIDEgICAgICAgICAgICAgICAgICA7IHN0ZG91dAogICAgbW92IGVjeCwgZXJyb3Jfb3Blbl9pbiAgICAgIDsg0KHQvtC+0LHRidC10L3QuNC1INC+0LEg0L7RiNC40LHQutC1CiAgICBtb3YgZWR4LCBsZW5fZXJyb3Jfb3Blbl9pbiAgOyDQlNC70LjQvdCwINGB0L7QvtCx0YnQtdC90LjRjwogICAgaW50IDB4ODAKICAgIGptcCBleGl0CgplcnJvcl9vcGVuX291dHB1dDoKICAgIG1vdiBlYXgsIDQgICAgICAgICAgICAgICAgICA7IHN5c193cml0ZQogICAgbW92IGVieCwgMSAgICAgICAgICAgICAgICAgIDsgc3Rkb3V0CiAgICBtb3YgZWN4LCBlcnJvcl9vcGVuX291dCAgICAgOyDQodC+0L7QsdGJ0LXQvdC40LUg0L7QsSDQvtGI0LjQsdC60LUKICAgIG1vdiBlZHgsIGxlbl9lcnJvcl9vcGVuX291dCA7INCU0LvQuNC90LAg0YHQvtC+0LHRidC10L3QuNGPCiAgICBpbnQgMHg4MAogICAgam1wIGV4aXQK