es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Dónde colocar las subrutinas de ensamblaje en el archivo del sector de arranque.

Tengo el siguiente sector de arranque escrito en nasm:

[org 0x7c00]

<p>my<em>print</em>function:
    mov ah, 0x0e
    int 0x10
    ret</p>

<p><em>start:
    mov al, 'A'
    call my</em>print<em>function
    call my</em>print_function</p>

<p>_boot:
    jmp $
    times 510-($-$$) db 0
    dw 0xaa55

Lo compilo con nasm -f bin boot.asm -o boot.bin y luego ejecuto qemu boot.bin, pero solo veo un carácter siendo impreso, y es el carácter basura 'U', no 'A'. Si cambio el orden de my_print_function y _start, funciona como se espera, pero la subrutina también se ejecuta una vez por sí sola sin que la llame, por lo que imprime 'A' tres veces.

Normalmente, si estuviera escribiendo en ensamblador, simplemente definiría la función my_print_function antes de la sección .text, y colocaría global _start en la sección .text, pero aquí parece que eso no hace nada. ¿Cómo puedo definir y usar esta subrutina sin que se ejecute una vez adicional solo porque la defino?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    El problema es que cuando colocas my_print_function sobre _start en el código, se ejecuta en el momento de cargar el código mismo, porque está fuera de cualquier procedimiento que solo debería ejecutarse al llamar a una función.

    Para definir y utilizar adecuadamente una subrutina en un cargador de inicio como este, debes mover la subrutina debajo de la etiqueta _start y definirla utilizando una etiqueta con dos puntos (por ejemplo, my_print_function: en lugar de solo my_print_function). Luego, puedes llamar a la subrutina con call my_print_function. Aquí está el código corregido:

    [org 0x7c00]
    
    _start:
        mov al, 'A'
        call my_print_function
        call my_print_function
    
    my_print_function:
        mov ah, 0x0e
        int 0x10
        ret
    
    _boot:
        jmp $
        times 510-($-$$) db 0
        dw 0xaa55
    

    De esta manera, la etiqueta _start se ejecuta primero, seguida de las dos llamadas a my_print_function. La etiqueta _boot solo se ejecuta si el programa cae desde _start y alcanza la instrucción jmp $.

    También ten en cuenta que no necesitas declarar la etiqueta _start como global en este caso, ya que es la primera etiqueta del archivo y se utilizará como el punto de entrada del programa de forma predeterminada.

Comments are closed.