Самый эффективный способ установить регистр в 1 или (-1) - PullRequest
19 голосов
/ 13 мая 2010

Я сейчас учусь на ассемблере, и парень, который проверяет наши домашние задания, является очень педантичным уродцем старой школы. Например, он вычитает 10%, если видит:

mov ax, 0

вместо:

xor ax,ax

, даже если он используется только один раз.

Я не новичок в программировании на ассемблере, но я не эксперт по оптимизации, поэтому мне нужна ваша помощь в чем-то (это может быть очень глупый вопрос, но я все равно задам его) если мне нужно установить значение регистра в 1 или (-1), лучше использовать:

mov ax, 1

или сделайте что-то вроде:

xor ax,ax
inc ax

Мне действительно нужна хорошая оценка, поэтому я стараюсь максимально ее оптимизировать. (Мне нужно оптимизировать как время, так и размер кода)

Ответы [ 4 ]

10 голосов
/ 13 мая 2010

Быстрый Google для 8086 instructions timings size обнаружил http://8086.tk/, который, кажется, имеет все время и размеры для 8086 (и более) наборов инструкций.

Без сомнения, вы можете найти официальный документ Intel в Интернете с аналогичной информацией.

По вашему конкретному вопросу:

xor ax,ax
inc ax

занимает 3 + 3 = 6 тактов и 2 + 1 = 3 байта, тогда как

mov ax,1

занимает 4 такта и 3 байта.

Так что последнее лучше в этом случае.


Но вам нужно поговорить с вашим учебным заведением об этом парне. 10% за такую ​​простую вещь не верят.

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

Затем, когда они признали, что существуют разные способы кодирования, в зависимости от того, чего вы пытаетесь достичь, скажите им, что вы пытаетесь достичь читабельности и удобства обслуживания и серьезно не можете сделать скачок. о потерянном цикле или байте здесь или там * a .

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

Что бы это ни стоило, sub ax,ax, кажется, находится на одном уровне с xor ax,ax в плане тактов и байтов, так что, возможно, вы могли бы добавить это в микс в следующий раз, чтобы заставить его еще немного поработать.

* a) Нет, на самом деле нет, но время от времени бывает интересно выпустить: -)

3 голосов
/ 30 июня 2010

Вам лучше с

mov AX, 1

на 8086. Если вы отслеживаете содержимое реестра, вы можете добиться большего успеха, если знаете, что, например, BX уже содержит 1:

mov AX, BX

или если вы знаете, что AH равен 0:

mov AL, 1

и т.д.

2 голосов
/ 13 мая 2010

В зависимости от ваших обстоятельств, вы можете сойти с рук ...

 sbb ax, ax

Результатом будет либо 0, если флаг переноса не установлен, либо -1, если флаг переноса установлен.

Однако, если приведенный выше пример не подходит для вашей ситуации, я бы порекомендовал

xor  ax, ax
inc  ax

метод. Это должно удовлетворить вашего профессора по размеру. Однако, если в вашем процессоре используется какая-либо конвейерная разметка, я ожидаю, что между этими двумя инструкциями будет некоторая задержка, связанная с соединением (я вполне могу ошибаться) Если такая связь существует, скорость можно немного улучшить, изменив порядок инструкций, чтобы между ними была другая инструкция (та, которая не использует топор).

Надеюсь, это поможет.

0 голосов
/ 13 мая 2010

Я бы использовал mov [e]ax, 1 при любых обстоятельствах. Его кодировка не длиннее, чем хакерская последовательность xor, и я уверен, что она быстрее где угодно. 8086 достаточно странно, чтобы быть исключением, и поскольку эта штука такая медленная, микрооптимизация, подобная этой, будет иметь наибольшее значение. Но в любом другом месте: выполнение 2 «простых» инструкций всегда будет медленнее, чем выполнение 1, особенно если учесть опасность данных и длинные конвейеры. Вы пытаетесь прочитать регистр в следующей инструкции после того, как измените ее, поэтому если ваш ЦП не может обойти результат от этапа N конвейера (где выполняется xor) до этапа N-1 (где inc пытается загрузить регистр, не говоря уже о добавлении 1 к его значению), у вас будут киоски.

Другие факторы, которые следует учитывать: ширина полосы выборки команд (спорный для 16-битного кода, оба по 3 байта); mov избегает изменения флагов (более вероятно, будет полезно, чем заставлять их все обнулять); в зависимости от того, какие значения могут содержать другие регистры, вы, возможно, можете сделать lea ax,[bx+1] (также 3 байта, даже в 32-битном коде, без влияния на флаги); как говорили другие, sbb ax,ax тоже может работать при определенных обстоятельствах - он также короче на 2 байта.

Когда вы сталкиваетесь с такого рода микрооптимизациями, вам действительно следует измерить альтернативы, а не слепо полагаться даже на руководства по процессорам.

P.S. Новое домашнее задание: xor bx,bx быстрее xor bx,cx (на любом процессоре)?

...