汇编语言学习笔记(终)

第29-30节课

汇编语言程序格式

一、汇编程序功能

如图所示,表示了汇编语言程序的建立和处理过程。首先用编辑程序产生汇编语言的源程序,源程序就是用汇编语言的语句编写的程序,它是不能为机器所识别的,所以要经过汇编程序加以翻译,因此汇编程序的作用就是把源文件转换成用二进制代码表示的目标文件(称为OBJ 文件)。在转换的过程中,汇编程序将对源程序进行扫视,如果源程序中有语法错误,则汇编结束后,汇编程序将指出源程序中的错误,用户还可以用编辑程序来修改源程序中的错误,最后得到无语法错误的OBJ文件。OBJ文件虽然已经是二进制文件,但它还不能直接上机运行,必须经过连接程序(link)把目标文件与库文件或其他目标文件连接在一起形成可执行文件(EXE文件),这个文件可以由DOS装入存储器,并在机器上运行。

汇编语言程序执行步骤:

(1)用编辑程序建立ASM源文件

(2)用MASM程序把ASM文件转换成OBJ文件

(3)用LINK程序把OBJ文件转换成EXE文件

(4)用DOS命令直接键入文件名就可执行该程序

汇编程序的主要功能:

(1)检查源程序

(2)测出源程序中的语法错误,并给出出错信息

(3)产生源程序的目标程序,并可给出列表文件(同时列出汇编语言和机器语言的文件,称为LST文件)

(4)展开宏命令

二、汇编语言语句

汇编语言语句分三大类:指令语句;伪指令语句;宏指令语句

1、指令语句:能汇编成机器指令的汇编指令构成,是可执行的。具体格式:

[标号:] 指令助记符  [操作数1] [, 操作数2]……[, 操作数n]  [; 注解]

2、伪指令语句:伪指令不像机器指令那样是在程序运行期间由计算机来执行的,而是在汇编程序对源程序汇编期间由汇编程序处理的操作,它们可以完成的操作有:处理器选择、定义程序模式、定义数据、分配存储区、指示程序结束等功能。

例:  .386    选择386指令系统     P118

       A  DW  1234H,   ‘ba’      ;DW  为字定义伪指令

3、宏指令:通过宏定义的汇编指令体集合

   宏定义格式:   宏名   MACRO   [参数表]

                        宏指令体(即汇编指令语句)

                        ENDM

注:宏在源程序的最开始部分定义,在程序中调用宏(称为宏展开)

三、段的定义格式

段名   SEGMENT   [定位类型]  [组合类型]  [使用类型]  [类别]

……

段名   ENDS

重要说明:

1.段名由用户自己取名,[   ]项为可选项,这些项都有默认值。

2.[定位类型] 表示段的起始地址的取值类型,有以下几种取值情形

(1) PARA  (默认取值)表示段地址能被10H(十进制16)整除,即这样的段地址形如:XXXX0H。所以1M地址空间最多可以分成64K个小段,这样的段地址可有64K个。(节类型)

(2)BYTE 段的起始地址为字节类型,表示段的起始地址能被1整除,任何地址可作为段起始地址。

(3)WORD 段的起始地址为字类型,表示段的起始地址能被2整除,任何偶数地址可作为段起始地址。

 (4) DWROD 段的起始地址为双字类型,表示段的起始地址能被4整除。

(5)PAGE  段的起始地址为页类型,表示段的起始地址能被100H(十进制256)整除。

3.[组合类型]:说明连接时,段的合并方法。

(1)PRIVATE (默认取值)该段为私有段,连接时将不与其它模块中的同名段合并。

(2)PUBLIC  该段连接时可以把不同模块中的同名段相连形成一个段,其连接次序由连接命令指定。(PARA类型,相连存在有小于16字节的空隙)

(3)COMMON 该段连接时可以把不同模块中的同名段重叠而形成一个段,由于同名分段有相同的起如地址,所以会产生覆盖。连接的段长取最大段长。

(4)AT  表达式:指定一个表达式的值作为段的起始地址值。

(5) MEMORY  : 与PUBLIC 含义一样

(6)STACK : 定义为堆栈段。

