2013-04-03 11 views
4

Мне нужно добавить содержимое CH в EAX в сборку x86, но нет режима адреса, который, как представляется, поддерживает это. В идеале я хотел бы в режим адресации, как:Как вы добавляете CH в EAX в сборку x86?

ADD EAX,r8 

или

ADD r32,r8 

или

ADD r/m32,r8 

Но ADD не имеет какой-либо из этих режимов. Я не могу замаскировать ECX, потому что в нем есть другой нежелательный контент, который я использую в другом месте, и я использовал все мои другие регистры, поэтому мой единственный вариант заключается в использовании доступа к памяти. Любые идеи, как я могу решить эту проблему?

Примечание. Я не могу использовать такой режим, как r/m8,r8, потому что тогда не будет переноса.

+3

Пора идти на x64 и получить эти дополнительные регистры. :) –

+0

[Опуская указатель кадра] (http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Optimize-Options.html) помогает освободить еще один регистр, ускоряет выполнение функций и создает меньший код с торговлей для более сложной отладки. Но в любом случае лучше перейти на 64-битный –

ответ

3

x86 просто не имеет таких гибких режимов адресации, как вы это заметили. Вы не можете добавить 8-битный регистр в 32-разрядный регистр за один шаг. Ваши варианты: либо высвободить регистр, либо добавить нуль/знак, а затем добавить r32, r32 или добавить r8, r8, а затем развернуть флаг переноса, чтобы настроить результат.

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

2

Используйте такой режим, как r/m8, r8, и при необходимости переносите перенос, добавляя постоянный 0x100 в EAX.

2

Если вы пролили регистр, вы можете избежать разветвления. например,

subl $4, %esp 

использовать последовательность инструкций:

movl %eax, (%esp) 
... 
movzbl %ch, %eax 
... 
addl (%esp), %eax 

и восстановить указатель стека в конце:

addl $4, %esp 

Это может сыграть злую шутку с любыми попытками отладки кода в этом блок, если это проблема.


Или, следуя предложению Дуг Карри:

addb %ch, %al 
jnc done 
addl 0x100, %eax 
done: 
+0

Разве код не указан так же, как «push eax» (за ним следует «pop eax» в конце)? – selbie

+0

Да - но я не знаю, требуется ли это в цикле или нет, поэтому я думал, что сделаю это явным. –

0

Вы можете также добавить 32-битные значения и отменить добавление 24 MSB: S:

add eax, ecx 
xor cl,cl   // also `and ecx, 0xffffff00` is possible 
sub eax, ecx 

Это естественно уничтожает добавленное значение, но сохраняет мусор. (И перечитывая вопрос, на самом деле необходимо окружить блок кода xchg cl,ch, что делает решение неоптимальным для задачи.)

1

перефразируя ответ Дуга (в синтаксисе Intel):

add al, ch 
    jnc no_carry 
    add eax, 100h 
no_carry: 
1

Это просто, для EAX:

add al,ch 
adc ah,0 
rorx eax,16 
adc ax,0 
rorx eax,16 

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

add al,ch 
adc ah,0 
bswap eax 
xchg al,ah 
adc ax 
xchg al,ah 
bswap eax 
+0

работает только на haspwell (макрос для короткого вращения без версии переноса, занимает 1 цикл) ... Другие варианты: bswap, xchg – Programmer

+0

Непрямые прыжки могут иметь большее наказание, чем большее количество инструкций, поэтому имеет смысл использовать дополнительные инструкции – Programmer