汇编语言实验报告 下载本文

合肥工业大学

实验报告

课 程:汇编语言程序设计

专业班级:

学 号:

姓 名:

实验一 Debug程序的使用

一. 实验目的

1、熟悉DEBUG程序中的命令,学会在DEBUG下调试运行汇编语言源程序。 2、掌握8086/8088的寻址方式及多字节数据的处理方法。

二. 实验内容

1、利用DEBUG程序中的“E”命令,将两个多字节数“12345678H”和“FEDCBA98H”分别送入起始地址为DS:0200H和DS:0204H两个单元中。

2、分别用直接寻址方式和寄存器间接寻址方式编写程序段,实现将DS:0200H单元和DS:0204H单元中的数据相加,并将运算结果存放在DS:0208H单元中。 要求:

本次实验的内容均在DEBUG下完成,实现数据的装入、修改、显示;汇编语言程序段的编辑、汇编和反汇编;程序的运行和结果检查。

三. 实验过程和程序

基础题:

1、利用DEBUG程序中的“E”命令,将两个多字节数“12345678H”和“FEDCBA98H”分别送入起始地址为DS:0200H和DS:0204H两个单元中。

2、分别用直接寻址方式和寄存器间接寻址方式编写程序段,实现将DS:0200H单元和DS:0204H单元中的数据相加,并将运算结果存放在DS:0208H单元中。

附加题:

1. 从DS:0000H开始的5个16位带符号数分别记为x,y,z,v,w,用E命令初始化为:540,1,-1,1080,0, 试求w=(v-(x*y+z-540))/x

2. 完成BX中1的个数的统计。

3. 用串操作指令将DS:0000开始20个字节初始化为:0CCH。并将这20个字节的内容复制到其后的20个字节里。

四. 实验结果(包括必要的截图) 基础题 1:

基础题 2:

附加题 1:

附加题 2:

附加题 3:

五. 实验体会

1. 在汇编语言中,变量的其实都是地址。 2. 在Debug中,数值都是16进制的。

3. 在读写内存中的数据时,必须指出数据类型是byte还是word。

实验二 汇编语言程序设计(顺序、多分支、循环)

一. 实验目的

1、掌握顺序和循环程序结构和设计方法;

2、熟悉在PC机上建立、汇编、连接、调试和运行8086/8088汇编语言程序的过程。

二. 实验内容

1、X、Y、Z、V均为字变量,在X、Y、Z、V字单元中存放是16位带符号数。试编写汇编语言程序完成以下功能: ①计算表达式值(V–(X*Y+Z-720))/X;

②将上述表达式运算结果整数放在SUM1单元,余数放在SUM2单元。 2、使用地址表实现如下功能:根据输入的数字1-7,分别显示相应的英文星期名,如果输入其他字符,则重新输入。

3、求一个班50名学生成绩的平均值、最大值和最小值,并将结果显示出来。

三. 实验过程和程序 第一题:

stack segment stack data code start:

mov ax,data mov ds,ax mov ax, X

segment

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

segment X dw 021CH Y dw 0001H Z dw 0FFFFH V dw 0438H SUM1 dw 0H SUM2 dw 0H

ends dw 512 dup(?) stack ends

data

imul word ptr Y mov cx, dx mov bx, ax mov ax, Z cwd add bx, ax adc cx, dx mov ax, 21CH cwd sub bx, ax sbb cx, dx mov ax, V

cwd sub ax, bx sbb dx, cx idiv word ptr X mov word ptr SUM1, ax mov word ptr SUM2, dx mov ah,4ch

int 21h

code

ends

end start

第二题:

stack segment stack dw 512 dup(?) stack ends

data segment

tip db 'Input number(1~7, 0 for quit):', '$' msg1 db 'Monday', 0DH, 0AH, '$' msg2 db 'Tuesday', 0DH, 0AH, '$' msg3 db 'Wednesday',0DH, 0AH, '$' msg4 db 'Thursday', 0DH, 0AH, '$' msg5 db 'Friday', 0DH, 0AH, '$' msg6 db 'Saturday', 0DH, 0AH, '$' msg7 db 'Sunday', 0DH, 0AH, '$'

