欧美视频免费在线观看,小黄鸭精品aⅴ导航网站入口,亚洲另类自拍http://www.shnenglu.com/oosky/一天一個(gè)腳印...... <br>每日一句: <script language="javascript" charset="utf-8" src="http://sl.iciba.com/spdshow.php"></script>zh-cnWed, 26 Nov 2025 16:15:45 GMTWed, 26 Nov 2025 16:15:45 GMT60調(diào)試5.0M sensor模組的筆記(轉(zhuǎn)載)http://www.shnenglu.com/oosky/archive/2010/09/15/126672.html任我行任我行Wed, 15 Sep 2010 08:58:00 GMThttp://www.shnenglu.com/oosky/archive/2010/09/15/126672.htmlhttp://www.shnenglu.com/oosky/comments/126672.htmlhttp://www.shnenglu.com/oosky/archive/2010/09/15/126672.html#Feedback0http://www.shnenglu.com/oosky/comments/commentRss/126672.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/126672.html詳細(xì)出處:http://www.52rd.com/Blog/Detail_RD.Blog_bmw7_24676.html#41074

   在25平臺(tái)上調(diào)試了一款帶ISP處理器的5.0M sensor 模組,在25上實(shí)現(xiàn)了5.0M sensor的預(yù)覽拍照功能。下面是調(diào)試過(guò)程中的一些筆記:

一.關(guān)于H-sync /V-Sync的知識(shí):

1. 分辨率:比如說(shuō)640x480,就會(huì)有640 個(gè)pixel &480 line,那么每個(gè)V-sync的信號(hào)時(shí)間內(nèi)就會(huì)有480個(gè)H-sync,而一個(gè)H-sync會(huì)有640個(gè)pixel。但是,每個(gè)pixel會(huì)有2 byte,所以我們會(huì)量到PCLK 在一個(gè)H-sync內(nèi)的數(shù)量會(huì)有1280個(gè)。

2. H-sync /V-Sync的極性polarity: polarity就是資料有效的準(zhǔn)備,比方說(shuō)V-sync上的H-sync有可能在V-sync的low,也有可能在high出現(xiàn)。

 

二. 所使用的ISP處理器簡(jiǎn)介:XXX838是一款isp(圖像信號(hào)處理器)ic,核心是一款arm7 process,提供自動(dòng)對(duì)焦,人臉識(shí)別等功能。BB通過(guò)i2c與其進(jìn)行命令類的數(shù)據(jù)通信,而sensor數(shù)據(jù)則通過(guò)CCIR總線傳輸給BB.

 

三. 25平臺(tái) camera處理流程學(xué)習(xí)

1.       void cam_event_ind_hdlr(ilm_struct *ilm_ptr)// This function is to handle camera event indication.

    在該函數(shù)中,通過(guò)camera_capture_mem_process(&capture_mem_param)命令從lcd層獲取capture數(shù)據(jù),然后通過(guò)jpeg_encode_process(&jpg_encode)命令將這些數(shù)據(jù)軟編碼成jpeg格式的數(shù)據(jù)。

  

2.       void cam_capture_req_hdlr(ilm_struct *ilm_ptr)// This function is to handle camera capture request.

(1)       該函數(shù)首先執(zhí)行exit_camera_preview_process();命令退出preview流程;

(2)       ./* copy preview data to MMI buffer */

memcpy(

                (kal_uint8*) cam_context_p->frame_buffer_p,

                (kal_uint8*) cam_context_p->int_frame_buffer_p,

                cam_context_p->frame_buffer_size);

(3). /* release preview related memory */

        cam_release_memory();

  

3.cam_context_p->capture_buffer_p :所需存儲(chǔ)的拍照數(shù)據(jù)指針

  cam_context_p->file_size :所要存儲(chǔ)的數(shù)據(jù)大小

4. 在cam_open_image_file函數(shù)中執(zhí)行命令

cam_context_p->capture_buffer_p = (kal_uint32) med_alloc_ext_mem(buffer_size);

來(lái)分配內(nèi)存。

Capture數(shù)據(jù)存儲(chǔ)指針:capture_isp_param.target_buffer_start_address = (kal_uint32) cam_context_p->capture_buffer_p;

camera_capture_jpeg_process(&capture_isp_param);

isp_capture_jpeg_data.target_buffer_start_address=isp_data->target_buffer_start_address;

sw_jpeg_encode_config_data.jpeg_file_start_address=isp_capture_jpeg_data.target_buffer_start_address;

 

 5. camera capture后的數(shù)據(jù)傳送流程:cam_context_p->intmem_start_address.

  (1).  capture_isp_param.intmem_start_address = cam_context_p->intmem_start_address =

        (kal_uint32) med_alloc_int_mem(cam_capture_mem[0]);//只有45k

    capture_isp_param.intmem_size = cam_context_p->intmem_size = (kal_uint32) cam_capture_mem[0];

  (2). file_size = camera_capture_jpeg_process(&capture_isp_param); //jpeg編碼后的文件大小

  (3).isp_capture_jpeg_data.intmem_start_address=isp_data->intmem_start_address;

       isp_capture_jpeg_data.intmem_size=isp_data->intmem_size;

  (4).    intmem_init((kal_uint32 *) isp_capture_jpeg_data.intmem_start_address,

                                   isp_capture_jpeg_data.intmem_size);

  (5).sw_jpeg_encode_config_data.intmem_start_address=isp_capture_jpeg_data.intmem_start_address; //將所獲取的capture原始數(shù)據(jù)地址指針賦給軟編碼的起始地址

 

 

四.調(diào)試關(guān)鍵點(diǎn)

1. 首先調(diào)通I2C通訊,必須確保BB與ISP的I2C通訊正常;

2.  重新定義#define MAX_CAM_FILE_BUFFER_LEN   (3150*1024)    /* 2700kb for 5.0M */

 

3.仿照camera_capture_jpeg_process函數(shù),創(chuàng)建一個(gè)新函數(shù),在該函數(shù)中對(duì)獲取的數(shù)據(jù)直接存儲(chǔ),而不經(jīng)過(guò)jpeg編碼流程(由于XXX838傳輸過(guò)來(lái)的已經(jīng)是jpeg格式的數(shù)據(jù))。

注意:

(1)       在該函數(shù)中,要設(shè)置:

ENABLE_CAMERA_OUTPUT_TO_MEM;//ISP輸出至Memory,

SET_CAMERA_CAPTURE_MODE

 /*** Capture,等待VSYNC中斷**/      

 (2).在capture完成后,要DISABLE_CMOS_SESNOR;//關(guān)閉sensor信號(hào)。

 (3).此時(shí),獲取的capture的數(shù)據(jù)已經(jīng)存儲(chǔ)在isp_data->target_buffer_start_address中;

然后讀取這些數(shù)據(jù),通過(guò)0xff ,0xd8判斷文件頭,0xff ,0xd9判斷jpeg文件尾及其長(zhǎng)度。

(4)最后,通過(guò)kal_int32 cam_close_image_file(kal_uint32 size)保存文件


 



任我行 2010-09-15 16:58 發(fā)表評(píng)論
]]>
關(guān)于調(diào)用約定(cdecl、fastcall、、thiscall) 的一點(diǎn)知識(shí)http://www.shnenglu.com/oosky/archive/2007/01/08/17422.html任我行任我行Mon, 08 Jan 2007 06:17:00 GMThttp://www.shnenglu.com/oosky/archive/2007/01/08/17422.htmlhttp://www.shnenglu.com/oosky/comments/17422.htmlhttp://www.shnenglu.com/oosky/archive/2007/01/08/17422.html#Feedback3http://www.shnenglu.com/oosky/comments/commentRss/17422.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/17422.html閱讀全文

任我行 2007-01-08 14:17 發(fā)表評(píng)論
]]>
PE文件格式詳解http://www.shnenglu.com/oosky/archive/2006/11/24/15614.html任我行任我行Fri, 24 Nov 2006 02:29:00 GMThttp://www.shnenglu.com/oosky/archive/2006/11/24/15614.htmlhttp://www.shnenglu.com/oosky/comments/15614.htmlhttp://www.shnenglu.com/oosky/archive/2006/11/24/15614.html#Feedback5http://www.shnenglu.com/oosky/comments/commentRss/15614.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/15614.html閱讀全文

任我行 2006-11-24 10:29 發(fā)表評(píng)論
]]>
消費(fèi)者維權(quán)的5種途徑http://www.shnenglu.com/oosky/archive/2006/10/12/13609.html任我行任我行Thu, 12 Oct 2006 09:25:00 GMThttp://www.shnenglu.com/oosky/archive/2006/10/12/13609.htmlhttp://www.shnenglu.com/oosky/comments/13609.htmlhttp://www.shnenglu.com/oosky/archive/2006/10/12/13609.html#Feedback0http://www.shnenglu.com/oosky/comments/commentRss/13609.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/13609.html值10.1期間,到上海買了款A(yù)cer的本本,7天后問(wèn)題出現(xiàn)。換機(jī)后麻煩更大。
詳細(xì)過(guò)程就不說(shuō)了,具體看這個(gè)網(wǎng)址:http://benyouhui.it168.com/viewthread.php?tid=399111&extra=page%3D1

上網(wǎng)找了找相關(guān)的法律及法規(guī)。才明白還可以有多種途徑。看來(lái)這個(gè)消費(fèi)者權(quán)益法還是必要讀讀看看。

消費(fèi)者維權(quán)的5種途徑



一、協(xié)商和解

協(xié)商和解的定義

????消費(fèi)者與經(jīng)營(yíng)者在發(fā)生爭(zhēng)議后,就與爭(zhēng)議有關(guān)的問(wèn)題進(jìn)行協(xié)商,在自愿、互諒的基礎(chǔ)上,通過(guò)直接對(duì)話擺事實(shí)、講道理,分清責(zé)任,達(dá)成和解協(xié)議,使糾紛得以解決的活動(dòng)。消費(fèi)者權(quán)益爭(zhēng)議的協(xié)商和解是一種快速、簡(jiǎn)便的爭(zhēng)議解決方式,無(wú)論是對(duì)消費(fèi)者還是對(duì)經(jīng)營(yíng)者,它都不失為一種理想的途徑。事實(shí)上,日常生活中大量的消費(fèi)者權(quán)益爭(zhēng)議都是通過(guò)這種方式解決的。

消費(fèi)者與經(jīng)營(yíng)者協(xié)商和解的法律依據(jù)

????《消費(fèi)者權(quán)益保護(hù)法》第34條明確規(guī)定:"消費(fèi)者和經(jīng)營(yíng)者發(fā)生消費(fèi)者權(quán)益爭(zhēng)議的,可以通過(guò)下列途徑解決:(1)與經(jīng)營(yíng)者協(xié)商和解;(2)請(qǐng)求消費(fèi)者協(xié)會(huì)調(diào)解;(3)向有關(guān)行政部門申訴;(4)根據(jù)與經(jīng)營(yíng)者達(dá)成的仲裁協(xié)議提請(qǐng)仲裁機(jī)構(gòu)仲裁;(5)向人民法院提起訴訟。"此條第1項(xiàng)規(guī)定,即"與經(jīng)營(yíng)者協(xié)商和解",便是消費(fèi)者與經(jīng)營(yíng)者協(xié)商和解的法律依據(jù)。

協(xié)商和解的步驟

????在實(shí)踐中,協(xié)商和解可以在其權(quán)益受到侵犯時(shí),帶上有關(guān)證據(jù),如購(gòu)貨憑證或者服務(wù)單據(jù)以及受損失證據(jù),找到經(jīng)營(yíng)者,向其負(fù)責(zé)人或者主管解決糾紛的部門說(shuō)明情況,并提出自己的意見(jiàn)和要求。如果經(jīng)營(yíng)者覺(jué)得消費(fèi)者的意見(jiàn)和要求合理,就會(huì)接受。如果經(jīng)營(yíng)者覺(jué)得消費(fèi)者的要求過(guò)高,就會(huì)要求消費(fèi)者降低其要求。經(jīng)過(guò)一番"討價(jià)還價(jià)"后,達(dá)成一個(gè)雙方都愿意接受的協(xié)議時(shí),爭(zhēng)議就解決了。

協(xié)商和解應(yīng)堅(jiān)持協(xié)作和平等原則:

????協(xié)作原則。要求消費(fèi)者與經(jīng)營(yíng)者在融洽的氣氛中,在互相諒解的基礎(chǔ)上,本著實(shí)事求是、團(tuán)結(jié)協(xié)作的精神,通過(guò)擺事實(shí)講道理,弄清事實(shí),分清責(zé)任,自愿地達(dá)成協(xié)議,避免只從自己一方的利益出發(fā),堅(jiān)持已見(jiàn),互不相讓。
????平等原則。消費(fèi)者和經(jīng)營(yíng)者要在平等的前提下自行協(xié)商解決消費(fèi)者權(quán)益爭(zhēng)議。決不允許任何一方憑借某種勢(shì)力,以強(qiáng)凌弱,以大壓小,享有特權(quán),獲得不平等的利益。

在協(xié)商和解時(shí),消費(fèi)者應(yīng)注意以下問(wèn)題:

????針對(duì)經(jīng)營(yíng)者故意拖延或無(wú)理拒絕消費(fèi)者協(xié)商和解建議的行為,消費(fèi)者應(yīng)立即采取措施,用其他途徑解決爭(zhēng)議問(wèn)題。即可用投訴、申訴或仲裁、起訴手段解決糾紛。如果經(jīng)營(yíng)者的故意拖延和無(wú)理拒絕,致使消費(fèi)者財(cái)產(chǎn)損失擴(kuò)大的,經(jīng)營(yíng)者除了應(yīng)當(dāng)滿足消費(fèi)者正常要求外,還應(yīng)當(dāng)就擴(kuò)大的損失承擔(dān)賠償責(zé)任。

????針對(duì)經(jīng)營(yíng)者故意推卸責(zé)任,認(rèn)為產(chǎn)品出現(xiàn)質(zhì)量問(wèn)題是生產(chǎn)廠家的事,要求消費(fèi)者直接找廠家交涉的行為,按《消費(fèi)者權(quán)益保護(hù)法》第35條規(guī)定:"消費(fèi)者在購(gòu)買、使用商品時(shí),其合法權(quán)益受到損害的,可以向銷售者要求賠償。銷售者賠償后,屬于生產(chǎn)者的責(zé)任或者屬于向銷售者提供商品的其他銷售者的責(zé)任的,銷售者有權(quán)向生產(chǎn)者或者其他銷售者追償。消費(fèi)者或者其他受害人因商品缺陷造成人身、財(cái)產(chǎn)損害的,可以向銷售者要求賠償,也可以向生產(chǎn)者要求賠償。屬于生產(chǎn)者責(zé)任的,銷售者賠償后,有權(quán)向生產(chǎn)者追償。屬于銷售者責(zé)任的,生產(chǎn)者賠償后,有權(quán)向銷售者追償。消費(fèi)者在接受服務(wù)時(shí),其合法權(quán)益受到損害的,可以向服務(wù)者要求賠償。"因此,當(dāng)消費(fèi)者遇到商品質(zhì)量問(wèn)題時(shí),如經(jīng)營(yíng)者推卸責(zé)任,認(rèn)為是生產(chǎn)廠家的問(wèn)題,要求消費(fèi)者直接找廠家交涉時(shí),消費(fèi)者應(yīng)當(dāng)有自我保護(hù)意識(shí),不能挾在中間讓廠家和經(jīng)營(yíng)者當(dāng)"皮球"踢。要以法律規(guī)定為依據(jù),切實(shí)維護(hù)自己的合法權(quán)益。

