8086汇编经典例程下
- 格式:doc
- 大小:47.00 KB
- 文档页数:2
简单的8086汇编程序(已加入详细注释)一位数加减乘除运算;波波安注释;注意分支结构,理清程序思路,一般出现CMP、JE等的地方都是分支。
;字体设置不同可能会出现编排结构混乱,我使用的字体是Times New Roman,常规,小二,大写DISPC MACRO CHAR;宏定义MOV DL,CHARMOV AH,2INT 21HENDMDATA SEGMENT;数据段S DB 'Please input data:$'X DB 0Y DB 0C DB 0Z DB 0,0DATA ENDSCODE SEGMENT;代码段ASSUME CS:CODE,DS:DATA,SS:DATA;说明;代码段开始START: MOV AX,DATAMOV DS,AX;输入第一个数L1: LEA DX,S;传送字符串的偏移地址MOV AH,9;显示字符串INT 21HCALL INPUT;调用子函数MOV X,AL;第一个数据输入成功,存入X;输入运算符L2: MOV AH,1INT 21H ;键盘输入并回显;分支CMP AL,'+'JE L3;相等,则跳转。
即若输入为“+”则跳转CMP AL,'-'JE L3CMP AL,'*'JE L3CMP AL,'/'JE L3DISPC 8;输入错误,执行错误处理DISPC 20HDISPC 8JMP L2;跳转回L2继续输入L3: MOV C,AL;运算符存入CCALL INPUT;接着输入第二个数MOV Y,AL;第二个数存入YDISPC '=';显示“=”;运算符判断;分支CMP C,'+';判断是否为“+”JNE L4;不等,则跳转。
即不为“+”则跳转L4MOV AL,X;为“+”,则执行加法操作。
算术运算中目的操作数一般为寄存器(AX)。
ADD AL,YMOV Z,AL;结果存入ZJMP L9;转到L9,显示结果L4: CMP C,'-';判断是否为“-”JNE L6;不等,则跳转,继续判断MOV AL,X;为“-”,则执行减法操作SUB AL,YMOV Z,AL;结果存入ZCMP Z,0;比较结果是否小于0JGE L5;不小于0,转到L9,直接显示。
一、计算X+Y=Z,将结果Z存入某存储单元。
(1). 实验程序如下:STACK SEGMENT STACKDW 64 DUP(?)STACK ENDSDATA SEGMENTXL DW ? ;请在此处给X低位赋值XH DW ? ;请在此处给X高位赋值YL DW ? ;请在此处给Y低位赋值YH DW ? ;请在此处给Y高位赋值ZL DW ?ZH DW ?DATA E NDSCODE S EGMENTASSUME CS:CODE,DS:DATASTART: MOV AX,DATAMOV DS,AXMOV AX,XL ;X低位送AXADD AX,YL ;X低位加Y低位MOV ZL,AX ;存低位和MOV AX,XH ;X高位送AXADC AX,YH ;X高位加Y高位MOV ZH,AXA1: JMP A1CODE E NDSEND START二、计算X-Y=Z,其中X、Y、Z为BCD码。
实验程序及流程如下:STACK SEGMENT STACKDW 64 DUP(?)STACK ENDSDATA SEGMENTX DW ? ;请在此处给X赋值Y DW ? ;请在此处给Y赋值Z DW ?DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART: MOV AX,DATAMOV DS,AXMOV AH,00HSAHFMOV CX,0002HLEA SI, XLEA DI, ZA1: MOV AL,[SI]SBB AL,[SI+02H]DASPUSHFAND AL,0FHPOPFMOV [DI],ALINC DIINC SILOOP A1A2: JMP A2CODE ENDSEND START三、乘法运算本实验实现十进制数的乘法,被乘数、乘数和乘积均以BCD码形式存放在内存中,实验程序及流程如下:STACK SEGMENT STACKDW 64 DUP(?)STACK ENDSDATA SEGMENTDATA1 DB 5 DUP(?)DATA2 DB ?RESULT DB 6 DUP(?)DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART: MOV AX,DATAMOV D S,AXCALL INITMOV S I,OFFSET DATA2MOV B L,[SI]AND B L,0FHCMP B L,09HJNC E RRORMOV S I,OFFSET DATA1MOV D I,OFFSET RESULTMOV C X,0005HA1: MOV A L,[SI+04H]AND A L,0FHCMP A L,09HJNC E RRORDEC S IMUL B LAAMADD A L,[DI+05H]AAAMOV [DI+05H],ALDEC D IMOV [DI+05H],AHLOOP A1MOV C X,06HMOV S I,OFFSET RESULTDISPLAY:MOV AH,01HMOV A L,[SI]ADD A L,30HMOV [SI],ALINC SILOOP DISPLAYA2: JMP A2INIT: MOV SI,OFFSET RESULTMOV C X,0003HMOV A X,0000HA3: MOV [SI],AXINC SIINC SILOOP A3RETERROR: MOV A X,0145HJMP A2CODE ENDSEND START。
8086指令系统实训实例一、80x86微处理器中的寄存器图1-1 80x86微处理器的基本结构寄存器标志寄存器对照表序号类别123456789EFLAG OF DF IF TF SF ZF AF PF CF DEBUG=1 OV DN EI NG ZR AC PE CY DEBUG=0NVUPDIPLNZNAPONC标志名称 设置 未设置标志名称 设置 未设置溢出 OV(溢出) NV(未溢出) 零位 ZR (为0) NZ(不等于零)方向 UP(增加) DN (减少) 辅助进位 AC (有进位)NA(无进位)中断 EI(许可) DI(禁止) 奇偶标志 PE(偶) PO(奇)符号 NG(负) PL(正) 进位 CY (有进位) NC(清除进位)累加器AH AL BH BL CL DHDLCH SP SI DI IP FLAGS CS DS SS ESBP 基址寄存器 计数寄存器 数据寄存器 堆栈指针寄存器 基址指针寄存器 源变址寄存器 目的变址寄存器 指令指针寄存器 标志寄存器 代码段寄存器 段寄存器 附加段寄存器堆栈段寄存器 数据寄存器地址指针和 变址寄存器 控制寄存器 通用寄存器数据段寄存器二、用DEBUG软件学习汇编语言DEBUG的几点规则说明:1.所有数据默认为16进制数,后缀“H”不用加;2.DEBUG命令都是一个字母,字母大小写不分,后面的参数可以用空格分开,也可以不用;命令与数字之间可以不分开,但是两个十六进制数字之间必须分开,如:L100 = L 100;100 110 ≠100110 ;3.DEBUG中的地址表示格式有如下几种:1)段寄存器:偏移量,如:cs:1002)段地址:偏移量,如:04ba:100 或4ba:1003)默认段寄存器不写,只写偏移量,如:100;4)确定地址范围可以有两种表示方式:a)段地址:起始地址的偏移量结束地址的偏移量,如:cs:100 110;b)段地址:起始地址的偏移量L(长度),如:cs:100 L10;DEBUG软件基本指令用法一览表实例:查看主板BIOS信息:①输入“D FE00:0”,回车后看到的结果就是主板BIOS的厂商信息。
8086汇编实现的五⼦棋⼩游戏⼀、五⼦程序设计要求汇编实现五⼦棋游戏。
⾸先显⽰空⽩棋盘,让玩家选择旗⾊,⽩⼦先⾏。
进⼊游戏对弈循环只要有⼀⽅连成同⾊五⼦,即获胜。
事先写了⼀个普通的c++五⼦棋,然后将这个思路⽤汇编实现出来,代码逾500⾏,五⼦棋功能⽐较完善了,获胜逻辑什么的判断部分基本没有问题,花费了我很⼤的精⼒。
选择旗⾊,先⼿玩家即为⽩⾊,后⼿玩家为⿊⾊,分别以W,B代表⿊⽩棋⼦。
⼆、设计思路五⼦棋,⾸先需要显⽰棋盘,然后玩家输⼊落⼦坐标,⽩⽅落⼦,⿊⽅落⼦,落⼦循环,其中每次落⼦都要判断⼀次落⼦点是否已经有棋⼦了,那就需要提醒玩家重新输⼊落⼦坐标,同理玩家输⼊的坐标超出棋盘边界的时候也要提醒玩家。
落⼦的部分解决了,就得考虑获胜的判定逻辑了,每次成功的落⼦,就要对该坐标进⾏判定,我的判定获胜的⽅法是这样的,对于落⼦坐标进⾏四类判定,⼀种是横向的,⼀种是纵向的,另外两类是左上到右下,与左下到右上的,这样就涵盖了所有的获胜的情况,并且具体怎么实现?设定⼀个变量COUNT计算同⼀线上的同⾊棋⼦数⽬,COUNT初始为1。
从落⼦坐标出发,对于横向的,分两种搜索,⼀类向左搜索,遇到同类的棋⼦COUNT+1,⼀旦不是同⾊棋⼦或者是搜索到棋盘外便转到向右搜索的循环中去,每次COUNT+1后判断是否达到5,达到5了则当前落⼦⽅获胜,遇到⾮同⾊棋⼦或搜索到棋盘外跳出循环,重置COUNT为1后进⼊其它三类判定,其它三类的获胜判定与该法原理⼀致。
原理简单易懂,但是在汇编上实现起来还是遇到了不少问题的。
同时,每次有效落⼦的时候有个变量OVERFLOW需要+1,这个是计算和棋的变量,五⼦棋的棋盘是15*15⼤⼩的,当OVERFLOW达到225时还没有决出胜负,这时候便可以宣布和棋了。
⼀些实现上的问题,由于8086汇编的输⼊中断⼀次仅识别⼀个ASII字符,导致两位数的输⼊还得⼿撸,便设置了两个暂存量TI,TJ⽤于暂存输⼊,事后再赋值给真正的落⼦坐标I,J。
[汇编]8086指令系统---算术指令(二)4 除法指令DIV src无符号数除法(unsigned divide)IDIV src带符号数除法(signed divide)字节操作: (AL) ← (AX) / src 的商(AH) ← (AX) / src 的余数字操作: (AX) ← (DX, AX) / src 的商(DX) ← (DX, AX) / src 的余数参加运算的除数和被除数是无符号数时,使用DIV指令,其商和余数也均为无符号数。
IDIV指令执行的操作与DIV相同,但操作数必须是带符号数,商和余数也均为带符号数,而且余数的符号与被除数的符号相同。
这两条除法指令的被除数必须存放在AX或DX,AX中,源操作数src作为除数,可用除立即数以外的任一种寻址方式来取得。
除法指令对所有条件码均无定义,因此对除法指令产生的错误,如除数为0或商溢出等错误,程序员都不能用条件码进行判断,而是由系统直接转入0型中断来处理。
所谓商溢出,是指被除数高一半的绝对值大于除数的绝对值时,商超出了16位的表示范围(字操作)或8位的表示范围(字节操作)。
由于使用除法指令的需要,经常要将字节数据扩展为字数据,或者将字数据扩展为双字数据,所以我们先介绍下面的符号扩展指令,然后再对除法指令举例。
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寄存器中。
这两条符号扩展指令都不影响条件码。
注意:除法指令要求字操作时,被除数必须为32位,除数是16位,商和余数是16位的;字节操作时,被除数必须为16位,除数是8位,得到的商和余数是8位的。
汇编语言程序设计实验报告学院:计算机科学与技术学院专业:计算机科学与技术班级:计科131MOV AX,WORD PTR N1MOV DX,WORD PTR N1+2MOV CX,WORD PTR N2MOV BX,WORD PTR N2+2ADD AX,CXADC DX,BXMOV WORD PTR N3,AXMOV WORD PTR N3+2,DXMOV AH,4CHINT 21HCODE ENDSEND START使用相应的文本编辑器建立文件two.asm,内容如上所示。
二. 生成可执行文件:1.汇编:C:\masm> masm two;2.连接:C:\masm> link two;三.运行及调试:1. 运行:C:\masm>debug two.exe-U0 ;通过反汇编查找程序的断点-T=0 2 ;加载数据段-D0 ;查看原始数据是否正确-G=0 1F ;运行程序至断点1F 处-D0 ;查看程序运行结果2.调试:若要判断此程序对于其它32 位数相加是否正确,则需要使用DEBUG 进行程序调试。
实验二:编程实现:将从2000H 单元开始的连续128 个单元的内容进行清零一. 编程CODE SEGMENTASSUME CS:CODE,DS:CODESTART:MOV BX,2000HMOV CX,128MOV AL,00HL1:MOV [BX],ALINC BXLOOP L1MOV AH,4CHINT 21HCODE ENDSEND START二.使用编辑器建立源程序文件four.asm。
三.生成可执行文件:1.汇编:C:\masm> masm four;2.连接:C:\masm> link four;四.运行及调试:1. 运行:C:\masm>debug four.exe-D2000;-R;-D CS:2000;-G;-D2000;实验三:编程实现:将3000H 单元的一个字节的内容进行拆分,高半字节放进3001H 单元的低半部分,其低半字节放进3002H 单元的低半部分一、编程源程序:DATA SEGMENTN0 DW 3000HN1 DW 3001HN2 DW 3002HDATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART:MOV AX,DATAMOV DS,AXMOV BX,N0AND BX,0FHMOV AX,N2MOV AX,[BX]MOV BX,N0MOV CL,4SHR AX,CLMOV AX,N1MOV AX,[BX]MOV AH,4CHINT 21HCODE ENDSEND START二.使用编辑器建立源程序文件five.asm。
1.编写一个程序,从键盘输入任意十进制正数,然后将这个数按16进制形式显示在屏幕上。
DECIHEX SEGMENT ; 定义代码段ASSUME CS:DECIHEXMAIN PROC FAR ; 主程序REPEAT: CALL DECIBIN ; 调用子程序输入十进制数CALL CRLF ; 显示回车、换行CALL BINIHEX ; 以十六进制数输出CALL CRLF ; 显示回车、换行JMP REPEAT ; 转REPEA T,继续MAIN ENDPDECIBIN PROC NEAR ; 十进制数输入子程序MOV BX, 0 ; BX保存输入数NEWCHAR: MOV AH, 1INT 21H ; 调用DOS功能输入字符SUB AL, 30H ; 转为数0-9JB EXIT ; 小于0,不是数字CMP AL, 9D ; 与9比较JA EXIT ; 大于,不是数字CBW ; AL=>AXXCHG AX, BX ; AX、BX互换MOV CX, 10D ; CX=10MUL CX ; AX=AX*CXADD BX, AX ; BX为前面输入的结果JMP NEWCHAREXIT: RETDECIBIN ENDPBINIHEX PROC NEARMOV CH, 4 ; CH循环次数ROTA TE: MOV CL, 4 ;每次循环输出一位十六进制数ROL BX, CL ; 即移位4个二进制位MOV AL, BL ; AL=BLAND AL, 0FH ; 取低4位ADD AL, 30H ; 转变为ASCII码CMP AL, 3AH ; 是否为’0’-‘9’ JL PRINTIT ; 是转PRINTITADD AL, 7H ; 否转为’A’-‘F’ PRINTIT: MOV DL, AL ; DL=输出字符MOV AH, 2INT 21H ;调用DOS中断,显示字符DEC CHJNZ ROTA TE ; 没循环结束,继续RET ; 返回BINIHEX ENDPCRLF PROC NEAR ; 输出回车、换行MOV DL, 0DHMOV AH, 2INT 21H ; 输出回车MOV DL, 0AHMOV AH, 2INT 21H ; 输出换行RETCRLF ENDPDECIHEX ENDSEND MAIN================================================================= 2.编写一个程序,从键盘输入任意一串字符,然后将这个字符串中的所有小写字母替换成大写字母(其他字母不做修改),并显示在屏幕上。
汇编语言程序设计实验报告学院:计算机科学与技术专业:计算机科学与技术班级:计科131MOV AH,2INT 21H ;显示高位ASCII 码MOV DL,BLAND DL,0FHCMP DL,9JBE NEXT2ADD DL,7NEXT2: ADD DL,30HMOV AH,2INT 21H ;显示低位ASCII 码MOV AH,4CHINT 21HCODE ENDS ;返回DOSEND START使用相应的文本编辑器建立文件three.asm,内容如上所示。
2.生成可执行文件:1>.汇编:C:\masm> masm three;2>.连接:C:\masm> link three;3.运行及调试:1>. 运行:C:\masm>debug three.exe-U0 ;通过反汇编查找程序的断点-T=0 2 ;加载数据段-D0 ;查看原始数据是否正确-G=0 XX ;运行程序至断点XX 处-R ;查看程序运行结果以上命令执行的细节可参照实验二中的说明。
4.调试:修改AL 的内容,判断此程序是否能正确显示其中的内容的方法。
例:修改AL 内容为9AH:-L ;重新加载可执行文件-A0 ;重新修改MOV AL,3EH 指令361E:0000 MOV AL,9A361E:0002-G=0 xx;带断点运行-R ;查看程序运行结果实验二:编写一个数据区移动程序,要考虑源数据区与目的数据区有重叠的情况。
1.源程序如下所示,编辑下面的源程序到文件lab.asm 中:使用相应的文本编辑器建立文件lab.asm,内容如上所示。
2.生成可执行文件:1>.汇编:C:\masm> masm lab;2>.连接:C:\masm> link lab;。
第二节 8088 汇编速查手册一、数据传输指令───────────────────────────────────────它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.1. 通用数据传送指令.MOV 传送字或字节.MOVSX 先符号扩展,再传送.MOVZX 先零扩展,再传送.PUSH 把字压入堆栈.POP 把字弹出堆栈.PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.BSWAP 交换32位寄存器里字节的顺序XCHG 交换字或字节.( 至少有一个操作数为寄存器,段寄存器不可作为操作数) CMPXCHG 比较并交换操作数.( 第二个操作数必须为累加器AL/AX/EAX )XADD 先交换再累加.( 结果在第一个操作数里 )XLAT 字节查表转换.── BX 指向一张 256 字节的表的起点, AL 为表的索引值 (0-255,即 0-FFH); 返回 AL 为查表结果. ( [BX+AL]->AL )2. 输入输出端口传送指令.IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,其范围是 0-65535.3. 目的地址传送指令.LEA 装入有效地址.例: LEA DX,string ;把偏移地址存到DX.LDS 传送目标指针,把指针内容装入DS.例: LDS SI,string ;把段地址:偏移地址存到DS:SI.LES 传送目标指针,把指针内容装入ES.例: LES DI,string ;把段地址:偏移地址存到ES:DI.LFS 传送目标指针,把指针内容装入FS.例: LFS DI,string ;把段地址:偏移地址存到FS:DI.LGS 传送目标指针,把指针内容装入GS.例: LGS DI,string ;把段地址:偏移地址存到GS:DI.LSS 传送目标指针,把指针内容装入SS.例: LSS DI,string ;把段地址:偏移地址存到SS:DI.4. 标志传送指令.LAHF 标志寄存器传送,把标志装入AH.SAHF 标志寄存器传送,把AH内容装入标志寄存器.PUSHF 标志入栈.POPF 标志出栈.PUSHD 32位标志入栈.POPD 32位标志出栈.二、算术运算指令───────────────────────────────────────ADD 加法.ADC 带进位加法.INC 加 1.AAA 加法的ASCII码调整.DAA 加法的十进制调整.SUB 减法.SBB 带借位减法.DEC 减 1.NEC 求反(以 0 减之).CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).AAS 减法的ASCII码调整.DAS 减法的十进制调整.MUL 无符号乘法.IMUL 整数乘法.以上两条,结果回送AH和AL(字节运算),或DX和AX(字运算),AAM 乘法的ASCII码调整.DIV 无符号除法.IDIV 整数除法.以上两条,结果回送:商回送AL,余数回送AH, (字节运算);或商回送AX,余数回送DX, (字运算).AAD 除法的ASCII码调整.CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)三、逻辑运算指令───────────────────────────────────────AND 与运算.OR 或运算.XOR 异或运算.NOT 取反.TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).SHL 逻辑左移.SAL 算术左移.(=SHL)SHR 逻辑右移.SAR 算术右移.(=SHR)ROL 循环左移.ROR 循环右移.RCL 通过进位的循环左移.RCR 通过进位的循环右移.以上八种移位指令,其移位次数可达255次.移位一次时, 可直接用操作码. 如 SHL AX,1.移位>1次时, 则由寄存器CL给出移位次数.如 MOV CL,04SHL AX,CL四、串指令───────────────────────────────────────DS:SI 源串段寄存器 :源串变址.ES:DI 目标串段寄存器:目标串变址.CX 重复次数计数器.AL/AX 扫描值.D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.Z标志用来控制扫描或比较操作的结束.MOVS 串传送.( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )CMPS 串比较.( CMPSB 比较字符. CMPSW 比较字. )SCAS 串扫描.把AL或AX的内容与目标串作比较,比较结果反映在标志位.LODS 装入串.把源串中的元素(字或字节)逐一装入AL或AX中.( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )STOS 保存串.是LODS的逆过程.REP 当CX/ECX<>0时重复.REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复.REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复.REPC 当CF=1且CX/ECX<>0时重复.REPNC 当CF=0且CX/ECX<>0时重复.五、程序转移指令───────────────────────────────────────1>无条件转移指令 (长转移)JMP 无条件转移指令CALL 过程调用RET/RETF过程返回.2>条件转移指令 (短转移,-128到+127的距离内)( 当且仅当(SF XOR OF)=1时,OP1<OP2 )JA/JNBE 不小于或不等于时转移.JAE/JNB 大于或等于转移.JB/JNAE 小于转移.JBE/JNA 小于或等于转移.以上四条,测试无符号整数运算的结果(标志C和Z).JG/JNLE 大于转移.JGE/JNL 大于或等于转移.JL/JNGE 小于转移.JLE/JNG 小于或等于转移.以上四条,测试带符号整数运算的结果(标志S,O和Z).JE/JZ 等于转移.JNE/JNZ 不等于时转移.JC 有进位时转移.JNC 无进位时转移.JNO 不溢出时转移.JNP/JPO 奇偶性为奇数时转移.JNS 符号位为 "0" 时转移.JO 溢出转移.JP/JPE 奇偶性为偶数时转移.JS 符号位为 "1" 时转移.3>循环控制指令(短转移)LOOP CX不为零时循环.LOOPE/LOOPZ CX不为零且标志Z=1时循环.LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.JCXZ CX为零时转移.JECXZ ECX为零时转移.4>中断指令INT 中断指令INTO 溢出中断IRET 中断返回5>处理器控制指令HLT 处理器暂停, 直到出现中断或复位信号才继续.WAIT 当芯片引线TEST为高电平时使CPU进入等待状态.ESC 转换到外处理器.LOCK 封锁总线.NOP 空操作.STC 置进位标志位.CLC 清进位标志位.CMC 进位标志取反.STD 置方向标志位.CLD 清方向标志位.STI 置中断允许位.CLI 清中断允许位.六、伪指令───────────────────────────────────────DW 定义字(2字节).PROC 定义过程.ENDP 过程结束.SEGMENT 定义段.ASSUME 建立段寄存器寻址.ENDS 段结束.END 程序结束.第三节 8088 汇编跳转一、状态寄存器PSW(Program Flag)程序状态字寄存器,是一个16位寄存器,由条件码标志(flag)和控制标志构成,如下所示:1 5 1413121119 8 7 6 5 4 3 2 1 0OFDFIFTFSFZFAF PF CF条件码:①OF(Overflow Flag)溢出标志。
8086汇编语⾔学习(⼆)8086汇编开发环境搭建和Debug模式介绍1. 8086汇编开发环境搭建 在上篇博客中简单的介绍了8086汇编语⾔。
⼯欲善其事,必先利其器,在8086汇编语⾔正式开始学习之前,先介绍⼀下如何搭建8086汇编的开发环境。
汇编语⾔设计之初是⽤于在没有操作系统的裸机上直接操作硬件的,但对于⼤部分⼈来说,在8086裸机上直接进⾏编程将会⾯临各种困难。
好在我们可以使⽤软件模拟器来模拟硬件进⾏8086的学习实践。
在《汇编语⾔》中作者推荐通过windows环境下的masm和debug进⾏学习。
masm介绍: masm是⼀款DOS下的汇编⼯具包,在8086汇编的学习中我们需要其中的⼏个⽂件,分别是masm.exe,link.exe。
masm.exe 汇编器,⽤于将⽂本格式的汇编语⾔源⽂件编译为.obj结尾的⼆进制⽂件,其⽣成的.obj结尾的⼆进制⽬标⽂件是被编译的源⽂件的对应的机器码。
单独的源程序⽬标⽂件通常是⽆法直接运⾏的,还需要和互相依赖的其它同样编译完成的⼆进制⽂件链接在⼀起才能⽣成最终的可执⾏⽂件(⽐如所需要的静态库函数) 。
因此,obj⽂件通常也被叫做中间⽂件。
link.exe 链接器,obj⽂件需要通过链接才能转换成可执⾏程序,⽽链接器就是负责完成这⼀任务的。
链接器能将多个obj⽬标⽂件以及其所依赖的库程序进⾏统⼀处理(例如多个⽬标⽂件中指令、数据内存地址的偏移处理),并⽣成可执⾏⽂件。
debug介绍: debug.exe 调试器,windows提供了⼀个在dos中调试8086汇编程序的⼯具debug.exe,提供了展⽰程序运⾏时CPU中各寄存器、内存中数据,指令级的单步调试等功能。
debug程序的使⽤会在本篇博客的后半段进⾏详细介绍。
64位操作系统兼容性问题: 由于《汇编语⾔》⼀书出版较早,当时的windows系统还是32位的,32位windows系统都默认安装了masm与debug,能打开dos窗⼝直接使⽤。
汇编语言(应用)程序(80X86/Pentium)设计:乐金松广东工业大学电子与信息工程学院;This program for:R0R1-R2R3=R4R5;---------------------------------------------------------------- ;define stack segmentSTACK SEGMENT STACK 'STACK'DB 1024 DUP (0)STACK ENDS;define data segmentDATA SEGMENTR0 DW (?)R1 DW (?)R2 DW (?)R3 DW (?)R4 DW (?)R5 DW (?)R6 DW (?)R7 DW (?)DATA ENDS;define code segmentNDWSUB SEGMENT;MAIN PROC FARASSUME CS:NDWSUB,DS:DATA,SS:STACK;START: PUSH DS ;return DOS standard programMOV AX,0PUSH AXMOV AX,DATA ;set DSMOV DS,AXMOV AX,R1SUB AX,R3MOV R5,AXMOV AX,R0SBB AX,R2MOV R4,AXRETMAIN ENDPNDWSUB ENDSEND START;This program for:R0R1+R2R3=R4R5;---------------------------------------------------------------- ;define stack segmentSTACK SEGMENT STACK 'STACK'DB 1024 DUP (0)STACK ENDS;define data segmentDATA SEGMENTR0 DW (?)R1 DW (?)R2 DW (?)R3 DW (?)R4 DW (?)R5 DW (?)R6 DW (?)R7 DW (?)DATA ENDS;define code segmentNDWADD SEGMENT;MAIN PROC FARASSUME CS:NDWADD,DS:DATA,SS:STACK;START: PUSH DS ;return DOS standard programMOV AX,0PUSH AXMOV AX,DATAMOV DS,AXMOV AX,R1ADD AX,R3MOV R5,AXMOV AX,R0ADC AX,R2MOV R4,AXRETMAIN ENDP ;end process NDWADD ENDS ;end segmentEND START三、无符号二进制32位乘32位,结果为64位乘法子程序;This program for:R2R3*R6R7=R4R5R6R7;----------------------------------------------------------- ;define stack segmentSTACK SEGMENT STACK 'STACK'DB 1024 DUP (0)STACK ENDS;define data segmentDATA SEGMENTBWORD EQU THIS BYTER0 DW (?)R1 DW (?)R2 DW (?)R3 DW (?)R4 DW (?)R5 DW (?)R6 DW (?)R7 DW (?)DATA ENDS;define code segmentNBMUL SEGMENT;MAIN PROC FARASSUME CS:NBMUL,DS:DATA,SS:STACK;START: PUSH DS ;return DOS standard programMOV AX,0PUSH AXMOV AX,DATA ;set DSMOV DS,AXMOV AX,R3MUL R7 ;R3*R7=DXAXXCHG AX,R7MOV R5,DXMUL R2 ;R2*R7=DXAXADD AX,R5MOV R4,AXMOV AX,0ADC AX,DX ;DC+Cy+0 to R5MOV R5,AXMOV AX,R6MUL R3ADD AX,R4XCHG AX,R6ADC R5,DXPUSHF ;Save Cy to stack MUL R2ADD R5,AXMOV AX,0ADC DX,AX ;DX+Cy+0=DXPOPFADC DX,AXMOV R4,AXRETMAIN ENDPNBMUL ENDSEND START四、无符号二进制64位除32位,结果为32位除法子程序注意几个问题:1、判断够减或不够减的方法2、够减时的处理方法3、不够减时的处理方法4、商上1的位置和方法5、商上零的方法;This program for:R4R5R6R7/R2R3=R6R7 ;Remainder=(R4R5);---------------------------------------------------------------- ;define stack segmentSTACK SEGMENT STACK 'STACK'DB 1024 DUP (0)STACK ENDS;define data segmentDATA SEGMENTBWORD EQU THIS BYTE ;注意这条伪指令的用法 R0 DW (?)R1 DW (?)R2 DW (?)R3 DW (?)R4 DW (?)R5 DW (?)R6 DW (?)R7 DW (?)DATA ENDS;define code segmentNBDIV SEGMENT;MAIN PROC FARASSUME CS:NBDIV,DS:DATA,SS:STACK;START: PUSH DS ;return DOS standard programMOV AX,0PUSH AXMOV AX,DATA ;set DSMOV DS,AXMOV AX,R5SUB AX,R3MOV AX,R4SBB AX,R2JNC DIV4 ;Over processMOV CX,32 ;32次循环的目的?DIV1: CLCRCL R7,1RCL R6,1RCL R5,1RCL R4,1PUSHFPOP R0 ;Store RF to R0MOV AX,R5SUB AX,R3MOV R1,AXMOV AX,R4SBB AX,R2PUSHFTEST BYTE PTR R0,01HJNZ DIV21POPFJNC DIV2JMP DIV3DIV21: POPFDIV2: MOV R4,AXMOV AX,R1MOV R5,AXINC R7DIV3: LOOP DIV1STCDIV4: RETMAIN ENDPNBDIV ENDSEND START五、10位非压缩BCD码转化成32位二进制数子程序(十翻二子程序)思考:1、结果乘10怎样乘?2、加下一位怎样加?3、将程序改成16位10进制数转换成48位二进制数,怎样修改程序?;This program for:buffer0-buffer9 BCD code convert into Binary;input=buffer0--buffer9 (10 Byte Type no compressible BCD code) ;output=R1R0 (Word Type binary);---------------------------------------------------------------- ;define stack segmentSTACK SEGMENT STACK 'STACK'DB 1024 DUP (0)STACK ENDS;define data segmentDATA SEGMENTBWORD EQU THIS BYTER0 DW (?)R1 DW (?)R2 DW (?)R3 DW (?)R4 DW (?)R5 DW (?)R6 DW (?)R7 DW (?)buffer0 DB (?)buffer1 DB (?)buffer2 DB (?)buffer3 DB (?)buffer4 DB (?)buffer5 DB (?)buffer6 DB (?)buffer7 DB (?)buffer8 DB (?)buffer9 DB (?)DATA ENDS;define code segmentDCTB SEGMENT;MAIN PROC FARASSUME CS:DCTB,DS:DATA,SS:STACK;START: PUSH DS ;return DOS standard program MOV AX,0PUSH AXMOV AX,DATA ;set DSMOV DS,AXLEA BX,buffer9MOV R0,0MOV R1,0MOV CX,10DO_LOOP: MOV AX,R0MOV R7,10MUL R7MOV R0,AXXCHG DX,R1MOV AX,DXMUL R7ADD R1,AXMOV AL,[BX]MOV AH,0ADD R0,AXADC R1,0DEC BXLOOP DO_LOOPRETMAIN ENDPDCTB ENDSEND START六、48位二进制数转换成十进制数子程序思考:1、结果乘二怎样乘?2、加下一位怎样加?在哪里加?3、用什么方法转化成10进制,如果无调整指令该怎么做?4、将程序改成32位二进制转化成十进制数怎么转化;This program for:R5R6R7 binanry data convert into BCD;of compressible code;input=R5R6R7;output=buffer0--buffer7;---------------------------------------------------------------- ;define stack segmentSTACK SEGMENT STACK 'STACK'DB 1024 DUP (0)STACK ENDS;define data segmentDATA SEGMENTBWORD EQU THIS BYTER0 DW (?)R1 DW (?)R2 DW (?)R3 DW (?)R4 DW (?)R5 DW (?)R6 DW (?)R7 DW (?)buffer0 DB (?)buffer1 DB (?)buffer2 DB (?)buffer3 DB (?)buffer4 DB (?)buffer6 DB (?)buffer7 DB (?)DATA ENDS;define code segmentBCTD SEGMENTMAIN PROC FARASSUME CS:BCTD,DS:DATA,SS:STACKSTART: PUSH DS ;return DOS standard program MOV AX,0PUSH AXMOV AX,DATA ;set DSMOV DS,AXMOV CX,8LEA BX,[buffer0]CLR_BUFFER: MOV BYTE PTR [BX],0INC BXLOOP CLR_BUFFERMOV CX,48DO_LOOP: CLCRCL R7,1RCL R6,1RCL R5,1MOV AL,buffer0ADC AL,ALDAAMOV buffer0,ALMOV AL,buffer1ADC AL,ALDAAMOV buffer1,ALMOV AL,buffer2ADC AL,ALDAAMOV buffer2,ALMOV AL,buffer3ADC AL,ALDAAMOV buffer3,ALMOV AL,buffer4ADC AL,ALDAAMOV AL,buffer5ADC AL,ALDAAMOV buffer5,ALMOV AL,buffer6ADC AL,ALDAAMOV buffer6,ALMOV AL,buffer7ADC AL,ALDAAMOV buffer7,ALLOOP DO_LOOPRETMAIN ENDPBCTD ENDSEND START七、键盘读入子程序功能:读入一个按键,并显示字符,,按“ESC”退出程序,其中调用字符显示程序思考: 1、如何判断有无按键按下?2、如何读取按键的键值?3、如何显示一个字符?;This program for:sample program of key input;----------------------------------------------------------------;define stack segmentSTACK SEGMENT STACK 'STACK'DB 1024 DUP (0)STACK ENDS;------------------------------------;define data segmentDATA SEGMENTBWORD EQU THIS BYTER0 DW (?)R1 DW (?)R2 DW (?)R3 DW (?)R4 DW (?)R5 DW (?)R6 DW (?)R7 DW (?)ROW_REG DB (?) ;ROW*COLCOL_REG DB (?)DATA ENDS;------------------------------------;define es segmentVIDEO SEGMENT AT 0B800HWD_BUFFER LABEL WORDV_BUFF DB 25*80*2 DUP (?)VIDEO ENDS;------------------------------------;define code segmentPROGRAM SEGMENTMAIN PROC FARASSUME CS:PROGRAM,DS:DATA,SS:STACK,ES:VIDEO;START: PUSH DS ;return DOS standard program MOV AX,0PUSH AXMOV AX,DATA ;set DSMOV DS,AXMOV AX,VIDEO ;set ESMOV ES,AXMOV ROW_REG,10MOV COL_REG,20MOV R0,0000H ;clr screenMOV R1,184FHMOV BH,0FH ;set background colorCALL CLR_SCREEN;---------------------------------------SCAN_KEY: MOV AH,1INT 16H ;Test KeyJZ SCAN_KEYYES_KEY: MOV AH,0INT 16H ;Read keyCMP AL,1BH ;test "esc=1bh" keyJNZ KEY_PROCESSJMP EXIT ;if "ESC" Key go to EXITKEY_PROCESS: MOV AH,5FH ;Set symbol colorMOV CL,COL_REG ;Set locat of symbolMOV CH,ROW_REGCALL DISPLAYINC COL_REGCMP COL_REG,61JNE KEY_PROCESS1MOV COL_REG,20INC ROW_REGCMP ROW_REG,16JNE KEY_PROCESS1MOV ROW_REG,15MOV COL_REG,60KEY_PROCESS1: MOV AH,02H ;Set arrow locationMOV DH,ROW_REGMOV DL,COL_REGMOV BH,0INT 10HJMP SCAN_KEYEXIT: MOV R0,0000HMOV R1,184FHMOV BH,0FH ;set background colorCALL CLR_SCREENRETMAIN ENDP;*************************************************************** ;bellow is a some proc near program;-----------------------------------;display a symbol;input: symbol=al ;字符的ASCII码; color=ah ;颜色属性; row=ch ;行坐标; col=cl ;列坐标;use reg:AX,BX,CXDISPLAY PROC NEAR ;address of display;buffer=row*80*2+col*2PUSH BXPUSH CXPUSH AXMOV AL,160MUL CH ;ROW*80*2(160)=AXMOV BL,CLMOV BH,0ADD BX,AXPOP AXMOV ES:[WD_BUFFER+BX],AXPOP CXPOP BXRETDISPLAY ENDP;-------------------------------------------------------------- CLR_SCREEN PROC NEAR ;清除屏幕MOV AH,06HMOV CX,R0MOV DX,R1INT 10HMOV AH,02HMOV DH,ROW_REGMOV DL,COL_REGMOV BH,0INT 10HRETCLR_SCREEN ENDP;-------------------------------------------------------------- PROGRAM ENDSEND START八、显示日期和时间程序思考:1、怎样读取日期,和时间2、怎样在屏幕上定位显示坐标?3、怎样显示日期和时间4、其中调用哪些系统程序?;This program for:display date and time;---------------------------------------------------------------- ;define stack segmentSTACK SEGMENT STACK 'STACK'DB 1024 DUP (0)STACK ENDS;define data segmentDATA SEGMENTBWORD EQU THIS BYTER0 DW (?)R1 DW (?)R2 DW (?)R4 DW (?)R5 DW (?)R6 DW (?)R7 DW (?);-------------------------------------------------- TEMP1 DW (?)TEMP2 DW (?)TEMP3 DW (?)TEMP4 DW (?);-------------------------------------------------- LED1 DB (?)LED2 DB (?)LED3 DB (?)LED4 DB (?)LED5 DB (?)LED6 DB (?)LED7 DB (?)LED8 DB (?)LED9 DB (?)LED10 DB (?)LED11 DB (?)LED12 DB (?)LED13 DB (?)LED14 DB (?)LED15 DB (?)LED16 DB (?)LED17 DB (?)LED18 DB (?)LED19 DB (?);------------------------------------YEAR_REG DB (?)MOTH_REG DB (?)DATE_REG DB (?)S_REG DB (?)M_REG DB (?)H_REG DB (?);----------------DATA ENDS;------------------------------------;define es segmentVIDEO SEGMENT AT 0B800HWD_BUFFER LABEL WORDV_BUFF DB 25*80*2 DUP (?)VIDEO ENDS;------------------------------------;define code segmentPROGRAM SEGMENT;MAIN PROC FARASSUME CS:PROGRAM,DS:DATA,SS:STACK,ES:VIDEO;START: PUSH DS ;return DOS standard program MOV AX,0PUSH AXMOV AX,DATA ;set DSMOV DS,AXMOV AX,VIDEO ;set ESMOV ES,AXMOV TEMP1,0000H ;clr screenMOV TEMP2,184FHMOV BH,0FH ;set background colorCALL CLR_SCREEN;---------------------------------------DO_WAIT: MOV AH,1INT 16H ;Test KeyJZ NO_KEYYES_KEY: MOV AH,0INT 16H ;Read keyCMP AL,1BH ;test "esc=1bh" keyJNZ NO_KEYJMP EXIT ;if "ESC" Key go to EXITNO_KEY: CALL READ_TIMECALL READ_DATECALL CONVERT_ASCIICALL DISPLAY_TIMECALL DISPLAY_DATEJMP DO_WAITEXIT: MOV TEMP1,0000HMOV TEMP2,184FHMOV BH,0FH ;set background colorCALL CLR_SCREENRETMAIN ENDP;*************************************************************** ;bellow is a some proc near program;-----------------------------------;read time;input=no;out= H_REG,M_REG,S_REG ,all data is BCD codeREAD_TIME PROC NEARMOV AH,02H ;read time,ah=02hINT 1AH ;out=ch(h),cl(m),dh(s)MOV H_REG,CHMOV M_REG,CLMOV S_REG,DHRETREAD_TIME ENDP;--------------------------------------;read date;input=on;out=YEAR_REG,MOTH_REG,DATE_REG,all data is BCD codeREAD_DATE PROC NEARMOV AH,04H ;read time,ah=02hINT 1AH ;out=ch(h),cl(m),dh(s)MOV YEAR_REG,CLMOV MOTH_REG,DHMOV DATE_REG,DLRET;------------------------------------------;convert time and data into ASCII code and store to display buffer CONVERT_ASCII PROC NEARMOV AL,H_REG ;process timeAND AL,0F0HMOV CL,4ROR AL,CLADD AL,30H ;Convert ASCIIMOV LED1,ALMOV AL,H_REGAND AL,0FHADD AL,30H ; Convert ASCIIMOV LED2,ALMOV AL,M_REGAND AL,0F0HMOV CL,4ADD AL,30H ; Convert ASCII MOV LED4,ALMOV AL,M_REGAND AL,0FHADD AL,30H ; Convert ASCII MOV LED5,ALMOV AL,S_REGAND AL,0F0HMOV CL,4ROR AL,CLADD AL,30H ; Convert ASCII MOV LED7,ALMOV AL,S_REGAND AL,0FHADD AL,30H ; Convert ASCII MOV LED8,ALMOV LED3,3AH ;set ":"MOV LED6,3AH ;set ":";----------------------------------------------------MOV AL,YEAR_REG ;process date AND AL,0F0HMOV CL,4ROR AL,CLADD AL,30H ; Convert ASCII MOV LED12,ALMOV AL,YEAR_REGAND AL,0FHADD AL,30H ; Convert ASCII MOV LED13,ALMOV AL,MOTH_REGAND AL,0F0HMOV CL,4ROR AL,CLADD AL,30H ; Convert ASCII MOV LED15,ALMOV AL,MOTH_REGAND AL,0FHADD AL,30H ; Convert ASCIIMOV LED16,ALMOV AL,DATE_REGMOV CL,4ROR AL,CLADD AL,30H ; Convert ASCIIMOV LED18,ALMOV AL,DATE_REGAND AL,0FHADD AL,30H ; Convert ASCIIMOV LED19,ALMOV LED10,32H ;"2"MOV LED11,30H ;"0"MOV LED14,2DH ;"-"MOV LED17,2DH ;"-"RETCONVERT_ASCII ENDP;-------------------------------------------------------;display a symbol;input: symbol=al; color=ah; row=ch; col=cl;use reg:AX,BX,CXDISPLAY PROC NEAR ;address of display;buffer=row*80*2+col*2PUSH BXPUSH CXPUSH AXMOV AL,160MUL CH ;ROW*80*2(160)=AXMOV BL,CLROL BL,1 ;BL*2MOV BH,0ADD BX,AXPOP AXMOV ES:[WD_BUFFER+BX],AXPOP CXPOP BXRETDISPLAY ENDP;-------------------------------------------------------------- ;display time,send led1-led8 data to screenDISPLAY_TIME PROC NEARMOV R0,8LEA BX,LED1MOV CX,0E23HDISPLAY_TIME1: MOV AL,[BX]MOV AH,1EH ;00001110B ,set symbol colorCALL DISPLAYINC CXINC BXDEC R0JNZ DISPLAY_TIME1RETDISPLAY_TIME ENDP;-------------------------------------------------------------- ;display DATE,send led10-led19 data to screenDISPLAY_DATE PROC NEARMOV R0,10LEA BX,LED10MOV CX,0922HDISPLAY_DATE1: MOV AL,[BX]MOV AH,5FH ;00001110B ,set symbol colorCALL DISPLAYINC CXINC BXDEC R0JNZ DISPLAY_DATE1RETDISPLAY_DATE ENDP;-------------------------------------------------------------- CLR_SCREEN PROC NEARMOV AH,06HMOV CX,TEMP1MOV DX,TEMP2INT 10HMOV AH,02HMOV DH,24MOV DL,80MOV BH,0INT 10HRETCLR_SCREEN ENDP;-------------------------------------------------------------- PROGRAM ENDSEND START。
1、产生频率200Hz的方波输出信号。
外加时钟频率为1MHz时,选择8253定时通道0。
画出电路图、按要求编写程序,在仿真环境下调试通过。
(N=5000)2、设计一个楼道延时开关电路。
通过一个按钮启动后,220VAC供电的照明灯点亮,同时20s延时启动;20s过后,照明灯灭。
延时控制信号通过一个继电器控制220VAC供电的照明灯。
外加时钟频率为1kHz,选择8253定时通道1。
画出电路图、按要求编写程序,在仿真环境下调试通过。
(N=20000)3、设计一个4位LED数码显示的十进制减法计数器。
初始值为1000,用一个按钮开关模拟计数信号,每按动一次按钮,计数器减一。
4位LED 7段数码管显示实时的计数值。
数码管选用BCD码控制的LED器件。
选择8253定时通道2。
画出电路图、按要求编写程序,在仿真环境下调试通过。
(方式0,读取计数值,通过IO接口电路发送,显示出来)代码1DA TAS SEGMENTnum_0 equ 0020hnum_1 equ 0022hnum_2 equ 0024hcontrol equ 0026h;此处输入数据段代码DA TAS ENDSSTACKS SEGMENT;此处输入堆栈段代码STACKS ENDSCODES SEGMENTASSUME CS:CODES,DS:DA TAS,SS:STACKSSTART:MOV AX,DATASMOV DS,AXmov al,00110111Bmov dx,controlout dx,almov al,00mov dx,num_0out dx,almov al,50mov dx,num_0out dx,al;此处输入代码段代码MOV AH,4CHINT 21HCODES ENDSEND STARTDA TAS SEGMENTnum_0 equ 0100hnum_1 equ 0102hnum_2 equ 0104hcontrol equ 0106h;此处输入数据段代码DA TAS ENDSSTACKS SEGMENT;此处输入堆栈段代码STACKS ENDSCODES SEGMENTASSUME CS:CODES,DS:DA TAS,SS:STACKS START:MOV AX,DATASMOV DS,AXmov al,01110011Bmov dx,controlout dx,almov al,00mov dx,num_2out dx,almov al,200mov dx,num_2out dx,al;此处输入代码段代码MOV AH,4CHINT 21HCODES ENDSEND START代码2DA TAS SEGMENTnum_0 equ 0100hnum_1 equ 0102hnum_2 equ 0104hcontrol equ 0106h;此处输入数据段代码DA TAS ENDSSTACKS SEGMENT;此处输入堆栈段代码STACKS ENDSCODES SEGMENTASSUME CS:CODES,DS:DA TAS,SS:STACKS START:MOV AX,DATASMOV DS,AXmov al,01110011Bmov dx,controlout dx,almov al,00mov dx,num_2out dx,almov al,200mov dx,num_2out dx,al;此处输入代码段代码MOV AH,4CHINT 21HCODES ENDSEND START。
1.编写一个程序,从键盘输入任意十进制正数,然后将这个数按16进制形式显示在屏幕上。
DECIHEX SEGMENT ; 定义代码段
ASSUME CS:DECIHEX
MAIN PROC FAR ; 主程序
REPEAT: CALL DECIBIN ; 调用子程序输入十进制数
CALL CRLF ; 显示回车、换行
CALL BINIHEX ; 以十六进制数输出
CALL CRLF ; 显示回车、换行
JMP REPEAT ; 转REPEA T,继续
MAIN ENDP
DECIBIN PROC NEAR ; 十进制数输入子程序
MOV BX, 0 ; BX保存输入数
NEWCHAR: MOV AH, 1
INT 21H ; 调用DOS功能输入字符
SUB AL, 30H ; 转为数0-9
JB EXIT ; 小于0,不是数字
CMP AL, 9D ; 与9比较
JA EXIT ; 大于,不是数字
CBW ; AL=>AX
XCHG AX, BX ; AX、BX互换
MOV CX, 10D ; CX=10
MUL CX ; AX=AX*CX
ADD BX, AX ; BX为前面输入的结果
JMP NEWCHAR
EXIT: RET
DECIBIN ENDP
BINIHEX PROC NEAR
MOV CH, 4 ; CH循环次数
ROTA TE: MOV CL, 4 ;每次循环输出一位十六进制数
ROL BX, CL ; 即移位4个二进制位
MOV AL, BL ; AL=BL
AND AL, 0FH ; 取低4位
ADD AL, 30H ; 转变为ASCII码
CMP AL, 3AH ; 是否为’0’-‘9’
JL PRINTIT ; 是转PRINTIT
ADD AL, 7H ; 否转为’A’-‘F’
PRINTIT: MOV DL, AL ; DL=输出字符
MOV AH, 2
INT 21H ;调用DOS中断,显示字符
DEC CH
JNZ ROTA TE ; 没循环结束,继续
RET ; 返回
BINIHEX ENDP
CRLF PROC NEAR ; 输出回车、换行
MOV DL, 0DH
MOV AH, 2
INT 21H ; 输出回车
MOV DL, 0AH
MOV AH, 2
INT 21H ; 输出换行
RET
CRLF ENDP
DECIHEX ENDS
END MAIN
================================================================= 2.编写一个程序,从键盘输入任意一串字符,然后将这个字符串中的所有小写字母替换成大写字母(其他字母不做修改),并显示在屏幕上。
data segment
keynum = 255
keybuf db keynum
db 0
db keynum dup(0)
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov dx,offset keybuf
mov ah,0ah
int 21h
mov dl,0ah
mov ah,2
int 21h
mov bx,offset keybuf+1
mov cl,[bx]
mov ch,0
again: inc bx
mov dl,[bx]
cmp dl,'a'
jb disp
cmp dl,'z'
ja disp
sub dl,20h
disp: mov ah,2
int 21h
loop again
mov ax,4c00h
int 21h
code ends
end start
========================================== =======================
3.编写一个小程序,测试给定的一个8位数,从最低位开始,那一位为“1”,显示该位的位号。
例如:如果给定数据为78H,则显示3,若给定数据为80H,则显示7。
data segment
number db 78h
addrs dw fun0, fun1, fun2, fun3
dw fun4, fun5, fun6, fun7
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov al,number
mov dl,'?'
cmp al,0
jz disp
mov bx,0
again: shr al,1
jc next
inc bx
jmp again
next: shl bx,1
jmp addrs[bx]
fun0: mov dl,'0'
jmp disp
fun1: mov dl,'1'
jmp disp
fun2: mov dl,'2'
jmp disp
fun3: mov dl,'3'
jmp disp
fun4: mov dl,'4'
jmp disp
fun5: mov dl,'5'
jmp disp
fun6: mov dl,'6'
jmp disp
fun7: mov dl,'7'
jmp disp
disp: mov ah,2
int 21h
mov ax,4c00h
int 21h
code ends
end start
==========================================
=======================
4. 编写一个小程序,任意从键盘输入一个字符,用二进
制数显示该字符的ASCII。
例如:如果输入的是“A”,则显示01000001,若输入的
是“7”,则显示00110111
code segment
assume cs:code
start:
mov ah,1
int 21h
mov bl,al
mov ah,2
mov dl,'='
int 21h
mov cx,8
again: shl bl,1
mov dl,0
adc dl,30h
mov ah,2
int 21h
loop again
mov ax,4c00h
int 21h
code ends
end start。