10.20-smbus

10.20

任务目标 // 进度:

  • SMBus/I2C:编写dos下小工具,读取256字节SPD信息
  • 汇编语言

工作结果:

学习笔记:

SMBus(System Management Bus)

SMBus:双线通信专利技术,与I2C串行总线兼容,是I2C的子集。SMBUS可获取内存的SPD参数。0xA0, 0xA2, 0xA4, 0xA6 读取SPD。

工作频率:10-100khz

应答信息:ACK / NACK

读操作:接收器->发送器; 写操作:发送器->接收器

总线协议:数据线SDA(双向),时钟线SCL(双向)

SMBus接口:主方式;从方式

基地址:从设备,SPD前四位1010,后三位硬件电路决定。ARP功能的主控制器0001000,默认设备地址1100001.

SPD:串行存在检测,包括内存芯片,模组厂商,工作频率,工作电压,速度,容量

读取方式:字节读取 / 块读取
​ 字节读取寄存器:HST_STS,HST_CNT,HST_CMD,XMIT_SLVA,HST_D0
​ 块读取寄存器:HST_STS,HST_CNT,HST_CMD,XMIT_SLVA,HST_D0,HOST_BLOCK_DB和AUX_CTL。

读取数据的过程:采用RU软件测试;采用汇编代码。

1.RU软件测试验证过程

1.1.Byte Data读取方式测试
第一步,将HST_STS(00H)设置为1EH(清掉各个标志位),可以看到HST_STS数值变成了40H。
第二步,将XMIT_SLVA(04H)设置为A1H,说明是要读取SPD。
第三步,将HST_CMD(03H)设置为00H,说明读取SPD中的00H处的数据,若要读取01H处的数据,就设置为01H。
第四步,将HST_CNT(02H)设置为48H(采用字节读取方式,并START),这是可以看到HST_CNT变成了08H,HST_STS变成了42H(说明INTR并且!HOST_BUSY,对比前面的英文描述),HST_D0变成了7F(这个是本测试电脑的SPD的第一个数据),也说明读取数据的目的已经达到。

1.2.Block 读取方式测试
该种读取方式比之于Byte Data方式要复杂一些,首先要特别关注AUX_CTL(0DH)中的E32B位。该为置1与否,也决定了读取过程。以下分别进行测试。
1.2.1 AUX_CTL设置为02H
第一步,将HST_STS(00H)设置为1EH(清掉各个标志位),可以看到HST_STS数值变成了40H。
第二步,将XMIT_SLVA(04H)设置为A1H,说明是要读取SPD。
第三步,将HST_CMD(03H)设置为00H,其实也是设置偏移地址的,如果设置成10H,那么就从10H位置读取数据。
第四步, 将HST_CNT(02H)设置为54H(采用Block读取方式,并START),这是可以看到HST_CNT变成14H,HST_STS变成了41H(说明!INTR并且HOST_BUSY),HST_D0变为7FH(说明该寄存器保存第一个数据,并且这第一个数据也是后面的COUNT。),HOST_BLOCK_DB在不停的闪动(说明该寄存器每被读取一次就变化一次,也就是E32B被置1的效果)。
1.2.2 AUX_CTL设置为00H
前面三步同上。
第四步,将HST_CNT(02H)设置为54H,HST_CNT变成14H,HST_STS变成C1H(注意这里是C1H,即DS被置1),HST_D0变成1F,HOST_BLOCK_DB变成了08H(注意它并没有闪),本机的SPD数据序列为:7F,08,08,0E,…。这明显的说明HST_D0保存的是第一个数据,它也是count。
第五步,将HST_STS设置为C1H(注意HST_STS的数据本来就是C1H,用这种方式清掉DS位,清掉之后发现HST_STS还是C1,没有变化,其实这一过程是有变化的,HST_STS先变成41,然后再变成C1,速度太快,看不到变化,在后面程序中用这一过程作为判断),发现HST_D0变为08H(这里还不能说是变化,值一样)。
第六步,继续第五步,发现HST_D0变为0EH。接着重复,可以把这个Block缓存数据读取完。以什么作为结束标志呢?INTR和!HOST_BUS。另外也可以将KILL位(在HST_CNT中)置1,中断传输。这种方式下可以读取超过32个字节的数据,有多少就能读多少。

