0

I just started learning assembly for a contest and I am using intel-syntax inline assembly.

Recentlly I've learned how to access global C variable's in assembly using <type> ptr[rip + <variable name>] syntax. (for example in the mov command)

I tried to do the same thing with arrays and by adding a + <n * size of one element> after the variable name, I can access the nth element of the C array.

But I decided to write a program that iterates over an array and calculate the sum.

Here is the code:

#include <stdio.h>

unsigned long long array[10];

int main()
{
    array[0] = 1;
    array[1] = 1;
    array[2] = 1;
    array[3] = 1;
    array[4] = 1;
    array[5] = 1;
    array[6] = 1;
    array[7] = 1;
    array[8] = 1;
    array[9] = 1;

    unsigned long long element_len = sizeof(*array);
    unsigned long long len = sizeof(array);

    unsigned long long sum = 0;
    
    asm(R"(
        .intel_syntax noprefix;
        
        mov rcx, 0;
        mov r8, 0;
        loop:
            add rcx, qword ptr[rip + array + r8];
            add r8, rax;

            cmp r8, rbx;
            jb loop;
        
        .att_syntax noprefix;
        )"
        
        : "=c" (sum)                    // outputs
        : "a" (element_len), "b" (len)  // inputs
        : "r8" // clobbers
        );
    
    printf("%llu\n", sum);
    
    return 0;
}

But because of that + r8; the compiler gives me this error (works fine when there is some constant value instead of r8)

$ gcc sum.c
sum.c: Assembler messages:
sum.c:61: Error: `qword ptr[rip+array+r8]' is not a valid base/index expression

I am using Kubuntu (technically Ubuntu) 20.04 on a 64-bit Intel processor and compiling the program using gcc 9.3.0.

EDIT: Fixed by @Jester's comment.

asm(R"(
        .intel_syntax noprefix;
        
        mov rcx, 0;
        mov r8, 0;
        lea rdx, [rip+array];
        loop:
            add rcx, [rdx+r8];
            add r8, rax;

            cmp r8, rbx;
            jb loop;
        
        .att_syntax noprefix;
        )"
        
        : "=c" (sum)                    // outputs
        : "a" (element_len), "b" (len)  // inputs
        : "r8" , "rdx"// clobbers
        );
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
OverShifted
  • 457
  • 1
  • 7
  • 17
  • 6
    As the assembler said, `[rip+array+r8]` is not a valid address. Consult a manual about what the accepted forms are. TL;DR: if you want `rip` relative, you can only have a displacement. You might do something like `lea rdx, [rip+array]` before the loop and then `add rcx, [rdx+r8]` – Jester Feb 03 '21 at 14:03
  • OT, `sizeof` is an operator, not a function. Use `sizeof *array` (or `sizeof array[0]`) and `sizeof array`. – the busybee Feb 03 '21 at 15:05
  • 1
    Another tip is that it is best to use [local labels](https://sourceware.org/binutils/docs-2.24/as/Symbol-Names.html) in inline asm. If the compiler inlines the function, unrolls a loop, etc, then your asm block may be repeated within the code, and then the label `loop` would be defined multiple times, which is an error. So you can replace `loop:` with `0:` and then `jb loop` with `jb 0b`. – Nate Eldredge Feb 03 '21 at 16:09
  • @NateEldredge I am completely new to assembly but is there any difference between `loop:` and `:`? – OverShifted Feb 03 '21 at 16:55
  • 1
    Yes there is, see the link I posted. Having the label `loop:` appear twice in the same asm source file is an error and the assembler will reject it, because when you say `jb loop` the assembler doesn't know which one you mean. But *local labels* like `0:` are special: you can have many of the same label in the same file, and when you write `jmp 0b` the assembler chooses the closest one that came before the `jmp`, which will always be what you want here. The `b` is for "back" (you can also write `jmp 0f` to jump to the closest `0` appearing after the `jmp`). – Nate Eldredge Feb 03 '21 at 17:02
  • Thanks! now I can understand it better. I only need assembly knowledge for that little contest and I probably won't continue with assembly. But thanks for the tip! – OverShifted Feb 03 '21 at 17:37

0 Answers0