根据英特尔在x64中,以下寄存器称为通用寄存器(RAX,RBX,RCX,RDX,RBP,RSI,RDI,RSP和R8-R15)https://software.intel.com/en-us/articles/介绍到x64组装.
在下面的文章中,写了RBP和RSP是专用寄存器(RBP指向当前堆栈帧的基础,RSP指向当前堆栈帧的顶部). https://www.recurse.com/blog/7-understanding-c-by-learning-assembly
现在我有两个相互矛盾的陈述.英特尔声明应该是值得信赖的,但是什么是正确的,为什么RBP和RSP被称为通用目的?
谢谢你的帮助.
在 x86-64 中,如果某些通用寄存器比其他寄存器更受欢迎,某些指令会执行得更快吗?
例如,mov eax, ecx执行速度会比mov r8d, ecx? 我可以想象后者需要一个 REX 前缀,这会使指令获取速度变慢?
使用rax而不是怎么样rcx?怎么样add还是xor?其他操作?较小的寄存器,如r15bvs al? al与ah?
AMD VS 英特尔?较新的处理器?旧处理器?指令组合?
澄清:某些通用寄存器是否应该优先于其他寄存器,它们是哪些?
在最近的 Intel CPU 上,POP指令的吞吐量通常为每个周期 2 条指令。但是,当使用寄存器R12(或者RSP,除了前缀之外具有相同编码)时,如果指令通过传统解码器,吞吐量会下降到每个周期 1(如果 μops 来自 DSB,吞吐量保持在每个周期大约 2 )。
这可以使用nanoBench重现,如下所示:
sudo ./nanoBench.sh -asm "pop R12"
Run Code Online (Sandbox Code Playgroud)
在 Haswell 机器上的进一步实验表明:当在 1 和 4 之间添加时nops,
sudo ./nanoBench.sh -asm "pop R12; nop;"
sudo ./nanoBench.sh -asm "pop R12; nop; nop;"
sudo ./nanoBench.sh -asm "pop R12; nop; nop; nop;"
sudo ./nanoBench.sh -asm "pop R12; nop; nop; nop; nop;"
Run Code Online (Sandbox Code Playgroud)
执行时间增加到 2 个周期。添加第 5 个时nop,
sudo ./nanoBench.sh -asm "pop R12; nop; nop; nop; …Run Code Online (Sandbox Code Playgroud) 我试图找出 x86 16 位寻址模式(MASM 程序集)中不存在比例因子的原因。而32位和64位寻址模式都有比例因子。这背后是否有实际原因或者不需要它?如果您能解释一下,我将不胜感激。
可以组合不同组件来创建有效地址的所有可能方式:
16 位和 32 位寻址模式之间的差异
我目前正在尝试编写一个反汇编程序.我找到了以下操作码列表及其含义,所以我决定在运行时解析它:http: //mprolab.teipir.gr/vivlio80X86/pentium.txt
但我被困在操作码0x00:接下来是reg/modbyte.解析它对我来说不是什么大问题.但是我在使用Scale-Index-Byte时遇到问题:如果你实际上将esp指定为索引寄存器,它实际上意味着没有索引寄存器.这同样适用于ebp的基址寄存器.但我用c ++内联汇编程序尝试了它:可以编译:"add [ebp*2 + ebp],cl"
那么当使用ebp作为基址寄存器时,如何将ebp用作基址寄存器实际上意味着根本不使用基址寄存器!
出于兴趣,我想在机器代码中编写一个小程序.
我目前正在学习寄存器,ALU,总线和内存,我有点着迷,指令可以用二进制而不是汇编语言编写.
是否需要使用编译器?
最好是在OSX上运行的.
我有一个内存位置,其中包含一个我想要与另一个角色进行比较的角色(并且它不在堆栈的顶部,所以我不能只是pop它).如何引用内存位置的内容以便进行比较?
基本上我如何在语法上做到这一点.
考虑一个简单的指令,例如
mov RCX, RDI # 48 89 f9
Run Code Online (Sandbox Code Playgroud)
48 是 x86_64 的 REX 前缀。它不是LCP。但请考虑添加 LCP(用于对齐目的):
.byte 0x67
mov RCX, RDI # 67 48 89 f9
Run Code Online (Sandbox Code Playgroud)
67 是地址大小前缀,在本例中用于没有地址的指令。该指令也没有立即数,并且不使用 F7 操作码(假 LCP 停止;F7 将是 TEST、NOT、NEG、MUL、IMUL、DIV + IDIV)。假设它也不跨越 16 字节边界。这些是 Intel优化参考手册中提到的 LCP 停顿情况。
该指令是否会导致 LCP 停顿(在 Skylake、Haswell 等上)?两个 LCP 怎么样?
我日常驾驶的是 MacBook。所以我无法访问 VTune,也无法查看 ILD_STALL 事件。还有其他方法可以知道吗?
performance assembly x86-64 cpu-architecture micro-optimization
我是组装新手,我正在从头开始编程学习它。在第 41 页和第 42 页,该书讨论了索引寻址模式。
内存地址引用的一般形式是:
ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)
所有字段都是可选的。要计算地址,只需执行以下计算:
FINAL ADDRESS = ADDRESS_OR_OFFSET + %BASE_OR_OFFSET + MULTIPLIER * %INDEX
ADDRESS_OR_OFFSET 和 MULTIPLIER 必须都是常量,而另外两个必须是寄存器。如果任何部分被遗漏,它只是在等式中用零代替。
所以我决定稍微玩一下这个。我写了下面的一段代码:
.code32
.section .data
str:
.ascii "Hello world\0"
.section .text
.global _start
_start:
movl $2, %ecx # The index register.
mov str(, %ecx, ), %bl
movl $1, %eax
int $0x80
Run Code Online (Sandbox Code Playgroud)
我希望得到 72(H 的 ASCII 代码)作为程序的退出结果,因为没有任何乘数(根据这本书,应该用零代替)。但令人惊讶的是,我得到了 108(l 的 ASCII 代码)。我认为这可能是.ascii一回事,并试图查看是否可以使用不同的数据类型获得不同的结果。我得到了相同的结果.byte。
我尝试使用 AT&T 语法在 x86 程序集中查找索引寻址模式,但找不到任何有用的信息(可能是因为我不知道要搜索什么)。
有什么我遗漏的或者是书中的错误吗?鉴于我是该领域的新手,如果您详细说明,我真的很感激。
[bits 32]
global _start
section .data
str_hello db "HelloWorld", 0xa
str_hello_length db $-str_hello
section .text
_start:
mov ebx, 1 ; stdout file descriptor
mov ecx, str_hello ; pointer to string of characters that will be displayed
mov edx, [str_hello_length] ; count outputs Relative addressing
mov eax, 4 ; sys_write
int 0x80 ; linux kernel system call
mov ebx, 0 ; exit status zero
mov eax, 1 ; sys_exit
int 0x80 ; linux kernel system call
Run Code Online (Sandbox Code Playgroud)
这里的基本要点是我需要将hello字符串的长度传递给linux的sys_write系统调用.现在,我很清楚我可以使用EQU,它会工作正常,但我真的想了解这里发生了什么.
所以,基本上当我使用EQU时,它会加载值,这很好.
str_hello_length equ $-str_hello …Run Code Online (Sandbox Code Playgroud) assembly ×9
x86 ×6
x86-64 ×4
performance ×3
att ×1
disassembly ×1
intel ×1
linux ×1
machine-code ×1
masm ×1
nasm ×1
x86-16 ×1