c語言中if語句是怎么變成匯編代碼的詳解
?1. 要編譯的測(cè)試代碼:?
int a; int b = 3; int main(void) { if (3) a = 4; else b = 5; }
2. 詞法分析
詞法分析將c源代碼解析成一個(gè)個(gè)的token。
關(guān)鍵的,將if兩個(gè)字符解析成一個(gè)if token,后續(xù)語法分析的輸入就從兩個(gè)字符減少為1個(gè)token,減小了語法分析的難度。
3. 語法分析
if (equal(tok, "if")) { Node *node = new_node(ND_IF, tok); tok = skip(tok->next, "("); node->cond = expr(&tok, tok); tok = skip(tok, ")"); node->then = stmt(&tok, tok); if (equal(tok, "else")) node->els = stmt(&tok, tok->next); *rest = tok; return node; }
如果當(dāng)前處理的token是if,則
3.1 創(chuàng)建新的類型為ND_IF的node。
3.2 跳過if后面的"("。
3.3 調(diào)用expr函數(shù)解析if語句()中的表達(dá)式,并將解析結(jié)果存儲(chǔ)在node->cond。
3.4 跳過“)”。
3.5 調(diào)用stmt處理then語句塊中的語句,這里是處理"a = 4;",將解析結(jié)果存儲(chǔ)在node->then。
3.6 如果if語句還有else部分,則調(diào)用stmt處理else語句塊中的語句,這里是處理"b = 5;",將解析結(jié)果存儲(chǔ)在node->els。
3.7 node->cond,node->then,node->els都為node節(jié)點(diǎn)。
4. 代碼生成
switch (node->kind) { case ND_IF: { int c = count(); gen_expr(node->cond); cmp_zero(node->cond->ty); println(" je .L.else.%d", c); gen_stmt(node->then); println(" jmp .L.end.%d", c); println(".L.else.%d:", c); if (node->els) gen_stmt(node->els); println(".L.end.%d:", c); return; } ...
如果當(dāng)前處理的node節(jié)點(diǎn)類型為ND_IF,則
4.1 gen_expr
這個(gè)函數(shù)處理if語句的條件部分,這里是處理3。判斷node節(jié)點(diǎn)為NUM,會(huì)生成匯編語句"mov? ? ?rax, 3",將3載入rax寄存器。
4.2 cmp_zero
cmp_zero會(huì)生成匯編語句"cmp? ? ?eax, 0",比較3和0。
4.3 println(" je .L.else.%d", c);
該語句會(huì)生成匯編代碼" je .L.else.1",當(dāng)上條比較語句中eax為0時(shí)會(huì)執(zhí)行跳轉(zhuǎn),跳轉(zhuǎn)到else分支運(yùn)行。這里由于eax為3,所以不跳轉(zhuǎn)。
4.4 gen_stmt(node->then);
這條語句會(huì)將then分支中的語句解析為匯編源碼,這里是"a = 4;",這條語句是表達(dá)式語句,所以會(huì)調(diào)用gen_expr函數(shù)。
4.4.1 gen_expr
"lea? ? ?rax, a",將a的地址載入rax寄存器中。
"push rax",將rax入棧。
"mov? ? ?rax, 4",將4載入rax寄存器中。
"pop? ? ?rdi",將變量a的地址載入rdi寄存器。
"mov? ? ?[rdi], eax",將4寫入變量a。?
4.5 println(" jmp .L.end.%d", c);
執(zhí)行完then分支代碼后跳轉(zhuǎn)到下一條語句處執(zhí)行。
4.6 println(".L.else.%d:", c);
插入一條標(biāo)簽,表示else分支代碼的開始,如果if語句條件為0會(huì)跳轉(zhuǎn)到這。
4.7 gen_stmt(node->els);
生成else分支代碼,處理"b = 5;"。
"lea? ? ?rax, b",將變量b的地址載入rax寄存器。
"push? ? rax",將rax寄存器入棧。
"mov? ? ?rax, 5",將5載入rax寄存器。
"pop? ? ?rdi",將b的地址載入rdi寄存器。
"mov? ? ?[rdi], eax",將5寫入變量b中。
4.8 println(".L.end.%d:", c);
插入一條標(biāo)簽,表示if語句的結(jié)束,then分支語句執(zhí)行完成后跳轉(zhuǎn)到這里。
總結(jié)
到此這篇關(guān)于c語言中if語句是怎么變成匯編代碼的文章就介紹到這了,更多相關(guān)c語言if語句變成匯編代碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Linux?C/C++實(shí)現(xiàn)網(wǎng)絡(luò)流量分析工具
網(wǎng)絡(luò)流量分析的原理基于對(duì)數(shù)據(jù)包的捕獲、解析和統(tǒng)計(jì)分析,通過對(duì)網(wǎng)絡(luò)流量的細(xì)致觀察和分析,幫助管理員了解和優(yōu)化網(wǎng)絡(luò)的性能,本文將通過C++實(shí)現(xiàn)網(wǎng)絡(luò)流量分析工具,有需要的可以參考下2023-10-10C語言中的一維數(shù)組與二維數(shù)組的實(shí)現(xiàn)
數(shù)組可以幫我們巧妙解決生活中的問題,使我們的代碼簡(jiǎn)潔,本文主要介紹了C語言中的一維數(shù)組與二維數(shù)組,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12用C++實(shí)現(xiàn)單向循環(huán)鏈表的解決方法
本篇文章是對(duì)用C++實(shí)現(xiàn)單向循環(huán)鏈表的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05完全掌握C++編程中構(gòu)造函數(shù)使用的超級(jí)學(xué)習(xí)教程
這篇文章主要介紹了C++中的構(gòu)造函數(shù),包括C++11標(biāo)準(zhǔn)中的新特性的介紹,十分推薦!需要的朋友可以參考下2016-01-01深入解析C++中的函數(shù)模板和函數(shù)的默認(rèn)參數(shù)
這篇文章主要介紹了深入解析C++中的函數(shù)模板和函數(shù)的默認(rèn)參數(shù),是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09C++?Opencv實(shí)現(xiàn)錄制九宮格視頻
這篇文章主要為大家介紹了如何利用C++和OpenCV庫實(shí)現(xiàn)錄制九宮格視頻,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)OpenCV有一定幫助,感興趣的可以了解一下2022-05-05