思勤无邪

上学时,因我年龄最小,个头也最小,上课时,就像大猩猩堆里的猴一般。如今,这猴偶尔也把最近的一些情况写在这里。

   :: 首页 :: 联系 :: 聚合  :: 管理
  132 Posts :: 1 Stories :: 178 Comments :: 0 Trackbacks

公告

     吾日常三省吾身,曰思、曰勤、曰无邪。

积分与排名

  • 积分 - 157051
  • 排名 - 142

最新随笔

最新评论

阅读排行榜

评论排行榜

    学习清华大学计算机系网络课程中的汇编语言程序设计。准备花两周来学习,这周主要是理论知识,下周加以实践,写一些Demo。

12-17:
    ★ 第一章 基础知识
        ◇第一节 进位计数制
        ◇第二节 不同基数的数之间的转换
        ◇第三节 二进制数和十六进制数的运算
        ◇第四节 数和字符的表示
    ★ 第二章 8086计算机组织
        ◇第一节 80x86微处理器系列概况
        ◇第二节 基于8086的微计算机系统
        ◇第三节 8086寄存器组
        ◇第四节 8086微处理器的存储器管理 
        ◇第五节 外部设备 
    ★ 第三章 8086的寻址方式和指令系统 
        ◇第一节 8086的寻址方式
        ◇第二节 机器语言指令的转换
        ◇第三节 8086的指令系统
12-18:
    ★ 第四章 汇编语言程序格式 
        ◇第一节 汇编程序功能
        ◇第二节 伪指令
        ◇第三节 汇编语言程序格式
        ◇第四节 汇编语言程序的上机过程 
12-19:
    ★ 第五章 循环与分支程序设计 
        ◇第一节 循环程序设计
        ◇第二节 分支程序设计
12-20:
    ★ 第六章 子程序结构 
        ◇第一节 子程序的设计方法
        ◇第二节 嵌套与递归子程序
        ◇第三节 子程序举例
12-21:
    ★ 第七章 高级汇编语言技术 
        ◇第一节 宏汇编
        ◇第二节 重复汇编
        ◇第三节 条件汇编
        ◇第四节 高级语言结构 
12-22:
    ★ 第八章 输入/输出程序设计 
        ◇第一节 I/O设备的数据传送方式
        ◇第二节 程序直接控制I/O方式
        ◇第三节 中断传送方式
12-23:
    ★ 第九章 BIOS和DOS中断 
        ◇第一节 键盘I/O
        ◇第二节 显示器I/O
        ◇第三节 打印机I/O
        ◇第四节 串行通信口I/O 
    ★ 第十章 模块化程序设计 
        ◇第一节 汇编程序概述
        ◇第二节 连接程序及对程序设计的要求
        ◇第三节 汇编语言程序与高级语言程序的连接
        ◇第四节 模块化程序设计概述  
下周的计划:
    ★ 第十一章 80x86汇编语言简介 
        ◇第一节 80x86的寄存器结构
        ◇第二节 80x86的指令系统和寻址方式
        ◇第三节 80x86处理器选择伪操作
        ◇第四节 保护模式下的80x86 
        ◇第五节 虚拟8086(V86)方式
        ◇第六节 保护方式下的中断处理 
 

posted on 2006-12-17 08:59 思勤无邪 阅读(1290) 评论(5)  编辑 收藏 引用 所属分类: 业余时间学习周计划

Feedback

# 2006-12-17 笔记 2006-12-17 10:27 思勤无邪
第一章 基础知识

1.1 进位计数制

1.2 不同基数的数之间的转换
1.2.1 二进制数和十进制数之间的转换
1.2.1.1 二进制转换为十进制
    各位按权求和
1.2.1.2 十进制转换为二进制
    除2取余
1.2.2 二进制和十六进制数之间的转换
    对于一个二进数,将它从低位到高位每4位一组,每组用一个十六进制数来表示。
    对于一个十六进制数,将它的每一位用4位二进制数表示。
    例: 0011  0101  1011 1111 
          3   5   B   F 
         即 0011010110111111B = 35BFH

    例: A    1    9   C 
        1010  0001  1001 1100 
        即 A19CH = 1010000110011100B
1.2.3 十六进制和十进制之间的转换
1.2.3.1 十六进制转换为十进制
        各位按权求各
1.2.3.2 十进制转换为十六进制
        除16取余

1.3 二进制数和十六进制数的运算

1.4 数和字符的表示
1.4.1 计算机中数的表示
1.4.1.1 补码表示法
    原码:最高位为符号位。0的表示不唯一
    反码:正数的反码同原码,负数的反码数值位与原码相反。0的表示不唯一。
    补码:正数的补码与原码相同;负数的补码表示:相应的正数按位求反,末位加1。
    符号扩展:是指一个数从位数较少扩展到位数较多,如从8位扩展到16位,或从16位扩展到32位。
    对于用补码表示的数,正数的符号扩展在前面补0,负数的符号扩展在前面补1,假设机器字长为16位,[+46]补码 = 002EH,[-46]补码 = FFD2H。
1.4.1.2 n位补码的表数范围
    n位补码的表数范围N是:
    -2的n-1次方 <= N <= 2的n-1次方-1
    如:用8位二进制补码表示带符号的数的表数范围是-128 <= N <= 127
1.4.1.3 补码的加、减法
    在机器里,补码减法是通过对减数求补后把减法转换为加法进行的。符号位参加运算,能自动得到正确结果。
    例:假设机器字长为8位,计算25+(-32)
        0001 1001
      + 1110 0000
      ------------
        1111 1001
    结果为-7的补码。
    在某些情况下,要处理的数全是正数(比如表示地址的数),就没有必要保留符号位了,可以把最高有效位也作为数值处理,这样的数称为无符号数。
1.4.2 计算机中字符的表示
    ASCII码用一个字节(8位二进制码)来表示一个字符,其中低7位为字符的ASCII值,最高位一般用作校验位。


第二章 8086计算机组织

2.1 80x86微处理器系列概况

2.2 基于8086的微计算机系统
2.2.1 8086微处理器的基本组成
    1. 执行部件(EU)
    2. 总线接口部件(BIU)
