Gcc 二进制和(&;)的操作数无效
我有这个“程序集”文件(仅包含) 结合此链接器脚本:Gcc 二进制和(&;)的操作数无效,gcc,assembly,ld,gnu-assembler,Gcc,Assembly,Ld,Gnu Assembler,我有这个“程序集”文件(仅包含) 结合此链接器脚本: SECTIONS { "$stack_top" = 0x10000; } 组装产生这个输出 file.s:汇编程序消息: file.s:错误:设置'prot_start'时,`&'的操作数(*UND*和*ABS*部分)无效 file.s:错误:设置'prot_end'时,`&'的操作数(*UND*和*ABS*部分)无效 我怎样才能做到这一点呢?该死的: 中缀运算符有两个参数,一个在两边。运算符具有优先级,但具有相同优先级的操作从
SECTIONS {
"$stack_top" = 0x10000;
}
组装产生这个输出
file.s:汇编程序消息:
file.s:错误:设置'prot_start'时,`&'的操作数(*UND*和*ABS*部分)无效
file.s:错误:设置'prot_end'时,`&'的操作数(*UND*和*ABS*部分)无效
我怎样才能做到这一点呢?该死的:
中缀运算符有两个参数,一个在两边。运算符具有优先级,但具有相同优先级的操作从左到右执行除了+
或-
之外,两个参数都必须是绝对的,并且结果是绝对的
为什么不可能? 您已经链接到了GAS文档,但这种无法使用的理由是什么 答:GAS必须通过ELF对象文件将操作传递给链接器,并且只能像这样传递
+
和-
(-
只是+
一个负值)。所以这是ELF格式的一个基本限制,而不仅仅是GAS开发者的懒散
当GAS编译到目标文件时,将执行链接步骤,重新定位将确定符号的最终值
问题:为什么+
可以被传达,而不是&
回答:因为+
是可传递的:(a+b)+c==a+(b+c)
但是+
和&
不是“一起传递的”:(a&b)+c!=a和(b+c)
让我们看看+
是如何通过ELF格式传达的,以说服我们自己&
是不可能的
如果您不熟悉搬迁,首先了解搬迁是什么:
让我们用另一个会产生相同错误的示例来最小化您的示例:
a: .long s
b: .long s + 0x12345678
/* c: .long s & 1 */
s:
编译和反编译:
as --32 -o main.o main.S
objdump -dzr main.o
输出包括:
00000000 <a>:
0: 08 00 or %al,(%eax)
0: R_386_32 .text
2: 00 00 add %al,(%eax)
00000004 <b>:
4: 80 56 34 12 adcb $0x12,0x34(%esi)
4: R_386_32 .text
其中:
:对象文件中重定位前的值 重新定位前S
的值==a
==08 00 00
以小尾端为单位 重新定位前的8
值==b
=80563412
,以小尾端为单位0x12345680
:加数,一个rellocation条目的字段,这里是A
(未显示在0
中),所以让我们忘掉它吧objdump
将替换为:a
address of text section + 8
有一个address of text section + (0x12345678 + 8) == address of text section + 0x12345680
,因为+8
是文本部分的第8个字节,前面有2个长字符s:
将替换为:b
address of text section + 8
啊哈,这就是为什么address of text section + (0x12345678 + 8) == address of text section + 0x12345680
出现在对象文件上的原因0x12345680
+
但是用这种机制(或者我知道的任何其他机制)无法表达
&
,因为我们不知道文本部分在重新定位后的地址是什么,所以我们不能对其应用&
。可能是另一个$
或两个?@FrankKotler:我觉得美元没有效果,由于遗留的原因,它们都在我的代码库中。不是吗?我不认为那是真的,但我不确定。我更擅长Nasm语法。@FrankKotler$
是GAS x86 ELF中的有效符号名字符“在大多数机器上,您也可以在符号名中使用$”,这不应该是问题所在。这是不可能的;-)