汇编语言笔记14端口

汇编语言笔记14端口

0x00 端口简介

​ 各种存储器和cpu的地址线,数据线,控制线相连接,cpu把各种存储器都当作内存来看待,将总地址看作一个由若干存储单元组成的逻辑储存器,称为地址空间

​ 在pc系统中,和cpu通过总线相连的除各种储存器外,还有以下三种芯片:

​ (1)各种接口卡,如网卡显卡(2)主板上的接口芯片(cpu通过他们对部分外设访问)(3)其他芯片,用来储存相关的系统信息,或进行相关的输入输出处理

​ 上述芯片有两点相同:

​ (1)都和cpu总线相连(2)cpu对他们的读写都通过控制总线向他们所在的芯片发出端口读写命令

​ 从cpu的角度,将这些芯片上的寄存器当作端口,对他们统一编址,从而建立一个统一的端口地址空间,每一个端口在地址空间中都有一个地址

​ cpu可以直接读写以下三个地方的数据 (1)cpu内部寄存器 (2)内存单元(3)端口

0x01 端口读写

​ 在访问端口的时候,cpu通过端口地址来定位端口,因为通过总线相连,端口地址通过地址总线来传送,在pc系统中,cpu可以定位64k个不同端口,范围为0-65535

​ 对端口的读写 有 in out 两条指令 in用来读端口数据 out 用来向端口写入数据

​ cpu执行内存访问指令过程:mov ax,ds:[8]

​ ①cpu通过地址总线发送地址信息8

​ ②cpu通过控制总先发送内存读命令,选中存储器芯片,通知要读数据

​ ③存储器通过数据线将8号单元的数据送入cpu

​ 访问端口:in al,20h(向20h端口读入一个字节到al)

​ ①cpu通过地址总线将地址信息从60h发出

​ ②cpu通过控制线发出端口读命令,选中端口所在的芯片,通知要读数据

​ ③端口所在芯片将60h端口中的数据通过数据线发送到cpu

​ 在in和out指令里,只能由ax或者al来存放从端口中读取或者要发送到端口中的数据,读写一个字节用al读写一个字用ax

对于0-255范围的端口进行读写时: in al,20h out 20h,al

对于256-65535的端口进行读写,端口号要放在dx

mov dx 3f8h
in al,dx
out dx,al

0x02 CMOS RAM芯片

​ PC机中有个CMOS RAM芯片,一般简称CMOS:

​ (1)包含一个实时钟,和一个12存储单元的RAM储存器

​ (2)该芯片靠纽扣电池供电,所以实时钟在关机后仍可工作,RAM信息不丢失

​ (3)128字节RAM中 0-dh 单元用来保存实践 其余部分用来保存系统配置信息,开机时供BIOS程序读取,BIOS也提供程序修改该部分

​ (4)芯片内部有两个端口 70h 和 71h从cpu通过这两个端口来读写CMOS RAM

​ (5)70h 为地址端口,存放要访问的CMOS RAM单元的地址,71h为数据端口,存放要读写CMOS RAM指定单元的数据

​ 由上,cpu要读写CMOS RAM分两步:1 向70h写入地址 2 读写71h

QQ截图20200608102003

assume cs:code
code segment
start:	mov al,2
		out 70h,al
		in bl,70h
		
		mov ax,4c00h
		int 21h
code ends
end start

QQ截图20200608102545

​ 上述代码运行正确

0x03 位运算指令

​ 之前学过按位逻辑运算 and or,其实那两个就是位运算实现的,现在又有新的:shl和shr 分别为左位移,和右位移 和c语言里的«  »一样

​ 指令格式为 shl 数据,移动位数 如 mov ax,3 shl ax,1 ax=6(左移一位相当于*2)

​ 注意 当移动位数 大于1时,要放在cl里,如mov ax,3 mov cl,3 shl ax,cl ax=24

QQ截图20200608102938

assume cs:code
code segment
start:	mov bx,8
		mov ax,bx
		shl ax,1
		mov cl,3
		shl bx,cl
		add bx,ax
		
		mov ax,4c00h
		int 21h
code ends
end start	

QQ截图20200608103757

​ 上述代码运行正确

0x04 实验14读取CMOS RAM中存储的时间

​ 在CMOS RAM,存放这当前的时间,年 月 日 时 分,秒,都为1字节,存放单元如下

QQ截图20200608104219

​ 但是这些时间数据是以 BCD码方式存放,BCD码是用4位二进制数表示1位十进制数的变码方式,如下

QQ截图20200608104411

​ 其实也就是用4bit来保存0-9,一个字节保存那么说明 时间信息都是两位 高4位保存的是十位数字,低4位是个位数字

任务一

QQ截图20200608104433

​ 思路:1要读取月份 所以将70端口写8h(只写一个字节,因为只有128byte 的ram 地址估计是8位的),读71端口得到月份的BCD码 2 BCD 码转字符串+30h 3显示 写b800:0

assume cs:code
code segment
start:		mov al,8;只写一个字节,用al
			out 70h,al
			in al,71h;al存放1个字节 低四位是6 高四位是0 表示06
			and al,00001111b;除掉高四位
			add al,30h;al存放着字符了
			mov dx,0b800h
			mov ds,dx
			mov ds:[1920],al
			mov byte ptr ds:[1921],2;绿色
			mov ax,4c00h
			int 21h
code ends
end start

QQ截图20200608110008

​ 上述代码运行正确

任务二

QQ截图20200608110113

assume cs:code
code segment
addr:		db 9,8,7,4,2,0; s m h d month y
start:		mov ax,0b800h
			mov ds,ax
			mov si,2000
			mov ax,cs
			mov es,ax
			mov di,offset addr
			mov cx,6
			
s:			mov al,es:[di]
			out 70h,al
			in al,71h;al里放的是两个bcd码 高4位是十位低4位是各位
			mov ah,al
			and al,00001111b
			and ah,11110000b

			push cx
			mov cl,4
			shr ah,cl
			pop cx

			add al,30h
			add ah,30h
			mov ds:[si],ah
			mov byte ptr ds:[si+1],2
			mov ds:[si+2],al
			mov byte ptr ds:[si+3],2
			mov byte ptr ds:[si+4],45;-
			mov byte ptr ds:[si+5],2
			inc di
			add si,6
			loop s
			
			mov ax,4c00h
			int 21h
code ends
end start

QQ截图20200608112858

​ 上述代码运行正确