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)