2.2.2 微型计算机的软件系统
    1. 系统软件
    2. 应用软件

2.3 8086寄存器组
    1. 通用寄存器
    通用寄存器包括了8个16位的寄存器:AX、BX、CX、DX、SP、BP、DI及SI。其中AX、BX、CX、DX在一般情况下作为通用的数据寄存器,用来暂时存放计算过程中所用到的操作数、结果或其他信息。它们还可分为两个独立的8位寄存器使用,命名为AL、AH、BL、BH、CL、CH、DL和DH。这4个通用数据寄存器除通用功能外,还有如下专门用途:
        AX作为累加器用,所以它是算术运算的主要寄存器。在乘除指令中指定用来存放操作数。另外,所有的I/O指令都使用AX或AL与外部设备传送信息。
        BX在计算存储器地址时,可作为基址寄存器使用。
        CX常用来保存计数值,如在移位指令、循环指令和串处理指令中用作隐含的计数器。
        DX在作双字长运算时,可把DX和AX组合在一起存放一个双字长数,DX用来存放高16位数据。此外,对某些I/O操作,DX可用来存放I/O的端口地址。
    SP、BP、SI、DI四个16位寄存器可以象数据寄存器一样在运算过程中存放操作数,但它们只能以字(16位)为单位使用。此外,它们更经常的用途是在存储器寻址时,提供偏移地址。因此,它们可称为指针或变址寄存器。
        SP称为堆栈指针寄存器,用来指出栈顶的偏移地址。
        BP称为基址指针寄存器,在寻址时作为基地址寄存器使用,但它必须与堆栈段寄存器SS联用来确定堆栈段中的存储单元地址。
        SI为源变址寄存器,在串处理指令中,SI作为隐含的源变址寄存器与DS联用,以确定数据段中的存储单元地址,并有自动增量和自动减量的变址功能。
        DI为目的变址寄存器,在串处理指令中,DI和附加段寄存器ES联用,以达到在附加段中寻址的目的,然后DI自动增量或减量。
2. 专用寄存器
    8086的专用寄存器包括IP、SP和FLAGS三个16位寄存器。
    IP为指令指针寄存器,它用来存放将要执行的下一条指令地址的偏移量,它与段寄存器CS联合形成代码段中指令的物理地址。
    SP为堆栈指针寄存器,它与堆栈段寄存器联用来确定堆栈段中栈顶的地址,也就是说SP用来存放栈顶的偏移地址。
    FLAGS为标志寄存器,这是一个存放条件码标志、控制标志的16位寄存器。
3. 段寄存器
    8086微处理器共有4个16位的段寄存器,在寻址内存单元时,用它们直接或间接地存放段地址。
        代码段寄存器CS:存放当前执行的程序的段地址。
      数据段寄存器DS:存放当前执行的程序所用操作数的段地址。
      堆栈段寄存器SS:存放当前执行的程序所用堆栈的段地址。
      附加段寄存器ES:存放当前执行程序中一个辅助数据段的段地址。

2.4 8086微处理器的存储器管理
    1.存储单元的地址和内容
    在存储器里以字节为编址单位,地址在机器中用无符号二进制数表示。
    对于字、双字、四字数据类型,其低地址中存放低位字节数据,高地址中存放高位字节数据。在读写数据时只需给出最低单元的地址号即可,然后依次存取后续字节。所以,同一个地址既可看作字节单元的地址,又可看作字单元、双字单元或4字单元的地址,这要根据使用时的情况来确定。而且多字节数据在存储器中是"逆序存放"的。
    在8086中,访问存储器(要求取数或存数)都是以字为单位进行的,也就是说,机器是以偶地址访问存储器的。这样,对于奇地址的字单元,要取一个字需要访问二次存储器,这就需要花费较多的时间。
2.存储器分段管理
    在8086中,物理地址是指由地址引线送出的20位地址码。这20位地址码送到存储器经过译码,最终选定一个存储单元进行读/写。
    偏移地址是相对于某段首地址的段内偏移量。
    逻辑地址是在程序中对存储器地址的一种表示方法,由某段的段地址和段内偏移地址组成。写成:段地址 : 偏移地址。
    存储器地址分段的具体做法是:把1MB的存储器空间分成若干段,每段的容量最大64KB,这样段内地址就可以用16位来表示。实际上,可以根据编程的需要来确定段的大小,它可以是64K字节范围内的任意多个字节。
  8086规定:从0地址开始,每16个字节为一小段,段的起始地址必须从任一小段(paragraph)的首地址开始,也就是说,段地址表示成20位的二进制地址码,其最低4位必须是"0"。
  存储器采用分段管理后,每个段的首地址(称为段基地址或段地址)保存在8086内部的CS、DS、SS和ES四个16位的寄存器中,可以对段寄存器设置不同的值以指向不同的段。
    16位的段地址和16位的偏移地址组合形成20位的物理地址,这就是8086的工作方式,这在80x86的寻址模式中称为实模式。
2.5 外部设备
    外部设备与主机(微处理器和存储器)的通信是通过外设接口进行的。每个接口包括一组寄存器。一般说来,这些寄存器有三种不同的用途:
      1. 数据寄存器:用来存放要在外设和主机间传送的数据,这种寄存器实际上起缓冲器的作用。
      2. 状态寄存器:用来保存外部设备或接口的状态信息,以便微处理器在必要时测试外设状态,了解外设的工作情况。 
      3. 命令寄存器:CPU给外设或接口的控制命令通过此寄存器送给外部设备。例如,CPU要启动磁盘工作,必须发出启动命令等。
  各种外部设备都有以上三种类型的寄存器,只是每个接口所配备的寄存器数量是根据设备的需要确定的。
  为了便于主机访问外设,外设中的每个寄存器给予一个端口地址(又称端口号),由这些端口地址组成了一个独立于内存储器的I/O地址空间。80x86的I/O地址空间可达64KB,所以端口地址的范围是0000~FFFFH,用16位二进制代码来表示。端口可以是8位或16位。
  在80x86系列机中,由于I/O地址空间是独立编址的,所以系统提供了访问外设的输入/输出指令IN和OUT。
  为了便于用户使用外设,8086提供了两种类型的例行程序供用户调用。一种是BIOS(Basic Input/Output System),另一种是DOS(Disk Operating System)功能调用。它们都是系统编制的子程序,通过中断方式转入所需要的子程序去执行。


