Переполнение влево при 68k / x86? - PullRequest
4 голосов
/ 11 ноября 2009

Я слышал, что архитектуры Motorola 68000 и Intel x86 по-разному обрабатывают переполнение от сдвига влево. В частности, 68k LSL в сравнении с инструкциями по сборке Intel SAL / SHL.

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

Ответы [ 3 ]

6 голосов
/ 11 ноября 2009

Бит Х не задействован. Путаница с флагами 68000 возникает из-за двух инструкций сдвига влево:

  • LSL, логический сдвиг влево, очищает флаг переполнения.
  • ASL, Арифметический сдвиг влево, устанавливает флаг V, если MSB меняет знак в любое время в течение сдвига.

Набор команд x86 не такой мощный. Если число сдвигов = 1, то OF, флаг переполнения = (MSB XOR CF), т.е. если MSB изменил знак в результате 1-битного сдвига, OF = 1, иначе OF = 0.

Если число сдвигов> 1, то OF равно undefined. ( HTML-фрагмент документации Intel для SHL ).

4 голосов
/ 11 ноября 2009

Руководства программиста для процессоров имеют особенности:

Motorola 68K :

X — Set according to the last bit shifted out of the operand; 
    unaffected for a shift count of zero. 
N — Set if the result is negative; cleared otherwise. 
Z  — Set if the result is zero; cleared otherwise. 
V — Always cleared. 
C — Set according to the last bit shifted out of the operand; 
    cleared for a shift count of zero. 

Intel x86 :

  • Флаг CF содержит значение последнего бита, сдвинутого из операнда назначения; он не определен для команд SHL и SHR, где число больше или равно размеру (в битах) операнда назначения.
  • Флаг OF затрагивается только для 1-битных сдвигов (см. «Описание» выше); в противном случае он не определен.
  • Флаги SF, ZF и PF устанавливаются в соответствии с результатом. Если количество равно 0, флаги не затрагиваются.
  • Для ненулевого счета флаг AF не определен.

Таким образом, флаг переполнения обрабатывается по-разному. В x86 вы узнаете, если умножение на 2 (сдвиг влево на один бит) приведет к переполнению. Я не знаю, почему это так характерно только для 1-битных смен. Я бы предположил (и это только предположение), что флаг OF устанавливается в соответствии с «последним» сдвигом битов - и это может не указывать на то, переполнена ли вся операция, поэтому Intel просто задокументировала это как «undefined».

3 голосов
/ 11 ноября 2009

(Да, я рассматриваю свой Motorola 68000 Reference с 1979 года.)

Вероятно, то, о чем вы думаете, это довольно странный бит Х 68000. Бит eXtend по сути является копией бита C (переноса), но не подвержен неарифметическим инструкциям. Предположим, вы добавляете целые числа из 12 слов, например. В x86 вы можете увидеть что-то вроде:

  .
  .
loop:
  ADC AX,[SI]    ; recycle carry-out from last iter as carry-in to this one

  LEA SI, [SI+2] ; flags untouched
  INC BX         ; BX is loop index.  sets all flags except CF
  CMP BX, 12     ; doh, changes carry (BUG)
  JB  loop

Этот код не работает, потому что инструкция сравнения сбрасывает флаг переноса. Это одна из причин, почему инструкция loop была исторически полезна, считая CX до нуля без изменения флагов. Обратный отсчет с помощью dec / jnz также работает, но вызывает задержки с частичным флагом на современном x86. К сожалению, loop сейчас тоже медленный , поэтому не было никакого хорошего способа сделать такой цикл примерно с 486 до Sandybridge.

Но в 68000:

  .
  .
loop:
  ADDX.W (A0)+, D0   ; both C and X set the same
  INC.W  D7          ; D7 is loop index
  CMP.W  #12, D7     ; harms C, but X left intact
  BCC  loop

Motorola думала, что они делают одолжение программистам, но X-битный бизнес в итоге вызвал больше путаницы, чем оно того стоило.

...