stray significa que program español error linux assembly x86 nasm

linux - significa - stray 302 in program arduino español



Función "Hello World" sin usar C printf (3)

ACTUALIZADO

Es mi segundo día trabajando con NASM . Después de entender esto a fondo

section .programFlow global _start _start: mov edx,len mov ecx,msg mov ebx,0x1 ;select STDOUT stream mov eax,0x4 ;select SYS_WRITE call int 0x80 ;invoke SYS_WRITE mov ebx,0x0 ;select EXIT_CODE_0 mov eax,0x1 ;select SYS_EXIT call int 0x80 ;invoke SYS_EXIT section .programData msg: db "Hello World!",0xa len: equ $ - msg

Quería envolver todo esto dentro de una función de ensamblaje. Todos (o la mayoría de) los ejemplos en la web están usando extern y llamando a la función printf de C (ver el código a continuación), y no quiero eso. Quiero aprender a crear una función "Hello World" en el ensamblaje sin usar C printf (o incluso otras llamadas a funciones externas).

global _main extern _printf section .text _main: push message call _printf add esp, 4 ret section .data message: db "Hello, World", 10, 0

Actualizar

Estoy practicando ensamblar para Linux, pero como no poseo una caja Linux, estoy ejecutando mi código ensamblador aquí compile_assembly_online .


Suponiendo que quiere decir en un entorno de símbolo del sistema de Windows, escribiendo a salida estándar:

Como estos proporcionan una versión virtualizada del antiguo entorno de DOS, creo que puede usar las antiguas interrupciones de DOS para ello:

int 21, la función 9 puede dar salida a una cadena: Establezca AH en 9, DS: DX en una cadena terminada en $ y desencadenar la interrupción.

int 21, la función 2 puede generar un único carácter, por lo que puede usarlo repetidamente si necesita generar $ (o no quiere Ctrl + C y tal control). AH a 2, DL al código de carácter ASCII (I expect) y desencadenar la interrupción.


int 0x80 no funcionará en Windows o DOS simplemente porque es algo de Linux. Entonces eso es lo primero que tiene que cambiar.

En términos de hacerlo en Windows, en algún momento necesitará llamar a una función API de Windows, como (en este caso) WriteConsole() . Eso es pasar por alto la biblioteca C como se desee.

Utiliza el sistema operativo para hacer el trabajo pesado para obtener resultados en la "pantalla", pero es lo mismo que int 0x80 y probablemente sea necesario ya sea Linux, Windows o DOS.

Si es un DOS original, su mejor lugar para comenzar es la excelente lista de interrupciones de Ralf Brown , específicamente Int21 / Fn9 .


Quiero señalar que Nasm "sabe" ciertos nombres de sección - ".text", ".data" y ".bss" (un par de otros que aún no necesita). El líder ''.'' es obligatorio, y los nombres son sensibles a mayúsculas y minúsculas. Usar otros nombres, como lo ha hecho en su primer ejemplo, puede "funcionar", pero puede que no le brinde los "atributos" que desea. Por ejemplo, la sección .programData is going to be read-only. Since you don''t try to write to it this isn''t going to do any harm... but is going to be read-only. Since you don''t try to write to it this isn''t going to do any harm... but se supone que la sección .data` puede escribirse.

Intentar aprender asm para Linux sin poder probarlo debe ser difícil. Tal vez ese sitio en línea es suficiente para ti. Hay una cosa llamada "andlinux" (creo) que te permitirá ejecutar programas de Linux en Windows. O podría ejecutar Linux en una "máquina virtual". O puede crear una partición en una de sus muchas unidades de repuesto e instalar Linux.

Para DOS, hay DosBox ... o puede instalar "DOS real" en una de esas particiones adicionales. Desde allí, puede escribir "directo a la pantalla" en B800h: xxxx. (un byte para "personaje" y el siguiente para "color"). Si desea hacer esto "sin ayuda del SO", puede ser lo que desee. En un SO de modo protegido, olvídalo. ¡Están protegidos de los Estados Unidos!

Tal vez solo quiera saber cómo escribir una subrutina, en general. Podríamos escribir una subrutina con "msg" y "len" codificados en ella, no muy flexibles. O podríamos escribir una subrutina que tome dos parámetros, ya sea en los registros o en la pila. O podríamos escribir una subrutina que espera una cadena terminada en cero (printf hace, sys_write no) y calcular la longitud para poner en edx . Si eso es lo que necesita ayuda, nos hemos distraído hablando de int 80h vs int 21h vs WriteFile . Es posible que deba preguntar de nuevo ...

EDITAR: Bien, una subrutina. La parte no obvia de esto es que call pone la dirección de retorno (la dirección de la instrucción justo después de la llamada) en la pila, y ret obtiene la dirección para regresar a la pila, por lo que no queremos modificar dónde ss:sp puntos ss:sp en el medio. Podemos cambiarlo, pero tenemos que volver a colocarlo donde estaba antes de llegar al ret .

; purpose: to demonstrate a subroutine ; assemble with: nasm -f bin -o myfile.com myfile.asm ; (for DOS) ; Nasm defaults to 16-bit code in "-f bin" mode ; but it won''t hurt to make it clear bits 16 ; this does not "cause" our code to be loaded ; at 100h (256 decimal), but informs Nasm that ; this is where DOS will load a .com file ; (needed to calculate the address of "msg", etc.) org 100h ; we can put our data after the code ; or we can jump over it ; we do not want to execute it! ; this will cause Nasm to move it after the code section .data msg db "Hello, World!", 13, 10, "$" msg2 db "Goodbye cruel world!", 13, 10, "$" section .text ; execution starts here mov dx, msg ; address/offset of msg call myprint ; "ret" comes back here ; no point in a subroutine if we''re only going to do it once mov dx, msg2 call myprint ; when we get back, do something intelligent exit: mov ah. 4Ch ; DOS''s exit subfunction int 21h ; --------------------------------------- ; subroutines go here, after the exit ; we don''t want to "fall through" into ''em! myprint: ; expects: address of a $-terminated string in dx ; returns: nothing push ax ; don''t really need to do this mov ah, 9 ; DOS''s print subfunction int 21h ; do it pop ax ; restore caller''s ax - and our stack! ret ; end of subroutine

Eso no se ha probado, pero está sujeto a errores tipográficos y lógicos estúpidos, "debería" funcionar. Podemos hacerlo más complicado: pasar el parámetro en la pila en lugar de simplemente en dx . Podemos proporcionar un ejemplo para Linux (la misma idea general). Sugiero tomarlo en pequeños pasos ...