????針對(duì)經(jīng)營(yíng)者以店堂通知、聲明、告示為由,拒不承擔(dān)責(zé)任的行為,按《消費(fèi)者權(quán)益保護(hù)法》第24條規(guī)定:"經(jīng)營(yíng)者不得以格式合同、通知、聲明、店堂告示等方式作出對(duì)消費(fèi)者不公平、不合理的規(guī)定,或者減輕、免除其損害消費(fèi)者合法權(quán)益應(yīng)當(dāng)承擔(dān)的民事責(zé)任。格式合同、通知、聲明、店堂告示等含有前款所列內(nèi)容的,其內(nèi)容無(wú)效。"因此,當(dāng)消費(fèi)者因商品質(zhì)量和服務(wù)問(wèn)題與商家交涉、協(xié)商時(shí),千萬(wàn)不能為其店堂內(nèi)服務(wù)規(guī)則或商品銷售告示所約束,這些服務(wù)規(guī)則與法無(wú)據(jù),沒(méi)有法律效力,應(yīng)視為無(wú)效規(guī)則。

二、投訴和調(diào)解

投訴的定義:

????消費(fèi)者投訴,是指消費(fèi)者為生活消費(fèi)需要購(gòu)買、使用商品或者接受服務(wù),與經(jīng)營(yíng)者之間發(fā)生消費(fèi)者權(quán)益爭(zhēng)議后,請(qǐng)求消費(fèi)者權(quán)益保護(hù)組織調(diào)解,要求保護(hù)其合法權(quán)益的行為。

調(diào)解的含義:

????調(diào)解,即由第三方對(duì)爭(zhēng)議雙方當(dāng)事人進(jìn)行說(shuō)服勸導(dǎo)、勾通調(diào)和,以促成爭(zhēng)議雙方達(dá)成解決糾紛的協(xié)議的活動(dòng)。
《消費(fèi)者權(quán)益保護(hù)法》規(guī)定,消費(fèi)者爭(zhēng)議可以通過(guò)消費(fèi)者協(xié)會(huì)調(diào)解解決。實(shí)際上,消費(fèi)者糾紛的調(diào)解并非只能由消費(fèi)者協(xié)會(huì)進(jìn)行,任何第三人參與消費(fèi)者糾紛的解決,促成爭(zhēng)議雙方達(dá)成協(xié)議的,都屬調(diào)解的范圍。并且只要不存在違法行為,則調(diào)解同樣受法律承認(rèn)。

調(diào)解的原則:


????1、自愿原則。調(diào)解應(yīng)建立在雙方自愿的基礎(chǔ)之上。調(diào)解不同于審判,當(dāng)任何一方不同意調(diào)解時(shí),應(yīng)終止調(diào)解,而不得以任何理由加以強(qiáng)迫。

????2、合法原則。調(diào)解活動(dòng)應(yīng)在合法的原則上進(jìn)行,既要有必要的靈活性,更要有高度的原則性,不能違反法律的規(guī)定來(lái)"和稀泥"。

投訴的形式:


????消費(fèi)者投訴可以采取電話、信函、面談、互聯(lián)網(wǎng)形式進(jìn)行。但無(wú)論采取哪種形式,都要講清楚以下內(nèi)容:一是投訴人基本情況。即投訴人的姓名、性別、聯(lián)系地址、聯(lián)系電話、郵政編碼等。二是被投訴方的基本情況。即被投訴方名稱、地址、電話等。三是購(gòu)買商品的時(shí)間、品牌、產(chǎn)地、規(guī)格、數(shù)量、價(jià)格等。四是受損害的具體情況、發(fā)現(xiàn)問(wèn)題的時(shí)間及與經(jīng)營(yíng)者交涉的經(jīng)過(guò)等。五是購(gòu)物憑證、保修卡、約定書(shū)復(fù)印件等。

三、行政申訴

申訴的定義

????消費(fèi)者和經(jīng)營(yíng)者發(fā)生權(quán)益爭(zhēng)議后,可以請(qǐng)求政府有關(guān)行政部門依行政程序解決爭(zhēng)議,與其他爭(zhēng)議解決途徑相比,申訴具有高效、快捷、力度強(qiáng)等特點(diǎn)。?
消費(fèi)者向政府有關(guān)行政部門申訴的法律依據(jù)

???《消費(fèi)者權(quán)益保護(hù)法》第34條的規(guī)定,消費(fèi)者和經(jīng)營(yíng)者發(fā)生消費(fèi)者權(quán)益爭(zhēng)議的,可以向有關(guān)行政部門申訴。

消費(fèi)者如何進(jìn)行申訴?

????消費(fèi)者決定申訴時(shí),應(yīng)依照商品和服務(wù)的性質(zhì)向具有相關(guān)職能的行政部門提出。消費(fèi)者申訴一般應(yīng)采用書(shū)面形式,一式兩份,并載明下列事項(xiàng):(1)消費(fèi)者的姓名、住址、電話號(hào)碼、郵政編碼;(2)被申訴人的名稱、地址、聯(lián)系電話、郵政編碼;(3)申訴的要求、理由及相關(guān)的事實(shí)根據(jù);(4)申訴的日期。必要時(shí),消費(fèi)者可委托代理人進(jìn)行申訴活動(dòng),但需向有關(guān)行政部門提交授權(quán)委托書(shū)。

????消費(fèi)者向有關(guān)行政部門提出申訴后,如果與經(jīng)營(yíng)者協(xié)商和解,達(dá)成和解協(xié)議的,可以撤回申訴,請(qǐng)求有關(guān)行政部門根據(jù)和解協(xié)議作出調(diào)解書(shū)。如果與經(jīng)營(yíng)者達(dá)成仲裁協(xié)議,可以撤回申訴,向仲裁機(jī)構(gòu)提請(qǐng)仲裁。如果想通過(guò)法律途徑解決,可以撤回申訴,向人民法院提起訴訟。

四、提請(qǐng)仲裁

仲裁的定義?

????雙方當(dāng)事人在爭(zhēng)議發(fā)生前或者爭(zhēng)議發(fā)生后達(dá)成的協(xié)議,自愿將他們之間的爭(zhēng)議提交雙方所同意的仲裁機(jī)構(gòu)居中調(diào)解,作出判斷或裁決的活動(dòng)。

仲裁的優(yōu)越性

仲裁具有當(dāng)事人意思自愿、程序簡(jiǎn)便、一裁終局、專家仲裁、費(fèi)用較低、保守機(jī)密、相互感情影響小等特征。

當(dāng)事人采取仲裁方式解決糾紛,應(yīng)注意以下幾點(diǎn):

(1)當(dāng)事人采用仲裁方式解決糾紛,應(yīng)當(dāng)是雙方自愿,并達(dá)成仲裁協(xié)議;

(2)向哪個(gè)仲裁組織提請(qǐng)仲裁,由當(dāng)事人協(xié)議選定;

(3)可以選擇或者委托仲裁組織指定仲裁員;

(4)可以自行和解,達(dá)成和解協(xié)議的,可以請(qǐng)求仲裁庭根據(jù)和解協(xié)議作出裁決書(shū),也可以撤回仲裁申請(qǐng)。

仲裁的原則和制度

仲裁實(shí)行自愿、獨(dú)立、公正、一裁終局的原則和制度。

仲裁協(xié)議的定義

????雙方當(dāng)事人自愿把他們之間的經(jīng)濟(jì)爭(zhēng)議提交仲裁解決的書(shū)面約定。其表現(xiàn)形式包括合同中訂立的仲裁條款和以其他書(shū)面方式在糾紛發(fā)生后前或者發(fā)生后達(dá)成請(qǐng)求的仲裁協(xié)議。仲裁協(xié)議是獨(dú)立存在的,合同的變更、解除、終止或者無(wú)效,不影響仲裁協(xié)議的效力。

仲裁協(xié)議應(yīng)具備的內(nèi)容

(1)請(qǐng)求仲裁的意思表示;

(2)仲裁事項(xiàng);

(3)選定的仲裁委員會(huì)。

當(dāng)事人提請(qǐng)仲裁應(yīng)當(dāng)符合的條件

(1)有仲裁協(xié)議;

(2)有具體的仲裁請(qǐng)求和事實(shí)理由;

(3)屬于仲裁委員會(huì)的管理范圍。

仲裁案件受理費(fèi)的承擔(dān)

????仲裁費(fèi)用原則上由敗訴的當(dāng)事人承擔(dān),當(dāng)事人部分勝訴,部分?jǐn)≡V的,由仲裁庭根據(jù)當(dāng)事人各方責(zé)任大小確定其各自應(yīng)當(dāng)承擔(dān)的仲裁費(fèi)用的比例,當(dāng)事人自行和解或者經(jīng)仲裁庭調(diào)解結(jié)案的,當(dāng)事人可以協(xié)商確定各自承擔(dān)的仲裁費(fèi)用的比例。

五、提起訴訟

提起訴訟的定義

????消費(fèi)者因其合法權(quán)益受到侵害后,可以向人民法院提起訴訟,請(qǐng)求人民法院依照法定程序進(jìn)行審判。在我國(guó),訴訟大致分為三種形式:(1)刑事訴訟;(2)民事訴訟;(3)行政訴訟。消費(fèi)者因其合法權(quán)益受到侵害而提起的訴訟屬于民事訴訟范疇。

提起訟訴必須具備的法定條件

(1)原告必須是與本案有直接利害關(guān)系的公民、法人和其他組織;
(2)有明確的被告;
(3)有具體的訴訟請(qǐng)求和事實(shí)、理由;
(1)屬于人民法院受理民事訴訟的范圍和受訴人民法院管轄。

符合以上條件的起訴,人民法院才會(huì)予以受理。




任我行 2006-10-12 17:25 發(fā)表評(píng)論
]]>
嵌入式面試考題http://www.shnenglu.com/oosky/archive/2006/08/28/11763.html任我行任我行Mon, 28 Aug 2006 01:51:00 GMThttp://www.shnenglu.com/oosky/archive/2006/08/28/11763.htmlhttp://www.shnenglu.com/oosky/comments/11763.htmlhttp://www.shnenglu.com/oosky/archive/2006/08/28/11763.html#Feedback5http://www.shnenglu.com/oosky/comments/commentRss/11763.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/11763.html 作者不祥,
別看這題目有些比較簡(jiǎn)單,仔細(xì)做來(lái),可還是發(fā)現(xiàn)不少問(wèn)題。?


預(yù)處理器(Preprocessor)


1. 用預(yù)處理指令#define 聲明一個(gè)常數(shù),用以表明1年中有多少秒(忽略閏年問(wèn)題)

#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在這想看到幾件事情:
1). #define 語(yǔ)法的基本知識(shí)(例如:不能以分號(hào)結(jié)束,括號(hào)的使用,等等)
2). 懂得預(yù)處理器將為你計(jì)算常數(shù)表達(dá)式的值,因此,直接寫(xiě)出你是如何計(jì)算一年中有多少秒而不是計(jì)算出實(shí)際的值,是更清晰而沒(méi)有代價(jià)的。
3). 意識(shí)到這個(gè)表達(dá)式將使一個(gè)16位機(jī)的整型數(shù)溢出-因此要用到長(zhǎng)整型符號(hào)L,告訴編譯器這個(gè)常數(shù)是的長(zhǎng)整型數(shù)。
4). 如果你在你的表達(dá)式中用到UL(表示無(wú)符號(hào)長(zhǎng)整型),那么你有了一個(gè)好的起點(diǎn)。記住,第一印象很重要。


2. 寫(xiě)一個(gè)“標(biāo)準(zhǔn)”宏MIN,這個(gè)宏輸入兩個(gè)參數(shù)并返回較小的一個(gè)。

#define MIN(A,B) ((A) <= (B) (A) : (B))
這個(gè)測(cè)試是為下面的目的而設(shè)的:
1). 標(biāo)識(shí)#define在宏中應(yīng)用的基本知識(shí)。這是很重要的,因?yàn)橹钡角度?inline)操作符變?yōu)闃?biāo)準(zhǔn)C的一部分,宏是方便產(chǎn)生嵌入代碼的唯一方法,對(duì)于嵌入式系統(tǒng)來(lái)說(shuō),為了能達(dá)到要求的性能,嵌入代碼經(jīng)常是必須的方法。
2). 三重條件操作符的知識(shí)。這個(gè)操作符存在C語(yǔ)言中的原因是它使得編譯器能產(chǎn)生比if-then-else更優(yōu)化的代碼,了解這個(gè)用法是很重要的。
3). 懂得在宏中小心地把參數(shù)用括號(hào)括起來(lái)
4). 我也用這個(gè)問(wèn)題開(kāi)始討論宏的副作用,例如:當(dāng)你寫(xiě)下面的代碼時(shí)會(huì)發(fā)生什么事?
least = MIN(*p++, b);


3. 預(yù)處理器標(biāo)識(shí)#error的目的是什么?

如果你不知道答案,請(qǐng)看參考文獻(xiàn)1。這問(wèn)題對(duì)區(qū)分一個(gè)正常的伙計(jì)和一個(gè)書(shū)呆子是很有用的。只有書(shū)呆子才會(huì)讀C語(yǔ)言課本的附錄去找出象這種
問(wèn)題的答案。當(dāng)然如果你不是在找一個(gè)書(shū)呆子,那么應(yīng)試者最好希望自己不要知道答案。


死循環(huán)(Infinite loops)


4. 嵌入式系統(tǒng)中經(jīng)常要用到無(wú)限循環(huán),你怎么樣用C編寫(xiě)死循環(huán)呢?

這個(gè)問(wèn)題用幾個(gè)解決方案。我首選的方案是:
while(1) { }
一些程序員更喜歡如下方案:
for(;;) { }
這個(gè)實(shí)現(xiàn)方式讓我為難,因?yàn)檫@個(gè)語(yǔ)法沒(méi)有確切表達(dá)到底怎么回事。如果一個(gè)應(yīng)試者給出這個(gè)作為方案,我將用這個(gè)作為一個(gè)機(jī)會(huì)去探究他們這樣做的
基本原理。如果他們的基本答案是:“我被教著這樣做,但從沒(méi)有想到過(guò)為什么。”這會(huì)給我留下一個(gè)壞印象。
第三個(gè)方案是用 goto
Loop:
...
goto Loop;
應(yīng)試者如給出上面的方案,這說(shuō)明或者他是一個(gè)匯編語(yǔ)言程序員(這也許是好事)或者他是一個(gè)想進(jìn)入新領(lǐng)域的BASIC/FORTRAN程序員。

數(shù)據(jù)聲明(Data declarations)

5. 用變量a給出下面的定義
a) 一個(gè)整型數(shù)(An integer)
b) 一個(gè)指向整型數(shù)的指針(A pointer to an integer)
c) 一個(gè)指向指針的的指針,它指向的指針是指向一個(gè)整型數(shù)(A pointer to a pointer to an integer)
d) 一個(gè)有10個(gè)整型數(shù)的數(shù)組(An array of 10 integers)
e) 一個(gè)有10個(gè)指針的數(shù)組,該指針是指向一個(gè)整型數(shù)的(An array of 10 pointers to integers)
f) 一個(gè)指向有10個(gè)整型數(shù)數(shù)組的指針(A pointer to an array of 10 integers)
g) 一個(gè)指向函數(shù)的指針,該函數(shù)有一個(gè)整型參數(shù)并返回一個(gè)整型數(shù)(A pointer to a function that takes an integer as an argument and returns an integer)
h) 一個(gè)有10個(gè)指針的數(shù)組,該指針指向一個(gè)函數(shù),該函數(shù)有一個(gè)整型參數(shù)并返回一個(gè)整型數(shù)( An array of ten pointers to functions that take an integer argument and return an integer )

答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer


人們經(jīng)常聲稱這里有幾個(gè)問(wèn)題是那種要翻一下書(shū)才能回答的問(wèn)題,我同意這種說(shuō)法。當(dāng)我寫(xiě)這篇文章時(shí),為了確定語(yǔ)法的正確性,我的確查了一下書(shū)。
但是當(dāng)我被面試的時(shí)候,我期望被問(wèn)到這個(gè)問(wèn)題(或者相近的問(wèn)題)。因?yàn)樵诒幻嬖嚨倪@段時(shí)間里,我確定我知道這個(gè)問(wèn)題的答案。應(yīng)試者如果不知道
所有的答案(或至少大部分答案),那么也就沒(méi)有為這次面試做準(zhǔn)備,如果該面試者沒(méi)有為這次面試做準(zhǔn)備,那么他又能為什么出準(zhǔn)備呢?


Static

6. 關(guān)鍵字static的作用是什么?

這個(gè)簡(jiǎn)單的問(wèn)題很少有人能回答完全。在C語(yǔ)言中,關(guān)鍵字static有三個(gè)明顯的作用:
1). 在函數(shù)體,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過(guò)程中維持其值不變。
2). 在模塊內(nèi)(但在函數(shù)體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問(wèn),但不能被模塊外其它函數(shù)訪問(wèn)。它是一個(gè)本地的全局變量。
3). 在模塊內(nèi),一個(gè)被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。
大多數(shù)應(yīng)試者能正確回答第一部分,一部分能正確回答第二部分,同是很少的人能懂得第三部分。這是一個(gè)應(yīng)試者的嚴(yán)重的缺點(diǎn),因?yàn)樗@然不懂得本地化數(shù)據(jù)和代碼范圍的好處和重要性。


Const

7.關(guān)鍵字const是什么含意?
我只要一聽(tīng)到被面試者說(shuō):“const意味著常數(shù)”,我就知道我正在和一個(gè)業(yè)余者打交道。去年Dan Saks已經(jīng)在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應(yīng)該非常熟悉const能做什么和不能做什么.如果你從沒(méi)有讀到那篇文章,只要能說(shuō)出const意味著“只讀”就可以了。盡管這個(gè)答案不是完全的答案,但我接受它作為一個(gè)正確的答案。(如果你想知道更詳細(xì)的答案,仔細(xì)讀一下Saks的文章吧。)如果應(yīng)試者能正確回答這個(gè)問(wèn)題,我將問(wèn)他一個(gè)附加的問(wèn)題:下面的聲明都是什么意思?

const int a;
int const a;
const int *a;
int * const a;
int const * a const;

前兩個(gè)的作用是一樣,a是一個(gè)常整型數(shù)。第三個(gè)意味著a是一個(gè)指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的,但指針可以)。第四個(gè)意思a是一個(gè)指向整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。最后一個(gè)意味著a是一個(gè)指向常整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是不可修改的,同時(shí)指針也是不可修改的)。如果應(yīng)試者能正確回答這些問(wèn)題,那么他就給我留下了一個(gè)好印象。順帶提一句,也許你可能會(huì)問(wèn),即使不用關(guān)鍵字const,也還是能很容易寫(xiě)出功能正確的程序,那么我為什么還要如此看重關(guān)鍵字const呢?我也如下的幾下理由:
1). 關(guān)鍵字const的作用是為給讀你代碼的人傳達(dá)非常有用的信息,實(shí)際上,聲明一個(gè)參數(shù)為常量是為了告訴了用戶這個(gè)參數(shù)的應(yīng)用目的。如果你曾花很多時(shí)間清理其它人留下的垃圾,你就會(huì)很快學(xué)會(huì)感謝這點(diǎn)多余的信息。(當(dāng)然,懂得用const的程序員很少會(huì)留下的垃圾讓別人來(lái)清理的。)
2). 通過(guò)給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。
3). 合理地使用關(guān)鍵字const可以使編譯器很自然地保護(hù)那些不希望被改變的參數(shù),防止其被無(wú)意的代碼修改。簡(jiǎn)而言之,這樣可以減少bug的出現(xiàn)。

Volatile

8. 關(guān)鍵字volatile有什么含意 并給出三個(gè)不同的例子。

一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。精確地說(shuō)就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個(gè)例子:
1). 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)
2). 一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量(Non-automatic variables)
3). 多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量
回答不出這個(gè)問(wèn)題的人是不會(huì)被雇傭的。我認(rèn)為這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問(wèn)題。嵌入式系統(tǒng)程序員經(jīng)常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內(nèi)容將會(huì)帶來(lái)災(zāi)難。
假設(shè)被面試者正確地回答了這是問(wèn)題(嗯,懷疑這否會(huì)是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。
1). 一個(gè)參數(shù)既可以是const還可以是volatile嗎?解釋為什么。
2). 一個(gè)指針可以是volatile 嗎?解釋為什么。
3). 下面的函數(shù)有什么錯(cuò)誤:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1). 是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖儭K莄onst因?yàn)槌绦虿粦?yīng)該試圖去修改它。
2). 是的。盡管這并不很常見(jiàn)。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。
3). 這段代碼的有個(gè)惡作劇。這段代碼的目的是用來(lái)返指針*ptr指向值的平方,但是,由于*ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結(jié)果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}

位操作(Bit manipulation)

9. 嵌入式系統(tǒng)總是要用戶對(duì)變量或寄存器進(jìn)行位操作。給定一個(gè)整型變量a,寫(xiě)兩段代碼,第一個(gè)設(shè)置a的bit 3,第二個(gè)清除a 的bit 3。在以上兩個(gè)操作中,要保持其它位不變。

對(duì)這個(gè)問(wèn)題有三種基本的反應(yīng)
1). 不知道如何下手。該被面者從沒(méi)做過(guò)任何嵌入式系統(tǒng)的工作。
2). 用bit fields。Bit fields是被扔到C語(yǔ)言死角的東西,它保證你的代碼在不同編譯器之間是不可移植的,同時(shí)也保證了的你的代碼是不可重用的。我最近不幸看到Infineon為其較復(fù)雜的通信芯片寫(xiě)的驅(qū)動(dòng)程序,它用到了bit fields因此完全對(duì)我無(wú)用,因?yàn)槲业木幾g器用其它的方式來(lái)實(shí)現(xiàn)bit fields的。從道德講:永遠(yuǎn)不要讓一個(gè)非嵌入式的家伙粘實(shí)際硬件的邊。
3). 用 #defines 和 bit masks 操作。這是一個(gè)有極高可移植性的方法,是應(yīng)該被用到的方法。最佳的解決方案如下:
#define BIT3 (0x1<<3)
static int a;
void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}
一些人喜歡為設(shè)置和清除值而定義一個(gè)掩碼同時(shí)定義一些說(shuō)明常數(shù),這也是可以接受的。我希望看到幾個(gè)要點(diǎn):說(shuō)明常數(shù)、|=和&=~操作。

訪問(wèn)固定的內(nèi)存位置(Accessing fixed memory locations)

10. 嵌入式系統(tǒng)經(jīng)常具有要求程序員去訪問(wèn)某特定的內(nèi)存位置的特點(diǎn)。在某工程中,要求設(shè)置一絕對(duì)地址為0x67a9的整型變量的值為0xaa66。編譯器是一個(gè)純粹的ANSI編譯器。寫(xiě)代碼去完成這一任務(wù)。

這一問(wèn)題測(cè)試你是否知道為了訪問(wèn)一絕對(duì)地址把一個(gè)整型數(shù)強(qiáng)制轉(zhuǎn)換(typecast)為一指針是合法的。這一問(wèn)題的實(shí)現(xiàn)方式隨著個(gè)人風(fēng)格不同而不同。典型的類似代碼如下:
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;

一個(gè)較晦澀的方法是:
*(int * const)(0x67a9) = 0xaa55;

即使你的品味更接近第二種方案,但我建議你在面試時(shí)使用第一種方案。

中斷(Interrupts)

11. 中斷是嵌入式系統(tǒng)中重要的組成部分,這導(dǎo)致了很多編譯開(kāi)發(fā)商提供一種擴(kuò)展—讓標(biāo)準(zhǔn)C支持中斷。具代表事實(shí)是,產(chǎn)生了一個(gè)新的關(guān)鍵字__interrupt。下面的代碼就使用了__interrupt關(guān)鍵字去定義了一個(gè)中斷服務(wù)子程序(ISR),請(qǐng)?jiān)u論一下這段代碼的。

__interrupt double compute_area (double radius)
{
??? double area = PI * radius * radius;
??? printf(" Area = %f", area);
??? return area;
}

這個(gè)函數(shù)有太多的錯(cuò)誤了,以至讓人不知從何說(shuō)起了:
1). ISR 不能返回一個(gè)值。如果你不懂這個(gè),那么你不會(huì)被雇用的。
2). ISR 不能傳遞參數(shù)。如果你沒(méi)有看到這一點(diǎn),你被雇用的機(jī)會(huì)等同第一項(xiàng)。
3). 在許多的處理器/編譯器中,浮點(diǎn)一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點(diǎn)運(yùn)算。此外,ISR應(yīng)該是短而有效率的,在ISR中做浮點(diǎn)運(yùn)算是不明智的。
4). 與第三點(diǎn)一脈相承,printf()經(jīng)常有重入和性能上的問(wèn)題。如果你丟掉了第三和第四點(diǎn),我不會(huì)太為難你的。不用說(shuō),如果你能得到后兩點(diǎn),那么你的被雇用前景越來(lái)越光明了。

代碼例子(Code examples)
12 . 下面的代碼輸出是什么,為什么?

void foo(void)
{
??? unsigned int a = 6;
??? int b = -20;
??? (a+b > 6) puts("> 6") : puts("<= 6");
}

這個(gè)問(wèn)題測(cè)試你是否懂得C語(yǔ)言中的整數(shù)自動(dòng)轉(zhuǎn)換原則,我發(fā)現(xiàn)有些開(kāi)發(fā)者懂得極少這些東西。不管如何,這無(wú)符號(hào)整型問(wèn)題的答案是輸出是“>6”。原因是當(dāng)表達(dá)式中存在有符號(hào)類型和無(wú)符號(hào)類型時(shí)所有的操作數(shù)都自動(dòng)轉(zhuǎn)換為無(wú)符號(hào)類型。 因此-20變成了一個(gè)非常大的正整數(shù),所以該表達(dá)式計(jì)算出的結(jié)果大于6。這一點(diǎn)對(duì)于應(yīng)當(dāng)頻繁用到無(wú)符號(hào)數(shù)據(jù)類型的嵌入式系統(tǒng)來(lái)說(shuō)是豐常重要的。如果你答錯(cuò)了這個(gè)問(wèn)題,你也就到了得不到這份工作的邊緣。

13. 評(píng)價(jià)下面的代碼片斷:

unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */

對(duì)于一個(gè)int型不是16位的處理器為說(shuō),上面的代碼是不正確的。應(yīng)編寫(xiě)如下:

unsigned int compzero = ~0;

這一問(wèn)題真正能揭露出應(yīng)試者是否懂得處理器字長(zhǎng)的重要性。在我的經(jīng)驗(yàn)里,好的嵌入式程序員非常準(zhǔn)確地明白硬件的細(xì)節(jié)和它的局限,然而PC機(jī)程序往往把硬件作為一個(gè)無(wú)法避免的煩惱。
到了這個(gè)階段,應(yīng)試者或者完全垂頭喪氣了或者信心滿滿志在必得。如果顯然應(yīng)試者不是很好,那么這個(gè)測(cè)試就在這里結(jié)束了。但如果顯然應(yīng)試者做得不錯(cuò),那么我就扔出下面的追加問(wèn)題,這些問(wèn)題是比較難的,我想僅僅非常優(yōu)秀的應(yīng)試者能做得不錯(cuò)。提出這些問(wèn)題,我希望更多看到應(yīng)試者應(yīng)付問(wèn)題的方法,而不是答案。不管如何,你就當(dāng)是這個(gè)娛樂(lè)吧…



動(dòng)態(tài)內(nèi)存分配(Dynamic memory allocation)



14. 盡管不像非嵌入式計(jì)算機(jī)那么常見(jiàn),嵌入式系統(tǒng)還是有從堆(heap)中動(dòng)態(tài)分配內(nèi)存的過(guò)程的。那么嵌入式系統(tǒng)中,動(dòng)態(tài)分配內(nèi)存可能發(fā)生的問(wèn)題是什么?

這里,我期望應(yīng)試者能提到內(nèi)存碎片,碎片收集的問(wèn)題,變量的持行時(shí)間等等。這個(gè)主題已經(jīng)在ESP雜志中被廣泛地討論過(guò)了(主要是 P.J. Plauger, 他的解釋遠(yuǎn)遠(yuǎn)超過(guò)我這里能提到的任何解釋),所有回過(guò)頭看一下這些雜志吧!讓?xiě)?yīng)試者進(jìn)入一種虛假的安全感覺(jué)后,我拿出這么一個(gè)小節(jié)目:下面的代碼片段的輸出是什么,為什么?

char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");

這是一個(gè)有趣的問(wèn)題。最近在我的一個(gè)同事不經(jīng)意把0值傳給了函數(shù)malloc,得到了一個(gè)合法的指針之后,我才想到這個(gè)問(wèn)題。這就是上面的代碼,該代碼的輸出是“Got a valid pointer”。我用這個(gè)來(lái)開(kāi)始討論這樣的一問(wèn)題,看看被面試者是否想到庫(kù)例程這樣做是正確。得到正確的答案固然重要,但解決問(wèn)題的方法和你做決定的基本原理更重要些。

Typedef

15. Typedef 在C語(yǔ)言中頻繁用以聲明一個(gè)已經(jīng)存在的數(shù)據(jù)類型的同義字。也可以用預(yù)處理器做類似的事。例如,思考一下下面的例子:
#define dPS struct s *
typedef struct s * tPS;

以上兩種情況的意圖都是要定義dPS 和 tPS 作為一個(gè)指向結(jié)構(gòu)s指針。哪種方法更好呢?(如果有的話)為什么?
這是一個(gè)非常微妙的問(wèn)題,任何人答對(duì)這個(gè)問(wèn)題(正當(dāng)?shù)脑颍┦菓?yīng)當(dāng)被恭喜的。答案是:typedef更好。思考下面的例子:
dPS p1,p2;
tPS p3,p4;

第一個(gè)擴(kuò)展為
struct s * p1, p2;

上面的代碼定義p1為一個(gè)指向結(jié)構(gòu)的指,p2為一個(gè)實(shí)際的結(jié)構(gòu),這也許不是你想要的。第二個(gè)例子正確地定義了p3 和p4 兩個(gè)指針。

晦澀的語(yǔ)法

16. C語(yǔ)言同意一些令人震驚的結(jié)構(gòu),下面的結(jié)構(gòu)是合法的嗎,如果是它做些什么?
int a = 5, b = 7, c;
c = a+++b;

這個(gè)問(wèn)題將做為這個(gè)測(cè)驗(yàn)的一個(gè)愉快的結(jié)尾。不管你相不相信,上面的例子是完全合乎語(yǔ)法的。問(wèn)題是編譯器如何處理它?水平不高的編譯作者實(shí)際上會(huì)爭(zhēng)論這個(gè)問(wèn)題,根據(jù)最處理原則,編譯器應(yīng)當(dāng)能處理盡可能所有合法的用法。因此,上面的代碼被處理成:
c = a++ + b;
因此, 這段代碼持行后a = 6, b = 7, c = 12。
如果你知道答案,或猜出正確答案,做得好。如果你不知道答案,我也不把這個(gè)當(dāng)作問(wèn)題。我發(fā)現(xiàn)這個(gè)問(wèn)題的最大好處是:這是一個(gè)關(guān)于代碼編寫(xiě)風(fēng)格,代碼的可讀性,代碼的可修改性的好的話題



任我行 2006-08-28 09:51 發(fā)表評(píng)論
]]>
KMP算法祥解http://www.shnenglu.com/oosky/archive/2006/07/06/9486.html任我行任我行Thu, 06 Jul 2006 06:02:00 GMThttp://www.shnenglu.com/oosky/archive/2006/07/06/9486.htmlhttp://www.shnenglu.com/oosky/comments/9486.htmlhttp://www.shnenglu.com/oosky/archive/2006/07/06/9486.html#Feedback38http://www.shnenglu.com/oosky/comments/commentRss/9486.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/9486.html閱讀全文

任我行 2006-07-06 14:02 發(fā)表評(píng)論
]]>
Boost安裝http://www.shnenglu.com/oosky/archive/2006/06/30/9243.html任我行任我行Fri, 30 Jun 2006 09:08:00 GMThttp://www.shnenglu.com/oosky/archive/2006/06/30/9243.htmlhttp://www.shnenglu.com/oosky/comments/9243.htmlhttp://www.shnenglu.com/oosky/archive/2006/06/30/9243.html#Feedback0http://www.shnenglu.com/oosky/comments/commentRss/9243.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/9243.html閱讀全文

