使用英特尔调试寄存器(GCC/内联程序集)的正确方法
我一直在尝试英特尔调试寄存器,但我似乎做了一些不正确的事情。我创建了一个非常简单的LinuxLKM,并尝试使用内联汇编来执行寄存器的简单操作。e、 g:使用英特尔调试寄存器(GCC/内联程序集)的正确方法,gcc,linux-kernel,x86,x86-64,Gcc,Linux Kernel,X86,X86 64,我一直在尝试英特尔调试寄存器,但我似乎做了一些不正确的事情。我创建了一个非常简单的LinuxLKM,并尝试使用内联汇编来执行寄存器的简单操作。e、 g: __asm__ ("movl %eax, %db0"); 我收到的错误消息表明我做了一些根本不正确的事情。e、 g: Error: unsupported for `mov' 有人知道如何使用这些寄存器吗 这是一个语法错误-gcc的内联汇编程序使用%作为操作数标识符,要在x86的寄存器名中显式使用它,您必须编写: __asm__ ("mo
__asm__ ("movl %eax, %db0");
我收到的错误消息表明我做了一些根本不正确的事情。e、 g:
Error: unsupported for `mov'
有人知道如何使用这些寄存器吗 这是一个语法错误-gcc的内联汇编程序使用
%
作为操作数标识符,要在x86的寄存器名中显式使用它,您必须编写:
__asm__ ("movl %%eax, %%db0\n\t");
那就可以编译了
更正:这里有多个问题:
\uuuu asm\uuuuu
语句中没有缓冲区是非常不寻常的(而且很少做您期望的事情,因为在汇编中很少有没有副作用的事情可以做)。尽管如此,如果且仅当指令实际上没有副作用且没有输入时,看起来有可能省略碰撞器列表。这样做的一个后果是不再需要转义
%
;这个简单示例中的编译器为\uuu asm\uuuu(“movl%eax,%db0\n\t”)创建相同的操作码代码>与完全指定的\uuuu asm\uuu(“movl%%eax,%%db0\n\t”:代码>。这不一定是一个优势,因为
(mov%0,%%db0\n\t):“a”((uintpttr)0):)代码>
在64位(gcc-m64…
)和32位(gcc-m32…
)上编译-它创建相同的指令,但在汇编中写入此指令时使用的寄存器对于64位是不同的:
208:0f 23 c0 mov%rax,%db0
在32位时,它会:
269:0f 23 c0 mov%eax,%db0
此处使用输入操作数提供了提取寄存器宽度的能力(uintpttr\u t
来自
,并保证始终为完整的通用寄存器宽度),因此相同的内联程序集可用于32位和64位编译
\uuuu asm\uuuu
的方式与“普通”这样的语句不同
在任何情况下,在修改调试寄存器时,实际上您肯定需要一个参数/clobber列表,因为对这些寄存器的访问是串行化指令,编译器应该将这些指令隐式地称为
内存
clobber。此外,你从他们那里读到的/写给他们的价值一定来自于某个地方。。。因此输入/输出。这是一个语法错误-gcc的内联汇编程序使用%
作为操作数标识符,要在x86的寄存器名中显式使用它,您必须编写:
__asm__ ("movl %%eax, %%db0\n\t");
那就可以编译了
更正:这里有多个问题:
\uuuu asm\uuuuu
语句中没有缓冲区是非常不寻常的(而且很少做您期望的事情,因为在汇编中很少有没有副作用的事情可以做)。尽管如此,如果且仅当指令实际上没有副作用且没有输入时,看起来有可能省略碰撞器列表。这样做的一个后果是不再需要转义
%
;这个简单示例中的编译器为\uuu asm\uuuu(“movl%eax,%db0\n\t”)创建相同的操作码代码>与完全指定的\uuuu asm\uuu(“movl%%eax,%%db0\n\t”:代码>。这不一定是一个优势,因为
(mov%0,%%db0\n\t):“a”((uintpttr)0):)代码>
在64位(gcc-m64…
)和32位(gcc-m32…
)上编译-它创建相同的指令,但在汇编中写入此指令时使用的寄存器对于64位是不同的:
208:0f 23 c0 mov%rax,%db0
在32位时,它会:
269:0f 23 c0 mov%eax,%db0
此处使用输入操作数提供了提取寄存器宽度的能力(uintpttr\u t
来自
,并保证始终为完整的通用寄存器宽度),因此相同的内联程序集可用于32位和64位编译
\uuuu asm\uuuu
的方式与“普通”这样的语句不同
在任何情况下,在修改调试寄存器时,实际上您肯定需要一个参数/clobber列表,因为对这些寄存器的访问是串行化指令,编译器应该将这些指令隐式地称为
内存
clobber。此外,你从他们那里读到的/写给他们的价值一定来自于某个地方。。。因此输入/输出。FrankH的答案在x64模式下不起作用。可能会用到的是:
inline void setDebugReg( long v )
{
__asm__ __volatile__ ("mov %0, %%db0\n\t" : : "r"(v) : ) ;
}
(db7需要一个类似的asm来设置监视点的标志)
但是,不能在用户空间中设置这些寄存器,因此需要其他方法。下面是使用ptrace执行此操作的示例代码,其中。FrankH的答案在x64模式下不起作用。可能会用到的是:
inline void setDebugReg( long v )
{
__asm__ __volatile__ ("mov %0, %%db0\n\t" : : "r"(v) : ) ;
}
(db7需要一个类似的asm来设置监视点的标志)
然而,设置这些寄存器不能在用户空间中完成,因此需要其他方法