第三章 8086的寻址方式和指令系统
3.1 8086的寻址方式
    计算机中的指令由操作码字段和操作数字段两部分组成。
    操作数字段可以有一个、二个或三个,通常称为一地址、二地址或三地址指令。
3.1.1 与数据有关的寻址方式
3.1.1.1 立即寻址方式(Immediate addressing)
    操作数直接存放在指令中,紧跟在操作码之后,它作为指令的一部分存放在代码段里,这种操作数称为立即数。
    如:MOV AX, 3064H
     指令执行后,(AX)= 3064H
    不能直接给段寄存器和标志寄存器赋予立即数。如:MOV DS, 1250H是错误的。
3.1.1.2 寄存器寻址方式(Register addressing)
    它使用寄存器来存放要处理的操作数,寄存器号由指令指定。
    如:MOV  AX, BX
    源寄存器和目的寄存器的位数必须一致。如:MOV CL, BX是错误指令。
有效地址EA(Effective Address)的概念:在8086里,把操作数的偏移地址称为有效地址。
3.1.1.3 直接寻址方式(Direct addressing)
    操作数存放在存储单元中,而这个存储单元的有效地址就在指令的操作码之后,操作数的物理地址可通过((DS)×16)再加上这个有效地址形成。
    在汇编语言指令中,可以用符号地址(变量名或标号)代替数值地址。
  例如: MOV AX, DATA
    或 MOV AX, [DATA]
    这里DATA是存放操作数单元的符号地址。
    直接寻址方式默认操作数在数据段中,如果操作数定义在其它段中,则应在指令中指定段跨越前缀。
  例如: MOV AX, ES:NUMBER
    或 MOV AX, ES:[NUMBER]
    这里NUMBER是附加段中的字变量。
3.1.1.4 寄存器间接寻址方式(Register indirect addressing)
    这种寻址方式通过基址寄存器BX、BP或变址寄存器SI、DI来保存操作数的有效地址。如果指令中使用的寄存器是SI、DI和BX,则操作数在数据段中,((DS)×16)再加上存器中的有效地址形成20位物理地址;如果指令中使用的寄存器是BP,则操作数在堆栈段中,((SS)×16)再加上BP中的有效地址形成20位物理地址。
    指令中也可以指定段跨越前缀来取得其他段中的数据。
  例如:MOV AX, ES:[BX]
3.1.1.5 寄存器相对寻址方式(Register relative addressing)
    这种寻址方式通过基址寄存器BX、BP或变址寄存器SI、DI与一个位移量相加形成有效地址,计算物理地址的缺省段仍然是SI、DI和BX为DS,BP为SS。
    如:MOV AX, COUNT[SI](也可表示为MOV AX, [COUNT+SI]),其中COUNT为16位位移量的符号地址。
3.1.1.6 基址变址寻址方式 (Based indexed addressing)
    操作数的有效地址是一个基址寄存器(BP或BX)和一个变址寄存器(SI或DI)的内容之和。如基址寄存器为BX时,与DS形成的物理地址指向数据段;如基址寄存器为BP时,与SS形成的物理地址指向堆栈段。
3.1.1.7 相对基址变址寻址方式(Relative based indexed addressing)
    基址加变址再加上一个位移量形成操作数的有效地址。缺省段的使用仍然是DS与BX组合,SS与BP组合。这种寻址方式通常用于对二维数组的寻址。如,存储器中存放着由多个记录组成的文件,则位移量可指向文件之首,基址寄存器指向某个记录,变址寄存器则指向该记录中的一个元素。
    如: MOV AX, MASK[BX][SI](或 MOV AX, MASK[BX+SI],或 MOV AX, [MASK+BX+SI])
有效地址可以由以下三种成分组成:
  · 位移量(Displacement)是存放在指令中的一个8位或16位数,但它不是立即数,而是一个地址。
  · 基址(Base)是存放在基址寄存器(BX或BP)中的内容。它是有效地址中的基址部分,通常用来指向数据段中数组或字符串的首地址。 
  · 变址(Index)是存放在变址寄存器(SI或DI)中的内容。它通常用来访问数组中的某个元素或字符串中的某个字符。
    有效地址的计算可用下式表示:
  EA = 基址 + 变址 + 位移量
    这三种成分都可正可负,以保证指针移动的灵活性。它们任意组合使用,可得到不同的寻址方式。
3.1.2 与转移地址有关的寻址方式
顺序执行的指令地址是由指令指针寄存器IP自动增量形成的,而程序转移的地址必须由转移类指令和CALL指令指出,这类指令表示转向地址的寻址方式包括:段内直接寻址、段内间接寻址、段间直接寻址、段间间接寻址。
    因为CS:IP寄存器总是指向下一条将要执行的指令的首地址(称为IP当前值),当转移指令执行后,必须修改IP或CS、IP的值。当转移指令给出位移量时,用IP当前值加上位移量即为新的IP的值。
  SHORT转移,称为短转移,位移量用一个字节(8位)来表示。位移量在-128~127字节之间。
  NEAR转移,称为近转移,位移量用16位表示,因为程序控制仍然在当前代码段,所以只修改IP的值,CS的值不变。位移量在-32768~32767字节范围内。
  FAR转移,称为远转移,因为程序控制超出了当前代码段,所以CS和IP都必须修改为新的值。转移距离超过±32K字节,或是在不同段之间转移。
  与转移地址有关的4种寻址方式就是告诉CPU如何修改CS和IP的值,以达到控制程序转移的目的。
3.1.2.1 段内直接寻址(Intrasegment direct addressing)
    这种寻址方式在指令中直接指出转向地址,如:
    JMP SHORT NEXT 
    JMP NEAR PTR AGAIN 
    其中,NEXT和AGAIN均为转向的符号地址。在机器指令中,操作码之后给出的是相对于当前IP值的位移量(转移距离),所以,转向的有效地址是当前IP值与指令中给出的位移量(8位或16位)之和。
3.1.2.2 段内间接寻址(Intrasegment indirect addressing)
    JMP BX 
    JMP NEAR PTR [BX] 
    JMP TABLE[SI]