任我行 2006-06-30 17:08 發(fā)表評(píng)論
]]>
難道C/C++是塊難啃的骨頭,這里落戶的兄弟太少了http://www.shnenglu.com/oosky/archive/2006/06/01/8022.html任我行任我行Thu, 01 Jun 2006 04:50:00 GMThttp://www.shnenglu.com/oosky/archive/2006/06/01/8022.htmlhttp://www.shnenglu.com/oosky/comments/8022.htmlhttp://www.shnenglu.com/oosky/archive/2006/06/01/8022.html#Feedback21http://www.shnenglu.com/oosky/comments/commentRss/8022.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/8022.html在Cppblog落戶的兄弟怎么還那么少呢?

看這首頁(yè)中的統(tǒng)計(jì)信息,少的可憐。1K用戶都不到,.NET區(qū)的一個(gè)零頭都不到。
  • 博客 - 822
  • 隨筆 - 2917
  • 文章 - 1217
  • 評(píng)論 - 2784
再來(lái)看看.NET區(qū):
  • 博客 - 15618
  • 隨筆 - 108752
  • 文章 - 34156
  • 評(píng)論 - 208492
看來(lái)大伙得想想辦法能熱鬧點(diǎn)。
dudu也來(lái)想想辦法。


任我行 2006-06-01 12:50 發(fā)表評(píng)論
]]>
推薦兩款瀏覽器-FireFox&Maxthonhttp://www.shnenglu.com/oosky/archive/2006/04/30/6498.html任我行任我行Sun, 30 Apr 2006 11:05:00 GMThttp://www.shnenglu.com/oosky/archive/2006/04/30/6498.htmlhttp://www.shnenglu.com/oosky/comments/6498.htmlhttp://www.shnenglu.com/oosky/archive/2006/04/30/6498.html#Feedback3http://www.shnenglu.com/oosky/comments/commentRss/6498.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/6498.html閱讀全文

任我行 2006-04-30 19:05 發(fā)表評(píng)論
]]>
打造UltralEdit-32為C/C++編譯器http://www.shnenglu.com/oosky/archive/2006/04/20/5936.html任我行任我行Thu, 20 Apr 2006 06:24:00 GMThttp://www.shnenglu.com/oosky/archive/2006/04/20/5936.htmlhttp://www.shnenglu.com/oosky/comments/5936.htmlhttp://www.shnenglu.com/oosky/archive/2006/04/20/5936.html#Feedback16http://www.shnenglu.com/oosky/comments/commentRss/5936.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/5936.html閱讀全文

任我行 2006-04-20 14:24 發(fā)表評(píng)論
]]>
VC6 + ICC8.1+...VC6與VS2005媲美http://www.shnenglu.com/oosky/archive/2006/04/10/5255.html任我行任我行Mon, 10 Apr 2006 11:22:00 GMThttp://www.shnenglu.com/oosky/archive/2006/04/10/5255.htmlhttp://www.shnenglu.com/oosky/comments/5255.htmlhttp://www.shnenglu.com/oosky/archive/2006/04/10/5255.html#Feedback28http://www.shnenglu.com/oosky/comments/commentRss/5255.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/5255.html下面自己去體驗(yàn)吧!
  閱讀全文

任我行 2006-04-10 19:22 發(fā)表評(píng)論
]]>
華為軟件編程規(guī)范和范例http://www.shnenglu.com/oosky/archive/2006/03/26/4625.html任我行任我行Sun, 26 Mar 2006 09:04:00 GMThttp://www.shnenglu.com/oosky/archive/2006/03/26/4625.htmlhttp://www.shnenglu.com/oosky/comments/4625.htmlhttp://www.shnenglu.com/oosky/archive/2006/03/26/4625.html#Feedback13http://www.shnenglu.com/oosky/comments/commentRss/4625.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/4625.html閱讀全文

