汇编 第十六章 直接定址表

第十六章 直接定址表

16.1 描述了单元长度的标号

​ 1.本章讨论如何有效合理地组织数据,以及相关的编程技术
​ 1.前面的课程中,我们一直在代码段中使用标号来标记指令、数据、段的起始地址
​ 2.还可以使用一种标号,这种标号不但可以表示内存单元的地址,还表示了内存单元的长度
​ 即:表示在此标号处的单元,是一个字节单元,还是字单元还是双字单元
​ 2.例如
​ 1.标号1
​ a : db 1,2,3,4,5,6,7,8
​ b : dw 0
​ 此种标号只能标记地址
​ 此种加有“:”的地址标号,只能在代码段中使用,不能在其他段中使用
​ 2.标号2
​ a db 1,2,3,4,5,6,7,8 ;标号a,描述了地址code:0,和从这个地址开始,以后的内存单元都是字节单元
​ b dw 0 ;标号b描述了地址code:8,和从这个地址开始,以后的内存单元都是字单元
​ 此种标号既可以标记地址,也可以表示此标号处的单元
​ 3.使用这种包含单元长度的标号,可以使我们以简洁的形式访问内存中的数据
​ 这种标号此后称为数据标号,它标记了存储数据的单元的地址和长度
​ 4.数据标号的用法
​ 指令:mov ax,b ;相当于:mov ax,cs:[8]
​ 指令:mov b,2 ;相当于:mov word ptr cs:[8],2
​ 指令:inc b ;相当于:inc word ptr cs:[8]
​ 指令:mov al,a [si] ;相当于:mov al,cs:0[si]
​ 指令:mov al,a[3] ;相当于:mov al,cs:0[3]
​ 指令:mov al,a[bx+si+3] ;相当于:mov al,cs:0[bx+si+3]

16.2 在其他段中使用数据标号

1.注意,如果想在代码段中,直接用数据标号访问数据,则需要用伪指令assume 将标号所在的段和一个段寄存器联系起来。assume cs:code ,ds : data.否则编译器在编译的时候,无法确定标号的段地址在哪一个寄存器中。

2.当然,这种联系是编译器需要的,但绝对不是说,我们因为编译器的工作需要,用assume指令将段寄存器和某个段相联系,段寄存器中就会真的存放该段的地址。

3.我们可以将数据标号当作数据来定义,此时,编译器将标号所表示的地址当作数据的值。

1.把数据标号当做数据来定义时,使用【dw】定义数据比如:
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dw a,b        ;数据标号c处存储的两个字型数据为标号a、b 的偏移地址。
data ends ;数据标号c处存储的两个字型数据为标号a、b 的偏移地址。
;相当于:
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dw offset a, offset b
data ends
2.把数据标号当做数据来定义时,使用【dd】定义数据
再比如:
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dd a,b  ;数据标号c处存储的两个双字型数据为标号a的偏移地址和段地址、标号b 的偏移地址和段地址。
data ends
;相当于:
data segment
a db 1,2,3,4,5,6,7,8
b dw 0
c dw offset a, seg a, offset b, seg b;seg操作符,功能为取得某一标号的段地址。
data ends

16.3 直接定址表

​ 本节课,我们将使用“查表”的方法,编写相关程序的技巧
​ 【任务】编写子程序,以十六进制的形式在屏幕中间显示给定的byte型数据

assume cs:code
code segment
start:
	mov al,0eh          ;al中存放了byte型数据
	call showbyte
    mov ax,4c00h
    int 21h
    ;子程序:
	;用al传送要显示的数据
showbyte:
    jmp short show
    table db '0123456789ABCDEF'	;字符表
show:  
	push bx                 ;保护现场
    push es    
    mov ah,al
    shr ah,1           
    shr ah,1
    shr ah,1
    shr ah,1			    ;右移4位,ah中得到高4位的值
    and al,00001111b		;al中为低4位的值
    mov bl,ah
    mov bh,0
    mov ah,table[bx];用高4位的值作为相对于table的偏移,取得对应的字符
    mov bx,0b800h
    mov es,bx
    mov es:[160*12+40*2],ah
    mov bl,al
    mov bh,0
    mov al,table[bx];用低4位的值作为相对于table的偏移,取得对应的字符   
    mov es:[160*12+40*2+2],al
    pop es
    pop bx
    ret
code ends
end start

16.4 程序入口地址的直接定址表

​ 【编程】实现一个子程序setscreen,为显示输出提供如下功能:
​ 1.清屏
​ 2.设置前景色
​ 3.设置背景色
​ 4.向上滚动一行
​ 1.入口参数说明:
​ 1.用ah寄存器传递功能号
​ 0:清屏;1:设置前景色;2:设置背景色;3:向上滚动一行
​ 2.对于2、3号功能,用al传递颜色值
​ al∈{0,1,2,3,4,5,6,7}
​ 2.各种功能如何实现
​ 1.清屏:
​ 将显存中当前屏幕中的字符设为空格符;
​ 2.设置前景色:
​ 设置显存中当前屏幕中处于奇地址的属性字节的第0、1、2位;
​ 012位存放前景色
​ 3.设置背景色:
​ 设置显存中当前屏幕中处于奇地址的属性字节的第4、5、6位;
​ 456位存放背景色
​ 4.向上滚动一行:
​ 依次将第 n+1行的内容复制到第n行处:最后一行为空。

