【问题标题】:How to convert a inline assembly in a header file function to c++ function without assembly to support x64?如何将头文件函数中的内联程序集转换为不支持 x64 的程序集的 c++ 函数?
【发布时间】:2013-02-27 17:07:13
【问题描述】:

任何人都可以帮助将头文件中的以下内联程序集转换为相应的 x86-64 .asm 文件或 c 样式函数而不使用程序集吗?

extern const char hexlu[];
void _inline hextoascii(char* a_src , char* a_dest ) {
_asm {

              mov esi, a_src;
    mov edi, a_dest;
    sub ebx,ebx

    mov edx,[esi+00]
    mov bl,dl
    mov ax,word ptr [ebx*2+hexlu]
    mov [edi+00],ax
};
}

【问题讨论】:

  • 你想要 C 还是 C++ ?它们是不同的语言。

标签: c assembly x86 x86-64 inline-assembly


【解决方案1】:
void hextoascii(char* src, char* dest)
{
    dest[0] = hexlu[  2*(unsigned)src[0]];
    dest[1] = hexlu[1+2*(unsigned)src[0]];
}

【讨论】:

  • 没有像 ASM 版本那样检查边界 :)
  • 我的 ASM 生锈了,但在我看来它是一个 256 字节的查找表,因此只有一个引用。 (有人想知道将其设为 ASM 有什么意义。)
  • *(short*)dest = *(((short*)hexlu) + *src); 或附近。 (假设 short 是 16 位。)
  • @Hot_Licks 我认为是一个 512 字节的查找表(每个字节值 2 个字符)
  • @HotLicks - 我们都知道在汇编中编写代码会非常快。魔法!这就是为什么。
【解决方案2】:

首先,我建议简单地使用itoa(),例如:

static inline void hextoasacii(char *a_src, char *a_dest)
{
    (void)itoa(*a_src, a_dest, 16);
}

但这有一个缺点,a_dest 将成为 NULL- 终止,即它需要三个(而不是两个)字节的空间,所以这不是 100% 等效的。

显示的内联汇编代码在任何情况下都不是特别优化的内存访问; C/C++ 中的原始表单(但它当然取决于 255 条目大小的 hexlu[] 数组的确切内容,我假设它看起来像 char *hexlu[] = { "00", "01", "02", ... };)将是:

static inline void hextoascii(char *a_src, char *a_dest)
{
    static const char hexdigits[16] = "0123456789abcdef";
    int src = *a_src;
    a_dest[0] = hexdigits[src >> 4];
    a_dest[1] = hexdigits[src & 15];

    // make this:
    // *(unsigned short*)a_dest =
    //     ((unsigned short)hexdigits[src & 15]) << 8 |
    //     (unsigned short)hexdigits[src >> 4]
    //
    // if it absolutely _must_ be a single store
}

旁注:

如果您真的想采用汇编方式进行二进制/十六进制转换,可以使用 SSSE3 (pshufb) 对 16 字符表查找进行上述编码。这样一来,sprintf("%llx", tgt_string, val_uint64) 的等效操作基本上可以在单个 pshufb 指令中完成。

如何做到这一点的例子和它是如何工作的解释可以在这里找到:

SSSE3 解决方案,用于逐字节处理,不会像一次性转换多个字节那样提供如此大的加速,因为只会使用 XMM 寄存器的 1/8;您的函数不能(有效地)转换为按原样使用 SSSE3。如果您在循环中调用它(打印内存区域的 hexdump),那么使用像 Wojciech 的示例代码这样的函数将提供非常显着的加速。

【讨论】:

    【解决方案3】:

    我认为您只需要将 32 位指针转换为 64 位指针即可。

    extern const char hexlu[];
    void _inline hextoascii(char* a_src , char* a_dest ) {
    _asm {
        mov rsi, a_src;
        mov rdi, a_dest;
        sub rbx, rbx;
    
        mov rdx, [rsi];
        mov bl, dl;
        mov ax, [2*rbx+hexlu];
        mov [rdi], ax;
    };
    }
    

    【讨论】:

    • 在我的情况下更改为 64 位寄存器对我没有帮助,但无论如何谢谢。
    猜你喜欢
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-23
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    相关资源
    最近更新 更多