Aaron Sulwer
Aaron Sulwer

Reputation: 1

inline asm to x64 - understanding

need some help understanding what this inline asm does (c++) so that I can properly convert it so that I can compile for x64. inline asm is not possible with Visual Studio and x64. my research tells me that I should use intrinics OR put the inline asm into an asm file and put that asm file in my project.

as you can I really do not know what I am talking about here but you should get the general idea.

I really would like to understand how to get this inline asm to work in either x86 or x64 compiled code. if i could understand what this is doing then maybe i could convert to c++. or move this inline asm to an asm file. i sort of know how to move to a separate file. the problem with moving to asm file is that i am not sure how to setup my asm function to accept the parameter i need to pass to it. i would like the easy answer where someone just does this for me BUT what i need is an explanation so that i can in the future i can do this on my own. i have two blocks of inline asm and this appears to be the easier of the two.

inline asm to asm file

// FIRST inline asm talked about above
// little endian
void BlockInc(unsigned char *data)
{
    #if DATA_BLOCK_SIZE==16
    __asm
    {
        mov edi,[data]
        add dword ptr [edi+0],1
        adc dword ptr [edi+4],0
        adc dword ptr [edi+8],0
        adc dword ptr [edi+12],0
    }
    #else
#error
    #endif
}

//this is the second more difficult inline asm not mentioned
void concThread(void *param)
{
    unsigned long threadN = *((unsigned long *)param);

    while(true)
    {
        unsigned long           index;

        // 1. synch
        WaitForSingleObject(concThread_semaphores1[threadN],INFINITE);
        ReleaseSemaphore(concThread_semaphores2[threadN],1,NULL);

        if(sharedStop)
        {
            _endthread();
        }

        // start "sharedValue" concurrent modify
        while(!sharedOkToGo);

        for(index=0;index<(CYCLE_NUM/128);index++)
        {
            LARGE_INTEGER   li;

            QueryPerformanceCounter(&li);

            if(threadN%2)
            {
                __asm
                {
                    movzx ecx,byte ptr [li]
                    jecxz LOOP0_PREHEAD
                    jmp LOOP0_HEAD

                    LOOP0_PREHEAD:
                    inc ecx
                    LOOP0_HEAD:
                    dec sharedValue
                    loop LOOP0_HEAD
                }
            }
            else
            {
                __asm
                {
                    movzx ecx,byte ptr [li]
                    jecxz LOOP1_PREHEAD
                    jmp LOOP1_HEAD

                    LOOP1_PREHEAD:
                    inc ecx
                    LOOP1_HEAD:
                    inc sharedValue
                    loop LOOP1_HEAD
                }
            }
        }

        ReleaseSemaphore(concThread_semaphores2[threadN],1,NULL);
    }
}

EDITED asm: comment below suggested it wasn't correctly written.

Upvotes: 0

Views: 1999

Answers (2)

Jester
Jester

Reputation: 58782

For starters, the code is wrong. Given that inc does not modify the carry flag, the following adc will use the initial zero value of it so it will never carry to the second dword.

That said, if you want to convert this code yourself, you will of course need an instruction set reference to see what each instruction does. In this case apparently it wants to increment a 128 bit number.

Upvotes: 3

J.J. Hakala
J.J. Hakala

Reputation: 6214

This

movzx ecx,byte ptr [li]
jecxz LOOP0_PREHEAD
jmp LOOP0_HEAD

LOOP0_PREHEAD:
inc ecx
LOOP0_HEAD:
dec sharedValue
loop LOOP0_HEAD

looks like

// ecx was used to hold a loop count
uint32_t i = li;
// do-while to guarantee execution at least once
// since LOOP0_PREHEAD incremented ecx if it was zero
do {
   sharedValue--;
   i--;
} while (i > 0);

Upvotes: 1

Related Questions