例:定义一个200字节空间的堆栈段,段名为SABC,段的起始地址能被100H整除,其它为默认值。定义格式如下:

SABC  SEGMENT  PAGE  STACK

DW  100  DUP (?)

SABC  ENDS 

重要说明:如果在程序中定义了一个堆栈,目标文件在连接时,不会出现下列所谓的错误提示L4021

4. [使用类型]:指明是16位寻址方式还是32位寻址方式,适合386及其后继机型。

(1)USE16: (默认值) 使用16位寻址方式

(2)USE32: 使用32位寻址方式

5. [类别](用单引号括起来) :在引号中给出连接时组成段组的类型名,类别说明并不能把相同类别的段合并起来,但在连接后形成的装入模块中,可以把它们的位置靠在一起。 

四、代码段中第一条伪指令格式:

   ASSUME  CS:代码段名,DS:数据段名1,ES:数据段名2,SS:堆栈段名

含义:指明定义的各个段相应的段地址存放在哪个段寄存器中。

五、数据段寄存器装填语句(即给段寄存器赋值)

格式:MOV  AX,  数据段名

      MOV  DS,  AX 

注:以累加器AX作过渡。代码段不要装填,堆栈段可装填,也可不装填。

典型例题:数据段定义及源程序指令系统分析综合举例

定义数据段如下:

DATA  SEGMENT 

A  DB  21H, ‘A’, 61H, 5,  ‘12345’

B  DW  5566H, 77H, ‘ba’

C  DD  1234H

D  DW  A+2, B  ;D+0与D+1定义A+2的偏移地址,D+3与D+4定义B的偏移地址。

E  DD   B      ;E的低字存放B的偏移地址,E的高字存放B所在段的段地址。

DATA  ENDS

注:假设数据段DATA在汇编连接时形成的段地址为073FH(即DS的值)

1、针对上述数据段DATA,完成下表关于DATA中的存储变量的内存分配示意图。

2、完成下面程序段语句旁边寄存器的值。

解:1、

存储单元逻辑地址

存储单元内容

符号变量名

073F:0000

21H

A+0

     0001

41H

A+1

     0002

61H

A+2

     0003

5

A+3

     0004

31H

A+4

     0005

32H

A+5

     0006

33H

A+6

存储单元逻辑地址

存储单元内容

符号变量名

073F: 0007

34H

A+7

     0008

35H

A+8

     0009

66H

B+0

     000A

55H

B+1

     000B

77H

B+1

     000C

00H

B+3

     000D

61H

B+4

     000E

62H

B+5

     000F

34H

C+0

     0010

12H

C+1

     0011

00H

C+2

     0012

00H

C+3

     0013

02H

D+0

     0014

00H

D+1

     0015

09H

D+2

     0016

00H

D+3

     0017

09H

E+0

     0018

00H

E+1

     0019

3FH

E+2

     001A

07H

E+3

2、    MOV  AX, DATA

       MOV  DS, AX                       ;DS=( 073FH )

       LEA   DX,  A+9                    ;DX=( 0009H )

       MOV  BX,  OFFSET  C+2            ;BX=( 0011H )

       MOV  BX,  WORD  PTR  C+3       ;BX=( 0200H )

       MOV  AL,  BYTE  PTR  C+8        ;AL=(  09H  )

       MOV  BX,  SEG B                  ;BX=(073FH)

说明:1、OFFSET <变量名>  表示取变量的偏移地址;SEG  <变量名>  表示取变量所在段的段地址

     2、BYTE PTR <变量名>  表示强制按字节类型访问该变量;WORD  PTR <变量名>  表示强制按字类型访问该变量。

     3、后面的存储单元可以按前面定义的符号变量名来访问。

子程序段内与段间及不同文件之调用编程

例:编程序计算S=1+2+3+…+100 并显示结果,要求主程序完成计算用子程序S=1+2+3+…+100的和,编写子程序OUTP完成显示S=1+2+3+…+100的和5050。

方案1:段内调用                              方案2:段间调用

DATA  SEGMENT                                         DATA  SEGMENT

S  DW 0                                                         S  DW  0

DATA  ENDS                                                   DATA  ENDS

STACK  SEGMENT  STACK                            STACK  SEGMENT  STACK