3.1.2.3 段间直接寻址(Intersegment direct addressing)
    段间直接寻址和段内直接寻址类似,指令中直接给出转向地址,不同的是,在符号地址之前要加上表示段间远转移的操作符FAR PTR。
    指令格式如下:
    JMP FAR PTR OUTSEG
3.1.2.4 段间间接寻址(Intersegment indirect addressing)
    用相继两个字的内容装入IP和CS来达到段间的转移目的的,但这两个字的存储器地址是通过指令中的数据寻址方式(除立即寻址方式和寄存器寻址方式外)来取得的。
  为了说明寻址两个字单元,指令中必须加上双字操作符DWORD。指令格式如下:
    JMP DWORD PTR [SI] 
    JMP DWORD PTR[TABLE+BX]
8086机器语言指令是一种可变长度的指令,一条指令可以由1~7个字节组成,这主要取决于指令的操作码、寻址方式以及操作数长度等因素。
机器语言指令的组成
段前缀  操作码  寻址方式  数据/偏移量  数据/偏移量  数据  数据

3.2 机器语言指令的转换
3.2.1 段前缀字节
    当指令中没有段前缀(如ES: )时,机器指令中无此字节。段前缀字节高3位和低3位是段前缀标志,3、4位(SEG)分别表示4个段前缀。
3.2.2 操作码字节
    操作码决定微处理器执行的操作,如,传送、加法、减法等,它通常用机器指令的第一个字节表示。多数机器语言指令的操作码占用一个字节,有时一个字节不够,在下一个字节再占用3位。
    操作码字节的高6位是操作码,它来自于机器指令表。
3.2.3 寻址方式字节
3.2.4 机器指令举例

3.2 8086指令系统
3.3.1 数据传送指令
数据传送指令的功能是把数据、地址传送到寄存器或存储器单元中。它分为4类。
    ⑴ 通用数据传送指令
     MOV  传送
     PUSH 进栈
     POP  出栈
     XCHG 交换
    ⑵ 累加器专用传送指令
        IN   输入
        OUT  输出
        XLAT 换码
  ⑶ 地址传送指令
     LEA  有效地址送寄存器
     LDS  指针送寄存器和DS
     LES  指针送寄存器和ES
    ⑷ 标志寄存器传送指令
        LAHF 标志送AH
        SAHF AH送标志寄存器
        PUSHF 标志进栈
        POPF 标志出栈
3.3.1.1 通用数据传送指令
    MOV dst, src;传送指令(move)
  执行操作:(dst) ← (src)
  功能: 将源操作数(字节或字)传送到目的地址。

    PUSH   src ; 进栈指令(push onto the stack) 
  执行操作: (SP) ← (SP)-2
        ((SP)) ← (src)

  POP    dst ; 出栈指令(pop from the stack)
  执行操作: (dst) ← ((SP))
        (SP) ← (SP)+2

    XCHG  opr1, opr2 ; 交换指令(exchange)
  执行操作:(opr1) ←→ (opr2)

3.3.1.2 累加器专用传送指令
    这组指令只限于使用累加器(ac:AX 或AL)传送信息。
  IN  ac, port ; 输入指令(input), port≤0FFH
  执行操作: (AL) ← (port) 传送字节
   或 (AX) ← (port+1,port) 传送字

  IN  ac, DX  ; 输入指令, DX中的port>0FFH
  执行操作: (AL) ← ((DX)) 传送字节
   或 (AX) ← ((DX)+1,(DX)) 传送字

  OUT  port, ac  ; 输出指令(output), port≤0FFH
  执行操作: (port) ← (AL) 传送字节
   或 (port+1,port) ← (AX) 传送字

  OUT  DX, ac   ; 输出指令(output), DX中的 port>0FFH
  执行操作: ((DX)) ← (AL) 传送字节
   或 ((DX)+1,(DX)) ← (AX) 传送字
    例:   IN   AL, 61H   ; (AL) ← 端口61H的内容
      MOV   DX, 278H   ; (DX) ← 端口地址278H
      IN   AL, DX    ; (AL) ← 端口278H的内容

          OUT   61H, AL   ; 61H端口 ← (AL)
      MOV   DX, 279H   ; (DX) ← 端口地址279H
      OUT   DX, AX    ; 279H端口 ← (AX)

    XLAT   ; 换码指令(translate)
  执行操作: (AL) ← ((DS)×16+(BX)+(AL))
    这条指令根据AL寄存器提供的位移量,将BX指示的字节表格中的代码换存在AL中。
3.3.1.3 地址传送指令
    这组指令完成把地址送到指定寄存器的功能。
  LEA reg, src ; 有效地址送寄存器(load effective address)
  执行操作:(reg) ← offset of src
  LEA指令把源操作数的有效地址送到指定的寄存器,这个有效地址是由src选定的一种存储器寻址方式确定的。

  LDS reg, src ; 指针送寄存器和DS(load DS with point)
  执行操作: (reg) ← (src)
       (DS) ← (src+2)

  LES reg, src ; 指针送寄存器和ES(load ES with point)
  执行操作: (reg) ← (src)
       (ES) ← (src+2)
3.3.1.4 标志寄存器传送指令
    LAHF 标志寄存器的低字节送AH(load AH with flags)
   执行操作: 
    (AH) ← (FLAGS)0-7

    SAHF AH送标志寄存器低字节(store AH into flags)
    执行操作: 
    (FLAGS) 0-7 ← (AH)

    PUSHF 标志进栈(push the flags)
   执行操作: 
   (SP) ← (SP)-2
   ((SP)+1,(SP)) ← (FLAGS)0-15
  
    POPF 标志出栈(pop the flags)
   执行操作: 
   (FLAGS) 0-15 ← ((SP)+1,(SP))
   (SP) ← (SP)+2

