Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Thông dịch máy ảo thanh ghi ba địa chỉ (register VM)

    Nhiều máy ảo hiệu năng cao (như CPython, Lua, Dalvik) dùng mô hình thanh ghi thay vì ngăn xếp, với các lệnh số học dạng ba địa chỉ (three-address code): op dst, src1, src2 nghĩa là kết quả của phép toán trên hai thanh ghi nguồn được ghi thẳng vào thanh ghi đích, giúp giảm số lệnh di chuyển dữ liệu so với máy ảo ngăn xếp.

    Xét một máy ảo thanh ghi với rrr thanh ghi đánh số 0,1,…,r−10, 1, \dots, r-10,1,…,r−1 (khởi tạo giá trị 000) và một con trỏ lệnh PC (bắt đầu từ 000). Chương trình gồm nnn lệnh, đánh số 0,…,n−10, \dots, n-10,…,n−1 theo thứ tự, mỗi lệnh trên một dòng thuộc một trong các dạng sau (d, s, s1, s2 là chỉ số thanh ghi; k là hằng số nguyên):

    • LOADK d k: rd←kr_d \gets krd​←k.
    • MOVE d s: rd←rsr_d \gets r_srd​←rs​.
    • ADD d s1 s2 / SUB d s1 s2 / MUL d s1 s2: rd←rs1 op rs2r_d \gets r_{s1} \ \text{op} \ r_{s2}rd​←rs1​ op rs2​.
    • DIV d s1 s2: rd←rs1÷rs2r_d \gets r_{s1} \div r_{s2}rd​←rs1​÷rs2​ (chia lấy phần nguyên, làm tròn về 0; đảm bảo rs2≠0r_{s2} \ne 0rs2​=0 khi lệnh này thực thi).
    • JMP off: PC được cộng thêm off (số nguyên, có thể âm) — tức PC ←\gets← PC +++ off — rồi tiếp tục (không cộng thêm 1 nữa).
    • JZ r off: nếu rr=0r_r = 0rr​=0 thì PC ←\gets← PC +++ off, ngược lại PC ←\gets← PC +1+ 1+1.
    • PRINT r: in ra giá trị hiện tại của rrr_rrr​ trên một dòng, rồi PC ←\gets← PC +1+ 1+1.
    • HALT: dừng chương trình ngay lập tức.

    Với các lệnh không phải JMP/JZ/HALT, sau khi thực thi PC tự động tăng thêm 111. Chương trình dừng khi gặp HALT, hoặc khi PC nằm ngoài khoảng [0,n)[0, n)[0,n). Dữ liệu vào đảm bảo chương trình luôn dừng.

    Ví dụ: chương trình LOADK 0 0, LOADK 1 5, LOADK 2 1, JZ 1 4, ADD 0 0 1, SUB 1 1 2, JMP -3, PRINT 0, HALT tính tổng 1+2+3+4+51+2+3+4+51+2+3+4+5 và in ra 15.

    • Định dạng đầu vào:
      • Dòng đầu tiên chứa hai số nguyên nnn và rrr (1≤n≤10001 \le n \le 10001≤n≤1000, 1≤r≤1001 \le r \le 1001≤r≤100) — số lệnh và số thanh ghi.
      • nnn dòng tiếp theo, mỗi dòng một lệnh đúng cú pháp mô tả ở trên (các tham số cách nhau bởi khoảng trắng, không có dấu phẩy).
    • Định dạng đầu ra:

      In ra, mỗi dòng một giá trị nguyên, kết quả của các lệnh PRINT theo đúng thứ tự được thực thi. Nếu không có lệnh PRINT nào được thực thi, không in gì.

    Ví dụ:

    Đầu vào:

    9 3
    LOADK 0 0
    LOADK 1 5
    LOADK 2 1
    JZ 1 4
    ADD 0 0 1
    SUB 1 1 2
    JMP -3
    PRINT 0
    HALT

    Đầu ra:

    15
    

    Đầu vào:

    4 3
    LOADK 0 3
    LOADK 1 4
    ADD 2 0 1
    PRINT 2

    Đầu ra:

    7
    

    Đang tải editor...