想象一下,您希望将一系列x86汇编指令与某些边界对齐.例如,您可能希望将循环对齐到16或32字节的边界,或者将指令打包以使它们有效地放置在uop缓存中或其他任何位置.
实现这一目标的最简单方法是单字节NOP指令,紧接着是多字节NOP.虽然后者通常效率更高,但这两种方法都不是免费的:NOP使用前端执行资源,并且还计入现代x86上的4宽1重命名限制.
另一个选择是以某种方式延长一些指令以获得所需的对齐.如果这样做没有引入新的停顿,它似乎比NOP方法更好.如何在最近的x86 CPU上有效地延长指令?
在理想的世界中,延长技术同时是:
有一种方法不可能同时满足所有上述要点,因此很好的答案可能会解决各种权衡问题.
1 AMD Ryzen的限制为5或6.
我是这里的新手,刚刚开始学习汇编语言.所以,如果我错了,请纠正我,或者如果这篇文章没有任何意义我会删除.
我在讨论x86-64英特尔架构中的数据移动指令.我已经读过,常规movq指令只能有直接的源操作数,可以表示为32位二进制补码数,而movabsq指令可以有任意64位立即数作为其源操作数,并且只能有一个寄存器作为目标.
你能详细说明一下吗?这是否意味着我只能使用movabsq指令移动64位立即值?只有立即价值到登记册?我不知道如何将64位立即值移动到内存中.或者也许我错了一些重要的事情.
当我拆开.text使用一些二进制文件的部分objdump(与两个AT&T和Intel语法),有时会看到指令用.s后缀,例如:cmpb.s %bh,%ch,sbbl.s %edi,%edi,或adcb.s %bl,%dh.
请问.s后缀有一个有效/有用的意思(也许甚至还不如一个后缀),或这是拆卸一些数据/填充,如果它是一个指令序列的假象?谢谢.
首先,我对movq和之间的区别有点困惑movabsq,我的教科书说:
常规movq指令只能具有可以表示为 32 位二进制补码的立即数源操作数。然后对该值进行符号扩展以生成目标的 64 位值。所述movabsq指令可以具有任意的64位立即值作为其源操作数,并且只能有一个寄存器作为目的地。
我有两个问题。
该movq指令只能具有可以表示为 32 位二进制补码的立即数源操作数。
所以这意味着我们不能做
movq $0x123456789abcdef, %rbp
Run Code Online (Sandbox Code Playgroud)
我们必须这样做:
movabsq $0x123456789abcdef, %rbp
Run Code Online (Sandbox Code Playgroud)
但是为什么movq被设计为不适用于 64 位立即数,这确实违背了q(四分字)的目的,我们需要movabsq为此目的而设置另一个,这不是很麻烦吗?
由于目标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
在 NASM (2.14.02) 中,指令add rbx, 0xffffffff导致
警告:有符号双字值超出界限 [-w+number-overflow]
我知道 64 位模式下的算术逻辑运算仅接受 32 位常量,但 0xffffffff 仍然是 32 位宽。
为什么 NASM 发出警告,为什么它假设一个有符号常量?它是否将 32 位符号扩展-1为 64 位-1(0xffffffffffffffff)并因此出现溢出?0x7fffffff 工作时不会发出警告。
我能以某种方式说服 NASM 这不是一个有符号常量,而是一个无符号常量吗?
为什么NASM在两个寄存器之间组装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
这些是MOV来自Intel\xc2\xae 64 和 IA-32 架构软件开发人员手册的指令操作码:
B8+ rd id MOV r32, imm32 OI Valid Valid Move imm32 to r32。
C7 /0 id MOV r/m32, imm32 MI Valid Valid Move imm32 to r/m32。
我拆解如下:
\n0: b8 44 33 22 11 mov eax, 0x11223344\nRun Code Online (Sandbox Code Playgroud)\n0: 67 c7 00 44 33 22 11 mov DWORD PTR[eax], 0x11223344\nRun Code Online (Sandbox Code Playgroud)\n我想问的问题是:
\n为什么C7操作码是寄存器/内存(r/m32, imm32)而不是仅内存(m32, imm32)?
是否有任何时候我们使用 …
assembly ×7
x86-64 ×5
x86 ×3
att ×2
nasm ×2
machine-code ×1
opcode ×1
optimization ×1
performance ×1