程序集 8086-从堆栈中插入和弹出寄存器不起作用

标签 assembly x86-16 qemu

我是一名初学者,出于某种原因,插入和弹出堆栈对我来说不起作用。我的引导加载程序:

org 0x7c00
bits 16
jmp main
print:
    pop bx
    mov al, [bx]
    mov ah, 0eh
    int 10h
    ret
main:
    mov bx, msg
    push bx
    call print

    cli
    hlt

    msg: db 'Hello World!', 0
    times 510 - ($-$$) db 0
    dw 0xAA55

我认为,这应该做的是推送地址 msgbx入栈然后将其检索到 bx 。然而,情况似乎并非如此。 'H'没有被打印。一个'-'而是打印出来。如果我使用 msg 就可以了作为有效地址。

编辑:正如邓肯指出的那样,call指令将返回地址压入堆栈顶部,这使得上述程序使用该返回地址进行 BIOS 中断!我现在pop返回地址为 dx然后pop进入bx ,使用 bx 的值和jmpdx完成后!

org 0x7c00
bits 16
jmp main
print:
    pop dx
    pop bx
    mov al, [bx]
    mov ah, 0eh
    int 10h
    jmp dx
main:
    mov bx, msg
    push bx
    call print

    cli
    hlt

    msg: db 'Hello World!', 0
    times 510 - ($-$$) db 0
    dw 0xAA55

最佳答案

call指令将程序计数器压入堆栈,ret从堆栈中弹出顶部值并跳转到该处。

因此,您不能通过在调用之前推送参数并在调用中弹出参数来将参数传递给函数,因为保存的 pc 会妨碍。

选项可能包括设置一个帧指针,以便您可以访问仍在堆栈上的参数,然后将它们作为返回的一部分弹出。

或者对于这么简单的事情,您可以将返回地址弹出到另一个寄存器中,而不是返回,而是跳转到它。

关于程序集 8086-从堆栈中插入和弹出寄存器不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45564831/

相关文章:

assembly - $ 在 NASM 中究竟是如何工作的?

assembly - intel x86 中的 REP stosl 相当于什么

assembly - 引导加载程序加载自身而不是内核

assembly - Assembly x86 Irvine 中的链表

c++ - GCC:错误:表达式后出现垃圾 `:0x+57f120'

assembly - CS :IP mean in assembly and how it works? 是什么意思

assembly - 如何将 8 位寄存器移动到 16 位内存位置?

linux - 如何使用 DDD 对本地 Qemu 虚拟机进行内核调试?

linux - 在kgdb中,我无法设置断点

memory - qemu 内存操作