您的位置:首页 > 其它

王爽《汇编语言》第十三章所有练习解答

2009-04-12 14:59 176 查看
请注意,里面有程序和测试程序,例如 exp1303.asm指的是13章第三个题目,exp1303t.asm指的是对exp1303程序的测试。。。

; exp1301.asm

; 安装中断7ch的中断例程
; 功能:求一个word型数的平方
;
;
assume cs:code

code segment
start:
; 拷贝代码到非系统管理区
mov ax, cs
mov ds, ax
mov si, offset sqr ; 从cs段的sqr开始复制到0:200处

mov ax, 0
mov es, ax
mov di, 200h

mov cx, offset sqrend - offset sqr ; cx为需要复制的代码字节数
cld
rep movsb ; 调用 movsb 把 es:[di] 的字节拷贝到 ds:[si]

; 设置好中断向量
mov ax, 0
mov es, ax
mov word ptr es:[7ch*4], 200h ; 用 word ptr 指明是要拷贝一个字
mov word ptr es:[7ch*4+2], 0

mov ax, 3
int 7ch

mov ax, 4c00h
int 21h

sqr:
mul ax
iret
sqrend:
nop

code ends

end start

; exp1302.asm

; 安装7ch中断的中断例程
; 功能:实现将 ds:[si] 开始的字符串显示出来

assume cs:code

data segment
db "welcome to masm!", 0
data ends

code segment
start:
; 拷贝代码到非系统管理区
mov ax, cs
mov ds, ax
mov si, offset int7c ; 从cs段的int7c开始复制到0:200处

mov ax, 0
mov es, ax
mov di, 200h

mov cx, offset int7cend - offset int7c
cld
rep movsb

; 设置好中断向量
mov ax, 0
mov es, ax
mov word ptr es:[7ch*4], 200h
mov word ptr es:[7ch*4+2], 0

; dh = 行数,dl = 烈数,cl = 颜色,ds:si指向首地址
mov dh, 10
mov dl, 10
mov cl, 2

mov ax, data
mov ds, ax

mov si, 0
int 7ch

mov ah, 01h
int 21h

mov ax, 4c00h
int 21h

int7c:
push ax
push bx
push cx
push dx
push es

; 计算好字串开始显示的地址Y = 160*(行数-1) + 列数*2-2, B800 : Y
; 循环将参数里的字串写进显卡内存,并检测到0就返回

; bx = 160*(行数-1)
sub dh, 1h
mov al, 160
mul dh
mov bx, ax ; bx 为根据行数算出来的偏移值

; ax = 列数*2-2
mov al, 2
mul dl
sub ax, 2 ; 根据列数算出来的偏移值
add bx, ax ; 行数和列数的和存在bx中了

mov ax, 0b800h
mov es, ax

mov dl, cl ; 保存字体颜色属性
mov ch, 0

s_show_str:
mov cl, ds:[si]
mov es:[bx], cl
jcxz ok_show_str

mov es:[bx+1], dl

inc si
add bx, 2
jmp short s_show_str

ok_show_str:
pop es
pop dx
pop cx
pop bx
pop ax
iret
int7cend:
nop

code ends

end start

; exp1302t.asm

; 上一个程序的测试程序

; 测试 7ch 中断,显示字符串

assume cs:code

data segment
db "Welcome to masm 6.11!", 0
data ends

code segment
start:
mov ax, data
mov ds, ax

mov dh, 10
mov dl, 10
mov cl, 2
mov si, 0

int 7ch

mov ax, 4c00h
int 21h
code ends

end start

; exp1303.asm

; 安装7ch中断的中断例程
; 功能:实现将ds:si开始,0结束的字符串转化为全部转化为大写

assume cs:code

data segment
db "welcome to masm!", 0
data ends

code segment
start:
; 拷贝代码到非系统管理区
mov ax, cs
mov ds, ax
mov si, offset int7c ; 把中断代码从cs段的int7c开始复制到0:200处

mov ax, 0
mov es, ax
mov di, 200h

mov cx, offset int7cend - offset int7c
cld
rep movsb

; 设置好中断向量 0:200 处
mov ax, 0
mov es, ax
mov word ptr es:[7ch*4], 200h
mov word ptr es:[7ch*4+2], 0

mov ax, data
mov ds, ax
mov si, 0
int 7ch

mov ah, 01h
int 21h

mov ax, 4c00h
int 21h

int7c:

; 将ds:[si]开始的字符比较,如果是小写字母,则将其变为大写
; 因为是0结尾,这里可以用jcxz
; 小写字母的范围是 61h~7Ah,大写字母比它少20h
; 可以用 jb 61h 和 ja 7ah来做判断,并循环
push cx
push si

mov ch, 0
loop1:
mov cl, ds:[si]
jcxz loop1end

cmp cl, 61h
jb notcase
cmp cl, 7ah
ja notcase

sub cl, 20h
mov ds:[si], cl
inc si
jmp short loop1

notcase:
inc si
jmp short loop1

loop1end:
pop si
pop cx
iret

int7cend:
nop

code ends

end start

; exp1303t.asm

; 测试exp1303,用中断7ch来将ds:[si]的小写字母全部转化为大写
; 在下面用show_str显示出来

; 注意,此题用 and bytr ptr [si], 11011111b 将字符化为大写能更简化

assume cs:code

data segment
db "welcome to masm!", 0
data ends

stack segment

stack ends

code segment
start:

mov ax, data
mov ds, ax
mov si, 0

int 7ch

mov ax, data
mov ds, ax
mov si, 0
mov dh, 2
mov dl, 3
mov cl, 2
call show_str

mov ah, 01h
int 21h

mov ax, 4c00h
int 21h

; 名称:show_str
; 功能:指定位置,用指定颜色,显示一个用0结束的字符串
; 参数:(dh) = 行号(0--24),(dl) = 列号(0--79)
; (cl) = 颜色,ds:si 指向字符串的首地址
; 返回:无
show_str:
push ax
push bx
push cx
push dx
push es

; 计算好字串开始显示的地址Y = 160*(行数-1) + 列数*2-2, B800 : Y
; 循环将参数里的字串写进显卡内存,并检测到0就返回

; bx = 160*(行数-1)
sub dh, 1h
mov al, 160
mul dh
mov bx, ax ; bx 为根据行数算出来的偏移值

; ax = 列数*2-2
mov al, 2
mul dl
sub ax, 2 ; 根据列数算出来的偏移值
add bx, ax ; 行数和列数的和存在bx中了

mov ax, 0b800h
mov es, ax

mov dl, cl ; 保存字体颜色属性
mov ch, 0

s_show_str:
mov cl, ds:[si]
mov es:[bx], cl
jcxz ok_show_str

mov es:[bx+1], dl

inc si
add bx, 2
jmp short s_show_str

ok_show_str:
pop es
pop dx
pop cx
pop bx
pop ax

ret

code ends

end start

; exp1304.asm

; 使用BIOS中断和DOS中断

assume cs:code, ds:data

data segment
db 'welcome to asm!', '$'
data ends

stack segment

stack ends

code segment
start:
; 调用BIOS中断例程
mov ah, 2
mov bh, 0
mov dh, 5
mov dl, 12
int 10h

mov ah, 9
mov al, 'a'
mov bl, 11001010b
mov bh, 0
mov cx, 3
int 10h

; 调用DOS 中断例程
mov ax, 4c00h
int 21h

code ends

end start

; exp1305.asm

assume cs:code, ds:data

data segment
db 'welcome to asm!', '$'
data ends

stack segment

stack ends

code segment
start:
mov ah, 2 ; BIOS置光标的例程
mov bh, 0 ; 第0页
mov dh, 5 ; dh 行号
mov dl, 12 ; dl 列号
int 10h

mov ax, data ;
mov ds, ax
mov dx, 0 ; ds:dx指向字符串的首地址 data:0
mov ah, 9 ; 21号中断例程的9号子程序
int 21h

mov ax, 4c00h
int 21h

code ends

end start

; exp1306.asm

; 用 int 7ch 代替loop功能,bx为偏移地址,cx为循环次数
; 安装 7ch 中断
; 关键是要在int7ch 之后,把cs:ip 的地址转为当前程序需要跳转到的cs:ip地址

; 主要注意调用中断的时候,几个重要的寄存器会压栈,顺序是:标志寄存器,cs, ip
; 这里的原理是调用中断7ch时,就把栈里的ip数值改变为循环开始地址,然后再中断返回
; 理解了以上两点,这题就没问题了,否则会访问出错,碰到操作系统的禁区

assume cs:code

code segment
start:
; 拷贝代码到0:200内存区
mov ax, cs
mov ds, ax
mov si, offset int7c

mov ax, 0
mov es, ax
mov di, 200h

mov cx, offset int7cend - offset int7c
cld
rep movsb

; 安装中断变量
mov ax, 0
mov es, ax
mov word ptr es:[7ch*4], 200h
mov word ptr es:[7ch*4 + 2], 0

mov ax, 4c00h
int 21h

int7c:
push bp

mov bp, sp
dec cx
jcxz offset int7cok

sub [bp+2], bx ; IP

int7cok:
pop bp
iret
int7cend:
nop

code ends

end start

; exp1306t

; 用 int 7ch 代替loop功能,bx为偏移地址,cx为循环次数
; 在屏幕中间显示80个 '!'

assume cs:code

code segment
start:
mov ax, 0b800h
mov es, ax
mov di, 160*12 ; 12行,刚好是80*24屏幕的中间行

mov bx, offset se - offset s
mov cx, 80
s:
mov byte ptr es:[di], '!'
mov byte ptr es:[di+1], 2
add di, 2
int 7ch
se:
nop

mov ax, 4c00h
int 21h

code ends

end start

; exp1307.asm

; 直接定址表和调用BIOS、DOS中断显示字符串

assume cs:code

code segment
s1 db 'Good, better, best!', '$'
s2 db 'Never let it rest!', '$'
s3 db 'Till good is better', '$'
s4 db 'And better, best.', '$'
s dw offset s1, offset s2, offset s3, offset s4
row db 12,14,16,18

start:
mov ax, cs
mov ds, ax
mov bx, offset s
mov si, offset row
mov cx, 4
ok:
; BIOS置光标
mov bh, 0
mov dh, [si]
mov dl, 0
mov ah, 2
int 10h

; DOS显示字符串例程
mov dx, [bx]
mov ah, 9
int 21h

inc si ; row 是db,一个字节
add bx, 2 ; 因为dw占两个字节,所以要加2

loop ok

mov ax, 4c00h
int 21h
code ends

end start

本章深入学习到中断的一些知识,通过调试观察,能更清楚的了解到调用 int 指令和 iret 指令时 栈和各个寄存器的变化。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: