; Секция данных (инициализированные данные)
section .data
msg db 'Sum of digits: ', 0 ; Строка сообщения с нуль-терминатором
msg_len equ $ - msg - 1 ; Вычисляем длину сообщения (без учета нуль-терминатора)
; $ - текущая позиция ассемблера, msg - начало строки
newline db 10 ; Символ новой строки (ASCII 10 = '\n')
; Секция неинициализированных данных (резервирование памяти)
section .bss
buffer resb 12 ; Резервируем 12 байт для буфера вывода числа
; Секция кода
section .text
global _start ; Объявляем точку входа _start как глобальную
_start:
; Инициализация регистров для вычисления суммы цифр
mov eax, 0x12AC8 ; Загружаем наше шестнадцатеричное число в EAX
xor ebx, ebx ; Обнуляем EBX - здесь будем накапливать сумму цифр
mov ecx, 16 ; Загружаем 16 в ECX (основание системы счисления)
; Цикл вычисления суммы цифр
.sum_loop:
test eax, eax ; Проверяем, не стало ли число нулём
jz .print ; Если ноль - переходим к выводу результата
xor edx, edx ; Обнуляем EDX (он будет содержать остаток от деления)
div ecx
; Делим EDX
:EAX на ECX
(16) ; Результат (частное) в EAX, остаток (цифра) в EDX
add ebx, edx ; Добавляем цифру (EDX) к общей сумме (EBX)
jmp .sum_loop ; Повторяем цикл
; Подготовка к выводу результата
.print:
; Преобразуем число (сумму цифр) в строку ASCII
lea edi, [buffer+11] ; Загружаем адрес конца буфера (12-й байт) в EDI
mov byte [edi], 0 ; Записываем нуль-терминатор в конец буфера
dec edi ; Перемещаем указатель на предыдущую позицию
mov eax, ebx ; Копируем сумму цифр в EAX для преобразования
mov ecx, 10 ; Устанавливаем делитель 10 (для десятичного вывода)
; Цикл преобразования числа в строку
.convert_loop:
xor edx, edx ; Обнуляем EDX перед делением
div ecx
; Делим EDX
:EAX на
10 ; Частное в EAX, остаток (цифра) в EDX
add dl, '0' ; Преобразуем цифру (0-9) в ASCII символ
mov [edi], dl ; Сохраняем символ в буфер
dec edi ; Перемещаем указатель назад
test eax, eax ; Проверяем, осталось ли что-то для преобразования
jnz .convert_loop ; Если да, продолжаем цикл
; Вывод сообщения "Sum of digits: "
mov eax, 4 ; Номер системного вызова sys_write (4)
mov ebx, 1 ; Файловый дескриптор stdout (1)
mov ecx, msg ; Указатель на начало сообщения
mov edx, msg_len ; Длина сообщения
int 0x80 ; Вызов ядра Linux
; Вывод самого числа (суммы цифр)
mov eax, 4 ; sys_write
mov ebx, 1 ; stdout
lea ecx, [edi+1] ; Указатель на начало числа в буфере
lea edx, [buffer+12] ; Указатель на конец буфера
sub edx, ecx ; Вычисляем длину строки (конец - начало)
int 0x80 ; Вызов ядра
; Вывод символа новой строки
mov eax, 4 ; sys_write
mov ebx, 1 ; stdout
mov ecx, newline ; Указатель на символ новой строки
mov edx, 1 ; Длина 1 байт
int 0x80 ; Вызов ядра
; Завершение программы
mov eax, 1 ; Номер системного вызова sys_exit (1)
xor ebx, ebx ; Код возврата 0 (успешное завершение)
int 0x80 ; Вызов ядра