微机4-12上第2章已学汇编课件_第1页
微机4-12上第2章已学汇编课件_第2页
微机4-12上第2章已学汇编课件_第3页
微机4-12上第2章已学汇编课件_第4页
微机4-12上第2章已学汇编课件_第5页
已阅读5页,还剩100页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第2章

指令系统及汇编语言程序设计2.18088/8086的寻址方式2.28088/8086的指令系统2.3汇编语言汇编语言源程序格式伪指令汇编语言源程序结构2.4汇编语言程序设计基本程序设计方法DOS功能调用顺序程序设计分支程序设计循环程序设计子程序设计本次课内容请大家复习《汇编语言》掌握本节内容第二章复习小结下次课5.9汇编语言单元考试及讲第3章2.3汇编语言汇编语言的特点汇编语言是一种以处理器指令系统为基础的低级程序设计语言,它采用助记符表达指令操作码利用汇编语言编写程序的主要优点是可以直接、有效地控制计算机硬件,因而容易创建代码序列短小、运行快速的可执行程序在有些应用领域,汇编语言的作用是不容置疑和无可替代的汇编程序设计的过程是与其他高级语言程序设计大致相同什么是汇编语言以助记符形式表示计算机指令助记符(mnemonic)是便于人们记忆、并能描述指令功能和指令操作数的符号助记符是表明指令功能的英语单词或其缩写汇编格式指令以及使用它们编写程序的规则就形成汇编语言(AssemblyLanguage)汇编语言程序:用汇编语言书写的程序汇编程序:将汇编语言程序“汇编”成机器代码目标模块的程序汇编语言程序与汇编程序是两个概念硬指令和伪指令汇编程序将汇编语言源程序翻译成在机器上能执行的机器语言程序(目的代码程序硬指令---执行性语句使CPU产生动作、并在程序执行时才处理的语句,就是第2章学习的处理器指令与具体的处理器有关、与汇编程序无关。汇编后对应一条指令代码伪指令(Directive)---说明性语句不产生CPU动作、在程序执行前由汇编程序处理的说明性语句,例如,数据说明、变量定义等等伪指令与具体的处理器类型无关,但与汇编程序的版本有关本课程采用微软宏汇编程序MASM6.15硬指令和伪指令采用易于记忆的符合表达,这就是助记符

MOVCX,0;传送指令,具有2个操作数DELA: NOP

;空操作指令,没有操作数,带有标号

LOOPDELA;循环指令,标号DELA说明转移位置BUFDB1,2,3,4,5,6,7

;数据定义伪指令,在主存中开辟7个连续的字节单元,初值依次为1~7,BU表示首地址汇编语言语句实例一.汇编语言源程序格式(4部分)标号

硬指令的位置(逻辑地址),后加冒号:

名字

伪指令的位置或存储单元名称(变量名),后不加冒号:一般最多由31个字母、数字及规定的特殊符号(如_、$、?、@)组成不能以数字开头(如1ABC错),不能是保留字指令助记符

必须有,其它3部分可无伪指令助记符----伪指令硬指令助记符-----硬指令注释语句中由分号“;”开始的部分为注释内容,用以增加源程序的可读性必要时,一个语句行也可以由分号开始作为阶段性注释汇编程序在翻译源程序时将跳过该部分,不对它们做任何处理标号: 硬指令助记符操作数1,操作数2

;注释名字伪指令助记符参数1,参数2,…;注释例:

硬指令

Done:moval,02h

伪指令Sumdb02h[标号]指令助记符[操作数][;注释]

汇编语言源程序格式---操作数操作数常数、数值表达式、寄存器、标号、变量等数值表达式一般是指由运算符连接的各种常数所构成的表达式汇编程序在汇编过程中计算表达式,最终得到一个确定的数值,所以也是常数常用的运算符是加减乘除(+-*/)

例:movax,3*4+5 ;等价于movax,17汇编语言源程序格式---操作数操作数常数、寄存器、标号、数值表达式、变量等常数汇编时已确定的数据如硬指令中立即数二进制数如MOVAL,10110101B十进制常数如MOVAL,181十六进制数常数以字母开头的十六进制数前加“0”。例:MOVAL,0B5H字符和字符串常数例:MOVAX,’AB’;AX4142h

MOVAX,’1’;AX31h用单引号括起来的单个字符或多个字符,其数值是每个字符对应的ASCII码的值.例如:'d'=64H,'AB'=4142H符号常数用符号名表示一个常数,可以提高程序的可读性,同时更具有通用性符号定义伪指令格式等价EQU伪指令符号名EQU表达式例:XY EQU5等号=伪指令符号名=表达式例:XY=5例:XY EQU 5MOVAH,XY;等价于MOVAH,5符号定义

DosWriteCharequ2 CarriageReturn=13 CallDOSequ<int21h>符号应用(左边程序段等价右侧的符号形式) movah,2 ;movah,DosWriteChar movdl,13 ;movdl,CarriageReturn int21h ;CallDOS符号常数实例2.变量定义伪指令(定义数据伪指令)变量定义伪指令为变量申请固定长度的存储空间,同时将相应存储单元初始化(参数为?则不初始化)。格式为:变量名DB/DW/DD/DQ参数1,参数2,…DB(或BYTE)定义字节其后每个参数占1个字节存储单元DW(或WORD)定义字其后每个参数占2个字节(先低字节后高字节)存储单元DD(或DWORD)定义双字其后每个参数占4个字节存储单元DQ(或QWORD)定义4个字其后每个参数占8个字节存储单元多个存储单元如果初值相同,可以用复制操作符DUP进行定义:

重复次数DUP(重复参数)变量实质指内存单元的数据,变量需要事先定义才能使用.定义后的变量可用变量名等引用其中的数据,即变量的数值例:alpha byte 30h,2DUP(55H),34h,?mov cx,alpha;cx5530h mov bx,offsetalpha mov al,[bx+3] ;al34h变量定义伪指令最常使用定义字节单元伪指令DBDB伪指令用于分配一个或多个字节单元,并可以将它们初始化为指定值初值表中每个数据一定是字节量(Byte),存放一个8位数据:可以是0~255的无符号数或是-128~+127带符号数也可以是字符串常数字节变量定义实例;数据段Xdb61h,0fbhdb2dup(64h),?Ydb'ABC'应用moval,XdecX+1movY,alASCII‘a’=61h’A’=41h‘B’=42h‘C’=43h;此处X表示它的第1个数据,故AL←61h;对X为始的第2个数据减1,故为0fah;Y=al=61h,现在Y这个字符串成为'aBC'定义字单元伪指令DWDW伪指令用于分配一个或多个字单元,并可以将它们初始化为指定值初值表中每个数据一定是字量(Word),一个字单元可用于存放任何16位数据:一个段地址一个偏移地址两个字符

0~65535之间的无符号数-32768~+32767之间的带符号数字变量定义实例;数据段count dw8000h,?,'AB'maxint equ64hnumber dwmaxintarray dwmaxintdup(0)ASCII’A’=41h‘B’=42h;数据段字变量和字常量的定义:WNUMEQU5678H;定义WNUM为常量COUNTDW20H;定义COUNT变量,假设在数据段的偏移地址为0010H;代码段字变量和字常量的应用:MOVAX,[BX+SI+WNUM] 等价于MOVAX,[BX+SI+5678H]

MOVAX,COUNT 等价于MOVAX,[0010H] ;AX0020HMOVAX,[SI+COUNT]等价于MOVAX,[SI+0010H]LEABX,COUNT 等价于LEABX,[0010H];BX0010HMOVBX,OFFSETCOUNT 等价于MOVBX,0010H;BX0010H字变量和字常量实例串操作类指令8088的串操作类指令能对主存中一个连续区域的数据(如数组、字符串等)进行传送、比较等同样操作。当DF=0地址自动增量,从低地址到高地址处理字符串;当DF=1地址减量指令有:传送数据串:MOVS,STOS,LODS检测数据串:CMPS,SCAS重复前缀:REP,REPZ,REPNZ源操作数----DS:[SI]目的操作数---ES:[DI]每执行一次串操作指令,SI和DI将自动修改:±1(对于字节串)或±2(对于字串)执行指令CLD后,DF=0,地址指针增1或2执行指令STD后,DF=1,地址指针减1或2利用循环程序也可以实现串操作指令的功能例:MOVSB(movestringbyte)

;ES:[DI]←DS:[SI];当DF=0,SI←SI+1DI←DI+1当DF=1,SI←SI-1DI←DI-1例.数据复制和显示 .modelsmall .stack .datasource db 33h,34h,35h,36h ;定义4个字符数据target db 80dup(?) ;分配数据空间4×20=80 .code .startup mov ax,ds mov es,ax ;data也作为附加段 cld mov si,offsetsource mov di,offsettarget mov cx,80

rep movsb

;串传送 mov si,0 ;显示 mov bx,offsettargetagain: mov dl,[bx+si] mov ah,2 int 21h inc si cmp si,80 jb again .exit0 end3.宏(Macro)命令伪指令为简化程序编制,对多次使用的程序,既可用子程序也可用宏指令、宏汇编实现宏定义宏是具有宏命令名的一段汇编语句序列 宏命令名

MACRO[形参数1,参数2,…]

…… ;宏定义体(硬指令、伪指令)

ENDM

宏调用

宏命令名[实参数1,参数2,…]宏需要先定义,然后才可在程序中宏调用,形式上类似其他指令,常称其为宏指令宏指令实际上是一段代码序列的缩写。在汇编时,宏指令被汇编程序用对应的代码序列替代,这就是宏展开因为是在汇编过程中实现的宏展开,所以常称为宏汇编宏与子程序的比较比较仅是源程序级的简化:宏调用在汇编时进行程序语句的展开,不需要返回;不减小目标程序,执行速度没有改变还是目标程序级的简化:子程序调用在执行时由CALL指令转向、RET指令返回;形成的目标代码较短,执行速度减慢宏子程序定位伪指令定位伪指令控制数据的偏移地址ORG参数ORG伪指令是将当前偏移地址指针指向参数表达的偏移地址:ORG100h ;从100h处安排数据或程序ORG$+10;使偏移地址加10,即跳过10个字节空间MASM中,符号“$”表示当前偏移地址值EVEN ;从偶地址开始ALIGNn ;从n的整数倍地址开始 org$+10array db45,45h .code movax,segarray movds,ax movbx,offsetarray ;等价于leabx,array movcl,array+4 ;等效于movcl,array[4] movax,es:[2000h]地址操作符实例

加4个字节单元属性运算符PTR对名字或标号的类型属性进行设置

类型名PTR名字/标号类型名可以是BYTE、WORD、DWORD(依次表示字节、字、双字)等,或者是NEAR、FAR(分别表示近、远)定义的类型例:moval,byteptrvar ;var是一个字节变量jmpfarptrlabel ;label是一个标号decwordptr[di]incbyteptr[di]使用PTR操作符,可以临时改变名字或标号的类型8088CPU的存储格式--小端存储方式D7D0字节D15D0字D31D0双字00006H78H00005H56H00004H12H00003H34H00002H00001H00000H低地址LSBMSB00002H单元的内容为:[00002H]=34H00002H“字”单元的内容为:[00002H]=1234H00002H号“双字”单元的内容为:[00002H]=78561234H多字节数据在存储器中占连续的多个存储单元存放:低字节存入低地址,高字节存入高地址表达:用低地址表示多字节数据占据的地址空间同一个存储器地址可以是字节单元地址、字单元地址、双字单元地址等等设DS=000002H“双字”单元MOVEAX,[0002H]00002H“字”单元MOVAX,[0002H]00002H单元

MOVAH,[0002H高地址存储单元D7D0存储器地址 .modelsmall .stack .datav_byte equthisbyte;v_byte是字节类型,与变量v_word的地址相同v_word dw3332h,3735h

;v_word是字类型的变量target dw5dup(20h)

;分配数据空间2×5=10字节crlf db0dh,0ah,'$'flag db0n_point dwoffsets_label

;取得标号s_label的偏移地址例3.4:属性及其应用-1/5例3.4:属性及其应用-2/5 .code .startup moval,byteptrv_word;用PTR改变v_word的类型,否则类型不匹配 decal movv_byte,al;对v_word的头一个字节操作,原为32H、现为31Hn_label: cmpflag,1 jzs_label ;flag单元为1转移 incflag jmpn_label ;进行短转移例3.4:属性及其应用-3/5s_label: cmpflag,2 jznext ;flag单元为2转移 incflag

jmpn_point;段内的存储器间接寻址,转移到s_label标号处next: movax,typev_word ;汇编结果为movax,2 movcx,lengthoftarget ;汇编结果为movcx,5例3.4:属性及其应用-4/5 movsi,offsettargetw_again: mov[si],ax ;对字单元操作 incsi ;SI指针加2 incsi loopw_again ;循环 movcx,sizeoftarget

;汇编结果为movcx,0ah moval,'?' movdi,offsettargetb_again: mov[di],al ;对字节单元操作 incdi ;DI指针加1 loopb_again ;循环例3.4:属性及其应用-5/5 movdx,offsetv_word ;显示结果:1357?????????? movah,9 int21h .exit0 end四.汇编语言源程序结构完整的汇编语言源程序由段组成一个汇编语言源程序可以包含若干个代码段、数据段、附加段或堆栈段,段与段之间的顺序可随意排列需独立运行的程序必须包含一个代码段,并指示程序执行的起始点,一个程序只有一个起始点所有的硬指令语句必须位于某一个代码段内,伪指令语句可根据需要位于任一段内通常,程序还需要一个堆栈段源程序由语句序列构成汇编语言翻译器(汇编程序,如MASM)对源程序有严格格式要求,才能将之翻译成目的代码段寄存器及逻辑段分配段寄存器及逻辑段分配8088CPU访问内存有20条地址线共220B=1MB个存储单元FFFFFH,内存地址00000H~FFFFFH8088CPU将1MB空间分成许多段,有4个16位段寄存器,对应4种逻辑段.每个段最大限制为64KBCodeSegment代码段StackSegment堆栈段DataSegment数据段ExtraSegment附加段8088有4个16位段寄存器CS(CodeSegmentRegister)指令SS(StackSegmentRegister)堆栈DS(DataSegmentRegister)数据ES(ExtraSegmentRegister)数据每个段寄存器用来确定一个逻辑段的起始地址,每种逻辑段均有各自的用途程序的指令序列必须安排在代码段CS程序使用的堆栈一定在堆栈段SS程序中的数据默认是安排在数据段DS,也经常安排在附加段ES,尤其是串操作的目的区必须是附加段汇编语言源程序格式源程序分别用两种格式书写第一种格式从MASM5.0开始支持简化段定义格式第二种格式MASM5.0以前就具有完整段定义格式(一般了解)求较大值—两无符号数AX、BX的较大值放入wmax例:程序功能简单,要求掌握求较大值—两无符号数AX、BX的较大值放入wmax

汇编语言程序实例wmax dw 0 cmpax,bx ;比较AX和BX jncnext ;若AX≥BX,转移 xchgax,bx ;若AX<BX,交换next: movwmax,ax简化段定义格式

求较大值—两无符号数AX、BX的较大值放入wmax

.modelsmall .data ;定义数据段wmax dw 0

.code ;定义代码段start: movax,@data ;程序起始点,建立DS movds,ax cmpax,bx ;比较AX和BX jncnext ;若AX≥BX,转移 xchgax,bx ;若AX<BX,交换next: movwmax,ax

.exit0 ;程序正常执行结束 endstart ;汇编结束

程序数据定义汇编语言程序实例stack segmentstack ;定义堆栈段 dw512dup(?) ;堆栈段有512字(1024字节)空间stack ends ;堆栈段结束data segment ;定义数据段wmax dw0data endscode segment’code’ ;定义代码段 assumecs:code,ds:data,ss:stackstart: movax,data ;建立DS段地址 movds,ax

cmpax,bx ;比较AX和BX jncnext ;若AX≥BX,转移 xchgax,bx ;若AX<BX,交换next: movwmax,ax

movax,4c00h int21h ;利用功能调用返回DOScode ends ;代码段结束 endstart ;汇编结束,同时指明程序起始点例:完整段定义格式完整段定义格式程序例题stack segmentstack dw512dup(?)stack endsdata segment …… ;数据定义(数据待填)data endscode segment’code’ assumecs:code,ds:data,ss:stackstart: movax,data movds,ax …… ;主程序(指令待填) movax,4c00h int21h

…… ;子程序(指令待填)code ends endstart完整段定义格式

MASM5.x支持源程序格式(一般了解)例题源程序格式(重点掌握)

.modelsmall;定义程序的存储模式 .data ;定义数据段

…… ;在数据段定义数据 .code ;定义代码段

.startup;程序起始点,设置DS、SS

…… ;主程序(指令待填) .exit0 ;程序结束点,返回DOS

…… ;子程序(指令待填) end ;汇编结束温馨提示:可以无数据段常用简化段定义格式

MASM6.x支持例题或者源程序格式(重点掌握)

.modelsmall;定义程序的存储模式 .data ;定义数据段

…… ;在数据段定义数据 .code ;定义代码段start: movax,@data;程序起始点,设置数据段段地址DS

movds,ax

…… ;主程序(指令待填) .exit0 ;程序结束点,返回DOS

…… ;子程序(指令待填) endstart ;汇编结束温馨提示:可以无数据段常用简化段定义格式

MASM6.x支持例题1.简化段定义格式

(1)源程序格式数据段定义伪指令.DATA创建一个数据段代码段定义伪指令.CODE创建一个代码段堆栈段由Windows维护,用户不必设置程序开始执行的位置应用一个标号(例如:START)汇编结束END指令的参数应用程序执行结束语句“EXIT0”将控制权交还操作系统提供给操作系统一个返回代码通常用0表示执行正确源程序汇编结束END语句执行结束≠汇编结束;SampleA.ASM .modelsmall .stack .data

... ;在数据段定义数据 .code .startup

... ;在代码段填入指令序列 .exit0

...

;子程序代码 end简化段定义格式

MASM6.x支持;SampleC.ASM .modelsmall .stack .data ... ;在数据段定义数据 .codestart:movax,@data movds,ax

... ;在代码段填入指令序列 movax,4c00h int21h

...

;子程序代码 endstart简化段定义格式

MASM5.x支持.modelsmall;定义程序的存储模式.data ;定义数据段.code ;定义代码段 .exit0 ;程序结束点,返回DOSend ;汇编结束(2)简化段定义格式伪指令存储模式伪指令.MODEL存储模式使用简化段定义,必须有存储模式伪指令.model语句必须位于所有段定义语句之前存储模式决定一个程序的规模,确定进行子程序调用、指令转移和数据访问的缺省属性MASM有7种不同的存储模式:①TINY ②SMALL③COMPACT ④MEDIUM⑤LARGE ⑥HUGE⑦FLATSMALL小型模式一般的程序(例如本书的绝大多数程序示例和习题)都可用这种模式在小型模式下,一个程序至多只能有一个代码段和一个数据段,每段不大于64KB这里的数据段是指数据段、堆栈段和附加段的总和,它们共用同一个段基址,总长度不可超过64KB;因此小模式下程序的最大长度为128KB访问操作数或指令都只需要使用16位偏移地址;这意味着诸如指令转移、程序调用以及数据访问等都是近属性(NEAR),即小型模式下的调用类型和数据指针缺省分别为近调用和近指针简化段定义伪指令.STACK[大小] ;堆栈段开始.DATA ;数据段开始.CODE[段名] ;代码段开始简化段定义伪指令指明一个逻辑段的开始,同时自动结束前面的一个段采用简化段定义伪指令前,需有.model语句使用简化段定义,各段名称和其他用户所需的信息可以使用MASM预定义符号,例如:@data表示由.data等定义的数据段的段名堆栈段伪指令.STACK[大小]堆栈段伪指令.STACK创建一个堆栈段,段名是:stack它的参数指定堆栈段所占存储区的字节数,默认是1KB(=1024=400h字节)数据段伪指令.DATA数据段伪指令.data创建一个数据段,段名是:_DATA。它用于定义具有初值的变量,当然也允许定义无初值的变量无初值变量可以安排在另一个段中,它用.data?伪指令创建,数据段名是:_BSS.const伪指令用于建立只读的常量数据段(段名:CONST)代码段伪指令.CODE[段名]代码段伪指令.code创建一个代码段,它的参数指定该代码段的段名如果没有给出段名,则采用默认段名:在TINY、SMALL、COMPACT和FLAT模式下,默认的代码段名是:_TEXT在MEDIUM、LARGE和HUGE模式下,默认的代码段名是:模块名_TEXT程序开始伪指令.STARTUP按照CPU类型、存储模式、操作系统和堆栈类型,产生程序开始执行的代码;同时还指定程序开始执行的起始点在DOS下,还将设置DS值,调整SS和SP值movdx,dgroupmovds,dx ;设置DSmovbx,sssubbx,dxshlbx,1shlbx,1shlbx,1shlbx,1cli ;关中断movss,dx ;调整SS和SPaddsp,bxsti ;开中断movdx,@datamovds,dx 程序终止伪指令.EXIT[返回参数]产生终止程序执行返回操作系统的指令代码它的可选参数是一个返回的数码,通常用0表示没有错误。例如.exit0对应的代码是:movax,4c00hint21hDOS功能调用的4ch子功能(返回DOS):入口参数:AH=4ch,AL=返回数码汇编结束伪指令END[标号]指示汇编程序MASM到此结束汇编过程源程序的最后必须有一条END语句可选的标号用于指定程序开始执行点,连接程序将据此设置CS:IP值采用了.startup伪指令就不需要再用“end标号”指明开始执行点,但还要有end伪指令

————不要糊涂————程序终止和汇编结束是两码事;主程序

moval,04h ;提供参数AL callhtoasc ;调用子程序retp1:movbl,0fh;retp1为返回地址 hlt;子程序:将AL低4位的一位16进制数转换成ASCII码htoasc: andal,0fh ;只取al的低4位 oral,30h ;al高4位变成3 cmpal,39h ;是0~9,还是0Ah~0Fh jchtend addal,7 ;是0Ah~0Fh,加上7htend: ret ;子程序返回ASCII码’0’=30h…‘9’=39h’A’=41h‘B’=42h…ACII码转换子程序调用程序 .modelsmall

;定义程序的存储模式

.code ;定义代码段start: movax,@data;程序起始点,建立DS

movds,ax

moval,04h ;提供参数AL callhtoasc ;调用子程序retp1: movbl,0fh ;retp1为返回地址 hlt .exit0 ;程序正常执行结束htoasc: ;子程序将AL低4位转换成ASCII码 andal,0fh ;只取al的低4位 oral,30h ;al高4位变成3 cmpal,39h ;是0~9,还是0Ah~0Fh jchtend addal,7 ;是0Ah~0Fh,加上7htend: ret ;子程序返回 endstart ;汇编结束简化段定义格式--例1ACII码转换子程序调用程序无数据段主程序子程序编程实现将sum开始的8个无符号数的和放至bpt开始的两个存储单元中;数据段sum db8dup(2)bpt dw? ;存放最大值;代码段

mov cx,8 mov si,offsetsum;存放无符号数的存储单元首地址赋给si xor ax,ax ;ax及进位CF清零done: add al,[si] adc ah,0 inc si;指向下一个无符号数的存储单元地址loopdone;cx-1≠0转向done

mov bx,offsetbpt;cx-1=0(8个无符号数已求完和)bxbpt偏移地址mov[bx],ax;则将此和放至bpt存储单元 hlt 循环程序结构loop循环指令循环指令用于控制程序的重复执行,根据CX(存放循环次数)决定循环(转移至目标地址label)还是顺序执行(下一条指令)循环指令

LOOP

label

CX-1≠0,则转移(首先CX←CX-1;然后判断若CX≠0,转移到label;否则,顺序执行)LOOPZ/LOOPE

label

CX-1≠0且ZF=1,则转移LOOPNZ/LOOPNElabel

CX-1≠0且ZF=0,则转移

JCXZlabelCX=0,则转移CMPCX,0JZlabeldececxjnzlabel简化段定义格式--例2

编程实现将sum开始的8个无符号数的和放至bpt开始的两个存储单元中

.modelsmall .data ;定义数据段sum db8dup(2)bpt dw? ;存放最大值 .code ;定义代码段start: movax,@data ;程序起始点,建立DS

movds,ax

mov cx,8 mov si,offsetsum;存放无符号数的存储单元首地址赋给si xor ax,ax ;ax及进位CF清零done: add al,[si] adc ah,0 inc si ;指向下一个无符号数的存储单元地址 Loopdone ;cx-1≠0转向done

mov bx,offsetbpt

;cx-1=0(8个无符号数已求完和)bxbpt偏移地址mov[bx],ax ;则将此和放至bpt存储单元hlt.exit0 ;程序正常执行结束 endstart ;汇编结束

程序数据定义完整段定义伪指令段名 segment 定位组合段字'类别' ... ;语句序列段名 ends完整段定义由SEGMENT和ENDS这一对伪指令实现,SEGMENT伪指令定义一个逻辑段的开始,ENDS伪指令表示一个段的结束段定义指令后的4个关键字用于确定段的各种属性,堆栈段要采用stack组合类型,代码段应具有‘code’类别,其他为可选属性参数如果不指定,则采用默认参数;但如果指定,注意要按照上列次序2.完整段定义格式

完整段定义利用SEGMENT和ENDS一对伪指令定义逻辑段同时需要配合ASSUME伪指令指明逻辑段是代码段、堆栈段、数据段还是附加段程序设计中常将具有一定功能的程序设计成一个过程。代码段中可有若干个过程指定段寄存器伪指令ASSUME段寄存器:段名[,段寄存器名:段名,...]通知MASM用指定的段寄存器来寻址对应的逻辑段,即建立段寄存器与段的缺省关系在明确了程序中各段与段寄存器之间的关系后,汇编程序会根据数据所在的逻辑段,在需要时自动插入段超越前缀。这是ASSUME伪指令的主要功能ASSUME伪指令并不为段寄存器设定初值,连接程序LINK将正确设置CS:IP和SS:SP由于数据段通常都需要,所以在样板源程序中,首先为DS赋值;如果使用附加段,还要赋值ESstack segmentstack dw512dup(?)stack endsdata segment …… ;在数据段定义数据data endscode segment’code’ assumecs:code,ds:data,ss:stackstart: movax,data movds,ax …… ;主程序(指令待填) movax,4c00h int21h

…… ;子程序(指令待填)code ends endstart完整段定义格式

MASM5.x支持源程序格式(一般了解)例题例:完整的汇编语言源程序实例例:将0500H开始的10个字节无符号数的和放至050AH、050BH单元中

mov cx,10 mov si,0500h;存放无符号数的存储单元首地址赋给si xor ax,ax ;ax及进位CY清零done: add al,[si] adc ah,0 inc si;指向下一个无符号数的存储单元地址loopdone;cx-1≠0转向done

mov bx,050ah;cx-1=0(10个无符号数已求完和),bx050ahmov[bx],ax;则将此和放至050AH、050BH存储单元完整的汇编语言源程序还需有以下处理:段定义过程汇编结束end

加过程处理

mov cx,10 mov si,0500h;存放无符号数的存储单元首地址赋给si xor ax,ax ;ax及进位CY清零done: add al,[si] adc ah,0 inc si;指向下一个无符号数的存储单元地址loopdone;cx-1≠0转向done

mov bx,050ahmov[050ah],ax;和放至050AH、050BH存储单元start proc farpush ds mov ax,0 push ax

retstartendp将0500H开始的10个无符号数的和放至050AH、050BH单元中过程定义伪指令程序设计中常将具有一定功能的程序设计成一个过程。过程语句格式过程名procnear或far(过程属性)…过程名endp为了使程序结束后能返回DOS系统,需:

过程名 proc far push ds mov ax,0 push ax … ret

过程名endp这样当该过程的程序运行完毕,便执行DS:0000H处的返回到DOS管理状态的指令push书51ret子程序返回指令RET(reture)RET ;无参数返回RETi16 ;有参数返回,除执行RET指令外还SP←SP+i16(16位立即数)RET指令放子程序末尾,执行时将堆栈中的返回地址出栈送IP(段内和段间调用)和CS(仅段间调用),使子程序执行完毕能返回主程序弹出CALL指令压入堆栈的返回地址段内返回——出栈偏移地址IPIP←SS:[SP],SP←SP+2段间返回——出栈偏移地址IP和段地址CSIP←SS:[SP],SP←SP+2CS←SS:[SP],SP←SP+2start proc far push ds mov ax,0

push ax

mov cx,10 mov si,0500h;存放无符号数的存储单元首地址赋给si xor ax,ax ;ax及进位CY清零done: add al,[si] adc ah,0 inc si;指向下一个无符号数的存储单元地址loopdone;cx-1≠0转向done mov bx,050ahmov[bx],ax;和放至050AH、050BH存储单元 retstartendp

sseg segment db 256dup(0)sseg ends

cseg segment assumecs:cseg,ds:dseg,ss:sseg加段定义代码段堆栈段cseg ends

end start ;汇编结束

段定义完整的汇编语言源程序分为代码段、数据段(可选)、堆栈段、附加段(可选),分别装入CS、DS、SS、ES段寄存器指定的物理段段定义语句格式

段名segment…段名ends伪指令ASSUME指明各段和段寄存器之间的关系例:dseg segment

sum db 0 dseg ends

sseg segmentparastack‘sseg’ db 256dup(0) sseg ends;堆栈段

cseg segment

assumecs:cseg,ds:dseg,ss:sseg…

cseg

ends代码段:硬指令、伪指令其它段:伪指令(存储单元的定义、分配等)代码段数据段堆栈段程序开始为了指明程序开始执行的位置,需要使用一个标号(例题中采用了start标识符)连接程序会根据程序起始点正确地设置CS和IP值,根据程序大小和堆栈段大小设置SS和SP值连接程序没有设置DS和ES值。程序如果使用数据段或附加段,必须明确给DS或ES赋值汇编结束汇编结束表示汇编程序到此结束将源程序翻译成目标模块代码的过程源程序的最后必须有一条END伪指令

END[标号]可选的“标号”参数指定程序开始执行点,连接程序据此设置CS和IP值(例题中采用了start标识符)

————不要糊涂————程序终止和汇编结束是两码事例题2.4汇编语言程序设计

一.汇编语言程序设计概述汇编语言程序设计步骤从实际问题抽象出数学模型,确定数学模型算法(如乘法用移位指令还是乘法指令)画出程序流程图编程思路,程序结构和相互之间关系方框:工作框例:菱形:判断框编程、调试形成文件判断程序质量程序执行时间程序所占内存字节数程序语句条数程序可读性

结束

初始化

循环体

控制条件YN二.汇编语言程序设计的基本方法DOS功能调用汇编语言程序结构顺序程序设计分支程序设计循环程序设计子程序设计1.DOS功能调用(书105页)DOS操作系统含很多I/O子程序,这些子程序已编号,可由汇编语言源程序调用。系统功能调用是程序设计的一个重要方面两种功能调用高级功能调用(DOS功能调用)低级功能调用对BIOS中的功能子程序的调用重点掌握DOS功能调用:显示一个字符,02H号功能调用显示一个字符串,09H号功能调用中断中断(Interrupt)是又一种改变程序执行顺序的方法,分为硬中断外部设备中断请求信号INTR、NMI软中断程序指令请求8088CPU支持256个软中断,每个中断用一个编号(中断向量号)区别INTn软中断调用指令,产生n号中断n为8位立即数,表示中断向量号掌握类似子程序调用指令CALL的中断调用指令INT,进而掌握系统功能调用

例:int21h ;产生21H号中断中断向量号0~255高级DOS功能调用高级DOS功能调用步骤

⑴AH系统功能调用号(子程序号)

⑵指定寄存器中设置入口参数

⑶用中断指令INT21h执行功能调用

⑷根据出口参数分析功能调用执行情况01H号DOS功能调用键盘输入接收从键盘输入的一个字符并在显示器上显示该字符。⑴功能调用号:AH=01H⑵入口参数:无⑶功能调用:INT21H⑷出口参数:AL=输入字符例:显示键盘输入的一个字符并送in-buff存储单元;在数据段定义要显示的字符in-buffdb ?

;

在代码段编写程序movah,01h ;设置功能调用号int21h ;功能调用movin-buff,al ;缓存键盘输入字符02H号DOS功能调用显示一个字符⑴功能调用号:AH=02H⑵入口参数:DL=欲显示字符的ASCII码⑶功能调用:INT21H⑷出口参数:无例:显示data中的一个字符;在数据段定义要显示的字符datadb ‘a’

;

在代码段编写程序movah,02h ;设置功能调用号movdl,’a’ ;设置入口参数int21h ;功能调用09H号DOS功能调用显示一个字符串⑴功能调用号:AH=09H⑵入口参数:DS:DX=欲显示字符串在内存中的首地址 (字符串以ASCII码形式保存,以“$”结尾,$并不显示)⑶功能调用:INT21H⑷出口参数:无例:显示字符串“Pressanykeytocontiune”;在数据段定义要显示的字符串msgkeydb ‘Pressanykeytocontiune’,’$’;

在代码段编写程序mov ah,9;设置功能调用号

;设置入口参数DX=字符串的偏移地址mov dx,offsetmsgkeyint21h;功能调用2.顺序程序设计没有分支、循环等转移指令的程序,会按指令书写的前后顺利依次执行,这就是顺序程序顺序结构是最基本的程序结构完全采用顺序结构编写的程序并不多见书100页例题2.1顺序程序设计实例3.分支程序设计分支程序根据条件是真或假决定执行与否判断的条件是各种指令如CMP、TEST等执行后形成的状态标志转移指令Jcc和JMP可以实现分支控制条件成立跳转,否则顺序执行分支语句体注意选择正确的条件转移指令和转移目标地址Jcc条件满足?分支语句体YN书100页例题2.2、例题2.3课后读此程序条件转移指令Jcc条件转移指令Jcc根据指定的条件确定程序是否发生转移。其通用格式为:

Jcc

label

;条件满足,发生转移 ;IP←IP+8位位移量; ;否则,顺序执行label是一个标号、一个8位位移量,表示Jcc指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移label只支持短转移的相对寻址方式例:计算AX中有符号数的绝对值

cmpax,0

jnlnonneg ;条件满足(AX≥0),转移

negax ;条件不满足,求补nonneg:

movresult,ax ;条件满足

;不恰当的分支

cmpax,0

jlyesneg ;条件满足(AX<0),转移 jmpnonnegyesneg:

negax ;条件不满足,求补nonneg:

movresult,ax ;条件满足有符号数AB转移有符号数AB转移例:显示BX的最高位方法一:分支程序设计

movdl,‘0’;DL←30H=‘0’

shlbx,1 ;BX最高位移入CF标志

jnctwo ;CF=0,即最高位为0,转移 movdl,‘1’;CF=1,即最高位为1:DL←31H=‘1’two: movah,2 int21h ;显示编写分支程序,需留心分支的开始和结束例:显示BX的最高位方法二:顺序程序设计(无分支) movdl,0 shlbx,1 ;BX最高位移入CF标志

adcdl,30h ;CF=0,DL←0+30h+0=30H=‘0’ ;CF=1,DL←0+30h+1=31H=‘1’two: movah,2 int21h ;显示逻辑左移指令SHL(shiftlogicalleft)

算术左移指令SAL(shiftalgebraicleft)SHL/SALreg/mem,1/CL ;reg/mem左移1或CL位 ;最低位补0,最高位进入CF演示4.循环程序设计循环程序结构是满足一定条件的情况下,重复执行某部分程序循环结构的程序通常有3个部分:关键

结束

初始化

循环体

修改部分控制条件YN

循环初始部分

为开始循环准备必要的条件,如循环次数、循环体需要的数值等

循环体部分

重复执行的程序部分,包括对循环条件等的修改程序段循环控制部分

判断循环条件是否成立,决定是否继续循环。循环条件为:(1)循环次数(计数控制循环)(2)特定条件(条件控制循环)循环程序设计例题例:将0500H开始的10个字节无符号数的和放至050AH、050BH单元中

mov cx,10 mov si,0500h;存放无符号数的存储单元首地址赋给si xor ax,ax ;ax及进位CY清零done: add al,[si] adc ah,0 inc si;指向下一个无符号数的存储单元地址loopdone;cx-1≠0转向done

mov bx,050ah;cx-1=0(10个无符号数已求完和),bx050ahmov[bx],ax;则将此和放至050AH、050BH存储单元初始化:循环次数=需累加的字节个数循环体:逐个累加循环控制:加完所有数据计数控制循环计数控制循环利用循环次数作为控制条件易于采用循环指令LOOP和JCXZ实现初始化:将循环次数或最大循环次数置入CX循环体循环控制:用LOOP指令对CX减1、并判断是否为0书102页例题2.4循环程序设计实例循环指令循环指令用于控制程序的重复执行,根据CX(存放循环次数)决定循环(转移至目标地址)还是顺序执行(下一条指令)循环指令

LOOPlabel;CX-1≠0,则转移(首先CX←CX-1;然后判断若CX≠0,转移)LOOPZ/LOOPElabel;CX-1≠0且ZF=1,则转移LOOPNZ/LOOPNElabel;CX-1≠0且ZF=0,则转移

JCXZlabel;CX=0,则转移labell只支持短转移(当前代码段内±127范围)deccxjnzlabel例:用二进制显示BX内容

movcx,16

;CX←8(循环次数)again: shlbx,1 ;左移进CF,从高位开始显示 movdl,0 ;MOV指令不改变CF adcdl,30h ;DL←0+30H+CF ;CF若是0,则DL←'0' ;CF若是1,则DL←'1' movah,2 int21h ;显示

loopagain ;CX减1,如果CX未减至0,则循环计数控制循环先循环后判断显示BX的最高位sum dw? xorax,ax ;被加数AX清0 movcx,100again: addax,cx ;从100,99,...,2,1倒序累加

loopagain movsum,ax ;将累加和送入指定单元例求和SUM=1+2+3+…+99+100

计数控制循环循环次数固定初始化:循环次数=需累加的字节个数循环体:逐个累加循环控制:加完所有数据?SUM=SUM-1-2-3?SUM=2+3+4计数控制循环例题:初始化返回第2章计数控制循环例题:求数组元素的最大值;数据段主体部分buffer db-1,0,2,3,8,9,10,88h,-3,45h;这是一个有符号字节元素组成的数组count equ$-buffer;符号“$”表示当前偏移地址值max db? ;存放最大值;代码段主体部分

初始化:循环次数=元素个数-1循环体:逐个比较求最大循环控制:比较完所有数据

mov cx,count

;取得元素个数

dec cx

;减1后是循环次数

lea bx,buffer

mov al,[bx]

;取出第一个元素给AL,AL用于暂存最大值

inc bxagain: cmp al,[bx] ;与下一个数据比较 jnl next ;≥转移 mov al,[bx] ;AL取得更大的数据next: inc bx

loop again

;计数循环 mov max,al ;保存最大值

初始化循环体例题改进:求数组元素的最大值和最小值,数组元素的第一个数据表示元素个数

;数据段主体部分array dw10;假设一个数组,其中第一个数据10表示元素个数 dw-3,0,20,900,587,-632,777,234,-34,-56;这是一个有符号字量元素组成的数组maxay dw? ;存放最大值minay dw? ;存放最小值初始化:循环次数=元素个数-1循环体:逐个比较求最大、小值循环控制:比较完所有数据例题改进代码段

;代码段主体部分 leasi,array movcx,[si] ;取得元素个数 deccx ;减1后是循环次数 addsi,2 movax,[si]

;取出第一个元素给AX,AX用于暂存最大值 movbx,ax ;取出第一个元素给BX,BX用于暂存最小值初始化例题改进代码段(续)maxck: addsi,2 cmp[si],ax ;与下一个数据比较 jleminck ;<= movax,[si] ;AX取得更大的数据 jmpnextminck: cmp[si],bx jgenext ;>= movbx,[si] ;BX取得更小的数据next: loopmaxck

;计数循环 movmaxay,ax ;保存最大值 movminay,bx ;保存最小值循环体条件控制循环条件控制循环需要利用特定条件(条件转移指令)判断循环是否结束转移指令可以指定目的标号来改变程序的运行顺序,如果目的标号指向一个重复执行的语句体的开始或结束,便构成了循环控制结构显示以0结尾的字符串--循环程序设计

;数据段主体部分string db'Letushaveatry!',0 ;代码段主体部分 movbx,offsetstringagain: movdl,[bx] cmpdl,0

jzdone

;为0结束 movah,2 ;不为0,显示 int21h incbx ;指向下一个字符

jmpagaindone: ……条件控制循环先判断后循环另解:用09号功能调用---顺序程序设计 ;数据段主体部分string db'Letushaveatry!',‘$’ ;代码段主体部分 movah,9;设置功能调用号 movds,seg string;入口参数DS=数据段地址

movdx,offsetstring;DX=字符串的偏移地址 int21h;功能调用

统计并显示某个字节存储单元中1的个数

;数据段主体部分number db11101111B

;代码段主体部分 movbl,number xordl,dl;循环初值:DL←0again: cmpbl,0 jzdone;全部是0就可以退出循环,减少循环次数 shlbl,1 ;用指令shrbl,1也可以 adcdl,0;利用ADC指令加CF的特点进行计数

jmpagaindone: adddl,‘0’ ;显示个数 movah,2 int21h条件控制循环先判断后循环5.子程序设计把功能相对独立的程序段单独编写,作为一个相对独立的模块供程序使用,就形成子程序子程序可以实现源程序的模块化,可简化源程序结构,可以提高编程效率主程序(调用程序)需要利用CALL指令调用子程序(被调用程序)子程序需要利用RET指令返回主程序例:显示data中的一个字符用子程序设计;在数据段定义要显示的字符datadb ‘a’

;

在代码段编写程序movdl,data ;设置入口参数movah,02h ;设置功能调用号int21h ;功能调用;主程序 movdl,data ;主程序提供显示字符

calldpchar

;调用子程序

;子程序:显示AL中的字符dpchar proc

;过程定义,过程名为dpchar

pushax

;保护寄存器 movah,02h ;02H号DOS功能调用显示一个字符功能 int21h

popax;恢复寄存器

ret ;子程序返回dpchar endp

;过程结束dseg segmentdata db ‘a’

dseg endssseg segment parastack‘stack’ db 256dup(0)sseg endscseg segment assume cs:cseg,ss:sseg,ds:dsegmain proc far push ds mov ax,0

push ax mov ax,dseg mov ds,ax

mov dl,data ;主程序提供显示字符

call dpchar

;调用子程序 retmain endpdpchar proc ;子程序:显示AL中的字符

push ax ;顺序入栈,保护寄存器

mov ah,02h ;设置功能调用号 int 21h

;功能调用 popax ;恢复寄存器 ret ;子程序返回dpchar endp

;过程结束cseg ends ;代码段结束 end main ;汇编结束

源程序主程序子程序子程序安排在主程序执行终止后的位置完整段定义格式子程序编写注意事项子程序要利用过程定义伪指令声明子程序最后利用RET指令返回主程序,主程序执行CALL指令调用子程序子程序中对堆栈的压入和弹出操作要成对使用,保持堆栈的平衡子程序开始应该保护使用到的寄存器内容,子程序返回前相应进行恢复例 ;主程序 movdl,data

calldpchar

;子程序dpchar proc

pushax

movah,02h int21h

popax

ret

dpchar endp

子程序应安排在代码段的主程序之外,最好放在主程序执行终止后的位置(返回DOS后、汇编结束END伪指令前),也可以放在主程序开始执行之前的位置处理好子程序与主程序间的参数传递问题多出口子程序;子程序HTOASC:十六进制数转换为ASCII码16进制数:0~9的ASCII码30H~39H

A~F的ASCII码41H~46HHTOASC proc andal,0fh cmpal,10 jchtoasc1 ;<10,转htoasc1 addal,37h ;是A~F,加37H ret ;子程序返回htoasc1: add,30h ;是0~9,加30H

ret ;子程序返回HTOASC endp含数据区的子程序;子程序HTOASC:十六进制数转换为ASCII码16进制数:0~9的ASCII码30H~39H

A~F的ASCII码41H~46H;数据区ASCII db30h,31h,32h,33h,34h,35h,36h,37h,38h,39h db41h,42h,43h,44h,45h,46hHTOASC proc movbx,offsetASCII andal,0fh

xlat

;换码:AL←[BX+AL]

retHTOASC endpXLAT指令的功能参数传递主程序与子程序间一个主要问题是参数传递入口参数(输入参数):主程序调用子程序时,提供给子程序的参数出口参数(输出参数):子程序执行结束返回给主程序的参数参数的具体内容传数值:传送数据本身传地址:传送数据的主存地址dpcharHTOASCdpchar子程序的参数传递(例:显示data中的一个字符)

;主程序 movdl,data ;主程序提供显示字符

calldpchar

;调用子程序

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论