C語言編程技巧_第1頁
C語言編程技巧_第2頁
C語言編程技巧_第3頁
已閱讀5頁,還剩21頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、函數包含類別功能_atoldmath.h數學子程序把字符串轉換為浮點數beginthreadprocess.h進程控制子程序啟動執(zhí)行一個新線程bios diskbios.h接口子程序輸出 BIOS 磁盤驅動器服務bios equiplistbios.h接口子程序檢查設備bios keybrdbios.h接口子程序直接使用 BIOS 的鍵盤接口bios memsizebiosd.h存儲子程序返回內存大小bios printerbios.h接口子程序直接調用 BIOS 服務進行打印機 I/Obios timeofdaybios.h時間和日期子程序讀取或設置 BIOS 時鐘_biosserialco

2、mbios.h接口子程序進行串行 I/O_c_exitprocess.h進程控制子程序不終止程序執(zhí)行如同 _exit 的清除_cexitprocess.h進程控制子程序不終止程序執(zhí)行如同 _exit 的清除chdrivedirect.h目錄控制子程序設置當前驅動器chian intrdos.h接口子程序chmodeio.h輸入輸出子程序改變文件的存取權限_clear87float.h數學子程序清除浮點狀態(tài)字_closeio.h輸入輸出子程序關閉文件( 3。 1)以下版本control87float.h數學子程序處理浮點控制字creatio.h輸入輸出子程序創(chuàng)建一個新文件或重寫一個已存在的文件d

3、isabledos.h接口子程序屏蔽中斷_dos_allocmemdos.h存儲子程序_dos_closedos.h輸入輸出子程序關閉一個文件dos craetedos.h輸入輸出子程序創(chuàng)建一個新文件或重寫一個已存在的文件_dos_createnewdos.h輸入輸出子程序創(chuàng)建一個新文件dos findfirstdos.h目錄控制子程序搜索一個磁盤目錄_dos_findnextdos.h目錄控制子程序繼續(xù) _dos_findfirst 的搜索_dos_freememdos.h存儲子程序_dos_getdatedos.h時間和日期子程序取得和設置系統(tǒng)日期dos getdiskfredos.h目錄

4、控制子程序取得磁盤空閑空間dos getdrivedos.h目錄控制子程序取得和設置當前驅動器號dos getfileattdos.h輸入輸出子程序取得和設置文件屬性dos getftimedos.h輸入輸出子程序取得和設置文件日期和時間_dos_gettimedos.h時間和日期子程序取得和設置系統(tǒng)時間_dos_getvectdos.h接口子程序取得中斷向量_dos_keepdos.h接口子程序dos opendos.h輸入輸出子程序打開一個文件用于讀和寫_dos_readdos.h輸入輸出子程序從文件讀_dos_setblockdos.h存儲子程序_dos_setdatedos.h時間和日

5、期子程序設置系統(tǒng)日期dos setdrivedos.h目錄控制子程序設置當前驅動器號dos setfileattdos.h輸入輸出子程序設置文件屬性_dos_setfitmedos.h_dos_settimedos.h_dos_setvectdos.h_dos_writedos.h_enabledos.h輸入輸出子程序 設置文件時間 時間和日期子程序 設置系統(tǒng)時間exitfpresent _fsopen _fullpath_getdcwd_graphfreemem _graphgetmem _harderr _hardresumeprocess.h float.h stdio.h stdlib

6、.h direct.h direct.hgraphics.h graphics.h dos.h dos.h_hardretn dos.h _heapaddalloc.h_heapminmalloc.h_hea 視頻教程 '>pset 塊接口子程序輸入輸出子程序 接口子程序進程控制子程序 數學子程序輸入輸出子程序 目錄控制子程序目錄控制子程序 目錄控制子程序圖形子程序 圖形子程序 接口子程序 接口子程序接口子程序malloc.h設置中斷向量寫向文件開硬件中斷終止程序重新初始化浮點數學包把相對路徑名轉換為絕對路徑名取得指定驅動器的當前目錄取得當前驅動器號可修改的圖形內存釋放函數可修改

