JOg*_*den 1 x86 gcc x86-64 linux-kernel
我一直试图尝试英特尔调试寄存器,但我似乎做错了什么.我创建了一个非常简单的Linux LKM,并尝试使用内联汇编来执行寄存器的简单操作.例如:
__asm__ ("movl %eax, %db0");
Run Code Online (Sandbox Code Playgroud)
我得到的错误消息表明我做的事情从根本上是错误的.例如:
Error: unsupported for `mov'
Run Code Online (Sandbox Code Playgroud)
有没有人对如何使用这些寄存器有任何见解?
这是一个语法错误 - gcc的内联汇编程序%用作操作数标识符,并且要在x86的寄存器名称中明确使用它,您必须编写:
__asm__ ("movl %%eax, %%db0\n\t");
Run Code Online (Sandbox Code Playgroud)
这将使它编译.
更正:
这里有多个问题:
__asm__没有clobbers的陈述是非常不寻常的(并且很少做你期望的事情,因为在装配中可以做很少的事情没有副作用).尽管如此,当且仅当指令实际上既没有副作用且没有输入时,它看起来可以省略clobber列表.%是不再需要逃逸; 这个简单示例的编译器创建了与__asm__("movl %eax, %db0\n\t");完全指定的操作码相同的操作码__asm__("movl %%eax, %%db0\n\t":::);.这不一定是优势,因为......__asm__("mov %0, %%db0\n\t" : : "a"((uintptr_t)0) : );gcc -m64 ...)和32位(gcc -m32 ...)上编译- 它创建相同的指令,但在汇编时使用的寄存器对于64位是不同的:208: 0f 23 c0 mov %rax,%db0269: 0f 23 c0 mov %eax,%db0uintptr_t来自<inttypes.h>并保证始终是完整的通用寄存器宽度),因此相同的内联汇编可用于32位和64位编译.我承认我不知道编译器将clobber-list-less __asm__与"普通"这样的语句区别对待.
在任何情况下,在现实中,你会肯定修改调试寄存器时,需要一个参数/撞列表,因为访问这些序列化应该被隐式地知道编译器的指令memory撞.此外,你从他们那里读取/写给他们的价值必须来自/来自某个地方......因此输入/输出.