2.汇编代码验证过程

2.1 Byte读取方式的代码过程
第一步:通过HST_STS判断SMBus是否空闲可用(HST_STS&1EH == 0?不为0则1EH=>HST_STS。HST_STS&01H == 0?不为0则循环)
第二步:设置XMIT_SLVA (SMBA+04h), 选择设备地址,以及读写设为01h
第三步:设置HST_CMD(SMBASE+03h),选择设备对应的Register Index
第四步:设置HST_CNT(SMBASE+02h),写48h表Byte Data形式读取
第五步:循环判断HST_STS(HST_STS&1CH不为0则报错,HOST_BUSY应为0且INTR应为1否则循环)
第六步:从HST_D0(SMBASE+05h)中读取数据低字节;从HST_D1(SMBASE+06h)中读取数据高字节。(第四步前写入低字节在HST_D0(SMBASE+05h),写入高字节在HST_D1(SMBASE+06h))

2.2Block读取方式
第一步:通过HST_STS判断SMBus是否空闲可用(参考:HST_STS&9EH == 0?不为0则HST_STS=>HST_STS。HST_STS&01H == 0?)
第二步:设置XMIT_SLVA(SMBASE+04h), 选择设备地址,以及读写设为01h
第三步:设置HST_CMD(SMBASE+03h)为00H,index清0
第四步:设置AUX_CTL(SMBASE+0DH)为00H,将E32B置0
第五步:设置HST_CNT(SMBASE+02h),写54H表Block Data形式读取
第六步:判断HST_STS,循环直到DS(bit7)被置1
第七步:HST_D0(SMBASE+05h)读取第一个数据,也将该数据作为后面总字节数
第八步:HOST_BLOCK_DB(SMBASE+07h)中读取一个字节
第九步:HST_STS的DS位置1清0
第十步:循环判断HST_STS,直到DS(bit7)被置1,再重复第七步,直到读完所以字节数
第十一步:设置HST_CNT为16H,KILL命令过程
第十二步:用HST_STS的数据清掉HST_STS

I2C:

​ 工作频率:0-400khz

​ 应答信息:无


SMBUS的访问过程

IO访问:F040 MMIO访问:F722A000

Base:F040

0:写入FE清零,地址为base address+0x00

read byte:

1:写入slave+1,写入地址为base address+0x04 ,bit 0 置一表示读操作

2:选择需要的寄存器,设置其偏移量(1~256),地址为base address+0x03

3:写入操作方式0x48,写入地址为base address+0x02

4:读出数据,读数据的地址为base address +0x05

HST_STS(00H)XMIT_SLVA(04H)HST_CMD(03H)HST_CNT(02H)HST_D0(05H)HST_D1(06H)
状态位寄存器从地址数据方式低字节高字节
FE(清零)A1(A0)048(字节读取)返回值
41(忙)A3(A2)14C(块读取)返回值返回值
42(可用)A5(A4)2
A7(A6)
注:末位置1表示读操作255

read Word:

1:写入slave+1,写入地址为base address+0x04,bit 0 置一表示读操作

2:选择需要的寄存器,设置其偏移量,地址为base address+0x03

3:写入操作方式0x4C,写入地址为base address+0x02

4:读出数据,读数据的地址为base address +0x05,base address +0x06

write byte:

1:写入slave,写入地址为base address+0x04,bit 0 置零表示写操作

2:选择需要的寄存器,设置其偏移量,地址为base address+0x03

3:写入需要的数据:一个byte,写数据的地址为base address +0x05

4:设置byte的工作方式0x48,写入地址为base address +0x02

write Word:

1:写入slave,写入地址为base address+0x04,bit 0 置零表示写操作

2:选择需要的寄存器,设置其偏移量,地址为base address+0x03

3:写入需要的数据:一个word,写数据的地址为base address +0x05,base address +0x06

4:设置word的工作方式0x4C,写入地址为base address +0x02


