Nhiệm vụ rất đơn giản: viết chương trình phân nhánh khác nhau theo x86 (32 bit) và x86-64 (64 bit) chỉ sử dụng các ký tự ASCII hiển thị có thể in 0x21 ... 0x7e (không được phép dấu cách và del) trong mã máy .
- Lắp ráp có điều kiện không được phép.
- Sử dụng các lệnh gọi API không được phép.
- Không được phép sử dụng mã chế độ kernel (ring 0).
- Mã phải chạy mà không gây ra ngoại lệ trong cả IA-32 và x86-64 trong Linux hoặc trong một số HĐH chế độ được bảo vệ khác.
- Các chức năng không được phụ thuộc vào các tham số dòng lệnh.
- Tất cả các hướng dẫn phải được mã hóa bằng mã máy chỉ sử dụng các ký tự ASCII trong phạm vi 0x21 ... 0x7e (33 ... 126 thập phân). Vì vậy, ví dụ.
cpuid
vượt quá giới hạn (0f a2
trừ khi), trừ khi bạn sử dụng mã tự sửa đổi. - Cùng một mã nhị phân phải chạy trong x86 và x86-64, nhưng vì các tiêu đề tệp (ELF / ELF64 / v.v.) có thể khác nhau, bạn có thể cần phải lắp ráp và liên kết lại. Tuy nhiên, mã nhị phân không được thay đổi.
- Các giải pháp nên hoạt động trên tất cả các bộ xử lý giữa i386 ... Core i7, nhưng tôi cũng quan tâm đến các giải pháp hạn chế hơn.
- Mã phải phân nhánh trong 32-bit x86 nhưng không phải trong x86-64 hoặc ngược lại, nhưng sử dụng các bước nhảy có điều kiện không phải là một yêu cầu (nhảy hoặc gọi gián tiếp cũng được chấp nhận). Địa chỉ đích của nhánh phải sao cho có không gian cho một số mã, ít nhất là 2 byte không gian trong đó một bước nhảy ngắn (
jmp rel8
) phù hợp.
Câu trả lời chiến thắng là câu trả lời sử dụng ít byte nhất trong mã máy. Các byte trong tiêu đề tệp (chẳng hạn ELF / ELF64) không được tính và bất kỳ byte mã nào sau nhánh (cho mục đích thử nghiệm, v.v.) cũng không được tính.
Vui lòng trình bày câu trả lời của bạn dưới dạng ASCII, dưới dạng byte thập lục phân và dưới dạng mã nhận xét.
Giải pháp của tôi, 39 byte:
ASCII: fhotfhatfhitfhutfhotfhatfhitfhut_H3<$t!
thập lục phân : 66 68 6F 74 66 68 61 74 66 68 69 74 66 68 75 74 66 68 6F 74 66 68 61 74 66 68 69 74 66 68 75 74 5F 48 33 3C 24 74 21
.
Mã số:
; can be compiled eg. with yasm.
; yasm & ld:
; yasm -f elf64 -m amd64 -g dwarf2 x86_x86_64_branch.asm -o x86_x86_64_branch.o; ld x86_x86_64_branch.o -o x86_x86_64_branch
; yasm & gcc:
; yasm -f elf64 -m amd64 -g dwarf2 x86_x86_64_branch.asm -o x86_x86_64_branch.o; gcc -o x86_x86_64_branch x86_x86_64_branch.o
section .text
global main
extern printf
main:
push word 0x746f ; 66 68 6f 74 (x86, x86-64)
push word 0x7461 ; 66 68 61 74 (x86, x86-64)
push word 0x7469 ; 66 68 69 74 (x86, x86-64)
push word 0x7475 ; 66 68 75 74 (x86, x86-64)
push word 0x746f ; 66 68 6f 74 (x86, x86-64)
push word 0x7461 ; 66 68 61 74 (x86, x86-64)
push word 0x7469 ; 66 68 69 74 (x86, x86-64)
push word 0x7475 ; 66 68 75 74 (x86, x86-64)
db 0x5f ; x86: pop edi
; x86-64: pop rdi
db 0x48, 0x33, 0x3c, 0x24
; x86:
; 48 dec eax
; 33 3c 24 xor edi,[esp]
; x86-64:
; 48 33 3c 24 xor rdi,[rsp]
jz @bits_64 ; 0x74 0x21
; branch only if running in 64-bit mode.
; the code golf part ends here, 39 bytes so far.
; the rest is for testing only, and does not affect the answer.
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
jmp @bits_32
@bits_64:
db 0x55 ; push rbp
db 0x48, 0x89, 0xe5 ; mov rbp,rsp
db 0x48, 0x8d, 0x3c, 0x25 ; lea rdi,
dd printf_msg ; [printf_msg]
xor eax,eax
mov esi,64
call printf
db 0x5d ; pop rbp
NR_exit equ 60
xor edi,edi
mov eax,NR_exit ; number of syscall (60)
syscall
@bits_32:
lea edi,[printf_msg]
mov esi,32
call printf
mov eax,NR_exit
int 0x80
section .data
printf_msg: db "running in %d-bit system", 0x0a, 0