如何将头文件函数中的内联汇编转换为c ++函数而不进行汇编以支持x64?

时间:2013-02-27 17:07:13

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

任何人都可以帮助将头文件中的以下内联汇编转换为相应的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
};
}

3 个答案:

答案 0 :(得分:1)

void hextoascii(char* src, char* dest)
{
    dest[0] = hexlu[  2*(unsigned)src[0]];
    dest[1] = hexlu[1+2*(unsigned)src[0]];
}

答案 1 :(得分:1)

首先,我建议只使用itoa(),例如:

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

但是这样做的缺点是a_dest将成为NULL - 由此终止,即它需要三个(而不是两个)字节的空间,因此这不是100%等效。

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

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的示例代码这样的函数将提供非常显着的加速。

答案 2 :(得分:0)

我认为你只需要将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;
};
}