DW 100  DUP(?)                                              DW  100  DUP(?)

STACK  ENDS                                               STACK  ENDS

CODE SEGMENT                                         CODE1  SEGMENT

ASSUME CS:CODE,DS:DATA,SS:STACK      ASSUME CS:CODE1,DS:DATA,SS:STACK

START:MOV AX,DATA                                    START:MOV AX,DATA

      MOV DS,AX                                             MOV DS, AX

      MOV CX,100                                              MOV CX, 100

      MOV AX, 1                                                MOV AX, 1

 AA1: ADD S, AX                                           AA1: ADD S, AX 

      INC AX                                                     INC AX

      LOOP  AA1                                             LOOP  AA1

      CALL  NEAR  PTR  OUTP                    CALL  FAR  PTR  OUTP

      MOV AH,4CH                                            MOV AH, 4CH

      INT 21H                                                     INT 21H

OUTP  PROC  NEAR                                     CODE1  ENDS

      MOV  AX, S                                         CODE2  SEGMENT     

      MOV  CX, 0                                      ASSUME CS:CODE2

      MOV  BX, 10                                    OUTP    PROC    FAR

AA2:  INC  CX                                        MOV  AX, S

      MOV  DX, 0                                          MOV  CX, 0

      DIV  BX                                             MOV  BX, 10

      PUSH  DX                                         AA2:  INC  CX

CMP AX, 0                                                  MOV  DX,0

      JNZ  AA2                                              DIV  BX

 AA3: POP DX                                          PUSH  DX

      OR  DL, 30H                                           CMP  AX, 0

      MOV AH, 2                                                   JNZ  AA2

      INT 21H                                                          AA3:  POP  DX

      LOOP  AA3                                                   OR DL, 30H

      RET                                                              MOV AH, 2

OUTP  ENDP                                                               INT 21H

CODE  ENDS                                                        LOOP AA3

       END START                                                     RET

                                                                        OUTP  ENDP

                                                                        CODE2  ENDS

                                                                              END  START

方案3. 在不同程序文件中调用子程序

主程序文件:main.asm    主程序调用下面3个子程序文件,显示:ABC

子程序1文件: sub1.asm   该程序显示1个字符:A

子程序2:文件 sub2.asm   该程序显示1个字符:B

子程序3:文件 sub3.asm   该程序显示1个字符:C

上机实现如下:

第一步:编写主程序文件main.asm

        Extrn  sub1:far, sub2:far, sub3:far

        Stack  segment  para stack ‘stack’

         Dw  100  dup(?)

        Stack  ends

        Code  segment

               Assume cs:code, ss:stack

               Start:mov ax,stack

                    Mov ss, ax

                    Call   sub1

                    Call   sub2

                    Call   sub3

                    Mov ah,4ch

                    Int 21h

                    Code  ends

                    End  start

存盘,汇编成目标文件: main.obj

第二步:编辑子程序文件1:sub1.asm

     Public  sub1

     Code  segment

     Sub1  proc   far

         Assume cs:code

         St1:mov dl, ‘A’

            Mov  ah,2

            Int 21h

            Ret

     Sub1  endp

     Code  ends

            End  st1

存盘,汇编成目标文件: sub1.obj

第三步:编辑子程序文件2:sub2.asm

     Public  sub2

     Code  segment

     Sub2  proc   far

         Assume cs:code

         St2:mov dl, ‘B’

            Mov  ah,2

            Int 21h

            Ret

     Sub2  endp

     Code  ends

            End  st2

存盘,汇编成目标文件: sub2.obj

第四步:编辑子程序文件3:sub3.asm

     Public  sub3

     Code  segment

     Sub3  proc   far

         Assume cs:code

         St3:mov dl, ‘C’

            Mov  ah,2

            Int 21h

            Ret

     Sub3  endp

     Code  ends

            End  st3

存盘,汇编成目标文件: sub3.obj

第五步:有两种立法可连接生成可执行文件(MAIN.EXE文件)

方法一:

C:\MASM>link  main+sub1+sub2+sub3  回车(4次)

运行

C:\MASM>MAIN  回车

屏幕屡示:ABC

方法二:(采用建立子程序库的方法,即使用LIB命令)

