浅析语言中寻址方式的区别

时间:2023年07月21日

/

来源:原来小昭

/

编辑:本站小编

收藏本文

下载本文

下面小编为大家带来浅析语言中寻址方式的区别,本文共8篇,希望能帮助大家!本文原稿由网友“原来小昭”提供。

篇1:浅析语言中寻址方式的区别

浅析汇编语言中寻址方式的区别

浅析汇编语言中寻址方式的区别

王传俊

【摘要】寻址方式是汇编语言中的一个重要内容,是学习编程的基础,同时也是该门课程的一个学习难点。本文通过以Inte18086CPU为例,使用分析比较的方法阐述了各寻址方式间的区别。

【关键词】汇编语言 寻址方式 有效地址 物理地址

在计算机应用技术的发展过程中,汇编语言是一座连接软件和硬件的桥梁,也是计算机能够提供给用户最快而又最有效的语言。

汇编语言不同于用O,1数字表示的机器语言,它是用人们熟悉的英文缩写字符表示相应的操作码,用符号或数值表示地址和操作数。因此,汇编语言为程序的编写、阅读和修改提供了方便。但由于汇编语言仍是一种面向机器的语言,所以在进行程序设计时必须考虑到机器的指令系统、寻址方式及存储设备的设置和功能,而熟悉并灵活地应用机器所采用的各种寻址方式,是运用汇编语言进行程序设计的根本。而一个指令系统具有哪几种寻址方式,是否为编写程序提供方便,是指令系统设计的关键,同时也是初学者学习汇编语言的难点。

在教学过程中,通常选用Inte18086CPU的PC机为基础机型来组织教学。Inte18086提供了九类寻址方式,它们分别是立即寻址、寄存器寻址、寄存器间接寻址、直接寻址、变址寻址、基址变址寻址、串寻址、端口寻址和隐含寻址。

由于Inte18086中的寻址方式有相似之处,极易混淆。在教学过程中,应使学生抓住各种寻址方式的特点,找出它们之间的区别和联系,从而形成正确的概念。

什么是寻址方式呢?这是首先要明确的概念。一个指令是由操作码和操作数两部分组成的。操作数在存储器中存放的位置,称为操作数地址。获得操作数地址的方式,就称为操作数地址的寻址方式,简称寻址方式。

在寻址过程中,操作数的存放位置决定着寻址的方式。在汇编语言的学习过程中,区分“存放位置”是理解寻址方式的前提。因此,在学习之前应使学生理解寄存器和存储器的不同。

