Добавление байта (из памяти) в регистр AX (MASM)

В настоящее время я пытаюсь выяснить, как добавить первый байт в памяти, на который указывает регистр указателя SI, к текущему содержимому регистра ax.

Поэтому, если SI содержит какой-то адрес, а значения в памяти - 00 01 по этому адресу, я хочу добавить только 00 в регистр ax.

Первой инструкцией, которую попробовал я сам по сборке, была add ax, byte ptr [SI] но, конечно, без кубиков, так как я пытаюсь добавлять операнды разного размера.

Мой текущий обходной путь

      mov dx,0000h             ;empty the contents of dx
mov dl,byte ptr [si]     ;get the value of the first byte in a register
add ax,dx                ;perform the originally desired addition

Но это невероятно расточительно и сильно сказывается на моем количестве выполненных инструкций (это часть подпрограммы, которая выполняется много раз).

Я ограничен набором инструкций 8086, поэтому этот вопрос / ответ Питера Кордеса, который предлагает movzx сжатие моих первых двух строк, к сожалению, нежизнеспособно.

Помощь приветствуется.

1 ответ

Как вы говорите, если вы можете предположить, что процессор, совместимый с 386, хорошим вариантом (особенно для современных процессоров) является movzx dx, byte [mem] / add ax,dx. Если нет, я думаю, мы можем притвориться, что настраиваемся на настоящий 8086, где размер кода в байтах часто более важен, чем количество команд . (Особенно на 8088 с его 8-битной шиной). Итак, вы определенно хотите использовать xor dx,dx до нуля DX (2 байта вместо 3 для mov reg, imm16), если вы не можете полностью избежать инструкции обнуления.

Поднимите обнуление DX (или DH) из любого цикла, так что вы просто mov dl, [mem] / add ax, dx. Если функция выполняет это только один раз, вам может потребоваться (вручную) встроить функцию в сайты вызовов, которые вызывают ее в цикле, если она достаточно мала для того, чтобы это имело смысл.

Как говорит Раймонд, вы можете выбрать любой другой регистр, старшая половина которого, как вы знаете, равна нулю в этой точке вашей функции. Возможно, вы могли бы вместо mov cl,4 если вам раньше понадобился CL=4 для чего-то еще, но вы закончили с CX к тому времени, когда вам нужно добавить в AX. mov cx, 4всего на 1 байт длиннее, поэтому вы получаете обнуление CH только с 1 дополнительным байтом размера кода. (против. xor cx,cx стоит 2 байта)


Другой вариант - байтовое добавление / adc , но он не идеален для размера кода. (Или производительность на более поздних процессорах)

        add al, [mem]      ; 2 bytes + extra depending on addr mode
  adc ah, 0          ; 3 bytes

Это на 1 байт больше, чем если бы у вас уже был запасной регистр с верхним нулем:

        mov  dl, [mem]     ; 2 bytes (+ optional displacement)
  add  ax, dx        ; 2 bytes

Но с другой стороны, add / adc вообще не нуждается в дополнительном регистре.


С указателем в SI стоит поискать способы воспользоваться преимуществами lodsbесли вы действительно оптимизируете размер кода. Что делает mov al, [si] / inc si (или вместо этого dec siесли DF=1). Итак, вы хотите добавить в другой регистр.

xchg ax, reg составляет всего 1 байт, но если вам нужно два свопа, он может не окупиться.

Другие вопросы по тегам