组装 - 在偏移量为 5 的寄存器/数组中移动 [英] Assembly - Moving through a register/array with an offset of 5

查看:25
本文介绍了组装 - 在偏移量为 5 的寄存器/数组中移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

快速提问.此代码不会编译:

Quick question. This code will not compile:

mov eax, dword [rbx+rsi*5]

我不指望它,并解释说 mov 和乘法是两种不同的 CPU 操作.可以实现的唯一原因是通过位移.

I don't expect it to, with the explaination that mov and multiplication are two different CPU operations. The only reason it can be achieved is through bit-shifting.

但是,这确实可以编译:

However, this does compile:

mov eax, dword [lst+rsi*5]

lst"是一个变量数组.在上下文中使用时它也会产生输出(因此代码编译和运行).为什么会这样?

With "lst" being a variable array. It also produces output when used in context (so the code compiles AND runs). What's the explanation for why this works?

yasm -Worphan-labels -g dwarf2 -f elf64 NAME.asm -l NAME.lst

推荐答案

x86 寻址模式必须符合 [base + idx*scale + disp0/8/32] 的形式.(或相对于 RIP.)

x86 addressing modes have to fit the form [base + idx*scale + disp0/8/32]. (Or RIP-relative.)

*scale 实际上编码为 2 位移位计数,因此它可以是 1、2、4 或 8.请参阅关于 [base + index*scale + disp] 的几个问题引用内存的内容地点.(x86 寻址模式)

The *scale is actually encoded as a 2-bit shift count, so it can be 1, 2, 4, or 8. See A couple of questions about [base + index*scale + disp] and Referencing the contents of a memory location. (x86 addressing modes)

这里发生的事情是你的汇编器分解了[lst + rsi*5]
[lst + rsi + rsi*4] 为您.
(或 1 + (1<<0..3) 形式的其他比例因子)
(其中 lst 是一个 4 字节(32 位)绝对地址,它被符号扩展为 64 位.是的,这适用于 Linux 非 PIE 可执行文件;静态代码+数据进入虚拟地址空间的低 2GiB正是这样,这可以工作.)

What's happening here is that your assembler decomposes [lst + rsi*5]
into [lst + rsi + rsi*4] for you.
(Or other scale factors of the form 1 + (1<<0..3))
(Where lst is a 4-byte (32-bit) absolute address that gets sign-extended to 64-bit. And yes this works in Linux non-PIE executables; static code+data goes in the low 2GiB of virtual address space exactly so this can work.)

但是如果您已经有一个基址寄存器,则无法将其拆分并仍然具有可编码的寻址模式.[rbx + rsi + rsi*4] 是不可能的.

But if you already have a base register, there's no way to split it up and still have an encodeable addressing mode. [rbx + rsi + rsi*4] is impossible.

类似地,NASM 和 YASM 允许您编写诸如 vaddps xmm0, [rbp] 而不是 vaddps xmm0, xmm0, [rbp+0](即使 RBP 作为基址寄存器没有位移就不能编码.也省略了第一个源操作数当它与目的地相同时).或者例如编写 [rbp + rax] 而不是 [rbp + rax*1] - 寻址模式每个基数或索引最多只能有 1 个.

Similarly, NASM and YASM let you write things like vaddps xmm0, [rbp] instead of vaddps xmm0, xmm0, [rbp+0] (even though RBP as a base register is not encodeable without a displacement. Also omitting the first source operand when it's the same as the destination). Or for example writing [rbp + rax] instead of [rbp + rax*1] - an addressing mode can only have at most 1 each base or index.

当您的代码表达的操作明确且可编码时,汇编程序有时会提供方便的功能,让源代码看起来与机器代码/反汇编代码不同.

When the operation expressed by your code is unambiguous and encodeable somehow, assemblers sometimes have convenient features to let the source look like different from the machine code / what you'd get from disassembly.

mov 和乘法是两种不同的 CPU 操作

mov and multiplication are two different CPU operations

寻址模式do包括加法和移位,尽管shladd也是分开的指令.这不是为什么.此外,imul ecx, [lst + rsi + rsi*4], 12345 是一条有效指令.使用内存源或目标操作数进行类似的移位或相加也是如此.

Addressing modes do include addition and shifting, even though shl and add are also separate instructions. That's not why. Also, imul ecx, [lst + rsi + rsi*4], 12345 is a valid instruction. So is a similar shift or add with a memory source or destination operand.

但是是的,x86 寻址模式不能编码任意乘法,只能编码 2 位移位计数.

But yes, x86 addressing modes can't encode arbitrary multiplications, just a 2-bit shift count.

通常你会在寄存器中得到一个指针并在循环内递增它

Normally you'd get a pointer in a register and increment it inside the loop

add  rsi, 5*4      ; 5*4 = 20 as an assemble time constant expression
add  eax, [rsi]

这基本上是将乘法或移位转换为加法的缩放的强度降低.这意味着您可以使用更高效的简单非索引寻址模式(代码大小,并避免在 Sandybridge 系列上分层.)

This is basically a strength-reduction of the scaling that turns multiplication or shifting into addition. It means you can use simple non-indexed addressing modes which are more efficient (code-size, and avoids unlamination on Sandybridge-family.)

这篇关于组装 - 在偏移量为 5 的寄存器/数组中移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