寄存器位于CPU内部,它的存取速度比存储器要快得多。在计算机的运算过程中寄存器主要用来存放运算过程中的`各种信息,包括操作数地址,操作数和运算的中间结果。

存储器是由许多存储单元组成的,每个单元有唯一确定的地址。它是计算机的记忆场所,能把计算和处理的数据及程序存入计算机,使计算机自主工作,免受其它因素的干扰。

在指令中,辨别操作数是存放在寄存器还是存储器中最简单的方法就是看这个操作数的书写有无[]。如果有[],则操作数一定是存储器操作数,即操作数存放在存储器中,而存储器操作数所在的存储器地址就是该操作数的物理地址。若无[],则操作数的存放分两种情况:一是在指令中操作数以立即数的形式给出,如3500H,则该操作数的寻址方式为立即寻址方式;二是操作数以通用寄存器形式给出,如AX,则该操作数的寻址方式为寄存器寻址方式。

立即寻址和寄存器寻址的相同之处在于都不需要访问内存,工作效率高。但立即寻址方式主要用来为存储单元或寄存器赋初值,如:MOVAX,2043H这条指令中的源操作数2043H以立即数形式给出,与操作码一起放在代码段区域中。而寄存器寻址方式的操作数放在一个通用寄存器中,即AX、BX、cx、DX、BP、sP、SI、DI中的任意一个。如:MAXAX,cx这条指令中的源操作数存放在cx中。

直接寻址方式和前两种寻址方式的区别是:操作数存放在存储器中,16位有效地址直接包含在指令中。它的物理地址是由指令中直接给出的16位有效地址与数据段寄存器DS向高位移动4位后相加得到的。如:MOVAX,[H]中源操作数的16位有效地址2000H直接出现在指令中,它的物理地址=DS*10H+2000H。

寄存器间接寻址、变址寻址、基址变址寻址这三种寻址方式的操作数都存放在内存储器中,而要访问内存中存放操作数的存储单元,就需要知道存储单元在内存储器中的有效地址。在Inte18086中,用来存放有效地址的寄存器只有四个,分别是DI、SI、BP和BX,即在指令中只有这四个寄存器可以放在[]中,作为寻址寄存器。四种寻址方式的有效地址就是通过这四个寄存器以不同寻址方式而得到的。

寄存器间接寻址方式的操作数的有效地址只能由四个寄存器中的一个存放。以DI、SI或BX间接寻址时,操作数隐含在存储器的数据段区域中,操作数的地址用数据段寄存器DS内容左移4位加上DI、SI或BX中的16位有效地址获得。如:MOVAX,[BX]中源操作数的有效地址为BX内容,它的物理地址=DS*10H+(BX)。以BP间接寻址时操作数隐含在存储器的对栈段区域中,操作数的地址用堆栈段寄存器ss内容左移4位加上BP中的16位有效地址获得。若指令中标明是段超越的,则操作数的地址用段前缀寄存器内容左移4位加上BP中的16位有效地址获得。

变址寻址方式的操作数有效地址由变址寄存器(DI、SI、BP、BX)内容和指令中给定的8位或16位位移量组成。与寄存器间接寻址方式相比多了位移量。如:MOVAX,disp[DI]中有效地址为disp+(DI),物理地址=DS*lOH+disp+(DI)。在基址变址寻址方式中,将SI或DI称为变址寄存器,将BP或BX称为基址寄存器,在使用时只能同时使用一个变址寄存器和一个基址寄存器。该寻址方式中的操作数有效地址=(SI)+(BX)。如:MOVAX,[SI][BX],物理地址=DS*10H+(SI)+(BX)。

在以上六种寻址方式中,物理地址只与存放在内存储器中的操作数有关,而这种操作数在指令格式中最大的特点就是带有[],而其它操作数的存取都与内存无关,因而也就不涉及物理地址。

串寻址方式用于字符串的操作,使用隐含的变址寄存器SI和DI寻址。源串操作数用SI寻址,目的串操作数用DI寻址,在指令执行过程中根据标志寄存器的DF标志位,自动修改SI和DI内容,以给定指向下一个操作数的地址,完成各种对字符串的操作。串寻址方式的特征主要表现在操作码上,通常串寻址方式的操作码是一般操作码后加S(string字符串的缩写),以区别与其它寻址方式的不同。如:MOV实现传送指令,MOVSB则实现字符串的字节传送。

端口寻址方式用于CPU寻址外设端口。并由8位或16位(存放在寄存器DX中)立即数构成端口地址。该寻址方式只有两个操作码:OUT(输出)和IN(输入)。需要注意的是输出指由CPU输出至端口地址,输入则指端口地址输入到CPU中。隐含寻址方式是指在Inte18086中,有些指令没有给出操作数,但却隐含着对固定寄存器的操作。如:AAA隐含对AL操作,LES隐含对ES操作。

这三种是具有特殊功能的寻址方式,理解了其各自的操作对象及操作码的特征,那么掌握起来就很容易了。

通过对这几种寻址方式的分析比较,将抽象且较难理解的寻址方式具体化、形象化,这对今后的指令系统和程序设计学习会有很大的帮助。

【参考文献】

1苏春莉:微机原理课程教学的实践与探讨[J],电脑知识与技术,,(24)

2陈佳:寻址方式教学方法的研究与研讨[J],科技技术,2009,(16)

3郭旭平:汇编语言寻址方式[J],机械管理开发,,(17)

【组稿编辑:包桂英】

(作者单位:265500山东省烟台市烟台汽车工程职业学院)

篇2:硬盘扇区的寻址方式

扇区的寻址方式

访问硬盘上的数据总是以扇区为单位进行的,即每次读或写至少是一个扇区的数据,寻找扇区的方式,即扇区的寻址方式有两种:物理寻址方式和逻辑寻址方式。

①物理寻址方式:又称CHS(CylinderHeadSector)方式,是用柱面号(即磁道号)、磁头号(即盘面号)和扇区号来表示一个特定的扇区。柱面和磁头从0开始编号,而扇区是从1开始编号的。

②逻辑寻址方式:又称LBA(logicalBlockAddressing)方式,是用逻辑编号来指定一个扇区,

扇区的逻辑编号与其物理编号的关系如下式:

逻辑编号(即LBA地址)=(柱面编号磁头数+磁头编号)扇区数+扇区编号-1

式中,磁头数为硬盘磁头的总数,扇区数为每磁道的扇区数。

从ATA-2标准开始,用28位二进制数来编码LBA地址。单从编址方式考虑,可支持的最大硬盘容量为128GB。但实际上,可配的硬盘容量还要受到BIOS和操作系统的限制。采用LBA寻址方式,没有磁头和磁道的转换操作,在访问连续扇区时,操作速度比物理寻址方式要快。

篇3:c语言中的堆和栈的区别

堆和栈的区别

1.申请方式

(1)栈(satck):由系统自动分配,例如,声明在函数中一个局部变量int b;系统自动在栈中为b开辟空间。

(2)堆(heap):需程序员自己申请(调用malloc,realloc,calloc),并指明大小,并由程序员进行释放。容易产生memory leak.

eg:char p;

p = (char *)malloc(sizeof(char));

但是,p本身是在栈中。

2.申请大小的限制

(1)栈:在windows下栈是向底地址扩展的数据结构,是一块连续的内存区域(它的生长方向与内存的生长方向相反)。栈的大小是固定的。如果申请的空间超过栈的剩余空间时,将提示overflow。

(2)堆:堆是高地址扩展的数据结构(它的生长方向与内存的生长方向相同),是不连续的内存区域。这是由于系统使用链表来存储空闲内存地址的,自然是不连续的,而链表的遍历方向是由底地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。

3.系统响应:

(1)栈:只要栈的空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

(2)堆:首先应该知道操作系统有一个记录空闲内存地址的链表,但系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的free语句才能正确的释放本内存空间。另外,找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

说明:对于堆来讲,对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低,

对于栈来讲,则不会存在这个问题,

4.申请效率

(1)栈由系统自动分配,速度快。但程序员是无法控制的

(2)堆是由malloc分配的内存,一般速度比较慢,而且容易产生碎片,不过用起来最方便。

5.堆和栈中的存储内容

(1)栈:在函数调用时,第一个进栈的主函数中后的下一条语句的地址,然后是函数的各个参数,参数是从右往左入栈的,然后是函数中的局部变量。注:静态变量是不入栈的。

当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续执行。

(2)堆:一般是在堆的头部用一个字节存放堆的大小。

6.存取效率

(1)堆:char *s1=”hellow tigerjibo”;是在编译是就确定的

(2)栈:char s1[]=”hellow tigerjibo”;是在运行时赋值的;用数组比用指针速度更快一些,指针在底层汇编中需要用edx寄存器中转一下,而数组在栈上读取。

补充:

栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

7.分配方式:

(1)堆都是动态分配的,没有静态分配的堆。

(2)栈有两种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的。它的动态分配是由编译器进行释放,无需手工实现。

篇4:C语言中break与continue的区别

C语言中break与continue的区别

break 关键字很重要,表示终止本层循环,现在这个例子只有一层循环,当代码执行到break 时,循环便终止。

如果把break 换成continue 会是什么样子呢?continue 表示终止本次(本轮)循环。当代码执行到continue 时,本轮循环终止,进入下一轮循环。

while(1)也有写成while(true) 或者while(1==1) 或者while((bool) 1)等形式的,效果一样。

do-while 循环:先执行do 后面的代码,然后再判断while 后面括号里的值,如果为真,循环开始;否则,循环不开始。其用法与while 循环没有区别,但相对较少用。

for 循环:for 循环可以很容易的控制循环次数,多用于事先知道循环次数的情况下,

《C语言中break与continue的`区别》()。

