微机原理程序示例Microcomputer Systems

3 篇文章 0 订阅
3 篇文章 0 订阅

前言

本文代码一部分为完整可运行代码,另一部分仅为片段不可运行。
仅为学习过程笔记,所以并非全部完整。
每个示例后面都会说明代码是否完整,供运行参考

示例一

内存存储示例-不完整程序-不可运行
DATA SEGMENT        ;定义数据段区域
NAMES DB 'TOM..', 20    ;DB(Define Byte):定义的变量为字节型 指向的每一个操作数占1个字节单元
      DB 'CATE', 25
DATA ENDS

以上数据区在内存中是如何存储的?


解释

变量在内存中的存储(16进制表示)

每个字符在内存中以ASCII码表示,占用1B

NAMES开始

54

'T'

4F

'O'

4D

'M'

2E

'.'

2E

'.'

14

20(十进制)

无间隙

43

'C'

41

'A'

54

'T'

45

'E'

19

25(十进制)

示例二

字符串输出示例-完整程序-可运行
DATA SEGMENT      ;定义数据段区域
    A DB '123ABC' ;定义变量 A 的值为123ABC   定义字符串必须用DB伪指令
DATA ENDS         ;DB(Define Byte):定义的变量为字节型 指向的每一个操作数占1个字节单元     

CODE SEGMENT      ;定义数据段区域
ASSUME CS:CODE,DS:DATA   ;说明所定义逻辑段(DATA、CODE)的性质。设定段寄存器(CS、DS)为指令助记符

START:MOV AX,DATA     ;除代码段之外的其他段寄存器的初始化 设置段基地址  代码段会自己初始化
      MOV DS,AX
      LEA BX,A      ;把变量A的偏移地址的值送给了BX 
      MOV CX,6  
      
   LP:MOV AH,2     ;功能号传送,功能号为2,单字符显示输出功能 出口参数:屏幕 入口参数:DL的值
      MOV AL,[BX]   ;由[BX]的值可得第一次传送即为A+0地址的内容,也就是字符1 (ASCII码31H)
      XCHG AL,DL
      INC BX
      INT 21H    ;系统功能调用的DOS软中断指令(大功能包,包含多个子功能)调用,中断类型码固定为21H 
      LOOP LP       ;LOOP循环的次数和CX有关 这里的LOOP自动减一并判断是否为0
      MOV AH,4CH
      INT 21H    ;程序执行完该2条语句后能正常返回OS 常位于程序结尾处
 CODE ENDS
      END START

解释

存储内容

地址

A开始

1

0000H

2

0001H

3

0002H

'A'

0003H

'B'

0004H

'C'

0005H

示例三

段间间接转移示例-不完整程序-不可运行
DATA SEGMENT      ;定义数据段区域
    TABLE DW 3400H,5600H,2300H,4500H,2300H,1200H,2344H,3500H;定义变量 TABLE 的值
DATA ENDS         ; DW (Define Word) :定义的变量为字类型 指向的每一个操作数占1个字单元 

CODE SEGMENT      ;定义数据段区域
ASSUME CS:CODE,DS:DATA   ;说明所定义逻辑段(DATA、CODE)的性质。设定段寄存器(CS、DS)为指令助记符

START:MOV AX,DATA     ;除代码段之外的其他段寄存器的初始化 设置段基地址  代码段会自己初始化
      MOV DS,AX
      MOV BX,OFFSET TABLE  ;把TABLE的偏移地址存入BX中
      MOV SI,06H
    A:JMP DWORD PTR[BX+SI+2]   ;段间间接转移

     ;后方为存储器操作数(带方括号)形式,所以为间接转移,转移的目标地址在内存中
     ;PTR说明了存储器操作数的字长DWORD为32位存储器操作数,也就是包含段地址和偏移地址,所以为段间转移
     ;综上为段间间接转移    
     ;[BX+SI+2]基址变址相对寻址:基址寄存器内容+变址寄存器内容+位移量
     ;基址寄存器为BX,默认在数据段 (BP则为堆栈段)

     ;所以转移目标地址存放在内存数据段,偏移地址为BX+SI+2所指向的区域起始四个单元中
     ;因为SI=06H,所以转移目标地址就保存在TABLE+6+2=TABLE+8的字单元中

     ;低地址单元存放转移目标的偏移地址,高地址单元存放的是转移目标的段基地址
     ;TABLE+8开始的四个字节都是目标地址,回看数据段TABLE+0的字单元内容是3400H
     ;TABLE+2的字单元内容是5600H,TABLE+8的字单元内容是2300H (注意这里说的是字单元)

     ;32位计算机:1字=32位=4字节 64位计算机:1字=64位=8字节
     :8086是16位处理器,1字=16位=2字节,而一字节固定等于8bit=两个十六进制位置,也就是XXH

     ;回到原问题,所以偏移地址就是2300H,段基地址就是1200H
     ;TABLE的数据存放由低到高,图示中则为由上到下
      ...

程序执行完标号为A 的指令后:CS=(2300H)IP=(1200H)


解释

存储内容

地址

解释

存储内容

地址

TABLE开始

00H

0000H

一字节内容

00H

0008H

34H

0001H

23H

0009H

先存低位后存高位

