bibi实验七 执行代码如下所示
可见 年份后面一串不知道什么东西的数据 因为有的数据为dword型 没有办法显示
一: 数据-字符串-显示到屏幕上
二:数据-直接显示到屏幕上
必须了解的是 : 直接将数据显示到屏幕上 如果其位数字 须在其基础上加30h变为ASCII码
assume cs:code
;寻址方式在结构化数据访问中的应用
;注意:因为程序要显示的数据有些已经大于65535 应该编写一个新的数据到字符串转化的子程序,完成dword型数据到字符串的转化
;需明白 sumn 和ne 这些数据存在dword型的数据
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个字符串 每个字符串4个字节
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514 ;首地址 ds:100+ (21*4)dec ds:154
dd 345980,590827,803530,1183000,184300,275900,375300,464900,593700
;以上是表示21年公司总收入的21个dword型数据 一个dword型数据占两个字 4个字节
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226 ;首地址 ds: 100+ 2*(21*4)dec ds:1A8
dw 11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word型数据
data ends
table segment
;0123456789abcdef
db 21 dup ('year sumn ne ?? ') ;年份字符串4个字节,dd型4个字节 dw型2个字节 首地址为 ds:100 + 21*(8+2)dec ds:1d2
table ends
stack segment
db 128 dup(0)
stack ends
;关于除法 看其为8位除法 还是16位除法 其中被除数 div 寄存器 还是 div内存
;关于数据移动 是通过栈比较好 还是通过寄存器比较好
code segment
start: mov ax,stack
mov ss,ax
mov sp,128
call input_table
mov ax,4c00h
int 21h
;========================================================================================
input_table: mov bx,data
mov ds,bx
mov si,0
mov bx,table
mov es,bx
mov di,0
mov bx,21*4*2 ;因此时为dword型 两个字 16位 雇员人数
mov cx,21
inputTable: push ds:[si+0] ;此时位一个byte单位
pop es:[di+0]
push ds:[si+2]
pop es:[di+2]
mov ax,ds:[si+21*4+0] ;低16位 收入
mov dx,ds:[si+21*4+2] ;高16位
mov es:[di+5],ax ;低16位
mov es:[di+7],dx ;高16位
push ds:[bx]
pop es:[di+10] ; 人数
div word ptr es:[di+10]
mov es:[di+13],ax
;0123456789abcdef
; db 21 dup ('year sumn ne ?? ')
add di,16 ;换行
add si,4 ;4个字节
add bx,2 ;人数为word型的 占2个字节
loop inputTable
ret
code ends
end start
效果图如下:
具体细节 全在 代码里面了 类比c语言当中的函数调用
assume cs:code
;寻址方式在结构化数据访问中的应用
;注意:因为程序要显示的数据有些已经大于65535 应该编写一个新的数据到字符串转化的子程序,完成dword型数据到字符串的转化
;需明白 sumn 和ne 这些数据存在dword型的数据
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个字符串 每个字符串4个字节
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514 ;首地址 ds:100+ (21*4)dec ds:154
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;以上是表示21年公司总收入的21个dword型数据 一个dword型数据占两个字 4个字节
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226 ;首地址 ds: 100+ 2*(21*4)dec ds:1A8
dw 11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word型数据
data ends
table segment
;0123456789abcdef
db 21 dup ('year sumn ne ?? ') ;年份字符串4个字节,dd型4个字节 dw型2个字节 首地址为 ds:100 + 21*(8+2)dec ds:1d2
table ends
stack segment
db 128 dup(0)
stack ends
;关于除法 看其为8位除法 还是16位除法 其中被除数 div 寄存器 还是 div内存
;关于数据移动 是通过栈比较好 还是通过寄存器比较好
code segment
start: mov ax,stack
mov ss,ax
mov sp,128
call input_table
call clear_screen
call output_table
mov ax,4c00h
int 21h
;=======================================================================================
clear_screen: mov bx,0B800h
mov es,bx
mov bx,0
mov dx,0700h ; 07 就是白色可保存字符 00对应的是 nul
mov cx,2000
clearScreen: mov es:[bx],dx
add bx,2
loop clearScreen
ret
;========================================================================================
input_table: mov bx,data
mov ds,bx
mov si,0
mov bx,table
mov es,bx
mov di,0
mov bx,21*4*2 ;因此时为dword型 两个字 16位 雇员人数
mov cx,21
inputTable: push ds:[si+0] ;此时位一个byte单位
pop es:[di+0]
push ds:[si+2]
pop es:[di+2]
mov ax,ds:[si+21*4+0] ;低16位 收入
mov dx,ds:[si+21*4+2] ;高16位
mov es:[di+5],ax ;低16位
mov es:[di+7],dx ;高16位
push ds:[bx]
pop es:[di+10] ; 人数
div word ptr es:[di+10]
mov es:[di+13],ax
;0123456789abcdef
; db 21 dup ('year sumn ne ?? ')
add di,16 ;换行
add si,4 ;4个字节
add bx,2 ;人数为word型的 占2个字节
loop inputTable
ret
;==============================================================================================
output_table: mov bx,table
mov ds,bx ;重新设置ds
mov si,0
mov bx,0B800h
mov es,bx
mov di,160*3 ;决定列
mov cx,21
outputTable: call show_year
call show_summ ; 因为年份是字符型 的 所以其不需要进行除法 来进行字符转换
call show_ne ;!!!!!!!!!!!!!!!!!!!!!!!!!!
call show_average
add di,160 ;换行
add si,16
loop outputTable
ret
;===============================================================================================
show_average: push ax
push bx
push cx
push dx
push si
push di
push es
push ds
mov ax,ds:[si+13] ;输入参数
mov dx,0
add di,40*2
call isShortDiv
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
;===============================================================================================
show_ne: push ax
push bx
push cx
push dx
push si
push di
push es
push ds
mov ax,ds:[si+10] ;输入参数
mov dx,0
add di,30*2
call isShortDiv
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
;===============================================================================================
show_summ: push ax ;每次调用此函数 皆为对一行数据所处理!!!!!!!!!!!!!!
push bx
push cx
push dx
push si
push di
push es
push ds ;输入参数
mov ax,ds:[si+5] ;低16位
mov dx,ds:[si+7] ;高16位
add di,20*2 ;决定收入的列
call isShortDiv
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
;0123456789abcdef
; db 21 dup ('year sumn ne ?? ')
ret
;====================================================================================================
isShortDiv: mov cx,dx ;若高位是零!!!!!则采用short_div!!!!!!!
jcxz short_div ;长除法最终会变为短除法
mov cx,10
push ax
mov bp,sp
call long_div
add sp,2 ;手动释放压入栈的ax 此时 ret能正确返回!!!!!!
add cl,30h
mov es:[di],cl
mov byte ptr es:[di+1],00000010b
sub di,2 ;对一个数倒着进行输入
jmp isShortDiv ;再次进行短除法
shortDivRet: ret
;=================================================================================================
long_div: mov ax,dx
mov dx,0
div cx
push ax ;此时是 高位除法的 商!
mov ax,ss:[bp+0] ;sp不能用于此等寻地址 将原来的压入栈的低位 数赋予ax再做一次除法
div cx
mov cx,dx ;存放长除法的余数
pop dx
ret
;=================================================================================================
short_div: mov cx,10 ;注意 参数为ax dx di !!!!!!!!!!!!!
div cx
add dl,30h ;dx存放余数 ax存放商
mov es:[di+0],dl
mov byte ptr es:[di+1],00000010B ; 添加一个绿色 注意此时对内存赋值 需要特别声明其为字节型
mov cx,ax ;对ax进行判断 看其是否为零
jcxz shortDivRet ;若其位零 则除法结束
mov dx,0
sub di,2 ;因除法是个十百千万来进行除法的
jmp short_div
;=================================================================================================
show_year: push ax
push cx
push ds
push es
push si
push di
mov cx,4
add di,3*2 ;决定年份列
showYear: mov al,ds:[si] ;单个字节进行传送
mov es:[di],al
add di,2 ;因为 显示屏幕去都是双地址的
inc si
loop showYear
pop di
pop si
pop es
pop ds
pop cx
pop ax
ret
code ends
end start
代码实现结果如下: