8086 Assembly Experiment: Application of Addressing Mode in Structured Data Access

Original title

Insert picture description here
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:
Insert picture description here
Insert picture description here

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:
Insert picture description here
Insert picture description here

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, estwo segment registers, so that dsfor the data segment a data segment register, esis a segment table register section, first section of the code below ds, es, sssegments 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 bpto address the table segment individually, and increments by 16 each time (because the size of a table structure instance is 16 bytes); it is used dito address the ne data in the data segment , and each cycle is self-incremented. Increase by 2 (each ne data occupies two bytes); use sito 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 be siregarded 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, required ax, dxtwo 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:
Insert picture description here
no error, enter the command link link:
Insert picture description here
you can debug after you see the generated exe file,
Insert picture description here
debug the
Insert picture description here
u command to find the end of the program, cs:ip
Insert picture description here
enter g 04d2:0058 to make the program run and
Insert picture description here
use d Command to view the storage form of the data segment in the memory and
Insert picture description here
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
Insert picture description here
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.
Insert picture description here
Insert picture description here
Data comparison shows that the calculation result of the assembler is correct

Guess you like

Origin blog.csdn.net/qq_45349225/article/details/115330744