0%

汇编:实验10三题

1、显示字符串

题目:

汇编源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
; 实验10.1
; 屏幕指定位置显示指定颜色的字符串

assume cs:code
data segment
db 'Welcome to masm!',0
data ends

stack segment
dw 8 dup (0)
stack ends

code segment
start:
mov dh,8 ; 行号 0-24
mov dl,3 ; 列号 0-79
mov cl,2 ; 颜色 绿色
mov ax,data
mov ds,ax
mov si,0 ; ds:si指向字符串开头
mov ax,stack
mov ss,ax
mov sp,10h ; 函数相关栈
push cx
push dx
call show_str

mov ax,4c00h
int 21h

; 参数为 行号dh 列号dl 颜色cl
show_str:
; 寄存器保存
push bp
mov bp,sp
push di
push si
push ax
push es

; 显存起始地址段地址
mov ax,0b800h
mov es,ax

; 显存中字符的开始地址
mov al,160 ; 每行字节数
mul byte ptr [bp+5]
mov dl,[bp+4]
mov dh,0
add ax,dx
add ax,dx
mov di,ax

fill:
mov cl,[si] ; 字符
mov ch,0
jcxz ok
mov ch,[bp+6] ; 颜色
mov es:[di],cx
add di,2
inc si
jmp fill
ok:
; 寄存器恢复
pop es
pop ax
pop si
pop di
pop bp
ret

code ends
end start

编译执行结果:

2、解决除法溢出问题

题目:

汇编源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
; 实验10.2
; 解决除法的商的溢出问题
; 公式:X/N = int(H/N)*65536 + [rem(H/N)*65536+L]/N
; 公式是二项式,第一项得出整个除法的商的高16位,65536不用真的乘
; 第二项得出整个除法的商的低16位,而余数是整个除法的余数
; 题目中除数0a,整个除法余数是0,不好验证,这里使用除数0b
assume cs:code
stack segment
dw 8 dup (0)
stack ends

code segment
start:
mov ax,stack
mov ss,ax
mov sp,10h

mov ax,4240h ; 被除数低16
mov dx,000fh ; 被除数高16
mov cx,0bh ; 除数
push cx
push dx
push ax
call divdw

mov ax,4c00h
int 21h

divdw:
push bp
mov bp,sp
push bx

; int(H/N)
mov dx,0
mov ax,[bp+6]
div word ptr [bp+8]
mov bx,ax ; 商的高16位,dx里是余数,不用动

; [rem(H/N)*65536+L]/N
; rem(H/N)*65536 表示余数放在高16位,刚好是dx
; +L 则为被除数低16位,放到ax里,作为新除法被除数的低16位
mov ax,[bp+4]
div word ptr [bp+8]
mov cx,dx ; cx为余数
mov dx,bx ; dx为商的高16位,ax为商的低16位

pop bx
pop bp
ret

code ends
end start
; 以上,在win2k的dos下用debug执行exe会无效指令,退出dos。可以用dosbox执行。

执行结果:

3、数值显示

题目:

汇编源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
; 将数据以十进制形式显示
assume cs:code

data segment
db 10 dup (0)
data ends

stack segment
dw 8 dup (0)
stack ends

swap segment
dw 10 dup (0)
swap ends

code segment
start:
mov ax,12666
mov bx,data
mov ds,bx
mov si,0
mov bx,stack
mov ss,bx
mov sp,10h
call dtoc

mov bx,swap
push ss
mov ss,bx
push sp
mov sp,20
call turn
pop sp
pop ss

mov dh,8
mov dl,3
mov cl,2
push cx
push dx
call show_str

mov ax,4c00h
int 21h

dtoc:
push cx
push si
push bx
s:
mov dx,0 ; 被除数dx:ax
mov bx,10
div bx
mov cx,ax ; 商ax
add dx,30h ; 余数+30h
mov [si],dl
jcxz oks
mov ax,cx
inc cx
inc si
jmp s
oks:
pop bx
pop si
pop cx
ret

; 参数为 行号dh 列号dl 颜色cl
show_str:
; 寄存器保存
push bp
mov bp,sp
push di
push si
push ax
push es

; 显存起始地址段地址
mov ax,0b800h
mov es,ax

; 显存中字符的开始地址
mov al,160 ; 每行字节数
mul byte ptr [bp+5]
mov dl,[bp+4]
mov dh,0
add ax,dx
add ax,dx
mov di,ax

fill:
mov cl,[si] ; 字符
mov ch,0
jcxz okf
mov ch,[bp+6] ; 颜色
mov es:[di],cx
add di,2
inc si
jmp fill

okf:
; 寄存器恢复
pop es
pop ax
pop si
pop di
pop bp
ret

; 字符串顺序翻转
turn:
push ax
push cx
push si

turn_s:
mov cl,[si]
mov ch,0
jcxz oks2
push cx
inc si
mov cx,2
jmp turn_s

oks2:
mov cx,si
mov si,0
ok_s:
pop ax
mov [si],al
inc si
loop ok_s

pop si
pop cx
pop ax
ret

code ends
end start
; 以上,在win2k的dos下用debug执行exe会无效指令,退出dos。可以用dosbox执行

执行结果: