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 ngăn xếp với nhãn và lệnh nhảy

    Để dịch các cấu trúc điều khiển như if, while sang bytecode, trình biên dịch cần các lệnh nhãn (label) và nhảy (jump). Mở rộng máy ảo ngăn xếp với bộ lệnh:

    • PUSH x: đẩy số nguyên xxx vào ngăn xếp.
    • ADD, SUB, MUL, DIV: như bài toán máy ảo cơ bản (bbb là đỉnh, aaa là phần tử dưới; DIV làm tròn phần nguyên về 0).
    • DUP: nhân đôi phần tử ở đỉnh ngăn xếp (không lấy ra).
    • POP: bỏ phần tử ở đỉnh ngăn xếp.
    • PRINT: in ra giá trị đỉnh ngăn xếp (không lấy ra).
    • LABEL name: đánh dấu vị trí này bằng tên name — bản thân lệnh này không làm gì khi thực thi.
    • JMP name: nhảy vô điều kiện tới vị trí lệnh LABEL name.
    • JZ name: lấy ra phần tử ở đỉnh ngăn xếp; nếu giá trị đó bằng 0 thì nhảy tới LABEL name, ngược lại thực hiện lệnh kế tiếp bình thường.
    • JNZ name: lấy ra phần tử ở đỉnh ngăn xếp; nếu giá trị đó khác 0 thì nhảy tới LABEL name, ngược lại thực hiện lệnh kế tiếp bình thường.
    • HALT: dừng thực thi ngay lập tức.

    Máy ảo bắt đầu thực thi từ lệnh đầu tiên của chương trình. Chương trình kết thúc khi gặp HALT hoặc khi con trỏ lệnh vượt quá dòng lệnh cuối cùng. Mỗi tên nhãn trong chương trình là duy nhất. Dữ liệu đảm bảo chương trình luôn kết thúc (không lặp vô hạn) và không xảy ra thiếu hụt ngăn xếp.

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

    PUSH 3
    LABEL loop
    DUP
    PRINT
    PUSH 1
    SUB
    DUP
    JNZ loop
    POP
    

    in ra lần lượt 3, 2, 1 — một vòng lặp đếm ngược in giá trị hiện tại rồi giảm 1, lặp lại khi giá trị còn khác 0.

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

      Dòng đầu chứa số nguyên nnn (1≤n≤10001 \le n \le 10001≤n≤1000). nnn dòng tiếp theo là các lệnh trong bộ lệnh nêu trên. Tổng số lệnh thực thi (kể cả lặp qua nhãn nhiều lần) không vượt quá 200000200000200000.

    • Đị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:

    8
    PUSH 0
    JZ skip
    PUSH 99
    PRINT
    LABEL skip
    PUSH 1
    PRINT
    HALT
    

    Đầu ra:

    1
    

    Đầu vào:

    9
    PUSH 3
    LABEL loop
    DUP
    PRINT
    PUSH 1
    SUB
    DUP
    JNZ loop
    POP
    

    Đầu ra:

    3
    2
    1
    

    Đang tải editor...