为什么我们不能在程序集中使用push和pop?

时间:2013-07-06 01:52:10

标签: assembly

    mov al,12
    mov ah,00
    mov cl,0
    convertBinary:
        cmp al,0
        je printBinary

        div two
        push ax
        inc cl

        mov ah,00
        jmp convertBinary

        printBinary:
            pop ax
            mov dl,ah
            add dl,48
            mov ah,02h
            int 21h
            loop printBinary

此代码无需过程即可正常运行。当我在程序中放入相同的代码并调用它时,它会因非法指令而显示错误。有人请解释一下为什么我们不能在程序中使用那些推送和弹出。

2 个答案:

答案 0 :(得分:2)

与编译器不同,汇编程序没有整个文件的整体语法,只有单独的行。因此,汇编程序甚至不关心您“在一个过程中” - 名称convertBinaryprintBinary只是它可以计算来自jmp和{的相对地址的符号{1}}和loop说明。

因此,无论您在程序内部处于何种“上下文”状态,都应该由汇编程序发出相同的操作码(不考虑汇编程序指令来更改默认操作大小)。我假设你在运行时得到非法指令,而不是在组装程序时?

仔细检查您的代码旁边是否有任何数据正在被溢出并在运行时覆盖代码,并且您没有错过任何必要的控制流(缺少call程序结束,或者缺少退出程序的代码,例如)。

另外,请仔细检查每个对应的ret是否有push条指令。仅仅因为每条指令在代码中出现的次数相同并不意味着每个poppush的执行次数相同。

答案 1 :(得分:2)

您的代码可以在某些输入状态下正常运行,对其他人来说会很疯狂。如果它在一个程序内部变得狂野,如果它没有首先在堆栈故障上终止,它将进行一次疯狂的跳转。

作为整个程序运行(除了最后的终止调用)将避免疯狂跳转,尽管错误的输入仍会产生错误的输出。

仔细看看你的循环。它不符合你的想法。

编辑:mbratch还提出了我错过的另一个失败案例。