任务一
验证性实验:有些汇编指令会影响到标志寄存器中的一个或多个状态标志位。
在debug环境中,分别实践、观察:
① add指令对标志寄存器中的零标志位ZF(Zero Flag)、进位标志位CF(Carry Flag)是否有影响?
有影响,ff 加上1后得到100h,最高有效位产生进位,al中的值为0,因此ZF结果为1,CF结果为1
② inc指令对标志寄存器中的零标志位ZF(Zero Flag)、进位标志位CF(Carry Flag)是否有影响?
对ZF有影响,对CF没有影响,得到的结果al为0,ZF值为1,而intel硬性规定inc指令不影响CF标志位
录入8086汇编源码task1.asm
1 assume cs:code, ds:data 2 3 data segment 4 x dw 1020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h 5 y dw 3210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 mov si, offset x 13 mov di, offset y 14 call add128 15 16 mov ah, 4ch 17 int 21h 18 19 add128: 20 push ax 21 push cx 22 push si 23 push di 24 sub ax, ax 25 mov cx, 8 26 s: mov ax, [si] 27 adc ax, [di] 28 mov [si], ax 29 30 inc si 31 inc si 32 inc di 33 inc di 34 35 loop s 36 pop di 37 pop si 38 pop cx 39 pop ax 40 ret 41 code ends 42 end start
① line31~line34的4条inc指令,能否替换成如下代码?你的结论的依据/理由是什么?
1 add si, 2 2 add di, 2
可以替换,line31~line34指令的作用是寻找下一字节数据,一共8个字的数据不会涉及到进位对CF造成影响,所以也不会影响adc的计算,两者效果相同,如图所示:
② 在debug中调试,观察数据段中做128位加之前,和,加之后,数据段的值的变化。
加之前的数据段:
加之后的数据段:
任务二
录入8086汇编源码task2.asm
1 assume cs:code, ds:data 2 data segment 3 s db 80 dup(?) 4 data ends 5 6 code segment 7 start: 8 mov ax, data 9 mov ds, ax 10 mov si, 0 11 s1: 12 mov ah, 1 13 int 21h 14 mov [si], al 15 cmp al, '#' 16 je next 17 inc si 18 jmp s1 19 next: 20 mov ah, 2 21 mov dl, 0ah 22 int 21h 23 mov cx, si 24 mov si, 0 25 s2: mov ah, 2 26 mov dl, [si] 27 int 21h 28 inc si 29 loop s2 30 31 mov ah, 4ch 32 int 21h 33 code ends 34 end start
运行程序,从键盘上输入一串字符,以#结束(比如,输入George Orwell, 1984#),观察结果。结合运 行结果,理解代码并回答问题:
① 汇编指令代码line11-18,实现的功能是?
读取键盘输入,加入到数据段当中。如果不是'#',继续读取,是'#'字符跳转到next标号处
② 汇编指令代码line20-22,实现的功能是?
显示输出数据 ah,该ascii码对应字符为换行符
③ 汇编指令代码line24-30,实现的功能是?
显示输出数据段当中的字符数据
任务三
已知逻辑段定义如下:
1 data segment 2 x dw 91, 792, 8536, 65521, 2021 3 len equ $ - x 4 data ends
编写8086汇编源程序task3.asm,在屏幕上以十进制形式输出data段中这一组连续的数据,数据和数据 之间以空格间隔:
1 data segment 2 x dw 91, 792, 8536, 65521, 2021 3 len equ $ - x 4 data ends 5 6 ;使用32位除16位,否则数据太大 7 code segment 8 start: 9 mov ax,data 10 mov ds,ax 11 mov ax,ds:[6] 12 mov dx,offset printNumber 13 mov cx,5 14 mov si,0 15 s0: push cx 16 call printNumber 17 call printSpace 18 pop cx 19 loop s0 20 21 mov ax,4c00h 22 int 21h 23 24 printNumber: 25 s1: mov ax,[si] 26 mov cx,0 ;记录余数个数 27 s2: mov dx,0 ;循环获取余数 28 mov bx,10 29 div bx 30 or dx,30h 31 push dx 32 inc cx 33 mov dx,0 34 cmp ax,0 35 jz s3 ;等于零输出空格,不等于零继续获取 36 jnz s2 37 38 s3: mov ax,200h ;完成取余循环之后,执行系统功能,输出dl 39 pop dx 40 int 21h 41 loop s3 42 43 add si,2 44 ret ;输出空格 45 46 printSpace: 47 mov ax,200h 48 mov dl,' ' 49 int 21h 50 ret 51 52 code ends 53 end start
任务四
针对8086CPU,已知逻辑段定义如下:
1 DATAS SEGMENT 2 str db "assembly language, it's not difficult but tedious" 3 len equ $ - str 4 DATAS ENDS
编写8086汇编源程序task4.asm,将data段中字符串里的小写字符转换成大写:
1 assume cs:code, ds:data 2 3 data segment 4 str_d db "assembly language, it's not difficult but tedious" 5 len equ $ - str_d 6 data ends 7 8 code segment 9 start: 10 mov ax,data 11 mov ds,ax 12 mov cx,len 13 mov si,0 14 s: call strupr 15 inc si 16 loop s 17 mov ah,4ch 18 int 21h 19 20 strupr: 21 mov dl,[si] 22 cmp dl,61h ;小于a跳过 23 jb s1 24 cmp dl,7ah ;大于z跳过 25 ja s1 26 and dl,0dfh 27 mov [si],dl 28 s1: ret 29 30 code ends 31 end start
任务五
使用任意文本编辑器,录入8086汇编源码task5.asm
1 assume cs:code, ds:data 2 3 data segment 4 str1 db "yes", '$' 5 str2 db "no", '$' 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 13 mov ah, 1 14 int 21h ; 从键盘输入字符 15 16 mov ah, 2 17 mov bh, 0 18 mov dh, 24 ; 设置光标位置在第24行 19 mov dl, 70 ; 设置光标位置在第70列 20 int 10h ; 设置光标位置 21 22 cmp al, '7' 23 je s1 24 mov ah, 9 25 mov dx, offset str2 26 int 21h ; 显示标号str2处的字符串 27 28 jmp over 29 30 s1: mov ah, 9 31 mov dx, offset str1 32 int 21h ; 显示标号str2处的字符串 33 over: 34 mov ah, 4ch 35 int 21h 36 code ends 37 end start
这段程序的功能是判断输入字符是不是7,如果是7,输出'yes',是其他字符则输出'no'
任务六
本实验任务中,要求自行实现一个42号软中断 例程,使得通过 int 42 或 int 2ah 软中断调用,实现在屏幕最下方中间以黑底绿字打印"welcome to 2049!"。
task6_1.asm
1 assume cs:code 2 3 code segment 4 start: 5 ; 42 interrupt routine install code 6 mov ax, cs 7 mov ds, ax 8 mov si, offset int42 ; set ds:si 9 10 mov ax, 0 11 mov es, ax 12 mov di, 200h ; set es:di 13 14 mov cx, offset int42_end - offset int42 15 cld 16 rep movsb 17 18 ; set IVT(Interrupt Vector Table) 19 mov ax, 0 20 mov es, ax 21 mov word ptr es:[42*4], 200h 22 mov word ptr es:[42*4+2], 0 23 24 mov ah, 4ch 25 int 21h 26 27 int42: 28 jmp short int42_start 29 str db "welcome to 2049!" 30 len equ $ - str 31 32 ; display string "welcome to 2049!" 33 int42_start: 34 mov ax, cs 35 mov ds, ax 36 mov si, 202h 37 mov ax, 0b800h 38 mov es, ax 39 mov di, 24*160 + 32*2 40 mov cx, len 41 s: mov al, [si] 42 mov es:[di], al 43 mov byte ptr es:[di+1], 2 44 inc si 45 add di, 2 46 loop s 47 48 iret 49 int42_end: 50 nop 51 code ends 52 end start
task6_2.asm
1 assume cs:code 2 3 code segment 4 start: 5 int 42 ; 调用自己实现的42号软中断 6 7 mov ah, 4ch 8 int 21h 9 code ends 10 end start
task6_1代码将中断处理程序存入到内存当中,程序入口地址从中断类型码N*4开始,段地址为N*4+2,偏移地址为N*4,并将42号表项写入到中断向量表中,实现当遇到中断类型码为42时,调用相应的中断处理程序,输出welcome to 2049!到相应位置。
总结
一些根据标志位跳转的指令
JZ ;为0则跳转
JNZ ;不为0跳转
JA ;无符号大于跳转
JB ;无符号小于跳转
JC ;进位跳转