Почему инструкции INC и DEC не влияют на флаг переноса?

Почему команда x86 INC (increment) и DEC (декремент) не влияет на CF (флаг переноса) в FLAGSREGISTER?

Ответы

Ответ 1

Чтобы понять, почему вам, вероятно, нужно помнить, что текущие процессоры "x86" с 32-разрядными и 64-битными значениями начали работу с гораздо более ограниченными 8-разрядными машинами, вернулись к Intel 8008. (Я закодировал в этом мире еще в 1973 году, Я все еще помню (тьфу) это!).

В этом мире регистры были драгоценными и маленькими. Вам нужны inc/dec для различных целей, наиболее распространенным из которых является управление контуром. Многие циклы включали выполнение "арифметики с несколькими точками" (например, 16 бит или более!) Благодаря тому, что inc/dec установил бит Z, вы могли бы использовать их для управления циклами довольно красиво; настаивая на том, что инструкции управления циклом не изменяют бит переноса, перенос сохраняется по итерациям цикла, и вы можете выполнять операции с множественными значениями без написания тонны кода для запоминания состояния переноса.

Это сработало очень хорошо, как только вы привыкли к уродливому набору команд.

На более современных машинах с большими размерами слов вам это не нужно, поэтому INC и DEC могут быть семантически эквивалентны ADD..., 1 и т.д. Это на самом деле то, что я использую, когда мне нужно переносить set: -}

В основном, я держусь подальше от INC и DEC, потому что они выполняют частичные обновления кода состояния, и это может вызвать смешные киоски в конвейере, и ADD/SUB этого не делают. Поэтому, когда это не имеет значения (большинство мест), я использую ADD/SUB, чтобы избежать киосков. Я использую INC/DEC только при сохранении небольшого значения кода, например, при установке в строку кэша, где размер одной или двух инструкций делает достаточную разницу для материи. Это, вероятно, бессмысленная nano [буквально!] - оптимизация, но я довольно старая школа в своих привычках кодирования.

Мое объяснение говорит нам, почему INC/DEC установил нулевой бит. У меня нет особого убедительное объяснение того, почему INC/DEC задает знак (и биты четности).

EDIT Апрель 2016: Кажется, что проблема с кабиной лучше справляется с современными x86. См. Инструкция INC и ADD 1: имеет ли это значение?

Ответ 2

Вопрос о том, почему знак, когда у вас есть флаг нуля, установленный inc/dec, лучше всего решать с вопросом: скорее бы вы предпочли без опции a?

a) for (n=7;n>=0;n--)   // translates to   `dec + jns`
b) for (n=8;n>0;n--)    // translates to   `dec + jnz`

Как Ира Бакстер уже выяснено, флаг Carry используется во множестве алгоритмов - не только арифметики с несколькими точками, но и для обработки растрового изображения в монохромном /cga/EGA эпохи: Это смещает 80 пикселов шириной один пиксель вправо...

        mov cx, 10
begin:  lodsb
        rcr al,1   // this is rotate though carry:
        stosb      // for the algorithm to work, carry must not be destroyed
        LOOP begin //

Но тогда: почему паритет?

Я считаю, что ответ - почему нет. Этот набор инструкций - с конца 70-х, когда транзисторов было мало. Отказ в вычислении флага четности для какой-либо конкретной инструкции не имел бы никакого смысла, а просто добавил к сложности CPU.

Ответ 3

Потому что нет необходимости влиять. Этого достаточно, чтобы проверить флаг Zero. Таким образом, после инструкций inc и dec флаг переноса остается неизменным, и в некоторых случаях это полезно.