内联 asm 到 x64 - 理解

Posted

技术标签:

【中文标题】内联 asm 到 x64 - 理解【英文标题】:inline asm to x64 - understanding 【发布时间】:2016-01-15 19:42:50 【问题描述】:

需要一些帮助来理解这个内联 asm 的作用 (c++),以便我可以正确转换它,以便我可以为 x64 编译。 Visual Studio 和 x64 无法使用内联汇编。我的研究告诉我,我应该使用 intrinics 或将内联 asm 放入 asm 文件并将该 asm 文件放入我的项目中。

如你所知,我真的不知道我在说什么,但你应该明白一般的想法。

我真的很想了解如何让这个内联汇编在 x86 或 x64 编译代码中工作。如果我能理解这是在做什么,那么也许我可以转换为 C++。或将此内联 asm 移动到 asm 文件。我有点知道如何移动到一个单独的文件。移动到 asm 文件的问题是我不确定如何设置我的 asm 函数来接受我需要传递给它的参数。我想要一个简单的答案,有人只是为我做这件事,但我需要的是一个解释,以便我将来可以自己做。我有两个内联 asm 块,这似乎是两者中更容易的一个。

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:下面的评论表明它没有正确编写。

【问题讨论】:

这是不建议 x86 使用内联汇编且 x64 或 ARM 不支持内联汇编的原因之一。编写此代码是为了针对某些可能比 C++ 更快的古老平台进行优化。 你能建议一种方法来完成同样的事情,但使用 c++ 吗? 我怀疑这个组件的第二个块对于任何平台来说都是最佳的,而且它根本不清楚是否有任何有用的东西。您需要弄清楚它应该做什么以及它是否真的有用,完全重写它以根据需要使用原子操作。 【参考方案1】:

对于初学者来说,代码是错误的。鉴于inc 没有修改进位标志,下面的adc 将使用它的初始零值,因此它永远不会进位到第二个双字。

也就是说,如果你想自己转换这段代码,你当然需要一个指令集引用来查看每条指令的作用。在这种情况下,显然它想增加一个 128 位的数字。

【讨论】:

如何修改此代码以按照您建议的方式实际工作?我能够将其与内联文件分离为 asm 文件,但我的 x64 重写并不顺利。我稍后会发布! 您应该使用add dword ptr [edi+ 0], 1 而不是inc dword ptr [edi+ 0],您可以删除clc。独立的 64 位版本只有 3 条指令:add qword ptr [rcx], 1; adc qword ptr [rcx+8], 0; ret .code BlockIncrement PROC, var1:QWORD mov rdi,var1 add qword ptr [rcx],1 adc qword ptr [rcx+8],0 ret BlockIncrement ENDP END【参考方案2】:

这个

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

LOOP0_PREHEAD:
inc ecx
LOOP0_HEAD:
dec sharedValue
loop LOOP0_HEAD

看起来像

// 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);

【讨论】:

由于代码看起来像是在对访问同一内存位置的多个线程(sharedValue)进行某种测试/验证,我相信原始 asm 的目的是确保内存访问不会重新排序、延迟或优化。在 MSVC++ 中,通过 volatile 引用访问 sharedValue 可能会给出类似的结果。他们也可能希望确保sharedValue 使用decinc 更新,它们提供了一些原子性。使用 C 运算符可能不会在机器级别映射到 inc/dec @MichaelBurr 如果std::atomic 可用,std::atomic&lt;int64_t&gt; sharedValue; 然后sharedValue.fetch_sub(1); 可能更可取? 当然 - 我应该想到提一下。 是的,最后一位 inline 正在测试多个线程。我不知道它到底是怎么做的,因为我根本不懂 asm。内联代码在使用线程进行某种验证的代码中。你的描述听起来很可能。 我可以删除这个内联并替换为 do while?

以上是关于内联 asm 到 x64 - 理解的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2008 内联汇编 关键字__asm出错

如何理解 Visual C++ 中的 _asm 命令

x86平台转x64平台关于内联汇编不再支持的解决

帮助理解 x86 内联汇编中的 DIV 指令

VS的 X64下的汇编编译

如何将 x86 和 x64 asm 文件包含到单个 Visual Studio 项目中?