table dw show1, show2, show3, show4, show5, show6, show7 data ends

code segment

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

mov ax,data mov ds,ax getnum:

; 打印提示信息 mov dx, offset tip mov ah, 09H int 21H

; 用户输入数字 mov ah, 01H int 21H mov bl, al

; 换行保持美观 mov ah, 02H mov dl, 0DH int 21H mov ah, 02h mov dl, 0AH int 21H

; 非法数值重新输入 cmp bl, '0' jb getnum cmp bl, '7' ja getnum

; 输入'0'直接退出 cmp bl, '0' je quit

and bx, 000FH dec bx

shl bx, 01H jmp table[bx] ; 输出对应单词 print:

mov ah, 09H int 21H jmp getnum quit:

mov ah,4ch int 21h show1:

mov dx, offset msg1

jmp print show2:

mov dx, offset msg2 jmp print show3:

mov dx, offset msg3 jmp print show4:

mov dx, offset msg4 jmp print show5:

mov dx, offset msg5 jmp print show6:

mov dx, offset msg6 jmp print show7:

mov dx, offset msg7 jmp print code ends end start

第三题:

stack segment stack dw 512 dup(?) stack ends

data segment

student db 50 dup(2)

table dw 10000, 1000, 100, 10, 1 NewLine db 0DH, 0AH, '$' MaxStr db 'Max:$' MinStr db 'Min:$'

Average db 'Average:$' data ends

code segment

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

mov ax,data mov ds,ax

call calcAverage call findMax call findMin

mov ah, 4CH int 21H calcAverage:

lea si, student mov cx, 50 mov ax, 0 PlusNext:

add al, [si] adc ah, 0 inc si

loop PlusNext mov bl, 50 div bl mov bl, al xor bh, bh

lea dx, Average mov ah, 09H int 21H call putnum

lea dx, NewLine mov ah, 09H int 21H ret findMax:

lea si, student mov cx, 50 mov al, 0 MaxNext:

cmp al, [si] ja MaxPass mov al, [si] MaxPass: inc si

loop MaxNext mov bl, al xor bh, bh

lea dx, MaxStr mov ah, 09H int 21H call putnum

lea dx, NewLine mov ah, 09H int 21H ret

findMin:

lea si, student mov cx, 50 mov al, 0FFH MinNext:

cmp al, [si] jb MinPass mov al, [si] MinPass: inc si

loop MinNext mov bl, al xor bh, bh

lea dx, MinStr mov ah, 09H int 21H call putnum

lea dx, NewLine mov ah, 09H int 21H ret putnum: mov cx, 5

lea di, table next:

mov ax, bx mov dx, 0H div word ptr[di] test al, 0H mov bx, dx add al, '0' mov dl, al mov ah, 02H int 21H add di, 2 loop next ret code ends end start

四. 实验结果(包括必要的截图) 第一题:

第二题:

第三题:

五. 实验体会

1. 汇编中的分支、循环只能通过跳转实现。 2. 地址表是实现多分支结构的常用方法。

实验三 循环和子程序设计

一. 实验目的

1、掌握循环程序和子程序的设计方法;

2、熟悉在PC机上建立、汇编、连接、调试和运行8086/8088汇编语言程序的过程。

二. 实验内容

1. 在内存Score缓冲区中存放有100个学生的成绩数据,为无符号字节数。设 计程序完成如下功能:根据用户输入的一个2位十进制数,作为查找对象,在该数组中查找,若找到则显示“Y”,若没找到则显示“N” 。

2. 从键盘读入一个字符串,以Enter结束,字符串不超过50个字符,并打印该字符串(附加题:查找中间是否有‘asm’子串。如果有,输出‘Yes’;否则,输出‘No’)。