7、的圖形內存分配函數建立一個硬件錯誤處理程序硬件錯誤處理函數硬件錯誤處理函數添加一個塊到堆上釋放無用的堆區(qū)域 用一個常量值填充堆上的自由_initEasyWin lrotl lrotr_makeepath matherrl matherrl open OvrInitEms OvrInitExt pclose_popen _read rotl rotl rotr searchstr setcursortype setcursortype setcursortype _splitpath _status87 _strdate _strerror _strtimeio.h初始化 Ease window

8、sstdlib.h數學子程序將無符號長整型數向左循環(huán)移位stdlib.h數學子程序將無符號長整型數向右循環(huán)移位stdlib.h目錄控制子程序生成一個路徑math.h診斷子程序用戶可修改的數學錯誤處理程序math.h數學子程序用戶可修改的數學錯誤處理程序io.h輸入輸出子程序打開一個文件進行讀和寫dos.h初始化復蓋治理程序用于交換 EMS 內存dos.h初始化復蓋治理程序用于交換 EXT 內存stdio.h等待一個管道命令結束stdio.h創(chuàng)建一個子命令處理程序管道io.h輸入輸出子程序讀文件( 3。1 以下版本)stdlib.h嵌入子程序將一個無符號整數左循環(huán)移位stdlib.h數學子程序把

9、一個無符號整數左循環(huán)移位stdlib.h嵌入子程序將一個無符號整數向左循環(huán)移位stdlib.h為某文件查找某些目錄graphics.h圖形子程序選擇光標類型conio.h輸入輸出子程序選擇光標類型conio.h文本窗口顯示子程選擇光標類型stdlib.h目錄控制子程序將一個全限定的路徑名分解各個成份float.h數學子程序取浮點狀態(tài)stdlib.h轉換子程序把當前日期轉換成字符串string.h stdio輸入輸出子程序建立用戶定義的錯誤信息stdlib.h轉換子程序轉換當前日期為字符串_strtoldstdlib.h轉換子程序_strtoldstdlib.h數學子程序tolowerctype

10、.h轉換子程序把字符轉換成小寫字母_writeio.h輸入輸出子程序寫文件abortprocess.h進程控制子程序異常終止一進程absstdlib.h compl數學子程序返回整數的絕對值abslmath.h數學子程序計算復數的模absreaddos.h接口子程序讀磁盤的絕對扇區(qū)abswritedos.h接口子程序寫磁盤的絕對扇區(qū)accessio.h輸入輸出子程序確定文件的存取權限acosmath.h complex數學子程序計算反余弦值acoslmath.h數學子程序計算反余弦值allocamalloc.h存儲子程序分配臨時堆??臻gallocmdos.h存儲子程序分配 DOS 內存arcg

11、raphics.h圖形子程序畫園弧argcomplex.h數學子程序求復平面中一個復數的弧度asctimetime.h時間和日期子程序 轉換日期和時間為對應的asinmath.h complex數學子程序反正弦函數asinlmath.h數學子程序反正弦函數assertassert.h診斷子程序條件終止函數atan2math.h complex數學子程序計算 y/x 的反正切值atan2lmath.h數學子程序計算 y/x 的反正切值atofstdlib.h轉換子程序將字符串轉換為浮點數at ofmath.h stdlib.數學子程序將字符串轉換成浮點數atoistdlib.h轉換子程序將字符串

12、轉換為整數atoistdlib.h數學子程序把字符串轉換成整型數atolstdlib.h轉換子程序將字銜串轉換成長整型數atolstdlib.h數學子程序抬字符串轉換為長整型bargraphics.h圖形子程序畫二維條形圖bar3dgraphics.h圖形子程序畫一個三維條形圖bcdbcd.h數學子程序把一個數轉換為相對應的bdosdos.h接口子程序DOS 系統(tǒng)調用bdosptrdos.h接口子程序DOS 系統(tǒng)調用bioscombios.h接口子程序I/O 通訊biosdiskbios.h接口子程序調用 BIOS 磁盤驅動程序bioseqiplistbios.h接口子程序檢查設備bioske

