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] Máy ảo thanh ghi với nhãn và rẽ nhánh

    Khác với máy ảo ngăn xếp, nhiều trình biên dịch thực (ví dụ cho các kiến trúc RISC, hay Android Runtime/ART) sinh mã cho máy ảo thanh ghi (register-based virtual machine). Máy ảo có 8 thanh ghi, đặt tên R0 đến R7, mỗi thanh ghi khởi tạo giá trị 000. Bộ lệnh (các toán hạng cách nhau bởi dấu phẩy và có thể có khoảng trắng):

    • MOV Ra, src: gán giá trị của src cho thanh ghi Ra. src có thể là một hằng số nguyên hoặc tên một thanh ghi khác (ví dụ R2).
    • ADD Ra, Rb, Rc / SUB Ra, Rb, Rc / MUL Ra, Rb, Rc / DIV Ra, Rb, Rc: tính Rb op Rc rồi gán kết quả vào Ra (Ra có thể trùng với Rb hoặc Rc). DIV cho kết quả làm tròn phần nguyên về 0 (truncate toward zero, giống C/C++/Java): ví dụ (−7)÷2=−3(-7) \div 2 = -3(−7)÷2=−3.
    • PRINT Ra: in ra giá trị hiện tại của thanh ghi Ra.
    • LABEL name: đánh dấu vị trí, không làm gì khi thực thi.
    • JMP name: nhảy vô điều kiện tới LABEL name.
    • JZ Ra, name: nếu Ra bằng 000 thì nhảy tới LABEL name, ngược lại thực hiện lệnh kế tiếp.
    • JNZ Ra, name: nếu Ra khác 000 thì nhảy tới LABEL name, ngược lại thực hiện lệnh kế tiếp.
    • HALT: dừng thực thi.

    Máy ảo bắt đầu chạy từ lệnh đầu tiên; chương trình kết thúc khi gặp HALT hoặc khi con trỏ lệnh vượt quá lệnh cuối. Tên nhãn duy nhất trong toàn chương trình. Dữ liệu đảm bảo chương trình luôn kết thúc, tổng số lệnh được thực thi (tính cả các vòng lặp) không vượt quá 200000200000200000, và không có phép DIV nào chia cho 000 khi thực thi thực tế.

    Ví dụ: chương trình

    MOV R0, 3
    LABEL loop
    PRINT R0
    MOV R1, 1
    SUB R0, R0, R1
    JNZ R0, loop
    

    in ra lần lượt 3, 2, 1.

    • Định dạng đầu vào:

      Dòng đầu chứa số nguyên nnn (1≤n≤20001 \le n \le 20001≤n≤2000). nnn dòng tiếp theo là các lệnh theo bộ lệnh nêu trên, các toán hạng của một lệnh được phân tách bởi dấu phẩy (có thể kèm khoảng trắng sau dấu phẩy).

    • Định dạng đầu ra:

      Mỗi giá trị được PRINT in ra trên một dòng riêng, theo đúng thứ tự thực thi. Nếu không có PRINT nào được thực thi, không in gì.

    Ví dụ:

    Đầu vào:

    5
    MOV R0, 5
    MOV R1, 7
    ADD R2, R0, R1
    PRINT R2
    HALT
    

    Đầu ra:

    12
    

    Đầu vào:

    6
    MOV R0, 3
    LABEL loop
    PRINT R0
    MOV R1, 1
    SUB R0, R0, R1
    JNZ R0, loop
    

    Đầu ra:

    3
    2
    1
    

    Đang tải editor...