欧美色欧美亚洲高清在线观看,国产特黄特色a级在线视频,国产一区视频一区欧美,亚洲成a 人在线观看中文

  1. <ul id="fwlom"></ul>

    <object id="fwlom"></object>

    <span id="fwlom"></span><dfn id="fwlom"></dfn>

      <object id="fwlom"></object>

      [電腦書籍]語(yǔ)言簡(jiǎn)介與入門

      時(shí)間:2019-05-13 14:09:43下載本文作者:會(huì)員上傳
      簡(jiǎn)介:寫寫幫文庫(kù)小編為你整理了多篇相關(guān)的《[電腦書籍]語(yǔ)言簡(jiǎn)介與入門》,但愿對(duì)你工作學(xué)習(xí)有幫助,當(dāng)然你在寫寫幫文庫(kù)還可以找到更多《[電腦書籍]語(yǔ)言簡(jiǎn)介與入門》。

      第一篇:[電腦書籍]語(yǔ)言簡(jiǎn)介與入門

      我不想夸大或者貶低匯編語(yǔ)言。但我想說(shuō),匯編語(yǔ)言改變了20世紀(jì)的歷史。與前輩相比,我們這一代編程人員足夠的幸福,因?yàn)槲覀冇懈魇礁鳂拥木幊陶Z(yǔ)言,我們可以操作鍵盤、坐在顯示器面前,甚至使用鼠標(biāo)、語(yǔ)音識(shí)別。我們可以使用鍵盤、鼠標(biāo)來(lái)駕馭“個(gè)人計(jì)算機(jī)”,而不是和一群人共享一臺(tái)使用笨重的繼電器、開關(guān)去操作的巨型機(jī)。相比之下,我們的前輩不得不使用機(jī)器語(yǔ)言編寫程序,他們甚至沒(méi)有最簡(jiǎn)單的匯編程序來(lái)把助記符翻譯成機(jī)器語(yǔ)言,而我們可以從上千種計(jì)算機(jī)語(yǔ)言中選擇我們喜歡的一種,而匯編,雖然不是一種“常用”的具有“快速原型開發(fā)”能力的語(yǔ)言,卻也是我們可以選擇的語(yǔ)言中的一種。

      每種計(jì)算機(jī)都有自己的匯編語(yǔ)言——沒(méi)必要指望匯編語(yǔ)言的可移植性,選擇匯編,意味著選擇性能而不是可移植或便于調(diào)試。這份文檔中講述的是x86匯編語(yǔ)言,此后的“匯編語(yǔ)言”一詞,如果不明示則表示ia32上的x86匯編語(yǔ)言。

      匯編語(yǔ)言是一種易學(xué),卻很難精通的語(yǔ)言。回想當(dāng)年,我從初學(xué)匯編到寫出第一個(gè)可運(yùn)行的程序,只用了不到4個(gè)小時(shí);然而直到今天,我仍然不敢說(shuō)自己精通它。編寫快速、高效、并且能夠讓處理器“很舒服地執(zhí)行”的程序是一件很困難的事情,如果利用業(yè)余時(shí)間學(xué)習(xí),通常需要2-3年的時(shí)間才能做到。這份教材并不期待能夠教給你大量的匯編語(yǔ)言技巧。對(duì)于讀者來(lái)說(shuō),x86匯編語(yǔ)言“就在這里”。然而,不要僵化地局限于這份教材講述的內(nèi)容,因?yàn)樗荒芨嬖V你匯編語(yǔ)言是“這樣一回事”。學(xué)好匯編語(yǔ)言,更多的要靠一個(gè)人的創(chuàng)造力于悟性,我可以告訴你我所知道的技巧,但肯定這是不夠的。一位對(duì)我的編程生涯產(chǎn)生過(guò)重要影響的人曾經(jīng)對(duì)我說(shuō)過(guò)這么一句話:

      寫匯編語(yǔ)言程序不是匯編語(yǔ)言最難的部分,創(chuàng)新才是。

      我想,愿意看這份文檔的人恐怕不會(huì)問(wèn)我“為什么要學(xué)習(xí)匯編語(yǔ)言”這樣的問(wèn)題;不過(guò),我還是想說(shuō)幾句:首先,匯編語(yǔ)言非常有用,我個(gè)人主張把它作為C語(yǔ)言的先修課程,因?yàn)橥ㄟ^(guò)學(xué)習(xí)匯編語(yǔ)言,你可以了解到如何有效地設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),讓計(jì)算機(jī)處理得更快,并使用更少的存儲(chǔ)空間;同時(shí),學(xué)習(xí)匯編語(yǔ)言可以讓你熟悉計(jì)算機(jī)內(nèi)部運(yùn)行機(jī)制,并且,有效地提高調(diào)試能力。就我個(gè)人的經(jīng)驗(yàn)而言,調(diào)試一個(gè)非結(jié)構(gòu)化的程序的困難程度,要比調(diào)試一個(gè)結(jié)構(gòu)化的程序的難度高很多,因?yàn)椤敖Y(jié)構(gòu)化”是以犧牲運(yùn)行效率來(lái)提高可讀性與可調(diào)試性,這對(duì)于完成一般軟件工程的編碼階段是非常必要的。然而,在一些地方,比如,硬件驅(qū)動(dòng)程序、操作系統(tǒng)底層,或者程序中經(jīng)常需要執(zhí)行的代碼,結(jié)構(gòu)化程序設(shè)計(jì)的這些優(yōu)點(diǎn)有時(shí)就會(huì)被它的低效率所抹煞。另外,如果你想真正地控制自己的程序,只知道源代碼級(jí)的調(diào)試是遠(yuǎn)遠(yuǎn)不夠的。

      浮躁的人喜歡說(shuō),用C++寫程序足夠了,甚至說(shuō),他不僅僅掌握C++,而且精通STL、MFC。我不贊成這個(gè)觀點(diǎn),掌握上面的那些是每一個(gè)編程人員都應(yīng)該做到的,然而C++只是我們“常用”的一種語(yǔ)言,它不是編程的全部。低層次的開發(fā)者喜歡說(shuō),嘿,C++是多么的強(qiáng)大,它可以做任何事情——這不是事實(shí)。便于維護(hù)、調(diào)試,這些確實(shí)是我們的追求目標(biāo),但是,寫程序不能僅僅追求這個(gè)目標(biāo),因?yàn)槲覀冏罱K的目的是滿足設(shè)計(jì)需求,而不是個(gè)人非理性的理想。這份教材適合已經(jīng)學(xué)習(xí)過(guò)某種結(jié)構(gòu)化程序設(shè)計(jì)語(yǔ)言的讀者。其內(nèi)容基于我在1995年給別人講述匯編語(yǔ)言時(shí)所寫的講義。當(dāng)然,如大家所希望的,它包含了最新的處理器所支持的特性,以及相應(yīng)的內(nèi)容。我假定讀者已經(jīng)知道了程序設(shè)計(jì)的一些基本概念,因?yàn)闆](méi)有這些是無(wú)法理解匯編語(yǔ)言程序設(shè)計(jì)的;此外,我希望讀者已經(jīng)有了比較良好的程序設(shè)計(jì)基礎(chǔ),因?yàn)槿绻闳狈?duì)于結(jié)構(gòu)化程序設(shè)計(jì)的認(rèn)識(shí),編寫匯編語(yǔ)言程序很可能很快就破壞了你的結(jié)構(gòu)化編程習(xí)慣,大大降低程序的可讀性、可維護(hù)性,最終讓你的程序陷于不得不廢棄的代碼堆之中?;旧希@份文檔撰寫的目標(biāo)是盡可能地便于自學(xué)。不過(guò),它對(duì)你也有一些要求,盡管不是很高,但我還是強(qiáng)調(diào)一下。學(xué)習(xí)匯編語(yǔ)言,你需要

      膽量。不要害怕去接觸那些計(jì)算機(jī)的內(nèi)部工作機(jī)制。知識(shí)。了解計(jì)算機(jī)常用的數(shù)制,特別是二進(jìn)制、十六進(jìn)制、八進(jìn)制,以及計(jì)算機(jī)保存數(shù)據(jù)的方法。

      開放。接受匯編語(yǔ)言與高級(jí)語(yǔ)言的差異,而不是去指責(zé)它如何的不好讀。經(jīng)驗(yàn)。要求你擁有任意其他編程語(yǔ)言的一點(diǎn)點(diǎn)編程經(jīng)驗(yàn)。頭腦。

      祝您編程愉快!

      先說(shuō)一點(diǎn)和實(shí)際編程關(guān)系不太大的東西。當(dāng)然,如果你迫切的想看到更實(shí)質(zhì)的內(nèi)容,完全可以先跳過(guò)這一章。

      那么,我想可能有一個(gè)問(wèn)題對(duì)于初學(xué)匯編的人來(lái)說(shuō)非常重要,那就是: 匯編語(yǔ)言到底是什么?

      匯編語(yǔ)言是一種最接近計(jì)算機(jī)核心的編碼語(yǔ)言。不同于任何高級(jí)語(yǔ)言,匯編語(yǔ)言幾乎可以完全和機(jī)器語(yǔ)言一一對(duì)應(yīng)。不錯(cuò),我們可以用機(jī)器語(yǔ)言寫程序,但現(xiàn)在除了沒(méi)有匯編程序的那些電腦之外,直接用機(jī)器語(yǔ)言寫超過(guò)1000條以上指令的人大概只能算作那些被我們成為“圣人”的犧牲者一類了。畢竟,記憶一些短小的助記符、由機(jī)器去考慮那些瑣碎的配位過(guò)程和檢查錯(cuò)誤,比記憶大量的隨計(jì)算機(jī)而改變的十六進(jìn)制代碼、可能弄錯(cuò)而沒(méi)有任何提示要強(qiáng)的多。熟練的匯編語(yǔ)言編碼員甚至可以直接從十六進(jìn)制代碼中讀出匯編語(yǔ)言的大致意思。當(dāng)然,我們有更好的工具——匯編器和反匯編器。

      簡(jiǎn)單地說(shuō),匯編語(yǔ)言就是機(jī)器語(yǔ)言的一種可以被人讀懂的形式,只不過(guò)它更容易記憶。至于宏匯編,則是包含了宏支持的匯編語(yǔ)言,這可以讓你編程的時(shí)候更專注于程序本身,而不是忙于計(jì)算和重寫代碼。

      匯編語(yǔ)言除了機(jī)器語(yǔ)言之外最接近計(jì)算機(jī)硬件的編程語(yǔ)言。由于它如此的接近計(jì)算機(jī)硬件,因此,它可以最大限度地發(fā)揮計(jì)算機(jī)硬件的性能。用匯編語(yǔ)言編寫的程序的速度通常要比高級(jí)語(yǔ)言和C/C++快很多--幾倍,幾十倍,甚至成百上千倍。當(dāng)然,解釋語(yǔ)言,如解釋型LISP,沒(méi)有采用JIT技術(shù)的Java虛機(jī)中運(yùn)行的Java等等,其程序速度更無(wú)法與匯編語(yǔ)言程序同日而語(yǔ)。

      永遠(yuǎn)不要忽視匯編語(yǔ)言的高速。實(shí)際的應(yīng)用系統(tǒng)中,我們往往會(huì)用匯編徹底重寫某些經(jīng)常調(diào)用的部分以期獲得更高的性能。應(yīng)用匯編也許不能提高你的程序的穩(wěn)定性,但至少,如果你非常小心的話,它也不會(huì)降低穩(wěn)定性;與此同時(shí),它可以大大地提高程序的運(yùn)行速度。我強(qiáng)烈建議所有的軟件產(chǎn)品在最后Release之前對(duì)整個(gè)代碼進(jìn)行Profile,并適當(dāng)?shù)赜脜R編取代部分高級(jí)語(yǔ)言代碼。至少,匯編語(yǔ)言的知識(shí)可以告訴你一些有用的東西,比如,你有多少個(gè)寄存器可以用。有時(shí),手工的優(yōu)化比編譯器的優(yōu)化更為有效,而且,你可以完全控制程序的實(shí)際行為。

      我想我在羅嗦了??傊谖覀兘Y(jié)束這一章之前,我想說(shuō),不要在優(yōu)化的時(shí)候把希望完全寄托在編譯器上——現(xiàn)實(shí)一些,再好的編譯器也不可能總是產(chǎn)生最優(yōu)的代碼。

      當(dāng)時(shí)我學(xué)過(guò)BASIC, Fortran和Pascal,寫的是一個(gè)

      對(duì)一個(gè)包含100個(gè)32bit整數(shù)的數(shù)組進(jìn)行快速排序,并且輸出出來(lái)的小程序。實(shí)際上用匯編器寫出的機(jī)器碼與在調(diào)試器中用它附帶的匯編程序?qū)懗龅臋C(jī)器碼還是有一些細(xì)微差別的,前者更大,然而卻可能更高效,因?yàn)閰R編器能夠?qū)⒋a放置到適合處理器的地方這句話假定兩個(gè)程序進(jìn)行了同等程度的優(yōu)化,一個(gè)寫的不好的匯編程序和一個(gè)寫的很好的C程序相比,匯編程序不一定更快。

      中央處理器(CPU)在微機(jī)系統(tǒng)處于“領(lǐng)導(dǎo)核心”的地位。匯編語(yǔ)言被編譯成機(jī)器語(yǔ)言之后,將由處理器來(lái)執(zhí)行。那么,首先讓我們來(lái)了解一下處理器的主要作用,這將幫助你更好地駕馭它。

      典型的處理器的主要任務(wù)包括 從內(nèi)存中獲取機(jī)器語(yǔ)言指令,譯碼,執(zhí)行

      根據(jù)指令代碼管理它自己的寄存器

      根據(jù)指令或自己的的需要修改內(nèi)存的內(nèi)容 響應(yīng)其他硬件的中斷請(qǐng)求

      一般說(shuō)來(lái),處理器擁有對(duì)整個(gè)系統(tǒng)的所有總線的控制權(quán)。對(duì)于Intel平臺(tái)而言,處理器擁有對(duì)數(shù)據(jù)、內(nèi)存和控制總線的控制權(quán),根據(jù)指令控制整個(gè)計(jì)算機(jī)的運(yùn)行。在以后的章節(jié)中,我們還將討論系統(tǒng)中同時(shí)存在多個(gè)處理器的情況。

      處理器中有一些寄存器,這些寄存器可以保存特定長(zhǎng)度的數(shù)據(jù)。某些寄存器中保存的數(shù)據(jù)對(duì)于系統(tǒng)的運(yùn)行有特殊的意義。

      新的處理器往往擁有更多、具有更大字長(zhǎng)的寄存器,提供更靈活的取指、尋址方式。寄存器

      如前所述,處理器中有一些可以保存數(shù)據(jù)的地方被稱作寄存器。

      寄存器可以被裝入數(shù)據(jù),你也可以在不同的寄存器之間移動(dòng)這些數(shù)據(jù),或者做類似的事情。基本上,像四則運(yùn)算、位運(yùn)算等這些計(jì)算操作,都主要是針對(duì)寄存器進(jìn)行的。

      首先讓我來(lái)介紹一下80386上最常用的4個(gè)通用寄存器。先瞧瞧下面的圖形,試著理解一下: 上圖中,數(shù)字表示的是位。我們可以看出,EAX是一個(gè)32-bit寄存器。同時(shí),它的低16-bit又可以通過(guò)AX這個(gè)名字來(lái)訪問(wèn);AX又被分為高、低8bit兩部分,分別由AH和AL來(lái)表示。對(duì)于EAX、AX、AH、AL的改變同時(shí)也會(huì)影響與被修改的那些寄存器的值。從而事實(shí)上只存在一個(gè)32-bit的寄存器EAX,而它可以通過(guò)4種不同的途徑訪問(wèn)。

      也許通過(guò)名字能夠更容易地理解這些寄存器之間的關(guān)系。EAX中的E的意思是“擴(kuò)展的”,整個(gè)EAX的意思是擴(kuò)展的AX。X的意思Intel沒(méi)有明示,我個(gè)人認(rèn)為表示它是一個(gè)可變的量。而AH、AL中的H和L分別代表高和低。

      為什么要這么做呢?主要由于歷史原因。早期的計(jì)算機(jī)是8位的,8086是第一個(gè)16位處理器,其通用寄存器的名字是AX,BX等等;80386是Intel推出的第一款I(lǐng)A-32系列處理器,所有的寄存器都被擴(kuò)充為32位。為了能夠兼容以前的16位應(yīng)用程序,80386不能將這些寄存器依舊命名為AX、BX,并且簡(jiǎn)單地將他們擴(kuò)充為32位——這將增加處理器在處理指令方面的成本。

      Intel微處理器的寄存器列表(在本章先只介紹80386的寄存器,MMX寄存器以及其他新一代處理器的新寄存器將在以后的章節(jié)介紹)通用寄存器

      下面介紹通用寄存器及其習(xí)慣用法。顧名思義,通用寄存器是那些你可以根據(jù)自己的意愿使用的寄存器,修改他們的值通常不會(huì)對(duì)計(jì)算機(jī)的運(yùn)行造成很大的影響。通用寄存器最多的用途是計(jì)算。EAX 32-bit寬

      通用寄存器。相對(duì)其他寄存器,在進(jìn)行運(yùn)算方面比較常用。在保護(hù)模式中,也可以作為內(nèi)存偏移指針(此時(shí),DS作為段 寄存器或選擇器)EBX 32-bit寬

      通用寄存器。通常作為內(nèi)存偏移指針使用(相對(duì)于EAX、ECX、EDX),DS是默認(rèn)的段寄存器或選擇器。在保護(hù)模式中,同樣可以起這個(gè)作用。

      ECX 32-bit寬

      通用寄存器。通常用于特定指令的計(jì)數(shù)。在保護(hù)模式中,也可以作為內(nèi)存偏移指針(此時(shí),DS作為 寄存器或段選擇器)。

      EDX 32-bit寬

      通用寄存器。在某些運(yùn)算中作為EAX的溢出寄存器(例如乘、除)。在保護(hù)模式中,也可以作為內(nèi)存偏移指針(此時(shí),DS作為段 寄存器或選擇器)。上述寄存器同EAX一樣包括對(duì)應(yīng)的16-bit和8-bit分組。用作內(nèi)存指針的特殊寄存器 ESI 32-bit寬

      通常在內(nèi)存操作指令中作為“源地址指針”使用。當(dāng)然,ESI可以被裝入任意的數(shù)值,但通常沒(méi)有人把它當(dāng)作通用寄存器來(lái)用。DS是默認(rèn)段寄存器或選擇器。EDI 32-bit寬

      通常在內(nèi)存操作指令中作為“目的地址指針”使用。當(dāng)然,EDI也可以被裝入任意的數(shù)值,但通常沒(méi)有人把它當(dāng)作通用寄存器來(lái)用。DS是默認(rèn)段寄存器或選擇器。EBP 32-bit寬

      這也是一個(gè)作為指針的寄存器。通常,它被高級(jí)語(yǔ)言編譯器用以建造‘堆棧幀’來(lái)保存函數(shù)或過(guò)程的局部變量,不過(guò),還是那句話,你可以在其中保存你希望的任何數(shù)據(jù)。SS是它的默認(rèn)段寄存器或選擇器。

      注意,這三個(gè)寄存器沒(méi)有對(duì)應(yīng)的8-bit分組。換言之,你可以通過(guò)SI、DI、BP作為別名訪問(wèn)他們的低16位,卻沒(méi)有辦法直接訪問(wèn)他們的低8位。段寄存器和選擇器

      實(shí)模式下的段寄存器到保護(hù)模式下?lián)u身一變就成了選擇器。不同的是,實(shí)模式下的“段寄存器”是16-bit的,而保護(hù)模式下的選擇器是32-bit的。

      CS 代碼段,或代碼選擇器。同IP寄存器(稍后介紹)一同指向當(dāng)前正在執(zhí)行的那個(gè)地址。處理器執(zhí)行時(shí)從這個(gè)寄存器指向的段(實(shí)模式)或內(nèi)存(保護(hù)模式)中獲取指令。除了跳轉(zhuǎn)或其他分支指令之外,你無(wú)法修改這個(gè)寄存器的內(nèi)容。

      DS 數(shù)據(jù)段,或數(shù)據(jù)選擇器。這個(gè)寄存器的低16 bit連同ESI一同指向的指令將要處理的內(nèi)存。同時(shí),所有的內(nèi)存操作指令 默認(rèn)情況下都用它指定操作段(實(shí)模式)或內(nèi)存(作為選擇器,在保護(hù)模式。這個(gè)寄存器可以被裝入任意數(shù)值,然而在這么做的時(shí)候需要小心一些。方法是,首先把數(shù)據(jù)送給AX,然后再把它從AX傳送給DS(當(dāng)然,也可以通過(guò)堆棧來(lái)做).ES 附加段,或附加選擇器。這個(gè)寄存器的低16 bit連同EDI一同指向的指令將要處理的內(nèi)存。同樣的,這個(gè)寄存器可以被裝入任意數(shù)值,方法和DS類似。

      FS F段或F選擇器(推測(cè)F可能是Free?)??梢杂眠@個(gè)寄存器作為默認(rèn)段寄存器或選擇器的一個(gè)替代品。它可以被裝入任何數(shù)值,方法和DS類似。

      GS G段或G選擇器(G的意義和F一樣,沒(méi)有在Intel的文檔中解釋)。它和FS幾乎完全一樣。SS 堆棧段或堆棧選擇器。這個(gè)寄存器的低16 bit連同ESP一同指向下一次堆棧操作(push和pop)所要使用的堆棧地址。這個(gè)寄存器也可以被裝入任意數(shù)值,你可以通過(guò)入棧和出棧操作來(lái)給他賦值,不過(guò)由于堆棧對(duì)于很多操作有很重要的意義,因此,不正確的修改有可能造成對(duì)堆棧的破壞。

      * 注意 一定不要在初學(xué)匯編的階段把這些寄存器弄混。他們非常重要,而一旦你掌握了他們,你就可以對(duì)他們做任意的操作了。段寄存器,或選擇器,在沒(méi)有指定的情況下都是使用默認(rèn)的那個(gè)。這句話在現(xiàn)在看來(lái)可能有點(diǎn)稀里糊涂,不過(guò)你很快就會(huì)在后面知道如何去做。特殊寄存器(指向到特定段或內(nèi)存的偏移量):

      EIP 這個(gè)寄存器非常的重要。這是一個(gè)32位寬的寄存器,同CS一同指向即將執(zhí)行的那條指令的地址。不能夠直接修改這個(gè)寄存器的值,修改它的唯一方法是跳轉(zhuǎn)或分支指令。(CS是默認(rèn)的段或選擇器)ESP 這個(gè)32位寄存器指向堆棧中即將被操作的那個(gè)地址。盡管可以修改它的值,然而并不提倡這樣做,因?yàn)槿绻悴皇欠浅C靼鬃约涸谧鍪裁?,那么你可能造成堆棧的破壞。?duì)于絕大多數(shù)情況而言,這對(duì)程序是致命的。(SS是默認(rèn)的段或選擇器)IP: Instruction Pointer, 指令指針 SP: Stack Pointer, 堆棧指針

      好了,上面是最基本的寄存器。下面是一些其他的寄存器,你甚至可能沒(méi)有聽(tīng)說(shuō)過(guò)它們。(都是32位寬):

      CR0, CR2, CR3(控制寄存器)。舉一個(gè)例子,CR0的作用是切換實(shí)模式和保護(hù)模式。還有其他一些寄存器,D0, D1, D2, D3, D6和D7(調(diào)試寄存器)。他們可以作為調(diào)試器的硬件支持來(lái)設(shè)置條件斷點(diǎn)。

      TR3, TR4, TR5, TR6 和 TR? 寄存器(測(cè)試寄存器)用于某些條件測(cè)試。

      最后我們要說(shuō)的是一個(gè)在程序設(shè)計(jì)中起著非常關(guān)鍵的作用的寄存器:標(biāo)志寄存器。本節(jié)中部份表格來(lái)自David Jurgens的HelpPC 2.10快速參考手冊(cè)。在此謹(jǐn)表謝意。先說(shuō)一點(diǎn)和實(shí)際編程關(guān)系不太大的東西。當(dāng)然,如果你迫切的想看到更實(shí)質(zhì)的內(nèi)容,完全可以先跳過(guò)這一章。

      那么,我想可能有一個(gè)問(wèn)題對(duì)于初學(xué)匯編的人來(lái)說(shuō)非常重要,那就是: 匯編語(yǔ)言到底是什么?

      匯編語(yǔ)言是一種最接近計(jì)算機(jī)核心的編碼語(yǔ)言。不同于任何高級(jí)語(yǔ)言,匯編語(yǔ)言幾乎可以完全和機(jī)器語(yǔ)言一一對(duì)應(yīng)。不錯(cuò),我們可以用機(jī)器語(yǔ)言寫程序,但現(xiàn)在除了沒(méi)有匯編程序的那些電腦之外,直接用機(jī)器語(yǔ)言寫超過(guò)1000條以上指令的人大概只能算作那些被我們成為“圣人”的犧牲者一類了。畢竟,記憶一些短小的助記符、由機(jī)器去考慮那些瑣碎的配位過(guò)程和檢查錯(cuò)誤,比記憶大量的隨計(jì)算機(jī)而改變的十六進(jìn)制代碼、可能弄錯(cuò)而沒(méi)有任何提示要強(qiáng)的多。熟練的匯編語(yǔ)言編碼員甚至可以直接從十六進(jìn)制代碼中讀出匯編語(yǔ)言的大致意思。當(dāng)然,我們有更好的工具——匯編器和反匯編器。

      簡(jiǎn)單地說(shuō),匯編語(yǔ)言就是機(jī)器語(yǔ)言的一種可以被人讀懂的形式,只不過(guò)它更容易記憶。至于宏匯編,則是包含了宏支持的匯編語(yǔ)言,這可以讓你編程的時(shí)候更專注于程序本身,而不是忙于計(jì)算和重寫代碼。

      匯編語(yǔ)言除了機(jī)器語(yǔ)言之外最接近計(jì)算機(jī)硬件的編程語(yǔ)言。由于它如此的接近計(jì)算機(jī)硬件,因此,它可以最大限度地發(fā)揮計(jì)算機(jī)硬件的性能。用匯編語(yǔ)言編寫的程序的速度通常要比高級(jí)語(yǔ)言和C/C++快很多--幾倍,幾十倍,甚至成百上千倍。當(dāng)然,解釋語(yǔ)言,如解釋型LISP,沒(méi)有采用JIT技術(shù)的Java虛機(jī)中運(yùn)行的Java等等,其程序速度更無(wú)法與匯編語(yǔ)言程序同日而語(yǔ)。

      永遠(yuǎn)不要忽視匯編語(yǔ)言的高速。實(shí)際的應(yīng)用系統(tǒng)中,我們往往會(huì)用匯編徹底重寫某些經(jīng)常調(diào)用的部分以期獲得更高的性能。應(yīng)用匯編也許不能提高你的程序的穩(wěn)定性,但至少,如果你非常小心的話,它也不會(huì)降低穩(wěn)定性;與此同時(shí),它可以大大地提高程序的運(yùn)行速度。我強(qiáng)烈建議所有的軟件產(chǎn)品在最后Release之前對(duì)整個(gè)代碼進(jìn)行Profile,并適當(dāng)?shù)赜脜R編取代部分高級(jí)語(yǔ)言代碼。至少,匯編語(yǔ)言的知識(shí)可以告訴你一些有用的東西,比如,你有多少個(gè)寄存器可以用。有時(shí),手工的優(yōu)化比編譯器的優(yōu)化更為有效,而且,你可以完全控制程序的實(shí)際行為。

      我想我在羅嗦了。總之,在我們結(jié)束這一章之前,我想說(shuō),不要在優(yōu)化的時(shí)候把希望完全寄托在編譯器上——現(xiàn)實(shí)一些,再好的編譯器也不可能總是產(chǎn)生最優(yōu)的代碼。

      當(dāng)時(shí)我學(xué)過(guò)BASIC, Fortran和Pascal,寫的是一個(gè)

      對(duì)一個(gè)包含100個(gè)32bit整數(shù)的數(shù)組進(jìn)行快速排序,并且輸出出來(lái)的小程序。實(shí)際上用匯編器寫出的機(jī)器碼與在調(diào)試器中用它附帶的匯編程序?qū)懗龅臋C(jī)器碼還是有一些細(xì)微差別的,前者更大,然而卻可能更高效,因?yàn)閰R編器能夠?qū)⒋a放置到適合處理器的地方這句話假定兩個(gè)程序進(jìn)行了同等程度的優(yōu)化,一個(gè)寫的不好的匯編程序和一個(gè)寫的很好的C程序相比,匯編程序不一定更快。

      在前一節(jié)中的x86基本寄存器的介紹,對(duì)于一個(gè)匯編語(yǔ)言編程人員來(lái)說(shuō)是不可或缺的?,F(xiàn)在你知道,寄存器是處理器內(nèi)部的一些保存數(shù)據(jù)的存儲(chǔ)單元。僅僅了解這些是不足以寫出一個(gè)可用的匯編語(yǔ)言程序的,但你已經(jīng)可以大致讀懂一般匯編語(yǔ)言程序了(不必驚訝,因?yàn)閰R編語(yǔ)言的祝記符和英文單詞非常接近),因?yàn)槟阋呀?jīng)了解了關(guān)于基本寄存器的絕大多數(shù)知識(shí)。在正式引入第一個(gè)匯編語(yǔ)言程序之前,我粗略地介紹一下匯編語(yǔ)言中不同進(jìn)制整數(shù)的表示方法。如果你不了解十進(jìn)制以外的其他進(jìn)制,請(qǐng)把鼠標(biāo)移動(dòng)到這里。

      匯編語(yǔ)言中的整數(shù)常量表示

      十進(jìn)制整數(shù)

      這是匯編器默認(rèn)的數(shù)制。直接用我們熟悉的表示方式表示即可。例如,1234表示十進(jìn)制的1234。不過(guò),如果你指定了使用其他數(shù)制,或者有凡事都進(jìn)行完整定義的小愛(ài)好,也可以寫成[十進(jìn)制數(shù)]d或[十進(jìn)制數(shù)]D的形式。十六進(jìn)制數(shù)

      這是匯編程序中最常用的數(shù)制,我個(gè)人比較偏愛(ài)使用十六進(jìn)制表示數(shù)據(jù),至于為什么,以后我會(huì)作說(shuō)明。十六進(jìn)制數(shù)表示為0[十六進(jìn)制數(shù)]h或0[十六進(jìn)制數(shù)]H,其中,如果十六進(jìn)制數(shù)的第一位是數(shù)字,則開頭的0可以省略。例如,7fffh, 0ffffh,等等。二進(jìn)制數(shù)

      這也是一種常用的數(shù)制。二進(jìn)制數(shù)表示為[二進(jìn)制數(shù)]b或[二進(jìn)制數(shù)]B。一般程序中用二進(jìn)制數(shù)表示掩碼(mask code)等數(shù)據(jù)非常的直觀,但需要些很長(zhǎng)的數(shù)據(jù)(4位二進(jìn)制數(shù)相當(dāng)于一位十六進(jìn)制數(shù))。例如,1010110b。八進(jìn)制數(shù)

      八進(jìn)制數(shù)現(xiàn)在已經(jīng)不是很常用了(確實(shí)還在用,一個(gè)典型的例子是Unix的文件屬性)。八進(jìn)制數(shù)的形式是[八進(jìn)制數(shù)]q、[八進(jìn)制數(shù)]Q、[八進(jìn)制數(shù)]o、[八進(jìn)制數(shù)]O。例如,777Q。需要說(shuō)明的是,這些方法是針對(duì)宏匯編器(例如,MASM、TASM、NASM)說(shuō)的,調(diào)試器默認(rèn)使用十六進(jìn)制表示整數(shù),并且不需要特別的聲明(例如,在調(diào)試器中直接用FFFF表示十進(jìn)制的65535,用10表示十進(jìn)制的16)。

      現(xiàn)在我們來(lái)寫一小段匯編程序,修改EAX、EBX、ECX、EDX的數(shù)值。我們假定程序執(zhí)行之前,寄存器中的數(shù)值是全0:

      ? X H L EAX 0000 00 00 EBX 0000 00 00 ECX 0000 00 00 EDX 0000 00 00

      正如前面提到的,EAX的高16bit是沒(méi)有辦法直接訪問(wèn)的,而AX對(duì)應(yīng)它的低16bit,AH、AL分別對(duì)應(yīng)AX的高、低8bit。

      mov eax, 012345678h mov ebx, 0abcdeffeh mov ecx, 1 mov edx, 2;將012345678h送入eax;將0abcdeffeh送入ebx;將000000001h送入ecx;將000000002h送入edx

      則執(zhí)行上述程序段之后,寄存器的內(nèi)容變?yōu)椋?/p>

      ? X H L EAX 1234 56 78 EBX abcd ef fe ECX 0000 00 01 EDX 0000 00 02

      那么,你已經(jīng)了解了mov這個(gè)指令(mov是move的縮寫)的一種用法。它可以將數(shù)送到寄存器中。我們來(lái)看看下面的代碼:

      mov eax, ebx mov ecx, edx;ebx內(nèi)容送入eax;edx內(nèi)容送入ecx

      則寄存器內(nèi)容變?yōu)椋?/p>

      ? X H L EAX abcd ef fe EBX abcd ef fe ECX 0000 00 02 EDX 0000 00 02

      我們可以看到,“move”之后,數(shù)據(jù)依然保存在原來(lái)的寄存器中。不妨把mov指令理解為“送入”,或“裝入”。

      練習(xí)題

      把寄存器恢復(fù)成都為全0的狀態(tài),然后執(zhí)行下面的代碼:

      mov eax, 0a1234h mov bx, ax mov ah, bl mov al, bh;將0a1234h送入eax;將ax的內(nèi)容送入bx;將bl內(nèi)容送入ah;將bh內(nèi)容送入al

      思考:此時(shí),EAX的內(nèi)容將是多少?[答案]

      下面我們將介紹一些指令。在介紹指令之前,我們約定:

      使用Intel文檔中的寄存器表示方式

      reg32 32-bit寄存器(表示EAX、EBX等)

      reg16 16-bit寄存器(在32位處理器中,這AX、BX等)reg8 8-bit寄存器(表示AL、BH等)imm32 32-bit立即數(shù)(可以理解為常數(shù))imm16 16-bit立即數(shù) imm8 8-bit立即數(shù)

      在寄存器中載入另一寄存器,或立即數(shù)的值:

      mov reg32,(reg32 | imm8 | imm16 | imm32)mov reg32,(reg16 | imm8 | imm16)mov reg8,(reg8 | imm8)

      例如,mov eax, 010h表示,在eax中載入00000010h。需要注意的是,如果你希望在寄存器中裝入0,則有一種更快的方法,在后面我們將提到。

      交換寄存器的內(nèi)容:

      xchg reg32, reg32 xchg reg16, reg16 xchg reg8, reg8

      例如,xchg ebx, ecx,則ebx與ecx的數(shù)值將被交換。由于系統(tǒng)提供了這個(gè)指令,因此,采用其他方法交換時(shí),速度將會(huì)較慢,并需要占用更多的存儲(chǔ)空間,編程時(shí)要避免這種情況,即,盡量利用系統(tǒng)提供的指令,因?yàn)槎鄶?shù)情況下,這意味著更小、更快的代碼,同時(shí)也杜絕了錯(cuò)誤(如果說(shuō)Intel的CPU在交換寄存器內(nèi)容的時(shí)候也會(huì)出錯(cuò),那么它就不用賣CPU了。而對(duì)于你來(lái)說(shuō),檢查一行代碼的正確性也顯然比檢查更多代碼的正確性要容易)剛才的習(xí)題的程序用下面的代碼將更有效: mov eax, 0a1234h mov bx, ax xchg ah, al;將0a1234h送入eax;將ax內(nèi)容送入bx;交換ah, al的內(nèi)容

      遞增或遞減寄存器的值:

      inc reg(8,16,32)dec reg(8,16,32)

      這兩個(gè)指令往往用于循環(huán)中對(duì)指針的操作。需要說(shuō)明的是,某些時(shí)候我們有更好的方法來(lái)處理循環(huán),例如使用loop指令,或rep前綴。這些將在后面的章節(jié)中介紹。

      將寄存器的數(shù)值與另一寄存器,或立即數(shù)的值相加,并存回此寄存器:

      add reg32, reg32 / imm(8,16,32)add reg16, reg16 / imm(8,16)add reg8, reg8 / imm(8)

      例如,add eax, edx,將eax+edx的值存入eax。減法指令和加法類似,只是將add換成sub。

      需要說(shuō)明的是,與高級(jí)語(yǔ)言不同,匯編語(yǔ)言中,如果要計(jì)算兩數(shù)之和(差、積、商,或一般地說(shuō),運(yùn)算結(jié)果),那么必然有一個(gè)寄存器被用來(lái)保存結(jié)果。在PASCAL中,我們可以用nA := nB + nC來(lái)讓nA保存nB+nC的結(jié)果,然而,匯編語(yǔ)言并不提供這種方法。如果你希望保持寄存器中的結(jié)果,需要用另外的指令。這也從另一個(gè)側(cè)面反映了“寄存器”這個(gè)名字的意義。數(shù)據(jù)只是“寄存”在那里。如果你需要保存數(shù)據(jù),那么需要將它放到內(nèi)存或其他地方。

      類似的指令還有and、or、xor(與,或,異或)等等。它們進(jìn)行的是邏輯運(yùn)算。

      我們稱add、mov、sub、and等稱為為指令助記符(這么叫是因?yàn)樗葯C(jī)器語(yǔ)言容易記憶,而起作用就是方便人記憶,某些資料中也稱為指令、操作碼、opcode[operation code]等);后面的參數(shù)成為操作數(shù),一個(gè)指令可以沒(méi)有操作數(shù),也可以有一兩個(gè)操作數(shù),通常有一個(gè)操作數(shù)的指令,這個(gè)操作數(shù)就是它的操作對(duì)象;而兩個(gè)參數(shù)的指令,前一個(gè)操作數(shù)一般是保存操作結(jié)果的地方,而后一個(gè)是附加的參數(shù)。

      我不打算在這份教程中用大量的篇幅介紹指令——很多人做得比我更好,而且指令本身并不是重點(diǎn),如果你學(xué)會(huì)了如何組織語(yǔ)句,那么只要稍加學(xué)習(xí)就能輕易掌握其他指令。更多的指令可以參考Intel提供的資料。編寫程序的時(shí)候,也可以參考一些在線參考手冊(cè)。Tech!Help和HelpPC 2.10盡管已經(jīng)很舊,但足以應(yīng)付絕大多數(shù)需要。

      聰明的讀者也許已經(jīng)發(fā)現(xiàn),使用sub eax, eax,或者xor eax, eax,可以得到與mov eax, 0類似的效果。在高級(jí)語(yǔ)言中,你大概不會(huì)選擇用a=a-a來(lái)給a賦值,因?yàn)闇y(cè)試會(huì)告訴你這么做更慢,簡(jiǎn)直就是在自找麻煩,然而在匯編語(yǔ)言中,你會(huì)得到相反的結(jié)論,多數(shù)情況下,以由快到慢的速度排列,這三條指令將是xor eax, eax、sub eax, eax和mov eax, 0。

      為什么呢?處理器在執(zhí)行指令時(shí),需要經(jīng)過(guò)幾個(gè)不同的階段:取指、譯碼、取數(shù)、執(zhí)行。

      我們反復(fù)強(qiáng)調(diào),寄存器是CPU的一部分。從寄存器取數(shù),其速度很顯然要比從內(nèi)存中取數(shù)快。那么,不難理解,xor eax, eax要比mov eax, 0更快一些。

      那么,為什么a=a-a通常要比a=0慢一些呢?這和編譯器的優(yōu)化有一定關(guān)系。多數(shù)編譯器會(huì)把a(bǔ)=a-a翻譯成類似下面的代碼(通常,高級(jí)語(yǔ)言通過(guò)ebp和偏移量來(lái)訪問(wèn)局部變量;程序中,x為a相對(duì)于本地堆的偏移量,在只包含一個(gè)32-bit整形變量的程序中,這個(gè)值通常是4):

      mov eax, dword ptr [ebp-x] sub eax, dword ptr [ebp-x] mov dword ptr [ebp-x],eax

      而把a(bǔ)=0翻譯成

      mov dword ptr [ebp-x], 0

      上面的翻譯只是示意性的,略去了很多必要的步驟,如保護(hù)寄存器內(nèi)容、恢復(fù)等等。如果你對(duì)與編譯程序的實(shí)現(xiàn)過(guò)程感興趣,可以參考相應(yīng)的書籍。多數(shù)編譯器(特別是C/C++編譯器,如Microsoft Visual C++)都提供了從源代碼到宏匯編語(yǔ)言程序的附加編譯輸出選項(xiàng)。這種情況下,你可以很方便地了解編譯程序執(zhí)行的輸出結(jié)果;如果編譯程序沒(méi)有提供這樣的功能也沒(méi)有關(guān)系,調(diào)試器會(huì)讓你看到編譯器的編譯結(jié)果。

      如果你明確地知道編譯器編譯出的結(jié)果不是最優(yōu)的,那就可以著手用匯編語(yǔ)言來(lái)重寫那段代碼了。怎么確認(rèn)是否應(yīng)該用匯編語(yǔ)言重寫呢?

      使用匯編語(yǔ)言重寫代碼之前需要確認(rèn)的幾件事情

      首先,這種優(yōu)化最好有明顯的效果。比如,一段循環(huán)中的計(jì)算,等等。一條語(yǔ)句的執(zhí)行時(shí)間是很短的,現(xiàn)在新的CPU的指令周期都在0.000000001s以下,Intel甚至已經(jīng)做出了4GHz主頻(主頻的倒數(shù)是時(shí)鐘周期)的CPU,如果你的代碼自始至終只執(zhí)行一次,并且你只是減少了幾個(gè)時(shí)鐘周期的執(zhí)行時(shí)間,那么改變將是無(wú)法讓人察覺(jué)的;很多情況下,這種“優(yōu)化”并不被提倡,盡管它確實(shí)減少了執(zhí)行時(shí)間,但為此需要付出大量的時(shí)間、人力,多數(shù)情況下得不償失(極端情況,比如你的設(shè)備內(nèi)存價(jià)格非常昂貴的時(shí)候,這種優(yōu)化也許會(huì)有意義)。其次,確認(rèn)你已經(jīng)使用了最好的算法,并且,你優(yōu)化的程序的實(shí)現(xiàn)是正確的。匯編語(yǔ)言能夠提供同樣算法的最快實(shí)現(xiàn),然而,它并不是萬(wàn)金油,更不是解決一切的靈丹妙藥。用高級(jí)語(yǔ)言實(shí)現(xiàn)一種好的算法,不一定會(huì)比匯編語(yǔ)言實(shí)現(xiàn)一種差的算法更慢。不過(guò)需要注意的是,時(shí)間、空間復(fù)雜度最小的算法不一定就是解決某一特定問(wèn)題的最佳算法。舉例說(shuō),快速排序在完全逆序的情況下等價(jià)于冒泡排序,這時(shí)其他方法就比它快。同時(shí),用匯編語(yǔ)言優(yōu)化一個(gè)不正確的算法實(shí)現(xiàn),將給調(diào)試帶來(lái)很大的麻煩。

      最后,確認(rèn)你已經(jīng)將高級(jí)語(yǔ)言編譯器的性能發(fā)揮到極致。Microsoft的編譯器在RELEASE模式和DEBUG模式會(huì)有差異相當(dāng)大的輸出,而對(duì)于GNU系列的編譯器而言,不同級(jí)別的優(yōu)化也會(huì)生成幾乎完全不同的代碼。此外,在編程時(shí)對(duì)于問(wèn)題的嚴(yán)格定義,可以極大地幫助編譯器的優(yōu)化過(guò)程。如何優(yōu)化高級(jí)語(yǔ)言代碼,使其編譯結(jié)果最優(yōu)超出了本教程的范圍,但如果你不能確認(rèn)已經(jīng)發(fā)揮了編譯器的最大效能,用匯編語(yǔ)言往往是一種更為費(fèi)力的方法。

      還有一點(diǎn)非常重要,那就是你明白自己做的是什么。好的高級(jí)語(yǔ)言編譯器有時(shí)會(huì)有一些讓人難以理解的行為,比如,重新排列指令順序,等等。如果你發(fā)現(xiàn)這種情況,那么優(yōu)化的時(shí)候就應(yīng)該小心——編譯器很可能比你擁有更多的關(guān)于處理器的知識(shí),例如,對(duì)于一個(gè)超標(biāo)量處理器,編譯器會(huì)對(duì)指令序列進(jìn)行“封包”,使他們盡可能的并行執(zhí)行;此外,宏匯編器有時(shí)會(huì)自動(dòng)插入一些nop指令,其作用是將指令湊成整數(shù)字長(zhǎng)(32-bit,對(duì)于16-bit處理器,是16-bit)。這些都是提高代碼性能的必要措施,如果你不了解處理器,那么最好不要改動(dòng)編譯器生成的代碼,因?yàn)檫@種情況下,盲目的修改往往不會(huì)得到預(yù)期的效果。

      曾經(jīng)在一份雜志上看到過(guò)有人用純機(jī)器語(yǔ)言編寫程序。不清楚到底這是不是編輯的失誤,因?yàn)橐粋€(gè)頭腦正常的人恐怕不會(huì)這么做程序,即使它不長(zhǎng)、也不復(fù)雜。首先,匯編器能夠完成某些封包操作,即使不行,也可以用db偽指令來(lái)寫指令;用匯編語(yǔ)言寫程序可以防止很多錯(cuò)誤的發(fā)生,同時(shí),它還減輕了人的負(fù)擔(dān),很顯然,“完全用機(jī)器語(yǔ)言寫程序”是完全沒(méi)有必要的,因?yàn)閰R編語(yǔ)言可以做出完全一樣的事情,并且你可以依賴它,因?yàn)橛?jì)算機(jī)不會(huì)出錯(cuò),而人總有出錯(cuò)的時(shí)候。此外,如前面所言,如果用高級(jí)語(yǔ)言實(shí)現(xiàn)程序的代價(jià)不大(例如,這段代碼在程序的整個(gè)執(zhí)行過(guò)程中只執(zhí)行一遍,并且,這一遍的執(zhí)行時(shí)間也小于一秒),那么,為什么不用高級(jí)語(yǔ)言實(shí)現(xiàn)呢?

      一些比較狂熱的編程愛(ài)好者可能不太喜歡我的這種觀點(diǎn)。比方說(shuō),他們可能希望精益求精地優(yōu)化每一字節(jié)的代碼。但多數(shù)情況下我們有更重要的事情,例如,你的算法是最優(yōu)的嗎?你已經(jīng)把程序在高級(jí)語(yǔ)言許可的范圍內(nèi)優(yōu)化到盡頭了嗎?并不是所有的人都有資格這樣說(shuō)。匯編語(yǔ)言是這樣一件東西,它足夠的強(qiáng)大,能夠控制計(jì)算機(jī),完成它能夠?qū)崿F(xiàn)的任何功能;同時(shí),因?yàn)樗膹?qiáng)大,也會(huì)提高開發(fā)成本,并且,難于維護(hù)。因此,我個(gè)人的建議是,如果在軟件開發(fā)中使用匯編語(yǔ)言,則應(yīng)在軟件接近完成的時(shí)候使用,這樣可以減少很多不必要的投入。

      第二章中,我介紹了x86系列處理器的基本寄存器。這些寄存器對(duì)于x86兼容處理器仍然是有效的,如果你偏愛(ài)AMD的CPU,那么使用這些寄存器的程序同樣也可以正常運(yùn)行。

      不過(guò)現(xiàn)在說(shuō)用匯編語(yǔ)言進(jìn)行優(yōu)化還為時(shí)尚早——不可能寫程序,而只操作這些寄存器,因?yàn)檫@樣只能完成非常簡(jiǎn)單的操作,既然是簡(jiǎn)單的操作,那可能就會(huì)讓人覺(jué)得乏味,甚至找一臺(tái)足夠快的機(jī)器窮舉它的所有結(jié)果(如果可以窮舉的話),并直接寫程序調(diào)用,因?yàn)檫@樣通常會(huì)更快。但話說(shuō)回來(lái),看完接下來(lái)的兩章——內(nèi)存和堆棧操作,你就可以獨(dú)立完成幾乎所有的任務(wù)了,配合第五章中斷、第六章子程序的知識(shí),你將知道如何駕馭處理器,并讓它為你工作。

      數(shù)字計(jì)算機(jī)內(nèi)部只支持二進(jìn)制數(shù),因?yàn)檫@樣計(jì)算機(jī) 只需要表示兩種(某些情況是3種,這一內(nèi)容超過(guò)了 這份教程的范圍,如果您感興趣,可以參考數(shù)字邏 輯電路的相關(guān)書籍)狀態(tài).對(duì)于電路而言,這表現(xiàn) 為高、低電平,或者開、關(guān),分別非常明顯,因而 工作比較穩(wěn)定;另一方面,由于只有兩種狀態(tài),設(shè) 計(jì)起來(lái)也比較簡(jiǎn)單。這樣,使用二進(jìn)制意味著低成 本、穩(wěn)定,多數(shù)情況下,這也意味著快速。

      與十進(jìn)制類似,我們可以用下面的式子來(lái)?yè)Q算出一 個(gè)任意形如am-1??a3a2a1a0 的m位r進(jìn)制數(shù)對(duì)應(yīng)的 數(shù)值n:

      程序設(shè)計(jì)中常用十六進(jìn)制和八進(jìn)制數(shù)字代替二進(jìn)制 數(shù),其原因在于,16和8是2的整次方冪,這樣,一 位十六或八進(jìn)制數(shù)可以表示整數(shù)個(gè)二進(jìn)制位。十六 進(jìn)制中,使用字母A、B、C、D、E、F表示10-15,而十六進(jìn)制或八進(jìn)制數(shù)制表示的的數(shù)字比二進(jìn)制數(shù) 更短一些。

      EAX的內(nèi)容為000A3412h.在前面的章節(jié)中,我們已經(jīng)了解了寄存器的基本使用方法。而正如結(jié)尾提到的那樣,僅僅使用寄存器做一點(diǎn)運(yùn)算是沒(méi)有什么太大意義的,畢竟它們不能保存太多的數(shù)據(jù),因此,對(duì)編程人員而言,他肯定迫切地希望訪問(wèn)內(nèi)存,以保存更多的數(shù)據(jù)。

      我將分別介紹如何在保護(hù)模式和實(shí)模式操作內(nèi)存,然而在此之前,我們先熟悉一下這兩種模式中內(nèi)存的結(jié)構(gòu)。3.1 實(shí)模式

      事實(shí)上,在實(shí)模式中,內(nèi)存比保護(hù)模式中的結(jié)構(gòu)更令人困惑。內(nèi)存被分割成段,并且,操作內(nèi)存時(shí),需要指定段和偏移量。不過(guò),理解這些概念是非常容易的事情。請(qǐng)看下面的圖:

      段寄存器這種格局是早期硬件電路限制留下的一個(gè)傷疤。地址總線在當(dāng)時(shí)有20-bit。

      然而20-bit的地址不能放到16-bit的寄存器里,這意味著有4-bit必須放到別的地方。因此,為了訪問(wèn)所有的內(nèi)存,必須使用兩個(gè)16-bit寄存器。

      這一設(shè)計(jì)上的折衷方案導(dǎo)致了今天的段-偏移量格局。最初的設(shè)計(jì)中,其中一個(gè)寄存器只有4-bit有效,然而為了簡(jiǎn)化程序,兩個(gè)寄存器都是16-bit有效,并在執(zhí)行時(shí)求出加權(quán)和來(lái)標(biāo)識(shí)20-bit地址。

      偏移量是16-bit的,因此,一個(gè)段是64KB。下面的圖可以幫助你理解20-bit地址是如何形成的:

      段-偏移量標(biāo)識(shí)的地址通常記做 段:偏移量 的形式。

      由于這樣的結(jié)構(gòu),一個(gè)內(nèi)存有多個(gè)對(duì)應(yīng)的地址。例如,0000:0010和0001:0000指的是同一內(nèi)存地址。又如,0000:1234 = 0123:0004 = 0120:0034 = 0100:0234 0001:1234 = 0124:0004 = 0120:0044 = 0100:0244

      作為負(fù)面影響之一,在段上加1相當(dāng)于在偏移量上加16,而不是一個(gè)“全新”的段。反之,在偏移量上加16也和在段上加1等價(jià)。某些時(shí)候,據(jù)此認(rèn)為段的“粒度”是16字節(jié)。

      練習(xí)題

      嘗試一下將下面的地址轉(zhuǎn)化為20bit的地址:

      2EA8:D678 26CF:8D5F 453A:CFAD 2933:31A6 5924:DCCF 694E:175A 2B3C:D218 728F:6578 68E1:A7DC 57EC:AEEA

      稍高一些的要求是,寫一個(gè)程序?qū)⒍螢锳X、偏移量為BX的地址轉(zhuǎn)換為20bit的地址,并保存于EAX中。

      [上面習(xí)題的答案]

      我們現(xiàn)在可以寫一個(gè)真正的程序了。

      經(jīng)典程序:Hello, world

      ;;;應(yīng)該得到一個(gè)29字節(jié)的.com文件

      .MODEL TINY.CODE

      CR equ 13 LF equ 10 TERMINATOR equ '$'

      ORG 100h

      Main PROC mov dx,offset sMessage mov ah,9 int 21h mov ax,4c00h int 21h Main ENDP

      sMessage: DB 'Hello, World!' DB CR,LF,TERMINATOR

      END Main;.COM文件的內(nèi)存模型是‘TINY’;代碼段開始

      ;回車;換行

      ;DOS字符串結(jié)束符

      ;代碼起始地址為CS:0100h

      ;令DS:DX指向Message;int 21h(DOS中斷)功能9;終止程序并返回AL的錯(cuò)誤代碼

      ;程序結(jié)束的同時(shí)指定入口點(diǎn)為Main

      那么,我們需要解釋很多東西。

      首先,作為匯編語(yǔ)言的抽象,C語(yǔ)言擁有“指針”這個(gè)數(shù)據(jù)類型。在匯編語(yǔ)言中,幾乎所有對(duì)內(nèi)存的操作都是由對(duì)給定地址的內(nèi)存進(jìn)行訪問(wèn)來(lái)完成的。這樣,在匯編語(yǔ)言中,絕大多數(shù)操作都要和指針產(chǎn)生或多或少的聯(lián)系。

      這里我想強(qiáng)調(diào)的是,由于這一特性,匯編語(yǔ)言中同樣會(huì)出現(xiàn)C程序中常見(jiàn)的緩沖區(qū)溢出問(wèn)題。如果你正在設(shè)計(jì)一個(gè)與安全有關(guān)的系統(tǒng),那么最好是仔細(xì)檢查你用到的每一個(gè)串,例如,它們是否一定能夠以你預(yù)期的方式結(jié)束,以及(如果使用的話)你的緩沖區(qū)是否能保證實(shí)際可能輸入的數(shù)據(jù)不被寫入到它以外的地方。作為一個(gè)匯編語(yǔ)言程序員,你有義務(wù)檢查每一行代碼的可用性。

      程序中的equ偽指令是宏匯編特有的,它的意思接近于C或Pascal中的const(常量)。多數(shù)情況下,equ偽指令并不為符號(hào)分配空間。

      此外,匯編程序執(zhí)行一項(xiàng)操作是非常繁瑣的,通常,在對(duì)與效率要求不高的地方,我們習(xí)慣使用系統(tǒng)提供的中斷服務(wù)來(lái)完成任務(wù)。例如本例中的中斷21h,它是DOS時(shí)代的中斷服務(wù),在Windows中,它也被認(rèn)為是Windows API的一部分(這一點(diǎn)可以在Microsoft的文檔中查到)。中斷可以被理解為高級(jí)語(yǔ)言中的子程序,但又不完全一樣——中斷使用系統(tǒng)棧來(lái)保存當(dāng)前的機(jī)器狀態(tài),可以由硬件發(fā)起,通過(guò)修改機(jī)器狀態(tài)字來(lái)反饋信息,等等。

      那么,最后一段通過(guò)DB存放的數(shù)據(jù)到底保存在哪里了呢?答案是緊挨著代碼存放。在匯編語(yǔ)言中,DB和普通的指令的地位是相同的。如果你的匯編程序并不知道新的助記符(例如,新的處理器上的CPUID指令),而你很清楚,那么可以用DB 機(jī)器碼的方式強(qiáng)行寫下指令。這意味著,你可以超越匯編器的能力撰寫匯編程序,然而,直接用機(jī)器碼編程是幾乎肯定是一件費(fèi)力不討好的事——匯編器廠商會(huì)經(jīng)常更新它所支持的指令集以適應(yīng)市場(chǎng)需要,而且,你可以期待你的匯編其能夠產(chǎn)生正確的代碼,因?yàn)闄C(jī)器查表是不會(huì)出錯(cuò)的。既然機(jī)器能夠幫我們做將程序轉(zhuǎn)換為代碼這件事情,那么為什么不讓它來(lái)做呢?

      細(xì)心的讀者不難發(fā)現(xiàn),在程序中我們沒(méi)有對(duì)DS進(jìn)行賦值。那么,這是否意味著程序的結(jié)果將是不可預(yù)測(cè)的呢?答案是否定的。DOS(或Windows中的MS-DOS VM)在加載.com文件的時(shí)候,會(huì)對(duì)寄存器進(jìn)行很多初始化。.com文件被限制為小于64KB,這樣,它的代碼段、數(shù)據(jù)段都被裝入同樣的數(shù)值(即,初始狀態(tài)下DS=CS)。

      也許會(huì)有人說(shuō),“嘿,這聽(tīng)起來(lái)不太好,一個(gè)64KB的程序能做得了什么呢?還有,你吹得天花亂墜的堆棧段在什么地方?”那么,我們來(lái)看看下面這個(gè)新的Hello world程序,它是一個(gè)EXE文件,在DOS實(shí)模式下運(yùn)行。

      ;;;應(yīng)該得到一個(gè)561 字節(jié)的EXE文件

      .MODEL SMALL.STACK 200h

      CR equ 13 LF equ 10 TERMINATOR equ '$'.DATA

      Message DB 'Hello, World!' DB CR,LF,TERMINATOR.CODE

      Main PROC mov ax, DGROUP mov ds, ax

      mov dx, offset Message mov ah, 9 int 21h

      mov ax, 4c00h int 21h Main ENDP END main

      ;采用“SMALL”內(nèi)存模型;堆棧段

      ;回車

      ;換行

      ;DOS字符串結(jié)束符

      ;定義數(shù)據(jù)段

      ;定義顯示串

      ;定義代碼段

      ;將數(shù)據(jù)段;加載到DS寄存器

      ;設(shè)置DX;顯示

      ;終止程序

      561字節(jié)?實(shí)現(xiàn)相同功能的程序大了這么多!為什么呢?我們看到,程序擁有了完整的堆棧段、數(shù)據(jù)段、代碼段,其中堆棧段足足占掉了512字節(jié),其余的基本上沒(méi)什么變化。

      分成多個(gè)段有什么好處呢?首先,它讓程序顯得更加清晰——你肯定更愿意看一個(gè)結(jié)構(gòu)清楚的程序,代碼中hard-coded的字符串、數(shù)據(jù)讓人覺(jué)得費(fèi)解。比如,mov dx, 0152h肯定不如mov dx, offset Message來(lái)的親切。此外,通過(guò)分段你可以使用更多的內(nèi)存,比如,代碼段騰出的空間可以做更多的事情。exe文件另一個(gè)吸引人的地方是它能夠?qū)崿F(xiàn)“重定位”?,F(xiàn)在你不需要指定程序入口點(diǎn)的地址了,因?yàn)橄到y(tǒng)會(huì)找到你的程序入口點(diǎn),而不是死板的100h。

      程序中的符號(hào)也會(huì)在系統(tǒng)加載的時(shí)候重新賦予新的地址。exe程序能夠保證你的設(shè)計(jì)容易地被實(shí)現(xiàn),不需要考慮太多的細(xì)節(jié)。

      當(dāng)然,我們的主要目的是將匯編語(yǔ)言作為高級(jí)語(yǔ)言的一個(gè)有用的補(bǔ)充。如我在開始提到的那樣,真正完全用匯編語(yǔ)言實(shí)現(xiàn)的程序不一定就好,因?yàn)樗槐阌诰S護(hù),而且,由于結(jié)構(gòu)的原因,你也不太容易確保它是正確的;匯編語(yǔ)言是一種非結(jié)構(gòu)化的語(yǔ)言,調(diào)試一個(gè)精心設(shè)計(jì)的匯編語(yǔ)言程序,即使對(duì)于一個(gè)老手來(lái)說(shuō)也不啻是一場(chǎng)惡夢(mèng),因?yàn)槟愫芸赡艿舻絼e人預(yù)設(shè)的“陷阱”中——這些技巧確實(shí)提高了代碼性能,然而你很可能不理解它,于是你把它改掉,接著就發(fā)現(xiàn)程序徹底敗掉了。使用匯編語(yǔ)言加強(qiáng)高級(jí)語(yǔ)言程序時(shí),你要做的通常只是使用匯編指令,而不必搭建完整的匯編程序。絕大多數(shù)(也是目前我遇到的全部)C/C++編譯器都支持內(nèi)嵌匯編,即在程序中使用匯編語(yǔ)言,而不必撰寫單獨(dú)的匯編語(yǔ)言程序——這可以節(jié)省你的不少精力,因?yàn)榍懊嬷v述的那些偽指令,如equ等,都可以用你熟悉的高級(jí)語(yǔ)言方式來(lái)編寫,編譯器會(huì)把它轉(zhuǎn)換為適當(dāng)?shù)男问健?/p>

      需要說(shuō)明的是,在高級(jí)語(yǔ)言中一定要注意編譯結(jié)果。編譯器會(huì)對(duì)你的匯編程序做一些修改,這不一定符合你的要求(附帶說(shuō)一句,有時(shí)編譯器會(huì)很聰明地調(diào)整指令順序來(lái)提高性能,這種情況下最好測(cè)試一下哪種寫法的效果更好),此時(shí)需要做一些更深入的修改,或者用db來(lái)強(qiáng)制編碼。

      3.2 保護(hù)模式

      實(shí)模式的東西說(shuō)得太多了,盡管我已經(jīng)刪掉了許多東西,并把一些原則性的問(wèn)題拿到了這一節(jié)討論。這樣做不是沒(méi)有理由的——保護(hù)模式才是現(xiàn)在的程序(除了操作系統(tǒng)的底層啟動(dòng)代碼)最常用的CPU模式。保護(hù)模式提供了很多令人耳目一新的功能,包括內(nèi)存保護(hù)(這是保護(hù)模式這個(gè)名字的來(lái)源)、進(jìn)程支持、更大的內(nèi)存支持,等等。

      對(duì)于一個(gè)編程人員來(lái)說(shuō),能“偷懶”是一件令人愉快的事情。這里“偷懶”是說(shuō)把“應(yīng)該”由系統(tǒng)做的事情做的事情全都交給系統(tǒng)。為什么呢?這出自一個(gè)基本思想——人總有犯錯(cuò)誤的時(shí)候,然而規(guī)則不會(huì),正確地了解規(guī)則之后,你可以期待它像你所了解的那樣執(zhí)行。對(duì)于C程序來(lái)說(shuō),你自己用C語(yǔ)言寫的實(shí)現(xiàn)相同功能的函數(shù)通常沒(méi)有系統(tǒng)提供的函數(shù)性能好(除非你用了比函數(shù)庫(kù)好很多的算法),因?yàn)橄到y(tǒng)的函數(shù)往往使用了更好的優(yōu)化,甚至可能不是用C語(yǔ)言直接編寫的。

      當(dāng)然,“偷懶”的意思是說(shuō),把那些應(yīng)該讓機(jī)器做的事情交給計(jì)算機(jī)來(lái)做,因?yàn)樗龅酶?。我們?yīng)該把精力集中到設(shè)計(jì)算法,而不是編寫源代碼本身上,因?yàn)榫幾g器幾乎只能做等價(jià)優(yōu)化,而實(shí)現(xiàn)相同功能,但使用更好算法的程序?qū)崿F(xiàn),則幾乎只能由人自己完成。

      舉個(gè)例子,這樣一個(gè)函數(shù):

      int fun(){ int a=0;register int i;for(i=0;i<1000;i++)a+=i;return a;}

      在某種編譯模式[DEBUG]下被編譯為

      push ebp mov ebp,esp sub esp,48h push ebx push esi push edi lea edi,[ebp-48h] mov ecx,12h mov eax,0CCCCCCCCh rep stos dword ptr [edi] mov dword ptr [ebp-4],0 mov dword ptr [ebp-8],0 jmp fun+31h mov eax,dword ptr [ebp-8] add eax,1 mov dword ptr [ebp-8],eax cmp dword ptr [ebp-8],3E8h jge fun+45h mov ecx,dword ptr [ebp-4] add ecx,dword ptr [ebp-8] mov dword ptr [ebp-4],ecx jmp fun+28h mov eax,dword ptr [ebp-4] pop edi pop esi pop ebx mov esp,ebp pop ebp ret;子程序入口

      ;保護(hù)現(xiàn)場(chǎng)

      ;初始化變量-調(diào)試版本特有。

      ;本質(zhì)是在堆中挖一塊地兒,存CCCCCCCC。;用串操作進(jìn)行,這將發(fā)揮Intel處理器優(yōu)勢(shì);‘a(chǎn)=0’;‘i=0’

      ;走著;i++

      ;i<1000?

      ;a+=i;

      ;return a;

      ;恢復(fù)現(xiàn)場(chǎng)

      ;返回

      而在另一種模式[RELEASE/MINSIZE]下卻被編譯為

      xor eax,eax xor ecx,ecx add eax,ecx inc ecx cmp ecx,3E8h jl fun+4 ret;a=0;;i=0;;a+=i;;i++;;i<1000?;是->繼續(xù)繼續(xù);return a

      如果讓我來(lái)寫,多半會(huì)寫成

      mov eax, 079f2ch ret;return 499500

      為什么這樣寫呢?我們看到,i是一個(gè)外界不能影響、也無(wú)法獲知的內(nèi)部狀態(tài)量。作為這段程序來(lái)說(shuō),對(duì)它的計(jì)算對(duì)于結(jié)果并沒(méi)有直接的影響——它的存在不過(guò)是方便算法描述而已。并且我們看到的,這段程序?qū)嶋H上無(wú)論執(zhí)行多少次,其結(jié)果都不會(huì)發(fā)生變化,因此,直接返回計(jì)算結(jié)果就可以了,計(jì)算是多余的(如果說(shuō)一定要算,那么應(yīng)該是編譯器在編譯過(guò)程中完成它)。

      更進(jìn)一步,我們甚至希望編譯器能夠直接把這個(gè)函數(shù)變成一個(gè)符號(hào)常量,這樣連操作堆棧的過(guò)程也省掉了。

      第三種結(jié)果屬于“等效”代碼,而不是“等價(jià)”代碼。作為用戶,很多時(shí)候是希望編譯器這樣做的,然而由于目前的技術(shù)尚不成熟,有時(shí)這種做法會(huì)造成一些問(wèn)題(gcc和g++的頂級(jí)優(yōu)化可以造成編譯出的FreeBSD內(nèi)核行為異常,這是我在FreeBSD上遇到的唯一一次軟件原因的kernel panic),因此,并不是所有的編譯器都這樣做(另一方面的原因是,如果編譯器在這方面做的太過(guò)火,例如自動(dòng)求解全部“固定”問(wèn)題,那么如果你的程序是解決固定的問(wèn)題“很大”,如求解迷宮,那么在編譯過(guò)程中你就會(huì)找錘子來(lái)砸計(jì)算機(jī)了)。然而,作為編譯器制造商,為了提高自己的產(chǎn)品的競(jìng)爭(zhēng)力,往往會(huì)使用第三種代碼來(lái)做函數(shù)庫(kù)。正如前面所提到的那樣,這種優(yōu)化往往不是編譯器本身的作用,盡管現(xiàn)代編譯程序擁有編譯執(zhí)行、循環(huán)代碼外提、無(wú)用代碼去除等諸多優(yōu)化功能,但它都不能保證程序最優(yōu)。最后一種代碼恐怕很少有編譯器能夠做到,不信你可以用自己常用的編譯器加上各種優(yōu)化選項(xiàng)試試:)

      發(fā)現(xiàn)什么了嗎?三種代碼中,對(duì)于內(nèi)存的訪問(wèn)一個(gè)比一個(gè)少。這樣做的理由是,盡可能地利用寄存器并減少對(duì)內(nèi)存的訪問(wèn),可以提高代碼性能。在某些情況下,使代碼既小又快是可能的。

      書歸正傳,我們來(lái)說(shuō)說(shuō)保護(hù)模式的內(nèi)存模型。保護(hù)模式的內(nèi)存和實(shí)模式有很多共同之處。

      毫無(wú)疑問(wèn),以'protected mode'(保護(hù)模式), 'global descriptor table'(全局描述符表), 'local descriptor table'(本地描述符表)和'selector'(選擇器)搜索,你會(huì)得到完整介紹它們的大量信息。

      保護(hù)模式與實(shí)模式的內(nèi)存類似,然而,它們之間最大的區(qū)別就是保護(hù)模式的內(nèi)存是“線性”的。

      新的計(jì)算機(jī)上,32-bit的寄存器已經(jīng)不是什么新鮮事(如果你哪天聽(tīng)說(shuō)你的CPU的寄存器不是32-bit的,那么它——簡(jiǎn)直可以肯定地說(shuō)——的字長(zhǎng)要比32-bit還要多。新的個(gè)人機(jī)上已經(jīng)開始逐步采用64-bit的CPU了),換言之,實(shí)際上段/偏移量這一格局已經(jīng)不再需要了。盡管如此,在繼續(xù)看保護(hù)模式內(nèi)存結(jié)構(gòu)時(shí),仍請(qǐng)記住段/偏移量的概念。不妨把段寄存器看作對(duì)于保護(hù)模式中的選擇器的一個(gè)模擬。選擇器是全局描述符表(Global Descriptor Table, GDT)或本地描述符表(Local Descriptor Table, LDT)的一個(gè)指針。

      如圖所示,GDT和LDT的每一個(gè)項(xiàng)目都描述一塊內(nèi)存。例如,一個(gè)項(xiàng)目中包含了某塊被描述的內(nèi)存的物理的基地址、長(zhǎng)度,以及其他一些相關(guān)信息。

      保護(hù)模式是一個(gè)非常重要的概念,同時(shí)也是目前撰寫應(yīng)用程序時(shí),最常用的CPU模式(運(yùn)行在新的計(jì)算機(jī)上的操作系統(tǒng)很少有在實(shí)模式下運(yùn)行的)。

      為什么叫保護(hù)模式呢?它“保護(hù)”了什么?答案是進(jìn)程的內(nèi)存。保護(hù)模式的主要目的在于允許多個(gè)進(jìn)程同時(shí)運(yùn)行,并保護(hù)它們的內(nèi)存不受其他進(jìn)程的侵犯。這有點(diǎn)類似于C++中的機(jī)制,然而它的強(qiáng)制力要大得多。如果你的進(jìn)程在保護(hù)模式下以不恰當(dāng)?shù)姆绞皆L問(wèn)了內(nèi)存(例如,寫了“只讀”內(nèi)存,或讀了不可讀的內(nèi)存,等等),那么CPU就會(huì)產(chǎn)生一個(gè)異常。這個(gè)異常將交給操作系統(tǒng)處理,而這種處理,假如你的程序沒(méi)有特別說(shuō)明操作系統(tǒng)該如何處理的話,一般就是殺掉做錯(cuò)了事情的進(jìn)程。

      我像這樣的對(duì)話框大家一定非常熟悉(臨時(shí)寫了一個(gè)程序故意造成的錯(cuò)誤):

      好的,只是一個(gè)程序崩潰了,而操作系統(tǒng)的其他進(jìn)程照常運(yùn)行(同樣的程序在DOS中幾乎是板上釘釘?shù)乃罊C(jī),因?yàn)镹ULL指針的位置恰好是中斷向量表),你甚至還可以調(diào)試它。

      保護(hù)模式還有其他很多好處,在此就不一一贅述了。實(shí)模式和保護(hù)模式之間的切換問(wèn)題我打算放在后面的“高級(jí)技巧”一章來(lái)講,因?yàn)槎鄶?shù)程序并不涉及這個(gè)。

      了解了內(nèi)存的格局,我們就可以進(jìn)入下一節(jié)——操作內(nèi)存了。

      3.3 操作內(nèi)存

      前兩節(jié)中,我們介紹了實(shí)模式和保護(hù)模式中使用的不同的內(nèi)存格局?,F(xiàn)在開始解釋如何使用這些知識(shí)。

      回憶一下前面我們說(shuō)過(guò)的,寄存器可以用作內(nèi)存指針。現(xiàn)在,是他們發(fā)揮作用的時(shí)候了。

      可以將內(nèi)存想象為一個(gè)順序的字節(jié)流。使用指針,可以任意地操作(讀寫)內(nèi)存。

      現(xiàn)在我們需要一些其他的指令格式來(lái)描述對(duì)于內(nèi)存的操作。操作內(nèi)存時(shí),首先需要的就是它的地址。

      讓我們來(lái)看看下面的代碼:

      mov ax,[0]

      方括號(hào)表示,里面的表達(dá)式指定的不是立即數(shù),而是偏移量。在實(shí)模式中,DS:0中的那個(gè)字(16-bit長(zhǎng))將被裝入AX。

      然而0是一個(gè)常數(shù),如果需要在運(yùn)行的時(shí)候加以改變,就需要一些特殊的技巧,比如程序自修改。匯編支持這個(gè)特性,然而我個(gè)人并不推薦這種方法——自修改大大降低程序的可讀性,并且還降低穩(wěn)定性,性能還不一定好。我們需要另外的技術(shù)。

      mov bx,0 mov ax,[bx]

      看起來(lái)舒服了一些,不是嗎?BX寄存器的內(nèi)容可以隨時(shí)更改,而不需要用冗長(zhǎng)的代碼去修改自身,更不用擔(dān)心由此帶來(lái)的不穩(wěn)定問(wèn)題。

      同樣的,mov指令也可以把數(shù)據(jù)保存到內(nèi)存中:

      mov [0],ax

      在存儲(chǔ)器與寄存器之間交換數(shù)據(jù)應(yīng)該足夠清楚了。

      有些時(shí)候我們會(huì)需要操作符來(lái)描述內(nèi)存數(shù)據(jù)的寬度: 操作符 意義

      byte ptr 一個(gè)字節(jié)(8-bit, 1 byte)word ptr 一個(gè)字(16-bit)dword ptr 一個(gè)雙字(32-bit)

      例如,在DS:100h處保存1234h,以字存放:

      mov word ptr [100h],01234h

      于是我們將mov指令擴(kuò)展為:

      mov reg(8,16,32), mem(8,16,32)mov mem(8,16,32), reg(8,16,32)mov mem(8,16,32), imm(8,16,32)

      需要說(shuō)明的是,加減同樣也可以在[]中使用,例如:

      mov ax,[bx+10] mov ax,[bx+si] mov ax,es:[di+bp]

      等等。我們看到,對(duì)于內(nèi)存的操作,即使使用MOV指令,也有許多種可能的方式。下一節(jié)中,我們將介紹如何操作串。

      感謝 網(wǎng)友 水杉 指出此答案中的一處錯(cuò)誤。感謝 Heallven 指出.COM程序?qū)嵗幾g失敗的問(wèn)題

      我們前面已經(jīng)提到,內(nèi)存可以和寄存器交換數(shù)據(jù),也可以被賦予立即數(shù)。問(wèn)題是,如果我們需要把內(nèi)存的某部分內(nèi)容復(fù)制到另一個(gè)地址,又怎么做呢?

      設(shè)想將DS:SI處的連續(xù)512字節(jié)內(nèi)容復(fù)制到ES:DI(先不考慮可能的重疊)。也許會(huì)有人寫出這樣的代碼:

      NextByte: mov cx,512 mov al,ds:[si] mov es:[di],al inc si inc di loop NextByte;循環(huán)次數(shù)

      我不喜歡上面的代碼。它的確能達(dá)到作用,但是,效率不好。如果你是在做優(yōu)化,那么寫出這樣的代碼意味著賠了夫人又折兵。

      Intel的CPU的強(qiáng)項(xiàng)是串操作。所謂串操作就是由CPU去完成某一數(shù)量的、重復(fù)的內(nèi)存操作。需要說(shuō)明的是,我們常用的KMP算法(用于匹配字符串中的模式)的改進(jìn)——Boyer算法,由于沒(méi)有利用串操作,因此在Intel的CPU上的效率并非最優(yōu)。好的編譯器往往可以利用Intel CPU的這一特性優(yōu)化代碼,然而,并非所有的時(shí)候它都能產(chǎn)生最好的代碼。某些指令可以加上REP前綴(repeat, 反復(fù)之意),這些指令通常被叫做串操作指令。舉例來(lái)說(shuō),STOSD指令將EAX的內(nèi)容保存到ES:DI,同時(shí)在DI上加或減四。類似的,STOSB和STOSW分別作1字節(jié)或1字的上述操作,在DI上加或減的數(shù)是1或2。

      計(jì)算機(jī)語(yǔ)言通常是不允許二義性的。為什么我要說(shuō)“加或減”呢?沒(méi)錯(cuò),孤立地看STOS?指令,并不能知道到底是加還是減,因?yàn)檫@取決于“方向”標(biāo)志(DF, Direction Flag)。如果DF被復(fù)位,則加;反之則減。

      置位、復(fù)位的指令分別是STD和CLD。

      當(dāng)然,REP只是幾種可用前綴之一。常用的還包括REPNE,這個(gè)前綴通常被用來(lái)比較兩個(gè)串,或搜索某個(gè)特定字符(字、雙字)。REPZ、REPE、REPNZ也是非常常用的指令前綴,分別代表ZF(Zero Flag)在不同狀態(tài)時(shí)重復(fù)執(zhí)行。下面說(shuō)三個(gè)可以復(fù)制數(shù)據(jù)的指令: 助記符 意義

      movsb 將DS:SI的一字節(jié)復(fù)制到ES:DI,之后SI++、DI++ movsw 將DS:SI的一字節(jié)復(fù)制到ES:DI,之后SI+=

      2、DI+=2 movsd 將DS:SI的一字節(jié)復(fù)制到ES:DI,之后SI+=

      4、DI+=4 于是上面的程序改寫為 cld mov cx, 128 rep movsd;復(fù)位DF;512/4 = 128,共128個(gè)雙字;行動(dòng)!

      第一句cld很多時(shí)候是多余的,因?yàn)閷?shí)際寫程序時(shí),很少會(huì)出現(xiàn)置DF的情況。不過(guò)在正式?jīng)Q定刪掉它之前,建議你仔細(xì)地調(diào)試自己的程序,并確認(rèn)每一個(gè)能夠走到這里的路徑中都不會(huì)將DF置位。

      錯(cuò)誤(非預(yù)期的)的DF是危險(xiǎn)的。它很可能斷送掉你的程序,因?yàn)檫@直接造成緩沖區(qū)溢出問(wèn)題。

      什么是緩沖區(qū)溢出呢?緩沖區(qū)溢出分為兩類,一類是寫入緩沖區(qū)以外的內(nèi)容,一類是讀取緩沖區(qū)以外的內(nèi)容。后一種往往更隱蔽,但隨便哪一個(gè)都有可能斷送掉你的程序。

      緩沖區(qū)溢出對(duì)于一個(gè)網(wǎng)絡(luò)服務(wù)來(lái)說(shuō)很可能更加危險(xiǎn)。懷有惡意的用戶能夠利用它執(zhí)行自己希望的指令。服務(wù)通常擁有更高的特權(quán),而這很可能會(huì)造成特權(quán)提升;即使不能提升攻擊者擁有的特權(quán),他也可以利用這種問(wèn)題使服務(wù)崩潰,從而形成一次成功的DoS(拒絕服務(wù))攻擊。每年CERT的安全公告中,都有6成左右的問(wèn)題是由于緩沖區(qū)溢出造成的。

      在使用匯編語(yǔ)言,或C語(yǔ)言編寫程序時(shí),很容易在無(wú)意中引入緩沖區(qū)溢出。然而并不是所有的語(yǔ)言都會(huì)引入緩沖區(qū)溢出問(wèn)題,Java和C#,由于沒(méi)有指針,并且緩沖區(qū)采取動(dòng)態(tài)分配的方式,有效地消除了造成緩沖區(qū)溢出的土壤。

      匯編語(yǔ)言中,由于REP*前綴都用CX作為計(jì)數(shù)器,因此情況會(huì)好一些(當(dāng)然,有時(shí)也會(huì)更糟糕,因?yàn)橛捎贑X的限制,很可能使原本可能改變程序行為的緩沖區(qū)溢出的范圍縮小,從而更為隱蔽)。避免緩沖區(qū)溢出的一個(gè)主要方法就是仔細(xì)檢查,這包括兩方面:設(shè)置合理的緩沖區(qū)大小,和根據(jù)大小編寫程序。除此之外,非常重要的一點(diǎn)就是,在匯編語(yǔ)言這個(gè)級(jí)別寫程序,你肯定希望去掉所有的無(wú)用指令,然而再去掉之前,一定要進(jìn)行嚴(yán)格的測(cè)試;更進(jìn)一步,如果能加上注釋,并通過(guò)善用宏來(lái)做調(diào)試模式檢查,往往能夠達(dá)到更好的效果。

      正如3.2節(jié)提到到的那樣,保護(hù)模式中,你可以使用32位的線性地址,這意味著直接訪問(wèn)4GB的內(nèi)存。由于這個(gè)原因,選擇器不用像實(shí)模式中段寄存器那樣頻繁地修改。順便提一句,這份教程中所說(shuō)的保護(hù)模式指的是386以上的保護(hù)模式,或者,Microsoft通常稱為“增強(qiáng)模式”的那種。

      在為選擇器裝入數(shù)值的時(shí)候一定要非常小心。錯(cuò)誤的數(shù)值往往會(huì)導(dǎo)致無(wú)效頁(yè)面錯(cuò)誤(在Windows中經(jīng)常出現(xiàn):)。同時(shí),也不要忘記你的地址是32位的,這也是保護(hù)模式的主要優(yōu)勢(shì)之一。

      現(xiàn)在假設(shè)存在一個(gè)描述符描述從物理的0:0開始的全部?jī)?nèi)存,并已經(jīng)加載進(jìn)DS(數(shù)據(jù)選擇器),則我們可以通過(guò)下面的程序來(lái)操作VGA的VRAM: mov edi,0a0000h mov byte ptr [edi],0fh;VGA顯存的偏移量;將第一字節(jié)改為0fh 很明顯,這比實(shí)模式下的程序 mov ax,0a000h mov ds,ax mov di,0 mov [di],0fh;AX-> VGA段地址;將AX值載入DS;DI清零

      ;修改第一字節(jié) 看上去要舒服一些。

      到目前為止,您已經(jīng)了解了基本的寄存器以及內(nèi)存的操作知識(shí)。事實(shí)上,您現(xiàn)在已經(jīng)可以寫出很多的底層數(shù)據(jù)處理程序了。

      下面我來(lái)說(shuō)說(shuō)堆棧。堆棧實(shí)在不是一個(gè)讓人陌生的數(shù)據(jù)結(jié)構(gòu),它是一個(gè)先進(jìn)后出(FILO)的線性表,能夠幫助你完成很多很好的工作。

      先進(jìn)后出(FILO)是這樣一個(gè)概念:最后放進(jìn)表中 的數(shù)據(jù)在取出時(shí)最先出來(lái)。先進(jìn)后出(FILO)和先 進(jìn)先出(FIFO, 和先進(jìn)后出的規(guī)則相反),以及隨 機(jī)存取是最主要的三種存儲(chǔ)器訪問(wèn)方式。

      對(duì)于堆棧而言,最后放入的數(shù)據(jù)在取出時(shí)最先出

      現(xiàn)。對(duì)于子程序調(diào)用,特別是遞歸調(diào)用來(lái)說(shuō),這 是一個(gè)非常有用的特性。

      一個(gè)鐵桿的匯編語(yǔ)言程序員有時(shí)會(huì)發(fā)現(xiàn)系統(tǒng)提供的寄存器不夠。很顯然,你可以使用普通的內(nèi)存操作來(lái)完成這個(gè)工作,就像C/C++中所做的那樣。

      沒(méi)錯(cuò),沒(méi)錯(cuò),可是,如果數(shù)據(jù)段(數(shù)據(jù)選擇器)以及偏移量發(fā)生變化怎么辦?更進(jìn)一步,如果希望保存某些在這種操作中可能受到影響的寄存器的時(shí)候怎么辦?確實(shí),你可以把他們也存到自己的那片內(nèi)存中,自己實(shí)現(xiàn)堆棧。

      太麻煩了??

      既然系統(tǒng)提供了堆棧,并且性能比自己寫一份更好,那么為什么不直接加以利用呢 系統(tǒng)堆棧不僅僅是一段內(nèi)存。由于CPU對(duì)它實(shí)施管理,因此你不需要考慮堆棧指針的修正問(wèn)題。可以把寄存器內(nèi)容,甚至一個(gè)立即數(shù)直接放到堆棧里,并在需要的時(shí)候?qū)⑵淙〕?。同時(shí),系統(tǒng)并不要求取出的數(shù)據(jù)仍然回到原來(lái)的位置。

      除了顯式地操作堆棧(使用PUSH和POP指令)之外,很多指令也需要使用堆棧,如INT、CALL、LEAVE、RET、RETF、IRET等等。配對(duì)使用上述指令并不會(huì)造成什么問(wèn)題,然而,如果你打算使用LEAVE、RET、RETF、IRET這樣的指令實(shí)現(xiàn)跳轉(zhuǎn)(比JMP更為麻煩,然而有時(shí),例如在加密軟件中,或者需要修改調(diào)用者狀態(tài)時(shí),這是必要的)的話,那么我的建議是,先搞清楚它們做的到底是什么,并且,精確地了解自己要做什么。正如前面所說(shuō)的,有兩個(gè)顯式地操作堆棧的指令:

      助記符 功能

      PUSH 將操作數(shù)存入堆棧,同時(shí)修正堆棧指針

      POP 將棧頂內(nèi)容取出并存到目的操作數(shù)中,同時(shí)修正堆棧指針 我們現(xiàn)在來(lái)看看堆棧的操作。執(zhí)行之前 執(zhí)行代碼 mov ax,1234h mov bx,10 push ax push bx 之后,堆棧的狀態(tài)為 之后,再執(zhí)行 pop dx pop cx 堆棧的狀態(tài)成為

      當(dāng)然,dx、cx中的內(nèi)容將分別是000ah和1234h。

      注意,最后這張圖中,我沒(méi)有抹去1234h和000ah,因?yàn)镻OP指令并不從內(nèi)存中抹去數(shù)值。不過(guò)盡管如此,我個(gè)人仍然非常反對(duì)繼續(xù)使用這兩個(gè)數(shù)(你可以通過(guò)修改SP來(lái)再次POP它們),然而這很容易導(dǎo)致錯(cuò)誤。

      一定要保證堆棧段有足夠的空間來(lái)執(zhí)行中斷,以及其他一些隱式的堆棧操作。僅僅統(tǒng)計(jì)PUSH的數(shù)量并據(jù)此計(jì)算堆棧所需的大小很可能造成問(wèn)題。CALL指令將返回地址放到堆棧中。絕大多數(shù)C/C++編譯器提供了“堆棧檢查”這個(gè)編譯選項(xiàng),其作用在于保證C程序段中沒(méi)有忘記對(duì)堆棧中多余的數(shù)據(jù)進(jìn)行清理,從而保證返回地址有效。本章小結(jié)

      本章中介紹了內(nèi)存的操作的一些入門知識(shí)。限于篇幅,我不打算展開細(xì)講指令,如cmps*,lods*,stos*,等等。這些指令的用法和前面介紹的movs*基本一樣,只是有不同的作用而已。

      4.0 利用子程序與中斷

      已經(jīng)掌握了匯編語(yǔ)言?沒(méi)錯(cuò),你現(xiàn)在已經(jīng)可以去破譯別人代碼中的秘密。然而,我們還有一件重要的東西沒(méi)有提到,那就是自程序和中斷。這兩件東西是如此的重要,以至于你的程序幾乎不可能離開它們。

      4.1 子程序

      在高級(jí)語(yǔ)言中我們經(jīng)常要用到子程序。高級(jí)語(yǔ)言中,子程序是如此的神奇,我們能夠定義和主程序,或其他子程序一樣的變量名,而訪問(wèn)不同的變量,并且,還不和程序的其他部分相沖突。

      然而遺憾的是,這種“優(yōu)勢(shì)”在匯編語(yǔ)言中是不存在的。

      匯編語(yǔ)言并不注重如何減輕程序員的負(fù)擔(dān);相反,匯編語(yǔ)言依賴程序員的良好設(shè)計(jì),以期發(fā)揮CPU的最佳性能。匯編語(yǔ)言不是結(jié)構(gòu)化的語(yǔ)言,因此,它不提供直接的“局部變量”。如果需要“局部變量”,只能通過(guò)堆或棧自行實(shí)現(xiàn)。

      從這個(gè)意義上講,匯編語(yǔ)言的子程序更像GWBASIC中的GOSUB調(diào)用的那些“子程序”。所有的“變量”(本質(zhì)上,屬于進(jìn)程的內(nèi)存和寄存器)為整個(gè)程序所共享,高級(jí)語(yǔ)言編譯器所做的,將局部變量放到堆或棧中的操作,只能自行實(shí)現(xiàn)。

      參數(shù)的傳遞是靠寄存器和堆棧來(lái)完成的。高級(jí)語(yǔ)言中,子程序(函數(shù)、過(guò)程,或類似概念的東西)依賴于堆和棧來(lái)傳遞。

      讓我們來(lái)簡(jiǎn)單地分析一下一般高級(jí)語(yǔ)言的子程序的執(zhí)行過(guò)程。無(wú)論C、C++、BASIC、Pascal,這一部分基本都是一致的。

      調(diào)用者將子程序執(zhí)行完成時(shí)應(yīng)返回的地址、參數(shù)壓入堆棧

      子程序使用BP指針+偏移量對(duì)棧中的參數(shù)尋址,并取出、完成操作

      子程序使用RET或RETF指令返回。此時(shí),CPU將IP置為堆棧中保存的地址,并繼續(xù)予以執(zhí)行

      毋庸置疑,堆棧在整個(gè)過(guò)程中發(fā)揮著非常重要的作用。不過(guò),本質(zhì)上對(duì)子程序最重要的還是返回地址。如果子程序不知道這個(gè)地址,那么系統(tǒng)將會(huì)崩潰。

      調(diào)用子程序的指令是CALL,對(duì)應(yīng)的返回指令是RET。此外,還有一組指令,即ENTER和LEAVE,它們可以幫助進(jìn)行堆棧的維護(hù)。

      CALL指令的參數(shù)是被調(diào)用子程序的地址。使用宏匯編的時(shí)候,這通常是一個(gè)標(biāo)號(hào)。CALL和RET,以及ENTER和LEAVE配對(duì),可以實(shí)現(xiàn)對(duì)于堆棧的自動(dòng)操作,而不需要程序員進(jìn)行PUSH/POP,以及跳轉(zhuǎn)的操作,從而提高了效率。

      作為一個(gè)編譯器的實(shí)現(xiàn)實(shí)例,我用Visual C++編譯了一段C++程序代碼,這段匯編代碼是使用特定的編譯選項(xiàng)得到的結(jié)果,正常的RELEASE代碼會(huì)比它精簡(jiǎn)得多。包含源代碼的部分反匯編結(jié)果如下(取自Visual C++調(diào)試器的運(yùn)行結(jié)果,我刪除了10條int 3指令,并加上了一些注釋,除此之外,沒(méi)有做任何修改): 1: int myTransform(int nInput){ 00401000 push ebp;保護(hù)現(xiàn)場(chǎng)原先的EBP指針 00401001 mov ebp,esp 2: return(nInput*2 + 3)% 7;00401003 mov eax,dword ptr [nInput];取參數(shù)

      00401006 lea eax,[eax+eax+3];LEA比ADD加法更快

      0040100A cdq;DWORD->QWORD(擴(kuò)展字長(zhǎng))0040100B mov ecx,7;除數(shù) 00401010 idiv eax,ecx;除

      00401012 mov eax,edx;商->eax(eax中保存返回值)3: } 00401014 pop ebp;恢復(fù)現(xiàn)場(chǎng)的ebp指針

      00401015 ret;返回

      ;此處刪除10條int 3指令,它們是方便調(diào)試用的,并不影響程序行為。4: 5: int main(int argc, char* argv[])6: { 00401020 push ebp;保護(hù)現(xiàn)場(chǎng)原先的EBP指針 00401021 mov ebp,esp 00401023 sub esp,10h;為取argc, argv修正堆棧指針。7: int a[3];8: for(register int i=0;i<3;i++){ 00401026 mov dword ptr [i],0;0->i 0040102D jmp main+18h(00401038);判斷循環(huán)條件 0040102F mov eax,dword ptr [i];i->eax 00401032 add eax,1;eax ++ 00401035 mov dword ptr [i],eax;eax->i 00401038 cmp dword ptr [i],3;循環(huán)條件: i與3比較

      0040103C jge main+33h(00401053);如果不符合條件,則應(yīng)結(jié)束循環(huán) 9: a[i] = myTransform(i);0040103E mov ecx,dword ptr [i];i->ecx 00401041 push ecx;ecx(i)-> 堆棧 00401042 call myTransform(00401000);調(diào)用myTransform 00401047 add esp,4;esp+=4: 在堆中的新單元;準(zhǔn)備存放返回結(jié)果 0040104A mov edx,dword ptr [i];i->edx 0040104D mov dword ptr a[edx*4],eax;將eax(myTransform返回值);放回a[i] 10: } 00401051 jmp main+0Fh(0040102f);計(jì)算i++,并繼續(xù)循環(huán) 11: return 0;00401053 xor eax,eax;返回值應(yīng)該是0 12: } 00401055 mov esp,ebp;恢復(fù)堆棧指針 00401057 pop ebp;恢復(fù)BP 00401058 ret;返回調(diào)用者(C++運(yùn)行環(huán)境)上述代碼確實(shí)做了一些無(wú)用功,當(dāng)然,這是因?yàn)榫幾g器沒(méi)有對(duì)這段代碼進(jìn)行優(yōu)化。讓我們來(lái)關(guān)注一下這段代碼中,是如何調(diào)用子程序的。不考慮myTransform這個(gè)函數(shù)實(shí)際進(jìn)行的數(shù)值運(yùn)算,最讓我感興趣的是這一行代碼:

      00401003 mov eax,dword ptr [nInput];取參數(shù) 這里nInput是一個(gè)簡(jiǎn)簡(jiǎn)單單的變量符號(hào)嗎?Visual C++的調(diào)試器顯然不能告訴我們答案——它的設(shè)計(jì)目標(biāo)是為了方便程序調(diào)試,而不是向你揭示編譯器生成的代碼的實(shí)際構(gòu)造。我用另外一個(gè)反匯編器得到的結(jié)果是:

      00401003 mov eax,dword ptr [ebp+8];取參數(shù)

      這和我們?cè)趍ain()中看到的壓棧順序是完全吻合的(注意,程序運(yùn)行到這個(gè)地方的時(shí)候,EBP=ESP)。main()最終將i的值通過(guò)堆棧傳遞給了myTransform()。

      剖析上面的程序只是說(shuō)明了我前面所提到的子程序的一部分用法。對(duì)于匯編語(yǔ)言來(lái)說(shuō),完全沒(méi)有必要拘泥于結(jié)構(gòu)化程序設(shè)計(jì)的框架(在今天,使用匯編的主要目的在于提高執(zhí)行效率,而不是方便程序的維護(hù)和調(diào)試,因?yàn)閰R編不可能在這一點(diǎn)上做得比C++更好)。考慮下面的程序:

      void myTransform1(int nCount, char* sBytes){ for(register int i=1;i

      void myTransform2(int nCount, char* sBytes){ for(register int i=0;i

      很容易看出,這兩個(gè)函數(shù)包含了公共部分,即

      for(i=0;i

      目前,還沒(méi)有編譯器能夠做到將這兩部分合并。依然沿用剛才的編譯選項(xiàng),得到的反匯編結(jié)果是(同樣地刪除了int 3):

      1: void myTransform1(int nCount, char* sBytes){ 00401000 push ebp 00401001 mov ebp,esp 00401003 push ecx 2: for(register int i=1;i

      非常明顯地,0040103d-0040106e和00401074-004010a5這兩段代碼存在少量的差別,但很顯然只是對(duì)寄存器的偏好不同(編譯器在優(yōu)化時(shí),這可能會(huì)減少堆棧操作,從而提高性能,但在這里只是使用了不同的寄存器而已)

      對(duì)代碼進(jìn)行合并的好處是非常明顯的。新的操作系統(tǒng)往往使用頁(yè)式內(nèi)存管理。當(dāng)內(nèi)存不足時(shí),程序往往會(huì)頻繁引發(fā)頁(yè)面失效(Page faults),從而引發(fā)操作系統(tǒng)從磁盤中讀取一些東西。磁盤的速度趕不上內(nèi)存的速度,因此,這一行為將導(dǎo)致性能的下降。通過(guò)合并一部分代碼,可以減少程序的大小,這意味著減少頁(yè)面失效的可能性,從而軟件的性能會(huì)有所提高 當(dāng)然,這樣做的代價(jià)也不算低——你的程序?qū)⒆兊秒y懂,并且難于維護(hù)。因此,再進(jìn)行這樣的優(yōu)化之前,一定要注意:

      優(yōu)化前的程序必須是正確的。如果你不能確保這一點(diǎn),那么這種優(yōu)化必將給你的調(diào)試帶來(lái)極大的麻煩。

      優(yōu)化前的程序?qū)崿F(xiàn)最好是最優(yōu)的。仔細(xì)檢查你的設(shè)計(jì),看看是否已經(jīng)使用了最合適(即,對(duì)于此程序而言最優(yōu))的算法,并且已經(jīng)在高級(jí)語(yǔ)言許可的范圍內(nèi)進(jìn)行了最好的實(shí)現(xiàn)。優(yōu)化最好能夠非常有效地減少程序大小(例如,如果只是減少十幾個(gè)字節(jié),恐怕就沒(méi)什么必要了),或非常有效地提高程序的運(yùn)行速度(如果代碼只是運(yùn)行一次,并且只是節(jié)省幾個(gè)時(shí)鐘周期,那么在多數(shù)場(chǎng)合都沒(méi)有意義)。否則,這種優(yōu)化將得不償失。4.2 中斷

      中斷應(yīng)該說(shuō)是一個(gè)陳舊的話題。在新的系統(tǒng)中,它的作用正在逐漸被削弱,而變成操作系統(tǒng)專用的東西。并不是所有的計(jì)算機(jī)系統(tǒng)都提供中斷,然而在x86系統(tǒng)中,它的作用是不可替代的。

      中斷實(shí)際上是一類特殊的子程序。它通常由系統(tǒng)調(diào)用,以響應(yīng)突發(fā)事件。

      例如,進(jìn)行磁盤操作時(shí),為了提高性能,可能會(huì)使用DMA方式進(jìn)行操作。CPU向DMA控制器發(fā)出指令,要求外設(shè)和內(nèi)存直接交換數(shù)據(jù),而不通過(guò)CPU。然后,CPU轉(zhuǎn)去進(jìn)行起他的操作;當(dāng)數(shù)據(jù)交換結(jié)束時(shí),CPU可能需要進(jìn)行一些后續(xù)操作,但此時(shí)它如何才能知道DMA已經(jīng)完成了操作呢?

      很顯然不是依靠CPU去查詢狀態(tài)——這樣DMA的優(yōu)勢(shì)就不明顯了。為了盡可能地利用DMA的優(yōu)勢(shì),在完成DMA操作的時(shí)候,DMA會(huì)告訴CPU“這事兒我辦完了”,然后CPU會(huì)根據(jù)需要進(jìn)行處理。

      這種處理可能很復(fù)雜,需要若干條指令來(lái)完成。子程序是一個(gè)不錯(cuò)的主意,不過(guò),CALL指令需要指定地址,讓外設(shè)強(qiáng)迫CPU執(zhí)行一條CALL指令也違背了CPU作為核心控制單元的設(shè)計(jì)初衷??紤]到這些,在x86系統(tǒng)中引入了中斷向量的概念。

      中斷向量表是保存在系統(tǒng)數(shù)據(jù)區(qū)(實(shí)模式下,是0:0開始的一段區(qū)域)的一組指針。這組指針指向每一個(gè)中斷服務(wù)程序的地址。整個(gè)中斷向量表的結(jié)構(gòu)是一個(gè)線性表。

      每一個(gè)中斷服務(wù)有自己的唯一的編號(hào),我們通常稱之為中斷號(hào)。每一個(gè)中斷號(hào)對(duì)應(yīng)中斷向量表中的一項(xiàng),也就是一個(gè)中斷向量。外設(shè)向CPU發(fā)出中斷請(qǐng)求,而CPU自己將根據(jù)當(dāng)前的程序狀態(tài)決定是否中斷當(dāng)前程序并調(diào)用相應(yīng)的中斷服務(wù)。不難根據(jù)造成中斷的原因?qū)⒅袛喾譃閮深悾河布袛嗪蛙浖袛?。硬件中斷有很多分類方法,如根?jù)是否可以屏蔽分類、根據(jù)優(yōu)先級(jí)高低分類,等等??紤]到這些分類并不一定科學(xué),并且對(duì)于我們介紹中斷的使用沒(méi)有太大的幫助,因此我并不打算太詳細(xì)地介紹它(在本教程的高級(jí)篇中,關(guān)于加密解密的部分會(huì)提到某些硬件中斷的利用,但那是后話)。

      在設(shè)計(jì)操作系統(tǒng)時(shí),中斷向量的概念曾經(jīng)帶來(lái)過(guò)很大的便利。操作系統(tǒng)隨時(shí)可能升級(jí),這樣,通過(guò)CALL來(lái)調(diào)用操作系統(tǒng)的服務(wù)(如果說(shuō)每個(gè)程序都包含對(duì)于文件系統(tǒng)、進(jìn)程表這些應(yīng)該由操作系統(tǒng)管理的數(shù)據(jù)的直接操作的話,不僅會(huì)造成程序的臃腫,而且不利于系統(tǒng)的安全)就顯得不太合適了——沒(méi)人能知道,以后的操作系統(tǒng)的服務(wù)程序入口點(diǎn)會(huì)不會(huì)是那兒。軟件中斷的存在為解決這個(gè)問(wèn)題提供了方便。對(duì)于一臺(tái)包含了BIOS的計(jì)算機(jī)來(lái)說(shuō),啟動(dòng)的時(shí)候系統(tǒng)已經(jīng)提供了一部分服務(wù),例如顯示服務(wù)。無(wú)論你的BIOS、顯示卡有多么的“個(gè)性”,只要他們和IBM PC兼容,那么此時(shí)你肯定可以通過(guò)調(diào)用16(10h)號(hào)中斷來(lái)使用顯示服務(wù)。調(diào)用中斷的指令是

      int 中斷號(hào)

      這將引發(fā)CPU去調(diào)用一個(gè)中斷。CPU將保存當(dāng)前的程序狀態(tài)字,清除Trap和Interrupt兩個(gè)標(biāo)志,將即將執(zhí)行的指令地址壓入堆棧,并調(diào)用中斷服務(wù)(根據(jù)中斷向量表)。

      編寫中斷服務(wù)程序不是一件容易的事情。很多時(shí)候,中斷服務(wù)程序必須寫成可重入代碼(或純代碼,pure code)。所謂可重入代碼是指,程序的運(yùn)行過(guò)程中可以被打斷,并由開始處再次執(zhí)行,并且在合理的范圍內(nèi)(多次重入,而不造成堆棧溢出等其他問(wèn)題),程序可以在被打斷處繼續(xù)執(zhí)行,并且執(zhí)行結(jié)果不受影響。

      由于在多線程環(huán)境中等其他一些地方進(jìn)行程序設(shè)計(jì)時(shí)也需要考慮這個(gè)因素,因此這里著重講一下可重入代碼的編寫。

      可重入代碼最主要的要求就是,程序不應(yīng)使用某個(gè)指定的內(nèi)存地址的內(nèi)存(對(duì)于高級(jí)語(yǔ)言來(lái)說(shuō),這通常是全局變量,或?qū)ο蟮某蓡T)。如果可能的話,應(yīng)使用寄存器,或其他方式來(lái)解決。如果不能做到這一點(diǎn),則必須在開始、結(jié)束的時(shí)候分別禁止和啟用中斷,并且,運(yùn)行時(shí)間不能太長(zhǎng)。

      下面用C語(yǔ)言分別舉一個(gè)可重入函數(shù),和兩個(gè)非可重入函數(shù)的例子(注.這些例子應(yīng)該是在某本多線程或操作系統(tǒng)的書上看到的,遺憾的是我想不起來(lái)是哪本書了,在這里先感謝那位作者提供的范例):

      可重入函數(shù):

      void strcpy(char* lpszDest, char* lpszSrc){ while(*dest++=*src++);*dest=0;}

      非可重入函數(shù)

      char cTemp;// 全局變量

      void SwapChar(char* lpcX, char* lpcY){ cTemp = *lpcX;*lpcX = *lpcY;lpcY = cTemp;// 引用了全局變量,在分享內(nèi)存的多個(gè)線程中可能造成問(wèn)題 }

      非可重入函數(shù)

      void SwapChar2(char* lpcX, char* lpcY){ static char cTemp;// 靜態(tài)變量

      cTemp = *lpcX;*lpcX = *lpcY;lpcY = cTemp;// 引用了靜態(tài)變量,在分享內(nèi)存的多個(gè)線程中可能造成問(wèn)題 }

      中斷利用的是系統(tǒng)的棧。棧操作是可重入的(因?yàn)闂?梢员WC“先進(jìn)后出”),因此,我們并不需要考慮棧操作的重入問(wèn)題。使用宏匯編器寫出可重入的匯編代碼需要注意一些問(wèn)題。簡(jiǎn)單地說(shuō),干脆不要用標(biāo)號(hào)作為變量是一個(gè)不錯(cuò)的主意。

      使用高級(jí)語(yǔ)言編寫可重入程序相對(duì)來(lái)講輕松一些。把持住不訪問(wèn)那些全局(或當(dāng)前對(duì)象的)變量,不使用靜態(tài)局部變量,堅(jiān)持只適用局部變量,寫出的程序就將是可重入的。書歸正傳,調(diào)用軟件中斷時(shí),通常都是通過(guò)寄存器傳進(jìn)、傳出參數(shù)。這意味著你的int指令周圍也許會(huì)存在一些“幫手”,比如下面的代碼: mov ax, 4c00h int 21h 就是通過(guò)調(diào)用DOS中斷服務(wù)返回父進(jìn)程,并帶回錯(cuò)誤反饋碼0。其中,ax中的數(shù)據(jù)4c00h就是傳遞給DOS中斷服務(wù)的參數(shù)。

      到這里,x86匯編語(yǔ)言的基礎(chǔ)部分就基本上講完了,《簡(jiǎn)明x86匯編語(yǔ)言教程》的初級(jí)篇——匯編語(yǔ)言基礎(chǔ)也就到此告一段落。當(dāng)然,目前為止,我只是蜻蜓點(diǎn)水一般提到了一些學(xué)習(xí)x86匯編語(yǔ)言中我認(rèn)為需要注意的重要概念。許多東西,包括全部匯編語(yǔ)句的時(shí)序特性(指令執(zhí)行周期數(shù),以及指令周期中各個(gè)階段的節(jié)拍數(shù)等)、功能、參數(shù)等等,限于個(gè)人水平和篇幅我都沒(méi)有作詳細(xì)介紹。如果您對(duì)這些內(nèi)容感興趣,請(qǐng)參考Intel和AMD兩大CPU供應(yīng)商網(wǎng)站上提供的開發(fā)人員參考。

      在以后的簡(jiǎn)明x86匯編語(yǔ)言教程中級(jí)篇和高級(jí)篇中,我將著重介紹匯編語(yǔ)言的調(diào)試技術(shù)、優(yōu)化,以及一些具體的應(yīng)用技巧,包括反跟蹤、反反跟蹤、加密解密、病毒與反病毒等等。

      5.0 編譯優(yōu)化概述

      優(yōu)化是一件非常重要的事情。作為一個(gè)程序設(shè)計(jì)者,你肯定希望自己的程序既小又快。DOS時(shí)代的許多書中都提到,“某某編譯器能夠生成非常緊湊的代碼”,換言之,編譯器會(huì)為你把代碼盡可能地縮減,如果你能夠正確地使用它提供的功能的話。目前,Intel x86體系上流行的C/C++編譯器,包括Intel C/C++ Compiler, GNU C/C++ Compiler,以及最新的Microsoft和Borland編譯器,都能夠提供非常緊湊的代碼。正確地使用這些編譯器,則可以得到性能足夠好的代碼。

      但是,機(jī)器目前還不能像人那樣做富于創(chuàng)造性的事情。因而,有些時(shí)候我們可能會(huì)不得不手工來(lái)做一些事情。

      使用匯編語(yǔ)言優(yōu)化代碼是一件困難,而且技巧性很強(qiáng)的工作。很多編譯器能夠生成為處理器進(jìn)行過(guò)特殊優(yōu)化處理的代碼,一旦進(jìn)行修改,這些特殊優(yōu)化可能就會(huì)被破壞而失效。因此,在你決定使用自己的匯編代碼之前,一定要測(cè)試一下,到底是編譯器生成的那段代碼更好,還是你的更好。

      本章中將討論一些編譯器在某些時(shí)候會(huì)做的事情(從某種意義上說(shuō),本章內(nèi)容更像是計(jì)算機(jī)專業(yè)的基礎(chǔ)課中《編譯程序設(shè)計(jì)原理》、《計(jì)算機(jī)組成原理》、《計(jì)算機(jī)體系結(jié)構(gòu)》課程中的相關(guān)內(nèi)容)。本章的許多內(nèi)容和匯編語(yǔ)言程序設(shè)計(jì)本身關(guān)系并不是很緊密,它們多數(shù)是在為使用匯編語(yǔ)言進(jìn)行優(yōu)化做準(zhǔn)備。編譯器確實(shí)做這些優(yōu)化,但它并不總是這么做;此外,就編譯器的設(shè)計(jì)本質(zhì)來(lái)說(shuō),它確實(shí)沒(méi)有義務(wù)這么做——編譯器做的是等義變換,而不是等效變換??紤]下面的代碼:

      // 程序段1 int gaussianSum(){ int i, j=0;for(i=0;i<100;i++)j+=i;

      return j;} 好的,首先,絕大多數(shù)編譯器恐怕不會(huì)自作主張地把它“篡改”為

      // 程序段1(改進(jìn)1)int gaussianSum(){ int i, j=0;for(i=1;i<100;i++)j+=i;

      return j;}

      多數(shù)(但確實(shí)不是全部)編譯器也不會(huì)把它改為

      // 程序段1(改進(jìn)2)inline int gaussianSum(){ return 5050;}

      這兩個(gè)修改版本都不同于原先程序的語(yǔ)義。首先我們看到,讓i從0開始是沒(méi)有必要的,因?yàn)閖+=i時(shí),i=0不會(huì)做任何有用的事情;然后是,實(shí)際上沒(méi)有必要每一次都計(jì)算1+...+100的和——它可以被預(yù)先計(jì)算,并在需要的時(shí)候返回。

      這個(gè)例子也許并不恰當(dāng)(估計(jì)沒(méi)人會(huì)寫出最初版本那樣的代碼),但這種實(shí)踐在程序設(shè)計(jì)中確實(shí)可能出現(xiàn)。我們把改進(jìn)2稱為編譯時(shí)表達(dá)式預(yù)先計(jì)算,而把改進(jìn)1成為循環(huán)強(qiáng)度削減。

      然而,一些新的編譯器的確會(huì)進(jìn)行這兩種優(yōu)化。不過(guò)別慌,看看下面的代碼:

      // 程序段2 int GetFactorial(int k){ int i, j=1;if((k<0)||(k>=10))return-1;

      if((k<=1))return 1

      for(i=1;i

      return j;}

      程序采用的是一個(gè)時(shí)間復(fù)雜度為O(n)的算法,不過(guò),我們可以把他輕易地改為O(1)的算法:

      // 程序段2(非規(guī)范改進(jìn))int GetFactorial(int k){ int i, j=1;static const int FractorialTable[]={1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800};

      if((k<0)||(k>=10))return-1;

      return FractorialTable[k];}

      這是一個(gè)典型的以空間換時(shí)間的做法。通用的編譯器不會(huì)這么做——因?yàn)樗鼪](méi)有辦法在編譯時(shí)確定你是不是要這么改??梢哉f(shuō),如果編譯器真的這樣做的話,那將是一件可怕的事情,因?yàn)槟菚r(shí)候你將很難知道編譯器生成的代碼和自己想的到底有多大的差距。

      當(dāng)然,這類優(yōu)化超出了本文的范圍——基本上,我把它們歸入“算法優(yōu)化”,而不是“程序優(yōu)化”一類。類似的優(yōu)化過(guò)程需要程序設(shè)計(jì)人員對(duì)于程序邏輯非常深入地了解和全盤的掌握,同時(shí),也需要有豐富的算法知識(shí)。

      自然,如果你希望自己的程序性能有大幅度的提升,那么首先應(yīng)該做的是算法優(yōu)化。例如,把一個(gè)O(n2)的算法替換為一個(gè)O(n)的算法,則程序的性能提升將遠(yuǎn)遠(yuǎn)超過(guò)對(duì)于個(gè)別語(yǔ)句的修改。此外,一個(gè)已經(jīng)改寫為匯編語(yǔ)言的程序,如果要再在算法上作大幅度的修改,其工作量將和重寫相當(dāng)。因此,在決定使用匯編語(yǔ)言進(jìn)行優(yōu)化之前,必須首先考慮算法優(yōu)化。但假如已經(jīng)是最優(yōu)的算法,程序運(yùn)行速度還是不夠快怎么辦呢?

      好的,現(xiàn)在,假定你已經(jīng)使用了已知最好的算法,決定把它交給編譯器,讓我們來(lái)看看編譯器會(huì)為我們做什么,以及我們是否有機(jī)會(huì)插手此事,做得更好。

      5.1 循環(huán)優(yōu)化:強(qiáng)度削減和代碼外提

      比較新的編譯器在編譯時(shí)會(huì)自動(dòng)把下面的代碼:

      for(i=0;i<10;i++){ j = i;k = j + i;}

      至少變換為

      for(i=0;i<10;i++);j=i;k=j+i;

      甚至

      j=i=10;k=20;

      當(dāng)然,真正的編譯器實(shí)際上是在中間代碼層次作這件事情。

      原理 如果數(shù)據(jù)項(xiàng)的某個(gè)中間值(程序執(zhí)行過(guò)程中的計(jì)算結(jié)果)在使用之前被另一中間值覆蓋,則相關(guān)計(jì)算不必進(jìn)行。

      也許有人會(huì)問(wèn),編譯器不是都給咱們做了嗎,管它做什么?注意,這里說(shuō)的只是編譯系統(tǒng)中優(yōu)化部分的基本設(shè)計(jì)。不僅在從源代碼到中間代碼的過(guò)程中存在優(yōu)化問(wèn)題,而且編譯器生成的最終的機(jī)器語(yǔ)言(匯編)代碼同樣存在類似的問(wèn)題。目前,幾乎所有的編譯器在最終生成代碼的過(guò)程中都有或多或少的瑕疵,這些瑕疵目前只能依靠手工修改代碼來(lái)解決。

      5.2 局部?jī)?yōu)化:表達(dá)式預(yù)計(jì)算和子表達(dá)式提取

      表達(dá)式預(yù)先計(jì)算非常簡(jiǎn)單,就是在編譯時(shí)盡可能地計(jì)算程序中需要計(jì)算的東西。例如,你可以毫不猶豫地寫出下面的代碼:

      const unsigned long nGiga = 1024L * 1024L * 1024L;

      而不必?fù)?dān)心程序每次執(zhí)行這個(gè)語(yǔ)句時(shí)作兩遍乘法,因?yàn)榫幾g器會(huì)自動(dòng)地把它改為

      const unsigned long nGiga = 1073741824L;

      而不是傻乎乎地讓計(jì)算機(jī)在執(zhí)行到這個(gè)初始化賦值語(yǔ)句的時(shí)候才計(jì)算。當(dāng)然,如果你愿意在上面的代碼中摻上一些變量的話,編譯器同樣會(huì)把常數(shù)部分先行計(jì)算,并拿到結(jié)果。

      表達(dá)式預(yù)計(jì)算并不會(huì)讓程序性能有飛躍性的提升,但確實(shí)減少了運(yùn)行時(shí)的計(jì)算強(qiáng)度。除此之外,絕大多數(shù)編譯器會(huì)把下面的代碼:

      // [假設(shè)此時(shí)b, c, d, e, f, g, h都有一個(gè)確定的非零整數(shù)值,并且,// a[]為一個(gè)包括5個(gè)整數(shù)元素的數(shù)組,其下標(biāo)為0到4] a[0] = b*c;a[1] = b+c;a[2] = d*e;a[3] = b*d + c*d;a[4] = b*d*e + c*d*e;

      優(yōu)化為(再次強(qiáng)調(diào),編譯器實(shí)際上是在中間代碼的層次,而不是源代碼層次做這件事情!):

      // [假設(shè)此時(shí)b, c, d, e, f, g, h都有一個(gè)確定的非零整數(shù)值,并且,// a[]為一個(gè)包括5個(gè)整數(shù)元素的數(shù)組,其下標(biāo)為0到4] a[0] = b*c;a[1] = b+c;a[2] = d*e;a[3] = a[1] * d;a[4] = a[3] * e;

      更進(jìn)一步,在實(shí)際代碼生成過(guò)程中,一些編譯器還會(huì)對(duì)上述語(yǔ)句的次序進(jìn)行調(diào)整,以使其運(yùn)行效率更高。例如,將語(yǔ)句調(diào)整為下面的次序:

      // [假設(shè)此時(shí)b, c, d, e, f, g, h都有一個(gè)確定的非零整數(shù)值,并且,// a[]為一個(gè)包括5個(gè)整數(shù)元素的數(shù)組,其下標(biāo)為0到4] a[0] = b*c;a[1] = b+c;a[3] = a[1] * d;a[4] = a[3] * e;a[2] = d*e;

      在某些體系結(jié)構(gòu)中,剛剛計(jì)算完的a[1]可以放到寄存器中,以提高實(shí)際的計(jì)算性能。上述5個(gè)計(jì)算任務(wù)之間,只有1, 3, 4三個(gè)計(jì)算任務(wù)必須串行地執(zhí)行,因此,在新的處理器上,這樣做甚至能夠提高程序的并行度,從而使程序效率變得更高。

      5.3 全局寄存器優(yōu)化

      [待修訂內(nèi)容] 本章中,從這一節(jié)開始的所有優(yōu)化都是在微觀層面上的優(yōu)化了。換言之,這些優(yōu)化是不能使用高級(jí)語(yǔ)言中的對(duì)應(yīng)設(shè)施進(jìn)行解釋的。這一部分內(nèi)容將進(jìn)行較大規(guī)模的修訂。

      通常,此類優(yōu)化是由編譯器自動(dòng)完成的。我個(gè)人并不推薦真的由人來(lái)完成這些工作——這些工作多半是枯燥而重復(fù)性的,編譯器通常會(huì)比人做得更好(沒(méi)說(shuō)的,肯定也更快)。但話說(shuō)回來(lái),使用匯編語(yǔ)言的程序設(shè)計(jì)人員有責(zé)任了解這些內(nèi)容,因?yàn)橹挥羞@樣才能更好地駕馭處理器。

      在前面的幾章中我已經(jīng)提到過(guò),寄存器的速度要比內(nèi)存快。因此,在使用寄存器方面,編譯器一般會(huì)做一種稱為全局寄存器優(yōu)化的優(yōu)化。

      例如,在我們的程序中使用了4個(gè)變量:i, j, k, l。它們都作為循環(huán)變量使用:

      for(i=0;i<1000;i++){ for(j=0;j<1000;j++){ for(k=0;k<1000;k++){ for(l=0;l<1000;l++)do_something(i, j, k, l);} } }

      這段程序的優(yōu)化就不那么簡(jiǎn)單了。顯然,按照通常的壓棧方法,i, j, k, l應(yīng)該按照某個(gè)順序被壓進(jìn)堆棧,然后調(diào)用do_something(),然后函數(shù)做了一些事情之后返回。問(wèn)題在于,無(wú)論如何壓棧,這些東西大概都得進(jìn)內(nèi)存(不可否認(rèn)某些機(jī)器可以用CPU的Cache做這件事情,但Cache是寫通式的和回寫式的又會(huì)造成一些性能上的差異)。

      聰明的讀者馬上就會(huì)指出,我們不是可以在定義do_something()的時(shí)候加上inline修飾符,讓它在本地展開嗎?沒(méi)錯(cuò),本地展開以增加代碼量為代價(jià)換取性能,但這只是問(wèn)題的一半。編譯器盡管完成了本地展開,但它仍然需要做許多額外的工作。因?yàn)榧拇嫫髦挥心敲从邢薜膸讉€(gè),而我們卻有這么多的循環(huán)變量。

      把四個(gè)變量按照它們?cè)谘h(huán)中使用的頻率排序,并決定在do_something()塊中的優(yōu)先順序(放入寄存器中的優(yōu)先順序)是一個(gè)解決方案。很明顯,我們可以按照l(shuí), k, j, i的順序(從高到低,因?yàn)閘將被進(jìn)行1000*1000*1000*1000次運(yùn)算!)來(lái)排列,但在實(shí)際的問(wèn)題中,事情往往沒(méi)有這么簡(jiǎn)單,因?yàn)槟悴恢纃o_something()中做的到底是什么。而且,憑什么就以for(l=0;l<1000;l++)作為優(yōu)化的分界點(diǎn)呢?如果do_something()中還有循環(huán)怎么辦?

      如此復(fù)雜的計(jì)算問(wèn)題交給計(jì)算機(jī)來(lái)做通常會(huì)有比較滿意的結(jié)果。一般說(shuō)來(lái),編譯器能夠?qū)Τ绦蛑凶兞康氖褂眠M(jìn)行更全面地估計(jì),因此,它分配寄存器的結(jié)果有時(shí)雖然讓人費(fèi)解,但卻是最優(yōu)的(因?yàn)橛?jì)算機(jī)能夠進(jìn)行大量的重復(fù)計(jì)算,并找到最好的方法;而人做這件事相對(duì)來(lái)講比較困難)。

      編譯器在許多時(shí)候能夠作出相當(dāng)讓人滿意的結(jié)果??紤]以下的代碼:

      int a=0;for(int i=1;i<10;i++)for(int j=1;j<100;j++){ a +=(i*j);}

      讓我們把它變?yōu)槟撤N形式的中間代碼:

      00: 0-> a 01: 1-> i 02: 1-> j 03: i*j-> t 04: a+t-> a 05: j+1-> j 06: evaluate j < 100 07: TRUE? goto 03 08: i+1-> i 09: evaluate i < 10 10: TRUE? goto 02 11: [繼續(xù)執(zhí)行程序的其余部分]

      程序中執(zhí)行強(qiáng)度最大的無(wú)疑是03到05這一段,涉及的需要寫入的變量包括a, j;需要讀出的變量是i。不過(guò),最終的編譯結(jié)果大大出乎我們的意料。下面是某種優(yōu)化模式下Visual C++ 6.0編譯器生成的代碼(我做了一些修改):

      xor eax, eax;a=0(eax: a)mov edx, 1;i=1(edx: i)push esi;保存esi(最后要恢復(fù),esi作為代替j的那個(gè)循環(huán)變量)nexti: mov ecx, edx;[t=i] mov esi, 999;esi=999: 此處修改了原程序的語(yǔ)義,但仍為1000次循環(huán)。nextj: add eax, ecx;[a+=t] add ecx, edx;[t+=i] dec esi;j--jne SHORT nextj;jne 等價(jià)于 jnz.[如果還需要,則再次循環(huán)] inc edx;i++ cmp edx, 10;i與10比較 jl SHORT nexti;i < 10, 再次循環(huán) pop esi;恢復(fù)esi

      這段代碼可能有些令人費(fèi)解。主要是因?yàn)樗粌H使用了大量寄存器,而且還包括了5.2節(jié)中曾提到的子表達(dá)式提取技術(shù)。表面上看,多引入的那個(gè)變量(t)增加了計(jì)算時(shí)間,但要注意,這個(gè)t不僅不會(huì)降低程序的執(zhí)行效率,相反還會(huì)讓它變得更快!因?yàn)橥瑯拥玫搅擞?jì)算結(jié)果(本質(zhì)上,i*j即是第j次累加i的值),但這個(gè)結(jié)果不僅用到了上次運(yùn)算的結(jié)果,而且還省去了乘法(很顯然計(jì)算機(jī)計(jì)算加法要比計(jì)算乘法快)。

      這里可能會(huì)有人問(wèn),為什么要從999循環(huán)到0,而不是按照程序中寫的那樣從0循環(huán)到999呢?這個(gè)問(wèn)題和匯編語(yǔ)言中的取址有關(guān)。在下兩節(jié)中我將提到這方面的內(nèi)容。

      5.4 x86體系結(jié)構(gòu)上的并行最大化和指令封包

      考慮這樣的問(wèn)題,我和兩個(gè)同伴現(xiàn)在在山里,遠(yuǎn)處有一口井,我們帶著一口鍋,身邊是樹林;身上的飲用水已經(jīng)喝光了,此處允許砍柴和使用明火(當(dāng)然我們不想引起火災(zāi):),需要燒一鍋水,應(yīng)該怎么樣呢?

      一種方案是,三個(gè)人一起搭灶,一起砍柴,一起打水,一起把水燒開。

      另一種方案是,一個(gè)人搭灶,此時(shí)另一個(gè)人去砍柴,第三個(gè)人打水,然后把水燒開。

      這兩種方案畫出圖來(lái)是這樣:

      僅僅這樣很難說(shuō)明兩個(gè)方案孰優(yōu)孰劣,因?yàn)槲覀儾⒉幻鞔_三個(gè)人一起打水、一起砍柴、一起搭灶的效率更高,還是分別作效率更高(通常的想法,一起做也許效率會(huì)更高)。但假如說(shuō),三個(gè)人一個(gè)只會(huì)搭灶,一個(gè)只會(huì)砍柴,一個(gè)只會(huì)打水(當(dāng)然是說(shuō)這三件事情),那么,方案2的效率就會(huì)搞一些了。

      在現(xiàn)實(shí)生活中,某個(gè)人擁有專長(zhǎng)是比較普遍的情況;在設(shè)計(jì)計(jì)算機(jī)硬件的時(shí)候則更是如此。你不可能指望加法器不做任何改動(dòng)就能去做移位甚至整數(shù)乘法,然而我們注意到,串行執(zhí)行的程序不可能在同一時(shí)刻同時(shí)用到處理器的所有功能,因此,我們(很自然地)會(huì)希望有一些指令并行地執(zhí)行,以充分利用CPU的計(jì)算資源。

      CPU執(zhí)行一條指令的過(guò)程基本上可以分為下面幾個(gè)階段:取指令、取數(shù)據(jù)、計(jì)算、保存數(shù)據(jù)。假設(shè)這4個(gè)階段各需要1個(gè)時(shí)鐘周期,那么,只要資源夠用,并且4條指令之間不存在串行關(guān)系(換言之這些指令的執(zhí)行先后次序不影響最終結(jié)果,或者,更嚴(yán)格地說(shuō),沒(méi)有任何一條指令依賴其他指令的運(yùn)算結(jié)果)指令也可以像下面這樣執(zhí)行:

      指令1 取指令 取數(shù)據(jù) 計(jì) 算 存數(shù)據(jù)

      指令2 取指令 取數(shù)據(jù) 計(jì) 算 存數(shù)據(jù)

      指令3

      取指令 取數(shù)據(jù) 計(jì) 算 存數(shù)據(jù)

      指令4

      取指令 取數(shù)據(jù) 計(jì) 算 存數(shù)據(jù)

      這樣,原本需要16個(gè)時(shí)鐘周期才能夠完成的任務(wù)就可以在7個(gè)時(shí)鐘周期內(nèi)完成,時(shí)間縮短了一半還多。如果考慮灰色的那些方格(這些方格可以被4條指令以外的其他指令使用,只要沒(méi)有串行關(guān)系或沖突),那么,如此執(zhí)行對(duì)于性能的提升將是相當(dāng)可觀的(此時(shí),CPU的所有部件都得到了充分利用)。

      當(dāng)然,作為程序來(lái)說(shuō),真正做到這樣是相當(dāng)理想化的情況。實(shí)際的程序中很難做到徹底的并行化。假設(shè)CPU能夠支持4條指令同時(shí)執(zhí)行,并且,每條指令都是等周期長(zhǎng)度的4周期指令,那么,程序需要保證同一時(shí)刻先后發(fā)射的4條指令都能夠并行執(zhí)行,相互之間沒(méi)有關(guān)聯(lián),這通常是不太可能的。

      最新的Intel Pentium 4-XEON處理器,以及Intel Northwood Pentium 4都提供了一種被稱為超線程(Hyper-Threading TM)的技術(shù)。該技術(shù)通過(guò)在一個(gè)處理器中封裝兩組執(zhí)行機(jī)構(gòu)來(lái)提高指令并行度,并依靠操作系統(tǒng)的調(diào)度來(lái)進(jìn)一步提升系統(tǒng)的整體效率。

      由于線程機(jī)制是與操作系統(tǒng)密切相關(guān)的,因此,在本文的這一部分中不可能做更為深入地探討。在后續(xù)的章節(jié)中,我將介紹Win32、FreeBSD 5.x以及Linux中提供的內(nèi)核級(jí)線程機(jī)制(這三種操作系統(tǒng)都支持SMP及超線程技術(shù),并且以線程作為調(diào)度單位)在匯編語(yǔ)言中的使用方法。

      關(guān)于線程的討論就此打住,因?yàn)樗嗟匾蕾囉诓僮飨到y(tǒng),并且,無(wú)論如何,操作系統(tǒng)的線程調(diào)度需要更大的開銷并且,到目前為止,真正使用支持超線程的CPU,并且使用相應(yīng)操作系統(tǒng)的人是非常少的。因此,我們需要關(guān)心的實(shí)際上還是同一執(zhí)行序列中的并發(fā)執(zhí)行和指令封包。不過(guò),令人遺憾的是,實(shí)際上在這方面編譯器做的幾乎是肯定要比人好,因此,你需要做的只是開啟相應(yīng)的優(yōu)化;如果你的編譯器不支持這樣的特性,那么就把它扔掉??據(jù)我所知,目前在Intel平臺(tái)上指令封包方面做的最好的是Intel的C++編譯器,經(jīng)過(guò)Intel編譯器編譯的代碼的性能令人驚異地高,甚至在AMD公司推出的兼容處理器上也是如此。5.5 存儲(chǔ)優(yōu)化

      從前一節(jié)的圖中我們不難看出,方案2中,如果誰(shuí)的動(dòng)作慢,那么他就會(huì)成為性能的瓶頸。實(shí)際上,CPU也不會(huì)像我描述的那樣四平八穩(wěn)地運(yùn)行,指令執(zhí)行的不同階段需要的時(shí)間(時(shí)鐘周期數(shù))是不同的,因此,縮短關(guān)鍵步驟(即,造成瓶頸的那個(gè)步驟)是縮短執(zhí)行時(shí)間的關(guān)鍵。

      至少對(duì)于使用Intel系列的CPU來(lái)說(shuō),取數(shù)據(jù)這個(gè)步驟需要消耗比較多的時(shí)間。此外,假如數(shù)據(jù)跨越了某種邊界(如4或8字節(jié),與CPU的字長(zhǎng)有關(guān)),則CPU需要啟動(dòng)兩次甚至更多次數(shù)的讀內(nèi)存操作,這無(wú)疑對(duì)性能構(gòu)成不利影響。

      基于這樣的原因,我們可以得到下面的設(shè)計(jì)策略:

      程序設(shè)計(jì)中的內(nèi)存數(shù)據(jù)訪問(wèn)策略

      盡可能減少對(duì)于內(nèi)存的訪問(wèn)。在不違背這一原則的前提下,如果可能,將數(shù)據(jù)一次處理完。盡可能將數(shù)據(jù)按4或8字節(jié)對(duì)齊,以利于CPU存取

      盡可能一段時(shí)間內(nèi)訪問(wèn)范圍不大的一段內(nèi)存,而不同時(shí)訪問(wèn)大量遠(yuǎn)距離的分散數(shù)據(jù),以利于Cache緩存*

      第一條規(guī)則比較簡(jiǎn)單。例如,需要求一組數(shù)據(jù)中的最大值、最小值、平均數(shù),那么,最好是在一次循環(huán)中做完。

      “于是,這家伙又?jǐn)€了一段代碼”??

      int a[]={1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0};int i;int avg, max, min;avg=max=min=a[0];

      for(i=1;i<(sizeof(a)/sizeof(int));i++){ avg+=a[i];if(max < a[i])max = a[i];else if(min > a[i])min = a[i];}

      avg /= i;

      Visual C++編譯器把最開始一段賦值語(yǔ)句翻譯成了一段簡(jiǎn)直可以說(shuō)是匪夷所思的代碼:

      ;int a[]={1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0};

      mov edi, 2;此時(shí)edi沒(méi)有意義

      mov esi, 3;esi也是!臨時(shí)變量而已。mov DWORD PTR _a$[esp+92], edi mov edx, 5;黑名單加上edx mov eax, 7;eax也別跑:)mov DWORD PTR _a$[esp+132], edi mov ecx, 9;就差你了,ecx

      ;int i;;int avg, max, min;;avg=max=min=a[0];

      mov edi, 1;edi搖身一變,現(xiàn)在它是min了。mov DWORD PTR _a$[esp+96], esi mov DWORD PTR _a$[esp+104], edx mov DWORD PTR _a$[esp+112], eax mov DWORD PTR _a$[esp+136], esi mov DWORD PTR _a$[esp+144], edx mov DWORD PTR _a$[esp+152], eax mov DWORD PTR _a$[esp+88], 1;編譯器失誤? 此處edi應(yīng)更好 mov DWORD PTR _a$[esp+100], 4 mov DWORD PTR _a$[esp+108], 6 mov DWORD PTR _a$[esp+116], 8 mov DWORD PTR _a$[esp+120], ecx mov DWORD PTR _a$[esp+124], 0 mov DWORD PTR _a$[esp+128], 1 mov DWORD PTR _a$[esp+140], 4 mov DWORD PTR _a$[esp+148], 6 mov DWORD PTR _a$[esp+156], 8 mov DWORD PTR _a$[esp+160], ecx mov DWORD PTR _a$[esp+164], 0 mov edx, edi;edx是max。

      mov eax, edi;期待已久的avg, 它被指定為eax

      這段代碼是最優(yōu)的嗎?我個(gè)人認(rèn)為不是。因?yàn)榫幾g器完全可以在編譯過(guò)程中直接把它們作為常量數(shù)據(jù)放入內(nèi)存。此外,如果預(yù)先對(duì)a[0..9]10個(gè)元素賦值,并利用串操作指令(rep movsdw),速度會(huì)更快一些。

      當(dāng)然,犯不上因?yàn)檫@些問(wèn)題責(zé)怪編譯器。要求編譯器知道a[0..9]和[10..19]的內(nèi)容一樣未免過(guò)于苛刻。我們看看下面的指令段:

      ;for(i=1;...mov esi, edi for_loop:

      ;avg+=a[i];

      mov ecx, DWORD PTR _a$[esp+esi*4+88] add eax, ecx

      ;if(max < a[i])

      cmp edx, ecx jge SHORT elseif_min

      ;max = a[i];

      mov edx, ecx

      ;else if(min > a[i])

      jmp SHORT elseif_min elseif_min: cmp edi, ecx jle SHORT elseif_end

      ;min = a[i];mov edi, ecx

      elseif_end:

      ;[for i=1];i<20;i++){

      inc esi cmp esi, 20 jl SHORT for_loop;};avg /= i;cdq idiv esi

      ;esi: i

      ;ecx: 暫存變量, =a[i];eax: avg

      ;edx: max

      ;有趣的代碼...并不是所有的時(shí)候都有用;但是也別隨便刪除;edi: min

      ;i++;i與20比較

      ;avg /= i

      上面的程序倒是沒(méi)有什么驚人之處。唯一一個(gè)比較嚇人的東西是那個(gè)jmp SHORT指令,它是否有用取決于具體的問(wèn)題。C/C++編譯器有時(shí)會(huì)產(chǎn)生這樣的代碼,我過(guò)去曾經(jīng)錯(cuò)誤地把所有的此類指令當(dāng)作沒(méi)用的代碼而刪掉,后來(lái)發(fā)現(xiàn)程序執(zhí)行時(shí)間沒(méi)有明顯的變化。通過(guò)查閱文檔才知道,這類指令實(shí)際上是“占位指令”,他們存在的意義在于占據(jù)那個(gè)地方,一來(lái)使其他語(yǔ)句能夠正確地按CPU覺(jué)得舒服的方式對(duì)齊,二來(lái)它可以占據(jù)CPU的某些周期,使得后續(xù)的指令能夠更好地并發(fā)執(zhí)行,避免沖突。另一個(gè)比較常見(jiàn)的、實(shí)現(xiàn)類似功能的指令是NOP。

      占位指令的去留主要是靠計(jì)時(shí)執(zhí)行來(lái)判斷。由于目前流行的操作系統(tǒng)基本上都是多任務(wù)的,因此會(huì)對(duì)計(jì)時(shí)的精確性有一定影響。如果需要進(jìn)行測(cè)試的話,需要保證以下幾點(diǎn):

      計(jì)時(shí)測(cè)試需要注意的問(wèn)題

      測(cè)試必須在沒(méi)有額外負(fù)荷的機(jī)器上完成。例如,專門用于編寫和調(diào)試程序的計(jì)算機(jī) 盡量終止計(jì)算機(jī)上運(yùn)行的所有服務(wù),特別是殺毒程序 切斷計(jì)算機(jī)的網(wǎng)絡(luò),這樣網(wǎng)絡(luò)的影響會(huì)消失

      將進(jìn)程優(yōu)先級(jí)調(diào)高。對(duì)于Windows系統(tǒng)來(lái)說(shuō),把進(jìn)程(線程)設(shè)置為Time-Critical;對(duì)于*nix系統(tǒng)來(lái)說(shuō),把進(jìn)程設(shè)置為實(shí)時(shí)進(jìn)程

      將測(cè)試函數(shù)運(yùn)行盡可能多次運(yùn)行,如10000000次,這樣能夠減少由于進(jìn)城切換而造成的偶然誤差

      最后,如果可能的話,把函數(shù)放到單進(jìn)程的系統(tǒng)(例如FreeDOS)中運(yùn)行。

      對(duì)于絕大多數(shù)程序來(lái)說(shuō),計(jì)時(shí)測(cè)試是一個(gè)非常重要的東西。我個(gè)人傾向于在進(jìn)行優(yōu)化后進(jìn)行計(jì)時(shí)測(cè)試并比較結(jié)果。目前,我基于經(jīng)驗(yàn)進(jìn)行的優(yōu)化基本上都能夠提高程序的執(zhí)行性能,但我還是不敢過(guò)于自信。優(yōu)化確實(shí)會(huì)提高性能,但人做的和編譯器做的思路不同,有時(shí),我們的確會(huì)做一些費(fèi)力不討好的事情。

      第二篇:金融學(xué)入門書籍[范文模版]

      一、入門教材:

      1、曼昆《經(jīng)濟(jì)學(xué)原理》上下冊(cè),88元。梁小民教授翻譯。曼昆為哈佛高才生,天才橫溢,屬新古典凱恩斯主義學(xué)派,研究范圍偏重宏觀經(jīng)濟(jì)分析。

      該書為大學(xué)一年級(jí)學(xué)生而寫,主要特點(diǎn)是行文簡(jiǎn)單、說(shuō)理淺顯、語(yǔ)言有趣。界面相當(dāng)友好,引用大量的案例和報(bào)刊文摘,與生活極其貼近,諸如美聯(lián)儲(chǔ)為何存在,如何運(yùn)作,Greenspan 如何降息以應(yīng)付經(jīng)濟(jì)低迷等措施背后的經(jīng)濟(jì)學(xué)道理。該書幾乎沒(méi)有用到數(shù)學(xué),而且自創(chuàng)歸納出“經(jīng)濟(jì)學(xué)10大原理”,為初學(xué)者解說(shuō),極其便利完全沒(méi)有接觸過(guò)經(jīng)濟(jì)學(xué)的人閱讀。學(xué)此書,可了解經(jīng)濟(jì)學(xué)的基本思維,常用的基本原理,用于看待生活中的經(jīng)濟(jì)現(xiàn)象??芍?jīng)濟(jì)學(xué)之功用及有趣,遠(yuǎn)超一般想象之外。推薦入門首選閱讀。目前國(guó)內(nèi)已經(jīng)有某些教授依據(jù)此書編著《西方經(jīng)濟(jì)學(xué)》教材,在書中出現(xiàn)“經(jīng)濟(jì)學(xué)10大原理”一詞,一眼便可看出是抄襲而來(lái)。

      2、薩繆爾森《經(jīng)濟(jì)學(xué)》(Economics)

      薩繆爾森,新古典綜合學(xué)派的代表人物,1970年成為第一個(gè)榮獲諾貝爾經(jīng)濟(jì)學(xué)獎(jiǎng)的美國(guó)人。研究范圍橫跨經(jīng)濟(jì)學(xué)、統(tǒng)計(jì)學(xué)和數(shù)學(xué)多個(gè)領(lǐng)域,對(duì)政治經(jīng)濟(jì)學(xué)、部門經(jīng)濟(jì)學(xué)和技術(shù)經(jīng)濟(jì)學(xué)有獨(dú)到的見(jiàn)解。目前經(jīng)濟(jì)學(xué)各種教科書,所使用的分析框架及分析方法,多采用由他1947年的《微觀經(jīng)濟(jì)分析》發(fā)展糅合凱恩斯主義和傳統(tǒng)微觀經(jīng)濟(jì)學(xué)而成的“新古典綜合學(xué)派”理論框架。他一直熱衷于把數(shù)學(xué)工具運(yùn)用于靜態(tài)均衡和動(dòng)態(tài)過(guò)程的分析,以物理學(xué)和數(shù)學(xué)論證推理方式研究經(jīng)濟(jì)。目前經(jīng)濟(jì)學(xué)理論數(shù)學(xué)化大行其道,此翁實(shí)始作俑者。

      全書結(jié)構(gòu)宏偉,篇幅巨大??芍^博大精深。滲透老薩數(shù)十年經(jīng)濟(jì)學(xué)見(jiàn)解。字里行間,三言兩語(yǔ),每有深意。其中諸如“熱情的心,冷靜的頭腦”、“相關(guān)未必因果”等言語(yǔ),可謂經(jīng)濟(jì)學(xué)之《老子》。讀完該書,可了解經(jīng)濟(jì)學(xué)所探討問(wèn)題在經(jīng)濟(jì)學(xué)體系中之位置及分析框架,對(duì)經(jīng)濟(jì)學(xué)有一個(gè)完備之認(rèn)識(shí)框架。知識(shí)龐雜,有一體系框架,則適宜以后更進(jìn)一步學(xué)習(xí)。學(xué)之愈深,愈知此框架之重要。盡管該框架在宏觀經(jīng)濟(jì)學(xué)的微觀基礎(chǔ)方面仍有斷層,但不失為一個(gè)好框架。此書國(guó)內(nèi)有機(jī)工版發(fā)行之英文版。建議直接閱讀英文版。

      3、斯蒂格利姿《經(jīng)濟(jì)學(xué)》及系列輔助教材。斯蒂格利姿在信息經(jīng)濟(jì)學(xué)成就甚高,此書可作為前二者的補(bǔ)充,前二者所涉及經(jīng)濟(jì)學(xué)內(nèi)容主要是以價(jià)格理論及邊際分析為基礎(chǔ),不包括不對(duì)稱信息經(jīng)濟(jì)學(xué)、不確定性分析部分。斯蒂格利姿之《經(jīng)濟(jì)學(xué)》可填充前二者之空白。

      盡管三位作者政策傾向不同,但教材體現(xiàn)凱恩斯主義的特征稍多一點(diǎn),總體上講,教材相當(dāng)客觀和公允。很適宜做入門教材。

      4、《經(jīng)濟(jì)學(xué)、原理、問(wèn)題與政策》及《經(jīng)濟(jì)學(xué)原理與問(wèn)題》、〈經(jīng)濟(jì)學(xué)案例〉、〈經(jīng)濟(jì)學(xué)小品〉、《經(jīng)濟(jì)學(xué)悖論》、〈社會(huì)問(wèn)題經(jīng)濟(jì)學(xué)〉等。此類書之特點(diǎn)是先提問(wèn)題,再論原理,主要是針對(duì)社會(huì)習(xí)見(jiàn)問(wèn)題,逐步解釋原理,水平、內(nèi)容大多較好,唯缺乏體系與框架,適宜略懂經(jīng)濟(jì)學(xué)者補(bǔ)充學(xué)習(xí)。

      5、國(guó)內(nèi)老師自行編寫之《西方經(jīng)濟(jì)學(xué)》教材:目前國(guó)內(nèi)各大學(xué)自己編寫的直接冠以《西方經(jīng)濟(jì)學(xué)》或〈經(jīng)濟(jì)學(xué)原理〉均屬入門教材。如高鴻業(yè)、歷以寧、宋承先、梁小民、朱錫慶、尹伯成、司春林等等。然皆遠(yuǎn)遜外國(guó)教材。

      說(shuō)明: 1)、越基礎(chǔ)性之教材越需深入淺出,將復(fù)雜抽象的道理聯(lián)系到生活實(shí)際上,才講的透徹,又能調(diào)起初學(xué)者之興趣。國(guó)外教材,形成一競(jìng)爭(zhēng)市場(chǎng),多極高明之著作,教材之撰寫也充分考慮學(xué)生學(xué)習(xí)之便利,如曼昆之教材,以完全不帶數(shù)學(xué)式而著稱,又或更新?lián)Q版本極快,以及時(shí)吸收新知識(shí),如斯蒂格利姿《經(jīng)濟(jì)學(xué)》之增加不對(duì)稱信息部分。低手所寫教材自然被市場(chǎng)淘汰。故市面之基礎(chǔ)教材,多為大高手所寫就。

      2)、國(guó)內(nèi)教材,建國(guó)以來(lái),除商務(wù)系列叢書初期之100年前古典學(xué)派部分,政府同意翻譯以作為馬克思批判之反面教材得以出版外,80年代以前,近50年間國(guó)外經(jīng)濟(jì)學(xué)研究學(xué)問(wèn)之成就,國(guó)人皆不得見(jiàn)。80年代末期,鄒至莊先生力倡西方經(jīng)濟(jì)學(xué),鄧大人首肯之后,國(guó)內(nèi)始漸有〈西方經(jīng)濟(jì)學(xué)〉之類教材出現(xiàn)。此類教材,多為新出道之老師,為進(jìn)階升職,湊出版物之?dāng)?shù)而編抄西人著作而成,機(jī)制所限,不敢添加“反動(dòng)”之知識(shí),又無(wú)競(jìng)爭(zhēng)機(jī)制,購(gòu)買者多為其聽(tīng)課學(xué)生。故質(zhì)量甚差,若非特殊目的如考研指定者,慎勿購(gòu)買。

      3)、按經(jīng)濟(jì)學(xué)有入門低、中級(jí)、高級(jí)之分。高級(jí)乃指其運(yùn)用之?dāng)?shù)學(xué)工具及闡述觀點(diǎn)之紛爭(zhēng)更多而言,并非此學(xué)問(wèn)高人一等。一如高等數(shù)學(xué)未必高初等數(shù)學(xué)一等之意。越是高級(jí),則越多分歧,也越追求數(shù)理邏輯之嚴(yán)謹(jǐn),反不如低級(jí)來(lái)的實(shí)用。初級(jí)的入門教材一般是針對(duì)初學(xué)者,所以大多舉案例和現(xiàn)象,加以文字解釋,偶爾插加二維圖案,高級(jí)教材注重?cái)?shù)理邏輯,而二維圖案及文字已難以表達(dá)、解決所說(shuō)明之問(wèn)題,故多用數(shù)學(xué)證明或代數(shù)方程,夾雜現(xiàn)代數(shù)學(xué)工具。中級(jí)教材則介乎其中,界定甚為模糊。教材難度不同,跨度也相差很大。

      二、中級(jí)微觀教材。

      中級(jí)教材一般以微觀、宏觀兩科為主,兼修其他應(yīng)用科目。傳統(tǒng)經(jīng)濟(jì)學(xué),本無(wú)宏觀、微觀之分,自凱恩斯針對(duì)名義變量進(jìn)行宏觀經(jīng)濟(jì)分析之后,始有宏觀一科。故歷來(lái)次序,先修微觀,再修宏觀,后及其他。

      微觀經(jīng)濟(jì)學(xué)為各科之基礎(chǔ)。其分析,乃基于馬歇爾的一般均衡分析及邊際效用學(xué)派之邊際分析,而后由薩謬而森發(fā)展數(shù)學(xué)方法及框架而成,涵蓋范圍甚廣,大致包括:

      基礎(chǔ)部分:傳統(tǒng)廠商理論(技術(shù)、利潤(rùn)、成本)、傳統(tǒng)消費(fèi)者理論(效用、偏好、選擇、需求)、局部均衡理論(完全競(jìng)爭(zhēng)市場(chǎng)之穩(wěn)定性)、一般均衡理論(福利經(jīng)濟(jì)學(xué)二大定理、交換方框圖)

      分支部分:寡占市場(chǎng)理論(寡頭、定價(jià)、市場(chǎng)細(xì)分)、博奕論(純策略均衡、混合博奕、廣延型結(jié)構(gòu)、廠商博奕、顫抖的手)、公共物品理論(公共物品、稅收制度設(shè)計(jì)、投票、外部效應(yīng))、不確定性經(jīng)濟(jì)學(xué)(風(fēng)險(xiǎn)、博采、保險(xiǎn)、投資)、信息經(jīng)濟(jì)學(xué)(不對(duì)稱信息、逆向選擇、信號(hào))、激勵(lì)理論(委托-代理理論、契約理論)、法和經(jīng)濟(jì)學(xué)(制度經(jīng)濟(jì)學(xué)、企業(yè)性質(zhì)分析、法律)、拍賣理論(拍賣機(jī)制設(shè)計(jì))、匹配理論等。

      學(xué)習(xí)者可根據(jù)上述內(nèi)容,與教材所列提綱比較,則可知教材側(cè)重點(diǎn)之所在。

      6《管理經(jīng)濟(jì)學(xué)》,有版本數(shù)種,特點(diǎn)各不相同。此類教材多為mba系列教材。其目的針對(duì)生產(chǎn)過(guò)程決策而設(shè),故與經(jīng)濟(jì)學(xué)之中級(jí)微觀教材相較而言,減少少量分支部分理論,增加回歸分析及計(jì)量統(tǒng)計(jì)部分。目前數(shù)種版本中,以人大版〈工商管理經(jīng)典譯從〉難度最低。機(jī)工版哈耶所寫之〈管理經(jīng)濟(jì)學(xué)-戰(zhàn)略與決策〉與標(biāo)準(zhǔn)中級(jí)教材難度大致相當(dāng),內(nèi)容也接近。唯其中也已采用函數(shù)表達(dá)式。機(jī)工版莫瑞斯(有英文版及中文版,中文為陳章武所譯)〈管理經(jīng)濟(jì)學(xué)〉難度最高,其側(cè)重內(nèi)容與中級(jí)教材大不相同,除回歸分析已采用大量數(shù)據(jù),要求建立模型,內(nèi)容接近計(jì)量預(yù)測(cè)外,內(nèi)容涉及對(duì)偶理論、不同代替效應(yīng)之圖解,附錄采用微分法,難度較高。此類書籍,側(cè)重經(jīng)濟(jì)學(xué)中與管理交叉管理。

      7、平狄克《微觀經(jīng)濟(jì)學(xué)》。人大版,此書乃標(biāo)準(zhǔn)中級(jí)微觀經(jīng)濟(jì)學(xué)教材。在美國(guó)多個(gè)大學(xué)供mba采用,國(guó)內(nèi)英文版有清華版,中文版有人大版。此書內(nèi)容適中,主題廣泛,均是各部分理論之要點(diǎn),不旁及其他分歧內(nèi)容,其中定價(jià)部分較為詳細(xì)。圖形清晰,語(yǔ)言流暢。所采用數(shù)學(xué)工具甚淺,有函數(shù)但不涉及微分,只用差值。曲線只用標(biāo)準(zhǔn)嚴(yán)格凹性曲線,不及擬凹部分、線性仿射內(nèi)容,成本函數(shù)也均為線性。建議此書應(yīng)通讀,可作進(jìn)階之用。

      8、曼斯非爾特《微觀經(jīng)濟(jì)學(xué)》人大版,內(nèi)容、難度、書價(jià)與平狄克相仿,唯編排次序不同。體系稍顯龐雜,不如平狄克之明晰,然也為一國(guó)外通行教材。若修習(xí)近平狄克有不明之處,則可先參照此教材或先修學(xué)其他國(guó)內(nèi)出版之書籍。如北大系列教材之周惠中〈微觀經(jīng)濟(jì)學(xué)〉,北大版朱善利之《微觀經(jīng)濟(jì)學(xué)》等。此書不屬必讀。

      9、《國(guó)外經(jīng)濟(jì)學(xué)教材庫(kù)》系列之《應(yīng)用微觀經(jīng)濟(jì)學(xué)》,32開,經(jīng)濟(jì)科學(xué)出版社。此書有大量案例及微觀經(jīng)濟(jì)原理之運(yùn)用,所用數(shù)學(xué)甚少,讀此書,可補(bǔ)充平狄克教材之案例。加深對(duì)經(jīng)濟(jì)學(xué)之了解。

      10、〈微觀經(jīng)濟(jì)學(xué): 現(xiàn)代觀點(diǎn)〉(Intermediate microeconomics)[美] 范里安(Varian, Hal R.)著,費(fèi)方域翻譯。據(jù)美國(guó)W.W.諾頓圖書公司 1990年版譯出,三聯(lián)版。此書是極規(guī)范之經(jīng)濟(jì)學(xué)專業(yè)的中級(jí)微觀教材。美國(guó)MIT,哈佛、伯克利經(jīng)濟(jì)學(xué)本科指定教材。32開,800多頁(yè)。易懂而深刻。本書為第二版,內(nèi)容除論述了市場(chǎng)、消費(fèi)者偏好、需求、技術(shù)、利潤(rùn)、生產(chǎn)等問(wèn)題,還增加了兩章, 分別論述了要素供給和信息經(jīng)濟(jì)等。內(nèi)容上相當(dāng)關(guān)注技術(shù)細(xì)節(jié)問(wèn)題,比平狄克要更深一些。范里安微觀經(jīng)濟(jì)學(xué)與數(shù)學(xué)造詣極深。然此書乃其為學(xué)生所寫之中級(jí)教材,刻意避免數(shù)學(xué)之應(yīng)用,大部分?jǐn)?shù)學(xué)推導(dǎo)放于附錄,微分運(yùn)用相當(dāng)少,適宜學(xué)完平狄克后重點(diǎn)閱讀??勺髌降铱酥懈鞑糠掷碚搩?nèi)容之拓展。

      三、中級(jí)宏觀教材。若無(wú)意進(jìn)一步學(xué)習(xí)高級(jí)微觀經(jīng)濟(jì)學(xué),則可同時(shí)學(xué)習(xí)宏觀經(jīng)濟(jì)學(xué)。微觀的特點(diǎn)是精深,宏觀則是駁雜。因?yàn)楹暧^流派很多,觀點(diǎn)各不相同。

      11、《宏觀經(jīng)濟(jì)學(xué)》曼昆,人大版。中文翻譯。此書秉承曼昆〈經(jīng)濟(jì)學(xué)原理〉之優(yōu)點(diǎn),以簡(jiǎn)單,淺顯為特點(diǎn)。雖只有很少量的數(shù)學(xué),但對(duì)原理及內(nèi)容均提煉得甚為簡(jiǎn)潔。前半部分寫得相當(dāng)清晰??勺x完薩謬而森《經(jīng)濟(jì)學(xué)》并略懂一點(diǎn)微觀后直接學(xué)習(xí)。適宜一個(gè)循環(huán)學(xué)習(xí),即以書入手,修完《全球視角》后,再回頭重修此書,有提綱挈領(lǐng)之用。缺點(diǎn)是作者似乎限于門戶之見(jiàn),對(duì)真實(shí)周期學(xué)派、奧地利學(xué)派等其他學(xué)派提得很少。建議閱讀。

      12、《宏觀經(jīng)濟(jì)學(xué)》多恩布什。人大版中文翻譯,東北財(cái)大有影印英文版。此書是標(biāo)準(zhǔn)的中級(jí)宏觀教材,屬正統(tǒng)教材。體系清楚,描述準(zhǔn)確,通行于美國(guó)各大學(xué)多年。采用凱恩斯IS-LM體系為框架,對(duì)各個(gè)流派評(píng)價(jià)及描述相當(dāng)公平。推薦必讀。

      13、《宏觀經(jīng)濟(jì)學(xué)》人大版,中文翻譯。羅伯特霍爾,整本書顯得有點(diǎn)凌亂,適宜讀過(guò)其他中級(jí)宏觀再做印證之用,內(nèi)容比上述兩本教材略深。不屬必讀范圍。

      14、《宏觀經(jīng)濟(jì)學(xué)》巴羅。清華,影印英文版。巴羅宏觀經(jīng)濟(jì)學(xué)造詣很深,主要研究領(lǐng)域在經(jīng)濟(jì)增長(zhǎng)理論。但寫的書卻銷路很差。學(xué)這本書可作為對(duì)上述教材所屬凱恩斯學(xué)派的一個(gè)補(bǔ)充。不屬必讀范圍。

      15、《全球視角的宏觀經(jīng)濟(jì)學(xué)》三聯(lián)版 杰佛里薩克斯,32開,1000頁(yè)。薩克斯成功處理了南美高通貨膨脹的問(wèn)題,但書一樣寫的相當(dāng)好,整本書注意細(xì)節(jié)而有條理。很適宜讀完多恩布什《宏觀經(jīng)濟(jì)學(xué)》后進(jìn)一步閱讀。以拓展知識(shí)。上述5種教材所用符號(hào)各不相同,對(duì)學(xué)習(xí)者實(shí)在甚為不便。

      16、《國(guó)際經(jīng)濟(jì)學(xué)》 保羅克魯格曼,今日之宏觀經(jīng)濟(jì)學(xué),已很難討論封閉的宏觀經(jīng)濟(jì),此書可謂進(jìn)一步拓展的宏觀經(jīng)濟(jì)學(xué),包括國(guó)際貿(mào)易和國(guó)際金融兩個(gè)部分,滲透克魯格曼的經(jīng)濟(jì)思想,所采用框架為AS-AD框架,可作IS-LM框架的補(bǔ)充。推薦閱讀。

      17《現(xiàn)代宏觀經(jīng)濟(jì)學(xué)發(fā)展與反思》及《現(xiàn)代宏觀經(jīng)濟(jì)學(xué)指南-各思想流派分析》及《與經(jīng)濟(jì)學(xué)大師對(duì)話》系列三冊(cè),前兩冊(cè)為商務(wù)版。此書乃對(duì)各不同流派經(jīng)濟(jì)學(xué)大師的采訪和評(píng)論,對(duì)各個(gè)流派的異同可以有清楚的了解,而且是直面經(jīng)濟(jì)學(xué)大師,可以看到各個(gè)大師之間彼此的觀點(diǎn)不同,甚至成見(jiàn)立場(chǎng),互相抨擊之處,實(shí)在有趣。推薦閱讀。

      四、其他教材:

      18、人大版《經(jīng)濟(jì)科學(xué)譯叢》系列之其他大多數(shù)教材:《經(jīng)濟(jì)思想史》、《財(cái)政學(xué)》、《公共部門經(jīng)濟(jì)學(xué)》、《人事經(jīng)濟(jì)學(xué)》、《金融學(xué)》(博迪)、《投資學(xué)》、《貨幣銀行學(xué)》(米十金)等等實(shí)務(wù)應(yīng)用之科目。適當(dāng)補(bǔ)充閱讀〈公共選擇理論〉、奧地利學(xué)派、哈耶克、劍橋之爭(zhēng)、非瓦爾拉斯均衡分析、等等內(nèi)容。

      19、三聯(lián)叢書黃皮書系列,其中顯要者如《公共經(jīng)濟(jì)學(xué)》(Lectures on public economics)(阿特金森(Atkinson, Anthony B.)[美] 斯蒂格里茨(Stiglitz, Joseph E.)著)、〈政治與市場(chǎng): 世界的政治—經(jīng)濟(jì)制度》、《財(cái)產(chǎn)權(quán)利與制度變遷: 產(chǎn)權(quán)學(xué)派與新制度學(xué)派譯文集》、《經(jīng)濟(jì)史中的結(jié)構(gòu)與變遷》、《貨幣、銀行與經(jīng)濟(jì)》(Money, Banking, and the Economy)〔美國(guó)〕托馬斯?梅耶(Thomas Mayer)、〈法和經(jīng)濟(jì)學(xué)〉等等。可對(duì)經(jīng)濟(jì)學(xué)之應(yīng)用領(lǐng)域獲得一個(gè)深刻視角。三聯(lián)叢書,推薦全部閱讀。

      20、張五?!顿u橘者言》、《佃農(nóng)理論》、《經(jīng)濟(jì)解釋》。張老先生近年是國(guó)內(nèi)焦點(diǎn)所在,也寫了幾本〈隨筆〉,發(fā)表不少演講,大體而言,〈隨筆〉不堪一讀,其中論書法、攝影部分,不關(guān)主旨,且水平甚低,多屬偏頗之見(jiàn),今不論之。唯上述專著中之〈佃農(nóng)理論〉,見(jiàn)解獨(dú)到,尤有過(guò)人之處。建議修完中級(jí)微觀后仔細(xì)閱讀?!督?jīng)濟(jì)解釋》則為論文集,然其中也有不少過(guò)激之言論及偏見(jiàn),不可以教材視之。其中“合約理論”部分,可以一讀。論“共產(chǎn)主義”部分,則未必有理。

      21、楊小凱〈經(jīng)濟(jì)學(xué)原理〉〈新興超邊際古典經(jīng)濟(jì)學(xué)〉,楊先生氣魄甚大,欲以一己之力重寫傳統(tǒng)經(jīng)濟(jì)學(xué)體系,與汪丁丁先生有異曲同工之妙??芍^經(jīng)濟(jì)學(xué)之異端,讀之可開闊視野。推薦閱讀。

      22、〈波斯納文集〉蘇力翻譯。老先生以法學(xué)專才,寫〈法之經(jīng)濟(jì)學(xué)分析〉,實(shí)一極高明之人士,于此不可不提。推薦閱讀。

      23、商務(wù)叢書《漢譯世界名著》系列:此叢書系列,自二十世紀(jì)初商務(wù)王云五先生主持,與是事者不計(jì)其數(shù),除文革中斷十余年外,每年陸續(xù)出版,涵蓋哲學(xué)(紅皮)、歷史(黃皮)、政治(綠皮)、經(jīng)濟(jì)(藍(lán)皮)、語(yǔ)言學(xué)、人類學(xué)(未成),所翻譯者,非經(jīng)典不收,皆大師之精華,所主持翻譯之人,多博學(xué)鴻儒或一代大師。單經(jīng)濟(jì)一門,翻譯之著作,至今已近百種。百年間,傳播知識(shí)無(wú)數(shù),可謂功德無(wú)量。讀完藍(lán)皮經(jīng)濟(jì)類之全部,則可通曉經(jīng)濟(jì)學(xué)之來(lái)龍去脈。

      至此,無(wú)意于經(jīng)濟(jì)學(xué)一門謀生者,已然足夠。然上述書籍,常人閱讀,少者耗時(shí)約需1、2年以上。多者3、5年。且其中論著,多高明之作,或有一讀再讀之需,而讀完,也或有“屠龍之技”之感也未之定,一笑!

      五、數(shù)學(xué)工具:即所謂數(shù)理經(jīng)濟(jì)學(xué)一科。

      若數(shù)學(xué)水平較高,有意進(jìn)一步玩弄經(jīng)濟(jì)學(xué)之?dāng)?shù)學(xué)智力游戲,則可參讀以下數(shù)學(xué)工具:中國(guó)大學(xué)本科考研究生之?dāng)?shù)學(xué)三(高數(shù)、線性代數(shù)、概率論與數(shù)理統(tǒng)計(jì))為必修之基礎(chǔ)課,其他之?dāng)?shù)學(xué)工具則包括拓?fù)鋵W(xué)初步(凸集、凹集、微分方程穩(wěn)定性)、線性規(guī)劃(代數(shù)理論、幾何理論、對(duì)偶理論)、非線性規(guī)劃(不等式約束規(guī)劃)、變分法(歐拉方程、泛函函數(shù)、收斂問(wèn)題、可變端點(diǎn)、橫截條件、勒讓得必要條件、相圖分析)、最優(yōu)控制理論(最大值原理、漢密爾頓函數(shù))、連續(xù)時(shí)間優(yōu)化規(guī)劃、離散時(shí)間優(yōu)化規(guī)劃(不動(dòng)點(diǎn)性質(zhì)、值函數(shù))、時(shí)間序列分析、非線性混沌系統(tǒng)、隨機(jī)變量等等。

      24、《經(jīng)濟(jì)學(xué)中的數(shù)學(xué)》(入門水平)

      25、蔣中一《數(shù)理經(jīng)濟(jì)學(xué)基礎(chǔ)》(基礎(chǔ)水平)

      26、《動(dòng)態(tài)優(yōu)化基礎(chǔ)》(進(jìn)階水平)

      27、高山成(takayama)《經(jīng)濟(jì)學(xué)中的優(yōu)化方法》(推薦閱讀)

      28、龔六堂《經(jīng)濟(jì)學(xué)中的優(yōu)化方法》(推薦閱讀)

      29、《經(jīng)濟(jì)學(xué)中的動(dòng)態(tài)遞歸方法》(推薦閱讀)

      30、〈數(shù)理經(jīng)濟(jì)學(xué)手冊(cè)〉人大版(重點(diǎn)閱讀)

      六、中高級(jí)微觀經(jīng)濟(jì)學(xué):下文書籍,未必盡是高明著作,然國(guó)內(nèi)此類教材甚少,下述書籍,聊勝于無(wú)。

      31、平新喬的《微觀經(jīng)濟(jì)學(xué)18講》,北大出版。內(nèi)容屬于中高級(jí)微觀經(jīng)濟(jì)學(xué),涉及微觀領(lǐng)域較多,引入大量的數(shù)學(xué)運(yùn)算,除文字內(nèi)容外,強(qiáng)調(diào)邏輯推理。惟書中有不少印刷錯(cuò)誤,且理論內(nèi)容跳躍太快,不利學(xué)習(xí)理解,數(shù)學(xué)運(yùn)用龐雜,不夠明快清晰。在國(guó)內(nèi)中高級(jí)教材中屬中上之作,接近國(guó)外大學(xué)本科高年級(jí)水平。最大的優(yōu)點(diǎn)是書后付有大量需要運(yùn)算的習(xí)題,均需花時(shí)間讀書和思考才能解決,很適宜學(xué)習(xí)訓(xùn)練。對(duì)從中級(jí)到高級(jí)過(guò)渡有幫助。不屬必讀范圍。

      32、張定勝《高級(jí)微觀經(jīng)濟(jì)學(xué)》。武大出版。此書屬于中高級(jí)內(nèi)容,因涉及主題較少,故比平新喬之〈18講〉顯得清晰。適宜找不到其他中高級(jí)教材,而高級(jí)教材又甚困難,可以此書做過(guò)渡。

      33、Nicholson < Microeconomic Theory>>。國(guó)內(nèi)中文翻譯出版。此書微積分運(yùn)用、數(shù)學(xué)運(yùn)算簡(jiǎn)潔明晰,全書難度、體系一致,排版清楚、內(nèi)容重點(diǎn)突出,主題有深度,實(shí)為一極佳之中高級(jí)教材。書后之參考書目適宜進(jìn)一步學(xué)習(xí)參考,為中級(jí)教材之中,最適宜和高級(jí)教材接軌者,唯書價(jià)稍貴,習(xí)題難度不深,習(xí)題量稍顯不足。此書似乎出版發(fā)行量不多,除北大、復(fù)旦等處書店有少量可見(jiàn)外,其他大學(xué)及城市似甚少見(jiàn)。推薦閱讀。

      34、蔣殿春《高級(jí)微觀經(jīng)濟(jì)學(xué)》,經(jīng)濟(jì)管理出版社。此書主題基礎(chǔ)部分已達(dá)高級(jí)水平,難度甚大。至博奕論以后部分,則難度甚淺。或與日本經(jīng)濟(jì)學(xué)之教授方法有關(guān)。對(duì)傳統(tǒng)的價(jià)格理論的數(shù)學(xué)描述相當(dāng)清楚。數(shù)學(xué)證明部分清楚。推薦閱讀。

      第三篇:管理學(xué)入門書籍[范文模版]

      管理學(xué)入門書籍

      科目推薦書目

      孫耀君,《西方管理學(xué)名著提要》,江西人民出版社

      ****管理學(xué)****

      斯蒂芬·P·羅賓斯,《管理學(xué)》,中國(guó)人民大學(xué)出版社

      邢以群,《管理學(xué)》,浙江大學(xué)出版社

      周三多,《管理學(xué)》,復(fù)旦大學(xué)出版社

      ****管理信息系統(tǒng)****

      Kenneth C.Laudon/ Jane P.Laudon,《管理信息系統(tǒng)—網(wǎng)絡(luò)化企業(yè)的組織與技術(shù)》(第六版,影印版),高等教育出版社

      斯蒂芬 ·哈格等,《信息時(shí)代的管理信息系統(tǒng)》,機(jī)械工業(yè)出版社

      薛華成,《管理信息系統(tǒng)》(第三版),清華大學(xué)出版社

      ****市場(chǎng)營(yíng)銷****

      菲利浦·科特勒,《市場(chǎng)營(yíng)銷》,清華大學(xué)出版社

      小威廉D.佩勒爾特 E.杰羅姆.麥卡錫,《市場(chǎng)營(yíng)銷學(xué)基礎(chǔ):全球管理(英文版.第12版)--國(guó)際通用MBA教材》,機(jī)械工業(yè)出版社

      郭毅等,《市場(chǎng)營(yíng)銷學(xué)原理》,電子工業(yè)出版社

      Malhotra,N.K.著,《市場(chǎng)營(yíng)銷研究應(yīng)用導(dǎo)向(第3版)》,電子工業(yè)出版社

      ****戰(zhàn)略管理****

      項(xiàng)保華,《戰(zhàn)略管理——藝術(shù)與實(shí)務(wù)》,華夏出版社

      邁克爾·波特,《競(jìng)爭(zhēng)戰(zhàn)略》,華夏出版社

      邁克爾·波特,《競(jìng)爭(zhēng)優(yōu)勢(shì)》,華夏出版社

      享利·明茨伯格(美),《戰(zhàn)略歷程》,機(jī)械工業(yè)出版社

      斯蒂文斯(英),《戰(zhàn)略性思維》,機(jī)械工業(yè)出版社

      Arthur A.Thompson, Jr.And A.J.Stricklan Ⅲ.Crafting&Implementing Strategy.6th Ed.Richard

      D.Irwin, Inc., 1995中文版《戰(zhàn)略管理學(xué):概念與案例(英文版.第十版)--國(guó)際通用MBA教材》,機(jī)械

      工業(yè)出版社

      David Besanko, David Dranove, & Mark Shanley.The Economics of Strategy.John Wiley & Sons, Inc.,1996

      Alan J.Rowe;et al..Strategic Management: A Methodological Approach.4th Ed.Addison-Wesley

      Publishing Company, Inc., 199

      4****組織行為學(xué)****

      斯蒂芬·P·羅賓斯,《組織行為學(xué)精要(原書第7版)--MBA教材精品譯叢》,機(jī)械工業(yè)出版社

      Steven L.McShane;Mary Ann Von Glinow,《組織行為學(xué)(英文版)--21世紀(jì)經(jīng)典原版經(jīng)濟(jì)管理教材文庫(kù)》,電子工業(yè)出版社

      盧盛忠等,《組織行為學(xué):理論與實(shí)踐》,浙江教育出版社

      ****人力資源管理****

      雷蒙德.A.諾伊,約翰.霍倫拜克,拜雷.格哈特,帕特雷克.萊特,《人力資源管理——贏得競(jìng)爭(zhēng)優(yōu)勢(shì)》(第三版)中國(guó)人民大學(xué)出版社英文版《Human Resource

      Management: Gaining a Competitive Advantage》,清華大學(xué)出版社

      約翰.M.伊萬(wàn)切維奇,《人力資源管理(英文版.原書第8版)--國(guó)際通用MBA教材》,機(jī)械工業(yè)出版社 Luis R.Gomez-Mejia,David B.Balkin,Robert L.Cardy,《管理人力資源 Managing Human Resources 》

      (英文版第三版),北京大學(xué)出版社

      ****財(cái)務(wù)管理****

      斯蒂芬·羅絲,《公司理財(cái)》,機(jī)械工業(yè)出版社

      ****管理統(tǒng)計(jì)****

      David R.Anderson Dennis J.Sweeney Thomas A.William,《商務(wù)與經(jīng)濟(jì)統(tǒng)計(jì)(第七版)--經(jīng)濟(jì)教材譯

      叢》,機(jī)械工業(yè)出版社

      David R.Anderson;Dennis J.Sweeney;Thomas A.William,《商務(wù)與經(jīng)濟(jì)統(tǒng)計(jì)(英文版.第8版)--21世紀(jì)

      經(jīng)典原版經(jīng)濟(jì)管理教材文庫(kù)》,機(jī)械工業(yè)出版社

      ****會(huì)計(jì)學(xué)****

      張啟鑾等,《會(huì)計(jì)學(xué)――工商管理碩士(MBA)系列教材》,大連理工大學(xué)出版社

      Cktde P.Stickney Roman L.Weil,《財(cái)務(wù)會(huì)計(jì)(英文版第9版)--國(guó)際通用MBA教材》,機(jī)械工業(yè)出版社

      Ronald W.Hilton,《管理會(huì)計(jì)(英文版.第三版)--國(guó)際通用MBA教材》,機(jī)械工業(yè)出版社

      ****西方經(jīng)濟(jì)學(xué)****

      [美]平狄克等:《微觀經(jīng)濟(jì)學(xué)》,中國(guó)人民大學(xué)出版社

      梁小民,《宏觀經(jīng)濟(jì)學(xué)》,中國(guó)社會(huì)科學(xué)出版社

      梁小民,《西方經(jīng)濟(jì)學(xué)導(dǎo)論》,北京大學(xué)出版社

      宋承先,《現(xiàn)代西方經(jīng)濟(jì)學(xué)》(宏觀經(jīng)濟(jì)學(xué)),復(fù)旦大學(xué)出版社

      [美] H.克雷格.彼得森等:《管理經(jīng)濟(jì)學(xué)》,中國(guó)人民大學(xué)出版社

      [美]S.Charles Maurice & Christopher R.Thomas, ManagerialEconomics, 機(jī)械工業(yè)出版社,2000年影印

      ****經(jīng)濟(jì)法****

      高程德,《經(jīng)濟(jì)法》(第九版),上海人民出版社

      ****電子商務(wù)****

      Daniel Amor,《電子商務(wù):變革與演進(jìn)--經(jīng)濟(jì)教材譯叢》,機(jī)械工業(yè)出版社

      ****組織理論****

      [美]達(dá)夫特著,李維安譯.《組織理論與設(shè)計(jì)精要》,機(jī)械工業(yè)出版社

      [英]Bernard Burnes.《變革時(shí)代的管理》,云南大學(xué)出版社

      [美]F·赫塞爾本等.未來(lái)的組織,四川人民出版社

      ****質(zhì)量管理****

      劉廣第,《質(zhì)量管理學(xué)(第二版)》,清華大學(xué)出版社

      ****生產(chǎn)管理****

      陳榮秋、馬士華,生產(chǎn)與運(yùn)作管理,高等教育出版社,1999 潘家軺等,現(xiàn)代生產(chǎn)管理學(xué),北京:清華大學(xué)出版社,1994 黃衛(wèi)偉,生產(chǎn)與作業(yè)管理,北京:人民大學(xué)出版社,1997

      ****項(xiàng)目管理****

      畢星、翟麗,《項(xiàng)目管理》,復(fù)旦大學(xué)出版社,2000

      [美]杰克.吉多等著, 《成功的項(xiàng)目管理》,機(jī)械工業(yè)出版社,1999白思俊主編, 《現(xiàn)代項(xiàng)目管理》(上,中,下),機(jī)械工業(yè)出版社,2002

      第四篇:股票入門書籍推薦

      股票入門書籍推薦

      1.道氏理論

      《股市晴雨表》(美)漢密爾頓

      2.K線

      《股票K線戰(zhàn)法》(美)史蒂夫·尼森

      《日本蠟燭圖技術(shù)》(美)史蒂夫·尼森

      3。波浪理論

      《波浪原理》(美)艾略特

      4?;煦绾头中?/p>

      《證券混沌操作法》(美)比爾。廉姆斯

      《資本市場(chǎng)的混沌與秩序》(美)埃德加。E。彼得斯

      《分形市場(chǎng)分析--將混沌理論應(yīng)用到投資與經(jīng)濟(jì)理論上》 埃德加?E?彼得斯

      5。交易心理

      《直覺(jué)交易商》(美)羅伯特。庫(kù)佩爾

      《冷靜自信的交易策略》(美)理查。邁克爾

      《逆向思考的藝術(shù)》(美)漢弗萊?B?尼爾

      《逆向投資策略》(美)戴維?德瑞曼

      《大眾心理與走勢(shì)預(yù)測(cè)》(美)托尼?普盧默

      6。技術(shù)方法

      《股市趨勢(shì)技術(shù)分析》(美)約翰.墨吉

      《期貨市場(chǎng)技術(shù)分析》(美)約翰?墨菲

      《期貨交易技術(shù)分析》(美)施威格

      《股票操作學(xué)》(臺(tái)灣)張齡松

      《短線交易秘訣》(美)拉瑞。威謙姆斯

      《專業(yè)投機(jī)原理》(美)維克多?斯波朗迪

      《技術(shù)分析精論》(美)馬丁。J。普林格

      《股市無(wú)敵》(美)小理查德阿姆斯

      7。系統(tǒng)方法

      《通向金融王國(guó)的自由之路》(美)范。K。撒普

      《系統(tǒng)交易方法》 波濤

      《證券期貨投資計(jì)算機(jī)化技術(shù)分析原理》 波濤

      8。理念

      《克羅談投資策略》 斯坦利.克羅

      《期貨交易策略》 斯坦利.克羅

      《投機(jī)智慧》(香港)許沂光

      《華爾街點(diǎn)金人》(美)施威格

      《美國(guó)期貨專家經(jīng)驗(yàn)談》(美)威可夫

      9。人物傳記

      《股票作手回憶錄》(美)愛(ài)德溫.李費(fèi)佛

      《交易冠軍》 馬丁.舒華茲

      《投機(jī)生涯》(美)維克多。尼德霍夫

      作為一個(gè)沒(méi)有做過(guò)股票的朋友,如果現(xiàn)在開始準(zhǔn)備做股票了 我覺(jué)得第一步要知道做股票的游戲規(guī)則,就是怎么玩

      記得《專業(yè)投機(jī)原理》的開篇講了一個(gè)很生動(dòng)的故事“賭博例”

      喬是撲克好手,但他卻在一次和農(nóng)民玩的撲克賭局中輸?shù)纳頍o(wú)分文 不是農(nóng)民的技巧有多高,一切只因?yàn)閱滩涣私猱?dāng)?shù)負(fù)淇说挠螒蛞?guī)則 那么,做股票也是同樣的道理

      你首先要充分了解整個(gè)股票的操作流程和交易規(guī)則 越詳細(xì)越具體越好

      例如,怎么買入怎么賣出怎么參與配股,st和非st有什么區(qū)別,代星號(hào)的st又代表什么意思,具體的成交順序,交易時(shí)間,買入最小單位是1手,賣出可以零碎,1手表示多少股,怎么參與新股配售,各項(xiàng)交易費(fèi)用,交易者的權(quán)利,證券公司對(duì)你應(yīng)盡的義務(wù)。。。。還有很多很多的必備知識(shí),我不再一一舉例 反正個(gè)人認(rèn)為

      最好能做到象營(yíng)業(yè)部大廳里的咨詢小姐那樣的了解程度就可以了 對(duì)于這些股票交易知識(shí)的資料可以問(wèn)問(wèn)自己開戶的營(yíng)業(yè)部有沒(méi)有 也可以到網(wǎng)上搜索查找一下 新華書店應(yīng)該也有這樣子的書 不過(guò)可能不容易找到 印象里,《炒股就這么幾招》的前面幾冊(cè)曾有比較詳細(xì)的介紹,適合新股民看看 呵呵,其實(shí)有些老股民也應(yīng)該補(bǔ)補(bǔ)課

      (二)在掌握了基本的交易知識(shí)以后,下面就可以開始交易技能的學(xué)習(xí)第一本書很重要

      因?yàn)榈酱藶橹?,你或許還是一張白紙

      白紙上落的第一筆,在某種程度上預(yù)示著以后發(fā)展的方向 我考慮了許久

      決定推薦《股市操練大全》 這一推薦可能會(huì)引起爭(zhēng)議

      因?yàn)槎鄶?shù)讀過(guò)書的交易老手都不建議看國(guó)內(nèi)的書 甚至把國(guó)內(nèi)書定為糟粕 但我不這么認(rèn)為

      國(guó)內(nèi)書總體格局小,卻也不乏好書

      在入門書上一下子就去讀國(guó)外書容易發(fā)生斷層 這套書非常本土化,使人產(chǎn)生很強(qiáng)的親切感 尤其是新穎的寫作模式讓人有不忍釋卷的沖動(dòng) 我不打算用自己的語(yǔ)言來(lái)多介紹這套書 想偷個(gè)懶,貼這套書的目錄和簡(jiǎn)介 股市操練大全》作者自述:

      參與股市的人都知道,股市如戰(zhàn)場(chǎng),輸贏全在一瞬間。為了把握股市勝機(jī),很多人忙著聽(tīng)股評(píng),參加股市沙龍,鉆研股票操作書,可謂樂(lè)此不疲。但是,令人遺憾的是,最終效果并不理想。一場(chǎng)股市風(fēng)暴來(lái)臨,大多數(shù)人仍然免不了被套的結(jié)局。那么,是什么原因造成這種狀況呢?我們以為,其真正的原因是股民在學(xué)習(xí)股票操作技巧時(shí)缺少了“強(qiáng)化訓(xùn)練”這一環(huán)節(jié)。從現(xiàn)代教學(xué)理論來(lái)說(shuō),人們要掌握一門知識(shí)和技巧,強(qiáng)化訓(xùn)練是必不可少的。譬如,要掌握

      開車技術(shù),就先要在練車場(chǎng)接受一套嚴(yán)格的駕駛技術(shù)的訓(xùn)練,只有在練車場(chǎng)過(guò)關(guān)后,才能正式到馬路上開車;又如,學(xué)生參加高考,事先都要有針對(duì)性復(fù)習(xí),做大量練習(xí)題,并進(jìn)行反復(fù)多次的模擬考試訓(xùn)練,高考才能取得好成績(jī)。但是,奇怪的是,這種在現(xiàn)代教育中屢試不爽的強(qiáng)化訓(xùn)練,一到股市就被人遺忘了,丟棄在一邊。謂子不信,請(qǐng)看:有的人買賣股票只憑自己的感覺(jué),有的人買賣股票完全依賴于股評(píng),有的人買賣股票跟著市場(chǎng)消息轉(zhuǎn),等等。這里面不要說(shuō)什么強(qiáng)化訓(xùn)練,恐怕連基本的操作原則都沒(méi)有。雖然也有人買賣股票時(shí),閱讀了不少股票操作技巧方面的書,但那也只是理論上的學(xué)習(xí),自己并沒(méi)有做過(guò)大量有針對(duì)性的練習(xí),因此,也就談不上接受了股市操作的強(qiáng)化訓(xùn)練。于是乎,作為現(xiàn)代教育中最重要的強(qiáng)化訓(xùn)練,在股市中完全沒(méi)有了蹤影。正因?yàn)檫@個(gè)原因,許多人買賣股票時(shí)失去了方向,陷入了屢買屢套,屢戰(zhàn)屢敗的怪圈。可見(jiàn),缺少股市操作強(qiáng)化訓(xùn)練,對(duì)投資者,尤其是對(duì)廣大中小散戶會(huì)造成多么嚴(yán)重的傷害。

      股市操作強(qiáng)化訓(xùn)練的重要性這里不再多說(shuō)了。但是如何開展股市操作強(qiáng)化訓(xùn)練呢?首先要有這方面的參考書籍,否則一切就無(wú)從談起。而迄今為止,圖書市場(chǎng)上還沒(méi)有這樣的書出現(xiàn)。別看現(xiàn)在的股票書如汗牛充棟,多得令人目不暇接,如你要想找一本用于股市操練的書,踏破鐵鞋無(wú)覓處。有鑒于此,我們?cè)谏虾H?lián)書店的大力支持下,組織有關(guān)專家和股市操盤手按照現(xiàn)代教育強(qiáng)化訓(xùn)練的理論,并根據(jù)滬深股市實(shí)際情況,設(shè)計(jì)編寫了中國(guó)股市第一本強(qiáng)化訓(xùn)練習(xí)題集。該習(xí)題集采用了“先易后難,循序漸進(jìn),反復(fù)比較,集中做題”的方式,對(duì)股民進(jìn)行強(qiáng)化訓(xùn)練,以此來(lái)幫助投資者真正掌握股市操作技巧,達(dá)到熟能生巧、運(yùn)用自如的目的。我們?cè)谠O(shè)計(jì)這本股市操作強(qiáng)化訓(xùn)練習(xí)題集時(shí),注意到很多投資者是新入市不久的股民,他們對(duì)股市操作技巧知之甚少。因此本書編寫的格調(diào)又有別于類似學(xué)生復(fù)習(xí)迎考習(xí)題集那種編寫方式,在指導(dǎo)讀者做習(xí)題的同時(shí),兼顧了股市操作知識(shí)的介紹,并把它系統(tǒng)化、條理化。讀者如果把書中習(xí)題與參考答案連起來(lái)閱讀,它就成了一本淺近易懂,專事介紹股市操作技巧的科普讀物。所以,本書實(shí)際上是一本兼有股市知識(shí)、技巧學(xué)習(xí)和股市操作強(qiáng)化訓(xùn)練兩方面用途的實(shí)用性操盤工具書。

      作為用于強(qiáng)化訓(xùn)練類的書,最大特點(diǎn)是:案例多、習(xí)題多。本書也不例外。本書的圖形就有600多幅,它幾乎把滬深股市10年來(lái)有代表性的K線走勢(shì)和技術(shù)圖形都選了進(jìn)去;習(xí)題100多個(gè),概念題、選擇題、是非題、.簡(jiǎn)答題、問(wèn)答題,應(yīng)有盡有。另外,每幅圖例都有專家、名人的精辟分析,每道題都有值得投資者一讀的參考答案,內(nèi)容十分豐富。為了發(fā)揮本書的效用、讀者在閱讀本書時(shí),不能只看不練,而要多做練習(xí)。因?yàn)橹挥型ㄟ^(guò)練習(xí),才能發(fā)現(xiàn)問(wèn)題,糾正操作中的錯(cuò)誤;只有通過(guò)練習(xí),才會(huì)駕輕就熟,把股市操作技巧用好用活。在學(xué)中練,在練中學(xué),反復(fù)比較,反復(fù)運(yùn)用,唯此才能達(dá)到股市操作強(qiáng)化訓(xùn)練的預(yù)期目的。這點(diǎn)必須引起投資者的高度重視。

      本書在選用滬深K線圖走勢(shì)時(shí),將個(gè)股的名稱、價(jià)位作了刪除(只有極少數(shù)圖案中的個(gè)股名稱、價(jià)位,因書中內(nèi)容需要作了保留),這主要是為了避免因投資者對(duì)某些股票的偏愛(ài)和價(jià)位上的錯(cuò)覺(jué),造成對(duì)K線技術(shù)圖形上的買賣信號(hào)作出錯(cuò)誤判斷,而所作的一種特殊處理。讀者對(duì)此不要有什么誤解。從K線、技術(shù)圖形操作理論上來(lái)說(shuō),任何股票都有強(qiáng)弱轉(zhuǎn)化的時(shí)候,這里面股質(zhì)本身是次要的,重要的是我們能不能在技術(shù)上找到買賣它們的理由和依據(jù)。當(dāng)K線和技術(shù)圖形走勢(shì)告訴我們可以買的時(shí)候,無(wú)論是績(jī)優(yōu)股、績(jī)差股,無(wú)論高價(jià)股、低價(jià)股,都要敢于買。反之,則要敢于賣。滬深股市上就有不少投資者因?yàn)閷?duì)績(jī)優(yōu)股的偏愛(ài),當(dāng)它們股價(jià)高高在上時(shí),仍然不斷追漲,對(duì)K線、技術(shù)圖形發(fā)出的見(jiàn)頂信號(hào)置之不理,結(jié)果被深套,損失慘重。這個(gè)教訓(xùn)是十分深刻的。因此,我們認(rèn)為刪除圖形上的個(gè)股名稱、價(jià)位,對(duì)促使投資者養(yǎng)成按圖形信號(hào)操作的習(xí)慣有很大的好處。

      本書每一章結(jié)束都安排了兩套測(cè)驗(yàn)題,這些測(cè)驗(yàn)題既是對(duì)讀者掌握K線或技術(shù)圖形操作技巧熟練程度的檢測(cè),也是對(duì)本書內(nèi)容的一個(gè)總結(jié)。因此,讀者必須認(rèn)真待之。測(cè)驗(yàn)題每一小

      欄都有得分多少說(shuō)明,并附有參考答案。讀者做完測(cè)驗(yàn)題后可自行打分。其評(píng)分標(biāo)準(zhǔn)和一般考試評(píng)分標(biāo)準(zhǔn)相同。60分為及格,80分以上為良好,90分以上為優(yōu)秀。如第一次測(cè)驗(yàn)成績(jī)較差者,說(shuō)明你對(duì)股市操盤技巧還沒(méi)掌握,參于股市操作的風(fēng)險(xiǎn)就較大。此時(shí),最佳的辦法是暫停股市買賣活動(dòng),重新學(xué)習(xí),反復(fù)練習(xí),待第二次測(cè)驗(yàn)成績(jī)提高后再積極參于股市運(yùn)作,這樣投資收益就會(huì)有很大的提高。書讀到這里,應(yīng)該開始看國(guó)外的經(jīng)典了 呵呵,所謂“取法乎上,得乎其中”

      如果老是在國(guó)內(nèi)的書里打轉(zhuǎn),恐怕會(huì)限制自己的視野,無(wú)法往高層進(jìn)階

      有時(shí)候,決定你是否能在市場(chǎng)里成為贏家的關(guān)鍵,不是在于你有多高的技巧,而更重要的是你的理念

      《期貨市場(chǎng)技術(shù)分析》這是一本很適合初學(xué)者看的技術(shù)分析的經(jīng)典書籍 講得不深,但很透徹,把每項(xiàng)技術(shù)分析的重點(diǎn)都拎了出來(lái) 加上丁圣元先生流暢貼切的翻譯

      使之成為中文版技術(shù)分析書籍中難得的好書 當(dāng)然,這本書的價(jià)格可能稍貴

      如果想追求性價(jià)比的朋友,可以選擇該書的更新版《金融市場(chǎng)技術(shù)分析》 《金融市場(chǎng)技術(shù)分析》是《期貨市場(chǎng)技術(shù)分析》的新版,增加了一些內(nèi)容 翻譯者是陳鑫。陳鑫先生也是國(guó)內(nèi)翻譯交易書籍的一把好手 不過(guò),對(duì)于我個(gè)人來(lái)說(shuō)

      捧著《期貨市場(chǎng)技術(shù)分析》這本大書 好像感覺(jué)更舒心和溫暖些

      接下去要看的書是《股市趨勢(shì)技術(shù)分析》 記得我曾經(jīng)說(shuō)過(guò)這樣的話,如果要出遠(yuǎn)門,而只能讓我?guī)б槐窘灰讜谏砩?,我?huì)選擇《期貨交易策略》

      現(xiàn)在我要說(shuō)的是,如果要拿走我書架上的交易書籍,而只能留一本下來(lái),我會(huì)選擇把《股市趨勢(shì)技術(shù)分析》留下

      這本書可以稱之為偉大,她的偉大主要體現(xiàn)在

      1)用具體圖表走勢(shì)對(duì)道氏理論進(jìn)行了細(xì)致和精彩的描述

      道氏理論之重要,交易者皆知,可惜很多人看道氏理論覺(jué)得空洞和枯燥,不過(guò)《股市趨勢(shì)技術(shù)分析》卻能給你一種豁然開朗的欣喜;她不僅能讓你領(lǐng)略到道氏理論的精髓,更可以給你一種對(duì)道氏理論震撼性的再認(rèn)識(shí)。我無(wú)意吹捧該書,因?yàn)檫@些都是我當(dāng)年讀書時(shí)的感覺(jué)。2)圖表分析的巔峰之作

      在我印象里,應(yīng)該沒(méi)有哪本書論述圖表分析能達(dá)到《股市趨勢(shì)技術(shù)分析》的高度 該書在圖表分析這一項(xiàng),不僅告訴我們應(yīng)該如何去分析圖表中各種力量的消長(zhǎng),平衡,突變,尺度,及我們就此所該做的應(yīng)對(duì)策略和手段,她更引導(dǎo)我們?nèi)ニ伎继綄る[藏在圖表背后的東西,即引起這些變化的實(shí)質(zhì)。我覺(jué)得,如果我們能領(lǐng)會(huì)該書的要義,那當(dāng)面對(duì)任何一張圖表的時(shí)候,我們都不僅能夠看出“然”,且會(huì)明了“所以然”。

      《股市趨勢(shì)技術(shù)分析》的中文版有個(gè)缺憾,就是翻譯好像并不理想(李先生翻譯)這對(duì)初學(xué)者的閱讀會(huì)帶來(lái)些障礙

      但在讀完上面幾本書后,我還是愿意向初學(xué)者推薦該書

      因?yàn)樽x這本書能夠大幅度提升你的格局,包括交易思想,交易策略以及技術(shù)分析的大局觀 在讀完上面這些書后

      你可能在腦子里已經(jīng)形成了初步的交易思想 并且對(duì)各種技術(shù)分析方法有了總體上的認(rèn)識(shí)

      但如果你打算現(xiàn)在就去進(jìn)行交易的話 那還是遠(yuǎn)遠(yuǎn)不夠的 面對(duì)宏大的市場(chǎng) 你會(huì)不知從何下手

      所以,接下來(lái)你需要做的是構(gòu)建屬于自己的交易體系 這是一個(gè)成熟的交易者必須要去做的一件事 當(dāng)然,在開始做此事以前

      因?yàn)楹芸赡苣悴⒉恢廊绾稳∩?,還不知道哪些東西是適合你的 所以你需要看一些書

      希望這些書能夠給你一些啟發(fā),便于讓你作出你的抉擇 這些書包括 1)《股票作手回憶錄》 2)《交易冠軍》 3)《華爾街操盤高手》(金融怪杰)4)《華爾街點(diǎn)金人》(新金融怪杰)5)《操盤建議--全球頂尖交易員的成功實(shí)踐和心路歷程》 6)《美國(guó)期貨專家經(jīng)驗(yàn)談》 7)《攻守四大戰(zhàn)技》 8)《投機(jī)智慧》 9)《期貨交易策略》 10)《刀疤老二的文章》

      第五篇:金融學(xué)入門書籍

      金融學(xué)入門書籍

      奮斗 2008-05-10 12:44:29 閱讀10 評(píng)論0 字號(hào):大中小

      1、《經(jīng)濟(jì)學(xué)原理》 N·格里高利·曼昆(N.Gregory Mankiw),中國(guó)人民大學(xué)出版社。

      2、《應(yīng)用經(jīng)濟(jì)計(jì)量學(xué)》 拉姆·拉瑪納山(Ramu Ramanathan),機(jī)械工業(yè)出版社。

      3、《金融經(jīng)濟(jì)學(xué)》(德)于爾根·艾希貝格爾,西南財(cái)經(jīng)大學(xué)出版社。

      4、《貨幣金融學(xué)》 弗雷德里克·S·米什金(Fredcric S.Mishkin),中國(guó)人民大學(xué)出版社。

      5、《金融學(xué)》 茲維·博迪、羅伯特·默頓,中國(guó)人民大學(xué)出版社。

      6、《國(guó)際經(jīng)濟(jì)學(xué)》(美)保羅·克魯?shù)侣袊?guó)人民大學(xué)出版社。

      7、《比較金融系統(tǒng)》 富蘭克林·艾倫,王晉斌等譯,中國(guó)人民大學(xué)出版社。

      8、《世界經(jīng)濟(jì)千年史》(英)安格斯·麥迪森(Angus Maddison),北京大學(xué)出版社。

      9、《金融市場(chǎng)與金融機(jī)構(gòu)基礎(chǔ)》(美)弗朗哥·莫迪利亞尼,清華大學(xué)出版社1999版。

      10、《微觀銀行學(xué)》弗雷克斯,西南財(cái)經(jīng)大學(xué)出版社。

      11、《公司理財(cái)》斯蒂芬·A·羅斯,機(jī)械工業(yè)出版社。

      12、《投資學(xué)》茲維·博迪,中國(guó)人民大學(xué)出版社

      先看《經(jīng)濟(jì)學(xué)原理》 然后學(xué)習(xí)一般的宏微觀經(jīng)濟(jì)學(xué)和貨幣銀行學(xué),再補(bǔ)充一些公司理財(cái)、投資學(xué)這樣的知識(shí)

      下來(lái)就可以學(xué)習(xí)金融經(jīng)濟(jì)學(xué)了,但同時(shí)要學(xué)習(xí)計(jì)量經(jīng)濟(jì)學(xué)的課程,可以先學(xué)計(jì)量也可以與金融經(jīng)濟(jì)學(xué)同時(shí)學(xué)

      上述課程學(xué)完之后就可以去看看專業(yè)一點(diǎn)的書籍了

      下載[電腦書籍]語(yǔ)言簡(jiǎn)介與入門word格式文檔
      下載[電腦書籍]語(yǔ)言簡(jiǎn)介與入門.doc
      將本文檔下載到自己電腦,方便修改和收藏,請(qǐng)勿使用迅雷等下載。
      點(diǎn)此處下載文檔

      文檔為doc格式


      聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),未作人工編輯處理,也不承擔(dān)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)有涉嫌版權(quán)的內(nèi)容,歡迎發(fā)送郵件至:645879355@qq.com 進(jìn)行舉報(bào),并提供相關(guān)證據(jù),工作人員會(huì)在5個(gè)工作日內(nèi)聯(lián)系你,一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

      相關(guān)范文推薦

        心理學(xué)入門書籍

        近年來(lái),心理問(wèn)題越來(lái)越成為社會(huì)關(guān)注的熱點(diǎn),追求幸福的現(xiàn)代人不時(shí)需要求助于心理學(xué),國(guó)內(nèi)心理學(xué)的高等教育與研究也迎來(lái)了發(fā)展的新階段。在這個(gè)背景下,“心理學(xué)”圖書——無(wú)論是專......

        心理咨詢?nèi)腴T書籍推薦

        推薦心理咨詢師入門書籍160本很多剛?cè)腴T的心理咨詢師朋友問(wèn)我該選擇哪些心理學(xué)書籍來(lái)閱讀學(xué)習(xí)。通過(guò)10年的學(xué)習(xí)、咨詢、培訓(xùn)、督導(dǎo)工作,我個(gè)人推薦160余本書籍供各位朋友選擇......

        法學(xué)入門書籍

        法學(xué)入門書籍 1、《法學(xué)總論》 2、《社會(huì)契約論》 3、《論法的精神》 4、《中國(guó)人的精神》 5、《拿破侖法典》(作為調(diào)劑) 西窗法雨 近距離看美國(guó) 哈特《法律的概念》拉茲《法......

        電腦基礎(chǔ)知識(shí)入門

        電腦基礎(chǔ)知識(shí)入門 想學(xué)好電腦,就要從電腦的基礎(chǔ)知識(shí)抓起,只有基礎(chǔ)學(xué)好了,才可以在前進(jìn)的路上走的更快,更好! 我以前對(duì)電腦也是義務(wù)所知,在21世紀(jì)的今天,在信息科技高速發(fā)展的今天,已......

        如何學(xué)習(xí)電腦入門

        如何學(xué)習(xí)電腦入門在學(xué)習(xí)電腦之前,先消除對(duì)電腦的緊張感,其實(shí)學(xué)電腦是很輕松的事,電腦并不神秘(如果搞的那么復(fù)雜,估計(jì)也不會(huì)發(fā)展那么迅速了),電腦只是一種工具,電腦的內(nèi)部工作原理雖......

        電腦入門學(xué)習(xí)方法

        看到不少電腦剛?cè)腴T者找不到適合自己的學(xué)習(xí)方法,到處碰壁,不但沒(méi)了信心和興趣,而且也耽誤了不少寶貴的時(shí)間和金錢,做了許多無(wú)用功,到頭來(lái)毫無(wú)收獲。 因此我總結(jié)了一下我個(gè)人的一......

        書籍簡(jiǎn)介與設(shè)計(jì)

        書脊設(shè)計(jì),精裝書還有護(hù)封設(shè)計(jì);版式設(shè)計(jì),包括扉頁(yè)、環(huán)襯、字體、開本、裝訂方式等;插圖,包括題頭、尾花和插圖創(chuàng)作等。 一、封面設(shè)計(jì) 假如書籍裝幀猶如一組建筑,那么書籍封面無(wú)疑......

        經(jīng)濟(jì)分析入門經(jīng)典書籍

        愛(ài)迪思_企業(yè)生命周期.pdf 巴納德_經(jīng)理人員的職能.pdf 布萊克和穆頓_新管理方格.pdf 大內(nèi)_Z理論.pdf 戴爾_偉大的組織者.pdf 德魯克_管理:任務(wù)、責(zé)任、實(shí)踐(上).pdf 德魯克_管......