Сборка: Увеличение на 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
Другие вопросы по тегам