了解Y86
Understanding Y86
我有以下代码。有人可以解释一下括号中的问题吗?
# Execution begins at address 0 (why?)
.pos 0
irmovq stack, %rsp # Set up stack pointer (how can i move the word "stack" in rsp)
call main # Execute main program
halt # Terminate program
# Sample linked list (what is the purpose of .align 8?)
.align 8
ele1:
.quad 0x00a
.quad ele2
ele2:
.quad 0x0b0
.quad ele3
ele3:
.quad 0xc00
.quad 0
main:
irmovq ele1,%rdi
call sum
ret
sum:
# Stack starts here and grows to lower addresses
.pos 0x100
stack:
执行从 0
开始,因为那是 .pos 0
在下一行所做的。
单词 "stack" 未移动:stack
它是代码中更下方的一个标签,它将堆栈指针 rsp
设置为内存中的那个位置。
对齐到 8 字节边界的目的是因为处理器不喜欢桥接这样的边界。 .quad
指令生成 8 字节数据。
寻求教程是题外话 - google 很容易找到适合自己的教程。
.pos <adr>
是改变编译器当前虚拟地址的指令。所以编译的下一条指令将被视为地址 <adr>
,如果你将 <label>
放在它前面,<label>
将具有值 <adr>
,因此后面的任何指令使用绝对地址 <label>
运行的代码将使用 <adr>
值进行编译。
此外,编译器在编译期间会跟踪当前虚拟地址,因此如果您稍后使用一些 <label2>
几条指令,它将具有 <adr + size_of_produced_machine_code_so_far>
值。
当您随后在实际内存中的那个位置加载机器代码时,代码中的所有绝对地址都将适合并正常工作(如果您在其他地方加载它,它将无法正常工作,因为指令仍然会请参阅 <adr>
,它们是为此而编译的)。
在您的示例中,这意味着第一个 irmovq
预计将放置在地址 0
,一旦该机器代码被加载到内存计算机中。
为什么从地址0开始执行?谁知道呢,这就是目标平台的特性。如果目标平台将从 0x300 开始执行,那么将启动代码放在那里是有意义的,使用 .pos 0x300
指令。
irmovq stack, %rsp # Set up stack pointer (how can i move the word "stack" in rsp)
rsp
设置为包含stack
符号的地址(实际上是"stack"符号的值,可以看成内存地址在人类逻辑中,但它只是数字,如 everything 在计算机中),这是 0x100
值(因为 .pos
指令就在 stack:
标签定义)。所以该指令确实 rsp = 0x100
.
what is the purpose of .align 8
?
对齐就是调整地址,可以被某个数整除,没有余数。在第一种情况下,标签 ele1
的地址可以被 8 整除。如果之前的机器代码以某个不可整除的地址结束,编译器将添加一些字节(通常是 nop
类指令)来填充到满足 align
要求的下一个可能地址的差距。
对齐对于内存控制器的性能很重要,因为它们通常在内部使用字节组,比如只能从 8 对齐地址中获取 8 字节的四字。如果你要求它从非对齐地址中获取四字,它将从(address & -8)
和((address & -8)+8)
中获取两个8字节的集合,并从获取的16个字节的中间读取最后的8字节结果字节。 (在 x86 .. 在其他平台上,未对齐的内存访问甚至可能是无效操作,导致 CPU 接收陷阱信号,在这种情况下 运行 崩溃处理程序)。
(为什么按位与 -8 使地址 8 对齐?-8 = 0xF..F8 = 0b11...11000 => 最后 3 位设置为零 => 强制被 8 整除)
我有以下代码。有人可以解释一下括号中的问题吗?
# Execution begins at address 0 (why?)
.pos 0
irmovq stack, %rsp # Set up stack pointer (how can i move the word "stack" in rsp)
call main # Execute main program
halt # Terminate program
# Sample linked list (what is the purpose of .align 8?)
.align 8
ele1:
.quad 0x00a
.quad ele2
ele2:
.quad 0x0b0
.quad ele3
ele3:
.quad 0xc00
.quad 0
main:
irmovq ele1,%rdi
call sum
ret
sum:
# Stack starts here and grows to lower addresses
.pos 0x100
stack:
执行从 0
开始,因为那是 .pos 0
在下一行所做的。
单词 "stack" 未移动:stack
它是代码中更下方的一个标签,它将堆栈指针 rsp
设置为内存中的那个位置。
对齐到 8 字节边界的目的是因为处理器不喜欢桥接这样的边界。 .quad
指令生成 8 字节数据。
寻求教程是题外话 - google 很容易找到适合自己的教程。
.pos <adr>
是改变编译器当前虚拟地址的指令。所以编译的下一条指令将被视为地址 <adr>
,如果你将 <label>
放在它前面,<label>
将具有值 <adr>
,因此后面的任何指令使用绝对地址 <label>
运行的代码将使用 <adr>
值进行编译。
此外,编译器在编译期间会跟踪当前虚拟地址,因此如果您稍后使用一些 <label2>
几条指令,它将具有 <adr + size_of_produced_machine_code_so_far>
值。
当您随后在实际内存中的那个位置加载机器代码时,代码中的所有绝对地址都将适合并正常工作(如果您在其他地方加载它,它将无法正常工作,因为指令仍然会请参阅 <adr>
,它们是为此而编译的)。
在您的示例中,这意味着第一个 irmovq
预计将放置在地址 0
,一旦该机器代码被加载到内存计算机中。
为什么从地址0开始执行?谁知道呢,这就是目标平台的特性。如果目标平台将从 0x300 开始执行,那么将启动代码放在那里是有意义的,使用 .pos 0x300
指令。
irmovq stack, %rsp # Set up stack pointer (how can i move the word "stack" in rsp)
rsp
设置为包含stack
符号的地址(实际上是"stack"符号的值,可以看成内存地址在人类逻辑中,但它只是数字,如 everything 在计算机中),这是 0x100
值(因为 .pos
指令就在 stack:
标签定义)。所以该指令确实 rsp = 0x100
.
what is the purpose of
.align 8
?
对齐就是调整地址,可以被某个数整除,没有余数。在第一种情况下,标签 ele1
的地址可以被 8 整除。如果之前的机器代码以某个不可整除的地址结束,编译器将添加一些字节(通常是 nop
类指令)来填充到满足 align
要求的下一个可能地址的差距。
对齐对于内存控制器的性能很重要,因为它们通常在内部使用字节组,比如只能从 8 对齐地址中获取 8 字节的四字。如果你要求它从非对齐地址中获取四字,它将从(address & -8)
和((address & -8)+8)
中获取两个8字节的集合,并从获取的16个字节的中间读取最后的8字节结果字节。 (在 x86 .. 在其他平台上,未对齐的内存访问甚至可能是无效操作,导致 CPU 接收陷阱信号,在这种情况下 运行 崩溃处理程序)。
(为什么按位与 -8 使地址 8 对齐?-8 = 0xF..F8 = 0b11...11000 => 最后 3 位设置为零 => 强制被 8 整除)