La tâche est simple: écrire un programme qui se branche différemment en x86 (32 bits) et x86-64 (64 bits) en utilisant uniquement des caractères ASCII visibles imprimables 0x21 ... 0x7e (espace et del ne sont pas autorisés) dans le code machine .
- L'assemblage conditionnel n'est pas autorisé.
- L'utilisation d'appels API n'est pas autorisée.
- L'utilisation du code en mode noyau (anneau 0) n'est pas autorisée.
- Le code doit s'exécuter sans provoquer d'exceptions dans IA-32 et x86-64 sous Linux ou dans un autre système d'exploitation en mode protégé.
- Le fonctionnement ne doit pas dépendre des paramètres de ligne de commande.
- Toutes les instructions doivent être codées en code machine en utilisant uniquement des caractères ASCII dans la plage 0x21 ... 0x7e (33 ... 126 décimal). Donc par exemple.
cpuid
est hors limites (c'est0f a2
), sauf si vous utilisez du code auto-modifiable. - Le même code binaire doit s'exécuter en x86 et x86-64, mais comme les en-têtes de fichiers (ELF / ELF64 / etc.) Peuvent être différents, vous devrez peut-être l'assembler et le lier à nouveau. Cependant, le code binaire ne doit pas changer.
- Les solutions devraient fonctionner sur tous les processeurs entre i386 ... Core i7, mais je suis également intéressé par des solutions plus limitées.
- Le code doit se ramifier en x86 32 bits mais pas en x86-64, ou vice versa, mais l'utilisation de sauts conditionnels n'est pas une exigence (un saut indirect ou un appel est également accepté). L'adresse cible de la branche doit être telle qu'il y ait de l'espace pour du code, au moins 2 octets d'espace dans lequel
jmp rel8
s'insère un court saut ( ).
La réponse gagnante est celle qui utilise le moins d'octets dans le code machine. Les octets dans l'en-tête du fichier (ELF / ELF64 par exemple) ne sont pas comptés et les octets de code après la branche (à des fins de test, etc.) ne sont pas comptés non plus.
Veuillez présenter votre réponse en ASCII, en octets hexadécimaux et en code commenté.
Ma solution, 39 octets:
ASCII: fhotfhatfhitfhutfhotfhatfhitfhut_H3<$t!
hexadécimal: 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
.
Code:
; 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