汇编语言:

1.物理地址/绝对地址

2.逻辑地址:段地址+偏移地址。段地址左移一位加偏移地址就是物理地址。

3.中断地址:中断的首地址保存到一个地址,这段地址是内存的绝对零地址(0000:0000)。
​ 中断地址的4个字节,数据是由低向高的。比如12 34 56 78所表示的地址是:7856:3412。

4.共享数据区:在绝对地址(0040:0000)开始。

5.可执行文件内存映像

​ DOS下可执行文件有两种(BAT是批处理文件,他只是简单调用DOS内部命令或其它程序,所以此处不认为它是可执行文件):一种是COM文件,一种是EXE文件。从程序内部看,前者程序的四个段重合,所以最大长度只等于一个段,用前面段地址的理解就是com文件最大只能是64K,所以com文件只适合小的程序。而exe,四个段可任何分配,并可扩充段,而且每个段的段地址可以任何改动,因此exe的访问内存能力大多了。这种格式访问能力只受地址结构的限制了。 用户程序所占的内存大小完全由程序本身决定,但最大,只能到640K。
​ 说到这里,还要提到段。每个段64K。段的作用就是数据组织单位。段的类型有三种:代码段(Code Segment,简称CS)、数据段(Data Segment,简称DS)、栈段(Stack Segment,简称SS),另外还有一个附加数据段(Extra Segment,简称ES),它的用与数据段DS可以认为完全一样,当数据段的64K不够用,或你就需要把数据放到两个段中以便移动、复制、比较时,才用到附加数据段ES。(当然,移动、复制、比较操作在一个段中也可以完成)。

5.1.段的作用

5.1.1 代码段(CS):程序装入内存中,DOS怎么知道是从哪里执行呢?答案就是系统自动从代码段指定位置开始执行,并且始终在代码段中执行。因此代码段CS的作用就是保存所有的指令。这里所说的代码也就是汇编指令了。所以编写汇编程序也就主要是编写代码段中的代码。

5.1.2 数据段(DS)、附加段(ES):顾名思义,数据段中存的就是数据,这些数据供代码段的程序调用。附加段就是附加数据段。作用与数据段相同。

5.1.3 栈段(SS):这个段非常重要,但实际上,你在使用中,似乎用不着这个段,但实际上,这是黑客编程中最重要的一部分,而且系统会不停地“偷偷地”使用这个段,正是这个偷偷地用,使得系统的很多动作被记录到这个段中。还有两点,你必须记住:一是如果你使用了这个栈,比如你把数据存到这个栈中,则必须有相应的出栈命令,并且入几个数据,就得出几个数据,多一个或少一个,你的程序就可能导致死机或异常;二是你要把握操作时机,比如你不能在系统使用栈的前后使用栈,比如你在调用子程序之前入栈,而在子程序中出栈,而在系统调用子程序时,系统也要使用栈,这种也将导致出错。
栈就是一种先入后出(也有称为后入先出)的结构,有地址由小到大的增加栈,有地址由大到小的逆向减栈。

5.2.段重叠

​ 从上面,我们可以看到,CS,DS,SS三者作用各不相同,内存就是象录音磁带,录新歌,则旧歌被删,带子上存的始终是最后录的那段音乐。因此,如果重叠则必然相互冲突。那还能重叠吗?
​ 这里所说的重叠不是指内容重叠,而是指概念上的重叠,即数据相互放到一个段中,但相互可以区分开。比如某一段既有数据也有代码,则代码在每要执行到数据之前加一个跳转指令跳过这段代码。这个跳转指令要求用户在编程的时候加上。
​ 而栈段呢?栈段有自己的特殊性,特殊就在于系统也会自动地使用,而用户则又在不知道系统在使用的情况下使用。避免这种冲突的方法就是采用逆向的栈段。

5.3 .COM文件内存映象