3. 编写一个子程序计算z=f(x,y)=x*y+x-y(x,y,z有符号数内存数)。要求通过堆栈(寄存器、内存)传送所有参数。(要求输入输出实现,且有提示)

三. 实验过程和程序

第一题:

stack segment stack dw 512 dup(0) stack ends

data segment

Score db 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 db 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 db 40, 41, 42, 43, 44, 45, 46, 47, 48, 49 db 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 db 60, 61, 62, 63, 64, 65, 66, 67, 68, 69 db 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 db 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 db 90, 91, 92, 93, 94, 95, 96, 97, 98, 99

db 100, 101, 102, 103, 104, 105, 106, 107, 108, 109 db 110, 111, 112, 113, 114, 115, 116, 117, 118, 119 NextLine db 0DH, 0AH, '$' Tip db 'Input a number:', '$' No db 'N', 0DH, 0AH, '$' Yes db 'Y', 0DH, 0AH, '$' InputBuf db 4, ?, 8 dup('$')

data ends

code segment

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

mov ax, data mov ds, ax

; 打印提示信息 lea dx, Tip mov ah, 09H int 21H

; 获取用户的输入,放在al sub sp, 2 call GetNum pop ax

; 扫描Score lea bx, Score mov cx, 100 L:

cmp al, [bx] ; 若[bx] == al, 找到 je Found inc bx loop L

; 循环没有中断,没找到,打印'No' lea dx, No jmp OutPut Found:

lea dx, Yes jmp OutPut OutPut:

mov ah, 09H int 21H Exit:

mov ah, 4CH int 21H

; 参数: 无

; 返回值: 8位无符号数 GetNum proc far push ax push bx push cx push dx push bp mov bp, sp

lea dx, InputBuf

mov ah, 0AH int 21H mov dl, 10 xor ax, ax

lea bx, InputBuf[2]

mov cl, InputBuf[1] ;设置CX xor ch, ch Next_GetNum: mul dl

mov dh, [bx] sub dh, '0' add al, dh inc bx

loop Next_GetNum xor ah, ah

mov ss:[bp+14], ax lea dx, NextLine mov ah, 09H int 21H pop bp pop dx pop cx pop bx pop ax ret

GetNum endp code ends end start

第二题:

stack segment stack dw 512 dup(0) stack ends

data segment

StrBuf db 50, ?, 50 dup('$'), '$'

Tip1 db 'Input a string:', 0DH, 0AH, '$' Tip2 db 'You input:', 0DH, 0AH, '$' No db 'No', 0DH, 0AH, '$' Yes db 'Yes', 0DH, 0AH, '$' NextLine db 0DH, 0AH, '$' data ends

code segment

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

mov ax, data mov ds, ax call GetLine

lea bx, StrBuf[2] ;BX为字符串首地址 L_BEGIN: ; 每次循环的开始

cmp byte ptr [bx], '$' ; 如果[bx]是'$',字符串已经结束,跳出循环 je L_END

cmp byte ptr [bx], 'a' ; 若[bx]是'a',比较[bx+1]是不是's' jne NEXT

cmp byte ptr [bx+1], 's' jne NEXT

cmp byte ptr [bx+2], 'm'; 若[bx+2]是'm',找到了'asm',跳出循环 je L_END NEXT:

inc bx

jmp L_BEGIN L_END:

cmp byte ptr [bx], '$' ;若[bx]=='$',则没找到'asm',否则就是找到了 jne Found lea dx, No jmp OutPut Found:

lea dx, Yes jmp OutPut OutPut:

mov ah, 09H int 21H Exit:

mov ah, 4CH int 21H

GetLine proc far push ax push bx push dx

; 打印输入提示 lea dx, Tip1 mov ah, 09H int 21H

; 获取用户输入 lea dx, StrBuf mov ah, 0AH

int 21H