拓展:

我有一个char * 型指针正巧指向一些int 型变量, 我想跳过它们。 为什么如下的代码((int *)p)++; 不行?

在C 语言中, 类型转换意味着“把这些二进制位看作另一种类型, 并作相应的对待”; 这是一个转换操作符, 根据定义它只能生成一个右值(rvalue)。而右值既不能赋值, 也不能用++ 自增。(如果编译器支持这样的扩展, 那要么是一个错误, 要么是有意作出的非标准扩展。) 要达到你的目的可以用:p = (char *)((int *)p + 1);

或者,因为p 是char * 型, 直接用p += sizeof(int);

但是, 在可能的情况下, 你还是应该首先选择适当的指针类型, 而不是一味地试图李代桃僵。

篇5:浅谈C语言中scanf,gets函数区别与联系

众所周知,scanf函数和gets函数是从键盘输入数据的函数,其基本函数功能这里不做过多赘述,只对两个函数易错点深入分析。

int main{ char a[20]; char b[20]; char c[20]; printf(“请输入a字符串\\n”); scanf(“%s”,&a); printf(“请输入b字符串\\n”); gets(b); printf(“请输入c字符串\\n”); gets(c); return 0;}

【分析】程序本意是输入三个字符串,之所以用printf提示输入是因为想更清楚地看清程序怎么运作的,可以从运行界面看到程序提示输入a字符串和c字符串,但是会越过b字符串不让输入。这里会让人感到困惑。