13、ybios.h接口子程序調用 BIOS 的鍵盤接口biosmemorybios.h接口子程序返加內存的大小biosprintfbios.h接口子程序調用 BIOS 的打印 I/O 接口biostimebios.h接口子程序讀取或設置 BIOS 時鐘brkalloc.h存儲子程序改變數據段內存分配cabsmath.h數學子程序計算復數的模callocalloc.h stdlib存儲子程序分配內存ceilmath.h數學子程序舍入ASCII 碼BCD 碼ceillmath.h數學子程序舍入cgetsconio.h輸入輸出子程序讀字符串chdirdir.h目錄控制子程序改變當前目錄chmodio.h

14、輸入輸出子程序改變文件存取權限chsizeio.h輸入輸出子程序修改文件長度circlegraphics.h圖形子程序畫園cleardevicegraphics.h圖形子程序清圖形屏幕clearerrio.h輸入輸出子程序復位錯誤標志clearviewportgraphics.h圖形子程序清除當前圖形窗口closeio.h輸入輸出子程序關閉文件closedirdirect.h目錄控制子程序關閉目錄流closegraphgraphics.h圖形子程序關閉圖形系統(tǒng)clreolconio.h文本窗口顯示子程清除從當前光標位置到行尾的字符clrscrconio.h文本窗口顯示子程清除文本窗口,并把光標

15、放在左上角complexcomplex.h數學子程序創(chuàng)建復數conjcomplex.h數學子程序求復數的共軛復數coreleftalloc.h stdlib存儲子程序 返順未使用的內存大小cosmath.h complex 數學子程序計算余弦值coshmath.h complex 數學子程序計算雙曲余弦值coshlmath.h數學子程序計算雙曲余弦值coslmath.h數學子程序計算余弦值countrydos.h接口子程序讀取與特定國家有關的格式cprintfconio.h輸入輸出子程序格式化并輸出數據到屏幕cputsconio.h輸入輸出子程序輸出一字符串到屏幕creatio.h輸入輸出子程

16、序創(chuàng)建一個新文件或重寫一個已存在的文件creatnewio.h輸入輸出子程序創(chuàng)建新文件creattempio.h輸入輸出子程序創(chuàng)建一個文件名唯一的文件cscanfconio.h輸入輸出子程序從控制臺執(zhí)行格式化輸入ctimetime.h時間和日期子程序把日期和時間轉化為對應的字符串ctrlbrkdos.h接口子程序設置 CTRL-BREAK 處理程序delaydos.h雜類子程序暫停 DOSdellineconio.h文本窗口顯示子程在文本窗口中刪去一行detectgraphgraphics.h圖形子程序檢測硬件并確定使用何種圖形驅運程序和圖形difftimetime.h時間和日期子程序計算二個

17、時刻的時間差disabledos.h接口子程序屏蔽中斷css.shtml' target'_blank' title ='div 視頻教程 '>divmath.h 數學子程序將二個整數相除,返回商和余數dosexterrdos.h接口子程序獲取擴展錯誤信息dostounixdos.h時間和日期子程序把日期和時間轉換成 UNIX 格式drawpolygraphics.h圖形子程序繪制多邊形dupio.h輸入輸出子程序復制文件句柄dup2io.h輸入輸出子程序將一個文件句柄復制到一個已有的文件句柄ecvtstdlib.h轉換子程序把浮點數轉換成字符串e

18、cvtstdlib.h數學子程序把浮點數轉換為字符串elipsegraphics.h圖形子程序繪制橢園enabledos.h接口子程序開硬件中斷eofio.h輸入輸出子程序檢測文件是否結束execleprocess.h進程控制子程序裝入并運行其它程序execlpprocess.h進程控制子程序裝入并運行其它程序execlpeprocess.h進程控制子程序裝入并運行其它程序exectprocess.h進程控制子程序execvprocess.h進程控制子程序裝入并運行其它程序本文章來自21 視頻教程網C 語言編程常見問題解答之常用函數的包含文件(1) _C 語言程序設計教程 原文鏈接:C 語言編

