相关疑难解决方法(0)

在现代x86上有哪些方法可以有效地扩展指令长度?

想象一下,您希望将一系列x86汇编指令与某些边界对齐.例如,您可能希望将循环对齐到16或32字节的边界,或者将指令打包以使它们有效地放置在uop缓存中或其他任何位置.

实现这一目标的最简单方法是单字节NOP指令,紧接着是多字节NOP.虽然后者通常效率更高,但这两种方法都不是免费的:NOP使用前端执行资源,并且还计入现代x86上的4宽1重命名限制.

另一个选择是以某种方式延长一些指令以获得所需的对齐.如果这样做没有引入新的停顿,它似乎比NOP方法更好.如何在最近的x86 CPU上有效地延长指令?

在理想的世界中,延长技术同时是:

  • 适用于大多数说明
  • 能够通过可变数量延长指令
  • 不会停止或以其他方式减慢解码器的速度
  • 在uop缓存中有效表示

有一种方法不可能同时满足所有上述要点,因此很好的答案可能会解决各种权衡问题.


1 AMD Ryzen的限制为5或6.

optimization performance x86 assembly micro-optimization

20
推荐指数
1
解决办法
683
查看次数

x86-64中movq和movabsq之间的区别

我是这里的新手,刚刚开始学习汇编语言.所以,如果我错了,请纠正我,或者如果这篇文章没有任何意义我会删除.

我在讨论x86-64英特尔架构中的数据移动指令.我已经读过,常规movq指令只能有直接的源操作数,可以表示为32位二进制补码数,而movabsq指令可以有任意64位立即数作为其源操作数,并且只能有一个寄存器作为目标.

你能详细说明一下吗?这是否意味着我只能使用movabsq指令移动64位立即值?只有立即价值到登记册?我不知道如何将64位立即值移动到内存中.或者也许我错了一些重要的事情.

x86 assembly x86-64 instruction-set att

19
推荐指数
1
解决办法
8093
查看次数

x86指令中的".s"后缀是什么?

当我拆开.text使用一些二进制文件的部分objdump(与两个AT&T和Intel语法),有时会看到指令用.s后缀,例如:cmpb.s %bh,%ch,sbbl.s %edi,%edi,或adcb.s %bl,%dh.

请问.s后缀有一个有效/有用的意思(也许甚至还不如一个后缀),或这是拆卸一些数据/填充,如果它是一个指令序列的假象?谢谢.

x86 assembly x86-64 att

12
推荐指数
2
解决办法
1174
查看次数

为什么我们不能将 64 位立即数移动到内存中?

首先,我对movq和之间的区别有点困惑movabsq,我的教科书说:

常规movq指令只能具有可以表示为 32 位二进制补码的立即数源操作数。然后对该值进行符号扩展以生成目标的 64 位值。所述movabsq指令可以具有任意的64位立即值作为其源操作数,并且只能有一个寄存器作为目的地。

我有两个问题。

问题 1

movq指令只能具有可以表示为 32 位二进制补码的立即数源操作数。

所以这意味着我们不能做

movq    $0x123456789abcdef, %rbp
Run Code Online (Sandbox Code Playgroud)

我们必须这样做:

movabsq $0x123456789abcdef, %rbp
Run Code Online (Sandbox Code Playgroud)

但是为什么movq被设计为不适用于 64 位立即数,这确实违背了q(四分字)的目的,我们需要movabsq为此目的而设置另一个,这不是很麻烦吗?

问题2

由于目标movabsq必须是寄存器,而不是内存,所以我们不能将 64 位立即数移动到内存中:

movabsq $0x123456789abcdef, (%rax)
Run Code Online (Sandbox Code Playgroud)

但有一个解决方法:

movabsq $0x123456789abcdef, %rbx
movq    %rbx, (%rax)   // the source operand is a register, not immediate constant, and the destination of movq can be memory
Run Code Online (Sandbox Code Playgroud)

那么为什么这条规则旨在让事情变得更难呢?

assembly x86-64 instruction-set cpu-architecture immediate-operand

4
推荐指数
2
解决办法
1835
查看次数

NASM Intel 64位模式:为什么32位常量0xffffffff会导致“警告:有符号双字值超出界限”

在 NASM (2.14.02) 中,指令add rbx, 0xffffffff导致

警告:有符号双字值超出界限 [-w+number-overflow]

我知道 64 位模式下的算术逻辑运算仅接受 32 位常量,但 0xffffffff 仍然是 32 位宽。

为什么 NASM 发出警告,为什么它假设一个有符号常量?它是否将 32 位符号扩展-1为 64 位-1(0xffffffffffffffff)并因此出现溢出?0x7fffffff 工作时不会发出警告。

我能以某种方式说服 NASM 这不是一个有符号常量,而是一个无符号常量吗?

assembly x86-64 nasm immediate-operand

4
推荐指数
1
解决办法
510
查看次数

为什么nasm在寄存器之间组装MOV指令时使用0x89?

为什么NA​​SM在两个寄存器之间组装MOV指令时使用0x89操作码(137)?

以下是使用NASM汇编的代码示例:

55      push ebp
89E5    mov ebp, esp
83EC04  sub esp, byte +0x4
31C0    xor eax, eax
C9      leave
C3      ret
Run Code Online (Sandbox Code Playgroud)

我想要这样的东西:

55      push ebp
8BEC    mov ebp, esp
83EC04  sub esp, byte +0x4
33C0    xor eax, eax
C9      leave
C3      ret
Run Code Online (Sandbox Code Playgroud)

我想要0x8B的原因是:如果你查看MOV指令的二进制表示,它在NASM中看起来像这样:

Opcode   Mod Reg R/M
10001001 11  100 101 (89 E5)
Run Code Online (Sandbox Code Playgroud)

令人困惑的部分是reg操作数是第二个.

NASM的语法是这样的:0x89 11 source_reg destination_reg
MOV指令是mov destination_reg, source_reg

assembly nasm

1
推荐指数
1
解决办法
1338
查看次数

MOV r/m32、imm32 和 MOV r32、imm32 之间的操作码差异

这些是MOV来自Intel\xc2\xae 64 和 IA-32 架构软件开发人员手册的指令操作码:

\n

B8+ rd id MOV r32, imm32 OI Valid Valid Move imm32 to r32

\n

C7 /0 id MOV r/m32, imm32 MI Valid Valid Move imm32 to r/m32

\n

我拆解如下:

\n
0:  b8 44 33 22 11          mov    eax, 0x11223344\n
Run Code Online (Sandbox Code Playgroud)\n
0:  67 c7 00 44 33 22 11    mov    DWORD PTR[eax], 0x11223344\n
Run Code Online (Sandbox Code Playgroud)\n

我想问的问题是:

\n
    \n
  • 为什么C7操作码是寄存器/内存(r/m32, imm32)而不是仅内存(m32, imm32)?

    \n
  • \n
  • 是否有任何时候我们使用 …

assembly x86-64 machine-code opcode instruction-encoding

1
推荐指数
1
解决办法
237
查看次数