因为scanf函数在读取字符串时,遇到回车、空格、制表符不会进行读取或转换,会舍弃掉它们以及它们后面的字符至缓冲区,最后在读取的字符后面加上‘\\0’.因此到了gets(b)的时候就会读取缓冲区剩下的东西以及最后的换行符就结束了,所以程序不会提示输入b字符串,但是从监视可以看到b中其实是读取了字符串的。然后缓冲区无剩余字符gets(c)可以实现输入c字符串。而且从这个程序也可以体现出来需要用到里面有空格的字符串的时候可以用gets函数。

这里还有一个注意点:在gets(c)读取从键盘输入的字符以及最后需要将缓冲区的数据刷新出去的回车符。它和scanf不同的是不会舍弃回车符至缓冲区中, 而是会丢弃换行符将其改为字符串结束标志‘\\0’,

所以我们一般喜欢使用这种带有清理收尾工作的输入函数。

最后一个点,我们可以看到b字符串其实读取的是缓冲区中的垃圾数据。因此,为了避免输入流缓冲区中垃圾数据对后续读入的影响,需要清空缓冲区。

下面就介绍方法(不同平台)

C标准规定 fflush()函数是用来刷新输出(stdout)缓存的。对于输入(stdin),它是没有定义的。但是有些编译器也定义了 fflush( stdin )的实现,比如微软的VC。其它编译器是否也定义了 fflush( stdin )的实现应当查找它的手册。GCC编译器没有定义它的实现,所以不能使用 fflush( stdin )来刷新输入缓存。

对于没有定义 fflush( stdin )的编译器,可以使用 fgets()函数来代替它(比用 getchar()、scanf()等函数通用性好)。可以这样忽略输入流中留下的回车等其它输入,从而使下一次的输入总保持一个“干净”的状态。(这个是任何平台下都可以的)

scanf函数读取字符

int main(){ char ch1; char ch2; char ch3; char ch4; scanf(“%c”,&ch1); scanf(“%c”,&ch2); scanf(“%c”,&ch3); scanf(“%c”,&ch4); return 0;}

【分析】用户输入'h'和' '和两个回车符,在监视中可以看到,四个字符如愿以偿得到了用户输入操作的四个字符,也并没有舍弃回车符到缓冲区。

