c、数组与汇编

  上次的“c调用汇编”使用的clang编译器,而且使用的是mac 64位系统。当时感觉写的汇编怪怪的,

今天闲来无事,就在w7 32位系统下把c文件汇编后,确实与mac后的差异很大。

可不仅仅是寄存器eax与rax的区别。我想说的是函数参数传递的不同。mac下clang编译后

函数的参数先保存在寄存器中(以一定的规则保存),然后在函数中压入栈里,

以待后用。例如上篇例子,红色部分:

.global _decToBin 
 
 _decToBin:
     pushq     %rbp
     movq    %rsp,%rbp
 
     movq     %rdi,-8(%rbp) #第一个参数,保存在rdi中
     movq     %rsi,-16(%rbp) #第二个参数,保存在rsi中
 
     movq    -8(%rbp),%rax
     movq    -16(%rbp),%rbx
     movq    $63,%rcx
 
......
 
     popq     %rbp
     ret

而我在w7下使用cygwin安装的gcc编译test.c文件:

test.c:

int hello(int a,int b,int c,int d)
{
    return b;
}

test.s:

    .file    "test.c"
    .text
    .globl    _hello
    .def    _hello;    .scl    2;    .type    32;    .endef
_hello:
    pushl    %ebp
    movl    %esp, %ebp
    movl    12(%ebp), %eax #说明参数是函数在使用其值之前就已经压入栈中
    popl    %ebp
    ret

这说明clang与gcc使用了两种不同的规则(网上有很多介绍函数值传递的不同规则的,我就不介绍了)。

所以不同的平台不同的编译器要不同的对待。以上算是上次的不足补充吧。

下面来看看数组:

test.c例子:

 1 void hello1()
 2 {
 3     int a[3]={1,2,3};
 4         int b=a[1];
 5 }
 6 void hello2()
 7 {
 8     int a[3]={1,2,3};
 9     int b=*(a+1);
10 } 
11 void hello3()
12 {
13     int a[3]={1,2,3};
14     int b=1[a]; //这也对?
15 }           

如果看的够仔细的话,三个函数没什么不同就是对数组a[1]的不同(当然函数名除外).

gcc -S test.c 后:

 

 1     .file    "test.c"
 2     .data
 3     .align 4
 4 LC0:
 5     .long    1
 6     .long    2
 7     .long    3
 8     .text
 9     .globl    _hello1
10     .def    _hello1;    .scl    2;    .type    32;    .endef
11 _hello1:
12     pushl    %ebp
13     movl    %esp, %ebp
14     pushl    %edi
15     pushl    %esi
16     pushl    %ebx
17     subl    $16, %esp
18     leal    -28(%ebp), %edx
19     movl    $LC0, %ebx
20     movl    $3, %eax
21     movl    %edx, %edi
22     movl    %ebx, %esi
23     movl    %eax, %ecx
24     rep movsl
25     movl    -24(%ebp), %eax
26     movl    %eax, -16(%ebp)
27     addl    $16, %esp
28     popl    %ebx
29     popl    %esi
30     popl    %edi
31     popl    %ebp
32     ret
33     .globl    _hello2
34     .def    _hello2;    .scl    2;    .type    32;    .endef
35 _hello2:
36     pushl    %ebp
37     movl    %esp, %ebp
38     pushl    %edi
39     pushl    %esi
40     pushl    %ebx
41     subl    $16, %esp
42     leal    -28(%ebp), %edx
43     movl    $LC0, %ebx
44     movl    $3, %eax
45     movl    %edx, %edi
46     movl    %ebx, %esi
47     movl    %eax, %ecx
48     rep movsl
49     leal    -28(%ebp), %eax
50     movl    4(%eax), %eax
51     movl    %eax, -16(%ebp)
52     addl    $16, %esp
53     popl    %ebx
54     popl    %esi
55     popl    %edi
56     popl    %ebp
57     ret
58     .globl    _hello3
59     .def    _hello3;    .scl    2;    .type    32;    .endef
60 _hello3:
61     pushl    %ebp
62     movl    %esp, %ebp
63     pushl    %edi
64     pushl    %esi
65     pushl    %ebx
66     subl    $16, %esp
67     leal    -28(%ebp), %edx
68     movl    $LC0, %ebx
69     movl    $3, %eax
70     movl    %edx, %edi
71     movl    %ebx, %esi
72     movl    %eax, %ecx
73     rep movsl
74     movl    -24(%ebp), %eax
75     movl    %eax, -16(%ebp)
76     addl    $16, %esp
77     popl    %ebx
78     popl    %esi
79     popl    %edi
80     popl    %ebp
81     ret

