什么是即时值?
在机器代码/指令集领域,立即数是嵌入指令本身的常数,而不是从另一个地方加载的。例如,在 x86 上:
6A 03 push 3
在这里, 3 是一个立即数,因为它直接作为操作码的一部分(在第二个字节中)包含在内。
在 ARM 上:
00 00 50 E3 CMP R0, #0
在这里,0 又是一个立即数,因为它是用操作码的位编码的。在 ARM 汇编中,立即数通常用#符号标记,尽管它在以后的版本中是可选的,当明确时。
另一个例子:
C8 30 1F E5 LDR R3, =0xC0B8
在这里,尽管表面上看起来,0xC0B8是不是一个立竿见影的。如果我们在 IDA 中开启 [x] Disable pointer dereferencing,则显示为:
LDR R3, dword_BDE0
和
B8 C0 00 00 dword_BDE0 DCD 0xC0B8
即这个值没有嵌入到指令中,而是从文字池中加载(保留用于存储不能表示为立即数的值的区域),但默认情况下,IDA 简化了此类指令以直接显示加载的值(大多数支持这种语法) ARM 汇编程序)。
立即数是存储在指令中的值。
例如(在 PIC16 中,因为这是我熟悉的):
MOVlw 0x01
MOVwf 0x07h
MOVlw 0x01
ADDwf 0x07h,0
该程序的作用如下:
- 将十六进制 01 的文字值移入累加器
- 将累加器移动到内存地址 0x07h
- 将十六进制 01 的文字值移入累加器
- 将地址 0x07h 添加到累加器并存储在累加器中。
这是一个向我们展示文字(立即)值和直接寻址之间区别的程序。
在第一条指令中,MOVlw 0x01我们将一个文字值移入累加器。这意味着该值直接从指令中获取,而不是从指令指向的寄存器中获取。当处理器读取这条指令时,它会获取操作数(在这种情况下是一个立即数),并将其直接放入累加器。除了获取指令所必需的之外,它不需要进行寄存器或内存访问。
在第四条指令 中ADDwf 0x07h,0,我们执行与上述相反的操作。指令不是直接从指令中获取值,而是包含值存储在内存中的地址。因此,当处理器读取这条指令时,它从内存中请求地址0x07h中的值,并使用内存返回的值进行操作。
再举一个例子,让我们看看这两条指令如何看待字节级别(请注意,对于实际的 PIC16 微控制器,这可能不是正确的机器代码):
让我们假设我们的指令有 8 位操作码和 8 位操作数。
我们的两条指令:MOVlw 0x01andADDwf 0x07h,0可能会变成:01 01and 02 7h 00。这使得查看真正发生的事情变得更加容易。
在01 01( MOVlw 0x01) 中,值01直接来自指令的操作数字段。但是,在02 7h 00( ADDwf 0x07h,0) 中,操作数是存储指令7h的实际操作数(在本例中为另一个01)的地址。
“立即值”是程序中包含的硬编码值。它是程序中存在的所有静态值。例如(如果翻译成 C):
x = 10;
x是一个变量并且10是一个立即数。
关于“在哪里找到值”,它在寄存器中r0。我不能说更多。如果您不知道寄存器是什么,您可以询问维基百科。