任我行 2006-03-26 17:04 發(fā)表評(píng)論
]]>
匯編語(yǔ)言超濃縮教程http://www.shnenglu.com/oosky/archive/2006/02/20/3354.html任我行任我行Mon, 20 Feb 2006 08:17:00 GMThttp://www.shnenglu.com/oosky/archive/2006/02/20/3354.htmlhttp://www.shnenglu.com/oosky/comments/3354.htmlhttp://www.shnenglu.com/oosky/archive/2006/02/20/3354.html#Feedback4http://www.shnenglu.com/oosky/comments/commentRss/3354.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/3354.html    “ 哎喲,哥們兒,還搗鼓匯編呢?那東西沒(méi)用,兄弟用VB"釣"一個(gè)API就夠你忙活個(gè)十天半月的,還不一定搞出來(lái)。”此君之言倒也不虛,那吾等還有無(wú)必要研他一究呢?(廢話,當(dāng)然有啦!要不然你寫(xiě)這篇文章干嘛。)別急,別急,讓我把這個(gè)中原委慢慢道來(lái):一、所有電腦語(yǔ)言寫(xiě)出的程序運(yùn)行時(shí)在內(nèi)存中都以機(jī)器碼方式存儲(chǔ),機(jī)器碼可以被比較準(zhǔn)確的翻譯成匯編語(yǔ)言,這是因?yàn)閰R編語(yǔ)言兼容性最好,故幾乎所有跟蹤、調(diào)試工具(包括WIN95/98下)都是以匯編示人的,如果閣下對(duì)CRACK頗感興趣……;二、匯編直接與硬件打交道,如果你想搞通程序在執(zhí)行時(shí)在電腦中的來(lái)龍去脈,也就是搞清電腦每個(gè)組成部分究竟在干什么、究竟怎么干?一個(gè)真正的硬件發(fā)燒友,不懂這些可不行。三、如今玩DOS的多是“高手”,如能像吾一樣混入(我不是高手)“高手”內(nèi)部,不僅可以從“高手”朋友那兒套些黑客級(jí)“機(jī)密”,還可以自詡“高手”盡情享受強(qiáng)烈的虛榮感--#$%& “醒醒!”

  對(duì)初學(xué)者而言,匯編的許多命令太復(fù)雜,往往學(xué)習(xí)很長(zhǎng)時(shí)間也寫(xiě)不出一個(gè)漂漂亮亮的程序,以致妨礙了我們學(xué)習(xí)匯編的興趣,不少人就此放棄。所以我個(gè)人看法學(xué)匯編,不一定要寫(xiě)程序,寫(xiě)程序確實(shí)不是匯編的強(qiáng)項(xiàng),大家不妨玩玩DEBUG,有時(shí)CRACK出一個(gè)小軟件比完成一個(gè)程序更有成就感(就像學(xué)電腦先玩游戲一樣)。某些高深的指令事實(shí)上只對(duì)有經(jīng)驗(yàn)的匯編程序員有用,對(duì)我們而言,太過(guò)高深了。為了使學(xué)習(xí)匯編語(yǔ)言有個(gè)好的開(kāi)始,你必須要先排除那些華麗復(fù)雜的命令,將注意力集中在最重要的幾個(gè)指令上(CMP LOOP MOV JNZ……)。但是想在啰里吧嗦的教科書(shū)中完成上述目標(biāo),談何容易,所以本人整理了這篇超濃縮(用WINZIP、WINRAR…依次壓迫,嘿嘿!)教程。大言不慚的說(shuō),看通本文,你完全可以“不經(jīng)意”間在前輩或是后生賣弄一下DEBUG,很有成就感的,試試看!那么――這個(gè)接下來(lái)呢?―― Here we go!(閱讀時(shí)看不懂不要緊,下文必有分解)

  因?yàn)閰R編是通過(guò)CPU和內(nèi)存跟硬件對(duì)話的,所以我們不得不先了解一下CPU和內(nèi)存:(關(guān)于數(shù)的進(jìn)制問(wèn)題在此不提)

  CPU是可以執(zhí)行電腦所有算術(shù)╱邏輯運(yùn)算與基本 I/O 控制功能的一塊芯片。一種匯編語(yǔ)言只能用于特定的CPU。也就是說(shuō),不同的CPU其匯編語(yǔ)言的指令語(yǔ)法亦不相同。個(gè)人電腦由1981年推出至今,其CPU發(fā)展過(guò)程為:8086→80286→80386→80486→PENTIUM →……,還有AMD、CYRIX等旁支。后面兼容前面CPU的功能,只不過(guò)多了些指令(如多能奔騰的MMX指令集)、增大了寄存器(如386的32位EAX)、增多了寄存器(如486的FS)。為確保匯編程序可以適用于各種機(jī)型,所以推薦使用8086匯編語(yǔ)言,其兼容性最佳。本文所提均為8086匯編語(yǔ)言。寄存器(Register)是CPU內(nèi)部的元件,所以在寄存器之間的數(shù)據(jù)傳送非常快。用途:1.可將寄存器內(nèi)的數(shù)據(jù)執(zhí)行算術(shù)及邏輯運(yùn)算。2.存于寄存器內(nèi)的地址可用來(lái)指向內(nèi)存的某個(gè)位置,即尋址。3.可以用來(lái)讀寫(xiě)數(shù)據(jù)到電腦的周邊設(shè)備。8086 有8個(gè)8位數(shù)據(jù)寄存器,這些8位寄存器可分別組成16位寄存器:AH&AL=AX:累加寄存器,常用于運(yùn)算;BH&BL=BX:基址寄存器,常用于地址索引;CH&CL=CX:計(jì)數(shù)寄存器,常用于計(jì)數(shù);DH&DL=DX:數(shù)據(jù)寄存器,常用于數(shù)據(jù)傳遞。為了運(yùn)用所有的內(nèi)存空間,8086設(shè)定了四個(gè)段寄存器,專門用來(lái)保存段地址:CS(Code Segment):代碼段寄存器;DS(Data Segment):數(shù)據(jù)段寄存器;SS(Stack Segment):堆棧段寄存器;ES(Extra Segment):附加段寄存器。當(dāng)一個(gè)程序要執(zhí)行時(shí),就要決定程序代碼、數(shù)據(jù)和堆棧各要用到內(nèi)存的哪些位置,通過(guò)設(shè)定段寄存器 CS,DS,SS 來(lái)指向這些起始位置。通常是將DS固定,而根據(jù)需要修改CS。所以,程序可以在可尋址空間小于64K的情況下被寫(xiě)成任意大小。 所以,程序和其數(shù)據(jù)組合起來(lái)的大小,限制在DS 所指的64K內(nèi),這就是COM文件不得大于64K的原因。8086以內(nèi)存做為戰(zhàn)場(chǎng),用寄存器做為軍事基地,以加速工作。除了前面所提的寄存器外,還有一些特殊功能的寄存器:IP(Intruction Pointer):指令指針寄存器,與CS配合使用,可跟蹤程序的執(zhí)行過(guò)程;SP(Stack Pointer):堆棧指針,與SS配合使用,可指向目前的堆棧位置。BP(Base Pointer):基址指針寄存器,可用作SS的一個(gè)相對(duì)基址位置;SI(Source Index):源變址寄存器可用來(lái)存放相對(duì)于DS段之源變址指針;DI(Destination Index):目的變址寄存器,可用來(lái)存放相對(duì)于 ES 段之目的變址指針。還有一個(gè)標(biāo)志寄存器FR(Flag Register),有九個(gè)有意義的標(biāo)志,將在下文用到時(shí)詳細(xì)說(shuō)明。

  內(nèi)存是電腦運(yùn)作中的關(guān)鍵部分,也是電腦在工作中儲(chǔ)存信息的地方。內(nèi)存組織有許多可存放數(shù)值的儲(chǔ)存位置,叫“地址”。8086地址總線有20位,所以CPU擁有達(dá)1M的尋址空間,這也是DOS的有效控制范圍,而8086能做的運(yùn)算僅限于處理16位數(shù)據(jù),即只有0到64K,所以,必須用分段尋址才能控制整個(gè)內(nèi)存地址。完整的20位地址可分成兩部份:1.段基址(Segment):16位二進(jìn)制數(shù)后面加上四個(gè)二進(jìn)制0,即一個(gè)16進(jìn)制0,變成20位二進(jìn)制數(shù),可設(shè)定1M中任何一個(gè)64K段,通常記做16位二進(jìn)制數(shù);2.偏移量(Offset):直接使用16位二進(jìn)制數(shù),指向段基址中的任何一個(gè)地址。如:2222(段基址):3333(偏移量),其實(shí)際的20位地址值為:25553。除了上述營(yíng)養(yǎng)要充分吸收外,你還要知道什么是DOS、BIOS功能調(diào)用,簡(jiǎn)單的說(shuō),功能調(diào)用類似于WIN95 API,相當(dāng)于子程序。匯編寫(xiě)程序已經(jīng)夠要命了,如果不用MS、IBM的子程序,這日子真是沒(méi)法過(guò)了(關(guān)于功能調(diào)用詳見(jiàn)《電腦愛(ài)好者》98年11期)。

  編寫(xiě)匯編語(yǔ)言有兩種主要的方法:1.使用MASM或TASM等編譯器;2.使用除錯(cuò)程序DEBUG.COM。DEBUG其實(shí)并不能算是一個(gè)編譯器,它的主要用途在于除錯(cuò),即修正匯編程序中的錯(cuò)誤。不過(guò),也可以用來(lái)寫(xiě)短的匯編程序,尤其對(duì)初學(xué)者而言,DEBUG 更是最佳的入門工具。因?yàn)镈EBUG操作容易:只要鍵入DEBUG回車,A回車即可進(jìn)行匯編,過(guò)程簡(jiǎn)單,而使用編譯器時(shí),必須用到文本編輯器、編譯器本身、LINK以及EXE2BIN等程序,其中每一個(gè)程序都必須用到一系列相當(dāng)復(fù)雜的命令才能工作,而且用編譯器處理源程序,必須加入許多與指令語(yǔ)句無(wú)關(guān)的指示性語(yǔ)句,以供編譯器識(shí)別,使用 DEBUG 可以避免一開(kāi)始就碰到許多難以理解的程序行。DEBUG 除了能夠匯編程序之外,還可用來(lái)檢查和修改內(nèi)存位置、載入儲(chǔ)存和執(zhí)行程序、以及檢查和修改寄存器,換句話說(shuō),DEBUG是為了讓我們接觸硬件而設(shè)計(jì)的。(8086常用指令用法將在每個(gè)匯編程序中講解,限于篇幅,不可能將所有指令列出)。

  DEBUG的的A命令可以匯編出簡(jiǎn)單的COM文件,所以DEBUG編寫(xiě)的程序一定要由地址 100h(COM文件要求)開(kāi)始才合法。FOLLOW ME,SETP BY SETP(步步回車):

  輸入 A100 ; 從DS:100開(kāi)始匯編
  2.輸入 MOV DL,1 ; 將數(shù)值 01h 裝入 DL 寄存器
  3.輸入 MOV AH,2 ; 將數(shù)值 02h 裝入 DL 寄存器
  4.輸入 INT 21 ; 調(diào)用DOS 21號(hào)中斷2號(hào)功能,用來(lái)逐個(gè)顯示裝入DL的字符
  5.輸入 INT 20 ; 調(diào)用DOS 20號(hào)中斷,終止程序,將控制權(quán)交回給 DEBUG
  6.請(qǐng)按 Enter 鍵
  7.現(xiàn)在已將匯編語(yǔ)言程序放入內(nèi)存中了,輸入 G(運(yùn)行)
  8.出現(xiàn)結(jié)果:輸出一個(gè)符號(hào)。
  ㄖ ←輸出結(jié)果其實(shí)不是它,因WORD97無(wú)法顯示原結(jié)果,故找一贗品將就著。
  Program terminated normally

  我們可以用U命令將十六進(jìn)制的機(jī)器碼反匯編(Unassemble)成匯編指令。你將發(fā)現(xiàn)每一行右邊的匯編指令就是被匯編成相應(yīng)的機(jī)器碼,而8086實(shí)際上就是以機(jī)器碼來(lái)執(zhí)行程序。
  1.輸入 U100,106
  1FED:0100 B201 MOV DL,01
  1FED:0102 B402 MOV AH,02
  1FED:0104 CD21 INT 21
  1FED:0106 CD20 INT 20
  DEBUG可以用R命令來(lái)查看、改變寄存器內(nèi)容。CS:IP寄存器,保存了將執(zhí)行指令地址。
  1.輸入R
  AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
  DS=1FED ES=1FED SS=1FED CS=1FED IP=0100 NV UP EI PL NZ NA PO NC
  1FED:0100 B201 MOV DL,01

  當(dāng)程序由DS:100開(kāi)始執(zhí)行,那么終止程序時(shí),DEBUG會(huì)自動(dòng)將IP內(nèi)容重新設(shè)定為100。當(dāng)你要將此程序做成一個(gè)獨(dú)立的可執(zhí)行文件,則可以用N命令對(duì)該程序命名。但一定要為COM文件,否則無(wú)法以DEBUG載入。
  輸入N SMILE.COM ;我們得告訴DEBUG程序長(zhǎng)度:程序從100開(kāi)始到106,故占用7
  ;字節(jié)。我們利用BX存放長(zhǎng)度值高位部分,而以CX存放低位部分。
  2.輸入RBX ;查看 BX 寄存器的內(nèi)容,本程序只有7個(gè)字節(jié),故本步可省略
  3.輸入 RCX  ;查看 CX 寄存器的內(nèi)容
  4.輸入 7  ;程序的字節(jié)數(shù)
  5.輸入 W ;用W命令將該程序?qū)懭耄╓rite)磁盤(pán)中

  修行至此,我們便可以真正接觸8086匯編指令了。 當(dāng)我們寫(xiě)匯編語(yǔ)言程序的時(shí)候,通常不會(huì)直接將機(jī)器碼放入內(nèi)存中,而是打入一串助記符號(hào)(Mnemonic Symbols),這些符號(hào)比十六進(jìn)制機(jī)器碼更容易記住,此之謂匯編指令。助記符號(hào),告訴CPU應(yīng)執(zhí)行何種運(yùn)算。 也就是說(shuō),助憶符號(hào)所構(gòu)成的匯編語(yǔ)言是為人設(shè)計(jì)的,而機(jī)器語(yǔ)言是對(duì)PC設(shè)計(jì)的。

  現(xiàn)在,我們?cè)賮?lái)剖析一個(gè)可以將所有ASCII碼顯示出來(lái)的程序。
  1. 輸入 DEBUG
  2. 輸入 A100
  3.輸入 MOV CX,0100 ;裝入循環(huán)次數(shù)
  MOV DL,00 ;裝入第一個(gè)ASCII碼,隨后每次循環(huán)裝入新碼
  MOV AH,02
  INT 21
  INC DL ;INC:遞增指令,每次將數(shù)據(jù)寄存器 DL 內(nèi)的數(shù)值加 1
  LOOP 0105 ;LOOP:循環(huán)指令,每執(zhí)行一次LOOP,CX值減1,并跳
  ;到循環(huán)的起始地址105,直到CX為0,循環(huán)停止
  INT 20
  4.輸入 G即可顯示所有ASCII碼
 
  當(dāng)我們想任意顯示字符串,如:UNDERSTAND?,則可以使用DOS21H號(hào)中斷9H號(hào)功能。輸入下行程序,存盤(pán)并執(zhí)行看看:
  1.輸入 A100
   MOV DX,109 ;DS:DX = 字符串的起始地址
   MOV AH,9 ;DOS的09h功能調(diào)用
  INT 21 ;字符串輸出
  INT 20
  DB 'UNDERSTAND?$';定義字符串

  在匯編語(yǔ)言中,有兩種不同的指令:1.正規(guī)指令:如 MOV 等,是屬于CPU的指令,用來(lái)告訴CPU在程序執(zhí)行時(shí)應(yīng)做些什么,所以它會(huì)以運(yùn)算碼(OP-code)的方式存入內(nèi)存中;2.偽指令:如DB等,是屬于DEBUG等編譯器的指令,用來(lái)告訴編譯器在編譯時(shí)應(yīng)做些什么。DB(Define Byte)指令用來(lái)告訴DEBUG 將單引號(hào)內(nèi)的所有ASCII 碼放入內(nèi)存中。使用 9H 功能的字符串必須以$結(jié)尾。用D命令可用來(lái)查看DB偽指令將那些內(nèi)容放入內(nèi)存。
  6.輸入 D100
  1975:0100 BA 09 01 B4 09 CD 21 CD-20 75 6E 64 65 72 73 74 ......!. underst
  1975:0110 61 6E 64 24 8B 46 F8 89-45 04 8B 46 34 00 64 19 and$.F..E..F4.d.
  1975:0120 89 45 02 33 C0 5E 5F C9-C3 00 C8 04 00 00 57 56 .E.3.^_.......WV
  1975:0130 6B F8 0E 81 C7 FE 53 8B-DF 8B C2 E8 32 FE 0B C0 k.....S.....2...
  1975:0140 74 05 33 C0 99 EB 17 8B-45 0C E8 D4 97 8B F0 89 t.3.....E.......
  1975:0150 56 FE 0B D0 74 EC 8B 45-08 03 C6 8B 56 FE 5E 5F V...t..E....V.^_
  1975:0160 C9 C3 C8 02 00 00 6B D8-0E 81 C3 FE 53 89 5E FE ......k.....S.^.
  1975:0170 8B C2 E8 FB FD 0B C0 75-09 8B 5E FE 8B 47 0C E8 .......u..^..G..

  現(xiàn)在,我們來(lái)剖析另一個(gè)程序:由鍵盤(pán)輸入任意字符串,然后顯示出來(lái)。db 20指示DEBUG保留20h個(gè)未用的內(nèi)存空間供緩沖區(qū)使用。
  輸入A100
   MOV DX,0116 ;DS:DX = 緩沖區(qū)地址,由DB偽指令確定緩沖區(qū)地址
  MOV AH,0A ;0Ah 號(hào)功能調(diào)用
  INT 21 ;鍵盤(pán)輸入緩沖區(qū)
  MOV DL,0A ;由于功能Ah在每個(gè)字符串最后加一個(gè)歸位碼(0Dh由 Enter
  MOV AH,02 ;產(chǎn)生),使光標(biāo)自動(dòng)回到輸入行的最前端,為了使新輸出的
  INT 21 ;字符串不會(huì)蓋掉原來(lái)輸入的字符串,所以利用功能2h加一
  ;個(gè)換行碼(OAh),使得光標(biāo)移到下一行的的最前端。
  MOV DX,0118 ;裝入字符串的起始位置
  MOV AH,09 ;9h功能遇到$符號(hào)才會(huì)停止輸出,故字符串最后必須加上
  INT 21 ;$,否則9h功能會(huì)繼續(xù)將內(nèi)存中的無(wú)用數(shù)據(jù)胡亂顯示出來(lái)
  INT 20
  DB 20 ;定義緩沖區(qū)
  送你一句話:學(xué)匯編切忌心浮氣燥。

  客套話就不講了。工欲善其事,必先利其器。與其說(shuō)DEBUG 是編譯器,倒不如說(shuō)它是“直譯器”,DEBUG的A命令只可將一行匯編指令轉(zhuǎn)成機(jī)器語(yǔ)言,且立刻執(zhí)行。真正編譯器(MASM)的運(yùn)作是利用文本編輯器(EDIT等)將匯編指令建成一個(gè)獨(dú)立且附加名為.ASM的文本文件,稱源程序。它是MASM 程序的輸入部分。MASM將輸入的ASM文件,編譯成.OBJ文件,稱為目標(biāo)程序。OBJ文件僅包含有關(guān)程序各部份要載入何處及如何與其他程序合并的信息,無(wú)法直接載入內(nèi)存執(zhí)行。鏈結(jié)程序LINK則可將OBJ文件轉(zhuǎn)換成可載入內(nèi)存執(zhí)行(EXEcute)的EXE文件。還可以用EXE2BIN,將符合條件的EXE文件轉(zhuǎn)成COM文件(COM 文件不但占用的內(nèi)存最少,而且運(yùn)行速度最快)。
  下面我們用MASM寫(xiě)一個(gè)與用DEBUG寫(xiě)的第一個(gè)程序功能一樣的程序。
  用EDIT編輯一個(gè)SMILE.ASM的源程序文件。
  源程序 DEBUG 程序
  prognam segment
  assume cs:prognam
  org 100h A100
  mov dl,1 mov dl,1
  mov ah,2 mov ah,2
  int 21h int 21
  int 20h int 20
  prognam ends
  end

  比較一下:1.因?yàn)镸ASM會(huì)將所有的數(shù)值假設(shè)為十進(jìn)制,而DEBUG則只使用十六進(jìn)制,所以在源程序中,我們必須在有關(guān)數(shù)字后加上代表進(jìn)制的字母,如H代表十六進(jìn)制,D代表十進(jìn)制。若是以字母開(kāi)頭的十六進(jìn)制數(shù)字,還必須在字母前加個(gè)0,以表示它是數(shù),如0AH。2.源程序增加五行敘述:prognam segment 與 prognam ends 是成對(duì)的,用來(lái)告訴 MASM 及LINK,此程序?qū)⒎旁谝粋€(gè)稱為PROGNAM(PROGram NAMe)的程序段內(nèi),其中段名(PROGNAM)可以任取,但其位置必須固定。assume cs:prognam 必須在程序的開(kāi)頭,用來(lái)告訴編譯器此程序所在段的位置放在CS寄存器中。end用來(lái)告訴MASM,程序到此結(jié)束, ORG 100H作用相當(dāng)于DEBUG的A100,從偏移量100開(kāi)始匯編。COM 文件的所有源程序都必須包含這五行,且必須依相同的次序及位置出現(xiàn),這點(diǎn)東西記下就行,千篇一律。接著,我們用MASM編譯SMILE.ASM。
  輸入 MASM SMILE ←不用打入附加名.ASM。
  Microsoft (R) Macro Assembler Version 5.10
  Copyright (C) Microsoft Corp 1981, 1988. All rights reserved.
  Object filename [SMILE.OBJ]: ←是否改動(dòng)輸出OBJ文件名,如不改就ENTER
  Source listing [NUL.LST]: ← 是否需要列表文件(LST),不需要就ENTER
  Cross-reference [NUL.CRF]: ←是否需要對(duì)照文件(CRF),不需要?jiǎng)tENTER
  50162 + 403867 Bytes symbol space free
  0 Warning Errors ←警告錯(cuò)誤,表示編譯器對(duì)某些語(yǔ)句不理解,通常是輸入錯(cuò)誤。
  0 Severe Errors ←嚴(yán)重錯(cuò)誤,會(huì)造成程序無(wú)法執(zhí)行,通常是語(yǔ)法結(jié)構(gòu)錯(cuò)誤。

  如果沒(méi)有一個(gè)錯(cuò)誤存在,即可生成OBJ文件。OBJ中包含的是編譯后的二進(jìn)制結(jié)果,它還無(wú)法被 DOS載入內(nèi)存中加以執(zhí)行,必須加以鏈結(jié)(Linking)。以LINK將OBJ文件(SMILE.OBJ)鏈結(jié)成 EXE 文件(SMILE.EXE)時(shí),。
  1.輸入 LINK SMILE ←不用附加名OBJ
  Microsoft (R) Overlay Linker Version 3.64
  Copyright (C) Microsoft Corp 1981, 1988. All rights reserved.
  Run File [SMILE.EXE]: ← 是否改動(dòng)輸出EXE文件名,如不改就ENTER
  List File [NUL.MAP]: ← 是否需要列表文件(MAP),不需要?jiǎng)tENTER
  Libraries [.LIB]: ←是否需要庫(kù)文件,要就鍵入文件名,不要?jiǎng)tENTER
  LINK : warning L4021: no stack segment← 由于COM文件不使用堆棧段,所以錯(cuò)誤信息
  ←"no stack segment"并不影響程序正常執(zhí)行

  至此已經(jīng)生成EXE文件,我們還須使用EXE2BIN 將EXE文件(SMILE.EXE),轉(zhuǎn)換成COM文件(SMILE.COM)。輸入EXE2BIN SMILE產(chǎn)生 BIN 文件(SMILE.BIN)。其實(shí) BIN 文件與 COM 文件是完全相同的,但由于DOS只認(rèn)COM、EXE及BAT文件,所以BIN文件無(wú)法被正確執(zhí)行,改名或直接輸入 EXE2BIN SMILE SMILE.COM即可。現(xiàn)在,磁盤(pán)上應(yīng)該有 SMILE.COM 文件了,你只要在提示符號(hào)C:>下,直接輸入文件名稱 SMILE ,就可以執(zhí)行這個(gè)程序了。

  你是否覺(jué)得用編譯器產(chǎn)生程序的方法,比 DEBUG 麻煩多了!以小程序而言,的確是如此,但對(duì)于較大的程序,你就會(huì)發(fā)現(xiàn)其優(yōu)點(diǎn)了。我們?cè)賹SCII程序以編譯器方式再做一次,看看有無(wú)差異。首先,用EDIT.COM建立 ASCII.ASM 文件。
  prognam segment ;定義段
  assume cs:prognam ;把上面定義段的段基址放入 CS
  mov cx,100h ; 裝入循環(huán)次數(shù)
  mov dl,0 ; 裝入第一個(gè)ASCII碼,隨后每次循環(huán)裝入新碼
  next: mov ah,2
   int 21h
   inc dl ;INC:遞增指令,每次將數(shù)據(jù)寄存器 DL 內(nèi)的數(shù)值加 1
  loop next ; 循環(huán)指令,執(zhí)行一次,CX減1,直到CX為0,循環(huán)停止
  int 20h
   prognam ends ;段終止
  end ;匯編終止
  在匯編語(yǔ)言的源程序中,每一個(gè)程序行都包含三項(xiàng)元素:
    start: mov dl,1 ;裝入第一個(gè)ASCII碼,隨后每次循環(huán)裝入新碼
    標(biāo)識(shí)符 表達(dá)式 注解

  在原始文件中加上注解可使程序更易理解,便于以后參考。每行注解以“;”與程序行分離。編譯器對(duì)注解不予理會(huì),注解的數(shù)據(jù)不會(huì)出現(xiàn)在OBJ、EXE或COM文件中。由于我們?cè)趯?xiě)源程序時(shí),并不知道每一程序行的地址,所以必須以符號(hào)名稱來(lái)代表相對(duì)地址,稱為“標(biāo)識(shí)符”。我們通常在適當(dāng)行的適當(dāng)位置上,鍵入標(biāo)識(shí)符。標(biāo)識(shí)符(label)最長(zhǎng)可達(dá)31 個(gè)字節(jié),因此我們?cè)诔绦蛑校M量以簡(jiǎn)潔的文字做為標(biāo)識(shí)符。現(xiàn)在,你可以將此ASCII.ASM 文件編譯成 ASCII.COM 了。1.MASM ASCII,2.LINK ASCII,3.EXE2BIN ASCII ASCII.COM。

  注意:當(dāng)你以編譯器匯編你設(shè)計(jì)的程序時(shí),常會(huì)發(fā)生打字錯(cuò)誤、標(biāo)識(shí)符名稱拼錯(cuò)、十六進(jìn)制數(shù)少了h、邏輯錯(cuò)誤等。匯編老手常給新人的忠告是:最好料到自己所寫(xiě)的程序一定會(huì)有些錯(cuò)誤(別人告訴我的);如果第一次執(zhí)行程序后,就得到期望的結(jié)果,你最好還是在檢查一遍,因?yàn)樗赡苁清e(cuò)的。原則上,只要大體的邏輯架構(gòu)正確,查找程序中錯(cuò)誤的過(guò)程,與寫(xiě)程序本身相比甚至更有意思。寫(xiě)大程序時(shí),最好能分成許多模塊,如此可使程序本身的目的較單純,易于撰寫(xiě)與查錯(cuò),另外也可讓程序中不同部份之間的界限較清楚,節(jié)省編譯的時(shí)間。如果讀程序有讀不懂的地方最好用紙筆記下有關(guān)寄存器、內(nèi)存等內(nèi)容,在紙上慢慢比劃,就豁然開(kāi)朗了。   下面我們將寫(xiě)一個(gè)能從鍵盤(pán)取得一個(gè)十進(jìn)制的數(shù)值,并將其轉(zhuǎn)換成十六進(jìn)制數(shù)值而顯示于屏幕上的“大程序”。前言:要讓8086執(zhí)行這樣的功能,我們必須先將此問(wèn)題分解成一連串的步驟,稱為程序規(guī)劃。首先,以流程圖的方式,來(lái)確保整個(gè)程序在邏輯上沒(méi)有問(wèn)題(不用說(shuō)了吧!什么語(yǔ)言都要有此步驟)。這種模塊化的規(guī)劃方式,稱之為“由上而下的程序規(guī)劃”。而在真正寫(xiě)程序時(shí),卻是從最小的單位模塊(子程序)開(kāi)始,當(dāng)每個(gè)模塊都完成之后,再合并成大程序;這種大處著眼,小處著手的方式稱為“由下而上的程序設(shè)計(jì)”。

  我們的第一個(gè)模塊是BINIHEX,其主要用途是從8086的BX寄存器中取出二進(jìn)制數(shù),并以十六進(jìn)制方式顯示在屏幕上。注意:子程序如不能獨(dú)立運(yùn)行,實(shí)屬正常。
   binihex segment
   assume cs:binihex
  mov ch,4 ;記錄轉(zhuǎn)換后的十六進(jìn)制位數(shù)(四位)
  rotate: mov cl,4 ;利用CL當(dāng)計(jì)數(shù)器,記錄寄存器數(shù)位移動(dòng)次數(shù)
  rol bx,cl ;循環(huán)寄存器BX的內(nèi)容,以便依序處理4個(gè)十六進(jìn)制數(shù)
  mov al,bl ;把bx低八位bl內(nèi)數(shù)據(jù)轉(zhuǎn)移至al
  and al,0fh ;把無(wú)用位清零
  add al,30h ;把AL內(nèi)數(shù)據(jù)加30H,并存入al
  cmp al,3ah ;與3ah比較
  jl printit ;小于3ah則轉(zhuǎn)移
  add al,7h ;把AL內(nèi)數(shù)據(jù)加30H,并存入al
  printit:mov dl,al ;把ASCII碼裝入DL
  mov ah,2
   int 21h
   dec ch ;ch減一,減到零時(shí),零標(biāo)志置1
  jnz rotate ;JNZ:當(dāng)零標(biāo)志未置1,則跳到指定地址。即:不等,則轉(zhuǎn)移
  int 20h ;從子程序退回主程序
  binihex ends
   end

  利用循環(huán)左移指令ROL循環(huán)寄存器BX(BX內(nèi)容將由第二個(gè)子程序提供)的內(nèi)容,以便依序處理4個(gè)十六進(jìn)制數(shù):1. 利用CL當(dāng)計(jì)數(shù)器,記錄寄存器移位的次數(shù)。2.將BX的第一個(gè)十六進(jìn)制值移到最右邊。利用 AND (邏輯“與”運(yùn)算:對(duì)應(yīng)位都為1時(shí),其結(jié)果為1,其余情況為零)把不要的部份清零,得到結(jié)果:先將BL值存入AL中,再利用AND以0Fh(00001111)將AL的左邊四位清零。由于0到9的ASCII碼為30h到39h,而A到F之ASCII碼為41h到46h,間斷了7h,所以得到結(jié)果:若AL之內(nèi)容小于3Ah,則AL值只加30h,否則AL再加7h。ADD指令會(huì)將兩個(gè)表達(dá)式相加,其結(jié)果存于左邊表達(dá)式內(nèi)。標(biāo)志寄存器(Flag Register)是一個(gè)單獨(dú)的十六位寄存器,有9個(gè)標(biāo)志位,某些匯編指令(大部份是涉及比較、算術(shù)或邏輯運(yùn)算的指令)執(zhí)行時(shí),會(huì)將相關(guān)標(biāo)志位置1或清0, 常碰到的標(biāo)志位有零標(biāo)志(ZF)、符號(hào)標(biāo)志(SF)、溢出標(biāo)志(OF)和進(jìn)位標(biāo)志(CF)。 標(biāo)志位保存了某個(gè)指令執(zhí)行后對(duì)它的影響,可用其他相關(guān)指令,查出標(biāo)志的狀態(tài),根據(jù)狀態(tài)產(chǎn)生動(dòng)作。CMP指令很像減法,是將兩個(gè)表達(dá)式的值相減,但寄存器或內(nèi)存的內(nèi)容并未改變,只是相對(duì)的標(biāo)志位發(fā)生改變而已:若 AL 值小于 3Ah,則正負(fù)號(hào)標(biāo)志位會(huì)置0,反之則置1。 JL指令可解釋為:小于就轉(zhuǎn)移到指定位置,大于、等于則向下執(zhí)行。CMP和JG 、JL等條件轉(zhuǎn)移指令一起使用,可以形成程序的分支結(jié)構(gòu),是寫(xiě)匯編程序常用技巧。

  第二個(gè)模塊DECIBIN 用來(lái)接收鍵盤(pán)打入的十進(jìn)制數(shù),并將它轉(zhuǎn)換成二進(jìn)制數(shù)放于BX 寄存器中,供模塊1 BINIHEX使用。
  decibin segment
  assume cs:decibin
  mov bx,0 ;BX清零
  newchar:mov ah,1 ;
  int 21h ;讀一個(gè)鍵盤(pán)輸入符號(hào)入al,并顯示
  sub al,30h ;al減去30H,結(jié)果存于al中,完成ASCII碼轉(zhuǎn)二進(jìn)制碼
  jl exit ;小于零則轉(zhuǎn)移
  cmp al,9d
   jg exit ;左>右則轉(zhuǎn)移
  cbw ;8位al轉(zhuǎn)換成16位ax
  xchg ax,bx ;互換ax和bx內(nèi)數(shù)據(jù)
  mov cx,10d ;十進(jìn)制數(shù)10入cx
  mul cx ;表達(dá)式的值與ax內(nèi)容相乘,并將結(jié)果存于ax
  xchg ax,bx
   add bx,ax
   jmp newchar ;無(wú)條件轉(zhuǎn)移
  exit: int 20 ;回主程序
  decibin ends
   end
  CBW 實(shí)際結(jié)果是:若AL中的值為正,則AH填入00h;反之,則AH填入FFh。XCHG常用于需要暫時(shí)保留某個(gè)寄存器中的內(nèi)容時(shí)。
  當(dāng)然,還得一個(gè)子程序(CRLF)使后顯示的十六進(jìn)制數(shù)不會(huì)蓋掉先輸入的十進(jìn)制數(shù)。
  crlf segment
  assume cs:crlf
  mov dl,0dh ;回車的ASCII碼0DH入DL
  mov ah,2
   int 21h
   mov dl,0ah ;換行的ASSII碼0AH入AH
  mov ah,2
   int 21h
   int 20 ;回主程序
  crlf ends
  end

  現(xiàn)在我們就可以將BINIHEX、DECIBIN及CRLF等模塊合并成一個(gè)大程序了。首先,我們要將這三個(gè)模塊子程序略加改動(dòng)。然后,再寫(xiě)一段程序來(lái)調(diào)用每一個(gè)子程序。
  crlf proc near;
  mov dl,0dh
  mov ah,2
  int 21h
  mov dl,0ah
  mov ah,2
  int 21h
  ret
  crlf endp

  類似SEGMENT與ENDS的偽指令,PROC與ENDP也是成對(duì)出現(xiàn),用來(lái)識(shí)別并定義一個(gè)程序。其實(shí),PROC 真正的作用只是告訴編譯器:所調(diào)用的程序是屬于近程(NEAR)或遠(yuǎn)程(FAR)。 一般的程序是由 DEBUG 直接調(diào)用的,所以用 INT 20 返回,用 CALL 指令所調(diào)用的程序則改用返回指令RET,RET會(huì)把控制權(quán)轉(zhuǎn)移到棧頂所指的地址,而該地址是由調(diào)用此程序的 CALL指令所放入的。
  各模塊都搞定了,然后我們把子程序組合起來(lái)就大功告成
  decihex segment ;主程序
  assume cs:decihex
  org 100h
  mov cx,4 ;循環(huán)次數(shù)入cx;由于子程序要用到cx,故子程序要將cx入棧
  repeat: call decibin;調(diào)用十進(jìn)制轉(zhuǎn)二進(jìn)制子程序
  call crlf ;調(diào)用添加回、換行符子程序
  call binihex ;調(diào)用二進(jìn)制轉(zhuǎn)十六進(jìn)制并顯示子程序
  call crlf
  loop repeat ;循環(huán)4次,可連續(xù)運(yùn)算4次
  mov ah,4ch ; 調(diào)用DOS21號(hào)中斷4c號(hào)功能,退出程序,作用跟INT 20H
  int 21H ; 一樣,但適用面更廣,INT20H退不出時(shí),試一下它
  decibin proc near push cx ;將cx壓入堆棧,;
  ┇ exit: pop cx ;將cx還原; retdecibin endp binihex proc near push cx
  ┇ pop cx retbinihex endp crlf proc near
   push cx
  ┇ pop cx retcrlf endpdecihex ends end

  CALL指令用來(lái)調(diào)用子程序,并將控制權(quán)轉(zhuǎn)移到子程序地址,同時(shí)將CALL的下行一指令地址定為返回地址,并壓入堆棧中。CALL 可分為近程(NEAR)及遠(yuǎn)程(FAR)兩種:1.NEAR:IP的內(nèi)容被壓入堆棧中,用于程序與程序在同一段中。2.FAR:CS 、IP寄存器的內(nèi)容依次壓入堆棧中,用于程序與程序在不同段中。PUSH、POP又是一對(duì)指令用于將寄存器內(nèi)容壓入、彈出,用來(lái)保護(hù)寄存器數(shù)據(jù),子程序調(diào)用中運(yùn)用較多。堆棧指針有個(gè)“后進(jìn)先出”原則,像PUSH AX,PUSH BX…POP BX,POP AX這樣才能作到保護(hù)數(shù)據(jù)絲毫不差。

  匯編語(yǔ)言超濃縮教程到這要告一段落了,希望能奠定你獨(dú)立設(shè)計(jì)的基礎(chǔ)。而更多更好的技巧則全依賴你平時(shí)的積累了。祝你成功!



