我试着用gcc和-masm=intel
选项编译一个非常简单的程序。但是出现了“错误:无效使用寄存器”。
// test.c
#include <stdio.h>
size_t offset;
int main(int argc, char **argv, char **envp)
{
offset = 20;
return 0;
}
字符串
结果:
$ gcc test.c -masm=intel
/tmp/ccPnqEmz.s: Assembler messages:
/tmp/ccPnqEmz.s:19: Error: invalid use of register
型
但是当我删除赋值语句时,它可以正常编译:
// test.c
#include <stdio.h>
size_t offset;
int main(int argc, char **argv, char **envp)
{
//offset = 20;
return 0;
}
型
结果:
$ gcc test.c -masm=intel
$
型
当我查看两者的汇编代码时,我只发现前者比后者多了一条存储指令,实现了offset = 20
赋值:
mov QWORD PTR offset[rip], 20
型
为什么GNU汇编程序会在GCC发出的这条指令上阻塞?
1条答案
按热度按时间ui7jx7zq1#
这是因为
offset
是Intel语法汇编中的关键字。Intel语法模式下的GNU汇编程序遵循微软汇编程序惯例,在汇编指令中提及空符号名会产生一个带有该符号地址的内存操作数,而不是立即操作数。要选择立即操作数解释,需要在符号前放置
offset
关键字。字符串
NASM有相反的约定,在那里人们会写:
型
在GNU汇编程序的AT&T语法中,这些将是:
型
当GNU汇编器解析编译器产生的代码时,单词
offset
被解释为关键字而不是符号名,这会混淆汇编器的解析器。为了在手工编写汇编代码时消除含义的歧义,您可以将符号名放在引号中:型
这将由汇编程序正确解析和解释。(NASM使用
$
用于此目的。)如果您将变量命名为与寄存器相同的变量,则会出现相同的问题,并进行相同的修复。Intel语法很少用于GNU汇编程序,特别是当GCC通常用于编译代码时,这意味着此错误很容易被忽略。