gpt4 book ai didi

linux - 在内联 GNU 汇编程序中获取字符串长度

转载 作者:太空狗 更新时间:2023-10-29 11:35:32 25 4
gpt4 key购买 nike

我正在重新学习我在非常老的 MS-DOS 机器上使用的汇编器!!!

这是我对该函数的理解。它编译但在尝试将 0xffffffff 放入 ecx 时因 SIGSEGV 而崩溃。

代码在具有 32 位 Debian 9 的虚拟机中运行。我们将不胜感激。

    int getStringLength(const char *pStr){

int len = 0;
char *Ptr = pStr;

__asm__ (
"movl %1, %%edi\n\t"
"xor %%al, %%al\n\t"
"movl 0xffffffff, %%ecx\n\t"
"repne scasb\n\t"
"subl %%ecx,%%eax\n\t"
"movl %%eax,%0"
:"=r" (len) /*Output*/
:"r"(len) /*Input*/
:"%eax" /*Clobbered register*/


);

return len;
}

最佳答案

使用 GCC 的内联汇编来学习汇编的问题在于,您花费了一半的时间来学习 gcc 的内联汇编是如何工作的,而不是实际学习汇编。例如,我可能会这样编写相同的代码:

#include <stdio.h>

int getStringLength(const char *pStr){

int len;

__asm__ (
"repne scasb\n\t"
"not %%ecx\n\t"
"dec %%ecx"
:"=c" (len), "+D"(pStr) /*Outputs*/
:"c"(-1), "a"(0) /*Inputs*/
/* tell the compiler we read the memory pointed to by pStr,
with a dummy input so we don't need a "memory" clobber */
, "m" (*(const struct {char a; char x[];} *) pStr)

);

return len;
}

查看编译器的 asm 输出 on the Godbolt compiler explorer .虚拟内存输入是棘手的部分:请参阅评论中的讨论和 on the gcc mailing list以最佳的方式做到这一点,这仍然是安全的。

将此与您的示例进行比较

  1. 我没有初始化 len,因为 asm 将其声明为输出 (=c)。
  2. 没有必要复制pStr,因为它是一个局部变量。根据规范,我们已经被允许更改它(虽然因为它是 const,我们不应该修改它指向的数据)。
  3. 没有理由告诉内联 asm 将 Ptr 放入 eax,而只是让您的 asm 将其移动到 edi。我只是首先将值放在 edi 中。请注意,由于 edi 中的值正在变化,我们不能将其声明为“输入”(根据规范,内联汇编不得更改输入的值)。将其更改为读/写输出可以解决此问题。
  4. 没有必要让 asm 为零 eax,因为您可以让约束为您做这件事。作为一个附带的好处,gcc 将“知道”它在 eax 寄存器中有 0,并且(在优化构建中)它可以重新使用它(想想:检查 2 个字符串的长度)。
  5. 我也可以使用约束来初始化 ecx。如前所述,不允许更改输入值。但是由于我将 ecx 定义为输出,gcc 已经知道我正在更改它。
  6. 由于 ecx、eax 和 edi 的内容都已明确指定,因此无需再破坏任何内容。

所有这些都有助于(稍微)更短和更高效的代码。

但这太荒谬了。到底怎么回事(我可以对 SO 说“见鬼”吗?)你应该知道所有这些吗?

如果目标是学习 asm,那么使用内联 asm 并不是最好的方法(事实上,我会说内联 asm 在大多数情况下是 bad idea)。我建议您将 getStringLength 声明为 extern 并将其完全用 asm 编写,然后将其与您的 C 代码链接。

通过这种方式,您可以了解参数传递、返回值、保留寄存器(以及了解必须保留哪些寄存器以及可以安全地用作临时寄存器)、堆栈帧、如何将 asm 与 C 链接等. 了解所有这些都比了解内联汇编的官方文章更有用。

关于linux - 在内联 GNU 汇编程序中获取字符串长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45649101/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com