我需要能够从我的C代码访问汇编寄存器。我有一个简单的方法将寄存器的值设置为变量的值,并将寄存器的值作为变量??希望这有道理......
如果你使用VC(微软的C编译器)
int regVal;
__asm {
mov [regVal], eax
}
这将加载任何eax
持有regVal
如果您正在使用GCC:
int regVal;
asm("movl %%eax, %0" : "=r"(regVal) :);
希望我做对了,我实际上并没有在GCC中进行内联汇编。
如果您真的想在执行某些代码时知道寄存器的值,那么使用调试器会更有意义。 (就像gdb与layout asm; layout reg
一样)。在没有看到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的主体然后变成无操作,因为你的输出操作数已经告诉编译器了。
无法保证gcc在asm块之前不会发出代码来破坏%eax
。这就是为什么这样做没有多大意义。 volatile
告诉编译器不要相对于其他源指令重新排序asm语句,但优化仍然意味着早期的初始化被折叠到后来使用它们的代码中。或相反亦然。结合使用this和显式寄存器局部变量可能有助于避免gcc使用您选择的寄存器作为临时寄存器来计算其他东西。 (见下文)。
要设置寄存器,请使用带有"a"
约束的内联asm来强制该操作数的值在%eax
(或%ebx
约束的"b"
等,请参阅x86特定的机器约束的文档)在内联asm出现的位置。如果要实际使用该寄存器值,请从内联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戳时才有用。
既然你没有给出你想要这个的用例,我强烈建议你不要写代码来做这件事。这听起来很难看。
由于您使用的是gcc,因此以下是在gcc:https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#AssemblerTemplate中使用asm模板的文档
要设置寄存器的值,您可以执行以下操作:
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 */);