任何人都可以帮助将头文件中的以下内联汇编转换为相应的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
};
}
答案 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
指令中完成。
如何执行此操作以及解释如何工作的示例可在此处找到:
pshufb
搜索BitRake的帖子)hexdump.c
);还建议阅读他关于使用类似的有趣技巧加快itoa(..., 10)
的文章 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;
};
}