操作如下:

第1步:创建子程序库:subm

C:\MASM>LIB  回车

Library  name : SUBM  回车

Library  does  not  exist, create?  Y  回车

Operations: +sub1+sub2+sub3  回车

List  file: subm   回车

第2步:连接生成可执行文件main.exe

C:\MASM>Link  main, , , subm  回车

第3步:运行

C:\MASM>MAIN  回车

屏幕显示:ABC

汇编语言程序运行结束的两种方式上机实例

题:编一程序,显示字符串“Hello!$”

方式一、调用DOS中断结束程序运行

DATA  SEFMENT

A  DB  ‘Hello!$’

DATA  ENDS

CODE  SEGMENT

ASSUME CS:CODE, DS:DATA

START:MOV AX, DATA

      MOV DS, AX

      LEA  DX, A

      MOV AH, 9

      INT  21H

      MOV AH,4CH

      INT 21H

      CODE  ENDS

CODE ENDS

      END START

方式二、以过程运行方式结束程序

DATA  SEFMENT

A  DB  ‘Hello!$’

DATA  ENDS

CODE  SEGMENT

ASSUME CS:CODE, DS:DATA

SUB1  PROC  FAR

       PUSH  DS

       XOR  AX, AX

       PUSH  AX

MOV AX, DATA

      MOV DS, AX

      LEA  DX, A

      MOV AH, 9

      INT  21H

      RET

SUB1  ENDP

CODE  ENDS

       END SUB1

第31-32节课 

中断与DOS中断

一、中断的概念 

中断是这样一个过程,当CPU内部或外部出现某种事件(中断源)需要处理时,中止正在执行的程序(断点),转去执行请求中断的那个事件的处理程序(中断服务程序),执行完毕,再返回被暂时中止执行的程序(中断返回指令IRET),从断点继续执行。

二、中断的分类

  1. 内部中断(也称软中断):由CPU内部事件引起的中断。

(1)除法出错中断(0号):若除数为0或除法运算溢出,产生一个向量号为0的内部中断。0型中断没有相应的中断指令,也不由外部硬件引起,故也称为“自陷”中断。

(2)单步中断(1号):每当TF=1时,在每条指令执行结束后,产生一个向量号为1的内部中断。中断执行过程:FLAGS入栈,TF和IF清零、以正常方式工作;中断结束,标志出栈,TF=1,又恢复单步中断工作方式。

(3)断点中断(3号):用于设置断点,停止正常程序的执行,将转去执行某种类型的特殊处理,用于调式程序。是指令中断中的一个特殊的单字节INT 3 指令中断(机器码:0CCH)。

(4)溢出中断(4号):溢出中断是在执行溢出中断指令INTO时,若OF=1,产生一个向量号为4的内部中断。

(5)指令中断(INT  n):产生一个向量号为n的内部中断,为两字节指令(INT 3除外)

用于系统定义或用户定义。

注:内部中断向量号除指令中断由指令指定外,其余都是预定好的,因此都不需要传递中断号,也不需要中断响应周期。指令中断的中断号n取值实际为:10H~FFH(十进制16~255)。

  1. 外部中断(也称硬件中断):是CPU外部中断请求信号引脚上输入有效的中断请求信号引起的,分为非屏蔽中断NMI(17号引脚)和可屏蔽中断INTR(18号引脚)

(1)非屏蔽中断NMI:由NMI引脚输入有效中断请求信号引起的一个向量号为2的外部中断。不可用软件屏蔽(不受IF位影响),而且是上升沿触发。NMI用来通知CPU发生了致命事件,如:电源掉电、存储器读写错、总线奇偶位错等。

(2)可屏蔽中断INTR:由CPU(18号)引脚INTR通常由中断控制器8259A的INT信号驱动,8259A又与请求中断的外设相连,INTR信号在每条指令的最后一个时钟周期采样的,需要传送中断向量号,需要中断响应周期。是否响应IF影响(即可屏蔽的概念。IF=1响应,否则不响应)。注:中断向量号08H~0FH,共8个外部硬件中断。CLI   IF=0;   STI   IF=1

3、中断类型及名称以及中断响应过程图如下

(1)中断分类图

(2)中断分类图2   清华社教材P316

