1.2 ASSEMBLY LANGUAGE

People are much happier moving up the ladder,socially or even technically.So our profession has moved from machine code to C/Win32 API,to C++/MFC,to java/AWT(Abstract Window Toolkit,classes for building graphics user interface in Java)/JFC(Java Foundation Classes,a new set of user interface classes which improve AWT),leaving only a few poor guys to implement the link backwards.

It's a good thing we can move forward in increasing productivity,but it's a sad thing that every time we move up the ladder,we quickly accept the new step as the only standard,and forget what's underneath.It's not strange nowadays to open a book on Visual C++ to find only pure MFC stuff inside or to hear questions like "How can I do this in MFC?"

Every time we add a layer of abstraction,a new layer of indirction is added.Someone has to implement each layer using the layers underneath,which id ultimately the assembly language.Even if you're not one of those people,having a deep understanding of assembly language gives you lots of advantages in your professional life.Assembly language helps you debug problems,understanding the working of the underlying OS(for example,just imagine that you got an exception in kernel32.dll).Assembly language helps you optimize your code to the highest performance;just try to understand why memory is implemented in such a comlicated way.Assembly language exposes features of the CPU that are normally not accessible in high-level language-for example,Intel's MMX(Multi-Media Extension)instructions. 

Here is a sample program that uses KTimer to measure your CPU clock speed and the time it takes to create a solid bursh:

//Timer.h
#pragma once

inline unsigned _int64 GetCycleCount(void)
{
    _asm _emit 0x0F
    _asm _emit 0x31
}

class KTimer
{
    unsigned _int64 m_startcycle;
public:
    unsigned _int64 m_overhead;
    KTimer(void)
    {
        m_overhead=0;
        Start();
        m_overhead=Stop();
    }

    void Start(void)
    {
        m_startcycle=GetCycleCount();
    }

    unsigned _int64 Stop(void)
    {
        return GetCycleCount()-m_startcycle-m_overhead;
    }
};
//GDISpeed.cpp

#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#include ".\timer.h"
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE,
 LPSTR lpCmd, int nShow)
{
 KTimer timer;
 TCHAR mess[128];
 timer.Start();
 Sleep(1000);
 unsigned cpuspeed10 = (unsigned)(timer.Stop()/100000);
 timer.Start();
 CreateSolidBrush(RGB(0xAA, 0xAA, 0xAA));
 unsigned time = (unsigned) timer.Stop();

 wsprintf(mess, _T("CPU speed       %d.%d mhz\n")
     _T("KTimer overhead %d clock cycles\n")
     _T("CreateSolidBrush %d clock cycles %d ns"),
     cpuspeed10 / 10,  cpuspeed10 % 10,
     (unsigned) timer.m_overhead,
     time, time * 10000 / cpuspeed10);

 MessageBox(NULL, mess, _T("How fast is GDI?"), MB_OK);
 return 0;
}

GetCycleCount使用了RDTSC(Read Time Stamp Counter,读取时间计数器)指令。RDTSC以64位无符号整数形式,通过EDX和EAX 32位普通寄存器时,返回自CPU引导后时针走过的圈数。RDTSC的使用方法即,

_emit 0x0F
_emit 0x31
posted @ 2016-01-02 11:34  廖凡  阅读(328)  评论(0编辑  收藏  举报