Я пытаюсь протестировать функцию добавления в 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, илисделать дополнение, не касаясь Carry Flag вообще?(Не добавить, adc, потому что оба они устанавливают флаг переноса в конце)