Сборка: Увеличение на 2 (или большее число) без разрушения CF в контуре АЦП?
Я пытаюсь проверить функцию добавления в 64-битной сборке TDM-GCC в Windows. Некоторое время назад я искал ресурсы и наткнулся на код, похожий на этот (я внес некоторые изменения, чтобы скомпилировать его в TDM-GCC).
typedef struct
{
int size;
__uint64_t uints[130];
} BigInteger;
void add(BigInteger *X, BigInteger *Y); // X += Y
// %rcx holds address of X, and %rdx holds address of Y apparently.
// calc.s - assembly file
.globl add
add:
movq 8(%rdx), %rax
addq %rax, 8(%rcx)
movq 16(%rdx), %rax
adcq %rax, 16(%rcx)
movq 24(%rdx), %rax
adcq %rax, 24(%rcx)
... ...
Этот первый код сборки работает. Недостатком является то, что даже для небольших чисел это займет столько же времени, сколько и для расчета наибольшего размера. Поэтому вместо этого я проверил размер X и Y и поместил цикл с условием размера, чтобы не всегда приходилось добавлять весь массив, если X и Y не большие.
...
// %r13 holds X addr, %r14 holds Y addr.
addq $8, %r13 // I have tried incq %r13
addq $8, %r14 // I have tried incq %r14
movq (%r14), %rax
addq %rax, (%r13)
decl %ecx
cmpl $0, %ecx
je .add4
.add3:
addq $8, %r13 // I have tried incq %r13
addq $8, %r14 // I have tried incq %r14
movq (%r14), %rax
adcq %rax, (%r13)
loop .add3
.add4:
...
Но я был слишком прост, чтобы думать, что добавление 8 байтов к адресам X и Y (%r13, %r14) с помощью оператора ADDQ позволило бы выполнить итерацию по массиву. Проблема здесь в том, что если я использую оператор ADDQ, подобный этому, он сбрасывает флаг переноса в 0, поэтому весь цикл, который вычисляет сложение с переносом (.add3), прерывается. Я пытался с помощью
incq %r13
мышление incq будет работать аналогично увеличению указателя в C++, который знает, на сколько байтов он должен перемещаться. Но это только увеличивает регистр значений на 1, а не на 8, что я думал, что будет двигаться.
Итак, мой вопрос: есть ли в сборке способ увеличить регистр на число больше 1 или сделать добавление, не касаясь флага переноса вообще? (Не добавить, adc, потому что они оба установили флаг переноса в конце)
1 ответ
Использовать эффективный адрес загрузки с регистром + смещение
lea rax,[rax+8] ;add 8 to rax