19、程常見問題解答之雜項 (Miscellaneous) ( 2)請參見:2012 怎樣把數據從一個程序傳遞到另一個程序?2017可以使熱啟動 (Ctrl+Alt+Delete) 失效嗎 ?2110 什么是動態(tài)連接 ?20 9 為什么要使用靜態(tài)變量 靜態(tài)變量作為一個局部變量是很合適的,它在函數退出后不會失去其本身的值。例如,有一個 要被調用很多次的函數,它的一部分功能就是計算自己被調用的次數。你不能用一個簡單的局部變 量來實現這部分功能,因為每次進入該函數時,這個變量都沒有被初始化。假如把這個計數變量說 明為靜態(tài)的,那么它就會象一個全局變量那樣保留自己的當前值。那么為什么不直接使用一個全局變量呢?

20、你可以使用一個全局變量, 而且這樣做沒有錯誤。 問題是使用了大量全局變量的程序維護起來很麻煩, 尤其是有許多函數都各自訪問一個全局變量的程序。 再說一遍,這樣做沒有錯誤,這只是一個程序設計和可讀性是否好的問題。假如你把這樣的變量說 明為靜態(tài)的, 你就可以提醒自己 (或者其它可能讀你的程序的人 )它是局部變量, 但要象全局變量那樣 被處理 (保留自己的值 )。假如你把它說明為全局的, 那么讀這個程序的人一定會認為有很多地方要引 用它,盡管實際上并不是這樣??偠灾?,當你需要一個能保持自己的值的局部變量時,使用靜態(tài)變量是一種好的編程習慣。請參見:2 17 可以頭文件中說明 static 變量嗎 ?

21、20 10 怎樣在一個程序后面運行另一個程序?顯然,在一個程序后面運行另一個程序的最簡單的辦法是把它們依次列入一個批處理文件中, 在執(zhí)行該批處理文件時,其中所列的程序就會依次運行。然而,這是一種人們已經知道的辦法。在 c 或 DOS 中,都沒有一種特定的方法來完成“在一個程序結束后運行另一個程序”這樣一種 函數調用。然而, c 提供了兩組函數,它們答應一個程序隨時可以運行另一個程序,而后者的運行 將結束前者的運行。 假如你將這樣的一個函數調用放到第一個程序的末尾, 你就能達到上述目的。 C 所提供的這兩組函數實際上是由exec()和spawn()所代表的兩個函數族,其中的每一個函數都具有一種區(qū)

22、別于同族其它函數的功能。exec()函數族包括這樣一些成員:execl(), execle(), execlp(), execlpe(),execv(),execve(),execvp()和execvpe()。下面列出了這此函數名中的e, l,p和v等后綴的含義:e明確地把一個指向環(huán)境參數的指針數組傳遞給子進程l把命令參數逐個傳遞給要執(zhí)行的程序p通過環(huán)境變量 PATH 找到要執(zhí)行的文件v把命令行參數以一個指針數組的形式傳遞給要執(zhí)行的程序在程序中選用哪一個函數完全取決于你以及要執(zhí)行的程序的需要。下例中的程序調用了其參數 由命令行指定的另一個程序:# include <stdio. h>

23、;# include <process. h> char * envString = "COMM VECTOR=0x63", "PARENT=LAUNCH. EXE", "EXEC=EDIT. COM", NULL ;voidmain(int argc, char *argv)/ * environment for the app * /* communications vector */ * name of this app * / * name of app to exec * / * must be NULL-ter

24、minated * / * Call the one with variable argumets and an enviroffment * /_execvpe (" EDIT. COM", argv, envString ) ;printf("If you can read this sentence, the exec didn't happen!n") ;上面這個短小的例子調用 _execvpe()來執(zhí)行DOS的文件編輯器 EDIT . COM , EDIT程序的參數 來自該例的命令行。在調用execvpe()函數后,上例中的程序就結束了

