Флаг знака указывает на то, что результаты операции отрицательны.
Теперь, когда результат операции отрицателен, как я понимаю, установлен флаг знака. Но зачем это нужно. Потому что, если операция возвращает отрицательный результат, мы можем проверить это в целевом регистре, является ли значение отрицательным или положительным. Можно ли удалить этот регистр флага знака из ЦП и выполнить всю работу
Был бы x86 по-прежнему полностью программируемым, если бы у него не было Sign Flag (SF)?
Ответы (3)
Вам даже не нужны никакие флаги, потому что в x86 MOV уже завершен по Тьюрингу, и существует компилятор, который может скомпилировать код C в исполняемый файл только с MOV (или только с одним из XOR, SUB, ADD, XADD, ADC, SBB, AND/OR, PUSH/POP, 1-битные сдвиги или CMPXCHG/XCHG)
Если у вас есть побитовые операции, то знаковый бит можно легко получить с помощью AND
или сдвига вправо
Is it possible to remove this sign flag register from the CPU and get all work done
ответ да, а скорость зависит от того, сколько осталось инструкций и регистров
- person phuclv; 30.04.2021
Да, x86 по-прежнему будет полным по Тьюрингу без SF и даже достаточно эффективно программируемым. Сравнение целых чисел со знаком (кроме ==
/!=
) будет медленнее, но все же выполнимо. Таким образом, x86-без-SF по-прежнему намного эффективнее, чем хаки с вычислением одной инструкции, такие как использование только MOV (с большим количеством таблиц поиска и режимов адресации). Вы по-прежнему можете выполнять обычные операции сложения/вычитания/умножения с обычными инструкциями и просто эмулировать условия сравнения со знаком, включающие SF.
Например, вы можете эмулировать cmp eax, ecx/jl
, используя два временных регистра. jl
переходит, если SF != OF. (Возможно, есть более простые способы сделать эту эмуляцию, но это наиболее прямо демонстрирует, что вы можете получить MSB результата во флаг, отличный от SF, и, таким образом, можете эмулировать его в других случаях.)
; inputs: EAX and ECX
; clobbers: EDX and EAX
;;; jumps if EAX < ECX, like cmp eax,ecx / jl
mov edx, eax
sub edx, ecx ; sets OF, and would set SF it it existed
bt edx, 31 ; CF = MSB, other flags unmodified.
;; jump if CF != OF , like jl = SF!=OF in normal x86
pushf
pop eax
and eax, 0x0801 ; isolate CF and OF
or al, ah ; combine both into the low byte, setting FLAGS
jpo eax_lower ; jump if parity odd: CF != OF means only one bit is set
Обратите внимание, что PF, флаг четности, устанавливается только в соответствии с младшим байтом результата; только после И он может сказать вам только о CF, бит 0 EFLAGS. Это неудачное дизайнерское решение, что OF находится за пределами младшего байта FLAGS, иначе lahf мог бы заменить pushf/pop reg.
Это просто первая идея, которая пришла мне в голову, я уверен, что это можно было бы сделать более эффективно. (Но большая часть кода будет отдавать предпочтение числам без знака, поэтому сравнения могут быть полностью эффективными.)
Если вам нужно было избежать 386 BT для установки только CF, не испортив другие биты, вы, конечно, могли бы просто shr dx, 15
, чтобы опустить MSB вниз, или rol dx, 1
. (Но это пишет FLAGS, поэтому вы должны сделать это после pushf/pop reg, и, возможно, вы выберете свой сдвиг или количество циклов, чтобы выровнять его с OF.)
Я думаю, что некоторые 8-битные ISA не имели подписанных условий сравнения, и людям все же удавалось что-то с ними сделать. :П
Да, именно так работает MIPS. MIPS не имеет ни флагов, ни флага знака, ни флага переполнения, ни флага нуля и т. д. В нем есть инструкции, которые проверяют регистр на наличие нуля/не нуля, ‹= или › 0.