El problema es con Ubuntu para Windows (Subsistema de Windows para Linux). Solo es compatible con syscall
de 64 bits interfaz y no x86 de 32 bits int 0x80
mecanismo de llamada al sistema.
Además de no poder usar int 0x80
(compatibilidad de 32 bits) en binarios de 64 bits, Ubuntu en Windows (WSL) tampoco admite la ejecución de ejecutables de 32 bits.
Necesitas convertir usando int 0x80
a syscall
. No es dificil. Se utiliza un conjunto diferente de registros para un syscall
y los números de llamada del sistema son diferentes de sus contrapartes de 32 bits. El blog de Ryan Chapman tiene información sobre el syscall
interfaz, las llamadas al sistema y sus parámetros. Sys_write
y Sys_exit
se definen de esta manera:
%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
Usando syscall
también golpea RCX y el R11 registros Se consideran volátiles. No confíe en que tengan el mismo valor después del syscall
.
Su código podría modificarse para ser:
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
Nota:en código de 64 bits si el destino registro de una instrucción es de 32 bits (como EAX , EBX , EDI , ESI etc.) el procesador cero extiende el resultado a los 32 bits superiores del registro de 64 bits. mov edi,1
tiene el mismo efecto que mov rdi,1
.
Esta respuesta no es una introducción a la escritura de código de 64 bits, solo sobre el uso de syscall
interfaz. Si está interesado en los matices de escribir código que llame a la C biblioteca, y se ajusta a la ABI del Sistema V de 64 bits, hay tutoriales razonables para que pueda comenzar, como el tutorial NASM de Ray Toal. Habla sobre la alineación de la pila, la zona roja, el uso de registros y una descripción general básica de la convención de llamadas System V de 64 bits.
Como ya se señaló en los comentarios de Ross Ridge, no utilice llamadas de 32 bits a las funciones del núcleo cuando compile 64 bits.
Compile para 32 bits o "traduzca" el código a llamadas al sistema de 64 bits. Así es como podría verse:
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