Estoy tratando de imprimir un solo carácter o un número usando NASM , apuntando a una arquitectura x86 GNU/Linux.
Aquí está el código que estoy usando:
section .text global _start _start: ; Linux printing preparation mov eax,4 mov ebx,1 ; Print 'A' character mov ecx,'A' ; ecx should contain the value to print mov edx,1 ; edx should contain how many characters to print int 80h ; System exit mov eax,1 mov ebx,0 int 80hSin embargo, ejecutar este código no imprime nada. ¿Qué estoy haciendo mal?
ecx debe contener un puntero al inicio de su búfer de caracteres. Por lo tanto, debe tener su búfer en la memoria. Puedes hacer lo siguiente:
; Print 'A' character mov eax, 4 ; __NR_write from asm/unistd_32.h (32-bit int 0x80 ABI) mov ebx, 1 ; stdout fileno push 'A' mov ecx, esp ; esp now points to your char mov edx, 1 ; edx should contain how many characters to print int 80h ; sys_write(1, "A", 1) ; return value in EAX = 1 (byte written), or error (-errno) add esp, 4 ; restore esp if necessary Puede mov byte [esp], 'A' o cualquier otra dirección si está bien sobrescribir lo que esté en la pila.
O puede tener una matriz de caracteres en section .rodata en lugar de almacenarla sobre la marcha.
Hacer una llamada al sistema write() con const void *buf arg siendo un número pequeño (como 'A' ) hará que devuelva -EFAULT sin imprimir nada. El núcleo tiene que verificar el puntero de todos modos, y las llamadas al sistema devuelven un error en lugar de generar SIGSEGV en punteros incorrectos.
Use strace ./my_program para rastrear las llamadas al sistema que realmente realizó, incluida la decodificación de los valores devueltos.
La llamada al sistema que está ejecutando espera que ecx contenga una dirección en la memoria. Esta puede ser una dirección literal arbitraria (es decir, en su código, "A" se traduce como la dirección 041h ), una dirección en la pila o una dirección definida por una etiqueta en el programa.
Aquí hay un ejemplo de cómo definir un byte en la memoria y escribirlo en el flujo de salida estándar de su terminal:
section .rodata ; This section contains read-only data buffer: db 'A' ; Define our single character in memory section .text global start _start: ; Prints the letter 'A', then exits mov eax, 4 ; sys_write() mov ebx, 1 ; ... to STDOUT mov ecx, buffer ; ... using the following memory address mov edx, 1 ; ... and only print one character int 80h ; SYSCALL mov eax, 1 ; Return to system mov ebx, 0 ; Exit zero, success int 80h ; SYSCALL