只要看红色的行,我们可以看到25-27行与74-76行一样,说明hello1与hello3没什么不同,

效率一样。而49-52行比他们多了一行,所以*(a+1)比a[1]和1[a]要低一点。

 但是我们看下面的例子。

test1.c与test2.c:

View Code
 //1--------------
#include <stdlib.h>
void hello()
{
    int *a=(int*)malloc(sizeof(int)*3);
    int b=*(a+1);
    free(a);
}

 //2--------------
#include <stdlib.h>
void hello()
{
    int *a=(int*)malloc(sizeof(int)*3);
    int b=a[1];
    free(a);
}

 

汇编后完全一样:

View Code
 1     .file    "main.c"
 2     .text
 3     .globl    _hello
 4     .def    _hello;    .scl    2;    .type    32;    .endef
 5 _hello:
 6     pushl    %ebp
 7     movl    %esp, %ebp
 8     subl    $40, %esp
 9     movl    $12, (%esp)
10     call    _malloc
11     movl    %eax, -12(%ebp)
12     movl    -12(%ebp), %eax
13     movl    4(%eax), %eax
14     movl    %eax, -16(%ebp)
15     leave
16     ret
17     .def    _malloc;    .scl    2;    .type    32;    .endef

  所以在堆中使用*(a+n)与a[n]没什么不同,只用在栈中才会有所不同。

  学习汇编不是必要,但是它可以让我们知道效率。

 

转载于:https://www.cnblogs.com/wuchaofan/archive/2013/04/19/3031749.html

32、C 语言与汇编语言中的算术运算及数组操作 本文深入探讨了C语言与汇编语言中的算术运算、数字转换以及数组操作,通过具体代码示例分析了底层数据处理机制。内容涵盖除法运算实现、数组传递与操作、函数编写实践以及性能优化技巧,帮助读者理解编程语言底层原理并提升实践能力。 阅读详情

相关推荐

物联网技术(AIR780E cat1-4G模块+小程序+腾讯云MQTT)驱动的智能井盖系统设计(连载01)

终端设备采用AIR780E模块作为主控器,电子模块有三轴加速度传感器、可燃气体传感器,AIR780E模块(4G模块)通过MQTT通信协议进行数据打包上传至EMQX服务器,在EMQX服务器中,用户可以自行订阅主题和发布主题,小程序通过MQTT通信协议订阅EMQX服务器的主题,服务器通过接收到硬件发布的数据,转发到微信小程序。

leida_3669的博客 2218

汇编学习--数组

数组是相同数据类型的元素的集合,它们的内存中按顺序连续存放在一起。在汇编状态下访问数组一般是通过基址加变址寻址实现的。 0x01 先找一个数组访问的C语言代码 #include<stdio.h> int main() { static int a[3]={0x11,0x22,0x33}; int i...

gclome的博客 1万+

若依(RuoYi)项目里,Quartz定时任务踩坑实录:并发控制、事务回滚与异常处理

本文深入解析若依(RuoYi)项目中Quartz定时任务的并发控制、事务回滚与异常处理三大核心问题。通过实战案例揭示@DisallowConcurrentExecution注解的局限性和Redis分布式锁的应用,详细讲解Spring事务集成方案及多数据源事务管理,并提供生产级监控体系搭建指南,帮助开发者规避Quartz在生产环境中的常见陷阱。

weixin_28731223的博客 412

C语言与汇编语言对照分析

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34239592的博客 4219

避坑指南:华为2288H-V5服务器安装系统时常见的RAID与驱动问题解决方案

本文针对华为2288H-V5服务器在安装系统时常见的RAID与驱动问题,提供了详细的避坑指南。文章深度解析了从BIOS版本兼容性核查、RAID配置实战到驱动加载与集成的全流程,重点解决了安装过程中因RAID控制器驱动缺失或兼容性问题导致的硬盘无法识别等典型故障,帮助用户高效完成系统部署。

weixin_29240711的博客 980

VS2019 从零构建 OSG+OSGEarth+OSGQt 开发环境实战指南

本文提供了一份详细的实战指南,指导开发者如何在Windows系统下使用VS2019从零开始编译和配置OSG、OSGEarth与OSGQt开发环境。文章涵盖了从环境准备、源码获取、CMake配置、Visual Studio编译到最终测试的完整流程,并分享了关键的避坑技巧,旨在帮助三维GIS与可视化开发者高效搭建稳定、可控的专业开发平台。

weixin_28826961的博客 367

汇编语言中数组的应用

