1

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

3 回答 3

1
void hextoascii(char* src, char* dest)
{
    dest[0] = hexlu[  2*(unsigned)src[0]];
    dest[1] = hexlu[1+2*(unsigned)src[0]];
}
于 2013-02-27T17:17:21.260 回答
1

首先,我建议简单地使用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 解决方案,用于逐字节进行,不会像一次性转换多个字节那样提供如此大的加速,因为只会使用 1/8 的XMM寄存器;您的函数不能(有效地)转换为按原样使用 SSSE3。如果您在循环中调用它(打印内存区域的十六进制转储),那么使用像 Wojciech 的示例代码这样的函数将提供非常显着的加速。

于 2013-02-27T17:46:05.533 回答
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;
};
}
于 2013-02-27T17:17:45.147 回答