​ COM文件被读到内存中后,该文件的前100H个字节被操作系统使用,操作系统使用这256个字节保存一些系统要使用的数据,汇编语言编程者不能在这里存自己的数据,但在知道这此数据的作用后可以使用其中的数据。从100H开始,就是程序的开始了。COM文件之所以最大只能有64K,其原因是COM文件的四个段是相互重叠的。也就是说,CS、DS、SS、ES四个段的地址都指向这个COM文件的100H处。程序代码、数据、栈都在由100H到64K的区域内。如何把三者分开呢?栈段采用逆向栈,这个栈由64K开始,随着数据入栈,则地址就减小。这样作的好处是,栈段由高端向低端进展,可以详细与数据、代码分开;坏处也不言而喻,假如一个COM程序大量用到栈(比如是个递归程序)因此栈就不停地降低,而程序代码本身也很多,甚至不停地申请新空间,这样数据和栈就会在中间碰头,导致程序被破坏。
​ 区分开数据代码段与栈段后,下面讨论把数据段和代码段也分开。这个简单的多,只要逻辑上分开就可以。不过一般的方法就是:在100H处放一个跳转指令,随后放数据,然后再放置其它的代码。而100H处的跳转指令就跳到这里。
​ 因此,COM文件内存映象就是:
​ CS:0000 (由于COM的CS,DS,SS,ES三段重叠,因此此行前CS,写成DS,SS,ES都一样)
​ CS:0100 一个跳转到YYYY地址的跳转指令。
​ CS:0101 本程序所需要用到的数据
​ CS:XXXX 数据结束处。
​ CS:YYYY 程序代码保存处。
​ CS:ZZZZ 程序代码结束处。
​ CS:FFFF 栈段开始处(注意栈是地址越来越小,所以这里是开始而不是结束处),也是程序的结束处。另外,此处FFFF与前面XXXX,YYYY,ZZZZ不一样,这里是十六进制的64K。

5.4.EXE文件

​ 比起COM文件,EXE文件要复杂一些,他的复杂就在于COM文件前面规定了100H个字节用于系统使用,而EXE文件则有个文件头,文件头的大小看具体内容多少。文件头的内容使得EXE看起来复杂了,但也更灵活了。更重要的是,对于病毒设计者,这个文件头使他们如鱼得水。因为文件头处
​ EXE文件的内存映象为:
​ XXXX:0000 文件头
​ XXXX:YYYY 文件头结束处

​ CS:0000 代码段开始处
​ CS:ZZZZ 代码段结束处

​ DS:0000 数据码段开始处
​ DS:WWWW 数据码段结束处

​ SS:0000 栈段开始处
​ SS:UUUU 栈段结束处

​ ES:0000 附加段开始处
​ ES:VVVV 附加段结束处

说明:

  1. 上述ES可以没有,要看实际需要
  2. CS,DS,ES,SS的顺序也是看编程者是怎么安排的,好在用户不必关心他的具体位置。
  3. 由上可见,CS,DS,ES,SS的段地址肯定保存到了文件头中。
  4. 由上可见,实际执行的只是CS,因此DS,ES,SS的首地址,CS肯定要想办法知道。:)

6.汇编指令

6.1数据传输指令

mov a,b ;这个指令是把B中的数据复制给A,(B中仍保存原状)。这里的A和B可以是寄存器,可以是内存。但可以同时是寄存器,不能同时是内存。

6.2算术运算指令

ADD A,N ;寄存器A加上N,把和仍存在A中。类似于高级语言中的let a=a+n/a:=a+n/a+=n。

6.3逻辑运算指令

6.4串指令

从一个地址到另一个地址的复制需要注意的是:
*)把源串段地址给DS。
*)把源串编址给SI。
*)把目的串段址给ES。
*)把目的串偏址给DI。
*)把要复制的个数给CX,这里可不考虑$了。
*)把FLAG中的方向标志标志你要的方向,一个是顺向,另一个是逆向。
*)发送loop movs,scans等命令。

6.5程序转移指令

记住:无条件转移指令 jmp。等于转 jz,不等于时转jnz

6.6伪指令

