.pos <adr>
是更改编译器当前虚拟地址的指令。因此,下一条编译的指令将被视为 at address <adr>
,如果您将其放在<label>
前面,则<label>
将具有 value <adr>
,因此以后在绝对地址操作的代码中的任何指令<label>
都将使用 value 进行编译<adr>
。
编译器还在编译过程中跟踪当前的虚拟地址,所以如果你<label2>
稍后使用一些指令,它就会<adr + size_of_produced_machine_code_so_far>
有价值。
然后,当您在实际内存中的该位置加载机器代码时,代码中的所有绝对地址都将适合并正常工作(如果您将其加载到其他地方,它将无法正常工作,因为说明仍将引用<adr>
, for它们是编译的)。
在您的示例中,这意味着一旦将该机器代码加载到内存计算机中,首先irmovq
将被放置在 address 。0
为什么从地址 0 开始执行?谁知道,那是目标平台的特性。如果目标平台将从 0x300 开始执行,则将启动代码放在那里是有意义的,而不是.pos 0x300
指令。
irmovq stack, %rsp # Set up stack pointer (how can i move the word "stack" in rsp)
rsp
设置为包含stack
符号的地址(实际上它是“堆栈”符号的值,在人类逻辑中可以看作是内存地址,但它只是数字,就像计算机中的所有内容一样),它是0x100
值(因为.pos
前面有指令stack:
标签定义)。所以该指令确实如此rsp = 0x100
。
目的是.align 8
什么?
对齐是指调整地址,使其可以被某个数整除而没有余数。在第一种情况下,标签ele1
将具有可被 8 整除的地址。如果先前的机器代码将在某个不可整除的地址处结束,编译器将添加一些字节(通常是nop
类似指令)来填补空白,直到下一个可能的地址满足align
要求.
对齐对于内存控制器的性能很重要,因为它们通常在内部使用字节组,例如只能从 8 对齐地址获取四字作为 8 字节。如果您要求它从非对齐地址中获取四字,它将从(address & -8)
和中获取两个 8 字节集((address & -8)+8)
,并从获取的 16 字节中间读取最终的 8 字节结果。(在 x86 .. 在其他平台上,未对齐的内存访问甚至可能是无效操作,导致 CPU 接收陷阱信号,在这种情况下运行崩溃处理程序)。
(为什么按位与 -8 使地址与 8 对齐?-8 = 0xF..F8 = 0b11...11000 => 最后 3 位设置为零 => 强制被 8 整除)