Выделение функций в отдельные файлы

Последнее обновление: 28.12.2022

Если программа небольшая, то можно весь код определить в одном файле. Однако если программа содержит много кода, тогда расположение кода в одном файле может усложить разработку приложения. Кроме того, возможно отдельные части приложения - отдельные функции затем потребуется применить в других приложениях. В этом случае гораздо рациональнее вынесение функций в отдельные файлы.

Например, определим файл copy.s, который будет содержать определение функции copy для копирования одной строки в другую:

// Функция copy, которая копирует символы из одной строки в другую
// Параметры функции
// X0 - адрес входящей строки
// X1 - адрес исходящей строки
//
// Результат функции
// X0 - длина строки
.global copy            // чтобы функция была видна извне
copy:
    MOV X4, X1          // сохраняем адрес начала строки, чтобы потом вычислить ее длину
// в цикле получаем все байты, пока не дойдем до нулевого байта
loop: 
    LDRB W5, [X0], #1        // загружаем из X0 один байт - один символ в W5 и увеличиваем адрес в X0 на 1 байт
    CMP W5, #0              // сравниваем с нулевым байтом
    B.EQ endloop            // если нулевой байт, переход к метке endloop 
    STRB W5, [X1], #1      // если символы равны, заменяем байт по адресу X1 и увеличиваем адрес в X1 на 1 байт
    B loop                  // переход обратно к метке loop для копирования следующего символа
endloop:    
    SUB X0, X1, X4      // помещаем в регистр X0 длину строки -  X0 = X1 - X4
    RET                 // выход из функции

В функции проходим по каждому байту из строки, адрес которой хранится в регистре Х0 и копируем его в строку, адрес которой хранится в регистре Х1. Когда дойдем до нулевого байта, то выходим из цикла, в регистр Х0 помещаем длину строки и завершаем выполнение функции.

Допустим, у нас есть главный файл программы, который называется main.s и который использует копирование с помощью вышеопределенной функции copy:

.global _start 
_start: 
    LDR X0, =input      // строка, их которой надо скопировать символы
    LDR X1, =output     // строка, в которую надо скопировать символы
    BL copy             // вызов функции copy

// печать строки на консоль
    MOV X2, X0          // в регистр X2 передаем результ функции copy - длину строки из регистра X0
    MOV X0, #1          // 1 = StdOut - стандартный поток вывода
    LDR X1, =output     // загружаем адрес выводимой строки
    MOV X8, #64         // функция Linux для вывода в поток
    SVC 0               // вызываем функцию Linux
// выход из программы
    MOV X0, 0         // код возврата - 0
    MOV X8, #93       // устанавливаем функцию Linux для выхода из программы
    SVC 0             // Вызываем функцию Linux

.data
    input: .asciz "Hello METANIT.COM!\n"
    output: .fill 256, 1, 0

При компиляции ассемблеру в этом случае передаются все компилируемые файлы, то есть main.s и copy.s:

aarch64-none-elf-as main.s copy.s -o main.o

Причем собираются они в один файл main.o. Линкеру передается только один файл main.o:

aarch64-none-elf-ld main.o -o main
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850