Project 1 Display The Data From Power Idea

Project Context

Mission: Display the data From Power Idea in Experiment 7 in the format shown below.
Format

The data of Power idea

Analysis

Since this project requires the data from Exp. 7, I wrote the code based directly on source.asm to save time.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
; source.asm
assume cs:codesg

data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
;The above 21 strings represent 21 years.

dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;The 21 dwords represent the yearly incomes over 21 years.

dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;The above 21 words represent the yearly number of employees over 21 years.
data ends

table segment
db 21 dup ('year summ ne ?? ')
table ends

Rename the Segment table text, to save the string required to be print.

1
2
3
4
text segment
db 160 dup (0)
; A huge segment made up of 160 bytes
text ends

Process the data types in the sequence of Years, Incomes, Employees, Per Capita Income(PCI) and print the results to the screen in four installments to improve efficiency.
When storing in Segment text, define 0 as the end marker for printable text, 0ah(i.e. LF) as Line Feed, in order to control formatting.

Program Implementation

Subprogram printf

The string-printing functionality is implemented via subprogram printf:

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
printf:
; Name:printf;
; Function:Print a string to a specific position of the screen, interpreting 0Ah as newline(\n) and 0 as end marker;
; Parameters:Segment text -> printable string;
; (si) -> position to print at;
push di
push cx
push es
push ds
push si
push si
; Save the register contents; same applies to the subprograms below.

mov di,0
mov cx,text
mov ds,cx
mov cx,0b800h
mov es,cx
s0:
mov ch,0
mov cl,ds:[di]
jcxz printf_cmpd ; 0 as end marker
sub cx,0ah
jcxz lineFeed ; LF as newline
add cx,0ah
mov ch,7h ; white fg with black bg
mov es:[si],cx
add si,2
s1:
add di,1
jmp short s0
lineFeed:
; newline
pop si
add si,0a0h
push si
jmp short s1
printf_cmpd:
pop si
pop si
pop ds
pop es
pop cx
pop di
ret

Subprogram wtoc

Data of type word(Employees, PCI) needs to be converted to string, which can be done using the subprogram wtoc as shown below:

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
wtoc:
; Name:wtoc
; Function:word -> string;
; Parameters:(ax) -> word;
; ds:si -> Beginning address of string;
; Return:(si) -> Ending address of string;
push ax
push bx
push cx
push dx
push di

mov di,0
divide_w:
mov dx,0
mov bx,10
div bx
; Principle:The value is repeatedly dividing by 10 to obtain each digit, and then 30h is added to get its ASCII representation, the dtoc below is the same.
add dx,30h
mov dh,0
push dx
inc di
mov cx,ax
jcxz wtoc_cmpd ; Break if 0.
jmp short divide_w
wtoc_cmpd:
; Arrange the characters obtained from the previous steps in reverse order.
mov cx,di
s7:
pop ax
mov es:[si],al
inc si
loop s7
mov byte ptr es:[si],0ah
; Add LF to its ending.
inc si

pop di
pop dx
pop cx
pop bx
pop ax
ret

Subprogram divdw

