Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Gcc 我该如何要求汇编程序“编辑”;请给我一个全尺寸的寄存器;?_Gcc_Assembly_X86 64_Inline Assembly - Fatal编程技术网

Gcc 我该如何要求汇编程序“编辑”;请给我一个全尺寸的寄存器;?

Gcc 我该如何要求汇编程序“编辑”;请给我一个全尺寸的寄存器;?,gcc,assembly,x86-64,inline-assembly,Gcc,Assembly,X86 64,Inline Assembly,我试图允许汇编程序给我一个它选择的寄存器,然后将该寄存器用于内联汇编。我正在使用下面的程序,以及它的seg故障。该程序是用g++-O1-g2-m64 wipe.cpp-o wipe.exe编译的 当我看到lldb下的崩溃时,我相信我得到的是32位寄存器而不是64位寄存器。我试图使用lea计算地址(基+偏移量),并将结果存储在汇编程序选择的寄存器中: "lea (%0, %1), %2\n" 在上面,我试图说“使用寄存器,我将它称为%2” 当我执行拆解时,我看到: 0x100000b29:

我试图允许汇编程序给我一个它选择的寄存器,然后将该寄存器用于内联汇编。我正在使用下面的程序,以及它的seg故障。该程序是用
g++-O1-g2-m64 wipe.cpp-o wipe.exe
编译的

当我看到lldb下的崩溃时,我相信我得到的是32位寄存器而不是64位寄存器。我试图使用
lea
计算地址(基+偏移量),并将结果存储在汇编程序选择的寄存器中:

"lea (%0, %1), %2\n"
在上面,我试图说“使用寄存器,我将它称为%2”

当我执行拆解时,我看到:

   0x100000b29:  leal   (%rbx,%rsi), %edi
-> 0x100000b2c:  movb   $0x0, (%edi)
因此,生成的代码似乎使用64位值(rbx和rsi)计算和寻址,但将其保存到32位寄存器(edi)(由汇编程序选择)中

以下是崩溃时的值:

(lldb) type format add --format hex register
(lldb) p $edi
(unsigned int) $3 = 1063330
(lldb) p $rbx
(unsigned long) $4 = 4296030616
(lldb) p $rsi
(unsigned long) $5 = 10
下面是关于输入操作数的简要说明。如果我删除
“r”(2)
,那么在调用
lea
内联asm字符串中的无效操作数时,当我引用
%2
时,就会出现编译器错误

我如何告诉汇编程序“给我一个完整大小的寄存器”,然后在我的程序中引用它



有趣的是,微软对volatile(大多数程序员所期望的——任何东西都可以改变内存,而不仅仅是内存映射硬件)使用了一种更为常见的解释,上面的代码是可以接受的。

gcc内联asm是一种复杂的野兽<代码>“r”(2)
表示分配一个
int
大小的寄存器,并用
2
值加载它。如果您只需要一个任意的暂存器寄存器,您可以声明一个64位的早期缓冲虚拟输出,例如输出部分中的
“=&r”(虚拟)
,前面声明了
void*dummy
。有关详细信息,请参阅


至于最后的代码片段,就像链接的电子邮件所说的,看起来你需要一个内存屏障。请参阅。

再次感谢@Jester。所以我很清楚:没有办法要求GCC给我一个它选择的完整大小的寄存器,然后在我的程序中使用它?(如果是这样的话,这是我第二次问错问题。太糟糕了,堆栈溢出不允许出现广泛的“我该怎么做…”问题。相反,我必须进入一个兔子洞,这会导致多个糟糕的问题)。我的回答在第一段中向您展示了如何做。您可以使用固定寄存器,但是我不知道有什么方法可以让编译器在不使用我的示例的情况下为您提供一个。但是你真的应该用记忆障碍来代替。谢谢Jester。“但是你真的应该使用内存屏障来代替…”-内存屏障不能解决优化器删除死代码的问题。这就是本练习的全部目的——“正确地”停止死代码删除。但我认为你是对的——最正确的说法是,需要一个内存屏障来确保在其他访问之前完成写操作(发布语义)?这里面什么都没有。
int main(int argc, char* argv[])
{
    string s("Hello world");
    cout << s << endl;

    char* ptr = &s[0];
    size_t size = s.length();

    if(ptr && size)
    {
        __asm__ __volatile__
        (
         "%=:\n"                /* generate a unique label for TOP */

         "subq $1, %1\n"        /* 0-based index */
         "lea (%0, %1), %2\n"   /* calcualte ptr[idx] */
         "movb $0, (%2)\n"      /* 0 -> ptr[size - 1] .. ptr[0] */
         "jnz %=b\n"            /* Back to TOP if non-zero */

         : /* no output */
         :  "r" (ptr), "r" (size), "r" (2)
         : "0", "1", "2", "cc"
         );
    }

    return 0;
}
volatile void* g_tame_the_optimizer = NULL;
...

unsigned char* ptr = ...
size_t size = ...;

for(size_t i = 0; i < size; i++)
   ptr[i] = 0x00;

g_tame_the_optimizer = ptr;