Experiment 7 Applying Addressing Modes to Access Structured Data

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 Register cs;
  • Segment data stores input data and corresponds to Register ds;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

Segment data is divided into three sections:

  • Years: from offset 0H to 53H, with a step size of 4 bytes;
  • Incomes: from offset 54H to A7H, 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 Register es;
1
2
3
table segment
db 21 dup ('year summ ne ?? ')
table ends

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
4
stack segment
dw 8 dup (0)
; For cx
stack ends

Define Segment code and the entry point start:
1
2
3
4
5
code 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
9
mov 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
22
mov 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
19
mov 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
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
; 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;
Assemble
The program behavior is as shown below:
Program Behavior

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 store 31 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 Income 10 00 00-00 (in little endian);
  • Offsets 10H-11H store the number of Employees 03 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.
~~~~~~~~~~~~~~ That’s all for now thank you for your reading. ~~~~~~~~~~~~~~