gentleman 发表于 2023-8-30 08:41:59

2023/08/22 第二十三集

   





   跳转太多了不好,会占用指令周期
   占用流水线
         
   JLE/JSL等判断Z或CY

   CJNEDJNE 这种是老朋友了 8051汇编就很常用的
   
   DJNZ 40H,LABEL1
   DJNZ 50H,LABEL2
   DJNZ 60H,LABEL

    RAM0X400X01
             0X500X70
             0X600X15
    执行后
            0X40 0X00
            0X50 0X6F
            0X60 0X14
      
   其实一般都用这两条做循环

               MOV R2,#8
   TOGGLE:CPL P1.7
                  DJNZ R2,TOGGLE

      NOP 空指令
             机器码 0
             1个时钟
             PC 指针+1

            有些库通过内嵌汇编 打到精准操作,给出精准的NOP

            
   汇编语言的程序设计
         
         keil的帮助手册可以去看看

         A251编译器          相对地址
         L251链接器         链接到绝对地址
         LIB251库,看不见         
         OH251   生成HEX文件的
                     



      

gentleman 发表于 2023-8-30 09:17:22

2023/08/22 第二十四集

    汇编语言程序设计
         汇编注重逻辑
         
         汇编程序是啥
                  是汇编语言助记符 + 汇编器助记符命令
         谁家的汇编都是这两部分
         
         汇编器助记符不翻译成机器指令

         例子1:
                  
            code 中的四个 立即数搬到edata里面

            用C来说 (应该对吧,自己是这样理解的)
            
            short code a = {0x13,0x0,0x2,0x4};
            short b;

            for(i = 0;i<4;i++)
            {
                      b = a;
               }

            汇编代码
         
            data_seg1 SEGMENT CODE                         ;声明个代码段
                           RSG         data_seg1                   ;用这个代码段
            
            TABLE:   DW          0x0123,0x4567,0x89ab,0xcdef         ;用DW 建个表 地址由链接器分频


            data_seg2 SEGMENT EDATA                         ;声明个edata段
                           RSG         data_seg2                   ;用这个edata段
            
            STORE:   DSW          4         ;整4个空间8个字节

            
            prog_seg SEGMENT CODE         ;    代码段
                     RSEGporg_seg                ;用代码段
                     LJMPmain                     ;跳主程序
                  ORG 0x0220                  ;跳过中断的区域
          main:
                   MOV             DPTR,#TABLE       ;指向表首地址
                   MOV             WR0,#STORE       ;把整个地址给寄存器
                   MOV            R4,#0x4             ;要循环的次数
         CON:
                   MOV            A,#0x0            ;      给累加器 0
                   MOVC      A,@A+DPTR         ;    开始指向第一个数据
                   MOV         R2,A               ;      放寄存器R2
                  INC               DPTR            ;          DPTR+1
                  MOV            A,#0X0         ;         又清0
                   MOV          A,@A+DPTR   ;            指向后8位
                   MOV         R3,A               ;   后8位放R3            由于R2 R3组成WR2
                   MOV          @WR0,WR2       ;    把WR2中 数据给WR0 中对应的地址
                   INC            DPTR             ;    指向code中下一个数据的地址
                   ADD         WR0,#0x2       ;    指向edata放下个放数据的地址
                   MOV            A,R4            ;R4是循环的次数
                   SUBB         A,#0x1         ;   A-1
                   MOV         R4,A                ;   A 放R4   
                   JNZ         CON                   ; 不为零就 跳CON里       这就相当于for循环
                  NOP                                  ;空指令

         为便于理解,给程序添加了逐行注释。

         segment段
               同名合并
               codedata 等
         

gentleman 发表于 2023-9-1 07:34:45

