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

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

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

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

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

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

      時(shí)間:2019-05-14 20:16:49下載本文作者:會(huì)員上傳
      簡(jiǎn)介:寫(xiě)寫(xiě)幫文庫(kù)小編為你整理了多篇相關(guān)的《書(shū)籍簡(jiǎn)介與設(shè)計(jì)》,但愿對(duì)你工作學(xué)習(xí)有幫助,當(dāng)然你在寫(xiě)寫(xiě)幫文庫(kù)還可以找到更多《書(shū)籍簡(jiǎn)介與設(shè)計(jì)》。

      第一篇:書(shū)籍簡(jiǎn)介與設(shè)計(jì)

      書(shū)脊設(shè)計(jì),精裝書(shū)還有護(hù)封設(shè)計(jì);版式設(shè)計(jì),包括扉頁(yè)、環(huán)襯、字體、開(kāi)本、裝訂方式等;插圖,包括題頭、尾花和插圖創(chuàng)作等。

      一、封面設(shè)計(jì)

      假如書(shū)籍裝幀猶如一組建筑,那么書(shū)籍封面無(wú)疑是這些建筑的外觀。不管是西方哥特式的教堂,還是中國(guó)古典式的皇宮寺院,建筑外觀都能體現(xiàn)出建筑的精神。而封面也是如此,將集中地體現(xiàn)書(shū)籍的主題精神,它是書(shū)籍裝幀設(shè)計(jì)的一個(gè)重點(diǎn)。

      封面的形式要素同樣包括了文字和圖形兩大類,封面設(shè)計(jì)也同樣需要突出主體形象。但從構(gòu)思到表現(xiàn)都講究一種寫(xiě)意美。表現(xiàn)在以文字為主和以圖形為主的設(shè)計(jì)上,都是如此。

      1.文字

      封面上簡(jiǎn)練的文字,主要是書(shū)名(包括叢書(shū)名、副書(shū)名)、作者名和出版社名,這些留在封面上的文字信息,在設(shè)計(jì)中起著舉足輕重的作用。

      在設(shè)計(jì)過(guò)程中,為了豐富畫(huà)面,可重復(fù)書(shū)名、加上拼音或外文書(shū)名,或目錄和適量的廣告語(yǔ)。有時(shí)為了畫(huà)面的需要,在封面上也可以不安排作者名有出版社名,讓它們出現(xiàn)在書(shū)脊和扉頁(yè)上,封面只留下不可缺少的書(shū)名。說(shuō)明文(出版意圖、叢書(shū)的目錄、作者簡(jiǎn)介)責(zé)任編輯、裝幀設(shè)計(jì)者名、書(shū)號(hào)定價(jià)等,則根據(jù)設(shè)計(jì)需要安排在勒口、封底和內(nèi)頁(yè)上。充滿活力的字體何嘗不是根據(jù)書(shū)籍的體 裁、風(fēng)格、特點(diǎn)而定,字體的排列同樣象廣告設(shè) 計(jì)構(gòu)圖中所講述的,把它們視為點(diǎn)、線、面來(lái)進(jìn)行設(shè)計(jì),有機(jī)地融入畫(huà)面結(jié)構(gòu)中,參與各種排列組合和分割,產(chǎn)生趣味新穎的形式,讓人感到言有盡而意無(wú)窮。

      2.圖形

      封面上的圖形,包括了了攝影、插圖和圖案,有寫(xiě)實(shí)的、有抽象的、還有寫(xiě)意的。具體的寫(xiě)實(shí)手法應(yīng)用在少兒的知識(shí)讀物、通俗讀物和某些文藝、科技讀物的封面設(shè)計(jì)中較多。因?yàn)樯倌陜和臀幕潭鹊偷淖x者對(duì)于具體的形象更容易理解。而科技讀物和一些建筑、生活 用品之類一畫(huà)冊(cè)封面運(yùn)用具象圖片,就具備了科學(xué)性、準(zhǔn)確性和感人的說(shuō)明力。

      有些科技、政治、教育等方面的書(shū)籍封面設(shè)計(jì),有時(shí)很難用具體的形象去提煉表現(xiàn),可以運(yùn)用 抽象的形式表現(xiàn),使讀者能夠意會(huì)到其中的含義,得到精神感受。

      在文學(xué)的封面上大量使用“寫(xiě)意”的手法,不只是象具象和抽象形式那樣提煉原著內(nèi)容的“寫(xiě)意”。而是似象非象的形式去表現(xiàn)。中國(guó)畫(huà)中有寫(xiě)意的手法,著重于抓住形和神的表現(xiàn),以簡(jiǎn)練的手法獲得具有氣韻的情調(diào)和感人的聯(lián)想。有人把自然圖案的變化方法也稱為 “寫(xiě)意變化”,在簡(jiǎn)練的自然形式基礎(chǔ)上,發(fā)揮想象力,追求形式美的表現(xiàn)。進(jìn)行夸張、變化和 組合。而運(yùn)用寫(xiě)意手法作為封面的形象,會(huì)使封面的表現(xiàn)更具象征意義和藝術(shù)的趣味性。如《少年文藝》封面“少”字的大特寫(xiě),好似飄揚(yáng)的紅領(lǐng)巾,給人一種聯(lián)想,從構(gòu)思到形式上都體現(xiàn)了《少年文藝》的個(gè)性。而變形的兒童讀物封面,更能引起孩子們的興趣,從中能找到童話、神話和寓言故事中自己的知心朋友。那些具有寫(xiě)意的中外古今圖案,在體現(xiàn)民族風(fēng)格和時(shí)代特點(diǎn)上也起著很大的作用。

      3.封面整體

      封面其實(shí)并不只是正面,誠(chéng)然,人們關(guān)心的主要是正面。但是出于審美的高要求,不應(yīng)當(dāng)將反面棄之不顧,再看書(shū)脊在書(shū)架上也同樣 發(fā)揮著廣告和美觀的作用。因此,封面的正反面和書(shū)脊都應(yīng)納入封面設(shè)計(jì)的范圍。整個(gè)封面是書(shū)籍裝幀大整體中的一個(gè)小整體,正反和書(shū)脊的相互關(guān)系有著統(tǒng)一的構(gòu)思和表現(xiàn),這種關(guān)系處理得成敗,同樣影響著書(shū)籍裝幀設(shè)計(jì)的整體效果。

      我們可以總結(jié)出幾種類型:

      A.正反面設(shè)計(jì)完全相同?;虼篌w設(shè)計(jì)相同,但文字有所變動(dòng),正面出現(xiàn)書(shū)名,反面采用拼音、外語(yǔ),或極小的責(zé)任編輯、裝幀設(shè)計(jì)人員名字。正反兩面色彩、設(shè)汁有所變化。

      B.以一張完整的設(shè)計(jì)畫(huà)面分成封面、封 底和書(shū)脊,分別裝飾文字。

      C.封底以封面縮小的畫(huà)面,或小標(biāo)志、圖案與正面形成呼應(yīng)。

      D.書(shū)脊應(yīng)該是封面設(shè)計(jì)的體現(xiàn),尤其在厚厚的書(shū)籍上,表現(xiàn)尤為如此,而不應(yīng)滿足于排列書(shū)名、作者名和出版社名。通過(guò)與正面書(shū)名相同的字體,在狹長(zhǎng)的面積內(nèi),安排好大小、疏密關(guān)系,有些運(yùn)用幾何的點(diǎn)、線、面和圖形進(jìn)行分割和與正反面形成呼應(yīng),并與之形成節(jié)奏變化。

      E.書(shū)脊的設(shè)計(jì)可以獨(dú)居一面,可以用文字壓在跨面的設(shè)計(jì)上。在精裝的書(shū)籍上,常常還有護(hù)封,既能起一種保護(hù)作用,同時(shí)也是一種重要的宣傳手段,是一種小型廣告。護(hù)封設(shè)計(jì)紙張、印刷精彩,表現(xiàn)力豐富。有護(hù)封的封面可以簡(jiǎn)潔些,達(dá)到變化的效果,同時(shí)又因?yàn)榉饷孢\(yùn)用了亞麻布、漆布、皮革等裝幀材料和印刷工藝的制約,故采用簡(jiǎn)潔的表現(xiàn)式。護(hù)封的勒口也需精心設(shè)計(jì),成為封面整體的一部分,并可利用其刊登內(nèi)容提要、作者介紹、出版信息,叢書(shū)目錄等。護(hù)封分全護(hù)封和半護(hù)封,半護(hù)封的高度只占封面的一半,包在封面的腰部,故稱為腰帶,用來(lái)刊登書(shū)籍廣告和有關(guān)書(shū)的一些補(bǔ)充各項(xiàng),也起著裝飾作用。

      二、版面設(shè)計(jì)

      所謂版面設(shè)計(jì),就是指在一定的新聞出版物幅面內(nèi),確定版面各要素的合理布局,即確定版心的尺寸及其在版面上所占的空間位置、文字的編排形式、文字的字體字號(hào)、文字的行間距、圖片與表格的位置及排版形式、版面裝飾物的使用等,使新聞出版物的版面具有美感并有獨(dú)特的風(fēng)格。

      在書(shū)籍的目錄或前言的前面設(shè)有扉頁(yè)。扉頁(yè)包括擴(kuò)頁(yè)、空白頁(yè)、像頁(yè)、卷首插頁(yè)或叢書(shū)名、正扉頁(yè)(書(shū)額)、版權(quán)頁(yè)、贈(zèng)獻(xiàn)題詞或感謝、空白頁(yè)等。太多的扉頁(yè)顯得喧賓奪主,因此它的數(shù)量不能機(jī)械地規(guī)定,必須根據(jù)書(shū)的特點(diǎn)和裝幀的需要而定。目前國(guó)內(nèi)外的書(shū)籍,往往比較簡(jiǎn)練,多采用護(hù)頁(yè)、正扉頁(yè)而直接直進(jìn)入目錄或前言,而版權(quán)頁(yè)的安排則根據(jù)具體情況而正。

      正扉頁(yè)上印有書(shū)名、作者名、出版者名和簡(jiǎn)練的圖案。由于人們的閱讀習(xí)慣。正扉頁(yè)的方向總是和封面一致。當(dāng)我們打開(kāi)封面、翻過(guò)環(huán)襯和空白頁(yè);文字就出現(xiàn)在右邊版心的中間或右上方。除此也有利用左右兩面作為正扉頁(yè)的設(shè)汁,稱為兩扉頁(yè)。扉頁(yè)上的字體不宜太大,主要采用美術(shù)字與封面的字體保持一致。扉頁(yè)的設(shè)汁非常簡(jiǎn)練,并留出大量空白,好似在進(jìn)入正文之前有塊放松的空間。

      無(wú)論打開(kāi)正反面封面,總有一張連接封面和內(nèi)頁(yè)的版面,叫做環(huán)襯,目的在于封面和內(nèi)心的牢固不脫離。精裝書(shū)的環(huán)襯設(shè)計(jì)也很講究,采用抽象的肌理效果、插圖、圖案,也有用照片表現(xiàn),其風(fēng)格內(nèi)容與書(shū)裝整體保持一致。但色彩相對(duì)于封面要有所變化。一般需要淡雅些,圖形的對(duì)比相對(duì)弱一些,有些可以運(yùn)用四方連續(xù)紋樣裝飾,產(chǎn)生統(tǒng)覺(jué)效果,在視覺(jué)上產(chǎn)生由封面到內(nèi)心的過(guò)渡。

      版面設(shè)計(jì)的目的一方面是為了使形式最好地表現(xiàn)版面內(nèi)容,另一方面是為了建立版面的風(fēng)格。一般而言,不同的新聞出版物的版面風(fēng)格都應(yīng)有所不同。但同一種新聞出版物的總體風(fēng)格應(yīng)保持一致。

      怎樣利用版面設(shè)計(jì)的手段達(dá)到設(shè)計(jì)版面的風(fēng)格目標(biāo)呢?一般認(rèn)為有如下幾種方法:

      1.從字體、字號(hào)上來(lái)體現(xiàn)。如有的版面不用黑體字以保持淡雅的風(fēng)格,有的版面則大量采用新型字體以體現(xiàn)其新穎、活潑的風(fēng)格;

      2.從正文行距行寬來(lái)體現(xiàn)。如有的版面加大行距以使版面明朗悅目,有的版面行寬很長(zhǎng)使版面莊重典雅;

      3.從圖片、表格的形式上來(lái)體現(xiàn)。圖片表格的大小、形狀、數(shù)量的多少以及位置的安排都能給版面帶來(lái)不同的特色;

      4.從版面裝飾來(lái)體現(xiàn)。版面裝飾主要指花邊、花線、題花、網(wǎng)底、加框等裝飾性符號(hào)。版面裝飾符號(hào)如何安排也是體現(xiàn)版面風(fēng)格的重要手段;

      5.從版面空間來(lái)體現(xiàn)。有的版面空白多,以體現(xiàn)明朗清秀的風(fēng)格;有的版面空白少,以容納更多的信息量。

      應(yīng)該說(shuō),版面設(shè)計(jì)工作是一項(xiàng)具有較強(qiáng)的創(chuàng)造性的工作。版面設(shè)計(jì)人員起碼應(yīng)具備以下素質(zhì):

      1.應(yīng)了解新聞出版工作的各環(huán)節(jié),懂得整個(gè)編輯排版流程;

      2.有較強(qiáng)的新聞理論業(yè)務(wù)知識(shí),有敏感的“新聞鼻”,也就是說(shuō)要“識(shí)貨”,知道那些新聞是最重要的,能基本判斷稿件新聞價(jià)值和宣傳價(jià)值的大?。?/p>

      3.應(yīng)熟悉一些印刷知識(shí)并掌握排版和制版的知識(shí)。就現(xiàn)代報(bào)紙版面設(shè)計(jì)人員而言,應(yīng)掌握激光照排技術(shù);

      4.應(yīng)熟悉本社激光照排系統(tǒng)中字體、字號(hào)、版面裝飾符號(hào)的種類并能熟練應(yīng)用之;

      5.應(yīng)了解各種制版方法對(duì)原稿的要求;

      6.有一定的美術(shù)知識(shí)修養(yǎng);

      7.此外,還應(yīng)該研究版面的構(gòu)圖、版面的結(jié)構(gòu)模式、版面的風(fēng)格、版面的閱讀適應(yīng)性以及版面的美化等,使版面設(shè)計(jì)給人以美感并有利于閱讀。

      三、插圖

      插圖是一種繪畫(huà),但是不同于一般獨(dú)立欣賞性的繪畫(huà),它具有相對(duì)的獨(dú)立性又具有必 要的從屬性。插圖必須具備一定的繪畫(huà)條件,不依靠文字。也能從它的形象本身.表現(xiàn)一定 的主題,同時(shí)又必須服從原著,成為輔助者,這 就是插圖的含義。

      插圖可以分為兩類。一類是文藝性的插圖。畫(huà)者通過(guò)選擇書(shū)中有意義的人物、場(chǎng)景和 情節(jié),用繪畫(huà)形象表現(xiàn)出來(lái),可以增加讀者閱讀書(shū)籍的興趣,使可讀性和可視性結(jié)合起來(lái)· 加深對(duì)原著的理解,同時(shí)又得到不同程度的美 的享受。另一類是科技及史地書(shū)籍.這類插圖 以幫助讀者進(jìn)一步理解知識(shí)內(nèi)容,以達(dá)到文字 難以表達(dá)的作用。它的形象語(yǔ)言應(yīng)力求準(zhǔn)確、實(shí)際,并能說(shuō)明問(wèn)題。一個(gè)蘋果的照片能幫助 我們看到非常客觀的形狀、顏色、結(jié)構(gòu)和質(zhì)感。一粒種子的說(shuō)明圖,不僅能再現(xiàn)它的形狀、結(jié) 構(gòu),而且能把它在土壤中發(fā)芽的過(guò)程體現(xiàn)出來(lái)。

      文學(xué)插圖可以說(shuō)是文藝性插圖的典型.包括了題頭、尾飾、單頁(yè)插圖和文間插圖。其表現(xiàn) 形式多種多樣:有水墨畫(huà)、白描、油畫(huà)、素描、版畫(huà)(木刻、石版畫(huà)、銅版畫(huà)、絲網(wǎng)畫(huà)),水粉、水彩、漫畫(huà)等等。有寫(xiě)實(shí)的.也有裝飾性的。插圖創(chuàng)作的第一步,在于對(duì)原著的理解。不但要了解具體內(nèi)容和要求,了解原作的主題精神,還要通過(guò)深入閱讀原著,搞清原著是中國(guó)文學(xué),還是外國(guó)文學(xué)?是古典文學(xué)還是兒童文學(xué)?是小說(shuō)、散文、詩(shī)歌.還是童話、寓言、笑話?原著風(fēng)格是粗獷豪放、細(xì)膩嚴(yán)謹(jǐn),還是熱情活潑、純樸深沉?原著中所描寫(xiě)的歷史時(shí)代、人物形象、服飾道具、日常習(xí)俗、建筑環(huán)境等。并且通過(guò)視覺(jué)形象資料加深理解,因?yàn)槲膶W(xué)是語(yǔ)言的藝術(shù),而 美術(shù)是視覺(jué)的藝術(shù),沒(méi)有文學(xué)中所描寫(xiě)的生活體驗(yàn),很難在畫(huà)面上體現(xiàn)文學(xué)內(nèi)容。只有查閱有關(guān)資料,如其民族、時(shí)代相近的繪畫(huà)、雕塑、建筑、工藝品.以及各種文物資料進(jìn)行分析,將各種感受聯(lián)系起來(lái),加以綜合研究,找出規(guī)律,以此為依據(jù),按原著要求確定作品的基調(diào),貫串于全部畫(huà)幅中。這樣書(shū)中的形象、資料中的形象、加上自己的想象,做到心中有底,才能表 現(xiàn)深入,而不至于概念,同時(shí)也是一種個(gè)人的積累不斷提高的方法,為以后的創(chuàng)作打好基礎(chǔ)有了這一步,則要對(duì)原著進(jìn)行提煉,找到有戲可唱的情節(jié)內(nèi)容。文學(xué)原著的篇幅很長(zhǎng),插圖又不是連環(huán)畫(huà)式的以圖為主、一本書(shū)只安排幾幅插圖,這就需要我們通過(guò)一幅插圖抓住 一段文字的情節(jié)內(nèi)容的主題,將最具有典型意 義的文字內(nèi)容,并適合于繪畫(huà)表現(xiàn)的情節(jié)表現(xiàn)出來(lái)。這種插圖不是停留在看文識(shí)圖上,而要 經(jīng)過(guò)再創(chuàng)作,使其具有藝術(shù)個(gè)性的感染力.同 時(shí)也要深入具體、刻劃入微,讓讀者從中既能得到藝術(shù)的享受。又能感覺(jué)到具體的生活形象。陳老蓮的《窺簡(jiǎn)》一圖,擇取營(yíng)駕躲在屏風(fēng)一端看信,發(fā)自內(nèi)心深處的喜悅,紅娘偷偷從屏風(fēng)另一端察看,她那手指點(diǎn)在唇邊,輕是機(jī)靈的神態(tài),活現(xiàn)出少女聰敏活潑的形象。畫(huà)面處理極為簡(jiǎn)潔,以一扇精彩的屏風(fēng)展現(xiàn)了閨房的環(huán)境,上面的花鳥(niǎo)畫(huà),無(wú)論是飛翔交樸的蝴 蝶,還是切切私語(yǔ)的鳥(niǎo)兒,都巧妙著營(yíng)營(yíng)的美好愿望。極為生動(dòng)形象地說(shuō)明了這個(gè)道理。

      正因?yàn)橐粡埐鍒D要表現(xiàn)眾多的文字內(nèi)容,有的插圖采用了將不同時(shí)間、地點(diǎn)納入一幅畫(huà)的方法;寫(xiě)實(shí)性的插圖運(yùn)用了蒙太奇的手法;裝飾性的插圖不受透視、比例等客觀條件的限制,更多地根據(jù)立意組織在畫(huà)面之中,中國(guó)的傳統(tǒng)繪畫(huà)和民間繪畫(huà)都采用了這種方法。

      插圖的形式表現(xiàn)豐富,同樣按寫(xiě)實(shí)和裝飾兩大類來(lái)分,各個(gè)國(guó)家的插圖都有自己風(fēng)格,即使同一國(guó)家、同一類文學(xué)作品,也會(huì)因?yàn)楦鱾€(gè)插圖家的藝術(shù)修養(yǎng)、對(duì)原著的理解不同,采 用不同的角度、不同的內(nèi)容、不同的畫(huà)面形式來(lái)表現(xiàn)。而作為一個(gè)插圖畫(huà)家,面對(duì)著不同內(nèi)容題材的書(shū)籍,要認(rèn)真研究思索,找到恰當(dāng)?shù)氖址ㄈケ憩F(xiàn),而不是千篇一律地去對(duì)待。黃永玉的插圖《阿詩(shī)瑪》不僅集中而真實(shí)地表現(xiàn)了主人翁的歡樂(lè)與幸福,勞動(dòng)與英勇,困難與遭遇,而且對(duì)詩(shī)的節(jié)奏、情緒和風(fēng)格的表達(dá),也有著周密的匠心經(jīng)營(yíng)。整套插圖富有韻律感的構(gòu)圖、流暢的線條、樸素淡雅的色彩、變化豐富的 刀法和裝飾味。但他為《葉圣陶童話選》、《馮雪峰寓言》作的插圖,根據(jù)原著不同風(fēng)格,又采用了不同的表現(xiàn)手法。在《葉圣陶童話選》的插圖中,出于畫(huà)家對(duì)童話的理解和兒童欣賞要求的熟悉,更加發(fā)揮藝術(shù)的夸張和想象,滿足兒童對(duì)新奇、強(qiáng)烈、稚氣和擬人化的興趣。一個(gè)個(gè)充滿人格化的動(dòng)物生動(dòng)活潑地出現(xiàn) 在小讀者的眼前。

      一本書(shū)的插圖,不會(huì)僅僅一張,因此插圖與插圖之間也是一個(gè)整體的關(guān)系問(wèn)題。作為文章開(kāi)幕用的題頭、閉幕用的尾飾和文本中間的插圖,要處理好與字和空間的關(guān)系。整套的插圖在構(gòu)思時(shí)就要有個(gè)整體設(shè)計(jì)安排,封面、環(huán)襯、扉頁(yè) 到尾聲上的插圖,以及裝飾圖案,要貫穿在書(shū)籍的主題中,并在書(shū)籍裝幀這組“建筑”中達(dá)到和諧完美,讓讀者在游覽過(guò)程中得到充分的精神享受。

      第二篇:核電書(shū)籍簡(jiǎn)介

      核電書(shū)籍簡(jiǎn)介

      一、900 MW壓水堆核電站系統(tǒng)與設(shè)備(上下):2005年,611頁(yè),嶺澳培訓(xùn)教材

      二、大亞灣核電站系統(tǒng)及運(yùn)行(上中下):1994年,2381頁(yè),大亞灣核電站工程全面介紹 四

      大亞灣核電站建設(shè)經(jīng)驗(yàn)匯編01: 1992年,489頁(yè),可以參考.五

      大亞灣核電站建設(shè)經(jīng)驗(yàn)匯編02: 1994年,546頁(yè),可以參考.六

      大亞灣核電站建設(shè)經(jīng)驗(yàn)匯編05: 1992年,559頁(yè),可以參考.七

      秦山三期水堆核電站建設(shè)經(jīng)驗(yàn)匯編01 綜合管理 2003,589.八

      秦山三期水堆核電站建設(shè)經(jīng)驗(yàn)匯編03 工程建造 2003,615.九

      慶祝秦山三期重水堆核電站工程全面建成學(xué)術(shù)報(bào)告會(huì)論文集 2003,249.十

      核電站建設(shè)的項(xiàng)目管理 1997, 416, 核工業(yè)集團(tuán)組織編制,可參考.

      第三篇:書(shū)籍簡(jiǎn)介——排版、設(shè)計(jì)、印刷、紙張

      書(shū)籍是人類用來(lái)紀(jì)錄一切成就的主要工具,也是人類交融感情,取得知識(shí),傳承經(jīng)驗(yàn)的重要媒介,對(duì)人類文明的開(kāi)展,貢獻(xiàn)至鉅。

      書(shū)籍裝幀是指塑造書(shū)的“體””和“貌”?!绑w”就是為書(shū)籍制作其盛納內(nèi)容的容器,“貌”則是將內(nèi)容傳達(dá)給讀者的外表。書(shū)的內(nèi)容就是通過(guò)裝幀將“體”和“貌”構(gòu)成完美的統(tǒng)一體,形成了可供閱讀的書(shū)籍。印刷和造紙是都是中國(guó)古代四大發(fā)明之一。它們對(duì)人類文明的貢獻(xiàn)是不可估量的。

      將文字、圖畫(huà)、照片等原稿經(jīng)制版、施墨、加壓等工序,使油墨轉(zhuǎn)移到紙張、織品、皮革等材料表面上,批量復(fù)制原稿內(nèi)容的技術(shù)。稱之為印刷。

      常規(guī)印刷必須具備有原稿(original)、印版(plate)、承印物、印刷油墨、印刷機(jī)械(printing machinery)五大要素,才能進(jìn)行印刷。

      紙張(Papers)種類:

      道林紙:材料為木漿

      模造紙:模仿道林紙, 紙漿為舊紙, 破布等

      銅版紙:是以模造紙為紙芯, 在其表面加上一層涂料并軋光, 使紙面的纖維縫隙填滿, 而印刷效果更佳, 此種紙通常用來(lái)印制彩色印刷品。

      雪面銅版紙:銅版紙之紙面再加涂料使之不反光 圣經(jīng)紙:全木纖維紙漿所制之薄紙, 常見(jiàn)用來(lái)印制圣經(jīng)

      再生紙:使用過(guò)的廢紙加以回收處理,制成再生紙漿, 以其取代原木紙漿所產(chǎn)出來(lái)的紙類 書(shū)籍裝幀包含3大部分

      (1)書(shū)皮:封面設(shè)計(jì),包括封面、封底、書(shū)脊設(shè)計(jì),精裝書(shū)還有護(hù)封設(shè)計(jì);

      詳細(xì)包括:封面、封底、書(shū)脊/護(hù)封、腰封/環(huán)襯,前環(huán)襯、后環(huán)襯,護(hù)頁(yè)/扉頁(yè), 副封面/勒口、前勒口、后勒口,折口/函套、書(shū)函、書(shū)套,半包式、全包式/紙張/厚度/工藝

      (2)書(shū)心:版式設(shè)計(jì),包括扉頁(yè)、環(huán)襯、字體、開(kāi)本、裝訂方式等;插圖,包括題頭、尾花和插圖創(chuàng)作等。紙張/厚度/字體、大小、間距,行距、字距/開(kāi)本/裝訂方式/插圖/版面,天頭、底腳、書(shū)眉、內(nèi)口、外口/

      印刷常用紙張

      凸版印刷紙、新聞紙、膠版印刷紙、銅板紙、書(shū)皮紙、字典紙、拷貝紙、板紙。

      厚度:50,60,70,80,100,105,115,120,128,150,157,180,200,210,220,240,250,280,300,350,400(g/m2)105,115,128,157(g/m2)進(jìn)口紙規(guī)格較多

      平板紙規(guī)格:787×1092,850×1168,880×1230 卷筒紙規(guī)格:寬度787,1092,850: 銅板紙規(guī)格:648×953,787×970,787×1092(目前國(guó)內(nèi)尚無(wú)卷筒紙)。889×1194為進(jìn)口銅版紙規(guī)格。

      圖書(shū)開(kāi)本:通常分三種類型:大型開(kāi)本、中型開(kāi)本和小型開(kāi)本。以787×1092的紙來(lái)說(shuō),12開(kāi)以上為大型開(kāi)本,16~36開(kāi)為中型開(kāi)本,40開(kāi)以下為小型開(kāi)本,但以文字為主的書(shū)籍一般為中型開(kāi)本。開(kāi)本形狀除6開(kāi)、12開(kāi)、20開(kāi)、24開(kāi)、40開(kāi)近似正方形外,其余均為比例不等的長(zhǎng)方形,分別適用于性質(zhì)和用途不同的各類書(shū)籍。

      787×1092mm 開(kāi)數(shù)(正)尺寸單位(mm)2開(kāi) 540×780 3開(kāi) 360×780 4開(kāi) 390×543 6開(kāi) 360×390 8開(kāi) 270×390 16開(kāi) 195×270 32開(kāi) 195×135 64開(kāi) 135×95 注:成品尺寸=紙張尺寸-修邊尺寸

      大度紙張:889*1194mm 開(kāi)數(shù)(大)尺寸單位(mm)

      2開(kāi) 590×880 3開(kāi) 395×880 4開(kāi) 440×590 6開(kāi) 395×440 8開(kāi) 295×440 16開(kāi) 220×295 32開(kāi) 220×145 64開(kāi) 110×145 注:成品尺寸=紙張尺寸-修邊尺寸 裝訂方式:平裝、精裝、線裝、散頁(yè)裝和軟精裝。詳細(xì):龜冊(cè)裝、簡(jiǎn)策裝、卷軸裝、旋風(fēng)裝、經(jīng)折裝、蝴蝶裝、和合裝、包背裝、線裝書(shū)、平裝、騎馬訂、精裝、特裝、活頁(yè)裝訂

      工藝:燙金、燙銀、起鼓、覆膜、UV上光,壓紋、磨砂、模切、包邊 封面設(shè)計(jì)的原則

      封面是書(shū)的外貌,她既體現(xiàn)書(shū)的內(nèi)容、性質(zhì),同時(shí)又給讀者以美的享受,并且還起了保護(hù)書(shū)的作用。封面設(shè)計(jì)包括書(shū)名、編著者名、出版社名等文字和裝飾形象、色彩及構(gòu)圖。如何使封面體現(xiàn)的的內(nèi)容、性質(zhì)、體裁,如何使封面能起著感應(yīng)人的心理、啟迪人的思維作用,是封面設(shè)計(jì)中最重要的一環(huán)。

      (1)封面設(shè)計(jì)的造型:造型要帶有明顯的閱讀者年齡、文化層次等特征。如對(duì)少年兒童讀物形象要具體、真實(shí)、準(zhǔn)確,構(gòu)圖要生動(dòng)活撥,尤其要突出知識(shí)性和趣味性;對(duì)中青年到老年人的讀物,形象可以由具象漸漸向于抽象,宜采用象征性手法,構(gòu)圖也可由生動(dòng)活撥的形式轉(zhuǎn)向于嚴(yán)肅、莊重的形式。

      (2)封面設(shè)計(jì)的色彩:色彩是由書(shū)的內(nèi)容與閱讀對(duì)象的年齡、文化層次等特征所決定的。對(duì)于讀者來(lái)說(shuō),因文化素養(yǎng)、民族、職業(yè)的不同,對(duì)于書(shū)籍的色彩也有不同的偏好。

      (3)封面的形式:封面的形式包括了文字和圖形兩大類,封面設(shè)計(jì)也同樣需要突出主體形象。

      封面形式設(shè)計(jì)法 1.文字

      封面上的文字主要包括書(shū)名(包括叢書(shū)名、副書(shū)名)、編著者名和出版社名。

      在設(shè)計(jì)過(guò)程中為了豐富畫(huà)面??稍黾舆m量的廣告語(yǔ)。文字的排列可以根據(jù)點(diǎn)、線、面的構(gòu)成方法來(lái)進(jìn)行設(shè)計(jì),有機(jī)地融入畫(huà)面中,參與各種排列組合和分割。2.圖形

      封面上的圖形包括了攝影、插圖等圖案,可為寫(xiě)實(shí)的、有抽象的或?qū)懸獾?。具體的寫(xiě)實(shí)手法應(yīng)用在少兒讀物、通俗讀物的封面設(shè)計(jì)中較多。因?yàn)樯倌陜和臀幕潭鹊偷淖x者對(duì)于具體的形象更容易理解。而科技讀物的封面和一些建筑、生活用品之類畫(huà)冊(cè)封面運(yùn)用具象圖片,就具備了科學(xué)性、準(zhǔn)確性和感人的說(shuō)服力。有些科技、政治、教育等方面的書(shū)籍封面設(shè)計(jì)。有時(shí)很難用具體的形象去提煉表現(xiàn),可以運(yùn)用抽象的形式表現(xiàn)使讀者能夠意會(huì)到其中的含義,得到精神享受。

      在文學(xué)的封面上大量使用“寫(xiě)意”的手法,不只是像具象和抽象形式那樣提煉原著內(nèi)容的“寫(xiě)意”。而是似像非像的形式去表現(xiàn)。在簡(jiǎn)練的自然形式基礎(chǔ)上發(fā)揮想象力,追求形式美的表現(xiàn)。進(jìn)行夸張、變化和組合。而運(yùn)用寫(xiě)意手法作為封面的形象,會(huì)使封面的表現(xiàn)更具象征意義和藝術(shù)的趣味性。

      裝幀設(shè)計(jì)的技巧

      封面、封底的設(shè)計(jì)和書(shū)脊的相互關(guān)系有著統(tǒng)一的構(gòu)思和表現(xiàn),這種關(guān)系處理,同樣影響著書(shū)籍的整體效果。

      關(guān)于設(shè)計(jì)技巧,大致可以終結(jié)出以下幾種類型。1.封面、封底設(shè)計(jì)

      (1)可采用完全相同或大體相同的設(shè)計(jì)方法,但文學(xué)將有所變動(dòng)。封面出現(xiàn)書(shū)名;封底采用拼音、外語(yǔ),或極小的責(zé)任編輯、裝幀設(shè)計(jì)人員名字。正反兩面色彩、設(shè)計(jì)有所變化。

      (2)可以用一張完整的設(shè)計(jì)畫(huà)面分成封面、封底和書(shū)脊,然后分別加入文字。(3)封底以縮小的畫(huà)面、標(biāo)志、圖案與封面形成呼應(yīng)。

      2.書(shū)脊

      書(shū)脊是封面設(shè)計(jì)的體現(xiàn),尤其在厚厚的書(shū)籍上表現(xiàn)尤為如此。而不應(yīng)滿足于排列出版信息,可以通過(guò)與封面書(shū)名相同的字體在狹長(zhǎng)的面積內(nèi)安排大小、疏密關(guān)系。有些運(yùn)用幾何的點(diǎn)、線、面和圖形進(jìn)行分割與封面形成呼應(yīng),并與之形成節(jié)奏變化。

      另外,有的書(shū)脊設(shè)計(jì)可以獨(dú)居一面,可以用文字壓在跨面的設(shè)計(jì)上。

      3.在精裝的書(shū)籍外部,常常還有護(hù)封,既起保護(hù)用,同時(shí)也是一種重要的宣傳手段。有護(hù)封的封面可以簡(jiǎn)潔一些。護(hù)封的勒口也需精心設(shè)計(jì),這是成為封面整體設(shè)計(jì)的一部分。

      護(hù)封分全護(hù)封和半護(hù)封,半護(hù)封的高度約占封面的一半,包在封面的腰部,故也稱為腰封,用來(lái)刊登書(shū)籍廣告和有關(guān)書(shū)的一些補(bǔ)充信息,也起著裝飾作用。內(nèi)頁(yè)版式的設(shè)計(jì)

      版式設(shè)計(jì),是指書(shū)籍正文部分的格式設(shè)計(jì)。一般,除封面、環(huán)襯和扉頁(yè)之外,前言也包括在其中。另外,在正文版中,還包括版心的設(shè)計(jì)。

      版心是指正文版式中文字和圖形所占的總面積,版心以上的空間叫天頭,版心以下的空間叫底腳,左右稱為內(nèi)口和外口。大部分的圖書(shū)會(huì)在版心外圍設(shè)計(jì)頁(yè)眉、頁(yè)腳或添加圖文標(biāo)題等。

      版心的大小根據(jù)書(shū)籍的類型而定。一般,畫(huà)冊(cè)、影集為了擴(kuò)大圖畫(huà)效果,宜取大版心,乃至出血處理(畫(huà)面四周不留空白);文獻(xiàn)資料類參考書(shū)以文字為主,則可以擴(kuò)大版心縮小邊口;圖文并茂的書(shū),圖可根據(jù)圖需要安排,較大的圖甚至可以跨頁(yè)排列或出血處理,使展開(kāi)的兩面相呼應(yīng)和均衡,讓版面更加生動(dòng)活撥,給人的視線帶來(lái)舒展感。

      在現(xiàn)代的圖書(shū)版式的設(shè)計(jì)者,應(yīng)該緊緊圍繞任何烘托標(biāo)志設(shè)計(jì)圖書(shū)內(nèi)容這一實(shí)際功利的需要,運(yùn)用形式美的法則,進(jìn)行版式設(shè)計(jì)的操作。實(shí)用與審美并重,構(gòu)思、設(shè)計(jì)出無(wú)窮無(wú)盡的版面變化,使自己所經(jīng)手的圖書(shū)生動(dòng)活潑,多姿多彩。探討圖書(shū)版式設(shè)計(jì)的創(chuàng)新,是具有理論意義和實(shí)踐意義的,以下有幾種圖書(shū)版式: 1.主題形象強(qiáng)化

      在進(jìn)行版式設(shè)計(jì)構(gòu)思時(shí),突出、強(qiáng)化主題形象的措施是,多次、多角度地展示這一主題。如封面、封底、前后環(huán)襯、目錄、譯序、題詞、護(hù)封都要有主題形象出現(xiàn),每形象應(yīng)該有不同的變化。

      2.版塊分疆缺損

      按黃金分割比例,留出相當(dāng)于黃金分割律畫(huà)出的一個(gè)方塊,即頂上頂右排文字作為一塊,另頂上通欄留白一塊,頂下頂左留白一塊。這種版式設(shè)計(jì),布局比較合理,標(biāo)題與排文字的版塊左右呼應(yīng),高低顧盼,文圖分布疏密有致。版面既呈三方塊的分疆,又于分疆中有缺損,使之變化。

      3.書(shū)眉交叉倒錯(cuò)

      采用書(shū)眉交叉倒錯(cuò)的方法,根據(jù)人的視線一般從幅左下方朝右上移動(dòng)的規(guī)律,雙碼書(shū)眉排在地腳,單碼書(shū)眉排在天頭,一天一地,左右交錯(cuò),全書(shū)書(shū)眉間隔倒錯(cuò),耐人尋味。上下左右間隔交錯(cuò)的這種書(shū)眉,打破常規(guī)的對(duì)稱之均衡,在形式上呈現(xiàn)令人驚訝的新意,有獨(dú)特的審美價(jià)值。

      4.訂口為軸對(duì)稱

      將書(shū)面攤開(kāi)后左邊與右邊兩面,即雙碼與單碼兩面當(dāng)成標(biāo)志設(shè)計(jì)面看,據(jù)此設(shè)計(jì)版式,常會(huì)有一種大氣魄的整體感,對(duì)視覺(jué)會(huì)帶來(lái)新鮮的刺激。以訂口為軸的對(duì)稱版式,外分內(nèi)合,張斂有致,或造成版面、開(kāi)本的擴(kuò)張,或加強(qiáng)向心力的聚斂,有衡穩(wěn)之效。

      5.大膽留出空白

      版面空白,是標(biāo)志設(shè)計(jì)版面注入生機(jī)的一種有效手段。大膽地留出大片,空白,是現(xiàn)代書(shū)籍版式設(shè)計(jì)意識(shí)的體現(xiàn)。恰當(dāng)、合理地留出空白,能傳達(dá)出設(shè)計(jì)者高雅的審美趣味,打破死板的常規(guī)慣例,使版面通透、開(kāi)朗標(biāo)志設(shè)計(jì)、跳躍、清新,給讀者在視覺(jué)上造成輕快、愉悅的刺激,目力因之得到松弛、小憩。當(dāng)然,標(biāo)志設(shè)計(jì)片空白不可亂用,一旦空白,必須有呼應(yīng),有過(guò)渡,以免造成版面空泛。6.圖案化的書(shū)眉

      書(shū)眉除具有方便檢索查閱的功能外,還具有裝飾的作用。一般書(shū)眉只占一行,并且只是由橫線及文字構(gòu)成。而用圖案做書(shū)眉,雖十分夸張,卻仍然得體,使被表達(dá)對(duì)象的標(biāo)志設(shè)計(jì)特征更加鮮明、突出,產(chǎn)生一種令人驚奇叫絕的美感

      總的來(lái)說(shuō),在圖書(shū)排版的時(shí)候多進(jìn)行些設(shè)計(jì)后的對(duì)比,就能看出不一樣的效果,但要注意有些小細(xì)節(jié)的地方,如果設(shè)計(jì)沒(méi)有考慮到的,就會(huì)導(dǎo)至整本圖書(shū)的面板視覺(jué)。設(shè)計(jì)年鑒圖書(shū)封面設(shè)計(jì)

      圖書(shū)的裝幀設(shè)計(jì)一般包括書(shū)的版式、字體、扉頁(yè)、目次、插畫(huà)、襯頁(yè)、封面、紙張、印刷等。其中,封面設(shè)計(jì)一般是書(shū)籍裝幀設(shè)計(jì)中最重要的內(nèi)容.優(yōu)秀的封面設(shè)計(jì)會(huì)直接影響讀者的購(gòu)買欲,同時(shí),也是圖書(shū)內(nèi)在精神的體現(xiàn).經(jīng)典漫畫(huà)雜志封面設(shè)計(jì)

      雜志屬于期刊類書(shū)籍,形式設(shè)計(jì)上相對(duì)固定一些,封面通常依據(jù)雜志風(fēng)格來(lái)設(shè)計(jì),因?yàn)殡s志具有延續(xù)性,封面與標(biāo)志的風(fēng)格一旦確立,很少更新版式,因此,雜志封面的版式設(shè)計(jì)要求也 更高.雜志版式設(shè)計(jì)

      優(yōu)秀的雜志是非常有個(gè)性和感染力的,它的核心是代表雜志的精華內(nèi)容和版式風(fēng)格。一個(gè)具有簡(jiǎn)潔之美的版面,同時(shí)也具備更豐富的內(nèi)涵,包括節(jié)奏、韻律、流暢等審美需要。這樣的版面要求設(shè)計(jì)人員具備更高層次的人文知識(shí)修養(yǎng)。

      附圖:

      附錄

      一、圖書(shū)整體設(shè)計(jì)的概念和內(nèi)容? 答:圖書(shū)的整體設(shè)計(jì),包括圖書(shū)外部裝幀設(shè)計(jì)和內(nèi)文版式設(shè)計(jì)。圖書(shū)外部裝幀設(shè)計(jì),包括圖書(shū)開(kāi)本選擇,結(jié)構(gòu)樣式的確定,以及圖書(shū)封面、護(hù)封、環(huán)襯、主書(shū)名頁(yè)、插頁(yè)等美術(shù)設(shè)計(jì)。圖書(shū)內(nèi)文版式設(shè)計(jì),包括圖書(shū)書(shū)芯部分的版式設(shè)計(jì)、用字的選擇,版心的確定、文字的排式及圖文在版面上的編排。

      二、圖書(shū)整體設(shè)計(jì)的原則是什么?

      答:圖書(shū)的整體設(shè)計(jì),兼具藝術(shù)性、技術(shù)性、實(shí)用性和經(jīng)濟(jì)性的統(tǒng)一。必須遵循以下一些原則:

      1、整體性原則,要求與圖書(shū)出版過(guò)程中的其他環(huán)節(jié)相配合(如材料、工藝、技術(shù)等);圖書(shū)內(nèi)容與形式相統(tǒng)一,使用價(jià)值與審美價(jià)值相統(tǒng)一;設(shè)計(jì)的藝術(shù)化與圖書(shū)主題的內(nèi)涵相統(tǒng)一;

      2、藝術(shù)性原則,要求充分體現(xiàn)藝術(shù)特點(diǎn)和獨(dú)特創(chuàng)意,體現(xiàn)時(shí)代特色和民族特色,同時(shí)又體現(xiàn)圖書(shū)不同性質(zhì)和門類的特點(diǎn);

      3、實(shí)用性原則,要求充分考慮不同層次讀者使用不同類別圖書(shū)的便利,充分考慮讀者經(jīng)濟(jì)上的承受能力和審美需求,充分考慮審美需要對(duì)提高讀者閱讀興趣的導(dǎo)向作用。

      4、效益比差原則,又稱“適度原則”,要求兼顧兩方面比差:(1)所需資金投入帶來(lái)實(shí)際經(jīng)濟(jì)效益的比差;(2)設(shè)計(jì)方案導(dǎo)致的圖書(shū)定價(jià)與讀者承受能力的比差。

      三、什么是開(kāi)本?圖書(shū)開(kāi)本受哪些因素制約?

      答:開(kāi)本是表示圖書(shū)幅面大小(規(guī)格尺寸)的行業(yè)用語(yǔ)。開(kāi)本以全張紙開(kāi)切的數(shù)量(開(kāi)數(shù))來(lái)表示。

      同一開(kāi)數(shù)的開(kāi)本,由于全張紙幅面尺寸大小不同,因此開(kāi)本相同的圖書(shū),其規(guī)格尺寸也會(huì)有所不同。圖書(shū)開(kāi)本的制約因素有3種:

      1、圖書(shū)性質(zhì)種類的制約。不同種類的圖書(shū),對(duì)開(kāi)本有不同要求,如畫(huà)冊(cè)、圖集、多采用大型開(kāi)本;學(xué)術(shù)著作、高等教材、刊物,多采用較大的中型開(kāi)本;通俗讀物、中小學(xué)課本,多采用較小的中型開(kāi)本;少兒讀物,多采用小型開(kāi)本;

      2、圖書(shū)篇幅的制約。較大的圖書(shū)多采用大中型開(kāi)本,篇幅較小的圖書(shū),多采用中小型開(kāi)本;

      3、圖書(shū)用途的制約。鑒賞類圖書(shū),多采用大中型開(kāi)本;閱讀類圖書(shū)多采用中型開(kāi)本;便攜類圖書(shū),多采用小型開(kāi)本;

      四、圖書(shū)的結(jié)構(gòu)部件有哪些?

      答:

      1、書(shū)芯。圖書(shū)的主體內(nèi)容,由若干“帖”組成(包括正文及輔文)

      2、封面。圖書(shū)的封面包括前勒口;前封面(也稱面封)、書(shū)脊;底封面(也稱封底);后勒口五個(gè)部分構(gòu)成。(也有不帶前后勒口的封面)(也有帶書(shū)殼的封面,稱“封殼”)

      3、環(huán)襯。封面與書(shū)芯之間連接起來(lái)的襯紙,(前環(huán)襯、后環(huán)襯)

      4、主書(shū)名頁(yè)。位于環(huán)襯后、書(shū)芯前,習(xí)稱“扉頁(yè)”或“內(nèi)封”,印有書(shū)名、著作者和出版者的名稱。位于單數(shù)頁(yè)碼。反面印有版權(quán)說(shuō)明、在版編目(CIP)數(shù)據(jù),版本記錄等。

      5、插頁(yè)。一般在主書(shū)名頁(yè)后,印有與圖書(shū)相關(guān)的圖版,有“集合型插頁(yè)”,也有“分散型插頁(yè)”。

      6、護(hù)封。(包封)包在硬質(zhì)封面外的包紙,前后勒口勒住封面封底。

      7、函套。有二種“書(shū)函”及“書(shū)套”,“書(shū)函”為我國(guó)傳統(tǒng)書(shū)籍護(hù)裝物; “書(shū)套”為硬質(zhì)書(shū)盒

      五、圖書(shū)有哪些裝訂樣式?

      答:平裝、精裝、線裝、散頁(yè)裝和軟精裝。平裝分為普通平裝、勒口平裝、封面貼膜平裝。

      精裝分為全紙面精裝,紙面布脊精裝、全面料精裝;三種精裝樣式都有園脊和平脊兩種形態(tài)。精裝書(shū)一般采用鎖線訂,膠背訂;

      線裝:如傳統(tǒng)古籍類圖書(shū)(在右側(cè)適當(dāng)寬度用線穿訂)

      散頁(yè)裝:?jiǎn)雾?yè)裝在紙袋或折盒內(nèi)。如教學(xué)掛圖、藝術(shù)圖片的裝訂。

      軟精裝:在勒口平裝的前后封面內(nèi)添加厚卡紙,使封面挺括度超過(guò)一般平裝圖書(shū)。

      六、圖書(shū)的美術(shù)設(shè)計(jì)有哪些手段?

      答:圖書(shū)裝幀的美術(shù)設(shè)計(jì)運(yùn)用的手段主要有:藝術(shù)手段,材料手段和技術(shù)手段。

      1、藝術(shù)手段:運(yùn)用形象、圖案、色彩、文字、紋飾等要素,以寫(xiě)真或?qū)懸馐址?,充分表現(xiàn)圖書(shū)的主題內(nèi)涵。

      2、材料手段:使用適宜的特種紙張、紙板、織物、塑料、皮革、電化鋁箔、粉箔、絲帶等材料,以裱糊、燙印、火印、覆壓等手法。

      3、技術(shù)手段:借助電子桌面的出版系統(tǒng)對(duì)文字、圖形、圖像進(jìn)行變形,對(duì)色彩進(jìn)行增減,使設(shè)計(jì)對(duì)象產(chǎn)生特殊藝術(shù)效果。

      七、圖書(shū)的版式設(shè)計(jì)形式有幾種? 答:圖書(shū)的版式設(shè)計(jì)形式常見(jiàn)的有三種。

      1、古典版式設(shè)計(jì):以訂口為軸心左右兩面嚴(yán)格對(duì)稱。字距、行距統(tǒng)一尺寸的保護(hù)性框子,具有均衡、典雅的特點(diǎn)。

      2、網(wǎng)格版式設(shè)計(jì):運(yùn)用固定的格子設(shè)計(jì)版面,把版心分為一欄、二欄、三欄等,具有緊密連貫、結(jié)構(gòu)嚴(yán)謹(jǐn)?shù)忍攸c(diǎn)。

      3、自由版式設(shè)計(jì):特點(diǎn)版心無(wú)疆界、字圖一體化,運(yùn)用計(jì)算機(jī)技術(shù)自由編排。[next]

      八、版式設(shè)計(jì)有哪些藝術(shù)規(guī)律?

      答:

      1、對(duì)稱與均衡。既要有整齊的平衡、又要有變化的平衡。

      2、比例與尺度。各要素間合適的比例與尺度,和諧完美。

      3、對(duì)比與調(diào)和。既要有差異性,如大小、黑白對(duì)比、又要講究調(diào)和統(tǒng)一。

      4、節(jié)奏與韻律。既有條理和規(guī)律性的重復(fù),又有節(jié)奏高級(jí)形態(tài)的韻律。

      5、變化與統(tǒng)一。既有充滿智慧與想象力的變化,又統(tǒng)一在有機(jī)品整體中。

      九、什么是字級(jí)?什么是字體?基本字體有哪幾種

      答:字級(jí)是指版面所排文字的大小級(jí)別。

      鉛字用號(hào)數(shù)制:(即初號(hào)、一號(hào)、二號(hào)-------七號(hào)等號(hào)數(shù)表示字級(jí)大?。?/p>

      之后采用點(diǎn)數(shù)制:每點(diǎn)的單位長(zhǎng)度為0.35毫米(5號(hào)字為10.5點(diǎn),公制為3.675毫米)照排級(jí)數(shù)制:每一級(jí)為0.25毫米(15級(jí)的照相字,為3.75毫米)現(xiàn)代計(jì)算機(jī)照排字為“無(wú)定級(jí)”(可任意大小)。字體是指版面所排文字的形體種類。

      基本字體有四種:宋體、黑體、楷體、仿宋體

      十、圖書(shū)的正文有哪些排式?

      圖書(shū)正文排式有橫排和直排兩種基本樣式。

      所謂橫排,是每行文字自左向右排列,每面各行從上到下排列的排式。所謂直排,是每行文字從上到下排列,每面各行自右向左排列的排式。橫排樣式中,有單欄、雙欄、三欄及多欄排式。

      十一、圖書(shū)標(biāo)題排式要注意什么?

      答:

      1、標(biāo)題字級(jí)、字體的選擇,依據(jù)圖書(shū)類別,開(kāi)本、標(biāo)題等級(jí)及標(biāo)題用字的原則(即字級(jí)大小有序,字體輕重相間的原則)。

      2、標(biāo)題位置,有居中、居左、居右三種樣式,依據(jù)開(kāi)本、標(biāo)題文字多少、及版面整體布局。

      3、標(biāo)題字空。標(biāo)題字?jǐn)?shù)少的,適當(dāng)增加字空。

      4、標(biāo)題占行。與標(biāo)題各等級(jí)相關(guān),一級(jí)標(biāo)題可多占行,二、三級(jí)標(biāo)題逐減少占行,全書(shū)前后一致。

      5、標(biāo)題轉(zhuǎn)行。不害文意。虛字不轉(zhuǎn)為下一行的第一字。

      十二、版面圖文合成有哪幾種樣式?

      答:

      1、以文為主。圖起輔助作用。合成原則“圖隨文走”“文先圖后”。

      2、圖文并重。不違反圖文在同一版面(或和合面)上合成的原則。

      3、以圖為主。文字起輔助作用,圖注文字,以文字靠近圖為宜,(或圖注文字集中于某一角,以序號(hào)與圖版相對(duì)應(yīng))。

      第四篇:[電腦書(shū)籍]語(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)使用笨重的繼電器、開(kāi)關(guān)去操作的巨型機(jī)。相比之下,我們的前輩不得不使用機(jī)器語(yǔ)言編寫(xiě)程序,他們甚至沒(méi)有最簡(jiǎn)單的匯編程序來(lái)把助記符翻譯成機(jī)器語(yǔ)言,而我們可以從上千種計(jì)算機(jī)語(yǔ)言中選擇我們喜歡的一種,而匯編,雖然不是一種“常用”的具有“快速原型開(kāi)發(fā)”能力的語(yǔ)言,卻也是我們可以選擇的語(yǔ)言中的一種。

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

      匯編語(yǔ)言是一種易學(xué),卻很難精通的語(yǔ)言?;叵氘?dāng)年,我從初學(xué)匯編到寫(xiě)出第一個(gè)可運(yùn)行的程序,只用了不到4個(gè)小時(shí);然而直到今天,我仍然不敢說(shuō)自己精通它。編寫(xiě)快速、高效、并且能夠讓處理器“很舒服地執(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ò)這么一句話:

      寫(xiě)匯編語(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++寫(xiě)程序足夠了,甚至說(shuō),他不僅僅掌握C++,而且精通STL、MFC。我不贊成這個(gè)觀點(diǎn),掌握上面的那些是每一個(gè)編程人員都應(yīng)該做到的,然而C++只是我們“常用”的一種語(yǔ)言,它不是編程的全部。低層次的開(kāi)發(fā)者喜歡說(shuō),嘿,C++是多么的強(qiáng)大,它可以做任何事情——這不是事實(shí)。便于維護(hù)、調(diào)試,這些確實(shí)是我們的追求目標(biāo),但是,寫(xiě)程序不能僅僅追求這個(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í)所寫(xiě)的講義。當(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í),編寫(xiě)匯編語(yǔ)言程序很可能很快就破壞了你的結(jié)構(gòu)化編程習(xí)慣,大大降低程序的可讀性、可維護(hù)性,最終讓你的程序陷于不得不廢棄的代碼堆之中。基本上,這份文檔撰寫(xiě)的目標(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ù)的方法。

      開(kāi)放。接受匯編語(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ě)程序,但現(xiàn)在除了沒(méi)有匯編程序的那些電腦之外,直接用機(jī)器語(yǔ)言寫(xiě)超過(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ì)算和重寫(xiě)代碼。

      匯編語(yǔ)言除了機(jī)器語(yǔ)言之外最接近計(jì)算機(jī)硬件的編程語(yǔ)言。由于它如此的接近計(jì)算機(jī)硬件,因此,它可以最大限度地發(fā)揮計(jì)算機(jī)硬件的性能。用匯編語(yǔ)言編寫(xiě)的程序的速度通常要比高級(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ì)用匯編徹底重寫(xiě)某些經(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,寫(xiě)的是一個(gè)

      對(duì)一個(gè)包含100個(gè)32bit整數(shù)的數(shù)組進(jìn)行快速排序,并且輸出出來(lái)的小程序。實(shí)際上用匯編器寫(xiě)出的機(jī)器碼與在調(diào)試器中用它附帶的匯編程序?qū)懗龅臋C(jī)器碼還是有一些細(xì)微差別的,前者更大,然而卻可能更高效,因?yàn)閰R編器能夠?qū)⒋a放置到適合處理器的地方這句話假定兩個(gè)程序進(jìn)行了同等程度的優(yōu)化,一個(gè)寫(xiě)的不好的匯編程序和一個(gè)寫(xiě)的很好的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靼鬃约涸谧鍪裁矗敲茨憧赡茉斐啥褩5钠茐?。?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ě)程序,但現(xiàn)在除了沒(méi)有匯編程序的那些電腦之外,直接用機(jī)器語(yǔ)言寫(xiě)超過(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ì)算和重寫(xiě)代碼。

      匯編語(yǔ)言除了機(jī)器語(yǔ)言之外最接近計(jì)算機(jī)硬件的編程語(yǔ)言。由于它如此的接近計(jì)算機(jī)硬件,因此,它可以最大限度地發(fā)揮計(jì)算機(jī)硬件的性能。用匯編語(yǔ)言編寫(xiě)的程序的速度通常要比高級(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ì)用匯編徹底重寫(xiě)某些經(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,寫(xiě)的是一個(gè)

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

      在前一節(jié)中的x86基本寄存器的介紹,對(duì)于一個(gè)匯編語(yǔ)言編程人員來(lái)說(shuō)是不可或缺的?,F(xiàn)在你知道,寄存器是處理器內(nèi)部的一些保存數(shù)據(jù)的存儲(chǔ)單元。僅僅了解這些是不足以寫(xiě)出一個(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)好,也可以寫(xiě)成[十進(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ù)字,則開(kāi)頭的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)寫(xiě)一小段匯編程序,修改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的縮寫(xiě))的一種用法。它可以將數(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提供的資料。編寫(xiě)程序的時(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ū)籍。多數(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)重寫(xiě)那段代碼了。怎么確認(rèn)是否應(yīng)該用匯編語(yǔ)言重寫(xiě)呢?

      使用匯編語(yǔ)言重寫(xiě)代碼之前需要確認(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ǔ)言編寫(xiě)程序。不清楚到底這是不是編輯的失誤,因?yàn)橐粋€(gè)頭腦正常的人恐怕不會(huì)這么做程序,即使它不長(zhǎng)、也不復(fù)雜。首先,匯編器能夠完成某些封包操作,即使不行,也可以用db偽指令來(lái)寫(xiě)指令;用匯編語(yǔ)言寫(xiě)程序可以防止很多錯(cuò)誤的發(fā)生,同時(shí),它還減輕了人的負(fù)擔(dān),很顯然,“完全用機(jī)器語(yǔ)言寫(xiě)程序”是完全沒(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ì)提高開(kāi)發(fā)成本,并且,難于維護(hù)。因此,我個(gè)人的建議是,如果在軟件開(kāi)發(fā)中使用匯編語(yǔ)言,則應(yīng)在軟件接近完成的時(shí)候使用,這樣可以減少很多不必要的投入。

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

      不過(guò)現(xiàn)在說(shuō)用匯編語(yǔ)言進(jìn)行優(yōu)化還為時(shí)尚早——不可能寫(xiě)程序,而只操作這些寄存器,因?yàn)檫@樣只能完成非常簡(jiǎn)單的操作,既然是簡(jiǎn)單的操作,那可能就會(huì)讓人覺(jué)得乏味,甚至找一臺(tái)足夠快的機(jī)器窮舉它的所有結(jié)果(如果可以窮舉的話),并直接寫(xiě)程序調(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)書(shū)籍)狀態(tài).對(duì)于電路而言,這表現(xiàn) 為高、低電平,或者開(kāi)、關(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

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

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

      我們現(xiàn)在可以寫(xiě)一個(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’;代碼段開(kāi)始

      ;回車;換行

      ;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ù)不被寫(xiě)入到它以外的地方。作為一個(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)行寫(xiě)下指令。這意味著,你可以超越匯編器的能力撰寫(xiě)匯編程序,然而,直接用機(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ǔ)充。如我在開(kāi)始提到的那樣,真正完全用匯編語(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ǔ)言,而不必撰寫(xiě)單獨(dú)的匯編語(yǔ)言程序——這可以節(jié)省你的不少精力,因?yàn)榍懊嬷v述的那些偽指令,如equ等,都可以用你熟悉的高級(jí)語(yǔ)言方式來(lái)編寫(xiě),編譯器會(huì)把它轉(zhuǎn)換為適當(dāng)?shù)男问健?/p>

      需要說(shuō)明的是,在高級(jí)語(yǔ)言中一定要注意編譯結(jié)果。編譯器會(huì)對(duì)你的匯編程序做一些修改,這不一定符合你的要求(附帶說(shuō)一句,有時(shí)編譯器會(huì)很聰明地調(diào)整指令順序來(lái)提高性能,這種情況下最好測(cè)試一下哪種寫(xiě)法的效果更好),此時(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ǔ)言寫(xiě)的實(shí)現(xiàn)相同功能的函數(shù)通常沒(méi)有系統(tǒng)提供的函數(shù)性能好(除非你用了比函數(shù)庫(kù)好很多的算法),因?yàn)橄到y(tǒng)的函數(shù)往往使用了更好的優(yōu)化,甚至可能不是用C語(yǔ)言直接編寫(xiě)的。

      當(dāng)然,“偷懶”的意思是說(shuō),把那些應(yīng)該讓機(jī)器做的事情交給計(jì)算機(jī)來(lái)做,因?yàn)樗龅酶?。我們?yīng)該把精力集中到設(shè)計(jì)算法,而不是編寫(xiě)源代碼本身上,因?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)寫(xiě),多半會(huì)寫(xiě)成

      mov eax, 079f2ch ret;return 499500

      為什么這樣寫(xiě)呢?我們看到,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),可以提高代碼性能。在某些情況下,使代碼既小又快是可能的。

      書(shū)歸正傳,我們來(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)開(kāi)始逐步采用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í)也是目前撰寫(xiě)應(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)存(例如,寫(xiě)了“只讀”內(nèi)存,或讀了不可讀的內(nèi)存,等等),那么CPU就會(huì)產(chǎn)生一個(gè)異常。這個(gè)異常將交給操作系統(tǒng)處理,而這種處理,假如你的程序沒(méi)有特別說(shuō)明操作系統(tǒng)該如何處理的話,一般就是殺掉做錯(cuò)了事情的進(jìn)程。

      我像這樣的對(duì)話框大家一定非常熟悉(臨時(shí)寫(xiě)了一個(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)在開(kāi)始解釋如何使用這些知識(shí)。

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

      可以將內(nèi)存想象為一個(gè)順序的字節(jié)流。使用指針,可以任意地操作(讀寫(xiě))內(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ì)有人寫(xiě)出這樣的代碼:

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

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

      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 于是上面的程序改寫(xiě)為 cld mov cx, 128 rep movsd;復(fù)位DF;512/4 = 128,共128個(gè)雙字;行動(dòng)!

      第一句cld很多時(shí)候是多余的,因?yàn)閷?shí)際寫(xiě)程序時(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ū)溢出分為兩類,一類是寫(xiě)入緩沖區(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ǔ)言編寫(xiě)程序時(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ù)大小編寫(xiě)程序。除此之外,非常重要的一點(diǎn)就是,在匯編語(yǔ)言這個(gè)級(jí)別寫(xiě)程序,你肯定希望去掉所有的無(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開(kāi)始的全部?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)可以寫(xiě)出很多的底層數(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)提供了堆棧,并且性能比自己寫(xiě)一份更好,那么為什么不直接加以利用呢 系統(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í)。限于篇幅,我不打算展開(kāi)細(xì)講指令,如cmps*,lods*,stos*,等等。這些指令的用法和前面介紹的movs*基本一樣,只是有不同的作用而已。

      4.0 利用子程序與中斷

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

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

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

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

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

      可重入函數(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)題。使用宏匯編器寫(xiě)出可重入的匯編代碼需要注意一些問(wèn)題。簡(jiǎn)單地說(shuō),干脆不要用標(biāo)號(hào)作為變量是一個(gè)不錯(cuò)的主意。

      使用高級(jí)語(yǔ)言編寫(xiě)可重入程序相對(duì)來(lái)講輕松一些。把持住不訪問(wèn)那些全局(或當(dāng)前對(duì)象的)變量,不使用靜態(tài)局部變量,堅(jiān)持只適用局部變量,寫(xiě)出的程序就將是可重入的。書(shū)歸正傳,調(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)站上提供的開(kāi)發(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í)代的許多書(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開(kāi)始是沒(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ì)寫(xiě)出最初版本那樣的代碼),但這種實(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)改寫(xiě)為匯編語(yǔ)言的程序,如果要再在算法上作大幅度的修改,其工作量將和重寫(xiě)相當(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ì)算的東西。例如,你可以毫不猶豫地寫(xiě)出下面的代碼:

      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é)開(kāi)始的所有優(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是寫(xiě)通式的和回寫(xiě)式的又會(huì)造成一些性能上的差異)。

      聰明的讀者馬上就會(huì)指出,我們不是可以在定義do_something()的時(shí)候加上inline修飾符,讓它在本地展開(kāi)嗎?沒(méi)錯(cuò),本地展開(kāi)以增加代碼量為代價(jià)換取性能,但這只是問(wèn)題的一半。編譯器盡管完成了本地展開(kāi),但它仍然需要做許多額外的工作。因?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這一段,涉及的需要寫(xiě)入的變量包括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,而不是按照程序中寫(xiě)的那樣從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)處有一口井,我們帶著一口鍋,身邊是樹(shù)林;身上的飲用水已經(jīng)喝光了,此處允許砍柴和使用明火(當(dāng)然我們不想引起火災(zāi):),需要燒一鍋水,應(yīng)該怎么樣呢?

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

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

      這兩種方案畫(huà)出圖來(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)度需要更大的開(kāi)銷并且,到目前為止,真正使用支持超線程的CPU,并且使用相應(yīng)操作系統(tǒng)的人是非常少的。因此,我們需要關(guān)心的實(shí)際上還是同一執(zhí)行序列中的并發(fā)執(zhí)行和指令封包。不過(guò),令人遺憾的是,實(shí)際上在這方面編譯器做的幾乎是肯定要比人好,因此,你需要做的只是開(kāi)啟相應(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++編譯器把最開(kāi)始一段賦值語(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ī)器上完成。例如,專門用于編寫(xiě)和調(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)力不討好的事情。

      第五篇:幾種早期教育書(shū)籍簡(jiǎn)介

      幾種早期教育書(shū)籍簡(jiǎn)介.txt如果青春的時(shí)光在閑散中度過(guò),那么回憶歲月將是一場(chǎng)凄涼的悲劇。雜草多的地方莊稼少,空話多的地方智慧少。即使路上沒(méi)有花朵,我仍可以欣賞荒蕪。==================== 軟件簡(jiǎn)介:

      世界上最受歡迎的九種教育法

      1、卡爾·威特:全能教育法 《卡爾·威特的教育》

      2、塞德茲:天才教育法 《俗物與天才》

      3、約翰·洛克:全面教育法 《教育漫話》(又譯《家庭學(xué)?!罚?/p>

      4、蒙臺(tái)梭利:特殊教育法 《蒙臺(tái)梭利教育法》、《蒙臺(tái)梭利手冊(cè)》、《教育人類學(xué)》、《高級(jí)蒙臺(tái)梭利方法》、《童年的秘密》、《兒童的發(fā)現(xiàn)》等書(shū)

      5、斯賓塞:快樂(lè)教育法 《智育》、《德育》、《體育》以及《什么知識(shí)最有價(jià)值》

      6、M.S.斯特娜:自然教育法 《M.S.斯特娜的自然教育》

      7、鈴木鎮(zhèn)一:才能教育法 《早期教育與能力培養(yǎng)》

      8、多湖輝:實(shí)踐教育法 《母愛(ài)促進(jìn)身心健康》、《如何開(kāi)發(fā)孩子的能力》、《管教孩子的技巧》、《學(xué)習(xí)指導(dǎo)法》《使孩子聰明的心理戰(zhàn)術(shù)》、《培養(yǎng)孩子學(xué)習(xí)興趣方法談》、《孩子的心理規(guī)律》、《責(zé)備孩子的方略》等多湖輝的著作從胎兒到小學(xué)教育,從教育心理學(xué)到具體的教育行為都有詳細(xì)的論述,可謂是“兒童教育的百科全書(shū)”

      9、井深大:早期教育法 網(wǎng)絡(luò)上能找到的不多,這些都是本人辛苦收集的幾本,拿出來(lái)分享!

      ===================================

      《蒙臺(tái)梭利早期教育法》

      本書(shū)是蒙臺(tái)梭利博士的第一本兒童教育專著,被譯成20多種文字,是她對(duì)自己親手創(chuàng)立的“兒童之家”的經(jīng)驗(yàn)總結(jié)。正是這本書(shū)的問(wèn)世,使她成為全球兒童教育理論與實(shí)踐方面最有影響力的教育家之一。本書(shū)是蒙臺(tái)梭利博士對(duì)她所進(jìn)行的教育創(chuàng)新背后的理論原則的揭示,向父母、教師和教育管理者介紹了蒙臺(tái)梭利方法的指導(dǎo)原則,傳授了如何“讓孩子通過(guò)自己的努力去自由地學(xué)習(xí)”。通過(guò)本書(shū)所介紹的方法,孩子能培養(yǎng)自己的秩序意識(shí)和邏輯思維能力。

      《蒙臺(tái)梭利兒童教育手冊(cè)》

      本書(shū)是蒙臺(tái)梭利博士在美國(guó)傳授蒙臺(tái)梭利方法期間,應(yīng)無(wú)數(shù)對(duì)她的方法感興趣的父母和教師的要求而寫(xiě)作的一本操作性手冊(cè)。該手冊(cè)向人們傳授了“兒童之家”所運(yùn)用的教具和技術(shù),以及如何為孩子們提供一個(gè)進(jìn)行“自我教育”的環(huán)境。從蒙臺(tái)梭利創(chuàng)辦第一所“兒童之家”至今,所有蒙臺(tái)梭利教室的教具都十分統(tǒng)一。蒙臺(tái)梭利博士在本書(shū)中傳授了如何教學(xué)前兒童使用這些教具,以刺激其觀察力、認(rèn)識(shí)力和判斷力的發(fā)育。蒙臺(tái)梭利博士強(qiáng)調(diào),對(duì)每個(gè)孩子的方法是不同的,成人的作用應(yīng)該是引導(dǎo)孩子自己去試驗(yàn),讓他們自己意識(shí)到自己的錯(cuò)誤,讓他們自己在學(xué)習(xí)中冒必要的風(fēng)險(xiǎn)。

      《童年的秘密》

      是蒙臺(tái)梭利對(duì)幼兒之謎的探索和解答,記錄了她在學(xué)前兒童方面的研究和教育工作,闡述了幼兒教育的原則和方法。在“導(dǎo)論”中,蒙臺(tái)梭利指出:“兒童并不是一個(gè)只可以從外表觀察的陌生人。更確切地說(shuō),童年構(gòu)成了人生中最重要的一部分,因?yàn)橐粋€(gè)人是在他的早期就形成的?!薄盀閮和睦嫠鞯淖巫尾痪牒驼嬲\(chéng)的努力將使我們能夠發(fā)現(xiàn)人類的秘密,正如科學(xué)的調(diào)查研究能使我們洞察眾多的自然秘密一樣?!?/p>

      《童年的秘密》是一本了解兒童發(fā)育和成長(zhǎng)秘密的最生動(dòng)的著作。在書(shū)中,蒙臺(tái)梭利詳細(xì)而生動(dòng)地描繪了兒童的生理和心理特征,揭開(kāi)兒童成長(zhǎng)奧秘的革命性觀念。它讓世人了解到,兒童具有豐富的潛能,但兒童只有在一個(gè)與他的年齡相適應(yīng)的環(huán)境中,他的心理生活才會(huì)自然地發(fā)展,并展現(xiàn)他內(nèi)心的秘密。而有些兒童之所以不能正常地發(fā)育和成長(zhǎng),主要是因?yàn)槭艿匠赡耆说暮鲆暫蛪阂帧R虼?,我感受最深的是:幼兒教育的原則和方法應(yīng)是理解、尊重兒童,根據(jù)兒童身心發(fā)展的規(guī)律,為兒童實(shí)現(xiàn)自身的潛能提供所需的幫助。

      但蒙臺(tái)梭利教育方法也存在著一定的局限性,如過(guò)分強(qiáng)調(diào)工作對(duì)兒童身心發(fā)展的作用,而輕視游戲的作用,把游戲僅視為閑暇時(shí)的一種快樂(lè)的消遣;過(guò)分強(qiáng)調(diào)教具的價(jià)值,而貶低玩具的價(jià)值;具有神秘主義和宗教色彩等等。因此,我們?cè)趯W(xué)習(xí)和借鑒蒙臺(tái)梭利教育理論方法的過(guò)程中,應(yīng)本著一切為了孩子的宗旨,結(jié)合具體情況加以利用、改造和創(chuàng)新。

      《發(fā)現(xiàn)孩子》

      蒙臺(tái)梭利教育法之所以能影響整個(gè)世界的教育體系,關(guān)鍵在于她在總結(jié)盧梭、裴斯泰格齊、福祿貝爾等人自然主義教育思想的基礎(chǔ)上,形成了自己革命性的兒童觀念。她認(rèn)為兒童有一種與生俱來(lái)的“內(nèi)在生命力”,這種生命力是一種積極的、活動(dòng)的、發(fā)展著的存在,它具有無(wú)窮無(wú)盡的力量。教育的任務(wù)就是激發(fā)和促進(jìn)兒童“內(nèi)在潛力”的發(fā)揮,使其按自身規(guī)律獲得自然的和自由的發(fā)展。她主張,不應(yīng)該把兒童作為一種物體來(lái)對(duì)待,而應(yīng)作為人來(lái)對(duì)待。兒童不是成人和教師進(jìn)行灌注的容器;不是可以任意塑造的蠟或泥;不是可以任意刻劃的木塊;也不是父母和教師培植的花木或飼養(yǎng)的動(dòng)物,而是一個(gè)具有生命力的、能動(dòng)的、發(fā)展著的活生生的人。教育家、教師和父母應(yīng)該仔細(xì)觀察和研究?jī)和?,了解兒童的?nèi)心世界,發(fā)現(xiàn)“童年的秘密”;熱愛(ài)兒童,尊重兒童的個(gè)性,促進(jìn)兒童的智力、精神、身體與個(gè)性自然發(fā)展。她還利用第一手觀察資料和“兒童之家”的實(shí)驗(yàn),提出了一系列有關(guān)兒童發(fā)展的規(guī)律。

      蒙臺(tái)梭利認(rèn)為,每個(gè)孩子都需要去觀察,對(duì)外界作出反應(yīng),去學(xué)習(xí),去集中注意力,甚至讓自己獨(dú)處。為此,蒙臺(tái)梭利一直致力于打破已有的教育傳統(tǒng),尋求了解孩子和愛(ài)孩子的新方法。在本書(shū)中,她描述了孩子的特性,傳授了如何更充分地喚起孩子學(xué)習(xí)熱情的方法。正如蒙臺(tái)梭利所言:“即便是對(duì)那些非常幼小孩子的教育,我們的目的不應(yīng)是為他們上學(xué)準(zhǔn)備,而是為了他們的生活?!?/p>

      《有吸收力的心靈》

      蒙臺(tái)梭利博士的封筆之作,集蒙臺(tái)梭利思想和方法大成之作。

      本書(shū)是蒙臺(tái)梭利博士最受歡迎,并且最能體現(xiàn)她理論創(chuàng)新意義的書(shū)。在本書(shū)中,我們處處能見(jiàn)到她那些至今仍然超前而且十分重要的思想。如教育并非“老師做了什么”,人類自身的自然發(fā)展在其中起著舉足輕重的作用;孩子的知識(shí)不是完全通過(guò)教育得到的,而是通過(guò)兒童在他們所處的環(huán)境中吸取經(jīng)驗(yàn)獲得的;教育不應(yīng)該只停留在課程和時(shí)間表上,它必須符合人類自身的實(shí)際,等等。本書(shū)將蒙臺(tái)梭利對(duì)兒童發(fā)展的探索與她有關(guān)“如何確立一種新的教育方法”的論述結(jié)合起來(lái),是一本了解蒙臺(tái)梭利教育思想的必讀書(shū)。

      =================== 1.2 蒙臺(tái)梭利留下了豐富的教育著作。就其內(nèi)容可大致分為四類:

      (一)關(guān)于從誕生到3周歲兒童教育的有:《童年的秘密》、《兒童的發(fā)現(xiàn)》和《有吸收力的心理》;

      (二)關(guān)于3歲至7歲兒童教育的有:《蒙臺(tái)梭利的方法》、《蒙臺(tái)梭利手冊(cè)》、《家庭中的兒童》;

      (三)關(guān)于7歲至13歲兒童及青春期教育的有:《高級(jí)蒙臺(tái)梭利方法》兩卷,包括《教育中的自發(fā)活動(dòng)》與《蒙臺(tái)梭利初等教具》、《青春期及其后的教育》;

      (四)關(guān)于教育與智力開(kāi)發(fā):《新世界的教育》、《教育人類學(xué)》、《開(kāi)發(fā)人類的潛能》、《教育的重建》、《和平教育》等。

      下載書(shū)籍簡(jiǎn)介與設(shè)計(jì)word格式文檔
      下載書(shū)籍簡(jiǎn)介與設(shè)計(jì).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)范文推薦

        書(shū)籍簡(jiǎn)介(小編整理)

        《賣茶翁茶器圖》 1823年刻,木村孔陽(yáng)氏編繪賣茶翁(日本江戶時(shí)代煎茶道中興之祖高游外之別號(hào))茶具計(jì)三十三件,彩繪木刻,可遠(yuǎn)窺我唐宋茶器形制之大略。原書(shū)現(xiàn)藏日本早稻田大學(xué)圖書(shū)......

        書(shū)籍設(shè)計(jì)與印刷藝術(shù) 讀后感

        書(shū)籍設(shè)計(jì)與印刷藝術(shù) 讀后感 作 者:毛德寶 出 版 社:東南大學(xué)出版社 這是一本書(shū)籍裝幀設(shè)計(jì)的圖文書(shū)。從書(shū)籍的目錄中可以看到,開(kāi)始緒論全面思考書(shū)籍是個(gè)一個(gè)整體,第二章是書(shū)籍的......

        書(shū)籍設(shè)計(jì)常識(shí)

        書(shū)籍設(shè)計(jì)小常識(shí) 頁(yè)面的術(shù)語(yǔ) 一張有2個(gè)PG,在印刷的前要弄清楚是單面印刷,還是雙面印刷;單頁(yè)還是成冊(cè)的書(shū)刊。頁(yè)面的每個(gè)細(xì)節(jié)都有不同的術(shù)語(yǔ)。出血位 印刷成品邊緣全白色無(wú)圖文,叫......

        書(shū)籍設(shè)計(jì)教案

        課題:文化的傳播-----書(shū)籍設(shè)計(jì) 課時(shí):2課時(shí) 授課人:樊昕靜 課 型:設(shè)計(jì) 授課對(duì)象:高中二年級(jí)學(xué)生 教學(xué)目標(biāo):1:知識(shí)和技能目標(biāo):使學(xué)生初步了解書(shū)籍裝幀的概念、歷史和相關(guān)術(shù)語(yǔ)。 2:過(guò)......

        書(shū)籍設(shè)計(jì)心得

        書(shū)籍設(shè)計(jì)心得 書(shū)籍是人類文明進(jìn)步的階梯,人類的智慧積淀、流傳與延續(xù),依靠書(shū)籍。書(shū)籍給人們知識(shí)與力量。古人說(shuō)過(guò),“三日不讀書(shū)便覺(jué)語(yǔ)言無(wú)味,而面目可憎也”。足見(jiàn)書(shū)籍作為精神......

        200本設(shè)計(jì)書(shū)籍

        3D書(shū)籍 PS彩平圖+鳥(niǎo)瞰建模渲染+室內(nèi)漫游 印象效果圖燈光與色彩的表現(xiàn) 3ds Max/mental ray印象 超寫(xiě)實(shí)效果圖表現(xiàn)專業(yè) http://dl.dbank.com/c0lpygqsyi http://dl.dbank.com/......

        教學(xué)設(shè)計(jì)書(shū)籍(合集)

        介紹你讀過(guò)的教學(xué)設(shè)計(jì)書(shū)籍,及其發(fā)展趨勢(shì)。 教學(xué)設(shè)計(jì)研究發(fā)展趨勢(shì)的探討 曾祥翊 論著選摘 摘要:教學(xué)設(shè)計(jì)是教育技術(shù)的重要研究領(lǐng)域,自其產(chǎn)生以來(lái)的近40余年來(lái),國(guó)內(nèi)外的教學(xué)設(shè)計(jì)......

        書(shū)籍設(shè)計(jì)教案

        書(shū)籍裝幀設(shè)計(jì)教案 ——書(shū)籍裝幀中其他環(huán)節(jié)的設(shè)計(jì) 教學(xué)目標(biāo)與要求:書(shū)籍設(shè)計(jì)中有很多容易被初學(xué)者忽視的環(huán)節(jié),在本章中將逐一講述,文字以及圖片說(shuō)明。要求學(xué)生全面掌握,在設(shè)計(jì)過(guò)......