Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 18 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
18
Dung lượng
393,5 KB
Nội dung
Sinh mã trung gian Nguyễn Phương Thái 2009 Mục tiêu Sinh mã trung gian có ưu điểm sau: • Dễ thiết kế phần • Sinh mã độc lập với máy tính cụ thể Từ làm giảm độ phức tạp sinh mã thực • Dễ tối ưu mã Mã ba địa • • • • • • • • • • • • • • Các câu lệnh gán có dạng x := y op z, op phép toán số học hai phép toán logic Các phép gán có dạng x := op y, op phép toán Các phép toán chủ yếu phép trừ, phép phủ định logic, phép chuyển đổi kiểu, phép dịch bít Các câu lệnh chép dạng x := y, gán y vào x Lệnh nhảy không điều kiện goto L Câu lệnh ba địa có nhãn L câu lệnh thực Các lệnh nhảy có điều kiện if x relop y goto L Câu lệnh thực phép toán quan hệ cho x y, thực câu lệnh có nhãn L quan hệ đúng, trái lại thực câu lệnh Câu lệnh param x call p,n dùng để gọi thủ tục Còn lệnh return y để trả giá trị lưu y Ví dụ để gọi thủ tục p(x1,x2, ,xn) sinh câu lệnh ba địa tương ứng sau: param x1 param x2 param xn call p, n Các phép gán số có dạng x := y[i] có ý nghĩa gán cho x giá trị vị trí i sau y tương tự x[i] := y Cú pháp điều khiển sinh mã địa • Đối với ký hiệu X, ký hiệu: • X.place nơi để chứa mã ba địa sinh X (dùng để chứa kết trng gian) Vì có hàm định nghĩa newtemp dùng để sinh biến trung gian (biến tạm) để gán cho X.place • X.code chứa đoạn mã ba địa X • thủ tục gen để sinh câu lệnh ba địa Biểu thức số học “x := a + ( b * c )” Sản xuất S -> id := E E -> E1 + E2 E -> E1 * E2 E -> - E1 E -> ( E1 ) E -> id Luật ngữ nghĩa Biểu thức số học “x := a + ( b * c )” Sản xuất Luật ngữ nghĩa S -> id := E S.code := E.code || gen(id.place ‘:=’ E.place) E -> E1 + E2 E.place := newtemp; E.code := E1.code || E2.code || gen(E.place ‘:=’ E1.place ‘+’ E2.place) E -> E1 * E2 E.place := newtemp; E.code := E1.code || E2.code || gen(E.place ‘:=’ E1.place ‘+’ E2.place) E -> - E1 E.place := newtemp; E.code := E1.code || gen(E.place ‘:=’ ‘uminus’ E1.place) E -> ( E1 ) E.place := E1.place E.code := E1.code E -> id E.place := id.place E.code := ‘’ Biểu thức logic Đối với biểu thức Boole E, dịch E thành dãy câu lệnh ba địa chỉ, phép toán logic sinh lệnh nhảy có điều kiện điều kiện đến hai vị trí: E.true, nơi quyền điều khiển chuyển tới E đúng, E.false, nơi quyền điều khiển chuyển tới E sai Ví dụ E có dạng a E1 and E2 E -> not E1 E -> ( E1 ) E -> id1 relop id2 E -> true E -> false Biểu thức logic Sản xuất Luật ngữ nghĩa E -> E1 or E2 E1.true := E.true; E1.false := newlable; E2.true := E.true; E2.false := E.false; E.code := E1.code || gen(E1.false ‘:’) || E2.code E -> E1 and E2 E1.true := newlable; E1.false := E.false; E2.true := E.true; E2.false := E.false; E.code := E1.code || gen(E1.true ‘:’) || E2.code E -> not E1 E1.true := E.false; E1.false := E.true; E.code := E1.code; E -> ( E1 ) E1.true := E.true; E1.false := E.false; E.code := E1.code; E -> id1 relop id2 E.code := gen(‘if’ id1.place relop.op id2.place ‘goto’ E.true) || gen(‘goto’ E.false) E -> true E.code := gen(‘goto’ E.true) E -> false E.code := gen(‘goto’ E.false) If a > b then a = a-b x=y+z S -> if E then S1 E -> id1 relop id2 E.true := newlable; E.false := S.next; S1.next := S.next; S.code := E.code || gen(E.true ‘:’) || S1.code E.code := gen(‘if’ id1.place relop.op id2.place ‘goto’ E.true) || gen(‘goto’ E.false) S -> if E then S1 else S2 ???? Ví dụ 1) Ví dụ if a>b then a:=a-b; else b:=b-a; 2) Ví dụ if a>b and c>d then x:=y+z else x:=y-z Mã địa if a>b goto L1 if a>b goto L1 goto L2 L1: t1 := a –b a := t1 goto Lnext L2: t2 := b-a b := t2 Lnext: goto L3 L1: if c>d goto L2 goto L3 L2: t1 := y+z x := t1 goto L4 L3: t2 := y-z x := t2 L4: Lệnh điều khiển Trong câu lệnh điều khiển có điều kiện, dựa vào biểu thức logic E để chuyển việc thực câu lệnh tới vị trí thích hợp Do ta cần hai nhãn: nhãn E.true để xác định vị trí câu lệnh chuyển tới biểu thức logic E đúng, nhãn E.false để xác định vị trí câu lệnh chuyển tới biểu thức logic E sai Để sinh nhãn mới, dùng thủ tục newlable Mặt khác S.next khối lệnh sinh ký hiệu S nhãn xác định vị trí lệnh sau S Đối với câu lệnh S -> while E S1 cần có nhãn bắt đầu khối lệnh để nhảy đến E đúng, cần nhãn S.begin để xác định vị trí bắt đầu khối lệnh Sản xuất S -> if E then S1 S -> if E then S1 else S2 S -> while E S1 Luật ngữ nghĩa while ab if a>b then a:=a-b else b:=b-a Sản xuất Lệnh điều khiển Luật ngữ nghĩa S -> if E then S1 E.true := newlable; E.false := S.next; S1.next := S.next; S.code := E.code || gen(E.true ‘:’) || S1.code S -> if E then S1 else S2 E.true := newlable; E.false := newlable; S1.next := S.next; S2.next := S.next; S.code := E.code || gen(E.true ‘:’) || S1.code || gen(‘goto’ S.next) || gen(E.false ‘:’) || S2.code S -> while E S1 S.begin := newlable; E.true := newlable; E.false := S.next S1.next := S.begin; S.code := gen(S.begin ‘:’) || E.code || gen(E.true ‘:’) || S1.code || gen(‘goto’ S.begin) Ví dụ while ab if a>b then a:=a-b else b:=b-a Mã địa L1: if ab goto L2 goto Lnext L2: if a>b goto L3 goto L4 L3: t1 := a-b a := t1 goto L1 L4: t2 := b-a b := t2 goto L1 Lnext: Khai báo Ví dụ: Giả sử ký hiệu offset để chứa địa tương đối định danh; số interger chiếm byte, số real chứa byte trỏ chứa byte; giả sử hàm enter dùng để nhập thông tin kiểu địa tương đối cho định danh, có ví dụ mô ta việc sinh thông tin vào bảng ký hiệu cho khai báo Sản xuất Luật ngữ nghĩa P -> D offset := D -> D ; D D -> id : T enter(id.name,T.type, offset) ; offset := offset + T width T -> interger T.type := interger; T width := T -> real T.type := real; T width := T -> array [ num ] of T1 T.type := array(num.val,T1.type); T.width := num.val * T1 width T -> ^T1 T.type := pointer(T1.type) T width := Khai báo • • • Đối với khai báo định danh, không sinh mã lệnh tương ứng mã ba địa mà dùng bảng ký hiệu để lưu trữ Như hiểu kết sinh mã ba địa từ chương trình nguồn tập lệnh ba địa bảng ký hiệu quản lý định danh Với định danh, lưu thông tin kiểu địa tương đối để lưu giá trị cho định danh Như vậy, đoạn mã ba địa chỉ, đề cập đến tên, tham chiếu đến bảng ký hiệu để lấy thông tin kiểu, địa tương ứng để sử dụng câu lệnh Hay nói cách khác thay định danh mục định danh bảng ký hiệu • Chú ý: địa tương đối phần tử mảng, ví dụ x[i] tính địa x cộng với i lần độ dài phần tử Hàm [...]... width := 4 T -> real T.type := real; T width := 8 T -> array [ num ] of T1 T.type := array(num.val,T1.type); T.width := num.val * T1 width T -> ^T1 T.type := pointer(T1.type) T width := 4 Khai báo • • • Đối với các khai báo định danh, chúng ta không sinh ra mã lệnh tương ứng trong mã ba địa chỉ mà dùng bảng ký hiệu để lưu trữ Như vậy có thể hiểu là kết quả của sinh mã ba địa chỉ từ chương trình nguồn là... báo Ví dụ: Giả sử ký hiệu offset để chứa địa chỉ tương đối của các định danh; mỗi số interger chiếm 4 byte, số real chứa 8 byte và mỗi con trỏ chứa 4 byte; giả sử hàm enter dùng để nhập thông tin về kiểu và địa chỉ tương đối cho một định danh, chúng ta có ví dụ dưới đây mô ta việc sinh thông tin vào bảng ký hiệu cho các khai báo Sản xuất Luật ngữ nghĩa P -> D offset := 0 D -> D ; D D -> id : T enter(id.name,T.type,... để xác định vị trí câu lệnh chuyển tới khi biểu thức logic E là đúng, và nhãn E.false để xác định vị trí câu lệnh chuyển tới khi biểu thức logic E là sai Để sinh ra một nhãn mới, chúng ta dùng thủ tục newlable Mặt khác S.next đối với khối lệnh sinh ra bởi ký hiệu S là nhãn xác định vị trí tiếp theo của các lệnh sau S Đối với câu lệnh S -> while E do S1 chúng ta cần có một nhãn bắt đầu của khối lệnh