有一个叫做CPU窗口的工具,我按Ctrl+Alt+C,它显示了我的代码的反汇编。
内存地址左边的绿色箭头表示当前执行点的位置,然后是内存地址,但是第二列是什么意思,为什么编译器有时在一条指令后跳转多个地址?
例如:|first column|second column|assembly|
004520F4 55 push ebp //continuous
004520F5 8BEC mov ebp, esp //jumps to F7
004520F7 6A00 push $00 //jumps to F9
004520F9 53 push ebx //continuous
004520FA 33D2 xor edx,edx
让我们看一下代码:
<>之前004520F4 55推ebp004520F5 8BEC mov ebp,尤指004520F7 6A00推$00004520F9 53推ebx004520FA 33D2 xor edx,edx之前这里的每一行代表一条机器指令。显示的信息如下:
- 第一列是指令开始的地址,以十六进制显示。
- 第二列是指令的机器码,以十六进制显示。
- 第三列是指令反汇编成汇编语言。
所以第二和第三列表示完全相同的信息。提供第三列是为了使代码更易于理解。
注意不同的指令有不同的长度。第一条和第四条指令只有一个字节长。其他的是两个字节长。这就解释了为什么指令地址在两个字节指令之后增加一个字节以上。
有些指令可以占用超过两个字节,所以你可以为这些指令设置3、4等的增量。一个很好的例子是编码目标地址或偏移量的调用或跳转指令。因此,32位机器上的绝对跳转可能被编码为5个字节,一个用于操作码,四个用于地址。
回到美好的过去,在我出生之前很久,程序员甚至没有汇编器,直接用机器指令编写代码。那一定很好玩!
程序集清单(第三列)是第二列中实际机器代码的人类可读形式,即cpu实际执行的代码。
如果"跳转一些地址"的意思是第一列中的地址不总是加1,那是因为机器代码中的指令长度是不同的。例如,第一行,push ebp
是一个值为0x55
的单字节,因此下一个地址只是多了一个。但是第二条指令的机器码mov ebp, esp
是两个字节(0x8b 0xec
),因此地址增加2。