TITLE the USE OF ARRAY ;**************************************************************** ;对程序运行平台的最小要求,也就是说程序使用的指令集合 .386 ;程序运行模型,flat指的是数据段和代码段共同使用一个4GB的内存, ;而stdcall指的是函数调用时使用的是自右向左压入堆栈的方式,同时函数

dasgk的专栏 9002

计算机视觉与深度学习实战:以Python为工具,基于帧间差法进行视频目标检测

计算机视觉是一门研究如何使机器从数字图像或视频中提取、分析和理解有用信息的学科。它涉及图像处理、计算机图形学、人工智能等多个领域的知识。通过计算机视觉技术,我们可以实现图像的识别、分类、目标检测等功能。本文介绍了计算机视觉与深度学习的基本概念和原理,并以Python为工具,基于帧间差分法实现了视频目标检测。帧间差分法具有算法实现简单、程序设计复杂度低、对光线等场景变化不太敏感等优点,因此在实际应用中得到了广泛的应用。然而,帧间差分法也存在一些局限性,如对于缓慢移动或静止的物体检测效果不佳。

一个好知识的传播者 1256

使用汇编语言完成下列C的数组赋值,汇编中的数组分配和指针的实现代码

数组简介如果各位猿友是一路跟着LZ看到这里的,那么数组的定义就非常简单了,它就是一个相同数据类型的数据集合。数组存储在一系列逻辑上连续的内存块当中,之所以说是逻辑上连续,是因为整个内存或者说存储器本身就是逻辑上连续的一个大内存数组。如果我们用Java语言的类型来表示我们的存储器的话,可以看做是byte[] memory这样的类型。数组的定义非常简单,它遵循以下这样简单的规则。T N[L];这当中T...

weixin_42168265的博客 2107

学习笔记7--激光雷达标定

本系列博客包括6个专栏,分别为:《自动驾驶技术概览》、《自动驾驶汽车平台技术基础》、《自动驾驶汽车定位技术》、《自动驾驶汽车环境感知》、《自动驾驶汽车决策与控制》、《自动驾驶系统设计及应用》,笔者不是自动驾驶领域的专家,只是一个在探索自动驾驶路上的小白,此系列丛书尚未阅读完,也是边阅读边总结边思考,欢迎各位小伙伴,各位大牛们在评论区给出建议,帮笔者这个小白挑出错误,谢谢! 此专栏是关于《自动驾驶汽车环境感知》书籍的笔记。 2.激光雷达标定 2.1 概述 激光雷达内参标定:内部激光发射器坐标系与雷达本

FUXI_Willard 8027

mjlab 入门教程(一)MuJoCo 人形机器人强化学习训练 sim-to-real 部署框架

摘要:mjlab是一个结合IsaacLab API与MuJoCo简洁性的GPU加速机器人仿真框架,专为强化学习和机器人研究设计。它提供快速安装(支持uv、pip、conda和Docker)、核心功能(域随机化、NaN守护、观测历史/延迟、执行器/传感器系统)以及从IsaacLab的迁移指南。相比IsaacLab,mjlab更轻量、启动更快,直接构建在MuJoCo Warp上,避免了Omniverse开销。其哲学强调裸机性能、开发者体验和核心领域专注,适合需要快速迭代和直接MuJoCo控制的用户,而Isaac

2506_90492529的博客 2726

c语言数组指针汇编,C语言中数组指针在汇编语言寻址方式中的应用

摘要:因高级语言不需要熟悉低层软件和硬件知识,所以学生有很大的学习兴趣,数组指针是C语言中的重点内容,学生们都能熟练掌握。而汇编语言因与硬件紧密相连,所以学生学习兴趣不大。为了更好的培养学生的学习兴趣,提高教学效率,本文通过分析数组指针与寻址方式的异同,提出了如何把寻址方式转化成数组指针来学习的方法。中图分类号:TP312.1-4文献标识码:A 文章编号:1007-9416(2012)04-000...

weixin_39775577的博客 559

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

在汇编中引用C语言中的数组

在汇编中引用C语言中的数组,要先取出数组的地址,利用  基址+索引 访问数组中的元素,如:    int arrary[5]={1,2,3,4,5};  lea eax,arrary; //取出数组arrary在内存中的地址  mov edx,2;     //取出数组arrary中某元素的下标  mov ebx,[eax+edx*4];    //取出数据arrary[1],

friendan的专栏 5349

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

C语言反汇编_数组和结构体