;功能子程序1:清屏
sub1:   
	push bx      ;保护现场,调用子程序的时候,注意要保护现场,运行子程序的时候,可能会修改一些寄存器的值
    push cx
    push es
    mov bx,0b800h
    mov es,bx
    mov bx,0
    mov cx,2000
sub1s:  
	mov byte ptr es:[bx],' '  ;循坏2000次
    add bx,2
    loop sub1s
    pop es          ;恢复现场
    pop cx
    pop bx
    ret 	
;功能子程序2:设置前景
sub2:	
	push bx
	push cx
	push es
	mov bx,0b800h
	mov es,bx
	mov bx,1
	mov cx,2000
sub2s:	
	and byte ptr es:[bx],11111000b	
	or es:[bx],al 
	add bx,2
	loop sub2s
	pop es
    pop cx
    pop bx
    ret		
;功能子程序3:设置背景色
sub3:	
	push bx
	push cx
	push es
	mov cl,4
	shl al,cl
	mov bx,0b800h
	mov es,bx
	mov bx,1
	mov cx,2000
sub3s:	
	and byte ptr es:[bx],10001111b
	or es:[bx],al 
	add bx,2
	loop sub2s
	pop es
    pop cx
    pop bx
    ret 
;功能子程序4:向上滚动一行
sub4:	
	push cx
	push si
	push di
	push es
	push ds
	mov si,0b800h
    mov es,si
    mov ds,si
    mov si,160			;ds:si指向第n+1行,第1行
    mov di,0			;es:di指向第n行,第0行
    cld
    mov cx,24;共复制24行
sub4s:	
	push cx
	mov cx,160
	rep movsb 			;复制
  	pop cx
	loop sub4s
	mov cx,80	
	mov si,0
sub4s1: 
	mov byte ptr es:[160*24+si],' '		;最后一行清空
	add si,2
	loop sub4s1
	pop ds
    pop es
    pop di
    pop si
    pop cx
    ret ;sub4 ends

3.可以将这些功能子程序的入口地址存储在一个表中,他们在表中的位置和功能号相对应

;编程:实现一个子程序setscreen,为显示输出提供如下功能:
;(1) 清屏。
;(2) 设置前景色。
;(3) 设置背景色。
;(4) 向上滚动一行。

;入口参数说明:
;(1) 用 ah 寄存器传递功能号:0 表示清屏,1表示设置前景色,2 表示设置背景色,3 表示向上滚动一行;
;(2) 对于2、3号功能,用 al 传送颜色值,(al) ∈{0,1,2,3,4,5,6,7}
setscreen: jmp short set
table  dw sub1,sub2,sub3,sub4
set: 
	push bx	
	cmp ah,3		;判断传递的是否大于 3
	ja sret
	mov bl,ah
	mov bh,0
	add bx,bx  ;根据ah中的功能号计算对应子程序的地址在table表中的偏移
	call word ptr table[bx]	;调用对应的功能子程序,学会本句代码,是本章节的【精髓】
sret:	
	pop bx	
	iret
;功能子程序1:清屏
sub1:   
	push bx
	push cx
    push es
	mov bx,0b800h
	mov es,bx
	mov bx,0
	mov cx,2000
sub1s:  
	mov byte ptr es:[bx],' '
    add bx,2
    loop sub1s
    pop es
    pop cx
    pop bx
	ret ;sub1 ends
;功能子程序2:设置前景色
sub2:	
	push bx
	push cx
	push es
	mov bx,0b800h
	mov es,bx
	mov bx,1
	mov cx,2000	
sub2s:	
	and byte ptr es:[bx],11111000b	
	or es:[bx],al 
	add bx,2
	loop sub2s
	pop es
    pop cx
    pop bx
    ret ;sub2 ends
;功能子程序3:设置背景色
sub3:	
	push bx
	push cx
	push es
	mov cl,4
	shl al,cl
	mov bx,0b800h
	mov es,bx
	mov bx,1
	mov cx,2000
sub3s:	
	and byte ptr es:[bx],10001111b
	or es:[bx],al 
	add bx,2
	loop sub2s
	pop es
    pop cx
    pop bx
    ret ; sub3 ends
;功能子程序4:向上滚动一行
sub4:	
	push cx
	push si
	push di
	push es
	push ds
	mov si,0b800h
    mov es,si
    mov ds,si
    mov si,160			;ds:si指向第n+1行
    mov di,0			;es:di指向第n行
    cld
    mov cx,24;共复制24行
sub4s:	
	push cx
	mov cx,160
	rep movsb 			;复制
  	pop cx
	loop sub4s
	mov cx,80	
	mov si,0
sub4s1: 
	mov byte ptr es:[160*24+si],' '		;最后一行清空
	add si,2
	loop sub4s1
	pop ds
    pop es
    pop di
    pop si
    pop cx
    ret ;sub4 ends
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值