Data of type dword (Incomes) requires a subprogram similar to wtoc. However, it may cause overflow to perform div on dword data. So a division subprogram that avoids overflow needs to be implemented.
The principle formula is as follows:

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
divdw:
; Name:divdw
; Function:Division subprogram that avoids overflow.
; c=a/b, a:dword, b:word, c:dword;
; Parameters:(ax) - Lower 16 bits of a;
; (dx) - Higher 16 bits of a;
; (cx)=b;
; Return:(ax) - Lower 16 bits of c;
; (dx) - Higher 16 bits of c;
; (cx)=Remainder;
; Principle:(H//N)*65536+[(H%N)*65536+L]/N
push bx

mov bx,ax
mov ax,dx
mov dx,0
div cx
push ax
push bx
pop ax
pop bx
; Exchange the content of ax and bx using stack;
div cx
mov cx,dx
mov dx,bx

pop bx
ret

Subprogram dtoc

Using subprogram dvidw, convert data of type dword(Incomes) to string, following the same principle as wtoc:

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
dtoc:
; Name:dtoc
; Function:dword -> string;
; Parameters:(ax)=dword(Lower 16 bits);
; (dx)=dword(Higher 16 bits);
; ds:si -> Beginning address of the string;
; Return:(si) -> Ending address of the string;
push ax
push bx
push cx
push dx
push di
push bp

mov di,0
divide:
mov cx,10
call divdw ; Replace div with divdw
mov bp,ax
add cx,30h
mov ch,0
push cx
inc di
or ax,dx
mov cx,ax
mov ax,bp
jcxz dtoc_cmpd
jmp short divide
dtoc_cmpd:
mov cx,di
s4:
pop ax
mov es:[si],al
inc si
loop s4
mov byte ptr es:[si],0ah
inc si

pop bp
pop di
pop dx
pop cx
pop bx
pop ax
ret

Main Program

Next, proceed to the main program.
Assume segment registers:

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

Define Segment stack:
1
2
3
4
stack segment
db 64 dup (0)
; A huge stack segment made up of 64 bytes
stack ends

Define Segment code:
1
2
3
4
5
code segment
start:
...
code ends
end start

Initialize segment registers:
1
2
3
4
5
6
7
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,32
mov ax,text
mov es,ax

To clear the screen, fill the video memory with 0720h(White fg with black bg, Space):
1
2
3
4
5
6
7
8
mov ax,0b800h
mov es,ax
mov cx,2000
mov bx,0
clear:
mov word ptr es:[bx],0720h
add bx,2
loop clear

Print the Years. Since the data of Years is already in string format. Write to Segment text and then print directly using printf, without any additional process:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mov ax,text
mov es,ax
mov di,0
mov cx,21
mov si,0
s2:
push cx
mov cx,4
s3:
mov al,ds:[di]
mov es:[si],al
inc di
inc si
loop s3
mov byte ptr es:[si],0ah ; Each Year a newline
inc si
pop cx
loop s2
mov byte ptr es:[si],0 ; Add 0 to the ending
mov si,0a0h ; Position:(0,1)
call printf

Next, print the Incomes. Convert them to strings through dtoc and then print them using printf:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mov ax,data
mov ds,ax
mov ax,text
mov es,ax

mov di,0
mov cx,21
mov si,0
s5:
mov ax,ds:[di+54h] ; ax -> The lower 16 bits
mov dx,ds:[di+56h] ; dx -> The higher 16 bits
call dtoc
add di,4
loop s5
mov byte ptr es:[si],0
mov si,0a0h
add si,40 ; Position(20,1)
call printf

Employees are converted to strings using wtoc so that they can be printed using printf:
1
2
3
4
5
6
7
8
9
10
11
12
mov di,0
mov cx,21
mov si,0
s6:
mov ax,ds:[di+0a8h]
call wtoc
add di,2
loop s6
mov byte ptr es:[si],0
mov si,0a0h
add si,80 ; Position(40,1)
call printf

The step sizes +54h+56h+0a8h have been discussed in Exp. 7, no more detailed description.

PCI can be calculated using div, and then converted to strings usingwtoc. Finally, print the results using printf:
(Since the PCI in Exp. 7 are of type dword, we can safely use div without concern for overflow.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mov di,0
mov cx,21
mov bx,0
mov si,0
s8:
mov ax,ds:[bx+54h]
mov dx,ds:[bx+56h]
div word ptr ds:[di+0a8h]
call wtoc
add di,2
add bx,4
loop s8
mov byte ptr es:[si],0
mov si,0a0h
add si,120 ; Position(60,1)
call printf

Finally, terminate:
1
2
mov ax,4c00h
int 21h

The full program is as shown below:
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
; p1.asm
assume cs:code,ds:data,ss:stack

data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
;The above is 21 strings representing 21 years

dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;The above is 21 dwords representing the incomes of 21 years

dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;The above is 21 words representing the numbers of employees
data ends

text segment
db 160 dup (0)
text ends

stack segment
db 64 dup (0)
stack ends

code segment
start:
; segReg init
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,32
mov ax,text
mov es,ax

; Clear the screen
mov ax,0b800h
mov es,ax
mov cx,2000
mov bx,0
clear:
mov word ptr es:[bx],0720h
add bx,2
loop clear

; Years
mov ax,text
mov es,ax
mov di,0
mov cx,21
mov si,0
s2:
push cx
mov cx,4
s3:
mov al,ds:[di]
mov es:[si],al
inc di
inc si
loop s3
mov byte ptr es:[si],0ah
inc si
pop cx
loop s2
mov byte ptr es:[si],0
mov si,0a0h ;(0,1)
call printf

; Incomes
mov ax,data
mov ds,ax
mov ax,text
mov es,ax

mov di,0
mov cx,21
mov si,0
s5:
mov ax,ds:[di+54h]
mov dx,ds:[di+56h]
call dtoc
add di,4
loop s5
mov byte ptr es:[si],0
mov si,0a0h
add si,40 ;(20,1)
call printf

; Employees
mov di,0
mov cx,21
mov si,0
s6:
mov ax,ds:[di+0a8h]
call wtoc
add di,2
loop s6
mov byte ptr es:[si],0
mov si,0a0h
add si,80 ; (40,1)
call printf

; PCI
mov di,0
mov cx,21
mov bx,0
mov si,0
s8:
mov ax,ds:[bx+54h]
mov dx,ds:[bx+56h]
div word ptr ds:[di+0a8h]
call wtoc
add di,2
add bx,4
loop s8
mov byte ptr es:[si],0
mov si,0a0h
add si,120 ; (60,1)
call printf

; Terminate
mov ax,4c00h
int 21h

printf:
; Name:printf
; Function:Print the strings at the specified position,0A -> \n,ending in 0
; Parameter:text seg -> content to be printed
; (si) -> position
push di
push cx
push es
push ds
push si
push si

mov di,0
mov cx,text
mov ds,cx
mov cx,0b800h
mov es,cx
s0:
mov ch,0
mov cl,ds:[di]
jcxz printf_cmpd
sub cx,0ah
jcxz lineFeed
add cx,0ah
mov ch,7h
mov es:[si],cx
add si,2
s1:
add di,1
jmp short s0
lineFeed:
pop si
add si,0a0h
push si
jmp short s1
printf_cmpd:
pop si
pop si
pop ds
pop es
pop cx
pop di
ret
divdw:
; Name:divdw
; Function:Dividing without overflow
; c=a/b, a:dword, b:word, c:dword
; Parameter:(ax)=a low 16 bits
; (dx)=a high 16 bits
; (cx)=b
; Return:(ax)=c low 16 bits
; (dx)=c high 16 bits
; (cx)=reminder
; Principle: (H//N)*65536+[(H%N)*65536+L]/N
push bx

mov bx,ax
mov ax,dx
mov dx,0
div cx
push ax
push bx
pop ax
pop bx
div cx
mov cx,dx
mov dx,bx

pop bx
ret
dtoc:
; Name:dtoc
; Function: dword -> char
; Parameter: (ax)=dword(low 16bits)
; (dx)=dword(high 16bits)
; ds:si(in) -> Starting address of string
; si(out) -> Ending address of string
push ax
push bx
push cx
push dx
push di
push bp

mov di,0
divide:
mov cx,10
call divdw
mov bp,ax
add cx,30h
mov ch,0
push cx
inc di
or ax,dx
mov cx,ax
mov ax,bp
jcxz dtoc_cmpd
jmp short divide
dtoc_cmpd:
mov cx,di
s4:
pop ax
mov es:[si],al
inc si
loop s4
mov byte ptr es:[si],0ah
inc si

pop bp
pop di
pop dx
pop cx
pop bx
pop ax
ret
wtoc:
; Name:wtoc
; Function: number(word) -> char
; Parameter: (ax)=Word
; ds:si -> Starting address of string
; si(out) -> Ending address of string
push ax
push bx
push cx
push dx
push di

mov di,0
divide_w:
mov dx,0
mov bx,10
div bx
add dx,30h
mov dh,0
push dx
inc di
mov cx,ax
jcxz wtoc_cmpd
jmp short divide_w
wtoc_cmpd:
mov cx,di
s7:
pop ax
mov es:[si],al
inc si
loop s7
mov byte ptr es:[si],0ah
inc si

pop di
pop dx
pop cx
pop bx
pop ax
ret
code ends
end start

Program Behavior

Assemble, link, generate p1.exe;
Assemble
The program behavior is as shown below:
Program Behavior
It can be seen that it fully meets the requirements of the project.
Project completed.

~~~~~~~~~~~~~~ That’s all for now thank you for your reading. ~~~~~~~~~~~~~~