Nano Hash - криптовалюты, майнинг, программирование

Язык ассемблера и числа Фибоначчи

Для простоты я получил свой первый проект MASM32, и он выглядит следующим образом: «Напишите программу на ассемблере для генерации и отображения первых 24 чисел Фибоначчи, начиная с 1 и заканчивая 46368». Поскольку это мой первый проект, я, честно говоря, понятия не имею, как начать или написать этот код. Любая помощь приветствуется. Большое спасибо.

28.03.2016

  • Что вы пытались до сих пор? 29.03.2016
  • Вы начинаете с написания программы, которая отображает число. 29.03.2016
  • Вы можете пойти очень простым путем и просто создать данные, содержащие первые 24 числа, и распечатать их. ;) 29.03.2016
  • Попробуйте сначала написать программу на другом языке, например C, а затем посмотрите, сможете ли вы снова написать ее на ассемблере. 29.03.2016
  • @DavidHoelzer: в этом случае в формулировке задания говорится, что числа должны быть сгенерированы программой сборки. 29.03.2016
  • Всегда есть старый способ написать блок-схему, основанную на алгоритмическом подходе. 29.03.2016
  • С чего начать: посмотрите на вывод компилятора и, если вы все еще застряли, найдите [x86] fibonacci здесь. в стекопереполнении. Для расчетной части я бы рекомендовал мой ответ на другой вопрос Фибоначчи для эффективного цикла. Все начинается с простого, затем становится сложным, так что просто прекратите читать, как только вы запутаетесь. Он хранится в массиве, но вы можете изменить это на printf вызовов. 29.03.2016
  • Этот дубликат также хочет напечатать серию в 32-битном формате x86 с вызовом _printf. Или, может быть, просто печатает последнее значение, но демонстрирует использование printf. Однако код ужасно неэффективен, поскольку все временные файлы хранятся в памяти. 29.03.2016

Ответы:


1

fibunacci, как правило, решается рекурсивно, в то время как решение с помощью простого цикла не менее просто

вы уже знаете, что ваш массив будет состоять из 24 слов,
и на первый взгляд кажется, что ваш цикл будет состоять из 24 шагов.

в то время как f(1) и f(2) уже установлены, и вам нужны как минимум эти 2 элемента для работы, количество необходимых элементов 22, а не 24 ... так что давайте начнем с того, что мы уже знаем

fib  dw 24 dup (0)    ; i don't know masm too well, this should create 24 words
    mov word ptr[fib  ],1   ; f(1)
    mov word ptr[fib+2],1   ; f(2)

    mov cx,22           ; this will be the loop counter
l1:
    ; add up the last 2 elements
    dec cx
    jnz l1

хорошо, пока все хорошо. "Добавить последние 2 элемента" НАМАШИВАЕТСЯ для 2 регистров, где хранятся последние два элемента, чтобы не всегда приходилось читать их из памяти. поэтому давайте использовать AX и BX, AX для элемента n-2, BX для n-1. мы складываем их и сохраняем результат в «следующем» элементе массива.
для массивов отлично использовать si и di, пока мы пишем, DI (целевой индекс) — наш лучший выбор

fib  dw 24 dup (0)    ; i don't know masm too well, this should create 24 words

calculate:
    cld
    mov word ptr[fib  ],1   ; f(1)
    mov ax, 1   
    mov word ptr[fib+2],1   ; f(2)
    mov bx, 1
    mov di, offset fib+4    ; does this work in MASM ?

    mov cx,22           ; this will be the loop counter
l1:
    add ax,bx
    stosw           ; write new element to array   
                    ; note: this is equivalent to mov [di], AX and add si,2

    dec cx
    jnz l1

после сложения нам нужно загрузить ax и bx с правильными значениями, ax с f(n) и bx с f(n-1)... мы могли бы сделать это с чтением из массива, но если мы посмотрим поближе , AX — это f(n) (последний вычисленный элемент) для этого цикла, который будет f(n-1) для следующего цикла, а BX — это f(n-1) , который будет f(n-2) для следующего цикла. следующая петля. Так что все, что нам нужно сделать, это просто поменять их местами.

fib  dw 24 dup (0)    ; i don't know masm too well, this should create 24 words

calculate:
    cld
    mov word ptr[fib  ],1   ; f(1)
    mov ax, 1   
    mov word ptr[fib+2],1   ; f(2)
    mov bx, 1
    mov di, offset fib+4    ; does this work in MASM ?

    mov cx,22           ; this will be the loop counter
l1:
    add ax,bx
    stosw           ; write new element to array   
                    ; note: this is equivalent to mov [di], AX and add si,2
    xchg ax,bx      

    dec cx
    jnz l1

и вуаля: вы вычислили 24 элемента

PS: я не уверен, что MASM скомпилирует это, я использую другой ассемблер, дайте мне подсказку, и я исправлю

29.03.2016
  • толкать/хлопать? Что за черт? xchg ax,bx делает то же самое. Для условия конца цикла вы можете cmp edi, 24*2 + OFFSET fib или что-то в этом роде вместо того, чтобы тратить ecx на счетчик. Конечно, вам вообще не нужно сохранять результаты: вызов printf из цикла — это самый простой способ (сохранить состояние цикла в регистрах, сохраняемых вызовом). И почему вы используете 16-битные указатели? ОП, кажется, спрашивает конкретно о 32-битной версии. 29.03.2016
  • Кроме того, Фибоначчи часто реализуется рекурсивно, но это только потому, что люди выбирают его как пример рекурсивной функции при обучении рекурсии. Это сложнее и намного реализовать рекурсивно. (O(Fib(n)) вместо O(n), для простой рекурсивной реализации без мемоизации.) Развертывание двумя способами означает еще меньше перемещаемых данных: add ebx, edi / print ebx / add edi, ebx / print edi делает свое дело. В любом случае, люди из IMO должны обучать рекурсии, используя функцию, в которой рекурсия имеет смысл, а цикл требует структуры данных, подобной стеку. Обход дерева является хорошим примером. 29.03.2016
  • Я мог бы использовать сравнение указателей, но CX не нужен, и мне нравится использовать регистры в качестве счетчика, так зачем мне это делать. Так это более читабельно (по крайней мере, для моих глаз, но это личное предпочтение). Но вы совершенно правы насчет обмена, я все время забываю инструкции (слишком много наборов инструкций не помогают запомнить, какой набор содержит какую инструкцию), я изменил его 29.03.2016
  • Мне не нравится вводить счетчики, которые ни для чего не используются. cmp/jcc может объединяться с AMD и Intel даже до SnB, но dec/jcc может объединяться только с Intel SnB-семейством. Сравнение с конечным указателем по-прежнему связывает регистр для хранения конечного указателя, поэтому вы правы в том, что преимущество, как правило, невелико. (Редко, когда конечная точка может быть непосредственной в реальном коде, поскольку приращения указателя обычно более эффективны, чем режимы индексированной адресации, особенно в семействе Intel SnB). Однако уменьшение индекса отлично подходит для циклов с индексацией, которые могут перемещаться по массиву в обратном направлении. 29.03.2016
  • Кстати, xchg составляет 3 мкп на Intel. Вы можете использовать lea esi, [edi, ebx] / mov edi, ebx / mov ebx, esi или что-то в этом роде, если хотите избежать развертывания цикла, чтобы избавиться от лишних ходов. 29.03.2016
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..