Original title
In the following program, these data have been defined:
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'
dd 16,22,382,1356,2390,8000,16000,24486,50056,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
data ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
The program writes the data in the data section into the table section in the following format, and calculates the income per capita in 21 years (rounded up). The result is also stored in the table section in the following format:
Problem solving
C language implementation
First of all, we understand the meaning of the question, and use the familiar C language to describe the operations that need to be performed:
- The first is the data segment, in C language, use an array to store:
char years[21][4] = {
'1', '9', '7', '5', '1', '9', '7', '6',
'1', '9', '7', '7', '1', '9', '7', '8',
'1', '9', '7', '9', '1', '9', '8', '0',
'1', '9', '8', '1', '1', '9', '8', '2',
'1', '9', '8', '3', '1', '9', '8', '4',
'1', '9', '8', '5', '1', '9', '8', '6',
'1', '9', '8', '7', '1', '9', '8', '8',
'1', '9', '8', '9', '1', '9', '9', '0',
'1', '9', '9', '1', '1', '9', '9', '2',
'1', '9', '9', '3', '1', '9', '9', '4',
'1', '9', '9', '5'};
int summs[21] = {
16, 22, 382, 1356, 2390, 8000, 16000, 24486,
50056, 97479, 140417, 197514, 345980, 590827,
803530, 1183000, 1843000, 2759000, 3753000, 4649000, 5937000};
short nes[21] = {
3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001,
1442, 2258, 2793, 4037, 5635, 8226, 11542, 14430, 15257, 17800};
- Then we have to create a table structure:
struct table
{
char year[4];
int summ;
short ne;
short ave;
};
struct table T[21];
- Now what the topic wants us to do is to store the data in the data section in the table section, which is implemented in C language:
// C语言描述
int main()
{
for (int i = 0; i < 21; i++)
{
for (int j = 0; j < 4; j++)
T[i].year[j] = years[i][j];
T[i].ne = nes[i];
T[i].summ = summs[i];
T[i].ave = summs[i] / nes[i];
}
}
- Below we output the decimal form and hexadecimal form of the table table respectively (used for later comparison):
for (int i = 0; i < 21; i++)
{
for (int j = 0; j < 4; j++)
printf("%c", T[i].year[j]);
printf("\t%d", T[i].summ);
printf("\t%d", T[i].ne);
printf("\t%d\n", T[i].ave);
}
for (int i = 0; i < 21; i++)
{
for (int j = 0; j < 4; j++)
printf("%c", T[i].year[j]);
printf(" %08x", T[i].summ);
printf(" %04x", T[i].ne);
printf(" %04x\n", T[i].ave);
}
The results of the operation are:
8086 assembly implementation
With the above analysis, the following assembly code is used to implement the above functions
. The C language description above shows that we need to copy a piece of data in the memory to another area of the memory according to a certain rule, that is, the cpu reads the memory first Then write the data to the memory, and there will be calculations of the data before writing.
- Before the code segment, a stack segment is needed to help process the data. In the C language description, there is a double-layer loop that needs to be used for the stack.
stacksg segment
db 16 dup (0) ;16字节的内存作为栈段
stacksg ends
- Operation of the two memory areas to be used
ds
,es
two segment registers, so thatds
for the data segment a data segment register,es
is a segment table register section, first section of the code belowds
,es
,ss
segments are stored in three data registers:
start: mov ax,stacksg
mov ss,ax
mov ax,datasg
mov ds,ax
mov ax,tablesg
mov es,ax
- The following code is used
bp
to address the table segment individually, and increments by 16 each time (because the size of a table structure instance is 16 bytes); it is useddi
to address the ne data in the data segment , and each cycle is self-incremented. Increase by 2 (each ne data occupies two bytes); usesi
to address the summ data in the data segment, and increment by 4 each time (summ is double-word data, which occupies 4 bytes); but we find The year data is also 4 bytes, so it can besi
regarded as an addressing for each year at the same time , using bx to loop through each byte of each year data; when calculating the division, pay attention to the 32-digit number divided by 16 digits, requiredax
,dx
two registers.
Complete assembly code:
assume cs:codesg,ds:datasg,ds:tablesg,ss:stacksg
stacksg segment
db 16 dup (0) ;16字节的内存作为栈段
stacksg ends
datasg 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'
;以上是表示21年的21个字符串,起始地址datasg:0
dd 16,22,382,1356,2390,8000,16000,24486,50056,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;以上是表示21年公司收入的21个dword型数据,起始地址datasg:84
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word新数据,起始地址datasg:168
;数据段总大小210字节
datasg ends
tablesg segment
db 21 dup ('year summ ne ?? ')
;|0123456789abcdef|
;|year summ ne ?? |
; 0 5 7 a d
tablesg ends
codesg segment
start: mov ax,stacksg
mov ss,ax
mov ax,datasg
mov ds,ax
mov ax,tablesg
mov es,ax
mov bp,0 ;用于table表寻址,每次循环自增16
mov si,0 ;用于数据中summ寻址,每次循环自增4
mov di,0 ;用于数据中ne寻址,每次循环自增2
mov cx,21
s: push cx
mov bx,si ;用于数据中year寻址
push si
mov si,0
mov cx,4
s0: mov al,ds:[bx+si]
mov es:[bp+si],al
inc si
loop s0
pop si
;以上循环实现将年份信息存入table表中
mov ax,ds:[di+168]
mov es:[bp+0ah],ax ;table表存入ne
;C语言描述中的T[i].ne = nes[i]
mov ax,ds:[si+84] ;双字型数据的低16位
mov dx,ds:[si+86] ;双字型数据的高16位
mov es:[bp+5],ax
mov es:[bp+7],dx ;table表存入summ
;C语言描述中的T[i].summ = summs[i]
div word ptr es:[bp+0ah]
mov es:[bp+0dh],ax ;除法计算,table表存入ave
;C语言描述中的T[i].ave = summs[i] / nes[i];
add bp,16
add si,4
add di,2
pop cx
loop s
mov ax,4c00h
int 21h
codesg ends
end start
test
First enter the dosbox and enter the masm command to compile:
no error, enter the command link link:
you can debug after you see the generated exe file,
debug the
u command to find the end of the program, cs:ip
enter g 04d2:0058 to make the program run and
use d Command to view the storage form of the data segment in the memory and
find the continuity of data storage.
The following d command to view the write status of the table table in the es segment register area
can see that the data has been written into the data, and the right side is the ASCII code corresponding Characters, the left side is a hexadecimal number, and the figure below is a data representation area.
Data comparison shows that the calculation result of the assembler is correct