Модуль в сборке 68K

Мне было интересно, есть ли команда/метод для выполнения по модулю в сборке Motorola 68000?

Я хочу выполнить d4 мод 1000 и d3 мод 100.

В настоящее время я использую следующую формулу, но это занимает несколько строк:

если по модулю n, то a - (n * int(a/n))

Я видел эту формулу для d0 mod d1

CLR.L D2
MOVE.W D0,D2
DIVU D1,D2
SWAP D2

Спасибо за ответы.


person Dartuso    schedule 13.10.2017    source источник
comment
Если вы хотите, чтобы это работало быстро, посмотрите на вывод gcc для функции C, которая делает то, что вы хотите. Он будет использовать мультипликативную инверсию для деления, которое на большинстве процессоров выполняется намного быстрее, чем деление. На современном x86 значительно быстрее умножить + сдвинуть, затем снова умножить и вычесть из исходного дивиденда, чем использовать аппаратную инструкцию div для прямого получения остатка.   -  person Peter Cordes    schedule 14.10.2017
comment
Почему GCC использует умножение на странное число в реализации целочисленного деления. При написании asm вручную самый простой способ сгенерировать константу для себя — это поместить unsigned foo(unsigned x) { return x/1000; } или % в компилятор Си.   -  person Peter Cordes    schedule 14.10.2017


Ответы (2)


Инструкция DIVU делает именно то, что вы ищете. Когда вы выполняете DIVU, длинное слово адресата делится на слово источника. В вашем случае вы написали:

DIVU D1, D2

Итак, D2 делится на D1. В частном возвращаются две части. Старшее слово D2 будет содержать остаток (модуль), а младшее слово содержит частное. Вот почему вы обычно видите SWAP d2. Это перемещает остаток в младшее слово.

person David Hoelzer    schedule 13.10.2017
comment
Спасибо, очень информативно, как можно удалить слово старшего или младшего порядка из регистра данных? - person Dartuso; 14.10.2017
comment
Вы можете сделать следующее: CLR.W D2, за которым следует SWAP D2 Это очищает младшее слово (частное), а затем выполняет обмен. - person David Hoelzer; 14.10.2017
comment
Вы забываете, что если частное становится настолько большим, что не помещается в 16 бит, инструкция DIVU сдается и помечает переполнение в регистре кода условия, и результат становится ненадежным. - person Gunnar Vestergaard; 01.01.2020

  1. Выполнить деление, результат — частное в младших 16 битах, модуль в старших 16 битах
  2. Установите частное равным нулю, чтобы...
  3. .. когда вы меняете модуль, это действительное 32-битное значение

START
       DIVU  #1000,D4
       CLR.W D4             ; delete quotient
       SWAP  D4             ; modulus from top to bottom 16 bits

       DIVU  #100,D3
       CLR.W D3             ; delete quotient
       SWAP  D3             ; modulus from top to bottom 16 bits

Одна вещь, которую этот код не обрабатывает, заключается в том, будет ли результат больше, чем #ffff(65535), для чего вам нужен дополнительный код, возможно, проверка, чтобы проверить, больше ли D3/D4, чем делитель, сдвинутый вверх на 16 бит.

Поскольку модуль будет представлять собой число от 0 до 99/999, в качестве альтернативы вы можете использовать EXT.W после замены вместо CLR.W до замены. Обратите внимание, что знак EXT расширяет значение.

person vogomatix    schedule 13.09.2018