高分:为什么立即数不能直接赋给段寄存器

疯癫小程序 2010-07-24 09:41:36
以下是我看到的一个网上的解释:

“有一个intel出来的同事真是好,对于标题所述的问题,他是这样解释的,由于立即数直接写入段寄存器这样的指令,被翻译成机器码之后将占用更多的字节,在事先规定的指令长度范围内无法存贮下这么多的内容,因此改由先写入通用寄存器,再由通用寄存器写入段寄存器的办法代替。立即数实际上是相当占地方的。”

对于上述的解释,我不是太赞同,他说把立即数赋给段寄存器对应得机器指令很长,那么,如果改赋给通用寄存器对应的机器指令不也一样长吗(段寄存器和通用寄存器都是寄存器)?中间还过度指令也要空间啊,所以我不理解这个解释。

请高手指点一下。
...全文
4054 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
疯癫小程序 2010-07-28
  • 打赏
  • 举报
回复
谢谢各位的讨论,现在结贴了。。。。
xiaopoy 2010-07-27
  • 打赏
  • 举报
回复
还在讨论,哈哈。

按我记的,没有指令可以实现之间内存间交换,不过可能指的是:
如果是内存到内存的,就成了DMA了,不经过cpu。另外这样的规定还可以避免对应的机器指令太长

wiki对opcode的执行流程 (Instruction cycle)描述是
[edit] 1. Fetch the instruction
The CPU presents, on the address bus, the value stored in the Program Counter. This is the memory address of the next instruction that is to be executed. The CPU then fetches the instruction from main memory via the data bus, and it is then placed into the CIR. The Program Counter is incremented to contain the address the next instruction.
[edit] 2. Decode the instruction
The instruction decoder interprets the instruction. If the instruction has an indirect address, the effective address is read from main memory, and any required data is fetched from main memory to be processed and then placed into data registers.
[edit] 3. Execute the instruction
The CU passes the decoded information as a sequence of control signals to the relevant function units of the CPU to perform the actions required by the instruction such as reading values from registers, passing them to the ALU to perform mathematical or logic functions on them, and writing the result back to a register. If the ALU is involved, it sends a condition signal back to the CU.
[edit] 4. Store results
The result generated by the operation is stored in the main memory, or sent to an output device. Based on the condition of any feedback from the ALU, Program Counter may be updated to a different address from which the next instruction will be fetched.
The cycle is then repeated.

1 IP的内容送到地址总线读取到对应的指令,之后CPU使IP指向下一个opcode,即意味着上一个指令到此可理解为完全执行结束了。
2 把段寄存器的内容传递给总线,把要读取的地址传递给总线,并把读取到的数据保存到(我们代码人无法碰到的)数据寄存器中。
3 执行指令的功能,通常是根据之前读取的数据寄存器中的那些数据,输入给ALU,经过ALU的运算后返回到一个寄存器里并返回EFLAGS。
4 根据ALU的运算结果来决定返回指令结果到内存中还是输出给一个外部硬件。

至于段寄存器无法被直接赋内存中值的原因是,因为段寄存器必须通过ALU来接触到,即必须通过寄存器才能输入值,而想返回一个结果到寄存器中,需要经过第四步,此时却已经过了操作ALU的过程了,因为如何赋值事实上是由其前的ALU运算结果决定的。想要给段寄存器设置值,由于这样的设计就相等于赋值两次,于是必须要先放寄存器中了。

至于不能直接操作内存,是因为输入和返回都是内存了,谁给ALU输入值?
goodbay98 2010-07-27
  • 打赏
  • 举报
回复
我是这么认为的:
段寄存器的地址都是16 的倍数, 如果直接把立即数传给段寄存器,那这个立即数在段寄存器中的偏移量是多少?即如何寻址?

献丑了, 咱是新手。
  • 打赏
  • 举报
回复 1
[Quote=引用 18 楼 xiaopoy 的回复:]
至于段寄存器无法被直接赋内存中值的原因是,因为段寄存器必须通过ALU来接触到,即必须通过寄存器才能输入值,而想返回一个结果到寄存器中,需要经过第四步,此时却已经过了操作ALU的过程了,因为如何赋值事实上是由其前的ALU运算结果决定的。想要给段寄存器设置值,由于这样的设计就相等于赋值两次,于是必须要先放寄存器中了。
[/Quote]

这... 没有“段寄存器无法被直接赋内存中值”这回事。
pop ds
mov es,[xxxx]
mov ds,[bx]
都是合法指令。
“立即数不能直接赋给段寄存器”和“段寄存器无法被直接赋内存中值”不是一回事,前者是诸如mov ds,1234h这种形式。
xiaopoy 2010-07-27
  • 打赏
  • 举报
