学汇编,记笔记(实验笔记)《汇编语言》王爽著——实验7_寻址方式在结构化数据访问中的应用

224 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

学习教材:《汇编语言(第4版)》王爽著 此笔记是书中内容+自我总结,方便查阅和复习 请支持原著

实验前别忘了复习笔记

编程,将 data 段中的数据按如下格式写入到 table 段中,并计算 21 年中的人均收入(取整),结果也按照下面的格式保存在 table 段中。

data段:

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'
  # 以上表示21年的21个字符串

  dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
  dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
  # 以上表示21年公司总收入的21个dword型数据

  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型数据
data ends

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

在这里插入图片描述

分析

由于寄存器数量限制,用两次循环。

第一次循环:先内循环四次移动年份,再分两次移动收入的低位和高位 第二次循环:先移动人数,再作除法

  • 定义栈用于嵌套循环
  • 对于移动年份,需要嵌套循环
  • 对于移动收入,由于是双字需要两次移动,以idata==2来移动高低位
  • 对于计算平均值,需要先存入ax和dx,是16位除法
  • mov不能直接对两个内存空间操作,需要借助寄存器
  • table段使用一个寄存器即可表示

答案

assume cs:codesg,ds:datasg,es:tablesg,ss:stacksg
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'

	dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417
	dd 197514,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
	
datasg ends

tablesg segment
	db 21 dup ('year summ ne ?? ') ;16字节
	
tablesg ends

stacksg segment
	dd 4 dup (0) ;定义16字节,8字,4双字的栈段
	
stacksg ends

codesg segment
	start:mov ax,datasg
	mov ds,ax
		
	mov ax,tablesg
	mov es,ax
		
	mov ax,stacksg
	mov ss,ax
	mov sp,10h
	;以上是段寄存器的声明
	
	mov bx,0 ;指向第一个年份
	mov bp,84 ;指向第一个收入,由于前面存储有4B*21==84B的年份数据,这里需要偏移84
	mov di,0 ;指向table段第一个数据
	mov cx,21
		
	s1:push cx ;外循环次数入栈
	mov si,0 ;年份偏移量,由0-3
	mov cx,4 ;四位年份循环4次
	
	year:mov al,byte ptr ds:[bx][si] ;借助寄存器暂存
	mov es:[di],al ;移动
	inc si
	inc di ;累计+4指向收入列
	loop year
	
	add bx,4 ;移动到下一个年份,为下一行准备
	
	income:mov ax,word ptr ds:[bp]
	mov dx,word ptr ds:2[bp]
	mov es:1[di],ax
	mov es:3[di],dx ;分两次移动双字
	
	add bp,4 ;移动到下一个收入
	add di,12 ;指向table段的人数列
	
	pop cx	
	loop s1 ;第一次循环
	
	mov bx,168 ;指向第一个人数,由于前面存储有4B*21*2==84B的年份和收入数据,这里需要偏移168
	mov di,5 ;指向table的收入列的低位数据
	mov cx,21
	
	s2:mov ax,word ptr ds:[bx]
	mov es:5[di],ax ;移动人数列,相对收入列偏移5
	mov ax,word ptr es:[di]
	mov dx,word ptr es:2[di] ;分别移动收入列低位和高位
	div word ptr es:5[di] ;以人数列作为除数作除法,16位除法
	mov es:8[di],ax ;结果存入平均列,相对收入列偏移8
	
	add di,10h ;增加一行,移动到下一行的人数列
	add bx,2 ;移动到下一个人数
	loop s2
			
	mov ax,4c00h
	int 21h
		
codesg ends

end start

在这里插入图片描述 结果正确