篇6:语言中的性别歧视

语言中的性别歧视

近几年,语言与性别的关系已经成为社会语言学中一个日益重要的领域.笔者通过大量例子展示了反映在语言中的性别歧视现象,分析了这一现象产生的原因,并提出了消除该现象的方法.从研究的角度来看,只有对说话双方的.性别进行认真系统的研究,才有可能消除语言中的性别歧视现象,从而使女性得到平等的待遇.

作 者:柯彤彤 KE Tongtong  作者单位:广东海洋大学 外国语学院,广东 湛江,524088 刊 名:语文学刊 英文刊名:JOURNAL OF LANGUAGE AND LITERATURE STUDIES 年,卷(期): “”(6) 分类号:H313 关键词:语言   性别歧视   表现   原因   消除   sexism   language   evidence   reason   eliminate  

篇7:Go语言中普通函数与方法的区别分析

作者:books1958 字体:[增加 减小] 类型:

这篇文章主要介绍了Go语言中普通函数与方法的区别,以实例形式对比分析了普通函数与方法使用时的区别与相关技巧,需要的朋友可以参考下

本文实例分析了Go语言中普通函数与方法的区别,分享给大家供大家参考。具体分析如下:

1.对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然。

2.对于方法(如struct的方法),接收者为值类型时,可以直接用指针类型的变量调用方法,反过来同样也可以。

以下为简单示例:

代码如下:

package structTest

//普通函数与方法的区别(在接收者分别为值类型和指针类型的时候)

//Date:-4-3 10:00:07

import (

“fmt”

)

func StructTest06Base {

structTest0601()

structTest0602()

}

//1.普通函数

//接收值类型参数的函数

func valueIntTest(a int) int {

return a + 10

}

//接收指针类型参数的函数

func pointerIntTest(a *int) int {

return *a + 10

}

func structTest0601() {

a := 2

fmt.Println(“valueIntTest:”, valueIntTest(a))

//函数的参数为值类型,则不能直接将指针作为参数传递

//fmt.Println(“valueIntTest:”, valueIntTest(&a))

//compile error: cannot use &a (type *int) as type int in function argument

b := 5

fmt.Println(“pointerIntTest:”, pointerIntTest(&b))

//同样,当函数的参数为指针类型时,也不能直接将值类型作为参数传递

//fmt.Println(“pointerIntTest:”, pointerIntTest(b))

//compile error:cannot use b (type int) as type *int in function argument

}

//2.方法

type PersonD struct {

id  int

name string

}

//接收者为值类型

func (p PersonD) valueShowName() {

fmt.Println(p.name)

}

//接收者为指针类型

func (p *PersonD) pointShowName() {

fmt.Println(p.name)

}

func structTest0602() {

//值类型调用方法

personValue := PersonD{101, “Will Smith”}

personValue.valueShowName()

personValue.pointShowName()

//指针类型调用方法

personPointer := &PersonD{102, “Paul Tony”}

personPointer.valueShowName()

personPointer.pointShowName()

//与普通函数不同,接收者为指针类型和值类型的方法,指针类型和值类型的变量均可相互调用

}

希望本文所述对大家的Go语言程序设计有所帮助,

篇8:浅谈语言中的预设问题

浅谈语言中的预设问题

预设是语用学中一个重要的.研究话题,在逻辑学、语义学、语言用学里都有涉及.预设最早应用于哲学领域,后来逐渐成为语言学的关注对象.

作 者:何茹  作者单位:江苏连云港财经高等职业技术学校 刊 名:现代语文(语言研究) 英文刊名:MODERN CHINESE 年,卷(期):2008 “”(2) 分类号:H1 关键词:预设   哲学   语义   语用  

音乐语言中浪漫主义品质论文

礼仪致辞在英汉语言中的对比论文

浅谈英语语言中的性别歧视及其消除方法

汉英语言中动物符号文化涵义差异对比分析

and与or的用法区别

下载浅析语言中寻址方式的区别(推荐8篇)
浅析语言中寻址方式的区别.doc
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档
点击下载本文文档