第五章 程序设计程序是计算机命令(语句)的有序集合。
汇编语言与高级语言区别汇编语言是面对机器的,要求程序员对机器指令系统、内存空间分配了如指掌,地址是汇编语言关键所在,执行速度快,但可移植性差。
高级语言是面向过程的,程序员没必要了解内存分配,更符合人的思维方式,执行速度相对慢一些,可移植性好。
计算机执行程序“从头到尾”,逐条顺序执行,
直到程序结束。
1.简单程序(顺序程序)
【 例 1】 用数据运算指令,对两个 16位数做加法运算。这两个数从地址 10050H开始连续存放,低位在小地址一端,结果存放在这两个数之后。
MOVAX,1000H
MOV DS,AX ; DS= 1000H
MOVSI,50H ; 被加数指针 SI= 50H
MOVDI,52H ; 加数指针 DI= 52H
MOVBX,54H ; 和的指针 BX= 54H
CLC ; 清 CF
XOR AX,AX ; 清 AX
MOVAX,[SI] ; 取一个字到 AX
ADC AX,[DI] ; AX←AX + [DI]+CF
MOV[BX],AX ; 存一个字到 [BX]
HLT ; 暂停
【 例 2】 将内存 10050H单元的内容拆成两段,每段 4位,并将它们分别存入内存 10051H和 10052H单元。即 10050H单元中的低 4位放入 10051H的低 4位,
10050H单元中的高 4位放入 10052H的低 4位,而
10051H和 10052H的高 4位均为零。
MOV AX,1000H
MOV DS,AX ; DS= 1000H
MOV SI,50H ; 需拆字节的指针 SI=50H
MOV AL,[SI] ; 取一个字节到 AL中
AND AL,0FH ; 把 AL的前 4位清 0
MOV [SI+1],AL ;把得到的后 4位放到 10051H单元
MOV AL,[SI] ; 再取出需拆字节放到 AL中
MOV CL,4
SHR AL,CL ; 逻辑右移四次,前 4位补 0
MOV [SI+2],AL ; 放入 10052H单元
HLT
分支程序是利用条件转移指令,使程序执行到某一指令后,根据条件是否满足,来改变程序的执行次序。
程序使计算机有了判断的功能。经常先用比较指令或数据操作及位检测指令改变标志寄存器各个标志位。
然后用条件转移指令进行分支。
【 例 1】 求 AX累加器和 BX寄存器中两个无符号数之差的绝对值,结果放在内存 2800H单元中。
2.分支程序
CLC ;清除 CF
MOV CX,AX
SUB AX,BX ;AX←AX - BX,影响 CF
JC AA ; CF= 1转 AA去执行(即 AX<BX时转移)
MOV DI,2800H ;结果指针 DI= 2800H
MOV [DI],AX ;结果送到 2800H和 2801H单元
JMP LP ;暂停
AA,SUB BX,CX ;BX←BX - CX
MOV DI,2800H
MOV [DI],BX
LP,HLT
【 例 2】 编制程序,从外设 71号端口中取一个数 M,
判断其值是否在 10和 20之间,即 10≤M<20。如果
M≥20H,则送 0FFH给外设 73H端口;如果 M<10,
则送 00H给外设 73H;如果 10≤M<20,则送 88H给外设 73H。
START,IN AL,71H ;将 71H端口的字节读入 AL
CLC ;清除 CF
CMP AL,10 ; AL←AL - 10
JC LP1 ; 小于 10转 LP1
CMP AL,20 ; AL←AL - 20
JC LP2 ; 10≤AL<20转 LP2
MOV BL,0FFH ;将 0FFH送入 BL寄存器
LP3,MOV AL,BL
OUT 73H,AL ;将结果的标志数据输出到 73H端口
HLT ; 暂停
LP1,MOV BL,00H
JMP LP3
LP2,MOV BL,88H
JMP LP3
3 循环程序
【 例 1】 求两个多字节数之和。这两个数在 10050H
地址开始的内存单元中,连续存放,低位在小地址一端,结果放在这两个数之后。设这两个多字节数均为八个字节长。
START:MOV AX,1000H
MOV DS,AX ; DS= 1000H
MOV SI,50H ;第一个数指针 SI=50H
MOV DI,58H ;第二个数指针 DI= 58H
MOV BX,60H ;结果指针 BX= 60H
MOV CX,4 ;循环次数 CX= 4
CLC ;清进位 CF= 0
AA,MOV AX,[SI] ;取一个字到 AX
ADC AX,[DI] ; AX←AX+[DI]+CF
MOV [BX],AX ;存一个字到 [BX]
PUSHF ;保护进位 CF,因为下面的; ADD指令可能破坏 CF状态
ADD SI,2 ;修改第一个数的地址指针 SI←SI+2
ADD DI,2 ;修改第二个数的地址指针 DI←DI+2
ADD BX,2 ;修改结果指针 BX←BX + 2
POPF ;恢复标志寄存器
LOOP AA ; CX←CX - 1
HLT ; CX= 0,暂停
4 子程序设计
【 例 1】 找出一个数据块中的最大数。其中,数据块的长度 >1,并且放在内存 2001H单元中,而数据块本身是从 2002H单元开始存放的,最后,把找出的最大值放到 2000H单元中,假设这段数据块中的数都是无符号的 8位数,请设计成一段可调用的子程序。
MAX,PUSHF
PUSH AX
PUSH CX
PUSH SI
MOV SI,2001H ;指针指向放数据块长度的单元
MOV CL,[SI] ;取出来作为循环次数
INC SI ;指针指向第一个数
MOV AL,00H ;设置最大值 00
MOV CH,00H ;初始化
LP,CLC ;清除进位位
CMP AL,[SI] ;取出数与最大值比较
JNC AA ; AL中数大,跳过去
MOV AL,[SI] ;把大数放到 AL中保存
AA,INC SI ;指针下移
LOOP LP ;次数减 1,判循环结束否
MOV [2000H],AL ;把最大值放到指定单元保存
POP SI
POP CX
POP AX
POPF
RET
5.上机操作
DATA SEGMENT
┇ } 存放数据项的数据段
DATA ENDS
EXTRA SEGMENT
┇ } 存放数据项的附加段
EXTRA ENDS
STACK1 SEGMENT PARA STACK
┇ } 作堆栈用的堆栈段
STACK1 ENDS
COSEG SEGMENT
ASSUME CS,COSEG,DS,DATA
ASSUME SS,STACK1,ES,EXTRA
BEING,MOV AX,DATA
MOV DS,AX
┇ } 存放指令序列
COSEG ENDS
END BEING
例 从键盘上输入任意一个 1位十进制数( 0~
9),用移位指令乘 10,并将结果显示出来。
NAME EX1
PAGE 50,70
DAT SEGMENT PARA 'DAT'
BUFF DB 4 DUP(?)
DAT ENDS
STAC SEGMENT PARA STACK'STA'
STA1 DB 100 DUP(?)
STAC ENDS
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE,DS:DAT
ASSUME SS:STAC,ES:DAT
START PROC FAR
PUSH DS
XOR AX,AX
PUSH AX;返回 DOS操作系统
MOV AX,DAT
MOV DS,AX ;设置 DS值
CALL P1 ;调键盘输入子程序
CALL P2 ;调乘 10子程序
CALL P3 ;调显示子程序
RET
LEA SI,BUFF ;建立缓冲区首址指针
-----------------------------------------------------
P1 PROC ;键盘输入子程序
RE,MOV AH,1
INT 21H
CMP AL,'0'
JC RE
CMP AL,'A'
JNC RE
AND AL,0FH
MOV [SI],AL;从键盘输入一个数并显示;数据输入合法否?若不合法,
重新输入?;将输入数据转换为 BCD码存缓冲区
MOV DL,0DH
MOV AH,2
INT 21H
MOV DL,0AH
MOV AH,02H
INT 21H
RET
P1 ENDP
-----------------------------------------------------------;回车换行符送显示
-----------------------------------------------------------
P2 PROC ;乘 10子程序
MOV AL,[SI] ;从缓冲区取数
SHL AL,1
MOV BL,AL
MOV CL,2
SHL AL,CL
ADD AL,BL;乘 10
MOV AH,0
MOV BL,10
DIV BL
ADD AH,30H
ADD AL,30H
MOV [SI],AL
MOV [SI+1],AH
RET
P2 ENDP
----------------------------------------------------------;将积转换成 ASCII码存缓冲区
------------------------------------------------------
P3 PROC ;显示子程序
MOV DL,[SI]
MOV AH,2
INT 21H
MOV DL,[SI+1]
MOV AH,2
INT 21H
RET
P3 ENDP
CODE ENDS
END START
编辑程序,ASM MASM,OBJ
LINK
.EXE
汇编语言上机过程开机进行系统选择 →DOS
进入 DOS环境 C:\>
C:\> CD MASM ↙
C:\MASM> EDIT ↙
进入编辑环境,输入程序,输入完毕存盘。
ALT-F →NEW 建立新文件
OPEN 打开已有文件
SAVE 保存
SAVE AS 另存为
↓
EXIT 退出选择 SAVE ↙,命名 EX1.ASM ↙
ALT- F → EXIT
回到 DOS环境
C:\MASM> MASM EX1.ASM ↙
3次回车,无错,0 warnings
0 errors.
C:\MASM> LINK EX1.ASM ↙
3次回车
Running,EX1.EXE,EX1↙ 看结果 !
汇编语言与高级语言区别汇编语言是面对机器的,要求程序员对机器指令系统、内存空间分配了如指掌,地址是汇编语言关键所在,执行速度快,但可移植性差。
高级语言是面向过程的,程序员没必要了解内存分配,更符合人的思维方式,执行速度相对慢一些,可移植性好。
计算机执行程序“从头到尾”,逐条顺序执行,
直到程序结束。
1.简单程序(顺序程序)
【 例 1】 用数据运算指令,对两个 16位数做加法运算。这两个数从地址 10050H开始连续存放,低位在小地址一端,结果存放在这两个数之后。
MOVAX,1000H
MOV DS,AX ; DS= 1000H
MOVSI,50H ; 被加数指针 SI= 50H
MOVDI,52H ; 加数指针 DI= 52H
MOVBX,54H ; 和的指针 BX= 54H
CLC ; 清 CF
XOR AX,AX ; 清 AX
MOVAX,[SI] ; 取一个字到 AX
ADC AX,[DI] ; AX←AX + [DI]+CF
MOV[BX],AX ; 存一个字到 [BX]
HLT ; 暂停
【 例 2】 将内存 10050H单元的内容拆成两段,每段 4位,并将它们分别存入内存 10051H和 10052H单元。即 10050H单元中的低 4位放入 10051H的低 4位,
10050H单元中的高 4位放入 10052H的低 4位,而
10051H和 10052H的高 4位均为零。
MOV AX,1000H
MOV DS,AX ; DS= 1000H
MOV SI,50H ; 需拆字节的指针 SI=50H
MOV AL,[SI] ; 取一个字节到 AL中
AND AL,0FH ; 把 AL的前 4位清 0
MOV [SI+1],AL ;把得到的后 4位放到 10051H单元
MOV AL,[SI] ; 再取出需拆字节放到 AL中
MOV CL,4
SHR AL,CL ; 逻辑右移四次,前 4位补 0
MOV [SI+2],AL ; 放入 10052H单元
HLT
分支程序是利用条件转移指令,使程序执行到某一指令后,根据条件是否满足,来改变程序的执行次序。
程序使计算机有了判断的功能。经常先用比较指令或数据操作及位检测指令改变标志寄存器各个标志位。
然后用条件转移指令进行分支。
【 例 1】 求 AX累加器和 BX寄存器中两个无符号数之差的绝对值,结果放在内存 2800H单元中。
2.分支程序
CLC ;清除 CF
MOV CX,AX
SUB AX,BX ;AX←AX - BX,影响 CF
JC AA ; CF= 1转 AA去执行(即 AX<BX时转移)
MOV DI,2800H ;结果指针 DI= 2800H
MOV [DI],AX ;结果送到 2800H和 2801H单元
JMP LP ;暂停
AA,SUB BX,CX ;BX←BX - CX
MOV DI,2800H
MOV [DI],BX
LP,HLT
【 例 2】 编制程序,从外设 71号端口中取一个数 M,
判断其值是否在 10和 20之间,即 10≤M<20。如果
M≥20H,则送 0FFH给外设 73H端口;如果 M<10,
则送 00H给外设 73H;如果 10≤M<20,则送 88H给外设 73H。
START,IN AL,71H ;将 71H端口的字节读入 AL
CLC ;清除 CF
CMP AL,10 ; AL←AL - 10
JC LP1 ; 小于 10转 LP1
CMP AL,20 ; AL←AL - 20
JC LP2 ; 10≤AL<20转 LP2
MOV BL,0FFH ;将 0FFH送入 BL寄存器
LP3,MOV AL,BL
OUT 73H,AL ;将结果的标志数据输出到 73H端口
HLT ; 暂停
LP1,MOV BL,00H
JMP LP3
LP2,MOV BL,88H
JMP LP3
3 循环程序
【 例 1】 求两个多字节数之和。这两个数在 10050H
地址开始的内存单元中,连续存放,低位在小地址一端,结果放在这两个数之后。设这两个多字节数均为八个字节长。
START:MOV AX,1000H
MOV DS,AX ; DS= 1000H
MOV SI,50H ;第一个数指针 SI=50H
MOV DI,58H ;第二个数指针 DI= 58H
MOV BX,60H ;结果指针 BX= 60H
MOV CX,4 ;循环次数 CX= 4
CLC ;清进位 CF= 0
AA,MOV AX,[SI] ;取一个字到 AX
ADC AX,[DI] ; AX←AX+[DI]+CF
MOV [BX],AX ;存一个字到 [BX]
PUSHF ;保护进位 CF,因为下面的; ADD指令可能破坏 CF状态
ADD SI,2 ;修改第一个数的地址指针 SI←SI+2
ADD DI,2 ;修改第二个数的地址指针 DI←DI+2
ADD BX,2 ;修改结果指针 BX←BX + 2
POPF ;恢复标志寄存器
LOOP AA ; CX←CX - 1
HLT ; CX= 0,暂停
4 子程序设计
【 例 1】 找出一个数据块中的最大数。其中,数据块的长度 >1,并且放在内存 2001H单元中,而数据块本身是从 2002H单元开始存放的,最后,把找出的最大值放到 2000H单元中,假设这段数据块中的数都是无符号的 8位数,请设计成一段可调用的子程序。
MAX,PUSHF
PUSH AX
PUSH CX
PUSH SI
MOV SI,2001H ;指针指向放数据块长度的单元
MOV CL,[SI] ;取出来作为循环次数
INC SI ;指针指向第一个数
MOV AL,00H ;设置最大值 00
MOV CH,00H ;初始化
LP,CLC ;清除进位位
CMP AL,[SI] ;取出数与最大值比较
JNC AA ; AL中数大,跳过去
MOV AL,[SI] ;把大数放到 AL中保存
AA,INC SI ;指针下移
LOOP LP ;次数减 1,判循环结束否
MOV [2000H],AL ;把最大值放到指定单元保存
POP SI
POP CX
POP AX
POPF
RET
5.上机操作
DATA SEGMENT
┇ } 存放数据项的数据段
DATA ENDS
EXTRA SEGMENT
┇ } 存放数据项的附加段
EXTRA ENDS
STACK1 SEGMENT PARA STACK
┇ } 作堆栈用的堆栈段
STACK1 ENDS
COSEG SEGMENT
ASSUME CS,COSEG,DS,DATA
ASSUME SS,STACK1,ES,EXTRA
BEING,MOV AX,DATA
MOV DS,AX
┇ } 存放指令序列
COSEG ENDS
END BEING
例 从键盘上输入任意一个 1位十进制数( 0~
9),用移位指令乘 10,并将结果显示出来。
NAME EX1
PAGE 50,70
DAT SEGMENT PARA 'DAT'
BUFF DB 4 DUP(?)
DAT ENDS
STAC SEGMENT PARA STACK'STA'
STA1 DB 100 DUP(?)
STAC ENDS
CODE SEGMENT PARA 'CODE'
ASSUME CS:CODE,DS:DAT
ASSUME SS:STAC,ES:DAT
START PROC FAR
PUSH DS
XOR AX,AX
PUSH AX;返回 DOS操作系统
MOV AX,DAT
MOV DS,AX ;设置 DS值
CALL P1 ;调键盘输入子程序
CALL P2 ;调乘 10子程序
CALL P3 ;调显示子程序
RET
LEA SI,BUFF ;建立缓冲区首址指针
-----------------------------------------------------
P1 PROC ;键盘输入子程序
RE,MOV AH,1
INT 21H
CMP AL,'0'
JC RE
CMP AL,'A'
JNC RE
AND AL,0FH
MOV [SI],AL;从键盘输入一个数并显示;数据输入合法否?若不合法,
重新输入?;将输入数据转换为 BCD码存缓冲区
MOV DL,0DH
MOV AH,2
INT 21H
MOV DL,0AH
MOV AH,02H
INT 21H
RET
P1 ENDP
-----------------------------------------------------------;回车换行符送显示
-----------------------------------------------------------
P2 PROC ;乘 10子程序
MOV AL,[SI] ;从缓冲区取数
SHL AL,1
MOV BL,AL
MOV CL,2
SHL AL,CL
ADD AL,BL;乘 10
MOV AH,0
MOV BL,10
DIV BL
ADD AH,30H
ADD AL,30H
MOV [SI],AL
MOV [SI+1],AH
RET
P2 ENDP
----------------------------------------------------------;将积转换成 ASCII码存缓冲区
------------------------------------------------------
P3 PROC ;显示子程序
MOV DL,[SI]
MOV AH,2
INT 21H
MOV DL,[SI+1]
MOV AH,2
INT 21H
RET
P3 ENDP
CODE ENDS
END START
编辑程序,ASM MASM,OBJ
LINK
.EXE
汇编语言上机过程开机进行系统选择 →DOS
进入 DOS环境 C:\>
C:\> CD MASM ↙
C:\MASM> EDIT ↙
进入编辑环境,输入程序,输入完毕存盘。
ALT-F →NEW 建立新文件
OPEN 打开已有文件
SAVE 保存
SAVE AS 另存为
↓
EXIT 退出选择 SAVE ↙,命名 EX1.ASM ↙
ALT- F → EXIT
回到 DOS环境
C:\MASM> MASM EX1.ASM ↙
3次回车,无错,0 warnings
0 errors.
C:\MASM> LINK EX1.ASM ↙
3次回车
Running,EX1.EXE,EX1↙ 看结果 !