00H

0002H

一个字内容

(16位)

00H

000AH

56H

0003H

12H

000BH

前数值在低位

后数值在高位

00H

0004H

44H

000CH

23H

0005H

23H

000DH

00H

0006H

00H

000EH

45H

0007H

35H

000FH

示例四

字符串比较示例-不完整程序-不可运行
此后开始,基础的注释将减少,可以参考前面的示例。
DATA SEGMENT
    STR1 DB ‘HELLO WORLD!‘
    STR2 DB ‘HELLO WOOLD!’
    COUNT DW 12    ;16位
    FLAG DB ?
DATA ENDS

CODE SEGMENT
    ASSUME CS: CODE, DS: DATA, ES: DATA    ;DATA既是数据段又是附加段
START: MOV AX, DATA    ;除代码段之外的其他段寄存器的初始化 设置段基地址  代码段会自己初始化
    MOV DS, AX
    MOV ES, AX          ;同时初始化两个段

    LEA BX, FLAG
    LEA SI, STR1    ;源串的指针
    LEA DI, STR2    ;目标串的指针
    MOV CX,COUNT  ;串长度值必须送给CX,因此数据段定义COUNT为DW字变量,因为要传送给CX,令字长相等
    CLD        ;确定了串比较的操作方向 CLD将DF清零,表示按增地址方向操作
    REPE CMPSB  ;串比较指令 按字节进行比较 REPE为重复前缀 CX≠0且相同则重复执行 
                ;源串默认数据段,指针必须SI给出,目标串必须在附加段,指针由DI表示
                ;这里将DATA同时设置为数据段和附加段令程序变得简单了
                ;操作时先比较,再将SI+1、DI+1、CX-1,然后再看比较结果
                ;这样可以保证比了几次,数值就改变了几次
    JZ NEXT1   ;通过ZF标志位是否跳转,当执行到JZ或者JE指令时,如果ZF=1则跳转,如果ZF=0,不跳转
    MOV Byte PTR[BX],00H
    JMP STOP
NEXT1: MOV Byte PTR(BX], OFFH
    STOP:......

当程序执行到STOP时:

错误结果:SI=(9) DI=(O) CX=(3) FLAG=(00H) ZF=(0)

正确结果:SI=(9) DI=(0015H) CX=(3) FLAG=(0) ZF=(0)

SI注意这里操作的方式是先比较,再将SI+1、DI+1、CX-1,然后再看比较结果。这里结果是9,我认为写0009H应该也对,和DI对应。
DI注意是偏移地址的值,而不是存储内容。
CX注意是从12开始减。
FLAG注意是把00H写入了FLAG,应该00H和0都对。
ZF是零标志位,用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。很明显,这里不相等,结果不为0,其值为0.

解释

存储内容

地址

解释

存储内容

地址

STR1开始

'H'

0000H

STR2开始

'H'

000CH

'E'

0001H

'E'

000DH

'L'

0002H

'L'

000EH

'L'

0003H

'L'

000FH

'O'

0004H

'O'

0010H

空格

00H

0005H

空格

00H

0011H

'W'

0006H

'W'

0012H

'O'

0007H

'O'

0013H

'R'

0008H

'O'

0014H

STR1+9

'L'

0009H

STR2+9

'L'

0015H

'D'

000AH

'D'

0016H

此处和STR2连接

'!'

000BH

'!'

0017H


示例五

端口输入+循环示例-不完整程序-不可运行
DATA SEGMENT
    SUM DB 8 DUP (0)   ;[变量名] 伪指令助记符 n DUP(初值 [,初值,… ] )
                       ;此处为 令从变量SUM地址开始设置八个字节的值,值均为0
DATA ENDS
CODE SEGMENT
    ASSUME CS: CODE, DS: DATA
START: MOV AX, DATA    
    MOV DS, AX

    LEA BX, SUM    ;将SUM偏移地址写入BX,后续使用进行存储
    MOV DX, 380H  ;从380H端口读入数据
    IN AL, DX     ;输入的值为45H
    MOV CX, 8
NEXT: ROR AL, 1 ;不含CF的循环右移指令 此处循环右移一位
    JNC NEXT1    ;根据CF是否为1跳转,为0不跳转,为1跳转
    MOV Byte PTR[BX], 0FFH ;将0FF写入SUM+自然数,其中自然数根据判断以及循环确定
    JMP NEXT2    ;无条件转移指令,直接跳转NEXT2
NEXT1: MOV Byte PTR [BX], 0
NEXT2: INC BX    ;逐渐变成SUM+1、SUM+2、SUM+3......
    LOOP NEXT   ;根据CX循环执行8次
    ......

如果从380H端口输入的是45H,则程序执行完后:

BX=(8)

INC八次之后BX从0变为8

AL=(45H)

循环8次之后回归原位置

SUM0-SUM7的内容为(FF,0,FF,0,0,0,FF,0)

由下表可得

解释

AL

循环右移

右移后的CF标志位

行为

45H转换二进制

0100 0101

1

将0FFH写入SUM

循环右移一次之后

1010 0010

0

将0写入SUM+1

循环右移两次之后

0101 0001

1

将0FFH写入SUM+2

之后的循环以此类推

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值