找回密码
 立即注册
查看: 395|回复: 6

C/汇编理论探究 ·【指针的基本概念】

[复制链接]
  • TA的每日心情
    郁闷
    5 天前
  • 签到天数: 27 天

    [LV.4]偶尔看看III

    11

    主题

    23

    回帖

    88

    积分

    注册会员

    积分
    88
    发表于 2023-11-12 00:00:30 来自手机 | 显示全部楼层 |阅读模式
    ORG 0030H ;「整活😋」(跳过中断入口地址)
    现在的C语言如此强大,最离不开的就是指针。
    可以说任何语言都离不开指针,学习一种语言最深的领悟就是学会其指针的作用和工作原理。

    小辈无聊期间,搜寻了一下网上用汇编语言来形容C语言的例程,发现绝大多数不是用机器编译就是直接写底层寄存器之间的调用。看完后觉得不够直观,不能让大伙更直观的理解到C语言中的指针在汇编语言中类似于什么样的形式,所以本人自顾自的想要以浅薄的学识,用111条助记符的方式来解释一下指针的概念和原理。如有错误,还请各位长辈指出,莫要让新人学习了错误,误了事。

    如已经基本了解C语言指针 请跳转至分界线

    */& 是C语言中指针的定义符号。定义一个指针:int *p 可以将其想象为:*表示定义了一个小盒子🎁 &表示定义小盒子的位置(即地址)。那么用初中数学代数的概念,将*p代换过来,意思就是说p成为了一个小盒子🎁。如果这个时候有一个int类型的函数number,它的地址为0010h,值为5。想将它的地址赋值给*p,则需要用到&(取地址指针)即*p = &number;如此一来 小盒子🎁“p”的名字(数值)就与number的地址相同。即p=0010h;也就是说现在这个盒子🎁就变的跟number的地址相同了。那既然地址相同了,就代表盒子跟number的盒子一样了,那里面的值一样吗?如果想要将知道答案,我就需要用到先前说到的“ * ”指针(取数值);测试结果为*p = (number)= (0010h)= 5。
    在此 C语言中指针的概念就大致如此。

    即当定义*p=&number时 p的数值就等同于number的地址 如果想要知道number的值则需要将p中的值作为地址打开,将其中的数据拿出来,则为number的数据(汇编中通常将括号“ () ”看成 将其中的数值作为地址看待;格式中将“ #XX ”作为数据看作)。
    即*p=(number)= (0010h)= 5;
    p= number = 0010h 。
    (温馨提醒如果想知道定义后的指针地址,即&p。则要根据定义类型来思考。因为指针本身也需要地址来作为指向标,所以指针都会在所在数据地址的“前”方,具体前多少 需要看定义符号,如int则是4byte,即4*8=32bit(32位)因为一个地址能存储8位数据,所以真实指针的地址 在定义指针的前4个字节的位置,即前4H个的地址。
    如上所述,即&p = number-4H = (0010H-0004H)= 000CH
    (数据从小往大增加 前4个地址即为当前地址位减去4个地址,“十六进制数借1当16” )

    ////////////////////////////////////////////////////////////
    //////////////////////分界线//////////////////////////
    //////////////////////////////////////////////////////////

    现在大伙都已经明白了指针的基本概念,那我们来看看用汇编语言怎么描述基本的指针概念。

    在基本了解指针后,发现其无非就是“取地址,取数据(取数值)”。那么我们在汇编语言111条指令中就需要用到“ @ ”符号,@符号表示将当前函数的地址打开 将里面的内容,即数据,再次作为新的地址,再从其新地址中把数据取出。
    脑子烧了吧…哈哈,其实就是这意思:
    【在汇编语言中@能使用的通用寄存器Ri就只有R0和R1。即地址00H,01H(低128B第0组通用寄存器R0/R1地址,可在8051微机原理中了解)】
    MOV 30H,#0FFH
    MOV R0,30H
    MOV A,@R0
    此程序就是将R0中的数据作为新地址,又因为R0本身地址为00H 则需要先打开R0地址然后再打开其中的地址
    即:
    ((R0))= ((00H))经打开一次后
    ((00H))—> (30H)再打开一次后
    (30H)—> 0FFH
    【所以可以理解成“ MOV A,@R0 ”这条指令就是把数据#0FFH 传送给了累加器A(高128B特殊寄存器 地址0E0H;;;需要注意的是汇编语言中“ # ”符号仅在程序中才作为数据,在注释描述中只是为了方便读者理解其为数字 而非地址 才使用的】

    以上就是汇编助记符指令描述C语言指令的基本概念啦~^_^😋 当然这只是作为指令操作概念来理解的。
    【如果想要理解 汇编指令指针在单片机的RAM中是怎么动作的需要引入真正意义上的指针 即“ SP ”堆栈指针 和 “ DPTR ”数据指针。但单片机操作最多的指针就是SP,这个东西很复杂 主要就是完完全全的描述 各条指令是怎么工作的 比如中断触发后 子程序调用后 单片机是怎么工作的。有些许复杂,我还没捋好思路怎么讲出来,如果各位前辈或汇编爱好者想了解的,可以留言,我会抽时间整理一下。】
    以上就是我所想让大家理解汇编语言指针的操作概念,希望大家喜欢👀😋
    END ;(程序结束)
    C语言指针概念描述 参考B站 BV1Gi4y1w7yG。
    IMG_6730.png
    IMG_6764.png
    IMG_6763.png
    LED点亮世界🇨🇳
    回复 送花

    使用道具 举报

  • TA的每日心情
    郁闷
    5 天前
  • 签到天数: 27 天

    [LV.4]偶尔看看III

    11

    主题

    23

    回帖

    88

    积分

    注册会员

    积分
    88
     楼主| 发表于 2023-11-13 00:48:05 来自手机 | 显示全部楼层
    8051部分特殊寄存器地址
    8051位寻址地址
    IMG_6739.jpeg
    IMG_6740.jpeg
    LED点亮世界🇨🇳
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    5 小时前
  • 签到天数: 187 天

    [LV.7]常住居民III

    0

    主题

    90

    回帖

    797

    积分

    高级会员

    积分
    797
    发表于 2023-11-16 00:17:03 | 显示全部楼层
    学习了
    回复 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 11:08
  • 签到天数: 123 天

    [LV.7]常住居民III

    10

    主题

    604

    回帖

    1022

    积分

    金牌会员

    积分
    1022
    发表于 2024-1-26 10:45:34 | 显示全部楼层
    指针就是变量的地址,不同类型的变量对应地址的“”宽度“”不一样。
    先学汇编在学C理解起来很简单,单纯学C就是不容易理解。
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    前天 08:40
  • 签到天数: 132 天

    [LV.7]常住居民III

    9

    主题

    92

    回帖

    630

    积分

    高级会员

    积分
    630
    发表于 2024-3-3 12:50:39 来自手机 | 显示全部楼层
    我认为的指针实际就是一个内存地址,定义时用*P代替而己,而且是定义变量时指向变量在内存的首地址,然后可以用+1调用后面的地址,如果调用不当可以超出变量范围而调用错误数据,循环取数据的过程中指针地址也会变化的,所以指针就是方便取内存数据而设计的直接指向内存地址的命令,
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    20

    主题

    580

    回帖

    1231

    积分

    荣誉版主

    积分
    1231
    发表于 2024-3-3 17:13:35 | 显示全部楼层
    本帖最后由 tzz1983 于 2024-3-3 17:20 编辑

    简单点来理解, C语言的指针包含两个信息:
    1. 地址
    2. 这个地址存放了什么类型的数据

    指针类型  实际上是指针指向的地址存放的数据的类型, 比如字符型指针,  整形指针.

    指针自身的宽度  和硬件相关, 比如 51内核的IDATA最多256字节, 8位足够表示所有地址  (idata *)指针自身的宽度是8位.   

    不同类型指针之间的强制转换规则  地址不变, 指向的数据类型改变.   比如  int a=0x3355;  int * pt=&a;  char b = *((char *)pt);  //结果是 b=0x33;  地址不变, 因为C51是高字节存在前面, 只读1字节char 即读到的数据是0x33

    指针是一个二进制的地址, 所以任何指针都可以转换为整形数据, 前提是整形的宽度容得下指针.  反过来 整形亦可转换为指针, 比如  int *pv = 0x3366;

    有两种特殊的指针:
    1.  void* 指针, 这种指针只包含地址, 没有说明这个地址上放的是什么类型的数据,  所以用这个指针前要先转换为有类型的指针再使用,  接上例  void * p = &a;    如果直接 int c =*p; 编译器报错, 编译器表示我不知道地址P内存的是什么数据. 正确的语句是 int c = *((int*)p);
    2. 函数指针.  函数经编译器编译过后就是一段汇编代码, 代码需要存在ROM内, 所以函数也是有地址的.  函数指针就是指向函数的指针,  函数除了有地址外, 还有形参格式, 所以函数指针也包含这类信息. 比如定义函数指针时, 需要用这样的书写格式:
    int (*f) (int x); /* 声明一个函数指针 */  即声明指针的同时,也要声明形参格式.

    回复 支持 1 反对 0 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 11:08
  • 签到天数: 123 天

    [LV.7]常住居民III

    10

    主题

    604

    回帖

    1022

    积分

    金牌会员

    积分
    1022
    发表于 2024-3-3 20:29:03 | 显示全部楼层
    要想好好从原理上学习、体验指针,可以用C写功能,编译为汇编来理解。
    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-6-2 05:48 , Processed in 0.064836 second(s), 56 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表