任我行 2006-02-20 16:17 發(fā)表評(píng)論
]]>
關(guān)于在8086/88內(nèi)存尋址方式http://www.shnenglu.com/oosky/archive/2006/02/20/3353.html任我行任我行Mon, 20 Feb 2006 08:15:00 GMThttp://www.shnenglu.com/oosky/archive/2006/02/20/3353.htmlhttp://www.shnenglu.com/oosky/comments/3353.htmlhttp://www.shnenglu.com/oosky/archive/2006/02/20/3353.html#Feedback0http://www.shnenglu.com/oosky/comments/commentRss/3353.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/3353.html 關(guān)于在8086/88內(nèi)存尋址方式

?Writer:HSLY
?Excerpt:80x86匯編小站 ?Preface:
在學(xué)匯編時(shí),很多初學(xué)者對(duì)PC的尋址方式和很不理解...... ?Content:

??? 在學(xué)匯編時(shí),很多初學(xué)者對(duì)PC的尋址方式和很不理解,甚至是很難理解。的確,這方面的知識(shí)是很抽象的,需要比較強(qiáng)的空間想象能力。尤其是我們?cè)谳斎胱址畷r(shí),那這些字符是如何進(jìn)行排列的呢?對(duì)于,這個(gè)問(wèn)題,我相信很多初學(xué)者也是很難想象是如何排列。但是,我可以這樣比喻:內(nèi)存就是有很多棟“樓房”,“樓房”又是由“單元號(hào)”,“門戶號(hào)”組成,那“樓房”就相當(dāng)于內(nèi)存地址的段地址,“單元號(hào)”就相當(dāng)于內(nèi)存的的 偏移地址,“門戶號(hào)(家)”就相當(dāng)于“變地址”,而每個(gè)單元有16個(gè)"門戶號(hào)(家)",又當(dāng)我們找到"門戶號(hào)(家)"后,走進(jìn)這個(gè)"門戶號(hào)(家)"就會(huì)見(jiàn)到里面會(huì)有"人",而我們所說(shuō)的人就是寄存器所指的"內(nèi)容"了,我畫(huà)個(gè)圖給你們看就會(huì)一目了然了。


用DEBUG的D命令得出這樣的效果:

 


|---------->0B1F就是"樓房"------>段地址
|
|???? |------>右邊的就是"單元號(hào)"--->偏移地址
|???? |
|???? |??????????? |-------->這部分就是"門戶號(hào)"----->變地址
|???? |????????? |<------------------------------------------>|
0B1F:0100 00 80 FF 02 75 05 C6 46-00 00 C3 E8 8C EB B4 3B
0B1F:0110 CD 21 72 39 8B FA 33 C0-8B C8 49 26 34 00 0E 0B
'
'
'
[省略]

看完這個(gè)圖之后,是不是就很明了呢?但是聰明的人就會(huì)有疑問(wèn),那我們?cè)趺醋哌M(jìn)"門戶號(hào)(家)"呢?問(wèn)得好,所以了為了可以走進(jìn)"門戶號(hào)(家)",就出現(xiàn)了一個(gè)叫做"尋址方式"的概念!說(shuō)白了,就是教你如何找到這個(gè)"門戶號(hào)(家)".呵呵!

好現(xiàn)在都明白了嗎?那你們就看看我是怎么理解PC的尋址方式(通俗易懂):
在這我就只介紹比較難理解的:

1:寄存器直接尋址:
你就想成:其實(shí)你已經(jīng)站在你要找的"門戶號(hào)(家)"面前了,直接敲門進(jìn)去就OK了!
例子: MOV AX,[2000H]
MOV AX,2000H -->2000H為存放操作數(shù)單元號(hào)的符號(hào)地址
上面兩者是不等效的

2:寄存器間接尋址方式:
你就想成:你已經(jīng)站在你要找的"門戶號(hào)(家)"的"單元號(hào)",你要找到它,必須知道它在當(dāng)前"單元號(hào)"幾樓.假如它在6樓,那你就上到6樓就OK了!!注意,最高只有16樓,因?yàn)槭裁茨?那就用DEBUG的D命令看看呀,慢慢數(shù)哦,呵呵!!
例子: MOV AX,[BX]

計(jì)算公式: 物理地址=16d*(DS)+(BX)
物理地址=16d*(DS)+(SI)
物理地址=16d*(DS)+(DI)
物理地址=16d*(SS)+(BP)

3:寄存器相對(duì)尋址方式:
你就想成:你要找的"門戶號(hào)(家)"其實(shí)就在你家的樓上或者樓下,你要找到它,就 必須知道它在你樓上幾樓,或者在樓下幾樓!就OK了!
例子: MOV AX,COUNT[SI]
MOV AX,[COUNT+SI]
其中 COUNT為位移量的符號(hào)地址


計(jì)算公式: 物理地址=16d*(DS)+(BX)+8位位移量
或+(SI) 或 16位位偏移量
或+(DI)


物理地址=16d*(SS)+(BP)+8位偏移量


4:基址變址尋址方式:
你就想成:你要找的"門戶號(hào)(家)"是跟住在同一棟樓的不同"單元號(hào)",你要找到它,就必須知道它是該棟的哪個(gè)"單元號(hào)",并且住在幾樓!那樣你就可以找到它了 !
例子: MOV AX,[BX][DI]
MOV AX,[BX+DI]

計(jì)算公式: 物理地址=16d*(DS)+(BX)+(SI)
或+(DI)
物理地址=16d*(SS)+(BP)+(SI)
或+(DI)


5:相對(duì)基址變址尋址方式:
你就想成:你就想成:你要找的"門戶號(hào)(家)"是跟住在同一棟樓的不同"單元號(hào)",它比你高幾層樓或者低幾層樓,然后用的你目前的樓數(shù)+/-就可以得出你要找的住在幾樓了!
例子: MOV,AX,MASK[BX][SI]
MOV,AX,MASK[BX+SI]
MOV,AX,[MASK+BX+SI]
以上三個(gè)例子是等效的!!

