PIC8 位单片机汇编语言常用指令的识读 ( 上 ) 各大类单片机的指令系统是没有通用性的, 它是由单片机生产厂家规定的, 所以用户必须遵循厂家规定的标准, 才能达到应用单片机的目的 PIC 8 位单片机共有三个级别, 有相对应的指令集 基本级 PIC 系列芯片共有指令 33 条, 每条指令是 12 位字长 ; 中级 PIC 系列芯片共有指令 35 条, 每条指令是 14 位字长 ; 高级 PIC 系列芯片共有指令 58 条, 每条指令是 16 位字长 其指令向下兼容 在这里笔者介绍 PIC 8 位单片机汇编语言指令的组成及指令中符号的功能, 以供初学者阅读相关书籍和资料时快速入门 一 PIC 单片机汇编语言指令格式 PIC 系列微控制器汇编语言指令与 MCS-51 系列单片机汇编语言一样, 每条汇编语言指令由 4 个部分组成, 其书写格式如下 : 标号操作码助记符操作数 1, 操作数 2; 注释 指令格式说明如下 : 指令的 4 个部分之间由空格作隔离符, 空格可以是 1 格或多格, 以保证交叉汇编时,PC 机能识别指令 1 标号与 MCS-51 系列单片机功能相同, 标号代表指令的符号地址 在程序汇编时, 已赋以指令存储器地址的具体数值 汇编语言中采用符号地址 ( 即标号 ) 是便于查看 修改, 尤其是便于指令转移地址的表示 标号是指令格式中的可选项, 只有在被其它语句引用时才需派上标号 在无标号的情况下, 指令助记符前面必须保留一个或一个以上的空格再写指令助记符 指令助记符不能占用标号的位置, 否则该助记符会被汇编程序作标号误处理 书写标号时, 规定第一字符必须是字母或半角下划线, 它后面可以跟英文和数字字符 冒号 (:) 制符表等, 并可任意组合 再有标号不能用操作码助记符和寄存器的代号表示 标号也可以单独占一行 2 操作码助记符该字段是指令的必选项 该项可以是指令助记符, 也可以由伪指令及宏命令组成, 其作用是在交叉汇编时, 指令操作码助记符 与 操作码表 进行逐一比较, 找出其相应的机器码一一代之 3 操作数由操作数的数据值或以符号表示的数据或地址值组成 若操作数有两个, 则两个操作数之间用逗号 (,) 分开 当操作数是常数时, 常数可以是二进制 八进制 十进制或十六进制数 还可以是被定义过的标号 字符串和 ASCⅡ 码等 具体表示时, 规定在二进制数前冠以字母 B, 例如 B10011100; 八进制数前冠以字母 O, 例如 O257; 十进制数前冠以字母 D, 例如 D122; 十六进制数前冠以 H, 例如 H2F 在这里 PIC 8 位单片机默认进制是十六进制, 在十六进制数之前加上 Ox, 如 H2F 可以写成 Ox2F 指令的操作数项也是可选项 PIC 单片机与 MCS-51 系列 8 位单片机一样, 存在寻址方法, 即操作数的来源或去向问题 因 PIC 系列微控制器采用了精简指令集 (RISC) 结构体系, 其寻址方式和指令都既少而又简单 其寻址方式根据操作数来源的不同, 可分为立即数寻址 直接寻址 寄存器间接寻址和位寻址四种 所以 PIC 系列单片机指令中的操作数常常出现有关寄存器符号 有关的寻址实例, 均可在本文的后面找到 4 注释用来对程序作些说明, 便于人们阅读程序 注释开始之前用分号 (;) 与其它部分相隔 当汇编程序检测到分号时, 其后面的字符不再处理 值得注意 : 在用到子程序时应说明程序的入口条件 出口条件以及该程序应完成的功能和作用 二 清零指令 ( 共 4 条 ) 1 寄存器清零指令实例 :CLRW; 寄存器 W 被清零 说明 : 该条指令很简单, 其中 W 为 PIC 单片机的工作寄存器, 相当于 MCS-51 系列单片机中的累加器 A,CLR 是英语 Clear 的缩 写字母
2 看门狗定时器清零指令 实例 :CLRWDT; 看门狗定时器清零 ( 若已赋值, 同时清预分频器 ) 说明 :WDT 是英语 Watchdog Timer 的缩写字母 CLR 见上述说明 注意该两条指令无操作数 3 寄存器 f 清零指令 指令格式 :CLRF f 实例 :CLRF TMRO; 对 TMRO 清零 说明 : 在 PIC 系列 8 位单片机中, 常用符号 F( 或 f) 代表片内的各种寄程器和 F 的序号地址 F 取值按 PIC 系列不同型号而不同, 一般为 Ox00~Ox1F/7F/FF TMRO 代表定时器 / 计数器 TMRO, 所以 CLRF 对寄程器清零, 采用了直接寻址方式直接给出要访问的寄存器 TMRO 4 位清零指令 指令格式 BCF f,b 实例 :BCF REG1,2; 把寄存器 REG1 的 D2 位清零说明 :BCF 是英语 Bit Clear F 的缩写 指令格式中的 F, 同上说明 ; 符号 b 是表示 PIC 片内某个 8 位数据寄存器 F 的位号 ( 或位地址 ), 所以 b 的取值为 0~7 或 D0~D7 实例中 REG 是 Register 的缩写 实例中的 2 代表指令格式中的 b=2 即寄存器 REG1 的 D2 位 通过上述四条清零指令格式和实例, 可以说明, 学习 PIC 系列 8 位单片机的指令时应首先了解指令的助记符意义 ( 功能 ), 再 有就是它的表达方式 初学者没有必要死记指令, 重要是理解和实践 三 面向字节 常数与控制操作的指令 1 传送立即数至工作寄存器 W 指令指令格式 :MOVLW k;k 表示常数 立即数和标号说明 :MOVLW 是 Move Literal to w 的缩写实例 :MOVL 0x1E; 常数 30 送 W 2 I/O 口控制寄存器 TRIS 设置指令指令格式 ;TRIS f 说明 ;TRIS f 是 Load TRIS Register 的缩写 其功能是把工作寄存器 W 的内容送入 I/O 口控制寄存器 f 当 W=0 时, 置对应 I/O 口为输出 ;W=1, 置 I/O 口为输入 实例 :MOVLW 0x00 ; 把 00H 送入 W TRIS RA ; 置 PIC RA 口为输出 MOVLW 0xFF ; 把 FFH 送入 W TRIS RB ; 置 PIC RB 口为输入 说明 : 这是 PIC 汇编语言中常用的几条指令, 即设置某个 I/O 口 ( 这里是 RA 口和 RB 口 ) 为输入或输出的语句 可见, 识读指令时, 一应充分理解语句格式的功能, 二应前后联系阅读 3 W 寄存器内容送寄存器 f(w 内容保持不变 ) 指令指令格式 :MOVWF f 说明 :MOVWF 是 Move W to f 的缩写实例 :MOVLW 0x0B; 送 0BH 送 W MOVWF 6 ; 送 W 内容到 RB 口 说明 : 第一条指令 0x0B( 常数 11) 送工作寄存器 W, 第二条指令, 把 W 内容常数 11 送到寄存器 F6 中, 查表 F6 即为 RB 口, 所以 P ORT_B(B 口 )=0BH=D11 4 寄存器 f 传送指令指令格式 :MOVF f,d 说明 :MOVF 是 Move
f 的缩写 F 代表 PIC 中的某个寄存器 指令中的 d 规定 :d=0 时,f 内容送 W;d=1 时,f 内容送寄存器 实例 :MOVF 6,0 ;RB 口内容送 W MOVWF 8 ;RB 口内容送 f8 说明 : 第一条指令中的 6 代表寄存器 f=6, 查寄存器表 f=6 为 RB 口 ;0 代表 d=0, 代表选择的目标为寄存器 W 第二条指令中的 8 代表寄存器 f=8 所以两条指令结果是把 RB 口的内容送 f8 至于 f8 内容是多少? 还应在汇编语言开始时附加指令, 这里从略 5 空操作指令指令格式 :NOP 说明 :NOP 是英语 No Operation 的缩写 NOP 无操作数, 所以称为空操作 执行 NOP 指令只使程序计数器 PC 加 1, 所以占用一个机器周期 实例 :MOVLW 0xOF ; 送 OFH 到 W MOVWF PORT_B ;W 内容写入 B 口 NOP ; 空操作 MOVF PORT_B,W ; 读操作 说明 : 该三条指令是一种对 I/O 口的 B 口连续操作的实例, 其目的达到写入 B 口的内容要读出时, 应保证写 读之间有个稳定时间, 因此加入了空操作指令 NOP 6 无条件跳转指令指令格式 :GOTO k 说明 : 执行该条指令时, 将指令转移到指定的地址 ( 跳转 ) 指令中的 k, 常与程序中的标号联系起来 实例 : 见第 9 条指令中 7 寄存器内容减 1, 结果为零的间跳指令指令格式 :DECFSZ f,d 说明 :DECFSZ 是英语 Decrement f,skip of not 0 的缩写 符号 f,d 代表的意义, 前述已作说明 该条指令是指寄存器的内容减 1 存入 W(d=0) 或 f(d=1) 中 若指令执行结果减 1 不为零, 指令顺序执行 ; 为零时, 就间跳下一条指令后再执行 ( 等效顺序执行一条空指令 NOP), 实际指令中, 当 d=1 时, 该项常被略去 8 寄存器内容加 1, 结果为零间跳指令指令格式 :INCFSZ f,d 说明 :INCFSZ 是英语 Increment f,skip of 0 的缩写 该条指令与上一条 (7) 指令差别仅在于 1 上, 即执行这条指令时, 寄存器 f 内容加 1, 若结果不为零, 则指令顺序执行 ; 为零则指令间跳执行 执行这条指令的其它逻辑关系与上条相同 9 子程序返回指令指令格式 :RETLW k 说明 :RETLW 是 Return Literal to W 的缩写 该指令代表子程序返回, 返回前先把 8 位立即数送 W 实例 :PIC 某个汇编语言的延时子程序 ( 摘要 ): (1)BELY MOVLW 0xC5 ; 送延时常数 0C5H 入 W (2) MOVWF COUNT2;0C5H 送入计数器 2 (3) CLRF COUNT1; 对计数器 1 清零 (4)LOOP INCFSZ COUNT1; 计数器 1 加 1 计数器 1 加 1 结果不为零, 跳转循环 (5) GOTO LOOP ; (6) DECTSZ CPUNT2 ; 计数 2 减 1 计数器 2 减 1 结果不为零, 跳转循环重复执行第 4 条指令
(7) GOTO LOOP ; (8) RETLW 0 ; 子程序执行结束返回 说明 : 程序中的注释已分别对每条指令的功能作了说明, 补充说明 1 当执行第 (4) 条加 1 指令结果为零时, 就间跳转到执行 第 (6) 条指令 2 当执行第 (6) 条减 1 指令结果为零时, 就间跳转到第 (8) 条子程序返回, 整个延时指令才算完成 3 计数器 1 或 2 代表 PIC 中某个寄存器, 该寄存器由程序开始的伪指令赋值决定 ( 关于伪指令今后将作专门介绍 ) 本文关于指令的注释将与前述指令中的略有不同 前述指令注释时是对指令具体完成的功能给以说明, 这种注释方法对初学者确实易于接受和理解, 但是实际应用中的 PIC 产品汇编语言的注释通常是以程序要做什么 ( 或指令的作用 ) 而不是说指令的直接功能 鉴于上述原因, 下述的指令注释将改变过去的注释方法, 用程序应起的作用作注释 10 寄程器半字节交换指令指令格式 :SWAPF f,d 说明 :SWAPF 是 Swap f 的合写 符号 f d 的意义与前述的相同 该条指令的功能是寄存器 f 的高 4 位与低 4 位交换, 即指令执行前, 若寄存器 f 的 8 位状态为 D7 D6 D5 D4 D3 D2 D1 D0, 执行后的 8 位状态变为 D3 D2 D1 D0 D7 D6 D5 D4, 其结果存入 W(d=0) 或 f(d=1) 中 实例 : 中断现场保护是中断技术中重要部分 由于 PIC16C 指令系统中没有进栈 PUSH 和出栈 POP 指令, 所以只能用其它指令来实现 因为在主程序中常常用到工作寄存器 W 和状态寄存器 STATUS, 所以中断现场保护常要保护寄存器 W 和 STAT US 下面是对 PIC16C7 系列芯片中断现场保护的实例程序 MOVWF W_TEMP ; 将 W 内容存入到临时寄存器 W_TEMP 中 SWAPF STATUS,W ; 交换 STATUS 与 W 内容 MOVWF STATUS_TEMP ; 将 STATUS 的内容存入到临 时寄存器 STATUS_TEMP 中中断服务程序 SWAPF STATUS_TEMP,W; 交换 STATUS_TEMP 与 W 的内容 MOVWF STATUS ;STATUS 复原成原来的状态 SWAPF W_TEMP,F ; 交换内容 SWAPF W_TEMP,W ;W 复原成原来的状态 说明 : 上述程序中各条指令的注释基本上都是以程序应达到的目的而注释的, 对每条指令的功能几乎未涉及 这是初学者应特别注意的 11 子程序调用指令 (Subroutine Call) 指令格式 :CALL k;k 为立即地址 说明 : 子程序调用, 不同型号芯片的实现方法不尽相同, 其共同点是首先将返回地址 ((PC)+1) 压栈保护, 再转入所调用的子程序入口地址执行 ( 与 MCS-51 指令功能相似 ) 指令格式模式 :HERE CALL DELAY; 调用延时子程序 DELAY MOVLW 0x80 ; 延时子程序 RETLW 0 说明 : 调用指令执行前,PC= 地址 HERE
调用指令执行后,PC= 地址 DELAY( 标号 ), 堆栈指针 TOS=HERE+1( 返回地址 ) 实例 : 见下条指令的实例 12 寄存器内容取反指令指令格式 :COMF f,d 说明 :COMF 是 Complement f 的缩写 其中 d=1 时, 操作 (f) f;d=0 时, 操作 (f) w 功能 : 寄存器 f 内容取反后送入 W(d=0) 或 f 自身 (d=1) 实例 : ORG 0x1FF GOTO MAIN ORG 0 DELAY MAIN MOVLW 0 ; 主程序开始 TRTS 5 ; 设置 RA 口为输出 BCF 5,0 ; 置 RA 口 0 位为 0 LOOP CALL DELAY; 闪动延时 COMF 5 ;RA 口求反 ( 亮 灭 亮 控制 ) GOTO LOOP ; 循环 说明 : 上述指令是一种 PIC16C54 LED 发光控制实验部分程序 其中延时子程序 DELY 未列出, 但不影响本条指令的识读 程序中的主程序开始的三条指令, 均已介绍过, 紧跟着的 CALL 指令是调用执行子程序, 其入口地址为标号 DELAY 子程序执行结束后, 又执行 COMF 5 的 LED 发光亮 灭 亮 灭 控制指令 后面一条 GOTO LOOP 指令是达到 LED 循环点亮目的 13 面向位的操作指令 ( 共 4 条,PIC 高级产品多增一条 ) 该类指令除一条位清零外, 另有一条寄存器 f 位 b 的置 1 指令和另外两条位跳步指令 (PIC 高级产品多增一条 f 的 b 位触发转换指令 ) (1) 位置 1 指令 指令格式 BSF f,b 说明 :BSF 是 Bit Set f 的缩写 F 和 b 的意义与前述相同, 该条指令的功能是将寄存器 f 的 b 位置 1 (2) 位测试 为零间跳指令 指令格式 BTFSC f,b 说明 :BTFSC 是 Bit Test,Skip if Clear 的缩写 指令功能是测试寄存器 f 位 b, 如为 0, 跳过下一条指令 ; 为 1 顺序执行, 即当 f(b)=0 时, 就不执行当前指令而执行下一条指令 ( 间跳 ), 即用一条空指令 NOP 代替它, 所以该条指令占用 2 个指令周期 (3) 位测试 为 1 间跳指令 指令格式 BTFSS f,b 说明 :BTFSS 是 Bit Test,Skip if Set 的缩写 其指令的逻辑功能与上条相反, 位测试 f(b)=1 就间跳执行,f(b)=0 顺序执行 上面介绍的 PIC 8 位单片机汇编语言指令仅是部分指令, 此外还有循环左 右移指令 ;W 和寄存器 f 相 加 相 与 指令和进入睡眠方式等指令 鉴于报纸版面的限制, 不在这里一一介绍, 今后将在程序的应用试验中再作补充说明