; 在StrBuf结尾添加'$' lea bx, StrBuf[2] mov al, StrBuf[1] xor ah, ah add bx, ax

mov byte ptr [bx], '$' ; 换行打印

lea dx, NextLine mov ah, 09H int 21H ; 输出提示 lea dx, Tip2 mov ah, 09H int 21H

; 打印用户输入的字符串 lea dx, StrBuf[2] mov ah, 09H int 21H ; 换行打印

lea dx, NextLine mov ah, 09H int 21H pop dx pop bx pop ax ret

GetLine endp code ends end start

第三题:

stack segment stack dw 512 dup(0) stack ends

data segment X db 0 Y db 0 Z dw 0

NextLine db 0DH, 0AH, '$' TipX db 'Input X:', '$' TipY db 'Input Y:', '$' TipZ db 'Z = ', '$'

InputBuf db 6, ?, 10 dup('$') OutputBuf db 16 dup('$')

Table dw 10000, 1000, 100, 10, 1 data ends

code segment

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

mov ax, data mov ds, ax ; 用户输入 X lea dx, TipX mov ah, 09H int 21H sub sp, 2 call GetNum pop ax mov X, al

lea dx, NextLine mov ah, 09H int 21H

; 用户输入 Y lea dx, TipY mov ah, 09H int 21H sub sp, 2 call GetNum pop ax mov Y, al

lea dx, NextLine mov ah, 09H int 21H mov al, X mov ah, Y push ax call Func pop ax mov Z, ax

push word ptr Z call PutNum Exit:

mov ah, 4CH int 21H

; 参数 8位有符号数X, Y ; 返回值: 16位有符号数 Func proc far push ax push bx push dx push bp mov bp, sp

mov bx, [bp+12] ;bl==X, bh==Y mov al, bl

imul bh ; ax = X*Y mov dx, ax; dx = X*Y ; dx += X mov al, bl cbw

add dx, ax ; dx -= Y mov al, bh cbw

sub dx, ax

mov [bp+14], dx pop bp pop dx pop bx pop ax ret 2 Func endp

; 参数: 无

; 返回值: 8位有符号数 GetNum proc far push ax push bx push cx push dx push bp mov bp, sp

lea dx, InputBuf mov ah, 0AH int 21H mov dl, 10 xor ax, ax

lea bx, InputBuf[2]

mov cl, InputBuf[1] ;设置CX

xor ch, ch

cmp byte ptr InputBuf[2], '-' jne Next_GetNum dec cx inc bx Next_GetNum: mul dl

mov dh, [bx] sub dh, '0' add al, dh inc bx

loop Next_GetNum

cmp byte ptr InputBuf[2], '-' jne End_GetNum mov bl, al xor al, al sub al, bl End_GetNum: xor ah, ah

mov ss:[bp+14], ax lea dx, NextLine mov ah, 09H int 21H pop bp pop dx pop cx pop bx pop ax ret

GetNum endp

; 参数: 16位有符号数 ; 返回值: 无 PutNum proc far push ax push bx push cx push dx push di push si push bp mov bp, sp

mov bx, [bp+18]

cmp word ptr [bp+18], 0

jge P1_PutNum mov bx, 0

sub bx, [bp+18] P1_PutNum: mov cx, 5

lea si, table lea di, OutputBuf Next_PutNum: mov ax, bx mov dx, 0H div word ptr [si] mov bx, dx add al, '0' mov [di], al add si, 2 inc di

loop Next_PutNum

mov byte ptr [di], '$' lea di, OutputBuf[-1] L_PutNum: inc di

cmp byte ptr [di], '0' je L_PutNum

cmp byte ptr [di], '$' jne OutPut_PutNum dec di

OutPut_PutNum:

cmp word ptr [bp+18], 0 jge P2_PutNum dec di

mov byte ptr [di], '-' P2_PutNum: mov dx, di mov ah, 09H int 21H pop bp pop si pop di pop dx pop cx pop bx pop ax ret 2 PutNum endp