C语言反汇编_数组与结构体 文章目录C语言反汇编_数组与结构体@[toc]0 . 说明1.数组1.数组对应堆栈空的分配2.数组的寻址1.一维数组2.二维数组3.三维数组3.数组的作为函数参数2.结构体 0 . 说明 ​ 看滴水逆向视频总结笔记 ​ 编译器VC++6.0 1.数组 1.数组对应堆栈空的分配 ​ 数组在汇编中的位置与普通局部变量有一些细节上的差异,一般局部变量都是从栈底依次分配到栈底,...

qq_35289660的博客 1344

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

c语言的汇编表示(指针数组和数组指针)

c语言的汇编表示(指针数组和数组指针) c的两大支柱:数组和指针,优良的继承并发扬了它的爹的两大特性:地址加偏移。 什么是数组 那就得先说明什么是数组 当我们定义了一个数组时,虽然没有赋值,编译器已经给我们划分好了空间 int main() { int a[10]; printf("%d", sizeof(a));//结果为40,情理之中 } 此时数组里面的值都是垃圾数据,比如a[0]=4011276318,如果开启了缓冲区溢出检查的话,编译器还会爆异常 所以数组就是在栈中从上到下依次排序的相同变量

sanqiuai的博客 867

sizeof结构体数组长度_从c语言到汇编(五)数组中的结构体

数组可以由结构体构成,这里讨论两种情况:数组的元素是结构体,数组的元素是结构体指针。数组的元素是结构体。struct obj { char sex; int old; int weight; int height; }; int fun(void) { struct obj objs[10]; in...

weixin_39929635的博客 1100

C编译器剖析_1.5 结合C语言来学汇编_指针、数组和结构体

让我们再来看一份C代码,及其经UCC编译器编译后产生的主要汇编代码,如图1.33所示,其中包含了数组、指针和结构体。 图1.33 数组、指针和结构体      按照C的语义,图1.33第9行的C代码是对局部数组number的初始化,需要把number[0]初始化为2015,而数组中的其他元素皆被初始化为0。UCC编译器采取的翻译方法是:先调用memset函数来把数组number所占的内

SheIsC的专栏 1753

c语言字节汇编代码,C语言中的数组和指针汇编代码分析实例

今天看《程序员面试宝典》时偶然看到讲数组和指针的存取效率,闲着无聊,就自己写了段小代码,简单分析一下C语言背后的汇编,可能很多人只注重C语言,但在实际应用当中,当出现问题时,有时候还是通过分析汇编代码能够解决问题。本文只是为初学者,大牛可以飘过~C源代码如下:#include "stdafx.h"int main(int argc, char* argv[]){char a=1;char c[] ...

weixin_33600816的博客 398

笔记 | 理解C/汇编中的数组元素访问

通过对C语言中数组访问的理解,理解汇编中对数组元素的访问,需求场景:PE可执行文件解析,从导出函数数组中,访问目标函数

JUST FOR FUN, CALM DOWN 720

c语言清空结构体数组_从c语言到汇编(五)数组中的结构体

数组可以由结构体构成,这里讨论两种情况:数组的元素是结构体,数组的元素是结构体指针。数组的元素是结构体。struct obj { char sex; int old; int weight; int height; }; int fun(void) { struct obj objs[10]; in...

weixin_39710249的博客 1104

ARM汇编和C语言混合编程中数组的数组的操作

ARM汇编和C语言混合编程中数组的数组的操作 此示例描述a数组中的元素累加的结果,c和b交换的实例: ·by fulinux(blog.youkuaiyun.com/fulinus) 代码块 例如: #include &amp;amp;amp;amp;amp;lt;stdio.h&amp;amp;amp;amp;amp;gt; int main (int argc, char **argv) { int a[4] = {1, 2, 3, 4}; int ...

fulinux的博客 4416

C语言中的数组和指针汇编代码关系分析

今天看《程序员面试宝典》时偶然看到讲数组和指针的存取效率,闲着无聊,就自己写了段小代码,简单分析一下C语言背后的汇编,可能很多人只注重C语言,但在实际应用当中,当出现问题时,有时候还是通过分析汇编代码能够解决问题。本文只是为初学者,大牛可以飘过~ #include “stdafx.h” int main(int argc, char* argv[]) { char a=1; char c[] = "1234567890"; char *p = "1234567890"; a =

u011159820的博客 502

C语言数组作为函数参数时长度信息去哪儿了?(深入汇编层解析)

解析C语言中数组作为函数参数的长度丢失问题,深入汇编层揭示形参退化为指针的本质。涵盖实际应用场景与保持长度的常用策略,助你掌握底层原理与应对方法,值得收藏。

BreakVein的博客 683
上一篇: ns-3介绍与安装
下一篇: UEFI与FAT
Sight2012
博客等级 码龄12年 1粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值