现代X86汇编-C和ASM混合编程举例

news2025/1/12 8:48:55

端午假期安装好了vs c++2022,并写了个简单的汇编代码,证明MASM真的可以运行。今天需要搞一个实实在在的C++和ASM混合编程的例子,因为用纯汇编的求伯君写WPS的时代一去不复返了。个别关键函数用汇编,充分发挥CPU的特色功能,偶尔还是需要的。

昨天找的随书代码的位置在github上:GitHub - Apress/modern-x86-assembly-language-programming-3e: Source Code for 'Modern X86 Assembly Language Programming' by Daniel Kusswurm

这是第三版,最新的书。又从z-liabrary上下载了这本英文书,导入微信读书,自动翻译为中文,z-libary加微信读书,使我实现了读书ziyou(啥时候财务ziyou,还远)。

这本书的附录A就举了怎样在vs2022环境建立一个C++加ASM的例子,今天咱们就逐步跟着书上学这个例子。

首先创建project

• Create a C++ project• Enable MASM support• Add an assembly language file• Set project properties•Edit the source code• Build and run the project

  1. 启动VS
  2. New Project
  3. Select Console App
  4. Project name:Example1
  5. Solution name:TestSolution
  6. Create
  7. Build>Configuration Manager,choose <Edit...>
  8. select X86, Remove--我的环境是Win32

其次,配置ASM环境的步骤

  1. View>Solution Explorer
  2. rigtht-click Example1 and select Build Denpendencies>Build Customizations
  3. check masm
  4. Add New Item
  5. select .cpp for the file style
  6. Example1_fasm.asm Add

第三步是设置project属性

  1. Example1  and select Properties
  2. All Configurations   All Platforms
  3. C/C++>Code Generation Set to Advanced Vector Extentions(/arch:AVX) or AVX2 or AVX512
  4. C/C++>Output change to Files Assembly Machine and Source Code(/FAcs)
  5. Microsoft Macro Assembler>Listing File  Enable Assembly Generated Code Listing to Yes(/Sg)
  6. Change the Assembled Code Listing File text filed to $(IntDir)\%(filename).lst
  7. Click OK

$(IntDir)\%(filename).lst  --这是1还是L?

最后一步就是写源码了

  1. AppendixA\TestSolution\Example1\Example1.cpp
  2. AppendixA\TestSolution\Example1\Example1_fasm.asm

Example1.cpp

#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>

extern "C" void CalcZ_avx(float* z, const float* x, const float* y, size_t n);

static void CalcZ_cpp(float* z, const float* x, const float* y, size_t n)
{
    for (size_t i = 0; i < n; i++)
        z[i] = x[i] + y[i];
}

int main(void)
{
    constexpr size_t n = 20;
    float x[n], y[n], z1[n], z2[n];

    // Initialize the data arrays
    for (size_t i = 0; i < n; i++)
    {
        x[i] = i * 10.0f + 10.0f;
        y[i] = i * 1000.0f + 1000.0f;
        z1[i] = z2[i] = 0.0f;
    }

    // Exercise the calculating functions
    CalcZ_cpp(z1, x, y, n);
    CalcZ_avx(z2, x, y, n);

    // Display the results
    constexpr char nl = '\n';
    constexpr size_t w = 10;
    constexpr float eps = 1.0e-6f;

    std::cout << std::fixed << std::setprecision(1);

    std::cout << std::setw(w) << "i";
    std::cout << std::setw(w) << "x";
    std::cout << std::setw(w) << "y";
    std::cout << std::setw(w) << "z1";
    std::cout << std::setw(w) << "z2" << nl;
    std::cout << std::string(50, '-') << nl;

    for (size_t i = 0; i < n; i++)
    {
        std::cout << std::setw(w) << i;
        std::cout << std::setw(w) << x[i];
        std::cout << std::setw(w) << y[i];
        std::cout << std::setw(w) << z1[i];
        std::cout << std::setw(w) << z2[i] << nl;

        if (fabs(z1[i] - z2[i]) > eps)
        {
            std::cout << "Compare error!\n";
            break;
        }
    }

}

Example1_fasm.asm

;------------------------------------------------------------------------------
; Example1_fasm.asm
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; void CalcZ_avx(float* z, const float* x, const float* x, size_t n);
;------------------------------------------------------------------------------

NSE     equ 8                                   ;num_simd_elements
SF      equ 4                                   ;scale factor for F32

        .code
CalcZ_avx proc

; Validate arguments
        test r9,r9                              ;n == 0?
        jz Done                                 ;jump if yes

; Initialize
        mov rax,-SF                             ;rax = array offset (Loop2)
        cmp r9,NSE                              ;n < NSE?
        jb Loop2                                ;jump if yes
        mov rax,-NSE*SF                         ;rax = array offset (Loop1)