3.3.2 算术指令
    ⑴ 加法指令
    ADD  加法
    ADC  带进位加
    INC  加1
    ⑵ 减法指令
        SUB  减法     
        DEC  减1
        NEG  求补
        CMP  比较
  ⑶ 乘法指令
    MUL  无符号数乘法
    IMUL 带符号数乘法
    ⑷ 除法指令
        DIV  无符号数除法
        IDIV 带符号数除法
  ⑸ 符号扩展指令
    CBW  字节转换为字
    CWD  字转换为双字
    ⑹ 十进制调整指令
    DAA  加法的十进制调整
    DAS  减法的十进制调整
    AAA  加法的ASCII调整
    AAS  减法的ASCII调整
    AAM  乘法的ASCII调整
    AAD  除法的ASCII调整
3.3.2.1 加法指令
  ADD dst,src 加法指令(addition)
  执行操作: (dst) ← (src)+(dst)

  ADC dst,src 带进位加指令(add with carry)
  执行操作: (dst) ← (src)+(dst)+CF

  INC opr 加1指令(increment) 
  执行操作: (opr) ← (opr)+1
3.3.2.2 减法指令
  SUB dst,src 减法指令(subtract)
  执行操作: (dst) ← (dst)-(src)

  SBB dst,src 带借位减法指令(subtract with borrow)
  执行操作: (dst) ← (dst)-(src)-CF

  DEC opr 减1指令(decrement)
  执行操作: (opr) ← (opr)-1

  CMP opr1,opr2 比较指令(compare)
  执行操作: (opr1)-(opr2),根据相减结果设置条件码,但不回送结果
3.3.2.3 乘法指令
  MUL  src  无符号数乘法(unsigned multiple)
  IMUL src  带符号数乘法(signed multiple)
  字节操作: (AX) ← (AL)×(src)
  字操作:  (DX, AX) ← (AX)×(src)
MUL和IMUL指令的区别仅在于操作数是无符号数还是带符号数,它们的共同点是,指令中只给出源操作数src。目的操作数是隐含的,它只能是累加器(字运算为AX,字节运算为AL)。隐含的乘积寄存器是AX或DX(高位)和AX(低位)。
3.3.2.4 除法指令
   DIV  src 无符号数除法(unsigned divide)
   IDIV src 带符号数除法(signed divide)
   字节操作: (AL) ← (AX) / src 的商
        (AH) ← (AX) / src 的余数
   字操作: (AX) ← (DX, AX) / src 的商
       (DX) ← (DX, AX) / src 的余数
这两条除法指令的被除数必须存放在AX或DX,AX中。除法指令对所有条件码均无定义,因此对除法指令产生的错误,如除数为0或商溢出等错误,程序员都不能用条件码进行判断,而是由系统直接转入0型中断来处理。
3.3.2.5 符号扩展指令
   CBW 字节扩展为字(convert byte to word)
   执行操作:
   (AH)= 00H 当(AL)的最高有效位为0时
   (AH)= FFH 当(AL)的最高有效位为1时

    CWD 字扩展为双字(convert word to double word)
   执行操作:
   (DX)=0000H当(AX)的最高有效位为0时
   (AH)=FFFFH当(AX)的最高有效位为1时
这是两条无操作数指令,进行符号扩展的操作数必须存放在AL寄存器或AX寄存器中。这两条符号扩展指令都不影响条件码。

 
3.3.2.6 十进制调整指令

  80x86微型机提供了一组十进制调整指令,用来处理ASCII码和BCD码表示的数。
 
  BCD码:
  BCD(Binary Coded Decimal)是用二进制编码表示的十进制数(见表3.3),十进制数采用0~9十个数字,是人们最常用的。在计算机中,同一个数可以用两种BCD格式来表示:①压缩的BCD码 ②非压缩的BCD码

  压缩的BCD码:
  压缩的BCD码用4位二进制数表示一个十进制数位,整个十进制数用一串BCD码来表示。例如,十进制数59表示成压缩的BCD码为0101 1001,十进制数1946表示成压缩的BCD码为0001 1001 0100 0110。

  非压缩的BCD码:
  非压缩的BCD码用8位二进制数表示一个十进制数位,其中低4位是BCD码,高4位是0。例如,十进制数78表示成压缩的BCD码为0000 0111 0000 1000。 

   从键盘输入数据时,计算机接收的是ASCII码,要将ASCII码表示的数转换成BCD码是很简单的,只要把ASCII码的高4位清零即可。

  压缩的BCD码调整指令
  DAA和DAS指令完成加法和减法的调整功能。

  DAA 加法的十进制调整(decimal adjust for addition)
  执行操作:(AL)← 把AL中的和调整为压缩的BCD格式

  DAS 减法的十进制调整(decimal adjust for subtraction)
  执行操作:(AL)← 把AL中的差调整为压缩的BCD格式

  DAA和DAS指令的调整方法如下:
  执行加法指令(ADD、ADC)或减法指令(SUB、SBB)后,
  1.如果结果的低4位 (AL)0~3>9或AF=1,则(AL)←(AL)±06H,且AF置1;
  2.如果结果的高4位 (AL)4~7>9或CF=1,则(AL)←(AL)±60H,且CF置1。

  对上述方法,加法调整作+06H和+60H,减法调整作-06H和-60H。这两个调整的条件,如果满足其一,则±06H或±60H;如果同时满足,则±06H后,再±60H。

  非压缩的BCD码调整指令
  AAA 加法的ASCII调整(ASCII adjust for add)
  执行操作:
  (AL)← 把AL中的和调整为非压缩的BCD格式
  (AH)←(AH)+ 调整产生的进位值

  AAS 减法的ASCII调整(ASCII adjust for sub)
  执行操作:
  (AL)← 把AL中的差调整为非压缩的BCD格式
  (AH)←(AH)- 调整产生的借位值

  加法和减法的操作数可以直接使用ASCII码,而不必把高位0011清为0000,AAA和AAS指令就是专门为ASCII码操作数或非压缩BCD码操作数的加减法而设计的。

  AAA和AAS的调整方法如下:
  执行加法指令(ADD、ADC)或减法指令(SUB、SBB)后,结果存放在AL寄存器中:
  (1)如果(AL)0~3= 0~9,且AF=0,则(AL)4~7= 0,AF的值送CF;
  (2)如果(AL)0~3=A~F,或AF=1,则(AL)←(AL)±06H,(AL)4~7= 0,(AH)←(AH)±1,AF的值送CF。
  AAA和AAS指令除影响AF和CF标志外,其余标志位均无定义。

  AAM 乘法的ASCII调整(ASCII adjust for mul)
  执行操作:(AX)← 把AX中的积调整为非压缩的BCD格式

  AAD 除法的ASCII调整(ASCII adjust for div)
  执行操作:(AX)← AX中的被除数(非压缩的BCD格式)转化为二进制数

  以上两条指令是专为非压缩的BCD码的乘除法而设计的,它们将乘法和除法的结果转换为非压缩的BCD码。
  
  注意:AAM和AAD都只对AX寄存器中的数进行调整,它们只影响SF、ZF和PF标志位,其它标志位无定义。

  AAM的调整方法为:
  执行乘法指令(MUL)后,调整存放在AL寄存器中的乘积:
   (AH)←(AL)/ 0AH的商
   (AL)←(AL)/ 0AH的余数

  AAM实际上是将两个一位数的非压缩BCD码相乘后得到的乘积进行二化十的转换,十位数放在AH中,个位数放在AL中,那么AX中就是乘积的非压缩BCD码。

  注意:如果是两个ASCII码数相乘,要先将它们转换成非压缩BCD码。

  AAD的调整方法为:
  执行除法指令之前,对AX中的非压缩BCD码(被除数)执行:
   (AL)←(AH)×10+(AL)
   (AH)← 0

  与其它调整指令不同的是,AAD用在DIV指令之前,即先将AX中的被除数调整成二进制数,并存放在AL中,再用DIV指令作二进制数的除法。AX中的被除数是二位非压缩BCD码,AH中的十位数乘10,再加上AL中的个位数,即转换为二进制数。
