Le problème concerne Ubuntu pour Windows (sous-système Windows pour Linux). Il ne prend en charge que le syscall
64 bits interface et non le x86 32 bits int 0x80
mécanisme d'appel système.
En plus de ne pas pouvoir utiliser int 0x80
(compatibilité 32 bits) dans les binaires 64 bits, Ubuntu sur Windows (WSL) ne prend pas non plus en charge l'exécution d'exécutables 32 bits.
Vous devez convertir en utilisant int 0x80
à syscall
. Ce n'est pas difficile. Un ensemble différent de registres est utilisé pour un syscall
et les numéros d'appel système sont différents de leurs homologues 32 bits. Le blog de Ryan Chapman contient des informations sur le syscall
l'interface, les appels système et leurs paramètres. Sys_write
et Sys_exit
sont définis de cette manière :
%rax System call %rdi %rsi %rdx %r10 %r8 %r9 ---------------------------------------------------------------------------------- 0 sys_read unsigned int fd char *buf size_t count 1 sys_write unsigned int fd const char *buf size_t count 60 sys_exit int error_code
Utilisation de syscall
clobbers aussi RCX et le R11 registres. Ils sont considérés comme volatils. Ne vous fiez pas à la même valeur après le syscall
.
Votre code pourrait être modifié pour être :
section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
mov edx,len ;message length
mov rsi,msg ;message to write
mov edi,1 ;file descriptor (stdout)
mov eax,edi ;system call number (sys_write)
syscall ;call kernel
xor edi, edi ;Return value = 0
mov eax,60 ;system call number (sys_exit)
syscall ;call kernel
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string
Remarque :en code 64 bits si la destination registre d'une instruction est de 32 bits (comme EAX , EBX , EDI , ESI etc) le processeur zéro étend le résultat dans les 32 bits supérieurs du registre 64 bits. mov edi,1
a le même effet que mov rdi,1
.
Cette réponse n'est pas une introduction à l'écriture de code 64 bits, uniquement à l'utilisation du syscall
interface. Si vous êtes intéressé par les nuances de l'écriture de code qui appelle le C et conforme à l'ABI System V 64 bits, il existe des didacticiels raisonnables pour vous aider à démarrer, comme le didacticiel NASM de Ray Toal. Il discute de l'alignement de la pile, de la zone rouge, de l'utilisation des registres et d'un aperçu de base de la convention d'appel System V 64 bits.
Comme déjà souligné dans les commentaires de Ross Ridge, n'utilisez pas l'appel 32 bits des fonctions du noyau lorsque vous compilez 64 bits.
Compilez pour 32 bits ou "traduisez" le code en appels système 64 bits. Voici à quoi cela pourrait ressembler :
section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
mov rdx,len ;message length
mov rsi,msg ;message to write
mov rdi,1 ;file descriptor (stdout)
mov rax,1 ;system call number (sys_write)
syscall ;call kernel
mov rax,60 ;system call number (sys_exit)
mov rdi,0 ;add this to output error code 0(to indicate program terminated without errors)
syscall ;call kernel
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string