c語言可以嵌套匯編:
專注于為中小企業(yè)提供成都網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)施秉免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了1000+企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
按照TC2.0的幫助系統(tǒng)所以說的,在TC2.0下是可以用匯編的,方法是使用asm關(guān)鍵字:其格式是:
asm opcode operands ;newline,如同別的注釋一樣,之間的表示可選的;例如:
main()
{
char *c="hello,world/n/r$";
asm mov ah,9;asm mov dx,c;asm int 33;
printf("You sucessed!/n");
}
或者是:
main()
{
char *c="hello,world/n/r$";
asm mov ah,9
asm mov dx,c
asm int 33
printf("You sucessed!");
}
兩種格式其實(shí)是一種.如果你用的是第一種的樣式,記住:
每一句匯編語句都要以asm開頭,如果一行內(nèi)有多個(gè)句子,
那么千萬不要忘記在兩個(gè)句子之間的這個(gè)semicolon(分號(hào)),
但是最后一句匯編后面(如果后面沒有其它的語句)的分號(hào)可有可無,象第一個(gè)例子中的
asm int 33;后面的分號(hào)就可以不要,因?yàn)樗暮竺鏇]有其它
的語句了.但如果是這樣:
asm mov ah,9; asm mov dx,c;asm int 33; printf("You sucessed!");
那么asm int 33;后面的分號(hào)便還是留下好,以免出現(xiàn)編譯錯(cuò)誤!
在這一點(diǎn)上頗象C語言.
還有一種格式是
asm{ assembly language statement},這種格式應(yīng)該被普遍的歡迎.
它們的例子如下(其中的語句排列格式與上面兩種相同):
asm{
mov ax,var1
add ax,var2
......
}
但是要注意這種格式TC2.0是不支持的!
只有后來的TC++3.0及后來的IDE支持!
工具的使用:
一旦你的C源文件里包括了這些好東西,則必須用TCC.EXE的COMMAND-LINE來編譯,具體的命令參數(shù)TCC.EXE已經(jīng)提供,這里不復(fù)闡述了.最簡(jiǎn)單的是:TCC C源文件名(使用這個(gè)方法,TCC會(huì)自動(dòng)調(diào)用TASM.EXE和TLINK.EXE,并且能夠使TLINK.EXE正確的找到需要的.obj和.lib文件,如果你單步編譯的話,可能會(huì)碰到很多的問題,主要是TLINK.EXE它自己并不會(huì)去找.obj和.lib文件,你自己可以建一個(gè).bat文件,如果要指定.lib文件的目錄的話可以用/L參數(shù),在文章的后面有一個(gè)例子).但大家要注意了,看一下你的TC目錄下面到底是否有TASM.EXE文件,并在TURBOC.CFG(這個(gè)文件包括TCC.EXE運(yùn)行期參數(shù),這里面所有參數(shù)在運(yùn)很期都將被自動(dòng)TCC.EXE使用,例如:-IH:/TC/INCLUDE/
-LH:/TC/LIB/)文件中設(shè)置好一些參數(shù),并確認(rèn)TASM.EXE的版本號(hào)要2.0以上,以及是否能夠向下兼容.但是在大多數(shù)的情況下TC的目錄是沒有TASM.EXE的,或是版本不正常.
如果你有TASM.EXE文件并且TURBOC.CFG文件也已經(jīng)寫好了,但是還要注意一個(gè)
問題:運(yùn)行TCC.EXE時(shí)要在獨(dú)立的DOS SHELL下面(不要害怕,這不是一個(gè)新東西,我的意思
是,不在諸如TC下的DOS SHELL下面運(yùn)行,我曾經(jīng)敗在這個(gè)問題下,當(dāng)我發(fā)現(xiàn)時(shí)直想揍電腦
一頓,還好沒有,不然就沒有這篇文件了.)
還有一句重要的話:TC2.0支持大部分8086指令(當(dāng)然用法有一些約定,不過現(xiàn)在我并不打算
進(jìn)行詳細(xì)說明,因?yàn)槟鞘且患芊彪s的事,以后有時(shí)間或許會(huì)寫出來----如果大家需要的話).
如果說上面我所說的那些約定很繁雜的話,那么下面的方法該是多么簡(jiǎn)單啊!
讓我們使用Borland為TC2.0內(nèi)建的變量來進(jìn)行偽匯編.
或許你還不知道在TC2.0中還有一些內(nèi)建的pseudo寄存器(可以看作是register 型的變量,但是它們比register型的變量好用的多)
_AX,_AH,_AL,
_BX,_BH,_BL,
_CX,_CH,_CL,
_DX,_DH,_DL,
_DI,_SI,_SP,
_CS,_DS,_ES,_SS
注意這些寄存器的size,_AX,_BX,_CX,_DX,_CS,_DS,_ES,_SS,_SI,_DI,_SP等都是16位的寄存器相當(dāng)于C語言的unsigned int類型,其余的都是8位的寄存器(相當(dāng)于unsigned char)(TC怎么可能支持32位的寄存呢,所以EAX等是不能用的,FS,GS和IP寄存器都是無效的),還有就是在傳遞參數(shù)的時(shí)候千萬不要忘記使用強(qiáng)制類型轉(zhuǎn)換.
中斷調(diào)用指令是:__int__(interrupt_#)(注意int的前輟和后輟都是兩個(gè)underscores)
For example:
#includedos.h
unsigned int _stklen=0x200;
unsigned int _heaplen=0;
main()
{
_DX=(unsigned int)"Hello,world./r/n$";
_AX=0x900;
__int__(0x21);
}
dos.h它是包含__int__()內(nèi)建中斷調(diào)用語句的頭文件,因此是不可
缺少的._stklen和_heaplen是定義運(yùn)行期堆棧和堆大小的兩個(gè)內(nèi)部
引用變量(這是個(gè)我自己想的名詞,意指如果這兩個(gè)變量在源文件中
顯式的聲明了,那么編譯程序會(huì)自會(huì)引用來構(gòu)造編譯時(shí)期的信息以產(chǎn)生
用戶希望的目標(biāo)文件,如果不顯式的聲明則編譯程序自動(dòng)確定).
這兩個(gè)變量也有一些約定,如果_stklen不顯式聲明,_heaplen賦值為零
都表示棧和堆都是defult的.
最后在TC2.0中還有一個(gè)沒有說明的標(biāo)志位寄存器flags,它也是內(nèi)建
pseudo寄存器是:_FLAGS,是一個(gè)16位寄存器.這些內(nèi)建的寄存器都可以進(jìn)行
運(yùn)算,但是要注意它們所代表的類型(必要時(shí)進(jìn)行類型轉(zhuǎn)換);
看起來這是不是一種好的辦法啊(而且使用這種方法只要用個(gè)一個(gè)dos.h頭文件就好,
不需要用TCC編譯,可以直接在TC20的IDE下編譯).
TC2.0中也提供了一些簡(jiǎn)單好用的函數(shù)來實(shí)現(xiàn)對(duì)DOS功能的調(diào)用如:
int86(...),int86x(...)(但是這些方法實(shí)際仍然要調(diào)用函數(shù),所以不如使用
偽寄存器,又因?yàn)橐獱可娴絬nion REGS結(jié)構(gòu)的內(nèi)存分配所以系統(tǒng)的開銷是增大了,
而使用偽寄存器是最簡(jiǎn)潔的),端口通信函數(shù)如:inportb(...),inport(...),
outportb(...),outport(...),指針轉(zhuǎn)換函數(shù):FP_OFF,FP_SEG,MK_FP,這些函數(shù)在
幫助系統(tǒng)中都有,有用時(shí)大家可以查閱.
tlinkbat.bat的例子:
rem The lib environment variable is the directory of the .obj and .lib file
set lib=h:/tc/lib/
rem 這下面的句子中的c0s(C 零S)是一個(gè).OBJ文件,是一個(gè)C程序的STARTUP文件
tlink %lib%c0s %1,%1,%1,/L%lib%emu.lib %lib%maths.lib %lib%cs.lib
set lib=
(使用時(shí)可將以rem開頭的句子刪除)
___________________________________________________
一些約定:
我們先說一下在TC20下寫匯編(內(nèi)聯(lián)匯編--自己起的名字,大家可以想叫什么叫什么)時(shí)的編譯器的編譯原則:
1.所有在main()函數(shù)外的的匯編語言的語句都作為數(shù)據(jù)聲明語句處理,也即在編譯器編譯時(shí)會(huì)將它放在數(shù)據(jù)段中,如:
asm string1 db "Hello",,,'world!',0ah,0xd,"$"
main()
{
asm mov dx,offset string1
asm mov ah,9
asm int 33
asm mov dx,offset string2
asm int 33
}
asm string2 db "the string can be declared after the main() function!$"
象這些樣子在main()外面的匯編語言的數(shù)據(jù)定義語句(事實(shí)上不管是什么匯編語句,
只要是在main()之外,包括這個(gè)句子:asm mov ax,0x4c00),在編譯后都放在數(shù)據(jù)段中,而C語言的數(shù)據(jù)聲明語句仍按C的規(guī)則!
2.所有在main()函內(nèi)的匯編語言的語句在編譯后都放在代碼段中,包括這個(gè)句子:
asm string2 db "the string can be declared after the main() function!$"
3.不要在以asm 開頭的語句中使用C語言的關(guān)鍵字,這會(huì)導(dǎo)致編譯階段的錯(cuò)誤
那么,根據(jù)這三條大家會(huì)得到什么樣的結(jié)論呢?(先閉上眼想一想,你可能會(huì)由此變的
很贊賞自己,是的你應(yīng)該這樣相信自己是對(duì)的!)
讓我們一起看一下這個(gè)結(jié)論:
1.根據(jù)編譯原則1得到:不可以在main()外面寫匯編命令語句(不要笑,正是與C語言相同才值得注意!),在任何地方都不要進(jìn)行任何的段定義和宏定義(這是因?yàn)榫幾g后的形式?jīng)Q定的,也即:在TC20下所有的匯編格式的語句只能是,直接性的數(shù)據(jù)定義和語句指令)!
2根據(jù)編譯原則2得到:不可以在main()之內(nèi)使用匯編的語句進(jìn)行數(shù)據(jù)定義(同樣不要笑,
大多數(shù)人在第一次在TC20下寫匯編都會(huì)有這樣的錯(cuò)誤的)
3.如同類強(qiáng)制類型這樣的事是不可以在以asm開頭的匯編語句中使用的
好了,天即朗,氣瞬清!這樣一說,一個(gè)大體的框架就出來了!只要遵守這個(gè)原則寫,就可避免很多莫名其妙的錯(cuò)誤出現(xiàn)!
通俗的說:
匯編語句的數(shù)據(jù)定義放在main()外面,指令放在main()里面.
如果你沒有更好的文檔,那么記住我的這些話!
一些細(xì)節(jié)的問題:
在以asm開頭的內(nèi)聯(lián)匯編語句中是不支持C的轉(zhuǎn)義字符的,但是用C語言聲明一個(gè)字符數(shù)組(含有轉(zhuǎn)義字符的),然后用int 33 ah=9這功能時(shí)輸出這個(gè)字符串時(shí),其中的轉(zhuǎn)義字符是有效的(這主要是因?yàn)榫幾g后其內(nèi)部表示形式不同造成的,自己想想會(huì)有答案的).
內(nèi)聯(lián)匯編支持C的一些如數(shù)值表示,字符串聲明格式等,
如:一個(gè)十六進(jìn)制的數(shù)據(jù)可以用兩種方式表示:0xa 和0ah,字符串可以是這樣:
"Hello,world!$"(如同C)也可以這樣'Hello,world!$'(用匯編自己的方式).
象C一樣你同樣要注意賦值的類型,而且要比C更嚴(yán)格(匯編從來不自己動(dòng)手做
如同類型轉(zhuǎn)換啊這樣事),所以一切的事完全要你自己做好!而且你不要企圖以C的形式
做這件事,如這樣的格式 asm mov dx,(unsigned)a(a是一個(gè)這樣的東西,
char a[ ]="hello,world!";),而且這樣句子也會(huì)導(dǎo)致錯(cuò)誤:asm mov dx,word ptr a(邏輯錯(cuò)誤),不過這不是在編譯時(shí)的錯(cuò)誤,而是運(yùn)行期的錯(cuò)誤(具體的原因自己想一想,象word label這樣的東西的運(yùn)算作用和會(huì)導(dǎo)致的后果),你可以這樣用一個(gè)句子做"中間人"如int i=(unsigned)a;asm mov dx,i(也千萬不要用asm mov dx,(unsigned)a 這樣的句子.但是,告訴大家一個(gè)好消息,你可以用指針指向一個(gè)字符串,然后你會(huì)驚訝你竟然可以這樣:
char *p="hello,world";asm mov dx,p,然后用int 33 ah=9的功能輸出這個(gè)字符串而不會(huì)有錯(cuò)誤(這也表現(xiàn)出指針的特點(diǎn),它是一個(gè)二字節(jié)的(TC20下)變量,含有的是一個(gè)地址,這與其指向的變量的類型是毫無關(guān)系的).
內(nèi)匯匯編語句不支持-這個(gè)運(yùn)算符.還有標(biāo)號(hào)的問題,在最后的例子中你會(huì)年看到一些特別之處!
上面所說的只是很細(xì)小并微少的一些事(也是很常遇到的),尚有很多的細(xì)節(jié)要說,但由于本人時(shí)間有限不能一一列舉,如C的結(jié)構(gòu)在內(nèi)聯(lián)匯編的應(yīng)用等大家可以按照其運(yùn)行機(jī)理去想想一下用法;另外,由于這只是一件學(xué)習(xí)的事,所以還是大家自己學(xué)(找一下有關(guān)文檔,當(dāng)然現(xiàn)在已經(jīng)沒有什么比較完整的了),情況會(huì)好的多,我在對(duì)內(nèi)聯(lián)匯編的學(xué)習(xí)過程中領(lǐng)會(huì)到了不少的東西,例如編譯原理方面的知識(shí),以及如何做會(huì)使代碼更高效,占空間最少等的方法.最后向大家推薦一種方法,在利用TCC的-S開關(guān)可以生成C源文件的匯編代碼
(或許很多的人都用過)是很好的學(xué)習(xí)材料!祝大家學(xué)有所成!
Cstarter
02-11-17
/* 由于個(gè)人的時(shí)間和能力有限,難免有錯(cuò)誤和不詳細(xì)的地方,請(qǐng)大家見諒!
My Email:wxe85@sina.com Cstarter1985@hotmail.com QQ:170594633 */
一些例子:
下面這個(gè)例子是對(duì)沈美明 溫冬嬋的
IBM-PC 匯編語言程序設(shè)計(jì)清華版第十一章程序的改寫
可直接在命令行上鍵入 tcc filename 就可以,當(dāng)然你要有TASM.EXE
/*
asm mus_frep dw 330,294,262,294,3 dup(330)
asm dw 3 dup(294),330,392,392
asm dw 330,294,262,294,4 dup(330)
asm dw 294,294,330,294,262,-1
asm mus_time dw 6 dup(25),50
asm dw 2 dup (25,25,50)
asm dw 12 dup(25),100
*/
asm mus_frep dw 330,392,330,294,330,392,330,294,330
asm dw 330,392,330,294,262,294,330,392,294
asm dw 262,262,220,196,196,220,262,294,330,262
asm dw -1
asm mus_time dw 3 dup (50),25,25,50,25,25,100
asm dw 2 dup (50,50,25,25),100
asm dw 3 dup (50,25,25),100
main()
{
asm jmp start
/*設(shè)置發(fā)聲的頻率,這一段在沈美明 溫冬嬋的
IBM-PC 匯編語言程序設(shè)計(jì)清華版第十一章有詳細(xì)的說明 */
sound:
asm mov al,0b6h
asm out 43h,al
asm mov dx,12h
asm mov ax,533h*896
asm div di
asm out 42h, al
asm mov al,ah
/* 這個(gè)延時(shí)是用來防止兩次IO操作的最后一次操作的錯(cuò)誤,
因?yàn)镃PU比總線的速度快很多,所以 要延時(shí)等待第一次操作完成后再進(jìn)行第二次操作*/
asm mov cx,1000
delay:
asm loop delay
asm out 42h,al
asm in al,61h
asm mov ah,al
asm or al,3
asm out 61h,al
/* 使用中斷15H功能86H延時(shí)CX:DX=微秒數(shù)*/
asm mov ax,2710h
asm mul bx
asm mov cx,dx
asm mov dx,ax
asm mov ah,86h
asm int 15h /*可用__int__(0x15);代替*/
asm mov al,ah
asm out 61h,al
asm jmp add_count
/*------------------*/
start:
asm mov si,offset mus_frep
asm lea bp,mus_time
frep:
asm mov di,[si]
asm cmp di,-1
asm je end_mus
asm mov bx,[bp]
asm jmp sound
add_count: /*標(biāo)號(hào)不能用匯編語言寫*/
asm add si,2
asm add bp,2
asm jmp frep
end_mus:;
}
對(duì)于上面的程序大家可用偽寄存器的方法寫一個(gè),要容易的多!
/*一個(gè)發(fā)聲程序!(引自PC技術(shù)內(nèi)幕電力版--這個(gè)版不好,不如清華版的)*/
#include"dos.h"
main()
{
static union REGS ourregs;
outportb(0x43,0xb6);
outportb(0x42,0xee);
outportb(0x42,0);
outportb(0x61,(inportb(0x61)|0x03));
ourregs.h.ah=0x86;
ourregs.x.cx=0x001e;
ourregs.x.dx=0x8480;
int86(0x15,ourregs,ourregs);
outportb(0x61,(inportb(0x61)0xfc));
}
最近三年,在工作中使用go開發(fā)了不少服務(wù)。深感g(shù)o的便捷,以及它的runtime的復(fù)雜。我覺得需要定期的進(jìn)行總結(jié),因此決定寫這篇文章,也許更準(zhǔn)確的,應(yīng)該叫筆記。
最近終于解決了一個(gè)和cgo有關(guān)的問題。這個(gè)問題從發(fā)現(xiàn)到解決前后經(jīng)歷了接近4個(gè)月,當(dāng)然,和人手不足也有關(guān)系。而對(duì)于我個(gè)人而言,這個(gè)問題其實(shí)歷時(shí)2年!這得從頭說起。
在上一家公司的一個(gè)項(xiàng)目里,有一個(gè)服務(wù)做音視頻數(shù)據(jù)的提取,這個(gè)服務(wù)運(yùn)行在嵌入式設(shè)備TX2上。音視頻提取這一關(guān)鍵功能主要利用nvidia基于gstreamer開發(fā)的插件,這個(gè)插件可以發(fā)揮nvidia gpu的硬件解碼功能。當(dāng)時(shí)這個(gè)服務(wù)使用go和c混編的方式,問題的癥狀是服務(wù)運(yùn)行一段時(shí)間后,不輸出音視頻數(shù)據(jù)。遺憾的是,由于疫情,項(xiàng)目停止,因此沒有機(jī)會(huì)繼續(xù)研究這個(gè)問題。
時(shí)間來到去年底。當(dāng)前這個(gè)項(xiàng)目進(jìn)行壓力測(cè)試,發(fā)現(xiàn)關(guān)鍵的語音處理服務(wù)運(yùn)行一段時(shí)間后,會(huì)出現(xiàn)不拉流的情況,因此也沒有后續(xù)的結(jié)果輸出。癥狀和上一個(gè)項(xiàng)目非常像。雖然使用的第三方SDK不一樣,但同樣用了go和c混編的方式。一開始,焦點(diǎn)就放在go的運(yùn)行時(shí)上,覺得可能是go和c相互調(diào)用的方式不對(duì)。經(jīng)過合理猜測(cè),并用測(cè)試進(jìn)行驗(yàn)證后,發(fā)現(xiàn)問題還是在第三方拉流的SDK上,它們的回調(diào)函數(shù)必須要快,否則有可能會(huì)阻塞它們的回調(diào)線程。當(dāng)然,在go調(diào)用c的時(shí)候,如果耗時(shí)比較長(zhǎng),會(huì)對(duì)go的運(yùn)行時(shí)造成一些副作用;在c回調(diào)go的時(shí)候,go的運(yùn)行時(shí)也有可能阻塞c的回調(diào)線程。但go的運(yùn)行時(shí)已經(jīng)比較成熟,因此我覺得它對(duì)這個(gè)問題的貢獻(xiàn)不大。以上采用了假設(shè)-驗(yàn)證的方法,主要的原因還是第三方的拉流SDK不開源。在定位問題的過程中,使用了gdb的gcore來生成堆棧;也搭建了灰度環(huán)境來進(jìn)行壓力測(cè)試,以及完善監(jiān)控,這些都是解決方法的一部分。
正是這一問題,促使我更多的了解go的運(yùn)行時(shí)。而我看得越多,越覺得go的運(yùn)行時(shí)是一個(gè)龐大的怪物。因此,抱著能了解一點(diǎn)是一點(diǎn)的心態(tài),不斷的完善這篇筆記。
1、不可以,不是一種語言,無法混編。
2、當(dāng)然如果是一部分功能用go實(shí)現(xiàn),一部分功能用JAVA實(shí)現(xiàn)是可以的。很多遺留系統(tǒng)就是這樣處理的。不過需要用到rpc技術(shù)了。
當(dāng)前題目:c語言go混編 go 編譯語言
標(biāo)題鏈接:http://chinadenli.net/article0/hgpcio.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、外貿(mào)建站、網(wǎng)站導(dǎo)航、品牌網(wǎng)站設(shè)計(jì)、靜態(tài)網(wǎng)站、ChatGPT
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)