25、;當 EDIT程序退出時,你將返回到DOS提示符。假如printf()語句的打印內容顯示在屏幕上,則說明_execvpe()函數調用出了問題,因為假如它調用成功,就不會有上述結果。注重,上例所提供的EDIT.COM 的環(huán)境變量是沒有任何意義的,然而,假如上例要執(zhí)行一個需要環(huán)境變量的程序,那么所提供的環(huán)境變量就能供該程 序使用了。用spawn()函數同樣可以完成上例所做的工作。spawn()函數族包括這樣一些成員:spawnl(), spawnle()。 spawnlp(), spawnlpe(), spawnv(), spawnve(), spawnvp()禾口 spawnvpe()。 這些函

26、數名中的 e, l, p和v等后綴的含義與 exec()族函數名中的相同。實際上,spawn()函數族與exec()函數族基本相同,只不過有一點小小的差別一一spaw n()函數既可以在結束原來的程序后啟動另一個程序,也可以啟動另一個程序并在該程序結束后返回到原來的程序。spaw n()函數的參數與exec()函數的基本相同,只不過需要增加一個參數一你必須用_P_OVERLAY(結束原來的程序)或_P_WAIT( 結束后返回到原來的程序 面的例子相同的工作:)作為spawn()函數的第一個參數。下例用spawn()函數元成了與前# include <stdio. h># inclu

27、de <process. h>char * envString = "COMM VECTOR = 0x63", "PARENT=LAUNCH. EXE", "EXEC=EDIT. COM" , NULL ;/ * environment for the app * / * communications vector * / * name of this app * / * name of app to exec * / * must be NULL-terminated * /voidmain(int argc, char

28、 *argv)/ * Call the one with variable argumets and an environment * /_spawnvpe (_P_OVERLAY, "EDIT. COM", argv, envString) ;printf("If you can read this sentence, the exec didn't happen!n" );這里唯一的區(qū)別是"exec”變?yōu)?quot;spawn",并且增加了模式(mode)參數。spawn()函數有覆蓋和等 待兩種相對立的功能,它使你可以在

29、spawn()運行期間做出是等待還是離開的決定。實現上,P_WAIT參數回答了下一個問題。請參見:2011 怎樣在一個程序執(zhí)行期間運行另一個程序?2011 怎樣在一個程序執(zhí)行期間運行另一個程序?正如你在20. 10的例子中看到的那樣,spawn()函數族答應在一個程序中啟動另一個程序,并 在后者結束后返回到前者之中。有關spawn()函數的背景知識和例子(你只需把其中的_P_OVERLAY改為 _P_WAIT) 請參見 20. 10。然而,還有另外一種方法可以完成這項工作,即使用system()函數。system()函數與exec()或spawn()函數相似,但也不有同之處。除了掛起(而不是結

30、束)當前程序去執(zhí)行新程序外,system()還要啟動COMMAND . COM 命令翻譯程序 (或者其它任何運行在你的計算機上的命令翻譯程序)。假如它找不到COMMAND .COM或類似的程序,那么它就不會去執(zhí)行所要求的程序(這一點與exec()或spaw n()函數不同 )。下例是調用 EDIT COM 打開一個文件的另一個程 序版本,其中的文件名也來自該例 的命令行:# include <stdio. h># include <process. h># inclued <stdlib. h>char argStr255 ;voidmain(int arg

31、c, char *argv)int ret ;/ * Have EDIT open a file called HELLO if no arg given * /sprintf (argStr ,"EDIT %s", (argv1 = NULL?"HELLO" :argyll3) ) ;/ * Call the one with variable arguments and an environment * /ret = sytem (argStr) ;printf("system() returned %dn" ,ret) ;與20

32、. 10中的例子一樣(使用_P_WAIT),在system()調用后面的print()語句會被執(zhí)行,因為原 來的程序只是被掛起而不是被終止。在每一種情況下,system()都會返回一個表示是否成功地運行了所指定的程序的值,而不會返回所指定的程序的返回值。請參見:2010 怎樣在一個程序后面運行另一個程序?2012 怎樣把數據從一個程序傳給另一個程序步驟都相當簡潔:首先,定義在何處存放數據,如何獲取數據,以及如何通知另一個程序來獲取或 設置數據;然后,你就可以獲取或設置數據了,盡管使用文件的技術定義和實現起來都比較簡單, 但它的速度往往比較慢 (并且輕易引起混亂 )。因此, 這里重點討論內存數據

33、轉移技術。下面將依次具體地分析這一過程的每一個環(huán)節(jié):定義在何處存放數據。當你編寫要共享數據的兩個程序時,你應該讓程序知道要訪問的數據存 放在何處。這個環(huán)節(jié)同樣有幾種實現方法: 你可以在一個 ( 或每個 )程序中建立一個固定的內部緩沖區(qū), 并在兩個程序之間傳遞指向這個緩沖區(qū)的指針;你也可以為數據分配動態(tài)內存,并在兩個程序之間 傳遞指向該數據的指針;假如要傳遞的數據很小,你還可以通過 CPU 的通用寄存器來傳遞數據 (這 種可能性很小,因為 x86 結構的寄存器很少 )。分配動態(tài)內存是最靈活和模塊性最強的方法。定義獲取數據的方法。這個環(huán)節(jié)非常簡潔你可以使用 fmemcpy() 或等價的內存拷貝函數

34、。 顯然,在獲取和設置數據時都可以使用這個函數。定義通知另一個程序的方法。因為 DOS 并不是一個多任務操作系統(tǒng),所以其中一個(或兩個 )程序的一部分必須已經駐留在內存中,并且可以接受來自另一個程序的調用。同樣,這個環(huán)節(jié)也有幾 種方法可供選擇:第一個程序可以是一個列入 CONFIG SYS 中的驅動程序,它在系統(tǒng)啟動時就被 裝入內存;第一個程序也可以是一個 TSR( 終止并駐留 ) 程序,在它退出時會把與第二個程序相互作 用的那部分程序駐留在內存中;此外,你也可以在第一個程序中利用system()或spawn()函數(見20.11)來啟動第二個程序。你可以根據需要選擇合適的方法。因為有關DOS

35、 驅動程序的數據傳遞在 DOS文檔中已經有詳盡的描述,而有關system。和spawn()函數的內容也已經在前文中介紹過,因此下面介紹 TSR 方法。下面的例子給出了兩個程序:第一個程序是一個完整的 TSR 程序,但為了突出整個過程中的要 害環(huán)節(jié),它寫得比較單?。ㄒ?0. 15中的解釋)。這個TSR程序先是安裝了一個中斷63H的中斷服務程序,然后調用終止并駐留退出函數,在執(zhí)行這個 TSR 程序后,執(zhí)行下文給出的另一個程序。這 個程序只是簡單地初始化一個對中斷63H的調用(類似于使用中斷21H調用),并且把“ Hello There ”傳送給上述 TSR 程序# include <stdl

36、ib. h># include <dos. h># include <string. h>void SetupPointers (void) ;void OutputString(char * );# define STACKSIZE4096unsigned int near OldStackPtr; unsigned int near OldStackSeg; unsigned int _near MyStackOff ; unsigned int _near MyStackSeg; unsigned char_near MyStackSTACKSIZE; un

37、signed char far * MyStackPtr= (unsigned char_far * )MyStack; unsigned short AX, BX,CX, DX,ES;/ * My interrupt handler * / void_interrupt_far_ 視頻教程 '>cdecl NewCommVector ( unsigned short es, unsigned short ds, unsigned short di, unsigned short si, unsigned short bp, unsigned short sp, unsigned

38、 short bx, unsigned short dx, unsigned short cx, unsigned short ax, unsigned short ip, unsigned short cs,unsigned short flags) ;/ * Pointers to the previous interrupt handier * / void(_interrupt_far_cdecl * CommVector)(); union REGS regs;struet SREGS segregs ;# define COMM_VECTOR0x63/ * Software int

