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ị 0. 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.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 0 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 0 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á 200000, và không có phép DIV nào chia cho 0 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.
Dòng đầu chứa số nguyên n (1≤n≤2000). n 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).
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...