L'attività è semplice: scrivere un programma che si ramifica in modo diverso in x86 (32 bit) e x86-64 (64 bit) utilizzando solo caratteri ASCII visibili stampabili 0x21 ... 0x7e (spazio e del non consentiti) nel codice macchina .
- L'assemblaggio condizionale non è consentito.
- L'uso delle chiamate API non è consentito.
- L'uso del codice in modalità kernel (ring 0) non è consentito.
- Il codice deve essere eseguito senza causare eccezioni sia in IA-32 sia in x86-64 in Linux o in altri sistemi operativi in modalità protetta.
- Il funzionamento non deve dipendere dai parametri della riga di comando.
- Tutte le istruzioni devono essere codificate nel codice macchina usando solo caratteri ASCII nell'intervallo 0x21 ... 0x7e (33 ... 126 decimale). Quindi ad es.
cpuid
è fuori dai limiti (è0f a2
), a meno che non si utilizzi un codice di modifica automatica. - Lo stesso codice binario deve essere eseguito in x86 e x86-64, ma poiché le intestazioni dei file (ELF / ELF64 / ecc.) Potrebbero essere diverse, potrebbe essere necessario assemblare e ricollegarlo. Tuttavia, il codice binario non deve cambiare.
- Le soluzioni dovrebbero funzionare su tutti i processori tra i386 ... Core i7, ma sono interessato anche a soluzioni più limitate.
- Il codice deve essere ramificato in x86 a 32 bit ma non in x86-64 o viceversa, ma l'utilizzo di salti condizionali non è un requisito (è accettato anche il salto o la chiamata indiretta). L'indirizzo di destinazione del ramo deve essere tale che vi sia spazio per un po 'di codice, almeno 2 byte di spazio in cui si
jmp rel8
inserisce un salto breve ( ).
La risposta vincente è quella che utilizza meno byte nel codice macchina. I byte nell'intestazione del file (ad esempio ELF / ELF64) non vengono conteggiati e non vengono conteggiati neanche i byte di codice dopo il ramo (a scopo di test ecc.).
Si prega di presentare la risposta come ASCII, come byte esadecimali e come codice commentato.
La mia soluzione, 39 byte:
ASCII: fhotfhatfhitfhutfhotfhatfhitfhut_H3<$t!
esadecimale: 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
.
Codice:
; 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