Project Context
The following table presents an overview of Power Idea from its founding in 1975 to 1995.
Years | Incomes | Employees | Per Capita Incomes(PCI) |
---|---|---|---|
1975 | 16 | 3 | ? |
1976 | 22 | 7 | ? |
1977 | 382 | 9 | ? |
1978 | 1356 | 13 | ? |
1979 | 2390 | 28 | ? |
1980 | 8000 | 38 | ? |
… | |||
1995 | 5,937,000 | 17,800 | ? |
The data is defined in the following program: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
Program: Write the data in Segment data
to Segment table
in the format shown below. Then calculate the PCIs over the 21 years and store the result in Segment table
as well.
Years (4B) | Space (1B) | Incomes (4B) | Space (1B) | Employees (2B) | Spaces (1B) | PCI (2B) | Space (1B) | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
table | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
0H | 1 | 9 | 7 | 5 | 16 | 3 | ?? | |||||||||
10H | 1 | 9 | 7 | 6 | 22 | 7 | ?? | |||||||||
… | ||||||||||||||||
140H | 1 | 9 | 9 | 5 | 5,937,000 | 17,800 | ?? |
Tip: Think of Segment data
as several arrays, and Segment table
as an array of structures. Use bx
to locate each structure, imm
(Immediate value) as a field offset, and si
to access individual bytes in dword fields. You can use addressing modes like [bx + idata]
and [bx + idata + si]
for access.
Analysis
In the source file source.asm
, three segments are defined: codesg
(hereafter referred to as code
for convenience), data
, and table
.
- Segment
code
stores assembly instructions and corresponds to Registercs
; - Segment
data
stores input data and corresponds to Registerds
;
1 | data segment |
Segment data
is divided into three sections:
- Years: from offset
0H
to53H
, with a step size of 4 bytes; - Incomes: from offset
54H
toA7H
, with a step size of 4 bytes; - Numbers of Employees: from offset
A8H
to the end of the segment, with a step size of 2 bytes;
Data can be accessed by adding the appropriate step size to bx
. Since the sections of Years and Incomes share the same step size and use the same offset addressing, they can be processed within the same loop.
- Segment
table
stores output data and corresponds to Registeres
;
1 | table segment |
In each “row”(10H
) of Segment table
:
year
(4 bytes) is used to store the Year (string);summ
(4 bytes) is used to store the Income (dword);ne
(2 bytes) is used to store the numbers of Employees (word);??
(2 bytes) is used to store the PCI (word);
Register es
is set to point to Segment table
. Advancing to the next “row” can be archieved by incrementing es
by 1.
Program Implementation
Assume segment registers:1
assume cs:code,ds:data,ss:stack
Define Segment stack
:1
2
3
4stack segment
dw 8 dup (0)
; For cx
stack ends
Define Segment code
and the entry point start
:1
2
3
4
5code segment
start:
......
code ends
end start
Initialize segment registers: set ds
to point to data
, es
to point to table
, ss:sp
to point to the bottom of stack
:1
2
3
4
5
6
7
8
9mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov ax,stack
mov ss,ax
mov sp,16
Process the Years and Incomes simultaneously, as both are 4 bytes in length:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22mov bx,0
mov cx,21
s0:
push cx
mov si,0
mov cx,4
; 4 bytes, 4 times, 1 byte each time;
s1:
; Years
mov al,ds:[bx+si] ; ds:[bx+si] -> Years(0-53H)
mov es:[si],al ; es:[si] -> "year" in each row(10H) of Segment table
; Incomes
mov al,ds:[bx+si+54h] ; ds:[bx+si+54h] -> Incomes(54H-A7H)
mov es:[si+5],al ; es:[si+5] -> "summ" in each row of Segment table
inc si
loop s1
add bx,4
pop cx
mov ax,es
inc ax
mov es,ax ;Advancing to the next "row" is archieved by incrementing `es` by 1.
loop s0
Process the numbers of Employees and PCI simultaneously, as both are 2 bytes in length:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19mov ax,table
mov es,ax
mov bx,0
mov cx,21
s2:
; Employees
mov ax,ds:[bx+0a8h] ; ds:[bx+0a8h] -> Employees(0A8H-End)
mov es:[10],ax ; es:[10] -> "ne" in each row of Segment table
; PCI
mov ax,es:[5] ; es:[5] -> lower 2 bytes of the Income
mov dx,es:[7] ; es:[7] -> higher 2 bytes of the Income
div word ptr es:[10] ; es:[10] -> number of Employees
mov es:[13],ax ; es:[13] -> "??" in each row of Segment table
add bx,2
mov ax,es
inc ax
mov es,ax
loop s2
Finally, terminate:1
2mov 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; code.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
table segment
db 21 dup ('year sums em ?? ')
; Create 336 bytes to save the table
table ends
stack segment
dw 8 dup (0)
; Create a stack to temporarily save CX
stack ends
code segment
start:
; Segment Register init
mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov ax,stack
mov ss,ax
mov sp,16
; Years and Incomes(4B)
mov bx,0
mov cx,21
s0:
push cx
mov si,0
mov cx,4
s1:
; Years
mov al,ds:[bx+si]
mov es:[si],al
; Incomes
mov al,ds:[bx+si+54h]
mov es:[si+5],al
inc si
loop s1
add bx,4
pop cx
mov ax,es
inc ax
mov es,ax
loop s0
; Employees and PCI(2B)
mov ax,table
mov es,ax
mov bx,0
mov cx,21
s2:
; Emplyees
mov ax,ds:[bx+0a8h]
mov es:[10],ax
; PCI
mov ax,es:[5]
mov dx,es:[7]
div word ptr es:[10]
mov es:[13],ax
add bx,2
mov ax,es
inc ax
mov es,ax
loop s2
; Termination
mov ax,4c00h
int 21h
code ends
end start
Program Behavior
Assemble, link, generate code.exe
;
The program behavior is as shown below:
1 | 0778:0000 31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20 1975 .... .. .. |
As shown:
- Offsets
0H-3H
store31 39 37 35
, which corresponds to the Year 1975 (in ASCII); - The 4th, 9th, 12th, and 15th bytes are all
20
, representing “ “ (Space); - Offsets
5H-8H
store the Income10 00 00-00
(in little endian); - Offsets
10H-11H
store the number of Employees03 00
(in little endian); - Offsets
13H-14H
store the PCI, which is the result of integer division (truncating toward zero) of Income by Employees:05 00
(in little endian);
It can be seen that it fully meets the requirements of the project.
Experiment completed.