回复
我自己迷糊,说的也迷糊。
指的是,取指令时从内存中读取的值,因为 通过内存由内存中读到的值有一个专门的临时寄存器保存,唔,LZ还是找intel手册的指令执行流程看看。
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 helonsy 的回复:]

这位大牛的貌似有点道理。。。

大牛是不是也觉得我此贴里我讲的那个Intel员工讲的也不通啊?
[/Quote]

大牛谈不上。就我个人的意见,你说的那个intel员工讲的原因“在事先规定的指令长度范围内无法存贮下这么多的内容”,应该是有问题的。

x86架构限定指令最长15字节(8086/8088没有这个限制,理论上可以任意长),而段寄存器是16位的,立即数装入段寄存器的指令,如果需要的话,最短只需要3个字节,所以编码长度应该不是问题。
baby_pray 2010-07-26
  • 打赏
  • 举报
回复
可以这样理解:段寄存器是虚拟的
burningstyle 2010-07-26
  • 打赏
  • 举报
回复
问题提的太好了,

本人是个初学者,认为如果将常数直接写到段寄存器中,会使编译器很不好办,因为段基地址这个东西,不能规定的太死,不然,你分配了,但在运行时,万一被别的程序给占用了,那多不好办……虽然这样的几率非常非常小,但是还是有的,

还不如让编译器给程序分个相对的基址,在程序加载时,再进行给cs,ds进行初始化
用户 昵称 2010-07-26
  • 打赏
  • 举报
回复
立即数进段寄存器,一条指令

立即数进通用寄存器,一条指令
通用寄存器进段寄存器,一条指令

一条指令盛不下,就用两条了。
  • 打赏
  • 举报
回复
立即数是存在内存中,切段之后,这个内存不一定还是这个值.
goodider 2010-07-25
  • 打赏
  • 举报
回复
其实这个问题还是应该看看书的前两章对于计算机的介绍。就知道为什么不能用立即数直接赋值给段寄存器了。
疯癫小程序 2010-07-25
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 blukercn 的回复:]
立即数是存在内存中,切段之后,这个内存不一定还是这个值.
[/Quote]
立即数好像在指令里吧,当然指令时存在内存中,但取出后则是存在指令寄存器中。
疯癫小程序 2010-07-25
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 delphiguy 的回复:]
就是这么定义的(也可以不这么定义)。

技术上是可以,但是实际使用中这种用法很少有需要,因为已经有了从通用寄存器装入段寄存器和从内存单元装入段寄存器(mov或者push/pop)两种方法了(但是对cs不行,修改cs只能通过jmp或者call指令来转换),为了节约指令编码空间,就不需要设置给段寄存器装入立即数这种指令了。
[/Quote]
这位大牛的貌似有点道理。。。

大牛是不是也觉得我此贴里我讲的那个Intel员工讲的也不通啊?
  • 打赏
  • 举报
回复
就是这么定义的(也可以不这么定义)。

技术上是可以,但是实际使用中这种用法很少有需要,因为已经有了从通用寄存器装入段寄存器和从内存单元装入段寄存器(mov或者push/pop)两种方法了(但是对cs不行,修改cs只能通过jmp或者call指令来转换),为了节约指令编码空间,就不需要设置给段寄存器装入立即数这种指令了。
无形忍者 2010-07-24
  • 打赏
  • 举报
回复
由于立即数直接写入段寄存器这样的指令,被翻译成机器码之后将占用更多的字节,在事先规定的指令长度范围内无法存贮下这么多的内容,因此改由先写入通用寄存器,再由通用寄存器写入段寄存器的办法代替。立即数实际上是相当占地方的
masmaster 2010-07-24
  • 打赏
  • 举报
回复
通常情况下, 机器指令只有1~2个字节
goodider 2010-07-24
  • 打赏
  • 举报
回复
这个和硬件流程有关系。
xiaopoy 2010-07-24
  • 打赏
  • 举报
回复
原因很简单。因为CPU的设计里面一次指令只能读写内存一次的流程设计。立即数直接赋值给段寄存器的话,相当于读一次内存,一次内存流程了,再写一次内存,二次内存流程了。
goodider 2010-07-24
  • 打赏
  • 举报
回复
可以看看硬件怎么与软件工作的。
疯癫小程序 2010-07-24
  • 打赏
  • 举报
回复 1
[Quote=引用 6 楼 masmaster 的回复:]
这问题就像“两个内存单元不能直接传送数据,必须用寄存器中转”这样的问题一样,intel手册就这么说的, 我们就应该遵循。段寄存器跟通用寄存器不一样,在运算中肯定不能像用通用寄存器那么随意。个人看法。
[/Quote]
不是这样的,任何一件事都有它的理由,比如你刚才说的两个内存单元不能直接赋值,也是有原因的:因为20根地址线在某一时刻只能在某一方向传递,所以你不可能在两个方向上同时传,即内存之间的赋值必须中转。
加载更多回复(2)

21,497

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