gcc如何知道在内联装配中使用的寄存器大小?

时间:2014-07-28 13:41:19

标签: gcc assembly x86 inline-assembly

我有内联汇编代码:

#define read_msr(index, buf)    asm volatile ("rdmsr" : "=d"(buf[1]), "=a"(buf[0]) : "c"(index))

使用此宏的代码:

u32 buf[2];

read_msr(0x173, buf);

我发现反汇编是(使用gnu工具链):

mov    eax,0x173
mov    ecx,eax
rdmsr  
mov    DWORD PTR [rbp-0xc],edx
mov    DWORD PTR [rbp-0x10],eax

问题是0x173小于0xffff,为什么gcc不使用" mov cx,0x173"?请问gcc会分析以下指令" rdmsr&#34 ;? gcc是否总能知道正确的寄存器大小?`re

3 个答案:

答案 0 :(得分:2)

取决于传递的值或变量的大小。

如果传递“short int”,它将设置“cx”并从“ax”和“dx”读取数据(如果buf也是短整数)。

对于char,它将访问“cl”等等。

所以“c”指的是“ecx”寄存器,但这可以通过“ecx”,“cx”或“cl”访问,具体取决于访问的大小,我认为这是有意义的。

要测试你可以尝试传递(unsigned short)0x173,它应该改变代码。

没有对内联汇编的分析(事实上它是在文本替换direclty复制到输出程序集之后,包括语法错误)。此外,没有默认寄存器大小,具体取决于您是否具有32位或64位目标。这将是限制的方式。

答案 1 :(得分:1)

我认为答案是因为当前的默认数据大小是32位。在64位长模式下,默认数据大小也是32位,除非使用“rex.w”前缀。

答案 2 :(得分:-1)

Intel将RDMSR指令指定为使用(全部)ECX来确定特定于模型的寄存器。既然如此,并且显然由您的宏指定,GCC完全有理由将您的常量加载到完整的ECX中。

所以关于它为什么不加载CX的问题似乎完全不合适。看起来GCC正在生成正确的代码。

(你没有问为什么它通过使用EAX来低效地分配ECX的负载;我不知道答案是什么。