; Calculate z[i:i+7] = x[i:i+7] + y[i:i+7]
Loop1:  add rax,NSE*SF                          ;update array offset
        vmovups ymm0,ymmword ptr [rdx+rax]      ;ymm0 = x[i:i+7]
        vmovups ymm1,ymmword ptr [r8+rax]       ;ymm1 = y[i:i+7]
        vaddps ymm2,ymm0,ymm1                   ;z[i:i+7] = x[i:i+7] + y[i:i+7]
        vmovups ymmword ptr [rcx+rax],ymm2      ;save z[i:i+7]

        sub r9,NSE                              ;n -= NSE
        cmp r9,NSE                              ;n >= NSE?
        jae Loop1                               ;jump if yes

        test r9,r9                              ;n == 0?
        jz Done                                 ;jump if yes
        add rax,NSE*SF-SF                       ;adjust array offset for Loop2

; Calculate z[i] = x[i] + y[i] for remaining elements
Loop2:  add rax,SF                              ;update array offset
        vmovss xmm0,real4 ptr [rdx+rax]         ;xmm0 = x[i]
        vmovss xmm1,real4 ptr [r8+rax]          ;xmm1 = y[i]
        vaddss xmm2,xmm0,xmm1                   ;z[i] = x[i] + y[i]
        vmovss real4 ptr [rcx+rax],xmm2         ;save z[i]

        sub r9,1                                ;n -= 1
        jnz Loop2                               ;repeat until done

Done:   vzeroupper
        ret                                     ;return to caller
CalcZ_avx endp
        end

最终构建运行即可

代码有点高大上,估计是用了AVX,两个loop同时运行。慢慢看书了解含义吧,还挺复杂的。

这个例子太高深了,再举个简单的例子,把数组倒序输出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1820039.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

论文阅读:H-ViT,一种用于医学图像配准的层级化ViT

来自CVPR的一篇文章&#xff0c;https://openaccess.thecvf.com/content/CVPR2024/papers/Ghahremani_H-ViT_A_Hierarchical_Vision_Transformer_for_Deformable_Image_Registration_CVPR_2024_paper.pdf 用CNNTransformer混合模型做图像配准。可变形图像配准是一种在相同视场…

计算机体系结构重点学习

从外部I/O与上层应用交互的整体软硬件过程 上层应用发出I/O请求&#xff1a;上层应用程序&#xff0c;如一个文本编辑器、网络浏览器或者任何软件应用&#xff0c;需要读取或写入数据时&#xff0c;会通过调用操作系统提供的API&#xff08;如文件操作API、网络操作API等&…

CATIA P3 V5-6R 中文版软件下载安装 达索CATIA三维设计软件获取

CATIA的建模和装配能力堪称业界翘楚。其强大的建模工具能够轻松应对各种复杂的几何形状和结构&#xff0c;帮助设计师们快速构建出精准的产品模型。同时&#xff0c;装配模块则能够实现零部件的快速装配&#xff0c;大大提高了设计效率。 在分析和仿真方面&#xff0c;CATIA同样…

基于python多光谱遥感数据处理、图像分类、定量评估及机器学习

原文链接&#xff1a;基于python多光谱遥感数据处理、图像分类、定量评估及机器学习 普通数码相机记录了红、绿、蓝三种波长的光&#xff0c;多光谱成像技术除了记录这三种波长光之外&#xff0c;还可以记录其他波长&#xff08;例如&#xff1a;近红外、热红外等&#xff09;光…

【技术】MySQL 8.4 免安装版配置

MySQL 8.4 免安装版配置 官网下载压缩包解压文件创建配置文件初始化数据库安装MySQL服务链接数据库修改密码 官网下载压缩包 从MySQL官网下载压缩包&#xff0c;官网&#xff1a;https://www.mysql.com/ 头部菜单点击【DOWNLOADS】&#xff0c;跳转到下载页面。在页面底部点击…

如何通过逆向分析法挖掘真实需求?

逆向分析法从现有问题或现象出发&#xff0c;反向追溯其根本原因&#xff0c;以揭示隐藏需求和潜在问题。此方法有助于深入理解用户的真实需求&#xff0c;提高需求分析质量和效率&#xff0c;优化用户体验&#xff0c;提高用户满意度和忠诚度。如果缺乏逆行分析法&#xff0c;…

4.1 Python 字符串类型常用操作及内置方法

0. 序列类型 序列是一种数据存储方式, 用来存储一系列的数据. 在内存中, 序列使用连续的内存空间用来存放多个值.序列类型的变量存储序列对象的地址, 而不是直接存在值的地址. 序列对象保存索引和对象的绑定关系.s ABCDprint(id(s), type(s), s) # _ 2050757126000 &…

电商开发者必读:微店商品详情API接口全解析

