Реализация функции возведения в степень - Assembler

  1. Всем привет. Прохожу один курс по асму, попалась такая задача: написать функцию, принимающую два беззнаковых числа (каждое из которых может равняться нулю), возвести в степень и вернуть ответ в rax. Написал такой код:


textual

Код к задаче: «Реализация функции возведения в степень - Assembler»

use64
 
; Входные данные: RCX - база (X), RDX - степень (Y); числа целые знаковые
; Результат: CF=0 - всё хорошо, RAX = X^Y (знаковое число); CF=1 - произошло переполнение, RAX = -1
SIntPower:
                ; Проверка исходных значений
                mov     eax,1                   ; результат RAX = 1 (пока что)
                test    rdx,rdx
;               jz      .exit                   ; если Y = 0, результат = 1 (даже для X = 0) - ЗАКОММЕНТИРОВАНО, т.к. нет смысла, и так будет выход на первом цикле вычислений
                js      .neg                    ; если Y < 0, прыгаем
 
                ; Вычисление
        .loop:  shr     rdx,1                   ; CF = младший бит EDX
                jnc     .nomul                  ; если CF=0, пропускаем умножение
                imul    rax,rcx                 ; иначе RAX = RAX * RCX
                jo      .overflow               ; произошло переполнение?
                test    rdx,rdx
        .nomul: jz      .exit                   ; выходим, если RDX = 0
                imul    rcx,rcx                 ; иначе RCX = RCX^2
                jno     .loop                   ; повторяем цикл, если не было переполнения
        .overflow:
                xor     eax,eax                 ; иначе возвращаем RAX = -1 и CF=1 (это будет после dec rax) в случае переполнения
        .zero:
                dec     rax                     ; результат RAX = 0
        .exit:  ret
 
        .neg:   ; Отрицательная степень
                cmp     rcx,1
                je      .exit                   ; если X = 1, результат = 1 - эти 2 строки можно вынести к началу (после mov eax,1), это ускорит возведение 1 в степень, но замедляют другие случаи возведения в положительную степень
                cmp     rcx,-1
                jne     .zero                   ; если X <> -1, результат будет = 0 (максимально возможное значение: 2^-1 = 0.5, но мы его всё равно округлим в меньшую сторону до 0)
                test    dl,al                   ; иначе (если X = -1), проверяем чётность Y (AL = 1)
                jz      .exit                   ; если Y чётная, результат = 1
                neg     rax                     ; иначе результат = -1 (можно заменить на mov rax,rcx)
                ret
 
; Входные данные: RCX - база (X), RDX - степень (Y); числа целые БЕЗзнаковые
; Результат: CF=0 - всё хорошо, RAX = X^Y (БЕЗзнаковое число); CF=1 - произошло переполнение, RAX = 0FFFFFFFFFFFFFFFFh (-1)
UIntPower:
                ; Подготовка
                mov     eax,1                   ; результат RAX = 1 (пока что)
;               cmp     rcx,rax
;               je      .exit                   ; если X = 1, результат = 1 - ЗАКОММЕНТИРОВАНО, т.к. эти 2 строки ускоряют возведение 1 в степень, но замедляют другие случаи
                mov     r8,rdx                  ; R8 = Y (т.е. RDX будет уничтожен после умножения через mul)
                mov     r9d,0FFFFFFFFh          ; R9 = 0FFFFFFFFh
 
                ; Вычисление
                jmp     .start                  ; пропускаем imul (он нужен только для следующих циклов)
        .loop:  imul    rcx,rcx                 ; RCX = RCX^2 (перемещено сюда, чтобы не делать лишних jcc-инструкций внутри цикла)
        .start: shr     r8,1                    ; CF = младший бит R8
                jnc     .nomul                  ; если CF=0, пропускаем умножение
                mul     rcx                     ; иначе RDX:RAX = RAX * RCX
                test    rdx,rdx
                jnz     .overflow               ; произошло переполнение?
                test    r8,r8
        .nomul: jz      .exit                   ; выходим, если R8 = 0
                cmp     rcx,r9
                jbe     .loop                   ; повторяем цикл, если RCX <= 0FFFFFFFFh (R9), иначе будет переполнение при возведении в квадрат
        .overflow:
                or      rax,-1                  ; иначе возвращаем RAX = 0FFFFFFFFFFFFFFFFh
                stc                             ; и CF=1
        .exit:  ret

СДЕЛАЙТЕ РЕПОСТ

10   голосов, оценка 4.100 из 5



Похожие ответы
  1. Сам я работаю на Масме для одной темы изучаю пример на Фасме в определённых частях кода мне интересно узнавать какое значение у определённого объекта Для этого сделал тандем функций wsprintf и MessageBox принцип я думаю всем понятный первая функция переводит значение в текстовый вид а вторая банально выводит это значение через месаджбокс всё работает нормально но каждый раз ставить этот тандем в нужном месте мягко говоря утомляет по этому решил завернуть этот тандем в функцию

  1. в задании сказано реализовать три ветки поведения программы: при х<13 - ((X^2)/2)-15 x>13 3x-15 x=13 ((2x)/3)-5 первые две ветки работают отлично. проблема с 3 ибо не получаеться 26/3 а потом отнять 5. в итоге должно получиться 3, у меня почему то получаеться 33.(после деления работать с целой частью (26/3=8-5=3)) вот код програмы. программу нужно реализовать через свич х=13 это 3 кейс вот код программы

  1. Дорогие знатоки, можете ли вы, по возможности, указать ссылкой на программу с построением графиков в Assembler. Заранее благодарен.

  1. Помогите написать програму пожалуйста. Условие: Штамповка деталей диаметром d1 от 0 до 5 дырок, диаметром d2 от 6 до 10 дыр.

  1. Составить программу на языке программирования Ассемблер, в которой реализована функция, вычисляющая функцию f(x)=(x^3+1)+12x на определенном участке. Диапазон переменных для вычисления значений функции задается оператором с клавиатуры.

  1. Здраствуйте, уже 3 час бьюсь что бы вызвать функцию в asm вставке, но никак не удаётся Этот код выполняется в обычном цикле, где i ровняется индексу, а p указателем на структуру куда надо записать элемент Arg

  1. Задание такое - Написать программу для решения функции y=х^2-x^4, где х меняется от -2 до +2 с шагом 0,5. Нужно вычислить функцию на каждом шаге. В формате вычисления с плавающей комой. Процессор х86.

  1. Написал резидентную программу, всё работает, но если моя или другие программы вызывают функцию 4ch прерывания 21h, консоль перестаёт реагировать на нажатия, хотя курсор мигает. Мне нужно вызывать эту функцию для выхода из копии программы при повторном запуске. Также, если после загрузки вызываю программу mem, то консоль перестаёт реагировать на нажатия, хотя курсор мигает. Скорее всего это связано с заменой вектора прерываний, но вот что именно не так, поянять не могу. Буду благодарен за помощь.