(3) 8088/8086的中断源        

 

(中断响应过程图)

三、中断优先级

除法错→INTO→INT n→NMI→INTR→单步中断

(或:软中断→NMI→INTR→单步中断)

四、8086/8088 CPU图及中断控制器8259A的图

1.8086/8088 CPU介绍及图片

8086是Intel系列的16位微处理器,芯片上有4万个晶体管,采用 HMOS工艺制造,用单一的+5V电源,时钟频率为4.77MHz~10MHz。

8086有16根数据线和20根地址线,它既能处理16位数据,也能处理8位数据。可寻址的内存空间为1MB。

在取得IBM个人电脑部门敲定的重要销售合约之后,Intel 8088处理器不仅成为了IBM个人电脑的大脑,而且还让IBM个人电脑成为新款畅销产品。为此,Intel 8088处理器的成功,也将英特尔进入“财富杂志500大企业排行榜”,《财富》杂志将英特尔评为 “70年代最成功的企业”之一。Intel 8088晶体管数目约为2.9万颗。

1978年英特尔公司生产的8086是第一个16位的微处理器。很快Zilog公司和摩托罗拉公司也宣布计划生产Z8000和68000。这就是第三代微处理器的起点。8086微处理器最高主频速度为8MHz,具有16位数据通道,内存寻址能力为1MB。同时,英特尔还生产出与之相配合的数学协处理器i8087,这两种芯片使用相互兼容的指令集,但intel8087指令集中增加了一些专门用于对数、指数和三角函数等数学计算的指令。人们将这些指令集统一称之为 x86指令集。虽然以后英特尔又陆续生产出第二代、第三代等更先进和更快的新型CPU,但都仍然兼容原来的x86指令,而且英特尔在后续CPU的命名上沿用了原先的x86序列,直到后来因商标注册问题,才放弃了继续用阿拉伯数字命名。

1979年,英特尔公司又开发出了8088。8086和8088在芯片内部均采用16位数据传输,所以都称为16位微处理器,但8086每周期能传送或接收16位数据,而8088每周期只能传输8位。因为最初的大部分设备和芯片是8位的,而8088的外部8位的数据传送、接收能与这些设备相兼容。8088采用40针的DIP封装工作频率为6.66MHz、7.16MHz或8MHz,微处理器集成了大约29000个晶体管。

8086和8088问世后不久,英特尔公司就开始对他们进行改进。他们将更多功能集成在芯片上,这样就诞生了80186和80188。这两款微处理器内部均以16位工作,在外部输入输出上80186采用16位,而80188和8088一样是采用8位工作。

1981年,IBM公司将8088芯片用于其研制的PC机中,从而开创了全新的微机时代。也正是从8088开始,个人电脑(PC)的概念开始在全世界范围内发展起来。从8088应用到IBM PC机上开始,个人电脑真正走进了人们的工作和生活之中,它也标志着一个新时代的开始

具有40条引脚的双列直插式封装的CPU

 

2.中断控制器8259A的图

(1)D0~D7:双向数据线,与系统的数据总线相连。编程时控制字,命令字由此写入;中断响应时,中断向量码由此送给CPU。

(2)/WR,/RD为读写控制信号,与系统总线的/IOW,/IOR相连接。

(3)/CS为片选信号,当/CS为低电平时,8259A被选中,CPU才能对它进行读写操作。此引脚连到系统的I/O译码器输出,由此确定8259A在系统I/O地址空间的基地址。

(4)A0是8259A内部寄存器的选择信号,它与/CS,/WR,/RD信号相配合,对不同的内部寄存器进行读写。使用中,通常接地址总线的某一位,例如A1,A0等。

5INT8259A的中断请求输出信号,可以直接接到CPUINTR输入端

6/INTA为中断响应输入信号,在中断响应过程中CPU的中断信号由此端进入8259A

(7)CAS0~CAS2为级联控制线。当多片8259A级联工作时,其中一片为主控芯片,其它均为从属芯片。对于主片的8259A,其CAS0到CAS2为输出,对于各从属芯片的CAS0到CAS2为输入。主片的CAS0到CAS2与从片相同引脚对应相连。当从片提出中断请求时,主片通过CAS0到CAS2送出相应的编码给从片,使得从片的中断被允许。