3.3.3 逻辑指令
    ⑴ 逻辑运算指令
     AND     逻辑与
     OR      逻辑或
     OT      逻辑非
     XOR     异或
     TEST     测试
    ⑵ 移位指令
     SAL     算术左移
     SHR     逻辑右移
     SAR     算术右移
     ROL    循环左移
     ROR    循环右移
     RCL    带进位循环左移
     RCR    带进位循环右移
3.3.3.1 逻辑运算指令
   AND dst,src ;逻辑与(logic and)
   执行操作: (dst)←(dst)&(src)

   OR dst,src ;逻辑或(logic or)
   执行操作: (dst)←(dst)|(src)

   NOT opr ;逻辑非(logic not)
   执行操作: (opr)← !(opr)

   XOR dst,src ;异或 (exclusive or)
   执行操作: (dst)←(dst)异或(src)

   TEST opr1,opr2 ;测试(test)
   执行操作: (opr1)&(opr2),根据与运算结果设置条件码,结果不回送
3.3.3.2 移位指令
3.3.4 串处理指令
    ⑴ 串处理指令
        MOVSB / MOVSW   串传送 
        STOSB / STOSW   存串 
        LODSB / LODSW   取串 
        CMPSB / CMPSW   串比较
        SCASB / SCASW   串扫描
    ⑵ 串重复前缀
        REP        重复串操作
        REPE / REPZ    相等/为零时重复
        REPNE / REPNZ   不等/不为零时重复
    ⑶ 设置方向标志
        CLD        使DF=0
        STD        使DF=1
3.3.4.1 设置方向标志指令
  CLD DF置0(clear direction flag)
  STD DF置1(set direction flag)
为了处理连续存储单元中的字符串或数串,地址指针需要连续地增量或减量,指针增量或减量决定了串处理的方向。当用CLD指令使DF=0时,源串的指针SI和目的串的指针DI自动增量(+1或+2),当用STD指令使DF=1时,指针SI和DI自动减量(―1或―2)。地址指针是±1还是±2,取决于串操作数是字节还是字。
3.3.4.2 串处理指令
  MOVSB / MOVSW 串传送(move string byte/word)
  执行操作:
  (ES:DI)←(DS:SI)
  (SI)←(SI)±1(字节)或±2(字)
  (DI)←(DI)±1(字节)或±2(字)

  STOSB / STOSW 存串(load from string byte/word)
  执行操作: 
  (ES:DI)←(AL)或(AX)
  (DI)←(DI)±1(字节)或±2(字)

  LODSB / LODSW 取串(store into string byte/word)
  执行操作: 
  (AL)或(AX)←(DS:SI)
  (SI)←(SI)±1(字节)或±2(字)

  CMPSB / CMPSW 串比较(compare string byte/word)
  执行操作: 
  (DS:SI)-(ES:DI),根据比较的结果设置条件码
  (SI)←(SI)±1(字节)或±2(字)
  (DI)←(DI)±1(字节)或±2(字)

  SCASB / SCASW 串扫描(scan string byte/word) 
  执行操作: 
  (AL)-(ES:DI)或(AX)-(ES:DI),根据扫描比较的结果设置条件码
  (DI)←(DI)±1(字节)或±2(字)
3.3.4.3 串重复前缀
  REP 重复执行串指令,(CX)=重复次数
  执行操作:
  ① (CX)=0时,串指令执行完毕,否则执行② ~ ④
  ② (CX)←(CX)-1
  ③ 执行串指令(MOVS或STOS)
  ④ 重复执行①

  REPE / REPZ 相等/为零时重复执行串指令,(CX)=比较/扫描的次数
  执行操作:
  ① (CX)=0或ZF=0时,结束执行串指令,否则继续② ~ ④
  ② (CX)←(CX)-1
  ③ 执行串指令(CMPS或SCAS)
  ④ 重复执行①

  REPNE / REPNZ 不等/不为零时重复执行串指令,(CX)=比较/扫描的次数
  执行操作:
  ① (CX)=0或ZF=1,结束执行串指令,否则继续② ~ ④
  ② (CX)←(CX)-1
  ③ 执行串指令(CMPS或SCAS)
  ④ 重复执行①
