我需要能够从我的C代码访问汇编寄存器。我有一个简单的方法将寄存器的值设置为变量的值,并将寄存器的值作为变量??希望这是有道理的......
答案 0 :(得分:3)
如果您使用的是VC(Microsoft的C编译器)
int regVal;
__asm {
mov [regVal], eax
}
这会加载eax
所持有的regVal
如果您正在使用GCC:
int regVal;
asm("movl %%eax, %0" : "=r"(regVal) :);
希望我说得对,我实际上并没有在GCC中进行内联汇编。
答案 1 :(得分:2)
如果您真的想在某些代码执行时知道寄存器的值,那么使用调试器会使很多更有意义。 (就像带有layout asm; layout reg
的gdb)。在没有看到asm代码的情况下查看寄存器值也没什么意义。
请参阅x86 wiki中的链接和指南。
但是,使用GNU inline asm,您可以执行类似
的操作int eax_snapshot;
asm volatile (
""
: "=a" (eax_snapshot)
// no inputs, no clobbers
);
// any amount of intervening code
printf("eax was %x\n", eax_snapshot); // print whatever eax had at the point where the inline asm appeared in program order
The a
constraint表示操作数必须使用%eax
寄存器。你的内联asm的主体然后变成no-op,因为你的输出操作数已经告诉编译器了。
无法保证gcc在asm块之前不会发出代码%eax
的代码。这就是为什么这样做没有多大意义。 volatile
告诉编译器不要相对于其他源指令重新排序asm语句,但优化仍然意味着早期的初始化被折叠到后来使用它们的代码中。或相反亦然。结合使用this和显式寄存器局部变量可能有助于避免gcc使用您选择的寄存器作为临时寄存器来计算其他东西。 (见下文)。
要设置寄存器,请使用带有"a"
约束的内联asm来强制该操作数的值位于%eax
(或%ebx
约束"b"
等,在内联asm出现的位置查看x86特定机器约束的文档。如果你想实际使用那个寄存器值,可以从内联asm语句中进行,否则寄存器可能被别的东西覆盖。
你也可以声明必须在特定寄存器中分配的变量,但我认为在没有初始化的情况下使用它们会使编译器不满意。 (代码转换通过检测未定义的行为,例如这可能会导致问题.IDK。)语法将是
register int eax asm ("eax"); // don't do this to read eax, it probably doesn't do what you think it would
The docs make it sound like using it for reading registers is not going to be a good idea.但是,为了设置寄存器值,这应该可以正常工作。 (只要寄存器分配器接受您的提示并将该变量保存在请求的寄存器中。)
不要这样做除非你有充分的理由。它对于正常编程非常不可能有用。正常的内联asm或调用函数是组合C和asm的更好方法。这只有在你想要在你的程序的内部状态下进行某种kludgy戳时才有用。
由于您没有给出用于此的原因的用例,我强烈建议您不要编写执行此操作的代码。这听起来很难看。
答案 2 :(得分:0)
由于您使用的是gcc,以下是在gcc中使用asm模板的文档:https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#AssemblerTemplate
要设置寄存器的值,请执行以下操作:
uint64_t rax = 0;
__asm__ __volatile__("mov %0, %%rax\n\t"
: /* no output */
: "a" (rax)
: "%rax");
为了读取寄存器的值,您需要执行以下操作:
uint64_t rax;
__asm__ __volatile__("mov %%rax, %0\n\t"
: "=a"(rax)
: /* no input */
: /* no clobbers */);