計(jì)算公式: 物理地址=16d*(DS)+(BX)+(SI)+8位位移量
或+(DI) 或 16位位偏移量
物理地址=16d*(SS)+(BP)+(SI)+8位位移量
或+(DI) 或 16位位偏移量
---------------------------------------------------------------------
呵呵,終于寫(xiě)完了這篇教程,好累哦!! 是不是覺(jué)得我的思維很另類呀,要?jiǎng)?chuàng)新呀!
書(shū)上太理論了,我就創(chuàng)新一個(gè),不知道你們看得懂嗎?
呵呵,反正你們不要
!@##)(#$*!@(@我就行了,我很努力寫(xiě)了!!!

下面,我舉個(gè)程序例子,讓你們加深印象!!!

----------------------------------------------------------------------
編程步驟:
1: 建立緩沖區(qū),為輸入字符串(最多能輸入9個(gè))
2: 取緩沖區(qū)的首地址,以便后面進(jìn)行"寄存器間接尋址方式"
3: 利用"寄存器間接尋址方式"取得實(shí)際輸入字符個(gè)數(shù),以便確認(rèn)循環(huán)次數(shù)
4: 利用"寄存器間接尋址方式"輸入字符串的最后一個(gè)字符
5: 利用LOOP指令和2號(hào)顯示功能來(lái)進(jìn)行倒著顯示
----------------------------------------------------------------------

;程序功能:任意輸入幾個(gè)字符(最多能輸入9個(gè)),按回車則倒著輸出!

data segment
user_string db 10,0,10 dup(?)
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
lea dx,user_string ;建立輸入字符串緩沖區(qū)
mov ah,0ah
int 21h
xor si,si
xor bx,bx
mov bx,dx
mov cx,[bx+si+1] ;看這個(gè)就是"寄存器間接尋址方式"
xor ch,ch ;其目的就是取實(shí)際輸入字符個(gè)數(shù)
mov di,cx
lop: mov ah,2
mov dx,[bx+di+1];看這又是"寄存器間接尋址方式"
int 21h ;其目的就是取輸入字符串的最后一個(gè)字符
dec di
loop lop ;依次循環(huán)倒著輸出字符
mov ah,4ch
int 21h
code ends
end start

-----------------------------------------------------------------------
完工了



任我行 2006-02-20 16:15 發(fā)表評(píng)論
]]>
常去的網(wǎng)址http://www.shnenglu.com/oosky/archive/2006/02/13/3232.html任我行任我行Mon, 13 Feb 2006 06:14:00 GMThttp://www.shnenglu.com/oosky/archive/2006/02/13/3232.htmlhttp://www.shnenglu.com/oosky/comments/3232.htmlhttp://www.shnenglu.com/oosky/archive/2006/02/13/3232.html#Feedback4http://www.shnenglu.com/oosky/comments/commentRss/3232.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/3232.htmlhttp://www.netyi.net/in.asp?id=oosky 書(shū)籍很多,但要你自己細(xì)細(xì)的尋找哦。
http://www.infoxa.com/ 這個(gè)網(wǎng)站不錯(cuò),推薦。很多經(jīng)典的圖書(shū)都能找到。
http://www.itebook.net/ 
http://www.itepub.net/ 這個(gè)站應(yīng)該很多人都知道的。

Linux免費(fèi)下載:
http://www.linuxeden.com/forum/t132533.html Mandriva Linux 2006 的光盤(pán)鏡像
http://public.planetmirror.com/pub/ 
http://www.linuxeden.com/download/1214.html fedora core linux
http://fedora.redhat.com/download/mirrors.html#ASIA  fedora core linux官方網(wǎng)
http://ftp.osuosl.org/pub/ 看了就知道了




貼這么多,等發(fā)現(xiàn)好的再貼出來(lái),大家也共享一下。


任我行 2006-02-13 14:14 發(fā)表評(píng)論
]]>
堆棧,堆棧,堆和棧的區(qū)別http://www.shnenglu.com/oosky/archive/2006/01/21/2958.html任我行任我行Sat, 21 Jan 2006 08:23:00 GMThttp://www.shnenglu.com/oosky/archive/2006/01/21/2958.htmlhttp://www.shnenglu.com/oosky/comments/2958.htmlhttp://www.shnenglu.com/oosky/archive/2006/01/21/2958.html#Feedback32http://www.shnenglu.com/oosky/comments/commentRss/2958.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/2958.html看完你就明白了。
  閱讀全文

任我行 2006-01-21 16:23 發(fā)表評(píng)論
]]>
#pragma 預(yù)處理指令詳解http://www.shnenglu.com/oosky/archive/2006/01/06/2464.html任我行任我行Fri, 06 Jan 2006 06:33:00 GMThttp://www.shnenglu.com/oosky/archive/2006/01/06/2464.htmlhttp://www.shnenglu.com/oosky/comments/2464.htmlhttp://www.shnenglu.com/oosky/archive/2006/01/06/2464.html#Feedback0http://www.shnenglu.com/oosky/comments/commentRss/2464.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/2464.html閱讀全文

任我行 2006-01-06 14:33 發(fā)表評(píng)論
]]>
驅(qū)動(dòng)開(kāi)程序發(fā)—安裝 http://www.shnenglu.com/oosky/archive/2006/01/03/2370.html任我行任我行Tue, 03 Jan 2006 02:11:00 GMThttp://www.shnenglu.com/oosky/archive/2006/01/03/2370.htmlhttp://www.shnenglu.com/oosky/comments/2370.htmlhttp://www.shnenglu.com/oosky/archive/2006/01/03/2370.html#Feedback4http://www.shnenglu.com/oosky/comments/commentRss/2370.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/2370.html作為一個(gè)完整的例子,你開(kāi)發(fā)出來(lái)驅(qū)動(dòng)還必須要能安裝。所以下面我講一下安裝。

如果前面的編譯過(guò)程沒(méi)有錯(cuò)誤的話,現(xiàn)在我們應(yīng)該已經(jīng)得到了一個(gè)HelloWDM.sys文件,假設(shè)它是放在D:\HelloWDM\objfre\i386中。

安裝WDM驅(qū)動(dòng)程序可以用兩種方法,一種是利用注冊(cè)表,還有一種是利用INF文件。我們一般是采用INF文件(這是微軟推薦的)。INF文件可以在 WINNT\INF 目錄中找到很多。為了順利安裝,我在這里先給出 HelloWDM 所需要的 HelloWDM.INF 文件:

;; The Win2K DDK documentation contains an excellent INF reference.

;--------- Version Section ---------------------------------------------------

[Version]
Signature="$CHICAGO$"
Provider=LC_Device
DriverVer=8/21/2002,3.0.0.3

; If device fits one of the standard classes, use the name and GUID here,
; otherwise create your own device class and GUID as this example shows.

Class=Unknown
ClassGUID={ff646f80-8def-11d2-9449-00105a075f6b}

;--------- SourceDiskNames and SourceDiskFiles Section -----------------------

; These sections identify source disks and files for installation. They are
; shown here as an example, but commented out.

[SourceDisksNames]
1 = "HelloWDM",Disk1,,

[SourceDisksFiles]
HelloWDM.sys = 1,objfre\i386,

;--------- ClassInstall/ClassInstall32 Section -------------------------------

; Not necessary if using a standard class

; 9X Style
[ClassInstall]
Addreg=Class_AddReg

; NT Style
[ClassInstall32]
Addreg=Class_AddReg

[Class_AddReg]
HKR,,,,%DeviceClassName%
HKR,,Icon,,"-5"

;--------- DestinationDirs Section -------------------------------------------

[DestinationDirs]
YouMark_Files_Driver = 10,System32\Drivers

;--------- Manufacturer and Models Sections ----------------------------------

[Manufacturer]
%MfgName%=Mfg0

[Mfg0]

; PCI hardware Ids use the form
; PCI\VEN_aaaa&DEV_bbbb&SUBSYS_cccccccc&REV_dd
;改成你自己的ID
%DeviceDesc%=YouMark_DDI, PCI\VEN_9999&DEV_9999

;---------- DDInstall Sections -----------------------------------------------
; --------- Windows 9X -----------------

; Experimentation has shown that DDInstall root names greater than 19 characters
; cause problems in Windows 98

[YouMark_DDI]
CopyFiles=YouMark_Files_Driver
AddReg=YouMark_9X_AddReg

[YouMark_9X_AddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,HelloWDM.sys
HKR, "Parameters", "BreakOnEntry", 0x00010001, 0

; --------- Windows NT -----------------

[YouMark_DDI.NT]
CopyFiles=YouMark_Files_Driver
AddReg=YouMark_NT_AddReg

[YouMark_DDI.NT.Services]
Addservice = HelloWDM, 0x00000002, YouMark_AddService

[YouMark_AddService]
DisplayName = %SvcDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %10%\System32\Drivers\HelloWDM.sys

[YouMark_NT_AddReg]
HKLM, "System\CurrentControlSet\Services\HelloWDM\Parameters",\
"BreakOnEntry", 0x00010001, 0


; --------- Files (common) -------------

[YouMark_Files_Driver]
HelloWDM.sys

;--------- Strings Section ---------------------------------------------------

[Strings]
ProviderName="Flying L Co.,Ltd."
MfgName="LC Soft"
DeviceDesc="Hello World WDM!"
DeviceClassName="LC_Device"
SvcDesc="???"



注意它可以同時(shí)在Win98或者Win2000中使用(系統(tǒng)會(huì)通過(guò)這個(gè)INF文件里面的字段名稱,自動(dòng)選擇適合當(dāng)前系統(tǒng)的安裝方法的)。關(guān)于INF文件的各個(gè)字段含義現(xiàn)在我也不知道,所以也沒(méi)有辦法說(shuō)清楚,如果誰(shuí)看到這篇文章,而又知道的話,不妨為我一份。

準(zhǔn)備好這個(gè) HelloWDM.INF 文件后,讓我們打開(kāi)控制面板,雙擊“添加/刪除硬件”,選擇“添加/排除設(shè)備故障”->“添加新設(shè)備”->“否,我想從列表選擇硬件”->“其它設(shè)備”->“從磁盤(pán)安裝”,選擇 HelloWDM.INF 所在的路徑,然后安裝。

當(dāng)安裝完成后,系統(tǒng)就會(huì)添加上你寫(xiě)好的驅(qū)動(dòng)程序了。(可以在“設(shè)備管理器”中查看到)。然后重啟電腦,這個(gè)驅(qū)動(dòng)程序就投入使用啦。

關(guān)于安裝,我也只知道這么多,到底安裝驅(qū)動(dòng)程序時(shí),操作系統(tǒng)都作了些什么,我也不是很清楚,等我弄明白了我再貼上。



任我行 2006-01-03 10:11 發(fā)表評(píng)論
]]>
驅(qū)動(dòng)程序開(kāi)發(fā)—編譯正傳 http://www.shnenglu.com/oosky/archive/2006/01/03/2369.html任我行任我行Tue, 03 Jan 2006 02:10:00 GMThttp://www.shnenglu.com/oosky/archive/2006/01/03/2369.htmlhttp://www.shnenglu.com/oosky/comments/2369.htmlhttp://www.shnenglu.com/oosky/archive/2006/01/03/2369.html#Feedback0http://www.shnenglu.com/oosky/comments/commentRss/2369.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/2369.html我在前面也講過(guò)了一些關(guān)于編譯環(huán)境及工具的。在這里結(jié)合本例子我再說(shuō)一下:

DDK分為98 DDK和2000 DDK兩種,它們工作起來(lái)是大同小異的,不過(guò)有些驅(qū)動(dòng)程序只能在2000 DDK中使用。由于Win98注定是一種即將被淘汰的操作系統(tǒng)了,所以我學(xué)習(xí)的時(shí)候也沒(méi)有過(guò)多的關(guān)注,我用的是2000的DDK,所以以下的所有內(nèi)容都是針對(duì)2000 DDK的。

·準(zhǔn)備工作
1、確定你已經(jīng)安裝了Visual C++
2、安裝2000 DDK
3、安裝2000 DDK成功后,在“開(kāi)始”->“程序”里應(yīng)該有“Development Kits”->“Windows 2000 DDK”的項(xiàng)目。
注意一定要先安裝好VC,然后才安裝DDK,這個(gè)順序決不能顛倒!!
4、保證DDKROOT環(huán)境變量設(shè)置為Windows 2000 DDK的基目錄,如果不是的話,請(qǐng)?jiān)诳刂泼姘濉?B>系統(tǒng)”屬性的“高級(jí)”標(biāo)簽環(huán)境變量編輯器中設(shè)置好這個(gè)環(huán)境變量。


·編寫(xiě)必需的文件
編譯WDM程序的時(shí)候,有兩個(gè)文件是必須要有的,它們是:
1、makefile
(這個(gè)是什么啊?你可能會(huì)問(wèn)。)對(duì)于比較年輕的程序員來(lái)說(shuō),有可能沒(méi)有見(jiàn)過(guò)這個(gè)文件吧。其實(shí)在VC這些IDE出現(xiàn)之前,我們都必須使用makefile來(lái)確定項(xiàng)目中哪些文件需要重新編譯,現(xiàn)在的IDE都把這個(gè)工作自動(dòng)做好了
我們要做的工作很簡(jiǎn)單,就是提供這樣一個(gè)文件,它的內(nèi)容是:

#
# DO NOT EDIT THIS FILE!!!  Edit .\sources. If you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#

!INCLUDE $(NTMAKEENV)\makefile.def


正如它所述,不要編輯這個(gè)文件。事實(shí)上每個(gè)WDM程序所需要的makefile的內(nèi)容都是一樣的,也就是說(shuō),我們只需要簡(jiǎn)單地copy一個(gè)makefile到新的項(xiàng)目中就可以了
2、Sources

TARGETNAME=HelloWDM //編譯出來(lái)的驅(qū)動(dòng)程序的名稱
TARGETTYPE=DRIVER      //編譯的類型是驅(qū)動(dòng)程序編譯
DRIVERTYPE=WDM           //驅(qū)動(dòng)程序的類型是WDM驅(qū)動(dòng)程序
TARGETPATH=OBJ             //生成的文件存放在OBJ目錄中

INCLUDES=$(BASEDIR)\inc;\   //這是需要引入的頭文件
         $(BASEDIR)\inc\ddk;\

TARGETLIBS=$(BASEDIR)\lib\*\free\usbd.lib\  //這是需要引入的庫(kù)文件

SOURCES=HelloWDM.cpp\    //這是源碼文件


這個(gè)文件指定了驅(qū)動(dòng)程序目標(biāo)名是HelloWDM.sys,是一個(gè)WDM驅(qū)動(dòng)程序,生成的文件存放在OBJ目錄中。值得注意的是,“=”前后不能有空格,否則編譯的時(shí)候會(huì)出錯(cuò)。


·開(kāi)始編譯
娃哈哈,前面羅羅嗦嗦講了一大堆,現(xiàn)在終于到重點(diǎn)了。WDM程序的編譯過(guò)程比較特殊,它不是在VC里面按F7來(lái)編譯的(盡管你可以通過(guò)設(shè)置來(lái)達(dá)到這一目的),而是通過(guò)一個(gè)DDK實(shí)用工具build來(lái)完成。下面我們來(lái)講講具體步驟:
1、“Debug”版的生成
首先,我們假設(shè)你的源代碼放在D:\HelloWDM里面。請(qǐng)跟著以下步驟:

“開(kāi)始”->“程序”->“Development Kits”->“Windows 2000 DDK”->“Checked Build Environment”

屏幕將顯示:(有“回車”的那行是需要讀者你親自打進(jìn)去的)

New or updated MSVC detected.  Updating DDK environment….

Setting environment for using Microsoft Visual C++ tools.
Starting dirs creation…Completed.

D:\NTDDK>cd\HelloWDM    (回車)

D:\HelloWDM>build    (回車)


如果源代碼沒(méi)有錯(cuò)誤的話,生成的HelloWDM.sys將存放在objchk\i386目錄中。

2、“Release”版的生成
請(qǐng)跟著以下步驟:

“開(kāi)始”->“程序”->“Development Kits”->“Windows 2000 DDK”->“Free Build Environment”