2023/08/25第二十五集
      何老师带着大家复习了一下上节课的汇编程序

      code ->edata

      查看c的反汇编语言

      数据先放到DR8 中
       由于不能操作32位
       分别放到WR8 WR10
       组成32位

      

       MOVWR6,@DR8+0x0006
       这里吧DR8 偏移6 搬到WR6寄存器
   
   


    MOVWR4,@DR8+0x0004
    MOVWR2,@DR8+0x0002

    MOVWR0,@DR8


      这是code区


    继续搬,可以看到把数据搬到了 这4个寄存器

   MOV@WR10+0x0010,WR4
   搬了最高的循环从4开始


   
   在监视窗口看到 搬了1个最高的数据到 STROE 中

DEC 给R7 -1
然后比较CMP R7 是否0
JNC 判断标志位 来决定是否跳转

后面3次循环与这次类似

这是这个搬移的过程 的反汇编分析


补充一下用到的几个指令

SEGMENT
      能用 下面这些段

   

   RSEG声明段
      
   DW初始化存储器

   前面都一样,后面用了32位拓展汇编指令

   MAIN:
            MOV DPTR,#TABLE
            MOV DPXL,#0FFH
            MOV WR0,#STROE
         MOVR4,#0x04
    CON:
            MOVWR6,@DR56
            MOV@WR0,WR6
            INCDR56,#2
            INCWR0,#2
            DECR4,#1
            JNE CON

      可看到 32位拓展的汇编指令能极大的 增加程序的简洁性
               8位的汇编要搬到AB来处理,AB 还只有有8位,增加了程序的复杂度
               
               

      








gentleman 发表于 2023-9-1 08:46:13

本帖最后由 gentleman 于 2023-9-1 08:53 编辑

2023/08/25 第二十六集
   MOV DPXL ,#01
          这条可以指向xdata区域

          开始时edta 区域

   EBIT
         扩展位可寻址

    EDATA HDATA
         这两个等效

   符号
      不能数字开头
      EQUSET
      LABEL:
   标号
         定义位置   作用跳转或提升可读性
         只能定义一次

   汇编器标号
         
   表达式与操作数
       vvvEQU 3
   数字
      记得字母前面加0
      可加$
   
         可用决定地址 (不完全可用,编译器不让,让用EDATA)
   字符
      不能超过2个
   字符串
      KEYMSG: DB 'SDFKLJSDLFKJSLDKFJ SDLJFL'
      EOLMSG: DB 'End of line', 00h
   位置计数器
      ORG 改初值
      $ 当前位置计数器
      JMP $
    优先级
      

   类操作符
   讲过好几次了

   类运算符
      
      
   
   
      
   
   
   

gentleman 发表于 2023-9-1 10:36:56

2023/08/25 第二十七集


控制语句
   不产生代码
      
   ALIGN位置计数器设置为下一个地址模2^表达式
               确保2^n 边界对齐
               51 不用 arm 得用用了有缝隙

    EVEN位置计数器指向下一个偶数

    ORG   这个太熟了   更改当前段 位置计数器为后续设置原点
            
            ORG 0200H

USING选用哪个寄存器组R0~R73组
            
             PUSH PSW
             MOV PSW,#(2 SHL 3)
             POP PSW

   EQU 定义AR0 要谨慎


DB
          MSG: DB 'PRESS A KEY',0
          TAB: DB2,3,4,5,6,7,';'

DD32位双字

DW2个字节
         
DBIT    段保留 几个位

DS /DSB   保留字节

DSD          32位双字(double)

DSW      16位

PROCENDP
               子程序
LABEL标号位置

EXTRN/EXTERN   多文件?必须public

PUBLIC      公共符号

CSEGCODE 绝对段

   CSEG AT0300H   我说这么眼熟中断号拓展用的这个指令

   ISEGIDATA段


   RSEG声明可重定义段 上节课的例子用了


SEGMENT
         
         
XSEG


BIT    指定位地址
            
CODE/DATA   定义地址
   
EQU   只能定义一次

sbit   能用再A251中         

SET创建新符号
         不能PUBLIC
   sfr    定义SFR

_ERROR_指定错误信息

   END       结束

   汇编接近尾声,c语言即将开始

      

gentleman 发表于 2023-9-2 08:47:41

