Часть 22: Ассемблерный математический сопроцессор

Arduino использует программную библиотеку для работы с float (числами с плавающей точкой), которая занимает ~4 КБ Flash и выполняется медленно. Мы напишем свои функции на ассемблере для критических вычислений.

Умножение двух 16-битных чисел (быстрый алгоритм):

.global mul16
; Умножение двух 16-битных чисел
; Вход: R16:R17 = A, R18:R19 = B
; Выход: R24:R25:R26:R27 = A * B (32 бита)

mul16:
    PUSH R0
    PUSH R1
    PUSH R2
    PUSH R3
    
    ; Копируем операнды
    MOV R0, R16
    MOV R1, R17
    MOV R2, R18
    MOV R3, R19
    
    ; Обнуляем результат
    CLR R24
    CLR R25
    CLR R26
    CLR R27
    
    ; Цикл по 16 битам
    LDI R20, 16
mul_loop:
    ; Проверяем младший бит R0
    SBRC R0, 0
    ; Если бит установлен, добавляем B к результату
    ADD R24, R2
    ADC R25, R3
    ADC R26, R1
    ADC R27, R1
    
    ; Сдвигаем A вправо
    LSR R1
    ROR R0
    
    ; Сдвигаем B влево
    LSL R2
    ROL R3
    
    DEC R20
    BRNE mul_loop
    
    POP R3
    POP R2
    POP R1
    POP R0
    RET

Использование в C++:

extern "C" {
    uint32_t mul16(uint16_t a, uint16_t b);
}

void setup() {
    Serial.begin(115200);
    
    uint32_t result = mul16(12345, 6789);
    Serial.print("12345 * 6789 = ");
    Serial.println(result);
}

void loop() {}

Быстрый квадратный корень (метод Ньютона на 16 бит):
.global isqrt16
; Целочисленный квадратный корень 16-битного числа
; Вход: R16:R17 = число
; Выход: R24 = корень (8 бит)

isqrt16:
    CLR R24
    LDI R25, 128          ; Начальное приближение = 128
    LDI R20, 8            ; 8 итераций

sqrt_loop:
    MOV R22, R24
    ADD R22, R25          ; mid = (low + high) / 2
    ROR R22
    
    ; Вычисляем mid * mid (используем mul16)
    MOV R16, R22
    MOV R17, R1           ; Обнуляем старший байт
    CLR R18
    MOV R19, R22
    CALL mul16
    
    ; Сравниваем mid^2 с входным числом
    ; ...
    DEC R20
    BRNE sqrt_loop
    
    RET

Вам также может понравиться

About the Author: ардуинчиков

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *