2014-02-10 5 views
1

Мне нужно установить регистр DX на -5, но просто используя логические операторы (кроме NOT), операторы shift/rotate и NEG, никаких других инструкций не разрешено (без присвоения констант).Как я могу решить эту проблему на ассемблере?

+2

Какой процессор? По крайней мере, все вопросы относительно сборки должны быть по-настоящему понятны. – unwind

+2

_ «использование логических операторов» _ 'XOR DX, DX' /' OR DX, -5'. Там закончилось. – Michael

+0

@EricPostpischil Конечно, я тоже могу предположить, но не лучше ли, если вопрос хотя бы * несколько точным? – unwind

ответ

2

Это невозможно, если мы не берем на себя некоторый регистр содержит ненулевое значение. Доказательство:

Per Intel 64 и IA-32 Архитектура Software Developer Руководство, март 2013, логические инструкции (5.1.4) являются AND, OR, XOR и NOT, а также сдвиг и вращают инструкции (5.1. 5) являются SAR, SHR, SAL/SHL, SHRD, SHLD, ROR, ROL, RCR и RCL. По запросу проблемы NOT исключается, но включен NEG.

Проверка этих инструкций, за исключением NOT, показывает, что ни один из них не выдаст ненулевой результат в регистре или флаг переноса, если входные регистры и флаг переноса являются нулями.

Мы можем разумно предположить, что указатель стека не равен нулю в любом нормальном ABI. Это позволяет нам производить -5:

  • Если DX, как известно, не равен нулю, XOR он сам по себе устанавливает его в ноль.
  • Используйте ИЛИ, чтобы переместить указатель стека в другой регистр.
  • Применить NEG к новому регистру. Это устанавливает CF.
  • Применить RCL на DX (без явного значения сдвига, по умолчанию один бит). Это дает 1 в DX.
  • Применить NEG, SHL, ROL, ROL на DX. Это манипулирует битами для создания -5.
+0

У меня есть + 1'd, но я думаю, вам нужно очистить DX до вашего третьего шага; ОП не предоставил (в вопросе), что он был равен нулю при входе. Вы действительно можете 'ИЛИ'' SP' в новый регистр, но не 'IP'? – abligh

+0

@abligh: OP заявляет в комментарии, что DX изначально равен нулю. Если нет, XOR DX с собой, чтобы установить его на ноль. Указатель команд (EIP и IP) напрямую не доступен на IA-32. Intel 64 делает его доступным как RIP, но я решил, что вопрос о регистре DX не должен учитываться в функциях Intel 64. –

1

Я принимаю любой постоянный запрещен.

Как насчет (формат Intel):

XOR DX, DX  # DX=0 
STC    # DX=0, carry flag set 
RCL DX, DX  # DX=1 
ROL DX, DX  # DX=2 
STC    # DX=2, carry flag set 
RCL DX, DX  # DX=5 
NEG DX   # DX=-5 

Я не могу сразу думать изящный способ сделать это без STC. Вам нужно будет использовать некоторый оператор (кроме NOT), чтобы установить регистр на что-то отличное от 0 без использования каких-либо констант. Мой отвратительный путь будет что-то вроде (и мой 80x86 ржавый)

XOR AX, AX  # Now we know IP is not zero, i.e. at least one bit is 1 
XOR BX, BX 
OR AX, IP 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX 
ROL AX, AX 
OR BX, AX  # Now we know BX=0xFFFF, as the bit that was 1 has been put 
       # in each of the 16 bits 
XOR DX, DX  # DX=0 
RCL BX, BX  # DX=0, carry flag set 
RCL DX, DX  # DX=1 
ROL DX, DX  # DX=2 
RCL BX, BX  # DX=2, carry flag set 
RCL DX, DX  # DX=5 
NEG DX   # DX=-5 
+0

ИЛИ AX, IP не выходит, насколько я помню. –

+0

вы можете выполнить 'xor ax, ax' для сброса CF, затем' pushf', 'pop ax',' neg ax', 'push ax',' popf' и у вас есть CF = 1. Остальное легко , –

+0

Нет, вы не можете использовать 'pushf' и' popf', потому что он не говорит никаких других инструкций. – abligh

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