2023/08/29 第二十八集


   条件汇编
         单个源文件   不同版本
   
   $
      
   
    有个例子   在编译器SET AA = 10

   使用$IF
            ...
            $ELSE
             ..
            $ENDIF
         
      通过keil调试 进行测试


       不带$
       直接使用AA SET 10 指令设置


    宏定义
          注意宏定义与子程序的区别
          宏适合做表不跳转,直接复制一份到下一行, 多次调用增加代码长度
          子程序跳转不增加代码长度


         A251 3种宏
               macro-name MACRO <[> parmeter-list <]
         <[> LOCAL local-labels <]>                     
          ... ...
         macro-body
          ... ...
          ENDM


         不调用 不展开


         例子
               

         


         
               


gentleman 发表于 2023-9-2 10:10:15

2023/08/29 第二十九集

      汇编实例 -点灯

         

          外设复用理念
                解决io不够用的问题
                传统跳线          麻烦
                晶体管 电压      好用

          I/O 寄存器
               端口寄存器
                      PXM0 PXM1
                      4种模式
                     上下设置,不是左右组合设置

               数据寄存器
                   PX.Y =0 低电平
                   PX.Y = 1 高电平
               
            
            程序要点
                   DATA 定义寄存器地址
                  
                  ORG 0x200前面给中断留着

                   MOV 寄存器复制

                   用 A 放循环移位初值

                   ACALL延时子程序

                   RL 移位

                   MOV 吧A 搬到 端口数据寄存器

                   延时子程序
                        SUBJNE 实现延时
                  
                   掌握这些,应该就可以独立完成流水灯的程序了。

                  配合调试可以更清晰的看到程序运行的过程。

gentleman 发表于 2023-9-2 10:23:12

2023/08/29 第三十集
       汇编实例-中断

      按下按键 灯移动一位

            

      按键按下io被拉低

      得出结论

            TCON.0=1
            TCON.2 =1
            EX0 = 1
            EX1 = 1
            EA = 1

      程序新增要点
            EQU 定义寄存器位

            ORG放中断入口

            中断子程序 实现RL/RR

         硬件/软件调试 判断是否进入中断

          这两节课的代码比较简单,在论坛上都有,就没有抄。

          到此mcs-251汇编就已经结束了,刚刚接触大量新增指令集的时候,确实很吃力。
          后面结合程序看,就好多了。
          当然现在也仅仅能看懂汇编,并不能完成汇编的程序设计。
          现阶段的目标也是能看懂汇编,配合c调试时生成的反汇编可以分析错误,分析底层逻辑。
          后面学习操作系统时,再来加强对汇编的理解。

            

gentleman 发表于 2023-9-9 14:39:57

本帖最后由 gentleman 于 2023-9-23 09:00 编辑



发现09/01 的课没有打卡,后面补上了

2023/09/05 第三十四集   
   C251 限定符
       const   运行未修改
       volatile   可能会被修改
            通常是硬件
      
      const 声明 的可以用xdata/code 指定存储位置 ,定义直接初始化

         const 指针 不能改他指向的常数
         普通指针 指向常数,改指向的值,不报错,也没效果

      特殊用法定义一个不可更改的指针

         

       volatile 不让编译器优化
            硬件寄存器不能给优化,优化了寄存器就没配置成功


      使用keil 调试,可以直观的看到这些变量定义与运算的过程


      
   
   单字 双字 直接MOV

      4字节 要MOV 两次
         


         
      
   

gentleman 发表于 2023-9-9 14:53:27

本帖最后由 gentleman 于 2023-9-23 09:00 编辑

2023/09/05 第三十五集



一开始就有干货
看到浮点定义的过程
这个要配合以前讲浮点数的内容理解

去掉volatile

就3行,被编译器优化了
编译器认为a b 没用
只记了结果

后面是个列表求和的例子

再次提到指令高速缓存概念


汇编帮助DEBUG


auto register static extern

这几个都很好理解






页: 1 2 [3] 4 5
查看完整版本: 【实验箱已收到】何老师 《STC32位8051单片机原理及应用-STC32G12K128》,打卡