提问人:InvalidBrainException 提问时间:4/28/2012 最后编辑:Peter CordesInvalidBrainException 更新时间:7/29/2019 访问量:27136
YASM/NASM x86 程序集中直接括号与方括号的基本用法
Basic use of immediates vs. square brackets in YASM/NASM x86 assembly
问:
假设我声明了以下内容:
section .bss
buffer resb 1
这些说明如下:section .text
mov al, 5 ; mov-immediate
mov [buffer], al ; store
mov bl, [buffer] ; load
mov cl, buffer ; mov-immediate?
我理解 bl 将包含值 5,而 cl 将包含变量的内存地址是否正确?buffer
我对两者之间的区别感到困惑
- 将直接项移动到寄存器中,
- 将寄存器移入即时寄存器(输入什么,数据还是地址?)和
- 将直接服务器移动到不带括号的寄存器中
- 例如,vs
mov cl, buffer
mov cl, [buffer]
- 例如,vs
更新:在阅读了回复后,我认为以下摘要是准确的:
mov edi, array
将第 0 个数组索引的内存地址放在 中。即标签地址。edi
mov byte [edi], 3
将 VALUE 3 放入数组的第 0 个索引中- 之后,现在包含数组的第 3 个索引的内存地址
add edi, 3
edi
mov al, [array]
将第 0 个索引处的 DATA 加载到 中。al
mov al, [array+3]
将第三个索引处的 DATA 加载到 中。al
mov [al], [array]
无效,因为 x86 无法对 2 个显式内存操作数进行编码,并且因为只有 8 位,即使在 16 位寻址模式下也无法使用。引用内存位置的内容。(x86 寻址模式)al
mov array, 3
无效,因为你不能说“嘿,我不喜欢存储的偏移量,所以我称之为 3”。immediate 只能是源操作数。array
mov byte [array], 3
将值 3 放入数组的第零个索引(第一个字节)中。需要
字节说明符来避免带有内存、即时操作数的指令的字节/字/dword 之间的歧义。否则,这将是组装时错误(操作数大小不明确)。
请提及其中任何一项是否为假。(编者注:我修复了语法错误/歧义,因此有效的语法实际上是有效的 NASM 语法。并链接了其他问答以获取详细信息)
答:
方括号本质上类似于取消引用运算符(例如,在 C 中)。*
所以,像这样的东西
mov REG, x
将 的值移动到 ,而x
REG
mov REG, [x]
将指向的内存位置的值移动到 。请注意,如果是标签,则其值是该标签的地址。x
REG
x
至于你的问题:
我是否正确地理解 bl 将包含值 5 和 cl 是否包含变量缓冲区的内存地址?
是的,你是对的。但请注意,由于只有 8 位宽,因此它只包含地址的最低有效字节。CL
buffer
评论
cl
将仅包含地址的 8 个最低有效位。
mov eax, var
[var]
mov eax, var
). If you want a load, always use
lea rdi, [var]
default rel
lea rdi, [var + rip]
确实,你的想法是正确的。也就是说,bl 将包含 5 和 cl 缓冲区的内存地址(实际上标签缓冲区本身就是一个内存地址)。
现在,让我解释一下您提到的操作之间的差异:
可以使用 将直接数据移动到寄存器中。可能令人困惑的是,标签(例如缓冲区)本身就是包含地址的即时值。
mov reg,imm
您不能真正将寄存器移动到即时寄存器中,因为即时值是常量,例如 或 。您可以做的是将寄存器移动到常量指向的位置。你可以像.
2
FF1Ah
mov [const], reg
您还可以使用间接寻址,例如提供的 reg1 指向有效位置,它会将 reg1 指向的值传输到 reg2。
mov reg2,[reg1]
因此,将缓冲区的地址移动到 cl(它可能会也可能不会给出正确的地址,因为 cl 只有一个字节长),而将获得实际值。mov cl, buffer
mov cl, [buffer]
总结
- 使用 [a] 时,将引用 a 指向的位置的值。例如,如果 a 是 ,则 [a] 是指 RAM 中的地址 F5B1。
F5B1
- 标签是地址,即像 .
F5B1
- 存储在寄存器中的值不必作为 [reg] 引用,因为寄存器没有地址。事实上,寄存器可以被认为是即时值。
评论
mov [const], reg
mov [const], reg
const
dd const
const
mov [0x0], ax
你明白了。但是,有几个细节值得牢记:
- 地址可以而且通常大于 8 位可以容纳的地址(8 位、16 位、32 位、64 位)。因此,很可能不等于变量的地址。它只有地址的最低有效 8 位。
cl
cx
ecx
rcx
cl
buffer
- 如果存在可以抢占上述代码和/或访问的中断例程或线程,则 中的值可能与 5 不同。中断例程损坏实际上可能会影响任何寄存器,因为它们无法保留寄存器值。
buffer
bl
评论
对于所有使用即时值作为操作数的指令,用于将值写入 ram 位置(或在其中进行计算),我们必须指定要访问的字节数。因为我们的集合无法知道我们是否只想访问一个字节、一个单词或一个多重词,例如,如果直接值是较低的值,如以下说明所示。
array db 0FFh, 0FFh, 0FFh, 0FFh
mov byte [array], 3
结果:
array db 03h, 0FFh, 0FFh, 0FFh
....
mov word [array], 3
结果:
array db 03h, 00h, 0FFh, 0FFh
....
mov dword [array], 3
结果:
array db 03h, 00h, 00h, 00h
匕首
评论
array resb 0
在标签“array”处保留一个零长度空间。例如,如果要在 .bss 部分中使用 10 个字节条目数组,则应指定 .resb 10