linux assembly x86 nasm windows-subsystem-for-linux

linux - El ejecutable compilado de ensamblado en Bash en Ubuntu en Windows no produce salida



assembly x86 (2)

Como ya se señaló en los comentarios de Ross Ridge, no use llamadas de 32 bits de funciones del núcleo cuando compila 64 bits.

Compile para 32 bits o "traduzca" el código en llamadas de 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

He estado buscando un tutorial para el ensamblaje, y estoy tratando de ejecutar un programa hello world. Estoy usando Bash en Ubuntu en Windows.

Aquí está la asamblea:

section .text global _start ;must be declared for linker (ld) _start: ;tells linker entry point mov edx,len ;message length mov ecx,msg ;message to write mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel mov eax,1 ;system call number (sys_exit) int 0x80 ;call kernel section .data msg db ''Hello, world!'', 0xa ;string to be printed len equ $ - msg ;length of the string

Estoy usando estos comandos para crear el ejecutable:

nasm -f elf64 hello.asm -o hello.o ld -o hello hello.o -m elf_x86_64

Y lo ejecuto usando:

./hello

Luego, el programa parece ejecutarse sin una falla o error de segmentación, pero no produce ningún resultado.

No puedo entender por qué el código no producirá una salida, pero me pregunto si usar Bash en Ubuntu en Windows tiene algo que ver con eso. ¿Por qué no produce resultados y cómo puedo solucionarlo?


El problema es con Ubuntu para Windows (Subsistema de Windows para Linux). Solo admite la interfaz syscall 64 bits y no el mecanismo de llamada al sistema x86 int 0x80 32 bits .

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 .

syscall convertir el uso de int 0x80 a syscall . No es dificil. Se utiliza un conjunto diferente de registros para una syscall al sistema 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 la interfaz syscall , 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

El uso de syscall también registra RCX y los registros R11 . Se consideran volátiles. No confíe en que tengan el mismo valor después de la syscall al 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 el código de 64 bits si el registro de destino 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 un manual para escribir código de 64 bits, solo se trata de usar la interfaz syscall . Si está interesado en los matices de escribir código que llama a la biblioteca C y se ajusta a la ABI de System V de 64 bits, existen tutoriales razonables para comenzar como el tutorial NASM de Ray Toal . Analiza la alineación de la pila, la zona roja, el uso del registro y una descripción básica de la convención de llamadas del Sistema V de 64 bits.