(8)/SP/EN为双功能引线,工作在缓冲模式时,为输出,控制缓冲器的传送方向。CPU–>8259A为高电平,数据从8259A–>CPU为低电平。工作在非缓冲方式时,为输入,指定8259A是否为主片从片。/SP=1为主片,/SP=0为从片。系统中只有一片8259A时,接高电平。

(9)IR0~IR7为中断请求输入信号,与外设中断请求线相连,上升沿或高电(可编程设定)时表示有中断请求到达。

四、选择题:

1. 下列优先级最低的中断是(  D  )

(A)NMI     (B)INTR      (C)INTO      (D)向量号为1的单步中断

2. 下列哪个向量号的中断优先级最低(  B  )。

(A)0号      (B)1号        (C)2号       (D)3号

3.在8086中,NMI中断向量在中断向量表中的位置是( C   )

(A)是由程序指定     (B)是由DOS自动分配      (C)固定在00008H单元

(D)固定在中断向量表的表首 

五、中断向量表

1、中断向量表的概念及位置

注:

(1)上述1MB内存中的红色部分(即绝对地址00000开始,即00000H~003FFH地址空间,用逻辑地址空间表示为0000:0000H~0000:03FFH即1KB=1024字节)为中断向量表的(记录256个中断向量的程序入口地址CS:IP表)存储空间部分。

(2)如何计算某个中断向量的入口地址存放在中断向量表的位置呢?

计算方法:中断类型号n*4,得到(4n+1,4n)低字单元存放中断类号nIP值;(4n+3,4n+2)高字单元存放中断类号nCS值。

例:计算  INT 21H在中断向量表的位置。

解:21H*4=84H,即0000:0084H 和0000:0085H两个字节单元存放INT 21H的IP值;0000:0086H 和0000:0087H两个字节单元存放INT 21H的CS值。实验结果如下:

查上述内存表得INT 21H 中断处理程序的CSIP的值为F000:14A0H

通过反汇编命令U可查阅INT  21H 程序汇编语言代码  

