2014-12-09 5 views
5

Я хочу разделить число 16 бит на два. Мое решение проблемы было нижеКак разделить число 16 бит на 2 в 6502 asm?

lda $17 ;set high byte 
    ldx $32 ;set low byte 

divide: 
    PHA   ;push A to stack   
    TXA   ;X > A 
    LSR   ;divide low byte by 2 
    TAX   ;A > X 

    PLA   ;pull A from stack 
    LSR   ;divide high byte by 2 
    BCC +  ;C=0, skip 

    PHA   ;while C=1 
    TXA   ;add $80 to the lsb 
    ADC#$80 
    TAX 
    PLA 
+ 
    +printDecimal $0400+120 

Все PHA/PLA обман, потому что мой printDecimal макрос читает MSB из A и LSB из X.

Когда я проверяю альтернативы в Интернете, я нашел альтернативу 4 инструкции к моему скромному разделение. Но я не понял.

div2: 
    LDA counter_hi  ;Load the MSB 
    ASL     ;Copy the sign bit into C 
    ROR counter_hi  ;And back into the MSB 
    ROR counter_lo  ;Rotate the LSB as normal 

    LDA counter_hi 
    LDX counter_lo  
    +printDecimal $0400+40  

Как это работает?

ответ

8

Подразделение на 2 (без знака числа) - это то же самое, что смещение всех бит в одну позицию вправо. Так, например, число 100 представлено в двоичной системе по:

01100100 

Перемещение всех позиций одного до нужных выходов

00110010 

который является двоичным представлением 50.

Команда движется ROR все позиции направо. Новый MSB байта будет равен старому значению флага переноса, а новое значение флага переноса будет равно старому младшему байту байта.

Если 16-битный номер без знака, то достаточно, чтобы сместить максимум и младшие байты числа справа:

LSR counter_hi 
ROR counter_lo 

LSR и ROR и перенести их аргумент вправо, но LSR делает MSB counter_hi 0 и сдвигает LSB counter_hi в флаг переноса, в то время как ROR делает MSB of counter_lo равным (старому) LSB counter_hi.

Если номер подписан, вам нужно сохранить бит знака и убедиться, что бит знака нового номера тот же. Это то, что делают первые две команды кода, который вы цитировали. Обратите внимание, что это работает, потому что номер хранится в two's complement.

+5

LSR = CLC + ROR – i486

+0

этом. Умножение и деление на (кратные) два являются не более чем бит-сдвигами влево или вправо. «LIB hi-byte, ROR lo-byte» достигнет вашей цели с 16-разрядным делением без повторений кода цикла, регистрации свопов и т. Д. –

+0

@ i486. Спасибо i486. Я отредактировал ответ. – Hoopje

2

Если я правильно помню, ROR и ROL сдвигают биты в указанном направлении, а наименее значимый бит (для ROR) и наиболее значимый (для ROL) перемещаются в флаг Carry.

Прошло около 25 лет с тех пор, как я посмотрел на любой 6502, хотя мне это не совсем понятно, но это сразу же, как я думал, что это будет сделано.

Редактировать: Кроме того, в ROR и ROL существующее состояние флага переноса переносится в младший/самый старший бит аккумулятора.

4

Это работает как комментарий в коде say;) В 6502, к сожалению, нет арифметического сдвига вправо, что оставило бы бит знака неповрежденным. Поэтому его нужно эмулировать. Для этого сначала бит знака извлекается из верхнего слова. Обратите внимание, что это делается с использованием аккумулятора, поэтому исходное значение не изменяется. На верхнем слове используется ROR, который вращает 9-битное значение, полученное из расширения операнда с флагом переноса. Таким образом, бит знака, который в настоящее время находится в CF, будет повернут в MSB, остальные биты будут сдвинуты вправо, а LSB окажется в CF. Это выполнило подписанное подразделение. Второй ROR на низком слове просто переносит LSB из верхнего слова в MSB низкого слова и сдвигает остальные биты вправо.

2

(Очевидно, что вы знаете, сдвигая вправо на N бит делится на 2^N, а так же оставил сдвигающие умножает на 2)

От this reference:

помещает наибольший значащий бит (СЗБ) привет байт counter_hi в регистр переноса (так что знак запоминается при сдвиге - деление на положительное целое число (2) не изменит первоначальный знак нашего 16-битного номера).

ROR counter_hi сдвигает counter_hi на 1 бит направо. Важно:

Carry смещается в бит 7, а исходный бит 0 сдвигается в Carry.

, который служит двум целям - сохраняя оригинальный знак, а также передаст младший бит counter_hi для второго ROR

ROR counter_lo затем делает то же самое для младшего байта. Младший бит counter_hi теперь сдвинуты в MSB из counter_lo

2

Не помню, все режимы адресации команд, но, возможно, это нормально:

LSR 
PHA 
TXA 
ROR 
TAX 
PLA 

 Смежные вопросы

  • Нет связанных вопросов^_^