6. 汇编语言与机器语言的差异

总目录

1. WinDbg概述
2. WinDbg主要功能
3. WinDbg程序调试示例
4. CPU寄存器及指令系统
5. CPU保护模式概述
6. 汇编语言不等于CPU指令
7. 用WinDbg观察托管程序架构
8. Windows PE/COFF文件格式简述
9. 让WinDbg自动打开DotNet Runtime源程序
10. WinDbg综合实战

前言

前面两篇文章,通过对Intel CPU的介绍,让我们对计算机底层架构有了基础了解。

本文比较短,主要是想进一步通过示例说清楚一个问题:

汇编助记符 ≠ CPU指令

或者说,汇编助记符并不能永远看成是CPU机器指令的精确表达。

抛开汇编语言有自己的语法体系,有自己的directive指令而机器语言没有不提,单从CPU instruction和汇编助记符的角度考量,很多同学都认为,汇编语言就是机器语言,常将两者等同看待。虽然在很多时候,这种认识不会引发什么问题。不过,在某些特殊场景下,则务必区分清楚汇编与机器指令的区别,两者并非一一对应。

示例程序

这次,我们用一个C++程序来进行说明。本来可以不展示原程序,直接上汇编代码,但为了让同学们知道本次试验的来龙去脉,还是将C++源程序及完整汇编都展示出来,但请读者一定要明白:是否能看懂这个源程序或汇编,与能否理解本文要讲的核心要点之间,无必然联系,也就是说,看不懂这段程序就直接略过,不会影响后面的分析。

C++源程序如下:

int main(int argc, char* argv[])
{
    _asm INT 3;
    _asm
    {
        __asm _emit 0xcd __asm _emit 0x03
    }
    return 0;
}

以x86调试模式调试,在Visual Studio中通过汇编代码窗口拷贝出该程序的完整汇编如下:

--- E:\test\a\TestingCpp\Source.cpp --------------------------------------------
TestingCpp.exe!main(int, char * *):
009C1770 55                   push        ebp  
009C1771 8B EC                mov         ebp,esp  
009C1773 81 EC C0 00 00 00    sub         esp,0C0h  
009C1779 53                   push        ebx  
009C177A 56                   push        esi  
009C177B 57                   push        edi  
009C177C 8B FD                mov         edi,ebp  
009C177E 33 C9                xor         ecx,ecx  
009C1780 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
009C1785 F3 AB                rep stos    dword ptr es:[edi]  
009C1787 CC                   int         3  
009C1788 CD 03                int         3  
009C178A 33 C0                xor         eax,eax  
009C178C 5F                   pop         edi  
009C178D 5E                   pop         esi  
009C178E 5B                   pop         ebx  
009C178F 81 C4 C0 00 00 00    add         esp,0C0h  
009C1795 3B EC                cmp         ebp,esp  
009C1797 E8 A3 FA FF FF       call        __RTC_CheckEsp (09C123Fh)  
009C179C 8B E5                mov         esp,ebp  
009C179E 5D                   pop         ebp  
009C179F C3                   ret  
--- No source file -------------------------------------------------------------

本文要点其实只有上面汇编代码中的两条语句:

009C1787 CC                   int         3  
009C1788 CD 03                int         3  

先说本文要点:

  1. 009C1787 和 009C1788是内存地址,意思是说:数据CC保存在内存地址为009C1787的单元,数据CD保存在内存地址为009C1788的单元,数据03保存在内存地址为009C1789的单元;
  2. CC,CD和03都是十六进制数据,也就是计算机程序运行时要传到CPU中的指令,其中CC是第一条指令,CD和03合起来是第二条指令;
  3. 两个int 3都是对应着前面的CPU指令的汇编语言程序。汇编语言是对CPU指令的翻译,并不是计算机真正执行的指令。在这个示例中,CC指令被Visual Studio翻译成 int 3,CD 03也被Visual Studio翻译成 int 3,但如同老外说awesome,有人翻译成“真了不起”,也有人翻译成“漂亮!”,但最真实的意思是永远翻译不过来的,最真实的意思只有awesome才能代表。

下面,我们介绍一下两个int 3之间的差异。

INT 3 指令

我们首先必须清楚,在CPU看来,CC和CD 03绝对是两条不同的指令。从下面截图的 Description部分,我们知道,CC的作用是产生断点陷阱,而CD 03产生的是03号软中断。

INT 3
本文也不想详细说明两个 int 3 的差别,我的目的只有一个,不要完全相信汇编语句,真出现模糊时,还是必须要查手册,要定位到CPU指令级别。

当然,既然抛出了问题,我就简单说一下差别。

相似点

在CPU层面,无论是CC还是CD 03,其作用都是产生断点,让程序执行过程暂停,所以功能上差异是不大的。

差异

如果必须了解这两条指令在CPU层面的差异,可以看Intel CPU架构手册第二册,其主要差别只在于是否做IOPL权限检查。不过,因为Windows操作系统对断点指令的处理包括了将当前指令指针EIP减1的动作,所以对于单字节指令CC来说,断点断下后EIP执行CC之后的第一个字节,EIP - 1之后,又指回了CC,还是int 3的首地址,所以后续继续运行不会出现任何问题。但对于CD 03来说,断点断下以后,EIP指向了03之后的字节,此时EIP - 1 以后,则指向了03,而不是CD,这最终导致了后续指令错乱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值