On Friday, 5 June 2015 at 19:19:23 UTC, Kyoji Klyden wrote:
On Friday, 5 June 2015 at 18:30:53 UTC, Kagamin wrote:
Well, reading assembler is good enough:

void f(int[] a)
{
 a[0]=0;
 a[1]=1;
 a[2]=2;
}

Here pointer is passed in rsi register and length - in rdi:

void f(int[]):
        push    rax
        test    rdi, rdi
        je      .LBB0_4
        mov     dword ptr [rsi], 0
        cmp     rdi, 1
        jbe     .LBB0_5
        mov     dword ptr [rsi + 4], 1
        cmp     rdi, 2
        jbe     .LBB0_6
        mov     dword ptr [rsi + 8], 2
        pop     rax
        ret
.LBB0_4:
        mov     edi, 55
        mov     esi, .L.str
        mov     edx, 5
        call    _d_arraybounds
.LBB0_5:
        mov     edi, 55
        mov     esi, .L.str
        mov     edx, 6
        call    _d_arraybounds
.LBB0_6:
        mov     edi, 55
        mov     esi, .L.str
        mov     edx, 7
        call    _d_arraybounds

You play with assembler generated for D code at http://ldc.acomirei.ru/

Never said I was good at asm but I'll give it a shot...

So push rax to the top of the memory stack, test if rdi == rdi since yes jump to.LBB0_4, in LBB0_4 move the value 55 into edi, then move .L.str (whatever that is) into esi, then 5 into edx, then call _d_arraybounds (something from Druntime maybe?) then LBB0_4 has nothing left so go back, move the value 0 into a 32-bit pointer(to rsi register), if rdi == 1 jump to LBB0_5 (pretty much the same as LBB0_4), then move 1 into the pointer (which points to rsi[+ 4 bytes cuz it's an int]), so on and so forth until we pop rax from the memory stack and return.

How did I do? :P (hopefully at least B grade)

Almost correct :-) The part of "has nothing left, so go back" is wrong. The call to _d_arraybounds doesn't return, because it throws an Error.


I'm not really sure what .L.str or _d_arraybounds is, but I'm guessing it's the D runtime?

Yes, inside the `f` function, the compiler cannot know the length of the array during compilation. To keep you from accidentally accessing invalid memory (e.g. if the array has only two elements, but you're trying to access the third), it automatically inserts a check, and calls that runtime helper function to throw an Error if the check fails. .L.str is most likely the address of the error message or filename, and 55 is its length. The 5/6/7 values are the respective line numbers. You can disable this behaviour by compiling with `dmd -boundscheck=off`.


Also in the mov parts, is that moving 1 into the pointer or into the rsi register? And is rsi + 4, still in rsi, or does it move to a different register?

It stores the `1` into the memory pointed to by `rsi`, or `rsi+4` etc. This is what the brackets [...] mean. Because it's an array of ints, and ints are 4 bytes in size, [rsi] is the first element, [rsi+4] the second, and [rsi+8] the third. `rsi+4` is just a temporary value that is only used during the store, it's not saved into a (named) register. This is a peculiarity of the x86 processors; they allow quite complex address calculations for memory accesses.

Reply via email to