【发布时间】:2020-06-02 01:36:58
【问题描述】:
我正在尝试处理 c 的内联 asm 中的字符串。我能够理解 strcpy 的工作原理(如下所示):
static inline char *strcpy(char *dest, char *src)
{
int d0, d1, d2;
char temp;
asm volatile(
"loop: lodsb;" /* load value pointed to by %si into %al, increment %si */
" stosb;" /* move %al to address pointed to by %di, increment %di */
" testb %%al, %%al;"
" jne loop;"
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
: "0" (src), "1" (dest)
: "memory"
);
}
我正在尝试使用此结构来制作它,以便在返回字符串之前修改字符串的各个字符。结果,我正在尝试看起来像这样的东西:
static inline char *strcpy(char *dest, char *src)
{
int d0, d1, d2;
char temp;
asm volatile(
"loop: lodsb;" /* load value pointed to by %si into %al, increment %si */
" mov %2, %3;" /* move al into temp */
/*
*
* Do and comparisons and jumps based off how I want to change the characters
*
*/
" stosb;" /* move %al to address pointed to by %di, increment %di */
" testb %%al, %%al;"
" jne loop;"
: "=&S" (d0), "=&D" (d1), "=&a" (d2), "+r" (temp)
: "0" (src), "1" (dest)
: "memory"
);
}
我基本上是将lodsb 指令放入%al 的字节移动到一个临时变量中,之后我将在其中进行任何处理。但是,由于某种我无法弄清楚的原因,该字符似乎从未实际存储在 temp 中。
【问题讨论】:
-
顺便说一句,
strcpy的第一个版本看起来安全且正确,很好。您可以使用"+S"(src)进行简化,因为您位于包装函数内部(因此可以修改此函数的本地src),但具有匹配约束的虚拟输出是在您想要销毁的寄存器中获取输入的规范方式。当然,在循环中使用 lodsb/stosb 并不是特别有效,尤其是在不将 AL 与 RAX 分开重命名的 CPU 上,因此每个负载也需要一个 ALU uop 来合并到 RAX。但是一次一个字节比你用 SSE2 做的要糟糕得多,所以让我们忽略性能。
标签: c gcc assembly x86 inline-assembly