我有一个关于装配的基本问题.
如果它们也可以在内存上工作,为什么我们只在寄存器上进行算术运算呢?
例如,以下两个原因(基本上)都将相同的值计算为答案:
片段1
.data
var dd 00000400h
.code
Start:
add var,0000000Bh
mov eax,var
;breakpoint: var = 00000B04
End Start
Run Code Online (Sandbox Code Playgroud)
片段2
.code
Start:
mov eax,00000400h
add eax,0000000bh
;breakpoint: eax = 0000040B
End Start
Run Code Online (Sandbox Code Playgroud)
从我所看到的,大多数文本和教程主要在寄存器上进行算术运算.使用寄存器只是更快吗?
编辑:那很快:)
给出了一些很好的答案; 根据第一个好的答案选择了最佳答案.
我正在阅读一些关于英特尔操作码汇编指令的资料,但我无法理解它遵循操作码字节是什么意思.例如:"cw","cd","/ 2","cp","/ 3".请给我一个提示是什么意思或在哪里可以找到完整的参考?提前致谢!
E8 cw CALL rel16相对于下一条指令调用near,relative,displacement
E8 cd CALL rel32相对于下一条指令调用near,relative,displacement
FF / 2 CALL r/m16调用r/m16中给出的接近绝对间接地址
FF / 2 CALL r/m32调用r/m32中给出的接近绝对间接地址
9A cd CALL ptr16:16调用操作数中给出的far,absolute,address
9A cp CALL ptr16:32调用操作数中给出的far,absolute,address
FF / 3 CALL m16:16调用m16:16中给出的远,绝对间接地址
FF / 3 CALL m16:32调用m16:32中给出的远,绝对间接地址
使用以下代码是否存在任何执行速度差异:
cmp al, 0
je done
Run Code Online (Sandbox Code Playgroud)
以下内容:
or al, al
jz done
Run Code Online (Sandbox Code Playgroud)
我知道JE和JZ指令是相同的,并且使用OR可以提供一个字节的大小改进.但是,我也关心代码速度.逻辑运算符似乎比SUB或CMP更快,但我只是想确定.这可能是规模和速度之间的权衡,或双赢(当然代码将更加不透明).
我试图了解地址计算指令的工作原理,尤其是leaq命令.然后当我看到leaq用于进行算术运算的例子时,我感到困惑.例如,以下C代码,
long m12(long x) {
return x*12;
}
Run Code Online (Sandbox Code Playgroud)
在组装中
leaq (%rdi, %rdi, 2), %rax
salq $2, $rax
Run Code Online (Sandbox Code Playgroud)
如果我的理解是正确的,那么leaq应该移动任何(%rdi, %rdi, 2)应该2*%rdi+%rdi评估的地址%rax.我感到困惑的是,因为值x存储%rdi在内,这只是内存地址,为什么%rdi乘以3然后左移这个内存地址 2等于x乘以12?是不是当我们%rdi用3时,我们跳到另一个没有值x的内存地址?
看http://ref.x86asm.net/coder32.html我发现两个匹配语句的操作码
xor eax,eax
1)操作码31 XOR r/m16/32 r16/32
2)操作码33 XOR r16/32 r/m16/32
两者都指操作数1和操作数2的32位寄存器.那么,XORing两个32位寄存器的这种特殊情况有什么不同吗?
累加器寄存器是一个保存临时值的寄存器。只有 EAX、AX、AL 寄存器是累加器。
据我所知,BX、CX、DX 和扩展版本可以保持永久值。那么,为什么我们使用 EAX、AX、AL 寄存器作为累加器呢?
什么是蓄能器?
我对x86-64二进制编码很新.我正在尝试修复一些旧的"汇编程序"代码.
无论如何,我正在尝试做这样的事情(英特尔语法):
mov [rbp+rcx], al
Run Code Online (Sandbox Code Playgroud)
汇编程序目前正在生成:
88 04 0D
Run Code Online (Sandbox Code Playgroud)
但这似乎不是一个有效的指示.如果我将SIB字节中的基数更改rbp为其他寄存器,则可以正常工作.另一种使其工作的方法是添加一个零字节的位移(88 44 0D 00).这似乎与其他类似的操作码一起发生.
为什么我不能rbp在那里使用mod=00?
在RISC-V中,可以Regs[x1] <- Regs[x2]+Regs[x3]使用指令执行整数运算
add x1,x2,x3
Run Code Online (Sandbox Code Playgroud)
在 x86 中,相同的操作显然需要两条指令,
mov x1,x2
add x1,x3
Run Code Online (Sandbox Code Playgroud)
该模式对于 x86 中的其他基本指令(例如、和 )src1 <- src1 op src2似乎很常见。然而,x86 确实有浮点数的eg 。andorsubdest <- src1 op src2add
是双指令模式mov x1,x2;op x1,x3; 通常将宏融合到单个微操作中?或者,对于这些操作来说,独立目标是如此不常见,以至于 x86 架构不会费心在单个 uop 中允许它?如果是这样,禁止独立目的地会带来什么效率?
assembly ×10
x86 ×8
machine-code ×2
opcode ×2
accumulator ×1
c ×1
instructions ×1
intel ×1
math ×1
optimization ×1
performance ×1
riscv ×1
x86-64 ×1
xor ×1