gpt4 book ai didi

c - 此汇编函数调用是否安全/完整?

转载 作者:太空狗 更新时间:2023-10-29 16:10:54 31 4
gpt4 key购买 nike

我没有组装经验,但这是我一直在做的。如果在通过程序集中的指针传递参数和调用函数时缺少任何基本方面,我希望输入。
例如,我想知道是否应该还原ecxedxesiedi 。我读到它们是通用寄存器,但我找不到它们是否需要恢复?打电话后我该做些什么清理工作吗?
这是我现在的代码,它确实有效:

#include "stdio.h"

void foo(int a, int b, int c, int d)
{
printf("values = %d and %d and %d and %d\r\n", a, b, c, d);
}

int main()
{

int a=3,b=6,c=9,d=12;
__asm__(
"mov %3, %%ecx;"
"mov %2, %%edx;"
"mov %1, %%esi;"
"mov %0, %%edi;"
"call %4;"
:
: "g"(a), "g"(b), "g"(c), "g"(d), "a"(foo)
);

}

最佳答案

最初的问题是Is this assembly function call safe/complete?。答案是:不。虽然在这个简单的例子中它似乎是有效的(特别是在优化被禁用的情况下),但是你违反了最终会导致失败的规则(那些很难找到的规则)。
我想解决(显而易见的)后续问题,即如何使其安全,但如果没有操作人员对实际意图的反馈,我不能真正做到这一点。
所以,我会尽我所能地利用我们所拥有的一切,试着描述那些使它变得不安全的事情,以及你能做的一些事情。
让我们从简化asm开始:

 __asm__(
"mov %0, %%edi;"
:
: "g"(a)
);

即使只有这一条语句,这段代码也已经不安全了。为什么?因为我们在不让编译器知道的情况下更改寄存器(EDI)的值。
编译器怎么可能不知道你在问?毕竟,它就在那里!答案来自 gcc docs中的这一行:
gcc不解析汇编程序指令本身,也不解析
知道它们的含义,甚至知道它们是否是有效的汇编程序输入。
在这种情况下,你如何让海合会知道发生了什么?答案在于使用约束(冒号后面的内容)来描述asm的影响。
也许修复此代码的最简单方法如下:
  __asm__(
"mov %0, %%edi;"
:
: "g"(a)
: edi
);

这会将edi添加到 clobber list中。简而言之,这告诉GCC,EDI的值将被代码更改,并且GCC不应该假设当ASM退出时将存在任何特定值。
现在,虽然这是最简单的,但未必是最好的方法。请考虑以下代码:
  __asm__(
""
:
: "D"(a)
);

它使用 machine constraint告诉gcc将变量 a的值放入edi寄存器中。这样做,gcc将在“方便”的时候为您加载寄存器,可能是通过始终将 a保存在edi中。
这段代码有一个(重要的)警告:通过将参数放在第二个冒号之后,我们将其声明为一个输入。输入参数需要是只读的(即它们在退出ASM时必须具有相同的值)。
在您的情况下, call语句意味着我们无法保证edi不会被更改,所以这不太管用。有几种方法可以解决这个问题。最简单的方法是在第一个冒号之后向上移动约束,使其成为一个输出,并指定 "+D"以指示该值是读+写的。但是,在asm之后, a的内容将几乎没有定义(printf可以将其设置为任意值)。如果破坏 a是不可接受的,总有这样的情况:
int junk;
__asm__ volatile (
""
: "=D" (junk)
: "0"(a)
);

这告诉gcc,在启动asm时,它应该将变量值 a放在与输出约束0(即edi)相同的位置。它还说,在输出时,edi将不再 a,它将包含变量 junk
编辑:由于“垃圾”变量实际上不会被使用,我们需要添加 volatile限定符。volatile在没有任何输出参数时是隐式的。
那条线上的另一点是:以分号结尾。这是合法的,将按预期工作。但是,如果您想使用 -S命令行选项来确切地查看生成了什么代码(如果您想很好地使用内联asm,您会发现这会产生难以读取的代码。我建议用 \n\t代替分号。
所有这些,我们仍然在第一条线上…
显然,这同样适用于其他两个 mov语句。
这就引出了 call语句。
michael和我都列出了在内联asm中调用很困难的一些原因。
处理所有可能被函数调用的abi破坏的寄存器。
处理红色区域。
处理对齐。
记忆冲击。
如果这里的目标是“学习”,那么请随意尝试。但我不知道在生产代码中这样做会不会让我感到舒服。即使看起来很管用,我也不会有信心,不会错过什么奇怪的案子。这与我通常关心的 using inline asm at all无关。
我知道,这是很多信息。作为gcc asm命令的介绍,可能比您期望的要多得多,但您已经选择了一个具有挑战性的起点。
如果您还没有这样做,请花时间查看gcc Assembly Language interface中的所有文档。这里有很多好的信息,还有一些例子来解释它是如何工作的。

关于c - 此汇编函数调用是否安全/完整?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37639993/

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