string DB '这是我的第一个汇编语言程序$' ;DB就是伪指令,他的作用就是告诉编译程序,把后面一些数据或字符串放到内存中。当然对于exe来说,已在内存中了,就不用“告诉”了。(这就是为什么叫伪指令)。string是你给这段内存起的名字,如果你不需要这段内存,不起名字也可以,但如果后面要用,当然要加上这个名字。'这是我的第一个汇编语言程序$'这个就是要处理的数据,当然你也可以换成别的内容,但需要注意的是,要以'$'结尾,这是汇编的约写,即:只是到了$,就认为字符串结束,否则就一直向下找,直到找到一个$为止。所以这就要求你的字符串中不能有'$'。`

`Lea A,string ;前面已经定义了string,后面要把地址找到,就要用到lea指令。lea是把字符串的地址给A这个寄存器中,A当然可以上前面提到的任意寄存器。

7.编写程序

开始编写我们的第一个程序。
程序要求:显示一个“Hello,Mr.286.”怎么样?
思路:

7.1 要显示一个字符串,根据前面我让你们记的七八个指令够吗?答案是:不仅够,而且还用不完。
首先定义一下总可以吧。
hellostr db 'Hello,Mr.286. ′ 最 后 的 ' 最后的 不要忘了。

7.2 首先要考虑的问题就是找中断,找到合适的中断,该中断就能帮我们完成这个显示任务。我找到(在哪找到的,怎么找到的,别问我,到网上或书上都能找到):
中断INT 21H功能09H
功能描述: 输出一个字符串到标准输出设备上。如果输出操作被重定向,那么,将无法判断磁盘已满
入口参数: AH=09H
DS:DX=待输出字符的地址
说明:待显示的字符串以’$'作为其结束标志
出口参数: 无
由上面看到,我们所需要作的就是把DS指向数据段,DX指向字符串的地址,AH等于9H,调用21h中断。
mov ds,数据段地址
lea dx,hellostr 'hellostr已在前面7.1中定义了。
mov ah,9h
int 21h
由于只要在调用int 21h之前把准备的东西准备齐就行了,所以int 21h前面三行的顺序并不重要。

7.3 退出程序,运行完总要退出呀。再查中断手册
中断INT 21H功能4CH
功能描述: 终止程序的执行,并可返回一个代码
入口参数: AH=4CH
AL=返回的代码
出口参数: 无
mov ah,4Ch
mov al,0
int 21h

mov ax,4c00h
int 21h
这里需要说明的是返回代码有什么用,返回给谁?返回给操作系统,因为是操作系统DOS调用的这个程序,这个返回值可以通过批处理中的errorlevel得到,这里不多说明,实际上操作系统很少处理这一值,因此al你随便写什么值影响都不大。

8.程序实现

data SEGMENT
msg DB 'Hello, Mr.286.$'
data ENDS

code SEGMENT
    ASSUME CS:code,DS:data
start:MOV AX,data
      MOV DS,AX
      lea dx,msg 
      mov ah,9h
      int 21h
      MOV AX,4C00h
      INT 21h

code ENDS
END start

9.编译运行

把上面程序保存成hello286.asm后,就可以编译运行了。进入DOS,进入汇编目录,如果还没下载,到前面找下载地址。

E:\Download\Masm>masm hello286.asm**
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.

Object filename [hello286.OBJ]:
Source listing  [NUL.LST]:
Cross-reference [NUL.CRF]:

50408 + 415320 Bytes symbol space free

0 Warning Errors
0 Severe  Errors

说明:上面连续三个回车,表示我要的都是默认值。下面是零个警告,零个严重错误,(当然了,我的程序还敢错吗?)

**E:\Download\Masm>link hello286**

Microsoft (R) Overlay Linker  Version 3.60
Copyright (C) Microsoft Corp 1983-1987.  All rights reserved.

Run File [HELLO286.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
LINK : warning L4021: no stack segment

说明:三个回车仍要默认,后面有个警告,没有栈段,这个没关系,没有的话系统会自动给一个。

**E:\Download\Masm>hello286**
Hello, Mr.286.

说明:运行成功。

E:\Download\Masm>

;颜色:蓝1,绿2,红4


[SMBus读取从设备总结]

SMBUS的介绍与访问

内存条上的SPD(eeprom)中读取内存参数

汇编基础知识入门

心情感悟:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值