我正在设计一个简单的玩具指令集和随附的模拟器,并且正在尝试找出支持哪些指令。在算术方面,我目前有无符号加法、减法、乘法和除法。但是,我似乎无法找到以下问题的明确答案:哪些算术运算符需要签名版本,哪些算术运算符的无符号和补码签名版本等效?
例如,1111 的补码等于 -1。如果你加 1 并假装它是一个无符号数,你会得到 0000,即使将其视为 -1,这也是正确的。然而,这对所有数字都适用吗?那么其他三个运算(减法、乘法、除法)呢?
对https://ridiculousfish.com/blog/posts/benchmarking-libdivide-m1-avx512.html的分析发现,新的 Apple CPU 花费了大量资源使整数除法速度大大加快。
这是一件令人惊讶的事情。根据我的经验,整数除法并没有真正使用,除非在除以编译时间常数的情况下,可以用移位或乘法代替。
更令人惊讶的是在https://news.ycombinator.com/item?id=27133804的讨论中有人说
当我一直在对性能关键代码进行微优化时,整数除法经常作为一个热点出现。
现在我真的很好奇:人们在做什么,使整数除法成为瓶颈?我正在考虑可以在哪里使用它。我见过的案例:
浮点模拟。但是现在,唯一没有硬件浮点的 CPU 是微型微控制器,无论如何也不会有硬件整数除法。
带有桶数的哈希表是素数,以获得一点额外的随机性。但是人们早就知道这不是最好的做事方式。如果您不相信您的散列函数提供足够的随机性,请获得更好的散列函数。
使用固定点坐标的早期 3D,如 PlayStation 1。但是现在每个人都在做浮点 3D。
那么所有这些整数除法究竟是用来做什么的呢?
performance cpu-architecture division integer-division instructions
我真的很困惑,这个问题可能听起来很愚蠢,但是当我们说指令大小是 32 位或 16 位时,我真的不确定这意味着什么。
如果操作数大小是 32 位,那么我们说它是 32 位指令,如果操作数大小是 16 位指令。
或者每条指令都有操作码,如果操作码地址是 32 位,那么我们说指令是 32 位。
我也在浏览 ARM 架构,在那里我读到的所有拇指指令都是 16 位的,但 ARM 模式指令是 32 位的。
指令大小完全取决于所使用的架构还是取决于 CPU 的运行模式?
http://www.xgc-tek.com/manuals/m1750-ada/m1750/x524.html
给定的链接表明,16 位指令由 8 位操作码和 4+4 位两个通用寄存器组成。
ARM拇指指令集是怎么回事??
我一直在努力理解来自x86汇编语言的ASCII调整指令.
我看到整个互联网信息告诉我不同的事情,但我想这是以不同形式解释的同样的东西,我仍然没有得到.
谁能解释为什么在AAA的伪代码中,AAS我们必须添加,从AL中的低阶半字节中减去6?
并且有人可以在英特尔指令集手册中解释AAM,AAD和Decimal调整指令伪代码,他们为什么这样,他们背后的逻辑是什么?
最后,有人可以举例说明这些说明是否有用,或者至少在过去它们有用的应用程序中.
我知道现在没有使用这些说明,但我仍然想知道这些说明是如何工作的,这很好.
我试图找出LLVM生成的C代码中的目的jp/ jnp指令.样品:
int main(int argc, const char * argv[]) {
double value = 1.5;
if (value == 1.5) {
value = 3.0;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
装配输出:
Ltmp4:
movsd LCPI0_0(%rip), %xmm0
movl $0, -4(%rbp)
movl %edi, -8(%rbp)
movq %rsi, -16(%rbp)
Ltmp5:
movsd %xmm0, -24(%rbp)
Ltmp6:
movsd -24(%rbp), %xmm1
ucomisd %xmm0, %xmm1
jne LBB0_2
jp LBB0_2
## BB#1:
movabsq $3, %rax
cvtsi2sdq %rax, %xmm0
Ltmp7:
movsd %xmm0, -24(%rbp)
Ltmp8:
LBB0_2:
movl $0, %eax
popq %rbp
retq
Run Code Online (Sandbox Code Playgroud)
将jne …
一方面,维基百科写了乱序执行的步骤:
- 取指令。
- 指令分派到指令队列(也称为指令缓冲区或保留站)。
- 指令在队列中等待,直到其输入操作数可用。然后允许该指令在较早、较旧的指令之前离开队列。
- 指令被发布到适当的功能单元并由该单元执行。
- 结果在排队。
- 只有在所有较旧的指令将其结果写回寄存器文件后,才会将该结果写回寄存器文件。这称为毕业或退休阶段。
类似的信息可以在《计算机组织与设计》一书中找到:
为了让程序表现得像在一个简单的有序流水线上运行,指令获取和解码单元需要按顺序发出指令,这允许跟踪依赖关系,并且提交单元需要将结果写入寄存器和程序获取顺序中的内存。这种保守的模式被称为有序提交……今天,所有动态调度的管道都使用有序提交。
因此,据我所知,即使指令以乱序方式执行,其执行结果也会保存在重新排序缓冲区中,然后以确定性顺序提交到内存/寄存器。
另一方面,有一个众所周知的事实,即现代 CPU 可以为性能加速目的重新排序内存操作(例如,可以重新排序两个相邻的独立加载指令)。维基百科在这里写到。
您能否解释一下这种差异?
cpu cpu-architecture dynamic-execution instructions pipelining
我很快就有了一个组装测试,在准备的时候,我注意到了一些奇怪的事情。
repe movsb在 ZF=0 时重复,我被教导repe应该在 CX 不等于 0 和 ZF=1 时重复。
我做了一些测试,发现之前movsb的rep,repe和repne指令的工作方式相同。
对此有何解释?
编辑:这是代码:
.model small
.data
A db ' This is a test '
N db 27
.stack 10h
.code
mov ax,@data
mov ds,ax
mov es,ax
cld
mov al,' '
mov cl,N
xor ch,ch
mov di,offset A
next: repe scasb
jcxz cont ; jump if cx=0
dec di
inc cx
xchg si,di ; swap between si and di …Run Code Online (Sandbox Code Playgroud) 正如LLVM 核心库入门中所述,LLVM 后端中有三个不同的指令调度程序。其中之一在寄存器分配之前运行,可以使用该-pre-RA-sched选项进行选择。其他两个在寄存器分配后运行。如何选择或禁用这三个调度程序中的每一个?他们之间有什么干扰吗?
众所周知,两个浮点数的精确乘积并不总是浮点数,但误差exact(a*b) - float(a*b)却是。一些精确乘法的代码通过返回两个数字来利用这一点
res = a * b
err = fma(a, b, -res)
Run Code Online (Sandbox Code Playgroud)
这利用了融合乘加指令,该指令(a*b)+c 通过一次舍入返回表达式。
现在,我想对sums做同样的事情,即
res = a + b
err = add3(a, b, -res)
Run Code Online (Sandbox Code Playgroud)
add3应该返回(a+b)+c 具有一次舍入的表达式。
除了这篇文章之外,我找不到add3现实世界中实际存在的提示。
是否有包含以下内容的CPU指令集add3?有语言实现它吗?
floating-point instruction-set floating-accuracy instructions
在Xeno Kovah在OpenSecurityTraining 上主持的x86 程序集介绍的第一天作业中,他指定:
我们现在知道的说明(24)
NOP PUSH/POP CALL/RET MOV/LEA ADD/SUB JMP/Jcc CMP/TEST AND/OR/XOR/NOT SHR/SHL IMUL/DIV REP STOS,REP MOV LEAVE
编写一个程序来查找我们尚未涵盖的指令,并在明天报告该指令。
他进一步断言这个任务是,
SAL/SAR MUL/IDIV变体IMUL/DIV也不要指望是否可以找到 GCC 当前输出的 x86 汇编指令列表,而不是objdump随机执行并审核它们然后创建源代码?
这个问题的基础似乎是实际使用的指令的一个非常小的子集,人们需要知道逆向工程(这是课程的重点)。Xeno 似乎试图找到一种有趣的、有指导意义的方式来说明这一点,
我认为知道大约 20-30(不包括变化)就足够了,你很少会检查手册
虽然我欢迎大家加入我在 OpenSecurityTraining 的这个很棒的课程,但问题是我提出的从 GCC 中找出它的方法(如果可能的话)。不是,让人们真正完成 Xeno 的任务。;)
instructions ×10
assembly ×5
x86 ×3
llvm ×2
machine-code ×2
arm ×1
bcd ×1
binary ×1
c ×1
cpu ×1
decimal ×1
division ×1
gcc ×1
performance ×1
pipelining ×1
repeat ×1
scheduling ×1
thumb ×1
x86-64 ×1