Assembly: Increment by 2 (or larger number) without destroying CF in an ADC loop?

2.3k Views Asked by At

I am trying to test an addition function in TDM-GCC 64 bit assembly in Windows. I searched for resources on this a while back and I came across a code similar to this(I made some changes to compile this in 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)
    ...     ...

This first assembly code works. The downside is even for small numbers it would take just as long as calculating the largest size. So instead I made it check the size of X and Y and put a loop with sized condition so that it won't always have to add the whole array if X and Y are not big.

    ...
// %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:
    ...

But I was too simple to think that adding 8 bytes to X and Y's address (%r13, %r14) using ADDQ operator would make it possible to iterate through the array. The problem here is that if I use ADDQ operator like this, it resets carry flag to 0, so the entire loop which calculates addition with carry (.add3) breaks down. I tried using

    incq %r13

thinking incq would work similarly to incrementing a pointer in C++ which knows by how many bytes it should move. But this only increment register values by 1, not 8 which I thought it would move by.


So my question is: Is there a way in assembly to increment a register by number larger than 1, or do addition without touching the Carry Flag at all? (Not add, adc because both of them set the carry flag at the end)

1

There are 1 best solutions below

0
rcgldr On BEST ANSWER

Use load effective address with register + offset

        lea     rax,[rax+8]    ;add 8 to rax