NASM汇编程序-如何确保功能标签不会再执行一次? [英] NASM assembler - How to make sure the function label isn't executed one extra time?

查看:111
本文介绍了NASM汇编程序-如何确保功能标签不会再执行一次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Hello I am tinkering around with assembly level programming. I have the following code

    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从堆栈中弹出地址,然后将其指向调用者并再次执行标签.

I have a label for printing the contents of al, which is working as expected (prints H). But also after the function returns, the same label is executed again and prints an extra H. This is again understandable since ret popped the address from the stack which pointed it back to the caller and the label executed again.

现在我的问题是,如何避免这种情况?我不能像实际功能那样仅使用标签而不将其打印两次吗?我不想执行可能会改变程序的额外执行.

Now my question is, how to avoid such circumstances? Can't I just use a label like an actual function without it printing it twice? I don't want extra executions which might alter my program.

推荐答案

CPU看不到您的标签,它从一条指令到另一条指令.

The CPU does not see your labels, it goes from instruction to instruction.

除非当前指令是某种类型的跳转(callret也是某种类型的跳转)-CPU完成当前指令后,它将转到下一条指令.

Unless the current instruction is some kind of jump (call and ret are also some kind of jumps) - after the CPU is done with current instruction, it will go to the next one, following it.

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

When you do call my_function, it will execute all instructions inside the function, then upon executing ret it will return back on next instruction after the call.

然后下一条指令再次是my_function的第一条指令,第二次执行...在第二次点击ret之后,它实际上会迷失在谁知道的地方(ret会取值)在堆栈的顶部,并将其用作下一条指令的地址,因此无论第二次ret发生时堆栈中的内容是什么,现在您的代码都在运行……)

And the next instruction is the first instruction of the my_function again, doing it second time... After hitting ret second time it will actually get lost who-knows-where (the ret will take value at top of the stack and use it as address of next instruction, so whatever was in stack at the time of second ret happening, there's your code now running wild...)

汇编源不仅是一组指令,还需要将它们放置在内存中,并通过将一条指令依次放置来控制代码流. CPU会像编写它们一样逐行依次执行它们(除非使用某种跳转来更改代码流,然后才可以跳过源代码的多行).

The assembly source is not just group of instructions, but you are also positioning them in memory, and controlling the code flow, by placing one instruction after another. The CPU will execute them sequentially, line after line, just like you wrote them (except when you change the code flow by using some kind of jump, then you can jump over several lines of source).

因此,如果您想在main完成后使CPU停止运行,并且正在创建引导加载程序,即没有任何要返回的内容(没有操作系统,或类似的东西),则将在以下位置创建死端主循环通过无限循环结束,例如:

So if you want the CPU to stop after your main is "finished", and you are creating bootloader, i.e. there's nothing to return to (no OS, or something like that), you will create dead-end at end of main by infinite loop like:

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

主端"紧接在call my_function之后. "my_function"本身必须在"main"之外定义,例如在此无限循环停止器之后.

And that "end of main" is right after the call my_function. "my_function" itself must be defined outside of "main", for example after this infinite loop stopper.

也许您错过了jmp $的含义,以及它在源代码中的用途是什么.在这种情况下,$符号表示汇编程序当前指令/行的地址",因此jmp $可以转换为跳转至同一行",这意味着它是一个无限循环,CPU将永远不会执行除此jmp $指令外的其他所有内容(除非设置为处理某些中断信号时,否则任何此类外部信号都将导致CPU将执行切换到特定的中断处理程序代码,就像程序员/OS在进入无穷大之前进行了配置一样)循环).

Maybe you missed what is jmp $ and what was it purpose in the source. The $ symbol in this case means for assembler "address of current instruction/line", so jmp $ can be translated to "jump to this same line", and that means it is an infinite loop, the CPU will never execute anything else except this jmp $ instruction (except when it was set to handle some interrupt signals, then any such external signal will cause CPU to switch execution to the particular interrupt handler code, as the programmer/OS did configured it before entering the infinite loop).

另一个想法:您可能需要检查 https://schweigi.github.io/assembler -simulator/,然后多次遍历"该示例,以查看CPU如何看不到源,而只能看到机器代码字节(在右侧以内存"的形式可见),以及它们如何从源代码中分离出来.接下来的说明,IP的变化方式,等等...

One more idea: you may want to check https://schweigi.github.io/assembler-simulator/ and "step" over the example few times to see how CPU doesn't see the source, but only the machine code bytes (visible on right side as "memory"), and how it goes from one instruction to next, how IP is changing, etc...

这篇关于NASM汇编程序-如何确保功能标签不会再执行一次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