3.3.5 控制转移指令
    ⑴ 无条件转移 
        JMP 跳转
    ⑵ 条件转移 
        JZ/JNZ    结果为零/不为零则转移 
        JS/JNS    结果为负/为正则转移 
        JO/JNO    溢出/不溢出则转移 
        JP/JNP    奇偶位为1/为0则转移 
        JB/JNB    低于/不低于则转移 
        JBE/JNBE   低于等于/高于则转移 
        JL/JNL    小于/不小于则转移 
        JLE/JNLE   小于等于/大于则转移 
        JCXZ     CX为零则转移
    ⑶ 循环指令
        LOOP      循环
        LOOPZ/LOOPE  为零/相等时循环
        LOOPNZ/LOOPNE 不为零/不等时循环
    ⑷ 子程序调用与返回
        CALL      调用
        RET       返回
    ⑸ 中断及中断返回
        INT       中断
        INTO      溢出则中断
        IRET       中断返回
3.3.6 处理机控制指令
  处理机控制指令包括一组置0或置1标志位的指令,还有一些控制处理机状态的指令。
    ⑴ 标志位处理指令
        CLC CF置0
        STC CF置1
        CMC CF求反
        CLD DF置0
        STD DF置1
        CLI IF置0
        STI IF置1
    ⑵ 处理机控制指令
        NOP 无操作
        HLT 停机
        WAIT 等待
        ESC 转义
        LOCK 封锁

下了一个不错的汇编开发环境。还是湖南的软件公司做的,感觉不错。下载地址:http://www.chencan.com/ccasm/  回复  更多评论
  

# 2006-12-18 笔记 2006-12-18 22:25 思勤无邪
第四章 汇编语言程序格式

4.1 汇编程序功能

4.2 伪指令
4.2.1 段定义伪指令
4.2.1.1 完整的段定义伪指令
    完整段定义伪指令的格式如下:
        段名 SEGMENT
            .
            .
            .
        段名 ENDS

4.2.2.2 存储模型与简化段定义伪指令
    1. 存储模型伪指令
    存储模型决定一个程序的规模,也确定进行子程序调用、指令转移和数据访问的缺省属性(NEAR或FAR)。当使用简化段定义的源程序格式时,在段定义语句之前必须有存储模型 .MODEL语句,说明在存储器中应如何安放各个段。
    Flat存储模型: 所有代码和数据放置在一个段中,但段地址是32位的,所以整个程序可为4GB。MASM 6.0支持该模型。 

    2. 简化的段伪指令 
    .CODE [段名]     创建一个代码段(段名为可选项,如不给出段名,则采用默认段名。对于多个代码段的模型,则应为每个代码段指定段名。)
    .DATA            创建一个数据段(段名是:_DATA)
    .DATA?           创建无初值变量的数据段(段名是:_BSS)
    .FARDATA [段名]  建立有初值的远调用数据段(可指定段名,如不指定,则将以FAR_DATA命名。) 
    .FARDATA? [段名] 建立无初值的远调用数据段(可指定段名,如不指定,则将以FAR_BSS命名。) 
    .CONST           建立只读的常量数据段(段名是:CONST)
    .STACK [大小]    创建一个堆栈段并指定堆栈段大小(段名是:stack。如不指定堆栈段大小,则缺省值为1KB) 

    3.与简化段定义有关的预定义符号
    (1)@code 由.CODE 伪指令定义的段名或段组名。
    (2)@data 由.DATA 伪指令定义的段名,或由 .DATA 、.DATA?、.CONST和 .STACK所定义的段组名。
    (3)@stack 堆栈段的段名或段组名。

    简化段定义举例

      .MODEL     SMALL
      .STACK     100H       ; 定义堆栈段及其大小
      .DATA                 ; 定义数据段
              .
              .
              .
      .CODE                 ; 定义代码段
  START:                    ; 起始执行地址标号
      MOV        AX, @DATA  ; 数据段地址
      MOV        DS, AX     ; 存入数据段寄存器
              .
              .
              .
      MOV       AX, 4C00H
      INT       21H
      END       START       ; 程序结束

4.2.2.3 段组定义伪指令
    段组定义伪指令能把多个同类段合并为一个64KB的物理段,并用一个段组名统一存取它。段组定义伪指令GROUP的格式如下:
    段组名  GROUP  段名 [, 段名 …]

4.2.3 程序开始和结束伪指令

4.2.4 数据定义及存储器分配伪指令
    ORG(origin)
    ORG伪指令用来表示起始的偏移地址,紧接着ORG的数值就是偏移地址的起始值。ORG伪操作常用在数据段指定数据的存储地址,有时也用来指定代码段的起始地址。

    DB(define byte)
    DB伪指令用来定义字节,对其后的每个数据都存储在一个字节中。DB能定义十进制数、二进制数、十六进制数和ASCII字符,二进制数和十六进制数要分别用"B"和"H"表示,ASCII字符用单引号(' ')括起来。DB还是唯一能定义字符串的伪操作,串中的每个字符占用一个字节。

   DW(define word)
    DW伪指令用来定义字,对其后的每个数据分配2个字节(1个字),数据的低8位存储在低字节地址中,高8位存储在高字节地址中,如下例中的变量DATA8的数据存储在0070字地址中,其中0070字节存储0BAH,0071字节存储03H。DW还可存储变量或标号的偏移地址。见左面DW伪指令的例子。

    DD(define doubleword)
    DD伪指令用来定义双字,对其后的每个数据分配4个字节(2个字)。该伪指令同样将数据转换为十六进制,并根据低地址存储低字节,高地址存储高字节的规则来存放数据。如下例DATA15的存储情况是:00A8:0F2H,00A9H:57H,00AAH:2AH,00ABH:5CH。
    用DD存入地址时,第一个字为偏移地址,第二个字为段地址。

    DQ(define quadword)
    DQ伪指令用来定义4字,即64位字长的数据,DQ之后的每个数据占用8个字节(4个字)。

    DT(define ten bytes)
    DT伪指令用来为压缩的BCD数据分配存储单元,它虽然可以分配10个字节(5个字),但最多只能输入18个数字,要注意的是,数据后面不需要加"H"。左面是DQ和DT的例子。

    DUP(duplicate)
    DUP伪指令可以按照给定的次数来复制某个(某些)操作数,它可以避免多次键入同样一个数据。例如,把6个FFH存入相继字节中,可以用下面两种方法,显然用DUP的方法更简便些。

  存入6字节的FFH