微店作为一个流行的电商平台&#xff0c;提供了丰富的API接口供开发者使用。详细介绍商品详情API接口的使用方法&#xff0c;帮助开发者快速获取商品信息&#xff0c;实现商品信息的自动化展示和管理。 1. 接口简介 微店商品详情API接口允许开发者通过商品ID获取商品的详细信…

三星公布尖端芯片进展 | 百能云芯

三星电子在本周三举办的年度晶圆制造盛会上&#xff0c;揭开了未来多项技术革新的神秘面纱&#xff0c;并宣布其晶圆制造业务将整合全球领先的记忆芯片、晶圆制造及封装服务&#xff0c;为AI芯片客户提供一站式服务&#xff0c;以加速其生产进程。 三星强调&#xff0c;客户仅需…

qt(使用c++建立图形化界面)

建立QQ页面 MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {//1:设置窗口标题this->setWindowTitle("QQ");//2:重新设计窗口大小this->resize(540,420);//3:设置窗口小图标 添加QIcon头文件 注意路径中替换/this->setWindowIcon(QIcon(&q…

Windows本地使用SSH连接VM虚拟机

WIN10 VM17.5 Ubuntu:20.04 1.网路设置 1)选择编辑->更改设置 配置完成 2.修改了服务器文件&#xff0c;修改sshd配置&#xff0c;在此文件下/etc/ssh/sshd_config&#xff0c;以下为比较重要的配置 PasswordAuthentication yes PermitRootLogin yes PubkeyAuthenticat…

【安装笔记-20240613-Linux-在 OpenWrt 的 LuCI界面支持命令行调试】

安装笔记-系列文章目录 安装笔记-20240613-Linux-在 OpenWrt 的 LuCI界面支持命令行调试 文章目录 安装笔记-系列文章目录安装笔记-20240613-Linux-在 OpenWrt 的 LuCI界面支持命令行调试 前言一、软件介绍名称&#xff1a;ttyd主页官方介绍特点 二、安装步骤测试版本&#xf…

远程开发端口转发

应用推荐场景&#xff1a; 1.服务器跑后台&#xff0c;本地出前端应用。 比如Stable Diffusion的大模型打标应用。 2.Docker容器服务器。 对于本地服务想要转出去&#xff0c;跑出来前端。该项能克服虚拟机的端口与ip访问问题。 正文&#xff1a; 涉及的软件&#xff1a; …

了解AIGC:让AI创造内容,改变未来

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 什么是AIGC&#xff1f; 定义和概念 &#x1f9e0; 关键技术 &#x1f916; AIGC的发展历程 &#x1f…

【LeetCode滑动窗口算法】长度最小的子数组 难度:中等

我们先看一下题目描述&#xff1a; 解法一&#xff1a;暴力枚举 时间复杂度&#xff1a;o(n^3) class Solution { public:int minSubArrayLen(int target, vector<int>& nums){int i 0, j 0;vector<int> v;for (;i < nums.size();i){int sum nums[i];fo…

0101 电路模型和电路定律

电路模型和电路定律 1.1电路和电路模型1.2电压和电流的参考方向1.3电功率和能量 理论分析课程 重点&#xff1a; 1.电压、电流的参考方向 2.电阻元件和电源元件的特性 3.基尔霍夫定律&#xff08;KCL、KVL&#xff09; 1.1电路和电路模型 1.实际电路&#xff1a;由电工设备和…

CentOS手工升级curl记

笔者一台服务器装有 CentOS 7.9 系统&#xff0c;运行 curl -V 查询 curl 的版本是 7.29&#xff0c;这个老版本的 curl 不支持 HTTP/2 协议。为了使 curl 能连接HTTP/2&#xff0c;curl 必须升级到至少7.46.0版本以上。查询 curl的官网得知当前最新版本是 8.8.0&#xff0c;然…

基于51单片机的温控风扇-数码管显示-风扇人体感应

一.硬件方案 系统采用51单片机作为控制平台对风扇转速进行控制。可由用户设置高、低温度值&#xff0c;测得温度值在高低温度之间时打开风扇弱风档&#xff0c;当温度升高超过所设定的温度时自动切换到大风档&#xff0c;当温度小于所设定的温度时自动关闭风扇。风扇控制状态随…

MySQL主从复制(六):数据库是否可用

select 1判断 场景示例&#xff1a; -- 设置innodb并发度为3&#xff0c;从而限制并发查询 set global innodb_thread_concurrency3;-- 创建表t CREATE TABLE t (id int(11) NOT NULL,c int(11) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB;-- 插入1行数据 insert into t v…

华为昇腾异构计算架构CANN及AI芯片简介

异构计算架构CANN 异构计算架构CANN&#xff08;Compute Architecture for Neural Networks&#xff09;是华为针对AI场景推出的异构计算架构&#xff0c;向上支持多种AI框架&#xff0c;包括MindSpore、PyTorch、TensorFlow等&#xff0c;向下服务AI处理器与编程&#xff0c;…