code ends end start

四. 实验结果(包括必要的截图) 第一题:

第二题:

第三题:

五. 实验体会

1.汇编没有易用的IO模块,在处理IO时应采用缓存方法。

2.函数可以通过栈传参数,但在调用函数前后要维持堆栈平衡。

实验四 宏与中断程序设计

一. 实验目的

1、汇编语言宏程序设计;

2、掌握中断服务子程序的编写。

二. 实验内容

1、编写一个宏,求三个数的最小数,原型为:MIN3 x,y,z,min 2、挂接1CH中断,正计时60秒后退出。要求屏幕显示0-59的秒数。 3、VC++中编写内联汇编,将字节数组的每个元素高低四位互换。 char dbyte[] = {0x34,0x45,0x56,0x67,0xaf};

三. 实验过程和程序 第一题:

MIN3 macro x, y, z, min local L1, L2 第二题:

INTNO EQU 1CH

DATA SEGMENT

OLDISR DW ?,? ; 记录原来的中断向量 TIMER DB 100

COUNTER DW 60 ; 60秒 ISDONE DB 0

; 标记,1 表示结束

push ax mov ax, x cmp ax, y jb L1 mov ax, y jb L2 mov ax, z pop ax

L1: cmp ax, z

L2: mov min, ax endm

DATA ENDS

CODE SEGMENT

ASSUME CS:CODE,DS:DATA START:

;WAIT HERE WAITHERE: CMP ISDONE,1 JNZ WAITHERE

EXIT: ;RESTORE

; 恢复中断向量表 CLI MOV AX,DATA MOV DS,AX MOV AX,0 MOV ES,AX ;PROTECT

; 保存 1CH 原有的中断向量 CLI

MOV AX, ES:[INTNO*4] MOV OLDISR[0],AX MOV AX,ES:[INTNO*4+2] MOV OLDISR[2], AX STI

;SET NEW ISR

; 挂接自己的中断过程 CLI

MOV WORD PTR ES:[INTNO*4], OFFSET ISR MOV WORD PTR ES:[INTNO*4+2],SEG ISR STI

MOV AX,OLDISR[0] MOV ES:[INTNO*4],AX MOV AX,OLDISR[2] MOV ES:[INTNO*4+2],AX STI

; 程序结束 MOV AX,4C00H INT 21H

ISR PROC FAR PUSH DX PUSH AX

MOV AX,DATA MOV DS,AX STI ; 便于中断嵌套 ;COUNT HERE INC TIMER

AGAIN:

CMP TIMER, 1000/55 ;18 JB DONE MOV TIMER,0 ;carriage MOV AH,2 MOV DL,13 INT 21H ;print time mov dx, COUNTER mov ax, 60 sub ax, dx

; MOV AX,COUNTER

MOV DL,10 DIV DL MOV DH,AH MOV DL,AL MOV AH,2 ADD DL,30H INT 21H MOV DL,DH ADD DL,30H INT 21H DEC COUNTER JGE DONE MOV ISDONE,1

DONE:

CODE ENDS END START 第三题: #include int main() {

char dbyte[5] = {0x34,0x45,0x56,0x67,0xaf}; int i; CLI POP AX POP DX

IRET ;中断返回 PUSHF

CALL DWORD PTR OLDISR

ISR ENDP

}

for (i = 0; i < 5; i++)

printf(\printf(\__asm { }

for (i = 0; i < 5; i++)

printf(\printf(\return 0;

lea ebx, dbyte; mov eax, ebx; add eax, 5; mov cl, 4

ror byte ptr [ebx], cl inc ebx; cmp ebx, eax jb T;

T:

四. 实验结果(包括必要的截图) 第一题:

第二题:

第三题:

五. 实验体会

1.中断调用会将FLAGS压栈,结束时再出栈。

2.宏会被编译器在源码中展开替换为指令串;函数则是在运行时由call指令调用。