【问题标题】:Best way to simulate a call with jmp(dos assembly)使用 jmp(dos 程序集)模拟调用的最佳方法
【发布时间】:2015-01-25 04:44:13
【问题描述】:

我在 Windows 上使用平面汇编程序,并且已经用 jmp 模拟了一个调用指令,但想知道是否有更好的方法来用更少的代码来完成它?(不使用调用)

这是代码。

org 100h

mov al, 'x'

push come_back ; - simulated "call" -
jmp test_label  ; -   continued  -
come_back:     ; - end of simulated "call" -


mov al, 'y'

push come_back2 ; - simulated "call" -
jmp test_label  ; -   continued  -
come_back2:     ; - end of simulated "call" -

Looop:
jmp Looop


test_label:
mov ah, 0x0e
int 0x10
pop cx   ; - simulated "ret" -
jmp cx   ; - end of simulated "ret" 

这段代码只是向控制台显示“xy”,两个字符。

我不想使用电话,因为我不想更好地理解,有时这涉及以错误的方式做事。 我是组装新手,不知道最好的方法是什么。

【问题讨论】:

    标签: assembly dos fasm


    【解决方案1】:

    您的操作方式与处理器内部的操作方式相同。你应该使用callret 来做到这一点。每条指令都需要时间来执行。这称为循环。您拥有的指令越多,所需的周期就越多,从而需要更多的时间来执行。

    在内部,当处理器在您的代码中执行call 指令时,会发生这种情况:

    1. 处理器在调用语句之后将IP 寄存器的地址压入堆栈。
    2. 处理器将IP 寄存器的地址更改为您的调用操作码的地址。
    3. 继续执行。

    当处理器在您的代码中处理ret 指令时,会发生这种情况:

    1. 处理器将 16 位地址从堆栈中弹出,并将其放入 IP 寄存器中。
    2. 继续执行

    虽然看起来有很多步骤,但这些步骤不会消耗周期,因为它内置在 CPU 的硬件中。

    【讨论】:

    • 很好的解释,我很高兴你澄清了这一点,因为我不知道我的方式是如何没有优化的。
    • 另一个因素是返回地址缓存,它可能会不同步并导致调用变得更慢。
    【解决方案2】:

    这可能有效:

    push $+5
    jmp fn
    ; no label needed here
    

    一些汇编程序会将$ 解释为指令地址。

    这是一个无限循环:

    jmp $
    

    【讨论】:

    • 我现在意识到您可能需要在推送中添加更多字节以考虑推送的大小。玩吧!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多