汇编指令操作数
Posted
技术标签:
【中文标题】汇编指令操作数【英文标题】:Assembly instruction operand 【发布时间】:2018-01-07 01:47:49 【问题描述】:movq 40(%rdi), %rax
中的40
是什么意思?
我看到该值(在gcc
自动生成的其他指令中)始终是 8 的正倍数(即 8、16、24、32...)
它也总是被()
包围
我也知道()
是地址。
但是示例中的40
是什么意思呢?
当我尝试更改它时,它甚至允许非 8 的倍数(例如 2、3、7、-3、-28)并且编译良好。
通过将 40 更改为其他值的一些示例值:
movq $1, (%rdi)
movq 0(%rdi), %rax
%rax: 2
movq $1, (%rdi)
movq 1(%rdi), %rax
%rax: 72057594037927937
movq $1, (%rdi)
movq 2(%rdi), %rax
%rax: 281474976710657
movq $1, (%rdi)
movq 8(%rdi), %rax
%rax: 2
movq $1, (%rdi)
movq 16(%rdi), %rax
%rax: 4
movq $1, (%rdi)
movq 24(%rdi), %rax
%rax: 140730710821713
movq $1, (%rdi)
movq 32(%rdi), %rax
%rax: 2761649059213359105
【问题讨论】:
movq 32(%rdi), %rax
将 32 添加到 %rdi
的内容中,并将其用作要移动的数据的地址。这是一个偏移量。这应该在任何程序集参考中进行描述。你读过文档吗?查找 x64 的“寻址模式”。
我不确定我是否理解。 movq $1, %rdi
然后 movq 32(%rdi), %rax
在运行时导致 seg 错误
确实如此,因为它尝试使用32+1=33
作为地址,而这通常是无效的。
不允许您的应用程序访问系统上的内存位置 33。所以你得到一个分段错误。应用程序不能任意访问它们想要访问的任何内存位置。
等等,你是不是没有看书/教程,只是看编译器输出来猜测程序集的作用?这条路将比您想象的要曲折得多,汇编语言更像是“硬件工程师所做的”,而不是“它在编程语言中的外观和意义”,因此,如果不阅读适当的书籍和文档,您的机会为零破译一些指令行为,例如mul ebx
或div ebx
是完全不可猜测的(但人们会尝试,然后他们会像每周左右一样发布新的 SO 问题)。
【参考方案1】:
40(%rdi)
在 AT&T 语法中是 [rdi + 40]
在 NASM 语法中。它是一个有效地址为 40 + RDI 的内存操作数。 0(%rdi)
和(%rdi)
是一回事:没有位移。见Referencing the contents of a memory location. (x86 addressing modes)。
您的第一个示例将一个 8 字节的 1
存储到 (%rdi)
,然后从同一地址重新加载。但是你声称你得到了2
,所以你在那里做错了。
您的另一个示例是存储然后从部分重叠的位置(如rdi+2
)或不重叠的位置(如rdi+16
)加载。在后一种情况下,加载结果完全不依赖于 store。
【讨论】:
以上是关于汇编指令操作数的主要内容,如果未能解决你的问题,请参考以下文章