МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
ФГБОУ ВО «АЛТАЙСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ»
Институт Цифровых Технологий Электроники и Физики (ИЦТЭФ)
Кафедра вычислительной техники и электроники (ВТиЭ)
Лабораторная работа № 3
Основы программирования на языке Ассемблер
Вариант 6
Выполнил: студент гр. 5.205-2
Керницкий М.В.
Проверил: преп. каф. ВТиЭ
А.В. Сеулеков
Лабораторная работа защищена
« » 2025 г.
Оценка
Барнаул 2025
Задание
Вывести на экран монитора в первую строчку символы цифр от “0” до “9” так, что бы каждой
цифре предшествовал 1 пробел слева и 8 пробелов справа. По нажатию клавиши “стрелка вниз”
- выводить информацию в следующую строку так, что бы количество предшествующих цифре
пробелов увеличивалось на единицу, а количество пробелов справа уменьшалось на единицу.
Код программы
.global _main // Делаем метку _main доступной извне
// Системные вызовы
SYS_WRITE = 4 // Номер системного вызова для записи
SYS_READ = 3 // Номер системного вызова для чтения
SYS_EXIT = 1 // Номер системного вызова для выхода
STDIN = 0 // Стандартный ввод (клавиатура)
STDOUT = 1 // Стандартный вывод (экран)
.data // Начало секции данных
digits: .ascii "0123456789" // Строка с цифрами от 0 до 9
newline: .asciz "\n" // Символ перевода строки
space: .asciz " " // Символ пробела
.text // Начало секции кода
_main:
mov x19, #1 // Инициализация: x19 = 1 (количество левых пробелов)
mov x20, #8 // Инициализация: x20 = 8 (количество правых пробелов)
main_loop:
mov x21, #0 // x21 = 0 (начальная цифра для вывода)
print_line:
// Левые пробелы
mov x22, x19 // x22 = x19 (счетчик левых пробелов)
left_spaces:
cbz x22, print_digit // Если x22 == 0, перейти к print_digit
mov x0, #STDOUT // x0 = 1 (файловый дескриптор stdout)
adrp x1, space@PAGE // Загрузить адрес страницы для space
add x1, x1, space@PAGEOFF // Добавить смещение в странице
mov x2, #1 // x2 = 1 (количество байт для записи)
mov x16, #SYS_WRITE // x16 = 4 (системный вызов write)
svc #0 // Вызов системного вызова
sub x22, x22, #1 // x22 = x22 - 1 (уменьшить счетчик пробелов)
b left_spaces // Перейти к началу цикла
print_digit:
// Вывод цифры
mov x0, #STDOUT // x0 = 1 (stdout)
adrp x1, digits@PAGE // Загрузить адрес страницы для digits
add x1, x1, digits@PAGEOFF // Добавить смещение в странице
add x1, x1, x21 // x1 = x1 + x21 (адрес текущей цифры)
mov x2, #1 // x2 = 1 (записать 1 байт)
mov x16, #SYS_WRITE // x16 = 4 (системный вызов write)
svc #0 // Вызов системного вызова
1
// Правые пробелы
mov x22, x20 // x22 = x20 (счетчик правых пробелов)
right_spaces:
cbz x22, next_digit // Если x22 == 0, перейти к next_digit
mov x0, #STDOUT // x0 = 1 (stdout)
adrp x1, space@PAGE // Загрузить адрес страницы для space
add x1, x1, space@PAGEOFF // Добавить смещение в странице
mov x2, #1 // x2 = 1 (количество байт)
mov x16, #SYS_WRITE // x16 = 4 (системный вызов write)
svc #0 // Вызов системного вызова
sub x22, x22, #1 // x22 = x22 - 1 (уменьшить счетчик)
b right_spaces // Перейти к началу цикла
next_digit:
add x21, x21, #1 // x21 = x21 + 1 (перейти к следующей цифре)
cmp x21, #10 // Сравнить x21 с 10
blt print_line // Если x21 < 10, перейти к print_line
// Перевод строки
mov x0, #STDOUT // x0 = 1 (stdout)
adrp x1, newline@PAGE // Загрузить адрес страницы для newline
add x1, x1, newline@PAGEOFF // Добавить смещение в странице
mov x2, #1 // x2 = 1 (количество байт)
mov x16, #SYS_WRITE // x16 = 4 (системный вызов write)
svc #0 // Вызов системного вызова
// Чтение клавиши
wait_key:
sub sp, sp, #16 // Выделить 16 байт на стеке для буфера
mov x0, #STDIN // x0 = 0 (файловый дескриптор stdin)
mov x1, sp // x1 = sp (буфер для чтения)
mov x2, #3 // x2 = 3 (прочитать 3 байта)
mov x16, #SYS_READ // x16 = 3 (системный вызов read)
svc #0 // Вызов системного вызова
// Проверка стрелки вниз (ESC [ B)
ldrb w0, [sp] // Загрузить байт из буфера в w0
cmp w0, #0x1B // Сравнить с ESC (0x1B)
bne wait_key // Если не ESC, ждать другую клавишу
ldrb w0, [sp, #1] // Загрузить второй байт из буфера
cmp w0, #0x5B // Сравнить с '[' (0x5B)
bne wait_key // Если не '[', ждать другую клавишу
ldrb w0, [sp, #2] // Загрузить третий байт из буфера
cmp w0, #0x42 // Сравнить с 'B' (0x42 - стрелка вниз)
bne wait_key // Если не стрелка вниз, ждать другую клавишу
// Увеличиваем сдвиг
add x19, x19, #1 // x19 = x19 + 1 (увеличить левые пробелы)
subs x20, x20, #1 // x20 = x20 - 1 (уменьшить правые пробелы)
bpl main_loop // Если x20 >= 0, перейти к main_loop
// Выход когда правые пробелы закончились
exit:
add sp, sp, #16 // Освободить 16 байт на стеке
2
mov x0, #0 // x0 = 0 (код возврата 0 - успех)
mov x16, #SYS_EXIT // x16 = 1 (системный вызов exit)
svc #0 // Вызов системного вызова (завершение программы)
Тестирование программы.
Код ^[[B означает нажатую клавишу вниз
Рис. 1. Результат работы программы.