Bảng xếp hạng - Biên soạn JIT (Thấp hơn là tốt hơn)
- es1024 - 81,2 điểm (bao gồm trình biên dịch hoạt động!)
- Kieth Randall - 116 điểm
- Ell - 121 điểm
Bảng xếp hạng - Giải thích (Thấp hơn là tốt hơn)
- Martin Büttner - 706654 điểm (đâu đó khoảng 2 giờ).
- criptych - 30379 điểm (97 giây)
Nhiệm vụ của bạn, nếu bạn chọn chấp nhận nó, là viết trình thông dịch / VM mã hóa nhỏ nhất có thể. VM / trình thông dịch sử dụng kiến trúc CISC nhỏ (các thao tác có thể thay đổi kích thước), với ngôn ngữ được chỉ định bên dưới. Sau khi hoàn thành, bạn phải in giá trị của 3 thanh ghi CPU để chứng minh rằng đầu ra chính xác được in (3.126.900.366).
Trình biên dịch
Nếu bạn muốn thực hiện các bài kiểm tra của riêng mình, một trình biên dịch được đăng dưới đây. Hãy gửi bài kiểm tra của bạn với câu trả lời của bạn.
Thông số kỹ thuật "VM"
VM có 3 thanh ghi tích phân không dấu 32 bit: R0, R1, R2. Chúng được biểu diễn dưới dạng hex là 0x00, 0x01 và 0x02.
Các hoạt động sau đây phải được hỗ trợ:
Định dạng là [name] [... toán hạng ...], [mã thập lục phân] [... toán hạng được lặp lại ...]
- LOAD [thanh ghi] [giá trị 4 byte], 0x00 [thanh ghi] [giá trị 4 byte]
- PUSH [đăng ký], 0x02 [đăng ký]
- POP [đăng ký], 0x03 [đăng ký]
- THÊM [đăng ký, 1 byte] [đăng ký, 1 byte], 0x04 [đăng ký] [đăng ký]
- SUB [đăng ký, 1 byte] [đăng ký, 1 byte], 0x05 [đăng ký] [đăng ký]
- MUL [đăng ký, 1 byte] [đăng ký, 1 byte], 0x06 [đăng ký] [đăng ký]
- DIV [đăng ký, 1 byte] [đăng ký, 1 byte], 0x07 [đăng ký] [đăng ký]
- JMP [dòng mã, 4 byte], 0x08 [Số dòng mã 4 byte]
- CMP [đăng ký, 1 byte] [đăng ký, 1 byte], 0x09 [đăng ký] [đăng ký]
- BRANCHLT [dòng mã, 4 byte], 0x0a [số dòng mã 4 byte]
Một số lưu ý:
- Các hoạt động toán học ở trên cộng các giá trị của 2 thanh ghi lại với nhau, đặt đầu ra vào thanh ghi đầu tiên.
- CMP, toán tử so sánh, nên so sánh các giá trị của 2 thanh ghi và lưu trữ đầu ra trong một số cờ nội bộ (điều này có thể được thực hiện cụ thể) để sử dụng trong các hướng dẫn chi nhánh trong tương lai.
- Nếu BRUC được gọi trước CMP, trừ khi BRUCEQ được gọi, "VM" sẽ không phân nhánh.
- PUSH / POP không đáng ngạc nhiên đẩy số hoặc pop từ ngăn xếp.
- Các toán tử Jump và Branch nhảy đến một hoạt động cụ thể (dòng mã), không phải là một địa chỉ nhị phân.
- Chi nhánh hoạt động không làm so sánh. Thay vào đó, họ lấy đầu ra từ so sánh cuối cùng để thực hiện.
- Các toán tử Branch và Jump sử dụng hệ thống lập chỉ mục số dòng dựa trên số không. (Ví dụ: JMP 0 nhảy đến dòng đầu tiên)
- Tất cả các hoạt động phải được thực hiện trên các số không dấu mà tràn về 0 và không ném ngoại lệ vào tràn số nguyên.
- Chia cho số 0 là không được phép và như vậy, hành vi của chương trình không được xác định. Bạn có thể (ví dụ) ...
- Tai nạn chương trình.
- Kết thúc thực thi VM và trả về trạng thái hiện tại của nó.
- Hiển thị thông báo "ERR: Chia cho 0".
- Chấm dứt chương trình được định nghĩa là khi con trỏ lệnh đến cuối chương trình (một chương trình không trống có thể được giả định).
Đầu ra Đầu ra phải chính xác như vậy (bao gồm các dòng mới)
R0 3126900366
R1 0
R2 10000
Điểm
Điểm được tính dựa trên công thức sau:Number Of Characters * (Seconds Needed To Run / 2)
Để tránh sự khác biệt về phần cứng gây ra các thời điểm khác nhau, mỗi thử nghiệm sẽ được chạy trên máy tính của tôi (i5-4210u, ram 8GB) trong máy chủ ub Ubuntu hoặc Windows 8, vì vậy hãy cố gắng không sử dụng một số thời gian chạy điên rồ chỉ biên dịch trên Dual G5 Mac Pro với chính xác 762,66 mb RAM miễn phí.
Nếu bạn đang sử dụng thời gian chạy / ngôn ngữ chuyên biệt, vui lòng gửi một liên kết đến nó.
- Đối với các bên quan tâm, tôi đã đăng mã kiểm tra (viết bằng C #) tại đây: http://pastebin.com/WYCG5Uqu
Chương trình kiểm tra
Ý tưởng xuất phát từ đây , vì vậy chúng tôi sẽ sử dụng một phiên bản sửa đổi phần nào của chương trình của họ.
Đầu ra chính xác cho chương trình là: 3.126.900.366
Trong C:
int s, i, j;
for (s = 0, i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++)
s += (i * j) / 3;
}
Trong mã: [R0 là đại diện của s, R1 của j, R2 của i]
LOAD R0 0
LOAD R2 0 <--outer loop value
LOAD R1 0 <--inner loop value
--Begin inner loop--
PUSH R1 <--push inner loop value to the stack
MUL R1 R2 <--(i*j)
PUSH R2
LOAD R2 3
DIV R1 R2 <-- / 3
POP R2
ADD R0 R1 <-- s+=
POP R1
PUSH R2
LOAD R2 1
ADD R1 R2 <--j++
POP R2
PUSH R2
LOAD R2 10000
CMP R1 R2 <-- j < 10000
POP R2
BRANCHLT 3 <--Go back to beginning inner loop
--Drop To outer loop--
LOAD R1 1
ADD R2 R1 <--i++
LOAD R1 10000
CMP R2 R1 <-- i < 10000
LOAD R1 0 <--Reset inner loop
BRANCHLT 2
Trong nhị phân / hex:
0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x02 0x00 0x00 0x00 0x00
0x00 0x01 0x00 0x00 0x00 0x00
0x02 0x01
0x06 0x01 0x02
0x02 0x02
0x00 0x02 0x00 0x00 0x00 0x03
0x07 0x01 0x02
0x03 0x02
0x04 0x00 0x01
0x03 0x01
0x02 0x02
0x00 0x02 0x00 0x00 0x00 0x01
0x04 0x01 0x02
0x03 0x02
0x02 0x02
0x00 0x02 0x00 0x00 0x27 0x10
0x09 0x01 0x02
0x03 0x02
0x0a 0x00 0x00 0x00 0x03
0x00 0x01 0x00 0x00 0x00 0x01
0x04 0x02 0x01
0x00 0x01 0x00 0x00 0x27 0x10
0x09 0x02 0x01
0x00 0x01 0x00 0x00 0x00 0x00
0x0a 0x00 0x00 0x00 0x02
Điểm thưởng (Hiệu ứng được áp dụng nhiều lần) Ví dụ: nếu bạn đủ điều kiện cho cả ba, nó sẽ là ((ký tự * 0,50) * 0,75) * 0,90
- Giảm 50% nếu trình thông dịch thực sự là trình biên dịch JIT
- Giảm 25% nếu áp dụng bất kỳ loại vòng lặp không kiểm soát / tối ưu hóa có ý nghĩa.
- Giảm 10% nếu bạn mở rộng VM với
- BRANCHEQ [dòng mã, 4 byte] (Chi nhánh nếu bằng - opcode 0x0b)
- BRANCHGT [dòng mã, 4 byte] (Chi nhánh nếu lớn hơn - opcode 0x0c)
- BRANCHNE [dòng mã, 4 byte] (Chi nhánh nếu không bằng - opcode 0x0d)
- TẢI XUỐNG [đăng ký 1] [đăng ký 2] (di chuyển giá trị của đăng ký 2 sang đăng ký 1 - opcode 0x01).
Không được phép
- Việc biên dịch lại trường hợp thử nghiệm vào chương trình đều bị cấm. Bạn phải chấp nhận mã byte từ STDIN hoặc từ tệp (Không quan trọng).
- Trả lại đầu ra mà không chạy chương trình.
- Bất kỳ cách nào khác bạn có thể nghĩ ra để gian lận yêu cầu VM.
CMP
kiểm tra ít hơn hoặc bình đẳng? Và điều gì xảy ra với kết quả của nó?
MUL
và DIV
cũng không được xác định rõ. Họ nên được ký hoặc không dấu? Điều gì xảy ra trên tràn nhân?