【汇编】实验(上)
实验课作业,实验截图就不放啦~放一些代码
实验一:
- 实验任务一:将汇编源程序拷贝到汇编集成环境,进行调试,体验汇编程序的运行。
(1) 实验步骤
源程序:
DATAS SEGMENT
a db ?
b db ?
k db ?
string db 'k=$'
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME cs:codes, ds:datas,es:datas
start:
main proc far
push ds
sub ax,ax
push ax
mov ax,datas
mov ds,ax
mov es,ax
mov a,1
mov b,2
mov al,a
add al,b
mov k,al
lea dx,string
mov ah,09
int 21h
add k,30h
mov dl,k
mov ah,2
int 21h
mov dl,0ah
int 21h
mov dl,0dh
int 21h
ret
main endp
CODES ENDS
END START
(2) 实验现象
运行结果为k=3.
原有代码存在一些问题,经过修改后代码如上,能够正常运行。
2. 实验任务二:DEBUG的使用
3. 实验任务三:练习使用DEBUG
实验二:
1. 实验任务一:七种寻址方式的认识与练习。
在代码段里输入指令或在DEBUG里输入指令,然后查看指令运行的结果,看看是否跟自己的设想一致,如有问题,想办法解决。
1.立即寻址:mov AL,5
运行结果:将05写入AL中,AX寄存器中为0705
2.寄存器寻址:mov BX,AX
运行结果:将AX写入BX中,BX寄存器中为0705
3.直接寻址:mov AX,DS:[2000H],未修改2000H的数据,仍为0000H。
运行结果:将地址为2000H的数据写入AX中,AX寄存器中为0000
4.寄存器间接寻址:mov CX,[BX],debug时输入-e DS:0705,将数据修改为0039h并运行。
运行结果:将BX为地址的数据写入CX中,CX寄存器中为0039
5.寄存器相对寻址:
mov SI,0065h
mov AX,3000h[SI],debug时输入-e DS:3065,将数据修改为0078h并运行。
运行结果:将[3000+0065]为地址的数据写入AX中,AX寄存器中为0078
6.基址变址寻址:
mov DI,10A5H mov AX,[BX][DI],将地址为17AAH的数据修改为0034H并运行。
运行结果:将[BX+DI]为地址的数据写入AX中,AX寄存器中为0034
7.相对基址变址寻址:
mov AX,1000H[BX][DI],将地址为27AAH的数据修改为0019H并运行。
运行结果:将[1000+BX+DI]为地址的数据写入AX中,AX寄存器中为0019
2. 实验任务二:指令的验证
1)数据传送指令
数据传送指令包括通用数据传送指令、累加器专用传送指令、地址传送指令、标志寄存器传送指令、类型转换指令。
通用数据传送指令包含:
MOV 传送;MOVSX带符号扩展传送;MOVZX 带零扩展传送;PUSH 进栈了;POP 出栈;PUSHA/PUSHAD 所有寄存器进栈;POPA/POPAD 所有寄存器出栈;XCHG 交换。
累加器专用传送指令包含:
IN 输入;OUT 输出;XLAT 换码。
地址传送指令包含:
LEA 有效地址送寄存器;LDS 指针送寄存器和DS;LES 指针送寄存器和ES;LFS 指针送寄存器和FS;LGS 指针送寄存器和GS;LSS 指针送寄存器和SS。
标志寄存器传送指令包含:
LAHF 标志送AH;SAHF AH送标志寄存器;PUSHF/PUSHFD 标志进栈;POPF/POPFD 标志出栈。
类型转换指令包含:
CBW 字节转换为字;CWD/CWDE 字转换为双字;CDQ 双字转换为4字;BSWAP 字节交换。
2)算术指令
算术指令包括加法指令、减法指令、乘法指令、除法指令、十进制调整指令。
加法指令包含:
ADD 加法;ADC 带进位加法;INC 加1;XADD 交换并相加。
减法指令包含:
SUB 减法;SBB 带借位减法;DEC 减1;NEG 求补;CMP 比较;CMPXCHG 比较并交换;CMPXCHG8B 比较并交换8字节。
乘法指令包含:
MUL 无符号数乘法; IMUL 带符号数乘法。
除法指令包含:
DIV 无符号数除法; IDIV 带符号数除法。
3)逻辑指令
逻辑指令包括逻辑运算指令、位测试并修改指令、位扫描指令、移位指令。
逻辑运算指令包含:
AND 逻辑与;OR 逻辑或;NOT 逻辑非;XOR 异或;TEST 测试。
位测试并修改指令包含;
BT 位测试;BTS 位测试并置1;BTR 位测试并置0;BTC 位测试并求反。
位扫描指令包含:
BSF 正向位扫描; BSR 反向位扫描。
移位指令包含:
SHL 逻辑左移;SAL 算术左移;SHR 逻辑右移;SAR 算术右移;ROL 循环左移;ROR 循环右移;RCL 带进位循环左移;RCR 带进位循环右移;SHLD 双精度左移;SHRD 双精度右移。
3. 实验任务三:小程序的调试
;给各个寄存器赋值
MOV AX, 1234H
MOV DX, 5678H
;运行代码
MOV BL, DL ;将DX低8位赋值给BL
MOV CL, 4 ;给CL赋值04
SAR DX, CL ;将DX算术右移4位
AND BL,0FH ;BL与0FH相与
SHR AX, CL ;将AX逻辑右移4位
ROR BL, CL ;将BL循环右移4位
OR AH, BL ;AH与BL相或
最终AX结果为AX=8123H。
4. 实验任务四:给出下列各条指令执行后AL值,以及CF、ZF、SF、OF和PF的状态
1)MOV AL, 89H
2)ADD AL, AL
3)ADD AL, 9DH
4)CMP AL, 0BCH
5)SUB AL, AL
6)DEC AL
7)INC AL
1)执行后AL值为89H
各标志位为
CF:NC(没有进位); ZF:NZ(不是零);
SF:PL(符号为正); OF:NV(没有溢出);
PF:PO(为奇)。
2)执行后AL值为12H
各标志位为
CF:CY(进位); ZF;NZ(不是零);
SF:PL(符号为正); OF:OV(溢出);
PF:PE(为偶)。
3)执行后AL值为AFH
各标志位为
CF:NC(没有进位); ZF:NZ(不为零);
SF:NG(符号为负); OF:NV(没有溢出);
PF:PE(为偶)。
4)执行后AL值为AFH,不变
各标志位为
CF:CY(进位); ZF:NZ(不为零);
SF:NG(符号为负); OF:NV(没有溢出);
PF:PE(为偶)。
5)执行后AL值为00H
各标志位为
CF:NC(没有进位); ZF:ZR(为零);
SF:PL(符号为正); OF:NV(没有溢出);
PF:PE(为偶)。
6)执行后AL值为FFH
各标志位为
CF:NC(没有进位); ZF:NZ(不为零);
SF:NG(符号为负); OF:NV(没有溢出);
PF:PE(为偶)。
7)执行后AL值为00H
各标志位为
CF:NC(没有进位); ZF:ZR(为零);
SF:PL(符号为正); OF:NV(没有溢出);
PF:PE(为偶)。
实验三:
1. 实验任务一:常用指令练习(结合Debug理解指令功能)
2. 实验任务二:程序段的编制
下面程序段的功能是什么?执行后CX的值为多少?
MOV CX, 0;
MOV BX, 3456H
repeat:
TEST BX, 0ffffh
JZ exit
JNS Shift
INC CX
Shift:
SHL BX,1
JMP repeat
exit:
该程序是一段循环左移的指令,将BX=3456H每次循环左移一位,CX值+1,最终将BX移成0000H为止,CX代表着移动几次,所以最终结果为CX=0007H,代表循环左移7次。
3. 实验任务三:程序段的编制
设变量字A和B的定义如下:
A DW 1234H, 5678H
B DW 9A07H, 45C2H
编程序段求A和B这两个双字数据的加法,和放在变量B中。
数据段代码
A DW 1234H,5678H
B DW 9A07H,45C2H
代码段代码
MOV AX,A
MOV BX,B
ADD BX,AX
MOV B,BX
MOV AX,A+2
MOV BX,B+2
ADD BX,AX
MOV B+2,BX
定义变量字A与B,由于存储单元连续,所以按照存储顺序在0000地址内存入了34,在0001地址中存入了12,0002地址中为78,0003地址中为56。同理,在0004至0007地址中,分别是07、9A、C2和45。
我对A和B的数据分别进行加法计算,先将1234H与9A07H进行加法计算,并把结果覆盖掉0004与0005地址中的内容,因此0004与0005地址中的内容为3B和AC。同理再对5678H与45C2H进行计算,得到9C3AH的计算结果,同样存入45C2H原本的存储单元内,即0006与0007地址所对应的内存单元中,将其中内容修改为3A和9C。
因此最后0004至0007地址中存入的数据为3B、AC、3A和9C,如下图所示。
实验四:
1. 实验任务一:设AL=x,若x<100,AL=AL+50;若x>=100,AL=AL-100,编程实现。
初始值x根据设定改变:
代码如下:
DATAS SEGMEpNT
Xdb 110
;string db 'AL=$'
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME DS:datas
start:
main proc far
MOV AX,DATAS
MOV DS,AX
MOV AL,X
CMP AL,100
JNZ NO1;不等于bai1
SUB AL,100;等于1的程序段du
JMP EXIT
NO1:CMP AL,100
JL XIAOYU
SUB AL,100;大于1的程序段
JMP EXIT
XIAOYU:ADD AL,50 ;小于1的程序段
EXIT:
;lea dx,string
mov dl,AL
AAM
MOV BL,AL
ADD BL,30H
ADD AH,30H
mov dl,AH
MOV AH,2
INT 21H
mov dl,BL
INT 21H
MOV AH,4CH
int 21h
ret
main endp
CODES ENDS
END START
2.实验任务二:编制程序完成如下两个32位数相加:1F98243H + 34567890H
双字运算只有在386及其后继机型可以进行,因此只能在8086中只可以进行16位的运算,因此将两个32位分别分成两个16位二进制进行进位运算。将01F98243H分成高4位01F9H和低四位8243H,将34567890H分成高四位3456H和低四位7890H,先进行低四位的运算8243H+7890H,得到答案FAD3H,并没有产生进位。再进行高四位运算,01F9H+3456H,得到364FH。将这两个16位二进制数存入之后相邻的内存单元,完成运算。
代码如下:
DATAS SEGMENT
A DW 01F9H,8243H
B DW 3456H,7890H
CC DW ?
E DW ?;此处输入数据段代码
DATAS ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV AX,A+2 ;先进行低四位运算
MOV BX,B+2
ADD BX,AX
MOV CC,BX
MOV AX,A ;再进行高四位运算
MOV BX,B
ADC BX,AX
MOV E,BX
;此处输入代码段代码
MOV AH,4CH
INT 21H
CODES ENDS
END START
3.在数据段定义3个字变量AA=200,BB=300,CC,编制程序实现AA和BB相加,结果保存在CC中。
数据段如下
DATAS SEGMENT
AA DW 100
BB DW 200
CC DW ?
;string db 'AL=$'
DATAS ENDS
4.实验任务四:编制程序计算以下表达式:Y=(W-X*Z)/(X-2)+100,其中W=100、X=10、Z=2 、Y在数据段定义。
由于8086的除法运算要求字节操作为16位被除数在AX中,8位除数为源操作数,结果的8位商在AL中,8位余数在AH中。因此,将W=100定义为字,X=10和Z=2定义为字节。数据段代码如下:
DATAS SEGMENT
W DW 100
X DB 10
Z DB 2
Y DW ?;此处输入数据段代码
DATAS ENDS
5.实验任务五:编程查找字符串STR中是否包含$字符,若包含,KEY单元置1,否则置0。
首先自行定义了一串字符串str1为‘ab$d’,KEY和字符串长度,数据段代码如下:
DATAS SEGMENT
KEY DB ?
str1 DB 'abd$'
len1 DW 4
;此处输入数据段代码
DATAS ENDS
在SI寄存器中存入0,表示正在判断的那一位字符。
SI从0开始进行判断:
先判断SI是否等于len1,若不等于则允许SI+1,若等于len1,则跳转到程序结束。
若str1[SI]等于‘$’,则将KEY置1,并结束程序;
若str1[SI]不等于‘$’,则SI+1。
代码段代码如下:
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
MOV SI,0
MOV KEY,0
L2: CMP SI,len1 ;SI与len1进行比较,若等于则结束程序
JZ L1
CMP str1[SI],'$' ;字符与‘$’进行比较
JZ L3
ADD SI,1
JMP L2
L3: MOV KEY,1 ;将KEY置1
JMP L1
L1: MOV AH,4CH ;程序结束
INT 21H
CODES ENDS
END START