gpt4 book ai didi

assembly - NASM 汇编器 - 如何确保函数标签不会被额外执行一次?

转载 作者:行者123 更新时间:2023-12-03 06:29:33 27 4
gpt4 key购买 nike

您好,我正在修改汇编级编程。我有以下代码

    mov al, 'H'
call my_function

my_function:
mov ah,0x0e ; BIOS print-character
int 0x10
ret

jmp $ ; infinite loop because there's no OS to exit to

times 510-($-$$) db 0
dw 0xaa55 ; boot sector signature

我有一个用于打印 al 内容的标签,它按预期工作(打印 H)。而且在函数返回后,相同的标签会再次执行并打印额外的 H。这也是可以理解的,因为 ret 从堆栈中弹出地址,将其指向调用者并再次执行标签。

现在我的问题是,如何避免这种情况?我不能像实际函数一样使用标签而不打印两次吗?我不想要可能改变我的程序的额外执行。

最佳答案

CPU 不会看到你的标签,它会从一条指令转到另一条指令。

除非当前指令是某种跳转(callret 也是某种跳转) - CPU 处理完当前指令后,它将继续执行到下一个,跟随它。

当您call my_function时,它将执行函数内的所有指令,然后在执行ret时,它将返回call<之后的下一条指令.

下一条指令又是my_function的第一条指令,第二次执行...第二次点击ret后,谁知道它实际上会丢失-where(ret 将获取堆栈顶部的值并将其用作下一条指令的地址,因此无论发生第二个 ret 时堆栈中的内容,您的代码现在正在疯狂运行...)

汇编源代码不仅仅是一组指令,而且您还可以将它们定位在内存中,并通过将一条指令放置在另一条指令中来控制代码流。 CPU 将按顺序逐行执行它们,就像您编写它们一样(除非您通过使用某种跳转来更改代码流程,然后您可以跳过几行源代码)。

因此,如果您希望 CPU 在您的 main “完成”后停止,并且您正在创建引导加载程序,即没有任何可返回的内容(没有操作系统或类似的东西),您将通过无限循环在 main 末尾创建死胡同,例如:

dead_end_loop:
pause ; give CPU hint this is idling loop
; so it will save power by switching off some circuitry
jmp dead_end_loop

“main 结束”就在调用 my_function 之后。 “my_function”本身必须在“main”之外定义,例如在此无限循环停止程序之后。

<小时/>

也许您错过了jmp $ 是什么以及它在源代码中的用途。这种情况下的 $ 符号对于汇编器来说意味着“当前指令/行的地址”,因此 jmp $ 可以翻译为“跳转到同一行”,这意味着它是一个无限循环,除了这个jmp $指令之外,CPU永远不会执行任何其他指令(除非它被设置为处理某些中断信号,那么任何此类外部信号都会导致CPU将执行切换到特定的中断处理程序代码,因为程序员/操作系统在进入无限循环之前对其进行了配置)。

<小时/>

还有一个想法:您可能需要检查https://schweigi.github.io/assembler-simulator/并“单步”几次示例,看看 CPU 如何看不到源代码,而只看到机器代码字节(在右侧显示为“内存”),以及它如何从一条指令到下一条指令,如何IP正在改变,等等...

关于assembly - NASM 汇编器 - 如何确保函数标签不会被额外执行一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48307937/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com