Завдання проста: написати програму, яка розгалужується по-різному на x86 (32-розрядні) та x86-64 (64-бітні), використовуючи лише видимі видимі символи ASCII 0x21 ... 0x7e (пробіл і del не заборонено) в машинному коді .
- Умовна збірка заборонена.
- Використання дзвінків API не дозволено.
- Використання коду в режимі ядра (дзвінок 0) заборонено.
- Код повинен запускатися, не спричиняючи винятків як в IA-32, так і в x86-64 в Linux або в інших захищених режимах ОС.
- Функціонування не повинно залежати від параметрів командного рядка.
- Усі інструкції повинні бути закодовані в машинному коді, використовуючи лише символи ASCII в діапазоні 0x21 ... 0x7e (33 ... 126 десятків). Так, наприклад.
cpuid
знаходиться поза межами (це0f a2
), якщо ви не використовуєте код, що самозмінюється. - Один і той же двійковий код повинен працювати у x86 та x86-64, але оскільки заголовки файлів (ELF / ELF64 / тощо) можуть бути різними, вам може знадобитися зібрати та зв'язати його ще раз. Однак двійковий код не повинен змінюватися.
- Рішення повинні працювати на всіх процесорах між i386 ... Core i7, але мене цікавлять і більш обмежені рішення.
- Код повинен розгалужуватися на 32-бітний x86, але не в x86-64, або навпаки, але використання умовних стрибків не є вимогою (непрямий стрибок або виклик також приймається). Цільова адреса гілки повинна бути такою, щоб було місце для деякого коду, принаймні, 2 байти простору, у який
jmp rel8
вписується короткий стрибок ( ).
Виграшною є відповідь, яка використовує найменше байт у машинному коді. Байти в заголовку файлу (наприклад, ELF / ELF64) не враховуються, а будь-які байти коду після гілки (для цілей тестування тощо) також не враховуються.
Будь ласка, подайте свою відповідь як ASCII, у вигляді шістнадцяткових байтів та як коментований код.
Моє рішення, 39 байт:
ASCII: fhotfhatfhitfhutfhotfhatfhitfhut_H3<$t!
шестнадцатеричное: 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
.
Код:
; 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