39、errupt vector * / * This is where the data gets passed into the TSR * / char_far * eallerBufPtr;char localBuffer255; / * Limit of 255 bytes to transfer * / char_far * localBufPtr=(ehar_far * )loealBuffer;unsigned int ProgSize= 276;/ * Size of the program in paragraphs * /voidmain(int argc,char * * a

40、rgv)int i, idx;/ * Set up all far pointers * /SetupPointers () ;/ * Use a cheap hack to see if the TSR is already loadedtf it is, exit,doing nothing * / comm_veetor =_dos_getvect (COMM_VECTOR) ; if(long)eomm_vector & 0xFFFFL) =(long) NewCommVector & OxFFFFL ) ) OutputString("Error :TSR

41、appears to already be loaded. n"); return ;/ * If everything's set,then chain in the TSR * / _dos_setvect (COMM_VECTOR ,NewCommVector) ;/ * Say we are loaded * /OutputString("TSR is now loaded at 0x63n");/ * Terminate, stay resident * / dos_keep (0, ProgSize ) ;/ * Initializes all

42、 the pointers the program will use * /voidSet upPointers ( )int idx ;/ * Save segment and offset of MyStackPtr for stack switching * / MyStackSeg = FP_SEG (MyStackPtr) ;MyStackOff = FP_OFF (MyStackPtr) ;/ * Initialize my stack to hex 55 so I can see its footprintif I need to do debugging * / for (id

43、x = 0 ;idx<STACKSIZE ; idx + ) MyStack idx = 0x55 ;void _interrupt_ far_cdecl NewCommVector (unsigned short es, unsigned short ds, unsigned short di, unsigned short si, unsigned short bp, unsigned short sp, unsigned short bx, unsigned short dx, unsigned short cx, unsigned short ax, unsigned short

44、 ip, unsign ed short cs, unsigned short flags)AX = ax;BX = bx ;CX = cx;DX = dx ;ES = es ;/ * Switch to our stack so we won't run on somebody else's * / _asm ;set up a local stackeli; stop interruptsmovOldStackSeg,ss; save stack segmentmovOldStackPtr,sp; save stack pointer (offset)movax,ds; r

45、eplace with my stack smovss,ax; dittomovax,MyStackOff; replace with my stack saddax,STACKSIZE-2;add in my stack sizemovsp ,ax; dittosti; OK for interrupts againswitch (AX) case 0x10;/ * print string found in ES:BX */ * Copy data from other application locally * / FP_ SEG (callerBufPtr) = ES ; FP_OFF

46、 (callerBufPtr) = BX ; _fstrcpy (localBufPtr, callerBufPtr ) ;/ * print buffer 'CX'number of times * /for(; CX>0; CX-)OutputString (localBufPtr) ; AX=1; /* show success */ break ;case 0x30:/* Unload stop processing interrupts * /_dos_setvect (COMM_VECTOR ,comm_vector) ; AX=2;/* show succe

47、ss */break ;default :OutputString (" Unknown commandrn" ) ;AX= 0xFFFF; / * unknown command-1 * /break ;/ * Switch back to the caller's stack * / asm climovmovsti;turn off interrupts ss,OldStackSeg;reset old stack segmentsp,OldStackPtr ;reset old stack pointer ;back on againax=AX;/* use

48、 return value from switch() */ * avoids calling DOS to print characters * / voidOutputString(char * str)int i ;regs. h. ah = 0x0E ;regs. x. bx = 0 ; for(i=strlen(str) ; i>0; i-,str+)regs. h. al= * str; int86 (0xl0, ?s, ?s) ;上述程序是這兩個程序中的TSR程序。這個程序中有一個NewCommVector()函數,它被安裝在中斷 63H(63H 通常是一個可用的向量 )處

49、作為中斷服務程序。 當它被安裝好后, 它就可以接收命令了。 switch 語句用來處理輸入的命令,并作出相應的反應。筆者隨意選擇了0x1O 和 0x30 來代表這樣兩條命令:“從 ES:BX 處復制數據,并打印到屏幕上, CX 中的數值為打印次數” ;“脫離中斷 63H, 并停止接收命令” 。下面是第二個程序向中斷 63H 發(fā)送命令的程序 (注重它必須在 Large 模式下 編譯 )。# include <stdlib. h># include <dos. h># define COMM VECTOR 0x63union REGS regs;struct SREGS s

50、egregs ;char buffer80;char _far * buf=(char_far *)buffer;main (int argc,char * * argv)intcnt;cnt = (argo= =1 ? 1:atoi(argv1) ;strcpy (bur, "Hello Therern" ) ;regs. x. ax= 0x10;regs. x. cx=cnt ;regs. x. bx=FP OFF(buf);segregs, es=FP SEG(buf) ;int86x(COMM_VECTOR ,?s, &segregs) ;printf (&

51、quot;TSR returned %dn" ,regs. x. ax) ;你可能會認為這個短小的程序看上去和那些通過調用int 21或int 10來在DOS中設置或檢索信息的程序差不多。假如你真的這么想,那就對了。唯一的區(qū)別就是現在你所用的中斷號是63H,而不是21H或10H。上述程序只是簡單地調用前文中的TSR程序,并要求后者把 es: bX所指向的字符串打印到屏幕上,然后,它把中斷處理程序(即那個TSR程序)的返回值打印到屏幕上。當字符串"Hello There ”被打印到屏幕上后,在兩個程序之間傳遞數據的全部必要步驟就都完成 了。這個例子的真正價值在于它能夠舉一反三

52、?,F在你能很輕松地編寫一個這樣的程序,它將發(fā)送 一條類似于“把要求你打印的最后一個字符串傳遞給我”的命令。你所要做的就是在前述TSR程序的 switch 語句中加入這條命令,然后再寫一個程序來發(fā)送這條命令。此外,你也可以在第二個程序 中利用20. 11中所介紹的system()或spawn()函數來啟動前述 TSR程序。由于TSR程序會檢查自己 是否已被裝入,因此你只需裝入一次 TSR 程序,就可以多次運行第二個程序了。在所有要和前述 TSR 程序通信的程序中,你都可以使用這里所說的方法。在建立前述 TSR 程序時,需要有幾個前提條件。其一就是沒有其它重要的中斷服務程序也在處 理中斷63H。例

53、如,筆者原來在程序中使用的是中斷67H,結果該程序能正常裝入并運行,但此后筆者就無法編譯程序了,因為Microsoft用來運行C編譯程序的DOS擴展程序也要使用中斷 67H。在筆者發(fā)送了命令 0x30(讓程序卸載自身)后,編譯程序又能正常運行了,因為DOS擴展程序的中斷處理程序已被該程序恢復了。第二個前提條件與駐留檢查在關。 筆者假設永遠不會有另一個中斷處理程序使用和 NewCommVector() 相同的近程型地址,盡管這種巧合的可能性極小,但讀者應該知道該程序并不是 萬無一失的。在該程序中,筆者特意讓 NewCommVector() 使用自己的棧,以避免它運行在調用它的 程序的棧上,但是,

54、 筆者還是假設調用所需的任何函數都是安全的。注重,該程序沒有調用 printf() ,因為它占用較多的內存,并且要調用DOS(int 21)來打印字符。在該程序中,當中斷63H發(fā)生時,筆者不知道DOS是否可以被調用,因此不能假設可以使用DOS調用。注重,在該程序中,可以調用那些沒有用到 DOS int21 服務程序的函數來完成所需的任務,假如必 須使用一個 DOS 服務程序,你可以在中斷 63H 發(fā)生時檢查 DOS 忙標志,以確定當時 DOS 是否可 以被調用。最后,對dos_keep()作一點說明:該函數要求知道在程序退出時要在內存中保留多少段(每段16字節(jié))數據。在本例這個TSR程序中,提供給該函數的段數(276)稍大于整個可執(zhí)行程序的大小。 當你的程序變大時,提供給該函數的段數也必須增大,否則就會出現一些異?,F象。請參見:20. 10 怎樣在一個程序后面運行另一個程序 ?20. 1l 怎樣在一個程序執(zhí)行期間運行另一個程序 ?20. 15 本書的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論