为什么我的汇编代码比 C 实现慢很多

2024-02-13

我正在学习汇编。所以我写了一个例程,如果输入非负则返回其输入的平方根,否则返回 0。

我已经在汇编和 C 中实现了该例程,我想了解为什么使用 -O2 编译的 C 例程比我的汇编例程快得多。 C 例程的反汇编代码看起来比我的汇编例程稍微复杂一些,所以我不明白哪里出了问题。

汇编例程(srt.asm):

global srt
section .text
srt:
pxor xmm1,xmm1
comisd xmm0,xmm1
jbe  P
sqrtsd xmm0,xmm0
retq
P:
  pxor xmm0,xmm0
retq

我将以上内容编译为

nasm -g -felf64 srt.asm

C 例程 (srtc.c)

#include <stdio.h>
#include <math.h>
#include <time.h>
extern double srt(double);

double srt1(double x)
{
    return sqrt( (x > 0) * x );
}

double srt2(double x)
{
    if( x > 0) return sqrt(x);
    return 0;
}


int main(void)
{
    double v = 0;
    clock_t start;
    clock_t end;
    double niter = 2e8;


    start = clock();
    v = 0;
    for( double i = 0; i < niter; i++ ) {
        v += srt(i);
    }
    end = clock();
    printf("time taken srt = %f v=%g\n", (double) (end - start)/CLOCKS_PER_SEC,v);

    start = clock();
    v = 0;
    for( double i = 0; i < niter; i++ ) {
        v += srt1(i);
    }
    end = clock();
    printf("time taken srt1 = %f v=%g\n", (double) (end - start)/CLOCKS_PER_SEC,v);

    start = clock();
    v = 0;
    for( double i = 0; i < niter; i++ ) {
        v += srt2(i);
    }
    end = clock();
    printf("time taken srt2 = %f v=%g\n", (double) (end - start)/CLOCKS_PER_SEC,v);

    return 0;
}

以上编译为

gcc -g -O2 srt.o -o srtc srtc.c -lm

程序的输出是

time taken srt = 0.484375 v=1.88562e+12
time taken srt1 = 0.312500 v=1.88562e+12
time taken srt2 = 0.312500 v=1.88562e+12

所以我的装配程序要慢得多。

反汇编的C代码是

Disassembly of section .text:

0000000000000000 <srt1>:
   0:   f3 0f 1e fa             endbr64 
   4:   66 0f ef c9             pxor   xmm1,xmm1
   8:   66 0f 2f c1             comisd xmm0,xmm1
   c:   77 04                   ja     12 <srt1+0x12>
   e:   f2 0f 59 c1             mulsd  xmm0,xmm1
  12:   66 0f 2e c8             ucomisd xmm1,xmm0
  16:   66 0f 28 d0             movapd xmm2,xmm0
  1a:   f2 0f 51 d2             sqrtsd xmm2,xmm2
  1e:   77 05                   ja     25 <srt1+0x25>
  20:   66 0f 28 c2             movapd xmm0,xmm2
  24:   c3                      ret    
  25:   48 83 ec 18             sub    rsp,0x18
  29:   f2 0f 11 54 24 08       movsd  QWORD PTR [rsp+0x8],xmm2
  2f:   e8 00 00 00 00          call   34 <srt1+0x34>
  34:   f2 0f 10 54 24 08       movsd  xmm2,QWORD PTR [rsp+0x8]
  3a:   48 83 c4 18             add    rsp,0x18
  3e:   66 0f 28 c2             movapd xmm0,xmm2
  42:   c3                      ret    
  43:   66 66 2e 0f 1f 84 00    data16 nop WORD PTR cs:[rax+rax*1+0x0]
  4a:   00 00 00 00 
  4e:   66 90                   xchg   ax,ax

0000000000000050 <srt2>:
  50:   f3 0f 1e fa             endbr64 
  54:   66 0f ef c9             pxor   xmm1,xmm1
  58:   66 0f 2f c1             comisd xmm0,xmm1
  5c:   66 0f 28 d1             movapd xmm2,xmm1
  60:   77 0e                   ja     70 <srt2+0x20>
  62:   66 0f 28 c2             movapd xmm0,xmm2
  66:   c3                      ret    
  67:   66 0f 1f 84 00 00 00    nop    WORD PTR [rax+rax*1+0x0]
  6e:   00 00 
  70:   66 0f 2e c8             ucomisd xmm1,xmm0
  74:   66 0f 28 d0             movapd xmm2,xmm0
  78:   f2 0f 51 d2             sqrtsd xmm2,xmm2
  7c:   76 e4                   jbe    62 <srt2+0x12>
  7e:   48 83 ec 18             sub    rsp,0x18
  82:   f2 0f 11 54 24 08       movsd  QWORD PTR [rsp+0x8],xmm2
  88:   e8 00 00 00 00          call   8d <srt2+0x3d>
  8d:   f2 0f 10 54 24 08       movsd  xmm2,QWORD PTR [rsp+0x8]
  93:   48 83 c4 18             add    rsp,0x18
  97:   66 0f 28 c2             movapd xmm0,xmm2
  9b:   c3                      ret    

Peter Cordes 评论解释了这里发生的事情。 srt1 和 srt2 是内联的,而 srt 不是。 引用彼得·科德斯的话:

哦,对了,问题就出在非内联函数上。 x86-64 系统 V 没有任何调用保留的 XMM 寄存器,因此添加 通过 v 的依赖链包括 srt() 的存储/重新加载,但不包括 当 srt1 或 srt2 内联时

