我为Project Euler Q14编写了这两个解决方案,在汇编和C++中.它们是用于测试Collatz猜想的相同蛮力方法.装配解决方案与组装
nasm -felf64 p14.asm && gcc p14.o -o p14
Run Code Online (Sandbox Code Playgroud)
C++是用.编译的
g++ p14.cpp -o p14
Run Code Online (Sandbox Code Playgroud)
部件, p14.asm
section .data
fmt db "%d", 10, 0
global main
extern printf
section .text
main:
mov rcx, 1000000
xor rdi, rdi ; max i
xor rsi, rsi ; i
l1:
dec rcx
xor r10, r10 ; count
mov rax, rcx
l2:
test rax, 1
jpe even
mov rbx, 3
mul rbx
inc rax
jmp c1
even:
mov rbx, 2 …Run Code Online (Sandbox Code Playgroud) 我使用英特尔®架构代码分析器(IACA)发现了一些意想不到的东西(对我而言).
以下指令使用[base+index]寻址
addps xmm1, xmmword ptr [rsi+rax*1]
Run Code Online (Sandbox Code Playgroud)
根据IACA没有微熔丝.但是,如果我用[base+offset]这样的
addps xmm1, xmmword ptr [rsi]
Run Code Online (Sandbox Code Playgroud)
IACA报告它确实融合了.
英特尔优化参考手册的第2-11节给出了以下"可以由所有解码器处理的微融合微操作"的示例
FADD DOUBLE PTR [RDI + RSI*8]
Run Code Online (Sandbox Code Playgroud)
和Agner Fog的优化装配手册也给出了使用[base+index]寻址的微操作融合的例子.例如,请参见第12.2节"Core2上的相同示例".那么正确的答案是什么?
我一直看到人们声称MOV指令可以在x86中免费,因为寄存器重命名.
对于我的生活,我无法在一个测试用例中验证这一点.每个测试用例我尝试揭穿它.
例如,这是我用Visual C++编译的代码:
#include <limits.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
unsigned int k, l, j;
clock_t tstart = clock();
for (k = 0, j = 0, l = 0; j < UINT_MAX; ++j)
{
++k;
k = j; // <-- comment out this line to remove the MOV instruction
l += j;
}
fprintf(stderr, "%d ms\n", (int)((clock() - tstart) * 1000 / CLOCKS_PER_SEC));
fflush(stderr);
return (int)(k + j + l);
}
Run Code Online (Sandbox Code Playgroud)
这为循环生成以下汇编代码(随意生成这个你想要的;你显然不需要Visual C++):
LOOP:
add edi,esi
mov …Run Code Online (Sandbox Code Playgroud) 似乎我所参加的每个课程都是对新主题的介绍,该主题无法提供全面的知识,使我能够生成可以在IDE外部执行的实际程序.实现我不知道的东西既令人沮丧又令人生畏,令我感到困惑的是,一个经过认证的计算机科学课程可以提供一个课程,从一开始就不会对这个过程有所了解.
实际问题:原谅介绍,但它提供了我(经验)的良好指示.我目前正在计算机架构课程中学习MIPS,并且已经获得了快速的装配介绍.程序执行方式的精细细节通常被描述为魔术,并在地毯下刷,以供另一位老师解释,如果可能的话.
据我所知,处理器电路在芯片之间变化很大,因此可能需要不同的低级指令来执行相同的高级代码.在成为原始机器代码之前,所有程序最终都会转换为汇编语言,还是不再需要此步骤?
如果是这样,处理器在什么时候开始执行自己独特的指令集?这是最低级别的代码,所以此时程序指令是由处理器逐位执行的吗?
最后,所有架构都需要汇编语言吗?
来自C++中的思考 - 第1卷:
在第二遍中,代码生成器遍历解析树并为树的节点生成汇编语言代码或机器代码.
至少在GCC中,如果我们给出生成汇编代码的选项,编译器会通过创建包含汇编代码的文件来服从.但是,当我们只是在gcc没有任何选项的情况下运行命令时,它是否在内部不生成汇编代码?
如果是,那么为什么需要首先生成汇编代码然后将其转换为机器语言?
我发现了一个有趣的现象:
#include<stdio.h>
#include<time.h>
int main() {
int p, q;
clock_t s,e;
s=clock();
for(int i = 1; i < 1000; i++){
for(int j = 1; j < 1000; j++){
for(int k = 1; k < 1000; k++){
p = i + j * k;
q = p; //Removing this line can increase running time.
}
}
}
e = clock();
double t = (double)(e - s) / CLOCKS_PER_SEC;
printf("%lf\n", t);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在i5-5257U Mac OS上使用GCC 7.3.0来编译代码 …
对于一个新手/愚蠢的问题,我很抱歉,但这让我困扰了一段时间,而且似乎很难找到直接的答案。问题是关于计算机如何在低级别工作 - 更具体地说,是否有计算机可以执行的命令未包含在x86-64指令中。换句话说,您可能会问是仅使用 x86-64 指令编程的操作系统,并且操作系统运行的程序也是如此。请注意,我不是在询问特定于处理器的隐藏命令或附加命令,我们可能假设这些不存在。
提问的动机:
通常的说法是编译器将特定语言的程序编译为机器码。但是,有许多命令不能(据我所知)仅使用 x86-64 指令用汇编语言编写。甚至像“malloc”这样简单的东西。所以看起来为操作系统编写的实际程序由机器代码和操作系统指令组成?
如果查看 x86-64 指令集,似乎 I/O 命令(例如访问键盘、鼠标、硬盘驱动器、GPU、音频接口、时间、显示器、扬声器等)并没有针对它的所有命令,尽管可以使用 INT 命令来完成某些任务。根据这个答案“在现代体系结构上,外围设备的访问方式与内存类似:通过总线上的映射内存地址。”,无论在代码方面意味着什么。所以看起来甚至操作系统也不是只用 x86-64 指令编写的?
assembly operating-system cpu-architecture machine-code low-level
assembly ×7
x86 ×4
performance ×2
c ×1
c++ ×1
cpu ×1
gcc ×1
iaca ×1
intel ×1
low-level ×1
machine-code ×1
optimization ×1