本课件由汇编网()制作提供《汇编语言》课件王爽著-清华大学出版社制作工具:MicrosoftPowerPoint2003本课件由汇编网()制作提供本课件由汇编网()制作提供第16章直接定址表16.1描述了单元长度的标号16.2在其他段中使用数据标号16.3直接定址表16.4程序入口地址的直接定址表本课件由汇编网()制作提供引言这一章,我们讨论如何有效合理地组织数据,以及相关的编程技术。本课件由汇编网()制作提供16.1描述了单元长度的标号本章中,我们要用到这种标号,先进行如下介绍。前面的课程中,我们一直在代码段中使用标号来标记指令、数据、段的起始地址。本课件由汇编网()制作提供16.1描述了单元长度的标号比如:下面的程序将code段中的a标号处的8个数据累加,结果存储到b标号处的字中。程序代码本课件由汇编网()制作提供16.1描述了单元长度的标号assumecs:codecodesegmenta:db1,2,3,4,5,6,7,8b:dw0start:movsi,offsetamovbx,offsetbmovcx,8s:moval,cs:[si]movah,0addcs:[bx],axincsiloopsmovax,4c00hint21hcodeendsendstart本课件由汇编网()制作提供16.1描述了单元长度的标号程序中,code、a、b、start、s都是标号。这些标号仅仅表示了内存单元的地址。但是,我们还可以使用一种标号,这种标号不但表示内存单元的地址,还表示了内存单元的长度,即表示在此标号处的单元,是一个字节单元,还是字单元,还是双字单元。上面的程序我们还可以写成这样:程序本课件由汇编网()制作提供16.1描述了单元长度的标号assumecs:codecodesegmentadb1,2,3,4,5,6,7,8bdw0start:movsi,0movcx,8s:moval,a[si]movah,0addb,axincsiloopsmovax,4c00hint21hcodeendsendstart本课件由汇编网()制作提供16.1描述了单元长度的标号我们在code段中使用的标号a、b后面没有“:”,它们是同时描述内存地址和单元长度的标号。标号a,描述了地址code:0,和从这个地址开始,以后的内存单元都是字节单元;而标号b描述了地址code:8,和从这个地址开始,以后的内存单元都是字单元。本课件由汇编网()制作提供16.1描述了单元长度的标号因为这种标号包含了对单元长度的描述,所以,在指令中,它可以代表一个段中的内存单元。比如,对于程序中的bdw0。指令:movax,b相当于:movax,cs:[8]指令:movb,2相当于:movwordptrcs:[8],2指令:incb相当于:incwordptrcs:[8]在这些指令中,标号b代表了一个内存单元,地址为code:8,长度为2字节。本课件由汇编网()制作提供16.1描述了单元长度的标号下面的指令会引起编译错误:moval,b因为b代表的内存单元是字单元,而al是8位寄存器。如果我们将程序中的指令:addb,ax,写为addb,al,将出现同样的编译错误。本课件由汇编网()制作提供16.1描述了单元长度的标号对于程序中的adb1,2,3,4,5,6,7,8:指令:moval,a[si]相当于:moval,cs:0[si]指令:moval,a[3]相当于:moval,cs:0[3]指令:moval,a[bx+si+3]相当于:moval,cs:0[bx+si+3]本课件由汇编网()制作提供16.1描述了单元长度的标号可见,使用这种包含单元长度的标号,可以使我们以简洁的形式访问内存中的数据。以后,我们将这种标号称为数据标号。它标记了存储数据的单元的地址和长度。它不同于仅仅表示地址的地址标号。本课件由汇编网()制作提供特别提示检测点16.1(page278)没有通过此检测点,请不要向下进行!本课件由汇编网()制作提供16.2在其他段中使用数据标号一般来说,我们不在代码段中定义数据,而是将数据定义到其他段中。在其他段中,我们也可以使用数据标号来描述存储数据的单元的地址和长度。注意:在后面加有“:”的地址标号,只能在代码段中使用,不能在其他段中使用。本课件由汇编网()制作提供16.2在其他段中使用数据标号右面的程序将data段中a标号处的8个数据累加,结果存储到b标号处的字中。assumecs:code,ds:datadatasegmentadb1,2,3,4,5,6,7,8bdw0dataendscodesegmentstart:movax,datamovds,axmovsi,0movcx,8s:moval,a[si]movah,0addb,axincsiloopsmovax,4c00hint21hcodeendsendstart本课件由汇编网()制作提供16.2在其他段中使用数据标号注意,如果想在代码段中,直接用数据标号访问数据,则需要用伪指令assume将标号所在的段和一个段寄存器联系起来。否则编译器在编译的时候,无法确定标号的段地址在哪一个寄存器中。本课件由汇编网()制作提供16.2在其他段中使用数据标号当然,这种联系是编译器需要的,但绝对不是说,我们因为编译器的工作需要,用assume指令将段寄存器和某个段相联系,段寄存器中就会真的存放该段的地址。我们在程序中还要使用指令对段寄存器进行设置。本课件由汇编网()制作提供16.2在其他段中使用数据标号比如:在上面的程序中,我们要在代码段code中用data段中的数据标号a、b访问数据,则必须用assume将一个寄存器和data段相联。在程序中,我们用ds寄存器和data段相联,则编译器对相关指令的编译如下:指令:moval,a[si]编译为:moval,[si+0]指令:addb,ax编译为:add[8],ax本课件由汇编网()制作提供16.2在其他段中使用数据标号因为这些实际编译出的指令,都默认所访问单元的段地址在ds中,而实际要访问的段为data,所以,若要访问正确,在这些指令执行前,ds中必须为data段的段地址。则,我们在程序中使用指令:movax,datamovds,ax设置ds指向data段。本课件由汇编网()制作提供16.2在其他段中使用数据标号我们可以将标号当作数据来定义,此时,编译器将标号所表示的地址当作数据的值。比如:datasegmentadb1,2,3,4,5,6,7,8bdw0cdwa,bdataends数据标号c处存储的两个字型数据为标号a、b的偏移地址。本课件由汇编网()制作提供16.2在其他段中使用数据标号相当于:datasegmentadb1,2,3,4,5,6,7,8bdw0cdwoffseta,offsetbdataends本课件由汇编网()制作提供16.2在其他段中使用数据标号再比如:datasegmentadb1,2,3,4,5,6,7,8bdw0cdda,bdataends数据标号c处存储的两个双字型数据为标号a的偏移地址和段地址、标号b的偏移地址和段地址。本课件由汇编网()制作提供16.2在其他段中使用数据标号相当于:datasegmentadb1,2,3,4,5,6,7,8bdw0cdwoffseta,sega,offsetb,segbdataendsseg操作符,功能为取得某一标号的段地址。本课件由汇编网()制作提供特别提示检测点16.2(page280)没有通过此检测点,请不要向下进行!本课件由汇编网()制作提供16.3直接定址表现在,我们讨论用查表的方法编写相关程序的技巧。编写子程序,以十六进制的形式在屏幕中间显示给定的byte型数据。分析本课件由汇编网()制作提供16.3直接定址表分析:一个字节需要用两个十六进制数码来表示,所以,子程序需要在屏幕上显示两个ASCII字符。我们当然要用“0”、“1”、“2”、“3”、“4”、“5”、“6”、“7”、“8”、“9”、“A”、“B”、“C”、“D”、“E”、“F”这16个字符来显示十六进制数码。本课件由汇编网()制作提供16.3直接定址表我们可以将一个byte的高4位和低4位分开,分别用它们的值得到对应的数码字符。比如2Bh,我们可以得到高4位的值为2,低4位的值为11。那么我们如何用这两个数值得到对应的数码字符“2”和“B”呢?本课件由汇编网()制作提供16.3直接定址表最简单的办法就是一个一个地比较,如下:如果数值为0,则显示“0”;如果数值为1,则显示“1”;:如果数值为11,则显示“B”;:我们可以看出,这样做,程序中要使用多条比较、转移指令。程序将比较长,混乱。本课件由汇编网()制作提供16.3直接定址表显然,我们希望能够在数值0~15和字符“0”~“F”之间找到一种映射关系。这样我们用0~15间的任何数值,都可以通过这种映射关系直接得到“0”~“F”中对应的字符。本课件由汇编网()制作提供16.3直接定址表数值0~9和字符“0”~“9”之间的映射关系是很明显的,即:数值+30h=对应字符的ASCII值:0+30h=“0”的ASCII值1+30h=“1”的ASCII值2+30h=“2”的ASCII值:本课件由汇编网()制作提供16.3直接定址表但是,10~15和“A”~“F”之间的映射关系是:数值+37h=对应字符的ASCII值:10+37h=“A”的ASCII值11+37h=“B”的ASCII值12+37h=“C”的ASCII值:本课件由汇编网()制作提供16.3直接定址表可见,我们可以利用数值和字符之间的这种原本存在的映射关系,通过高4位和低4位值得到对应的字符码。但是由于映射关系的不同,我们在程序中必须进行一些比较,对于大于9的数值,我们要用不同的计算方法。本课件由汇编网()制作提供16.3直接定址表这样做,虽然使程序得到了简化。但是,如果我们希望用更简捷的算法,就要考虑用同一种映射关系从数值得到字符码。所以,我们就不能利用0~9和“0”~“9”之间与10~15和“A”~“F”之间原有的映射关系。本课件由汇编网()制作提供16.3直接定址表因为数值0~15和字符“0”~“F”之间没有一致的映射关系存在,所以,我们应该在它们之间建立新的映射关系。具体的做法是,我们建立一张表,表中依次存储字符“0”~“F”,我们可以通过数值0~15直接查找到对应的字符。子程序代码本课件由汇编网()制作提供16.3直接定址表可以看出,在子程序中,我们在数值0~15和字符“0”~“F”之间建立的映射关系为:以数值N为table表中的偏移,可以找到对应