.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我的汇编代码比 C 实现慢很多 的相关文章

  • 在列标题上绘制矩形

    I m painting rectangle on the column headers in datagridview but on scrolling to right it disappears as in the picture s
  • 使用 ITextSharp 从内存流附加 PDF 文件时遇到问题

    我在附加内存中创建的 PDF 文件并将其附加到电子邮件模板时遇到问题 电子邮件没有任何问题 但没有附件 我不明白为什么会发生这种情况 这是该过程的完整代码 ExtendedEmailTemplate emailTemp new Extend
  • C# - 带 GUI 的后台应用程序

    我的问题是我想创建一个后台应用程序 但具有可以恢复并最小化到系统托盘的用户界面 并且它从窗口启动 我尝试搜索如何启动 但只找到有关 Windows 服务的线程 没有 UI 或创建表单并隐藏它 所以我的问题是我应该如何开始 Windows 窗
  • 简单、高效的弱指针,当目标内存被释放时设置为 NULL

    有没有简单 高效的弱 保护指针 我需要多个指向同一对象的指针 当删除该对象时 这些指针都会自动设置为 NULL 有一个 主 指针始终用于删除对象 但可以有多个其他指针引用同一对象 以下是一些不太符合我的需求的解决方案 QPointer ht
  • 如何用单反斜杠替换双反斜杠

    我想用单反斜杠替换双反斜杠 Using string destinationFile System IO Path Combine msiDirectory fileName Replace gives C Hg temp LogFile
  • 通过 Microsoft Graph 从 Azure AD 获取组中的用户

    我正在通过 Microsoft Graph 从 AzureAD 请求用户列表 我取回了 User 对象 但它们的 MemberOf 属性始终为 null 我认为我可以使用 Expand 来专门请求该属性 虽然它不会导致错误 但它也不会填充该
  • 如何在 Mac OS X 中获取 aio 信号处理程序的用户数据

    我尝试在 Mac OS X 下使用 aio 函数进行异步文件 IO 但在将某种形式的用户数据输入信号处理程序时遇到问题 这是设置操作的代码 class aio context public aio context int fildes bo
  • 在 C# 中将 Exe 文件作为嵌入式资源运行

    我有一个第 3 方 EXE 我只需要从我的 C 应用程序运行它 我的主要目标是对我的 C 文件中的第 3 方可执行文件进行版权保护 有没有更好的方法来做到这一点 我怎样才能做到这一点 首先将嵌入的可执行文件作为资源文件添加到您现有的资源文件
  • 保存到会话状态的 DataTable 丢失事件处理程序

    我有一个来自强类型数据集的数据表 该数据集在 TableNewRow 事件上有一个事件处理程序 用于初始化一些日期字段 当我将此表保存到会话状态时 事件处理程序会正常触发 直到表被序列化 在后续请求中 当我从会话状态检索表时 事件处理程序不
  • C# Response.Write pdf 不适用于 Android 浏览器

    我目前在 Android 环境中使用 pdf 导出时遇到了巨大的问题 我正在使用报告查看器控件将报告呈现为字节数组 接下来我使用response binarywrite方法将字节流输出到浏览器 这适用于所有浏览器以及 iPhone 和 iP
  • ElementReference 对 Blazor 中条件创建的元素的引用

    我正在尝试将焦点设置为有条件呈现的输入控件 我正在设置ElementReference但它的 id 和 context 都是空的
  • std::function 中参数的自动动态转换

    我们有多态类 A 和 B 例如 struct A virtual A struct B final public A void f std cout lt lt f lt lt std endl 我想分配一个变量std function
  • 底层连接已关闭:接收时发生意外错误

    我来这里是因为我在通过 ftp 协议下载一些文件时遇到问题 这很奇怪 因为它偶尔会发生 甚至对于同一个文件也是如此 只是一个精确度 我正在下载非常大的文件 从 500 Mo 到 30Go 以下是我的函数返回的异常类型 抱歉 这是法语 Sys
  • WebProxy 错误:需要代理身份验证

    我使用以下代码从互联网获取html数据 WebProxy p new WebProxy localproxyIP 8080 true p Credentials new NetworkCredential domain user passw
  • 使用signinmanager成功登录后,用户仍然显示为已注销?

    我已将 Asp Net 身份框架添加到从前端调用的 WebAPI 中 注册帐户后 并看到它在数据库中正确显示 我使用该用户的用户名和密码登录 结果成功 但根据登录管理器 用户未登录 我尝试使用 cookie 身份验证使用此示例 https
  • xaml.cs 文件上的 InitializeComponent() 出现错误

    有时我会收到一个红色错误 内容如下 InitializeComponent 在当前上下文中不存在 以及我的其他变量 xaml受约束的x Name The x ClassXaml 文件中的名称空间和类名确实对应于我的xaml cs file
  • 真实文件对象比 StringIO 和 cStringIO 慢?

    StringIO其代码中有以下注释 Notes Using a real file is often faster but less convenient There s also a much faster implementation
  • Outlook 插件:从选定的日历中获取元素

    我正在创建 Outlook 加载项 我想知道如何从选定的日历中获取元素 例如 我需要从名为 myCalendar 的日历中获取所有约会项目 现在 我可以从所有日历中获取所有约会项目 谢谢你 这些额外的日历作为主日历文件夹的子文件夹提供 所以
  • Postgres 服务器性能在达到一定数量的记录后急剧下降

    我正在使用游标从大型 postgres 表中检索记录 4亿条记录 使用子表对数据进行分区 我的游标定义为 select from parent table order by indexed column 同时使用 JDBC 和 psql 前
  • 如何在 Ubuntu x64 中使用 ptrace 插入 int3?

    我正在努力追随本指南 http eli thegreenplace net 2011 01 27 how debuggers work part 2 breakpoints 通过设置断点达到相同的结果 唯一的区别是我在 x64 系统上 所以

随机推荐