Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gcc如何知道内联汇编中要使用的寄存器大小?_Gcc_Assembly_X86_Inline Assembly - Fatal编程技术网

gcc如何知道内联汇编中要使用的寄存器大小?

gcc如何知道内联汇编中要使用的寄存器大小?,gcc,assembly,x86,inline-assembly,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工具链): 问题是0x173小于0xffff,为什么gcc不使用“mov cx,0x173”?gcc是否会分析以下指令“rdmsr”?gcc是否总是知道正确的寄存器大小?

我有内联汇编代码:

#define read_msr(index, buf)    asm volatile ("rdmsr" : "=d"(buf[1]), "=a"(buf[0]) : "c"(index))
使用此宏的代码:

u32 buf[2];

read_msr(0x173, buf);
我发现拆解是(使用gnu工具链):


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

英特尔将RDMSR指令指定为使用(全部)ECX来确定特定型号的寄存器。在这种情况下,显然正如宏指定的那样,GCC完全有理由将常量加载到完整的ECX中

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


(您没有问为什么它使用EAX来低效率地分期加载ECX;我不知道答案)。

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

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

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

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

所以“c”指的是“ecx”寄存器,但根据访问的大小,可以使用“ecx”、“cx”或“cl”来访问它,我认为这是有意义的

要进行测试,您可以尝试传递(无符号短)0x173,它应该更改代码


没有对内联程序集的分析(事实上,它是在文本替换直接复制到输出程序集之后,包括语法错误)。此外,也没有默认的寄存器大小,这取决于您的目标是32位还是64位。这将是一种限制。

我认为这是由于
0x173
的类型是
int
,因此
gcc
使用32位
mov
指令
mov-cx,0x173
不会将
ecx
设置为0x173。上面的16位将包含早期计算中留下的任何值。@RaymondChen:我知道你说的。我想知道为什么gcc知道必须使用“ecx”。@RaymondChen我认为问题是gcc如何知道“c”约束是指
ecx
,而不是
cx
rcx
。如果我是正确的,那么您的编辑会更改其含义。GCC不能以这种方式工作。唯一决定分配哪个寄存器的是约束和类型的大小。GCC不分析指令本身。即使它愿意也不行,因为可能有多条指令。如前所述,他的宏在ECX上建立了约束。如果GCC确实知道RDMSR的注册要求(它可能不知道,我不是GCC专家),那么如果OP以某种方式指定了CX,RDMSR代码生成器会反对它没有获得完整值。如果您承认您不知道GCC是否以这种方式运行,为什么要在您的答案中写下它是这样的?正如我所说,GCC不可能以这种方式运行,因为在内联程序集中,
rdmsr
之前可能有其他指令,包括可能的分支指令,并且知道哪个指令是使用
ecx
的指令与解决停止问题一样困难。如果只分配了
cx
,代码生成器不会像您所说的那样给出错误:它只会使用高阶位的先前内容。它的clear OP对于设置CX以实现RDMSR的目的感到困惑。很明显,他指定了“C”寄存器来设置该值。我不知道GCC代码生成器对指令的具体作用,但它非常复杂,我可以想象(可能是错误的)它理解每条指令的输入和输出要求。虽然它可能无法确定一位自定义汇编代码是否正确设置了寄存器,但它有可能确定寄存器ECX是否未设置,因此如果仅设置了CX,它可能会抱怨。否,C中的
0x173
具有type
int
,这是x86-64系统V ABI中的32位类型。这就是它为
“c”(0x173)
选择32位寄存器的原因。
int
与默认操作数大小相同并不是巧合,但它们是不同的。(例如,
gcc-m16
targeting 16位模式仍然使用32位int和指针,尽管这要求汇编程序在大多数指令上使用操作数大小和地址大小前缀。而在非x86指令上,例如AVR,
int
需要2个寄存器。)
mov    eax,0x173
mov    ecx,eax
rdmsr  
mov    DWORD PTR [rbp-0xc],edx
mov    DWORD PTR [rbp-0x10],eax