-U F000:14A0  (详单略

  1. 中断指令及说明

中断指令格式: INT  中断号(0~255,或00H~0FFH)

共可有256个中断。其实指令中断的中断号取值:10H~0FFH  (只有240个)

中断向量号说明:

(1)0~4由系统定义,不允许用户修改;

(2)5~31是系统备用中断,是为软硬件开发保留,一般也不允许改为它用;

(3)32~255供用户自由应用。(但BIOS中断调用占用10H~1AH共11个;DOS中断占用20H~3FH共32个,其中A0H~BBH和30H~1AH 为DOS保留类型号)

(4)中断号60H~67H是为用户保留的软中断类型号,用户因此可实现自己的软中断处理

注:从类型号5开始,中断类型可以是双字节INT n指令中断,也可以是INTR的硬件中断。

4.中断返回指令:IRET

编写用户自己的中断处理程序(DOS 功能号为25HDOSINT 21H中断调用)

  1. 软中断处理程序说明
  1. 调用格式: INT  中断号

理论上“中断号”(0~255,或00H~0FFH),保留给普通用户自己编写中断处理程序的中断号:60H~67H

  1. 中断返回格式:IRET 

功能:返回源程序中调用软中断的下一条语句处,开始继续执行中断了的程序。

注:回想一下“子程序调用”和“宏调用”以及“中断调用”的异同点。

2、用户软中断处理程序创建步骤

第一步:创建中断处理子程序

方法步骤:与创建“调用不同文件之间的子程序”方法一样。即在中断子程序名前(中断子程序名  PROC  FAR)面的一个语句行为:PUBLIC  中断子程序名,中断子程序最后的返回语句为IRET根据子程序的需求定义中断调用的入口参数(可选),其它与“调用不同文件的子程序”创建完全一样。

第二步:主程序中如何调中用户中断子程序?

  1. 调用前,设置用户中断向量表

即中断子程序的所在段地址送DS,中断子程序所在段内的偏移地址送DX,功能号25H送AH,用户中断号送AL,再调DOS的INT  21H

例:假设用户中断程序过程名为inttab1, 开发的中断号为66H,即在主程序中编写如下语句:

MOV  DS,  SEG  inttab1

MOV  DX,  OFFSET  inttab1

MOV  AX,  2566H

INT   21H

;66Hx4=0198H

  1. 用户中断调用

在主程序需要的位置编写语句:

第一步:置入口参数(可选)

第二步: INT  用户中断号

 

简易用户中断调用程序编写上机举例

一、设置中断向量(DOS的25H调用)

调用前,AL中为设置的中断类型号,DS:DX指向欲设置的中断向量值(中断处理程序的入口地址)。调用后,该中断向量被置入中断向量表中。

二、最简单的用户中断调用程序编写举例(注:60H~67H  为用户保留的软中断

开发一个中断向量号为66H的中断处理程序,该中断程序INT  66H执行格式如下:

  1. 入口参数:置十进制两位数整数BH,十进制两位数整数BL(确保和小于100)
  2. 出口参数:屏幕显示两位十进制数BH与BL的和

第一步:编写一个中断调用子程序:inttab1.asm

code segment

assume cs:code

public inttab1

inttab1 proc far

        mov al,bl          ;定义入口参数BL

        add al,bh          ;定义入口参数BH

mov ah,0           ;以下指令部分完成两个两位十进数和的输出

 mov bl,10

        div bl              ;AX/BL  商在AL,余数在AH

        push ax

        mov dl,al           ;显示商

        or dl,30h

        mov ah,2

        int 21h

        pop dx

        mov dl,dh           ;显示余数

        or dl,30h

        mov ah,2

        int 21h

        iret            ;中断返回

 inttab1 endp

       code ends

       end

存盘退出,操作如下(将inttab1.asm 汇编成inttab1.obj):

 

第二步:编写主程序:mainint1.asm ,置入口参数BH,BL后,调用中断 int 66H,显示十进制结果。

stack segment para stack 'stack'          ;定义堆栈

dw 100 dup(?)

stack ends

data segment

a db 57,19                                ;定义两个两位十进制字节数57与19

data ends

extrn inttab1:far

code segment

assume cs:code,ds:data,ss:stack

      start:mov ax,seg inttab1            ;设置int 66H  中断向量

            mov ds,ax

            mov dx,offset inttab1

            mov ax,2566h

            int 21h

            mov ax,data

            mov ds,ax

            mov bh,a                        ;置int 66H的两个入口参数BH与BL

            mov bl,a+1

            int 66h                         ;执行int 66H

            mov ah,4ch

            int 21h

            code ends

                 end start

存盘退出,完成如下操作:(将mainint1.asm 汇编成 mainint1.obj)

 

第三步:生成运行文件:mainint1.exe 检验运行结果:57+19=?

 

运行结果如下:

 

上机作业1编写一个中断处理程序INT 62H,  该程序的入口参数为AX,该程序的功能是显示AX的十进制值。

上机作业2(升级版):编写一个中断处理程序INT 63H, 该程序的两个入口参数为AX,BX。其中AX中是一个整数,BX是另一个整数,将AX中的整数转化成BX进制且显示输出(例在主程序中分别输入:23578和8,AX=23578, BX=8,即把十进制23578化8进制显示输出)。主程序的功能是通过键盘输入一个两个整数,输入的第一个整数作为转换进制的对象,输入的第二个整数为转换的进制。

       上机作业2 解答如下:

第一步:编辑用户中断处理子程序inttab2.asm

C:\>edit  inttab2.asm               ;编辑中断处理子程序inttab2.asm

public inttab2

code segment

assume cs:code

inttab2  proc far

         mov cx, 0

    aa1:inc cx

       mov dx,0

       div bx                   ;(DX,AX)/ BX 商送AX,余数送DX

       push dx

       cmp ax, 0

       jnz aa1

   aa2:pop dx

       cmp dl,9

       jg yy1

       or dl,30h

       mov ah,2

       int 21h

       loop aa2

       cmp cx,0

       jz yy2

   yy1:add dl,37h

      mov ah,2

      int 21h

      loop aa2

   yy2:iret

   inttab2 endp

   code ends

        end

存盘,并将其汇编成:inttab2.obj

第二步:编辑调用中断子程序的主程序mainint.asm

C:\>edit  mainint.asm

extrn  inttab2:far               ;说明调用外部的中断子过程名

outlin macro                     ;定义一个输出回车换行的宏指令outlin

mov dl,0dh

mov ah,2

int 21h

mov dl,0ah

mov ah,2

int 21h

endm                              ;定义宏指令outlin结束

data segment

s1  dw  0

s2  dw  0

data ends

code segment

assume cs:code,ds:data

      start:mov ax, seg inttab2   ;设置用户中断向量int 63H

            mov ds,ax

            mov dx, offset inttab2

            mov ax,2563H

            int 21h

            mov ax,data

            mov ds,ax

            call inpu             ;调用子程序输入第一个整数到bx

            mov s1,bx             ;将bx保存在字变量s1中

            outlin                ;显示回车换行

            call inpu             ;调用子程序输入第一个整数到bx

            mov s2,bx             ;将bx保存在字变量s1中

            mov  ax,s1            ;为调用int 63H,置第一个入口参数ax

            mov  bx,s2            ;为调用int 63H,置第一个入口参数bx

            int 63h                 ;调用用户中断程序int 63h

            mov ah,4ch

            int 21h

        inpu proc                   ;键盘输入多位数整数的子程序inpu

            mov bx,0

       aa2: mov ah,1

            int 21h

            sub al,30h

            jl exit

            cmp al,09h

            jg exit

            cbw

            xchg ax,bx

            mov cx,10

            mul cx

            xchg ax,bx

            add bx,ax

            jmp aa2

         exit:ret                   ;子程序inpu 返回

        inpu endp                   ;子程序inpu结束

            code ends

                 end start          ;主程序结束搭配语句

存盘退出,将主程序mainint.asm 汇编成mainint.obj 文件

第三步:连接生成执行文件mainint.exe    (有3种连接生成EXE可执行文件的方法,略)

上机操作序列示例如下:

(1)将inttab2.asm 汇编成inttab2.obj

 

(2)将mainint.asm 汇编成mainint.obj

 

(3) 将mainint.obj与inttab2.obj连接生成mainint.exe

 

(4) 程序运行演示

下面的结果是:(89)10=( 1011001) 2  (89) 10=(59) 16  (74) 10=( 4A) 16   (298) 10=(100101010) 2

​​​​​​​

 

 

  • 2
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嗨!对于逆向学习汇编语言学习笔记,我可以给你一些基本的指导。首先,汇编语言是一种低级语言,它与计算机的底层硬件密切相关。逆向工程则是通过分析和理解已编译的程序来获取程序的内部信息。 以下是一些学习汇编语言和逆向工程的建议: 1. 学习基础知识:了解计算机体系结构、寄存器、内存和指令集等基础概念是必要的。可以先阅读相关的书籍或在线教程,掌握这些基本概念。 2. 掌握汇编语言的语法和指令集:每种计算机体系结构都有自己的汇编语言语法和指令集。选择一种你感兴趣的体系结构(如x86、ARM等),并学习它的汇编语言。 3. 练习编写和调试汇编代码:通过编写简单的汇编代码来熟悉语法和指令集。使用调试器来单步执行代码并观察寄存器和内存的变化。 4. 分析已编译程序:选择一个目标程序进行逆向分析。使用反汇编器将程序转换为汇编代码,并分析代码的逻辑和功能。这有助于理解程序的结构和运行过程。 5. 使用调试器进行动态分析:通过调试器来动态地执行程序,并观察程序在运行时的行为。使用断点、内存查看器和寄存器查看器等工具来分析程序的状态和数据。 6. 学习逆向工程工具和技术:了解常用的逆向工程工具和技术,如IDA Pro、OllyDbg、Ghidra等。掌握这些工具的使用可以提高你的逆向分析能力。 7. 参考优秀资源:阅读与逆向工程和汇编语言相关的书籍、论文和博客,关注相关的社区和论坛。与其他逆向工程师交流经验也是很有帮助的。 记住,逆向工程是一个需要耐心和实践的过程。持续学习和实践将帮助你提高逆向分析的技能。祝你在学习汇编语言和逆向工程的过程中取得好成果!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值