3

我正在尝试在 Windows 中测试 TDM-GCC 64 位程序集中的附加功能。不久前我搜索了这方面的资源,发现了一个类似的代码(我做了一些更改以在 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:
    ...

但是我太简单了,认为使用 ADDQ 运算符将 8 个字节添加到 X 和 Y 的地址 (%r13, %r14)就可以遍历数组。这里的问题是,如果我像这样使用 ADDQ 运算符,它将进位标志重置为 0,因此计算进位(.add3)加法的整个循环会中断。我尝试使用

    incq %r13

思考 incq 的工作方式类似于在 C++ 中增加一个指针,该指针知道它应该移动多少字节。但这只会将寄存器值增加 1,而不是我认为它会移动的 8。


所以我的问题是:在汇编中有没有办法将寄存器增加大于 1 的数字,或者在不触及进位标志的情况下进行加法?(不加,adc,因为他们都在最后设置了进位标志)

4

1 回答 1

6

使用带有寄存器+偏移量的加载有效地址

        lea     rax,[rax+8]    ;add 8 to rax
于 2018-10-15T11:53:06.477 回答