1. 要編譯的測試**:
int plus(int x, inty) int main(void
)
2. main中return語句語法分析
if (equal(tok, "return
"))
2.1 當前token為return,則建立型別為nd_return的node。
2.2 由於return後面跟著plus(3, 4),所以呼叫expr函式解析這個表示式。
2.3 跳過";"符號。
2.4 將型別為nd_return的node的左表示式設定為型別為nd_cast的node。
3. expr的處理
3.1 解析"plus"
if (tok->kind ==tk_ident)
static node *new_var_node(obj *var, token *tok)
當token型別為tk_ident時,從符號表中找到代表plus函式的node,這個node
是在解析plus函式時建立的,就不詳細分析了。
建立新的型別為nd_var的node,這個node的var域為代表plus函式的node。
if (equal(tok, "("))
if (ty->kind != ty_struct && ty->kind !=ty_union)exp = new_cast(exp, current_fn->ty->return_ty);
node->lhs =exp;
return node;
解析完函式名plus後,繼續解析函式引數呼叫,如果plus後面跟著是"(",則判斷為函式呼叫,
於是呼叫funcall函式建立型別為nd_funcall的node,funcall函式的引數node即為上面建立的
型別為nd_var的node。
建立完型別為nd_funcall的node,又呼叫new_cast建立型別為nd_cast的節點,這個節點
的左表示式為型別為nd_funcall的node。return的node型別為nd_return,它的左表示式為
nd_cast的node。
3.2 funcall函式
node head ={};node *cur = &head;
while (!equal(tok, ")"
))
else
if (arg->ty->kind ==ty_float)
cur = cur->next =arg;
}*rest = skip(tok, ")"
);node *node =new_unary(nd_funcall, fn, tok);
node->func_ty =ty;
node->ty = ty->return_ty;
node->args =head.next;
return node;
在funcall函式中呼叫assign函式解析"(3,4)",3被解析為型別為nd_num的node,
node *new_cast(node *expr, type *ty)
呼叫new_cast函式,建立型別為nd_cast的node節點,這個節點的左表示式為代表3的node。
跳過",",繼續呼叫assign解析4,4也被解析為nd_num的node,繼續呼叫new_cast,建立型別為
nd_cast的node節點,這個節點的左表示式為代表4的node。
跳出迴圈,跳過")"。
new_unary函式中建立型別為nd_funcall的node,這個node的左表示式為plus函式的node,
args引數為解析"(3,4)"生成的兩個型別為nd_cast的node。
4. 生成組合語言
staticvoid gen_stmt(node *node)
println(" jmp .l.return.%s", current_fn->name);
...}
判斷node節點為nd_return,則呼叫gen_expr處理型別為nd_cast的節點。
staticvoid gen_expr(node *node)
case
nd_var:
gen_addr(node);
return;
case
nd_cast:
gen_expr(node->lhs);
cast(node->lhs->ty, node->ty);
return
;...
}...
4.1 判斷為nd_cast型別的node,則呼叫gen_expr,引數為型別為nd_funcall的node。
4.2 呼叫push_args函式依次生成彙編語句
"mov rax, 4"
"push rax"
"mov rax, 3"
"push rax"
將4和3壓入棧。
4.3 遞迴呼叫gen_expr,引數為型別為nd_var的node。
4.4 呼叫gen_addr函式生成彙編**"lea rax, plus",將plus函式位址載入rax暫存器。
4.5 pop語句生成彙編**"pop rdi","pop rsi",將3彈入rdi暫存器,將4彈入rsi暫存器,
plus函式中從這兩個暫存器中讀取引數。
4.6 生成彙編**
"mov r10, rax"
"call r10"
"add rsp, 0"
將plus函式位址從rax載入r10暫存器,call語句完成呼叫plus函式,由於沒有分配棧空間傳遞引數
,所以這裡不需要修改rsp暫存器的值。
4.7 "jmp .l.return.main",跳轉到main函式的結尾處,實現return功能。
Silverlight 呼叫 WCF 如何處理錯誤
silverilght 客戶端不支援 faultexception.只會顯示乙個 404 錯誤。所以,服務端丟擲的異常,在客戶端是無法直接通過序列化 反序列化傳遞得到的。但是可以改用下列一些方法來幫助從客戶端得到錯誤資訊 1.在 service 端,將返回值物件重新設計,在其中新增錯誤資訊的字段,傳...
C 如何處理內聯虛函式
當乙個函式是內聯和虛函式時,會發生 替換或使用虛表呼叫嗎?為了弄清楚內聯和虛函式,讓我們將它們分開來考慮。通常,乙個內聯函式是被展開的。01.classcfoo 10.11.intsetval intv 12.13.這裡,如果使用下列 1.cfoo x 2.3.x.setval 17 4.5.int...
Tomcat Server是如何處理http請求的
下面就讓我們簡單了解一下 tomcat server處理乙個http請求的過程 假設來自客戶的請求為 jsp1 請求被傳送到本機埠8080,被在那裡偵聽的coyote http 1.1 connector獲得 2 connector把該請求交給它所在的service的engine來處理,並等待來自e...