隨后的步驟跟“Debug”版相同,不同的是生成的HelloWDM.sys將存放在objfre\i386目錄中。

任我行 2006-01-03 10:10 發(fā)表評(píng)論
]]>
驅(qū)動(dòng)程序開(kāi)發(fā)—編譯前傳http://www.shnenglu.com/oosky/archive/2006/01/03/2368.html任我行任我行Tue, 03 Jan 2006 02:08:00 GMThttp://www.shnenglu.com/oosky/archive/2006/01/03/2368.htmlhttp://www.shnenglu.com/oosky/comments/2368.htmlhttp://www.shnenglu.com/oosky/archive/2006/01/03/2368.html#Feedback0http://www.shnenglu.com/oosky/comments/commentRss/2368.htmlhttp://www.shnenglu.com/oosky/services/trackbacks/2368.html好啦,辛辛苦苦終于寫(xiě)完了程序,讓我們編譯運(yùn)行吧!按下Ctrl+F5(嘿嘿,讓我們先假設(shè)你習(xí)慣用VC來(lái)寫(xiě)程序),我等啊等……疑?怎么毫無(wú)動(dòng)靜的?再看看Output窗口,哇!有幾百個(gè)錯(cuò)誤啊!!不禁頭大——這是怎么回事呢?

原來(lái),WDM程序編譯出來(lái)的并不是我們常見(jiàn)的.exe,而是.sys文件,在未經(jīng)設(shè)置編譯環(huán)境之前,是不能直接用VC來(lái)編譯的(這就是為什么會(huì)有幾百個(gè)錯(cuò)誤了)。這種類型的文件你可以在WINNT\System32\Drivers里面找到很多。其實(shí)驅(qū)動(dòng)程序也是一種PE文件,它同樣由DOS MZ header開(kāi)頭,也有完整的DOS stub和PE header,同樣擁有Import table和Export table——……那跟普通的PE文件有什么不一樣呢?那么就讓我們先來(lái)做個(gè)小剖析,加深對(duì).sys文件的認(rèn)識(shí)吧


首先祭出Delphi里附帶的tdump.exe程序。讓我們鍵入:
C:\WINNT\System32\Drivers>tdump ccport.sys -em -ee
參數(shù)-em是列出Import table,-ee是列出Export table。回車之后,屏幕列出一大堆東西:

C:\WINNT\SYSTEM32\DRIVERS>tdump ccport.sys -em -ee
Turbo Dump  Version 5.0.16.12 Copyright ? 1988, 2000 Inprise Corporation
                    Display of File CCPORT.SYS

IMPORT:     NTOSKRNL.EXE={hint:011Fh}.’memcpy’
IMPORT:     NTOSKRNL.EXE={hint:003Dh}.’IoDeleteDevice’
IMPORT:     NTOSKRNL.EXE={hint:0030h}.’IoAttachDeviceToDeviceStack’
IMPORT:     NTOSKRNL.EXE={hint:008Eh}.’KeSetEvent’
IMPORT:     NTOSKRNL.EXE={hint:0068h}.’IofCallDriver’
IMPORT:     NTOSKRNL.EXE={hint:0095h}.’KeWaitForSingleObject’
IMPORT:     NTOSKRNL.EXE={hint:0074h}.’KeInitializeEvent’
IMPORT:     NTOSKRNL.EXE={hint:003Fh}.’IoDetachDevice’
IMPORT:     NTOSKRNL.EXE={hint:00D3h}.’RtlFreeUnicodeString’
IMPORT:     NTOSKRNL.EXE={hint:0077h}.’KeInitializeSpinLock’
IMPORT:     NTOSKRNL.EXE={hint:0129h}.’strcpy’
IMPORT:     NTOSKRNL.EXE={hint:0121h}.’memset’
IMPORT:     NTOSKRNL.EXE={hint:003Ch}.’IoCreateUnprotectedSymbolicLink’
IMPORT:     NTOSKRNL.EXE={hint:0038h}.’IoCreateDevice’
IMPORT:     NTOSKRNL.EXE={hint:00C2h}.’RtlAnsiStringToUnicodeString’
IMPORT:     NTOSKRNL.EXE={hint:0069h}.’IofCompleteRequest’
IMPORT:     NTOSKRNL.EXE={hint:0124h}.’sprintf’
IMPORT:     NTOSKRNL.EXE={hint:003Eh}.’IoDeleteSymbolicLink’
IMPORT:     NTOSKRNL.EXE={hint:0042h}.’IoFreeIrp’
IMPORT:     NTOSKRNL.EXE={hint:004Dh}.’IoInitializeIrp’
IMPORT:     NTOSKRNL.EXE={hint:002Dh}.’IoAllocateIrp’
IMPORT:     NTOSKRNL.EXE={hint:0027h}.’InterlockedExchange’
IMPORT:     NTOSKRNL.EXE={hint:0025h}.’InterlockedCompareExchange’
IMPORT:     NTOSKRNL.EXE={hint:0035h}.’IoCancelIrp’
IMPORT:     NTOSKRNL.EXE={hint:012Ah}.’strlen’
IMPORT:     NTOSKRNL.EXE={hint:0126h}.’strcat’
IMPORT:     NTOSKRNL.EXE={hint:0114h}.’atoi’
IMPORT:     NTOSKRNL.EXE={hint:0128h}.’strcmp’
IMPORT:     NTOSKRNL.EXE={hint:0034h}.’IoBuildSynchronousFsdRequest’
IMPORT:     NTOSKRNL.EXE={hint:00D5h}.’RtlInitAnsiString’
IMPORT:          HAL.DLL={hint:0006h}.’KfAcquireSpinLock’
IMPORT:          HAL.DLL={hint:0009h}.’KfReleaseSpinLock’

EXPORT ord:0001=’Vcomm_DriverControl’



看到了嗎?它主要調(diào)用了NTOSKRNL.EXE和HAL.DLL文件(實(shí)際上你會(huì)發(fā)現(xiàn),幾乎所有的WDM驅(qū)動(dòng)程序都會(huì)調(diào)用NTOSKRNL.EXE文件,從它的名字你可以看出為什么了吧?),并且輸出了一個(gè)函數(shù)“Vcomm_DriverControl”。這表明,其實(shí).sys跟.exe文件一樣,都是一種PE文件來(lái)的。不同的是,.sys文件Import的通常是NTOSKRNL.EXE,而.exe文件Import的通常是KERNEL32.DLL和USER32.DLL。

知道了這些有什么用呢?實(shí)際上,由于.sys通常不調(diào)用KERNEL32.DLL和USER32.DLL,所以你是不能在設(shè)備驅(qū)動(dòng)程序里面調(diào)用任何C、C++和Win32函數(shù)的,而且也不能用C++關(guān)鍵字new和delete等(可以用malloc和free來(lái)代替),而必須使用大量的內(nèi)核函數(shù)。另外,你應(yīng)該也能看到她調(diào)用了像IoDeleteDevice、IoAttachDeviceToDeviceStack等等函數(shù),這些你以前可能沒(méi)有見(jiàn)過(guò)的函數(shù)都是些內(nèi)核函數(shù)。為了讀者的方便,下面我列出一些常見(jiàn)的驅(qū)動(dòng)程序可用的內(nèi)核函數(shù):

Ex…        執(zhí)行支持
Hal…        硬件抽象層(僅NT/Windows 2000)
Io…        I/O管理器(包括即插即用函數(shù))
Ke…        內(nèi)核
Ks…        內(nèi)核流IRP管理函數(shù)
Mm…        內(nèi)存管理器
Ob…        對(duì)象管理器
Po…        電源管理
Ps…        進(jìn)程結(jié)構(gòu)
Rtl…        運(yùn)行時(shí)庫(kù)
Se…        安全引用監(jiān)視
Zw…        其他函數(shù)


最后讓我們?cè)賮?lái)看看,寫(xiě)設(shè)備驅(qū)動(dòng)程序時(shí)必須注意的一些問(wèn)題:

1、內(nèi)核宏
如果查看DDK頭文件,會(huì)發(fā)現(xiàn)有幾個(gè)內(nèi)核函數(shù)是以宏的方式實(shí)現(xiàn)的。這種宏中有幾個(gè)宏的定義是相當(dāng)糟糕的。例如,我們看到RemoveHeadList的定義如下:

#define RemoveHeadList(ListHead)
        (ListHead)->Flink;
        {RemoveEntryList((ListHead)->Flink)}


如果以以下方式調(diào)用RemoveHeadList,則將編譯錯(cuò)誤的代碼:

if(SomethingInList)
        Entry = RemoveHeadList(list);


使這個(gè)調(diào)用安全的唯一方法是使用花括號(hào):

if(SomethingInList)
    {
        Entry = RemoveHeadList(list);
    }


所以我們切勿為了貪圖一時(shí)的方便,而使用不太規(guī)范的寫(xiě)法,最好是在所有的if、for和while等語(yǔ)句中使用花括號(hào)。

2、驅(qū)動(dòng)程序函數(shù)名稱
跟C/C++的main()函數(shù)一樣,設(shè)備驅(qū)動(dòng)程序也有一個(gè)必須存在,而且只能以DriverEntry()為名稱的入口函數(shù)。然而,除此之外,我們可以使用任何名字來(lái)給其他函數(shù)命名——只要你自己記得就行了,當(dāng)然,最好符合某些特定的規(guī)范啦,例如匈牙利命名法……

3、安裝時(shí)的問(wèn)題
·在Windows98中驅(qū)動(dòng)程序可執(zhí)行文件必須是8.3文件名。(別問(wèn)我為什么,我也不知道,我只能建議你去問(wèn)比爾該死)
·如果INF文件中含有非法節(jié)的詳細(xì)資料,Windows將不使用這個(gè)INF文件。

本節(jié)羅羅嗦嗦講了一大堆,跟實(shí)際的編程卻并沒(méi)有太大的關(guān)系,前傳嘛!就是這樣的啦!



任我行 2006-01-03 10:08 發(fā)表評(píng)論
]]>
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产自产2019最新不卡| 亚洲调教视频在线观看| 一区二区日韩伦理片| 欧美一二三视频| 麻豆成人91精品二区三区| 亚洲欧洲精品一区二区三区波多野1战4| 99在线精品视频| 久久国内精品视频| 欧美日韩国产区一| 黑人巨大精品欧美黑白配亚洲| 亚洲免费久久| 欧美影院午夜播放| 亚洲欧洲偷拍精品| 欧美综合二区| 欧美色精品在线视频| 激情一区二区三区| 亚洲影院在线观看| 欧美高清你懂得| 亚洲一区高清| 欧美电影在线播放| 国产亚洲一区二区精品| 在线中文字幕一区| 狂野欧美激情性xxxx欧美| 一区二区三区回区在观看免费视频| 久久精品一级爱片| 国产精品久久久久999| 亚洲激情在线激情| 久久se精品一区二区| 日韩视频在线观看免费| 久久综合久久综合久久| 国产精品亚洲不卡a| 99综合视频| 欧美成人四级电影| 香蕉免费一区二区三区在线观看| 欧美日韩国产综合久久| 亚洲动漫精品| 久久精品国产综合| 亚洲午夜精品一区二区| 欧美日韩高清免费| 亚洲国产一区二区三区高清| 久久精品夜夜夜夜久久| 一区二区日本视频| 欧美久色视频| 91久久精品一区二区别| 久久亚洲综合网| 亚洲女性裸体视频| 欧美性久久久| 一区二区精品在线| 亚洲国产高清一区二区三区| 久久男人资源视频| 国产主播精品| 久久九九免费| 午夜精品影院| 国产欧美日韩精品a在线观看| 亚洲视屏一区| 日韩网站免费观看| 欧美日本亚洲| 一区二区av| 亚洲日本在线观看| 欧美高清在线一区| 亚洲精品乱码久久久久久按摩观| 欧美99久久| 狂野欧美一区| 136国产福利精品导航| 老牛国产精品一区的观看方式| 欧美一区二区视频免费观看| 国产无一区二区| 久久精品久久综合| 欧美在线观看视频在线| 国产视频在线一区二区| 久久精品国产精品 | 亚洲国产精品精华液2区45| 久久伊人免费视频| 亚洲国产精品成人| 欧美激情一区三区| 欧美福利视频网站| 日韩亚洲欧美一区二区三区| 亚洲精品日韩久久| 欧美午夜一区二区福利视频| 亚洲欧美伊人| 午夜精品视频一区| 激情另类综合| 亚洲电影免费观看高清| 欧美精品日韩一区| 亚洲一区二区三区免费在线观看| 宅男精品导航| 国产日韩欧美在线观看| 另类天堂av| 欧美mv日韩mv国产网站| 一区二区三区高清在线| 亚洲自拍偷拍福利| 国产在线国偷精品产拍免费yy| 老司机午夜精品视频在线观看| 欧美69wwwcom| 亚洲深夜福利| 午夜视频精品| 亚洲高清不卡在线| 99精品国产一区二区青青牛奶| 国产精品久久久久久久电影| 久久九九电影| 欧美成人免费在线观看| 亚洲一级网站| 久久国产精品久久精品国产| 亚洲精品久久久久久久久久久| 一区二区激情| 很黄很黄激情成人| 亚洲精品久久7777| 国产欧亚日韩视频| 亚洲电影免费观看高清完整版在线| 欧美日韩在线不卡| 久久综合九色综合欧美狠狠| 欧美精品v国产精品v日韩精品| 欧美一级片一区| 免费看成人av| 欧美一区二区在线观看| 美腿丝袜亚洲色图| 亚洲欧美激情在线视频| 久久免费一区| 亚洲综合色自拍一区| 久久久一本精品99久久精品66| 亚洲天堂成人在线观看| 久久久欧美一区二区| 亚洲一区美女视频在线观看免费| 久久精品在线| 亚洲在线免费| 蜜臀av国产精品久久久久| 性欧美超级视频| 欧美顶级艳妇交换群宴| 久久国产精品第一页| 欧美精品导航| 久久香蕉国产线看观看av| 欧美日韩中文在线观看| 欧美成人午夜免费视在线看片 | 国产精品日日做人人爱| 欧美丰满高潮xxxx喷水动漫| 国产精品久线观看视频| 亚洲高清在线| 国内成+人亚洲| 亚洲私人影院在线观看| 日韩视频一区二区三区在线播放免费观看 | 在线观看欧美亚洲| 亚洲欧美在线一区二区| 一区二区三区.www| 免费不卡视频| 久久青草久久| 国产精品在线看| 亚洲免费福利视频| 亚洲精品国产系列| 久久xxxx精品视频| 欧美一区激情视频在线观看| 欧美日韩国产在线播放| 亚洲高清在线观看一区| 精品不卡视频| 午夜精品久久久久99热蜜桃导演| 亚洲午夜激情在线| 欧美精品一区二| 欧美激情导航| 亚洲高清久久久| 久久精品一区二区国产| 久久久久久高潮国产精品视| 国产伦精品一区| 亚洲天堂网在线观看| 亚洲一区二区欧美日韩| 欧美人妖在线观看| 亚洲激情在线观看| 最新国产乱人伦偷精品免费网站| 久久亚洲电影| 麻豆精品在线视频| 一区二区视频欧美| 久久九九精品| 久久综合伊人| 伊人天天综合| 久久尤物电影视频在线观看| 老牛嫩草一区二区三区日本| 黄色成人91| 久久日韩粉嫩一区二区三区| 美女91精品| 亚洲国产欧美不卡在线观看| 久久米奇亚洲| 你懂的成人av| 亚洲激情另类| 欧美激情精品久久久久久黑人| 亚洲高清三级视频| 日韩一二三在线视频播| 欧美日韩一本到| 一本色道久久综合亚洲精品小说| 亚洲天天影视| 国产精品午夜电影| 欧美一区二区大片| 麻豆精品传媒视频| 亚洲国产一区在线| 欧美日本不卡高清| 中日韩美女免费视频网址在线观看| 亚洲一区二区三区在线视频| 国产精品久久影院| 欧美一级久久久久久久大片| 久久人人精品| 亚洲激情欧美| 欧美日韩亚洲一区二区三区在线观看| 99精品热视频|