我目前正在研究x86汇编语言,请参阅Kip Irvine的书“用于x86处理器的第7版Edi汇编语言”。
在第4章中,作者谈到了机器指令
我的问题是,为什么机器指令al
中不存在al
(或A0 00010400
的表示)?如果缺少al
,机器如何知道我们要将地址00010400
的值移至al
?
============ 编辑1 ===============
我尝试了mov bl var1
,并为bl
.386
.MODEL FLAT, STDCALL
.STACK 4096
ExitProcess PROTO, dwExitCode: DWORD
.DATA
var1 BYTE 10h
.CODE
main PROC
MOV BL, var1
invoke ExitProcess, 0
main ENDP
END main
答案 0 :(得分:8)
作为一般规则,机器指令中存在寄存器值 然而,x86指令集中有许多遗留的“包袱” 引入8086时,指令的长度会影响执行时间:更短的指令运行得更快。
A
寄存器(AX/AL
)称为“累加器”,曾经是CPU中最通用的寄存器。它具有特殊的短版本指令(以前)运行得更快(在原始的8086/8088上)。在x86的后续迭代中,其他寄存器被升级为更通用的。现在你几乎可以使用任何寄存器用于所有目的。
您可以在x86操作码地图上清楚地看到这一点,请参阅:http://sparksandflames.com/files/x86InstructionChart.html
请注意mov al,[absolute address]
有2个编码,它们做同样的事情:
A0和8A 05
0: a0 00 00 00 00 mov al,BYTE PTR ds:0x0
5: 8a 05 00 00 00 00 mov al,BYTE PTR ds:0x0
回想起来,这很浪费。但是当时使用累加器寄存器更快地制作指令似乎是个好主意。由于向后兼容,这些错误现在无法纠正
有可能在新的X64指令集中消除这种重复,但AMD不想做太多改动,所以我们永远坚持这些历史文物。
答案 1 :(得分:5)
我的问题是,为什么机器指令
al
中没有al
(或A0 00010400
的表示)?
因为MOV
指令(0xA0
)存在特殊编码,所以总是将AL
寄存器作为其目标操作数。其余的代码字节专用于指定源操作数,在本例中为0x00010400
- var1
部分中.DATA
的地址。
您可以在this table中看到。您还会看到还有其他特殊的说明编码,例如0xA1
MOV
AX
/ EAX
作为其目标操作数,0xA2
对于版本为MOV
且其操作数已反转(例如,mov var1, al
)。
原因为什么存在这些替代编码是为了在生成的机器代码中保存字节。作为Hans Passant commented,在20世纪70年代中期到x86处理器构思和设计时,这种事情很重要。那时内存非常昂贵,而且总线速度要慢得多,因此节省空间很重要 - 即使代价是使处理器的指令解码器更复杂。鉴于8088上的非常小的(4字节)提取队列,使用这些特殊的单字节指令编码可以significantly increase the speed of a particular sequence of code。然而,现在,这个设计在40年后仍在使用,这是英特尔继续遭受的x86平台的一些传统包袱。现代x86芯片必须将不成比例的大部分硅片用于复杂的指令解码器,即使内存非常便宜,因为这些类型的优化并不能真正帮助任何人。
当其中一个操作数是累加器寄存器时,这些特殊编码不是 ,而是that is by far the most common case for a special encoding。
通常情况下,指令 用操作码字节编码,后跟每个操作数的字节。这就是您在mov bl, var1
看到的内容。 mov reg8, r/m8
的操作码为0x8A
。然后0x1D
将DL
寄存器指定为目标操作数。有a handy opcode table here,或者您可以在英特尔的IA-32架构手册中找到每条指令的相关信息。 This site非常有用,为说明提供“备忘单”。您可以在Stack Overflow上的x86标记wiki中找到更多这样的链接。
答案 2 :(得分:1)
一些/较旧(/ CISC)指令集,特别是那些使用8位或可变长度的指令集,从x86等8位指令开始。而不是你在mips或arm或其他(特别是risc)指令集中看到的,通常很清楚这些N位调用特定的寄存器。对于这些基于8位的指令集(比如x86,6502,z80等),您可以创建一个要实现的指令列表,然后经常以对解码有意义的方式对它们进行排列,有时某些位可能会实际上是一个注册表。查看8086或z80或其他的操作码图表并查看模式。同时它有点武断,我说157条指令我可以用一个字节代表最多256件事,完成了。只列出事物并为它们分配一个数字。逻辑内部基本上有一个表,将其转换为微代码(对于x86和6502等微编码体系结构,但通常没有任何意义上的risc),同样解码或读取你必须参考表的机器代码因此,许多“无论指令集参考”文档通常以操作码映射开始,甚至是ARM,但在ARM情况下,它处理确定什么族的字的分数,然后其余位明确指示寄存器号在CISC中,如z80,8086等,操作码映射通常是字节,256个可能的指令,每个字节可以唯一地定义整个操作,输入,输出,然后任何immediates跟随它作为可变长度的一部分。 / p>