DATA20 DB 0FFH 0FFH 0FFH 0FFH 0FFH 0FFH;
DATA21 DB 6 DUP(0FFH)    

    DUP操作一般用来保留数据区,如用数据定义伪指令"DB 64 DUP(?)"可为堆栈段保留64个字节单元。DUP还可以嵌套,其用法见左例。

    PTR属性操作符
    PTR指定操作数的类型属性,它优先于隐含的类型属性。其格式为:

    类型 PTR 变量[ ± 常数表达式]

    其中类型可以是BYTE、WORD、DWORD、FWORD、QWORD或TBYTE,这样变量的类型就可以指定了。

    LABEL伪指令
    LABEL可以使同一个变量具有不同的类型属性。其格式为:

    变量名 LABEL 类型
或  标号   LABEL 类型

    其中变量的数据类型可以是BYTE,WORD,DWORD,标号的代码类型可以是NEAR或FAR。

4.2.5 表达式赋值伪指令
    EQU是一个赋值伪操作(伪指令),它给一个数据标号赋于一个常数值,但这个常数不占用存储单元。当这个数据标号出现在程序中时,汇编程序即用它的常数值代替数据标号。EQU可以在数据段之外使用,甚至可用在代码段中间。

    = 伪操作

    赋值伪操作"="的作用与EQU类似。它们之间的区别是,EQU伪操作中的标号名是不允许重复定义的,而=伪操作是允许重复定义的。

4.2.6 地址计数器与对准伪指令
    1.地址计数器$

    在汇编程序对源程序汇编的过程中,使用地址计数器来保存当前正在汇编的指令的地址。地址计数器的值在汇编语言中可用$来表示。

    当$用在伪指令的参数字段时,它所表示的是地址计数器的当前值

    2.EVEN伪指令

    EVEN伪指令使下一个变量或指令开始于偶数字节地址。

    3. ALIGN伪指令

    ALIGN伪指令使它后面的数据或指令从2的整数倍地址开始。其格式为:

        ALIGN 2n (n为任意整数)


4.2.7 基数控制伪指令 
    .RADIX伪指令

    .RADIX可以把默认的基数改变为2~16范围内的任何基数。其格式如下:
          .RADIX 基数值

    其中基数值用十进制数来表示。

4.3 汇编语言程序格式 
4.3.1.汇编语言源程序语句的格式 
4.3.2 表达式

    (1) 算术操作符
    算术操作符有+、-、*、/ 和MOD。
    MOD是指除法运算后得到的余数,如19/7的商是2,而19 MOD 7则为5(余数)。

    (2) 逻辑操作符 
    逻辑操作符有:AND(与)、OR(或)、XOR(异或)、NOT(非)。
    逻辑操作符都是按位操作的,只能用于数字表达式中。逻辑操作符要求汇编程序对其前后两个操作数(或表达式)作指定的逻辑操作。

    (3) 关系操作符
    关系操作符有:EQ(相等)、NE(不等)、LT(小于)、GT(大于)、LE(小于或等于)、GE(大于或等于)。
    关系操作符的两个操作数必须都是数字或是同一段内的两个存储器地址。计算的结果应为逻辑值:结果为真,表示为0FFFFH;结果为假,则表示为0。

    (4) 数值回送操作符 
    数值回送操作符有:TYPE、LENGTH、SIZE、OFFSET、SEG等。
    数值操作符把一些特征或存储器地址的一部分作为数值回送。

    · TYPE
    格式为:TYPE 表达式
    如果表达式是变量,则汇编程序将回送该变量的以字节数表示的类型:DB为1,DW为2,DD为4,DF为6,DQ为8,DT为10。如果表达式是标号,则汇编程序将回送代表该标号类型的数值:NEAR为 -1,FAR为 -2。如果表达式为常数,则应回送0。

    · LENGTH
    格式为:LENGTH 变量
    对于变量中使用DUP的情况,汇编程序将回送分配给该变量的单元数,而对于其他情况则送1。

    · SIZE
    格式为:SIZE 变量
    汇编程序应回送分配给该变量的字节数。但是,此值是LENGTH值和TYPE值的乘积。

    · OFFSET
    格式为:OFFSET 变量或标号
    汇编程序将回送变量或标号的偏移地址值。

    · SEG
    格式为:SEG 变量或标号
    汇编程序将回送变量或标号的段地址值。

    (5) 属性操作符
    属性操作符主要有:PTR、段操作符、SHORT、THIS、HIGH、LOW等。

    · PTR
    格式为:类型 PTR 符号地址
    PTR用来给已分配的存储地址(用符号地址表示)赋予另一种属性,使该地址具有另一种类型。
    类型可有BYTE、WORD、DWORD、FWORD、QWORD、TBYTE、NEAR和FAR等几种,所以PTR也可以用来建立字、双字、四字或段内及段间的指令单元等。

    · 段操作符
    段操作符用来表示一个标量、变量或地址表达式的段属性。
    格式为: 
    段寄存器∶地址表达式
    段名∶地址表达式
    组名∶地址表达式

    · SHORT
    用来修饰JMP指令中转向地址的属性,指出转向地址是在下一条指令地址的±127个字节范围之内。

    · THIS
    格式为: THIS 属性或类型
    THIS可以象PTR一样建立一个指定类型(BYTE、WORD、DWORD)或指定距离(NEAR或FAR)的地址操作数。该操作数的段地址和偏移地址与下一个存储单元地址相同。

    · HIGH和LOW
    称为字节分离操作符,它接收一个数或地址表达式,HIGH取其高位字节,LOW取其低位字节。

4.3.3 汇编语言源程序格式举例

4.4 汇编语言程序的上机过程
4.4.1 建立汇编语言的工作环境
4.4.2 汇编语言程序上机运行过程
4.4.3 COM文件
  回复  更多评论
  

# 2006-12-19 笔记 2006-12-20 14:30 思勤无邪
昨天因有别的事(修改帮别人做过的网站)而没有时间完成学习计划。
将大一点的目标写成计划,并具体到天还是很有好处的,至少能督促自己尽力去完成。  回复  更多评论
  

# 都有哪些名词是用字母表示的 2007-11-03 13:23 郭佳宁
rvey   good  回复  更多评论
  

# 都有哪些名词是用字母表示的 2007-11-03 13:24 郭佳宁
veryverygood  回复  更多评论
  


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理