gpt4 book ai didi

c - 在 COM 程序中保存寄存器状态

转载 作者:太空宇宙 更新时间:2023-11-04 06:24:12 25 4
gpt4 key购买 nike

我反汇编了一个简单的 DOS .COM 程序,其中有一些代码可以保存和恢复寄存器值

PUSH AX ; this is the first instruction
PUSH CX
....
POP CX
POP AX
MOV AX, 0x00 0x4C
INT 21 // call DOS interrupt 21 => END

这与 C 程序中的函数序言和结尾非常相似。但是序言是由编译器自动添加的,上面的程序是用汇编程序手动编写的,因此程序员对这段代码中的值的保存和恢复负全部责任。

我的问题是如果我无意中忘记在我的程序中保存一些寄存器会发生什么?

如果我在 HEX 编辑器中故意将这些指令替换为 NOP 会怎么样?这会导致程序崩溃吗?为什么被调用函数负责在堆栈上保存外部上下文?从我的角度来看,这应该以某种方式在调用函数时完成,以防止在我使用第 3 方库和编写糟糕的代码时出现问题,这可能会破坏我的程序执行。

最佳答案

让调用函数在调用另一个函数之前保存其所有工作寄存器的一个问题是,有时函数在其不知情的情况下被中断(即硬件中断)。例如,在 DOS 中,有一个讨厌的 54 毫秒计时器滴答声。每秒 18 次,硬件中断会将控制权从正在执行的任何代码转移到计时器滴答处理程序。这会自动发生,除非您的程序专门禁用了中断。

定时器节拍处理程序将保存所有它要使用的寄存器,完成它的工作,然后在返回之前恢复它保存的寄存器。

当然,您可以说中断处理程序很特殊,但为什么呢?即使 8086 上的寄存器很少(AX、BX、CX、DX、SI、DI、标志——我忘记了什么吗?我故意不包括段寄存器),使函数在传输之前保存其整个状态控制意味着您将使用大量不必要的堆栈空间和执行周期来保存内容,因为它们可能 会被修改。但是如果被调用函数只负责保存它使用的寄存器,并且它只使用 AX 和 CX,那么它可以只保存这两个寄存器。它使代码更小、速度更快,并且使用的堆栈空间更少。

当您开始谈论深度很多的调用层次结构时,压入 8 个寄存器与压入 2 个寄存器之间的区别很快就会加起来。

考虑 x86-64 及其 64 个通用寄存器。你真的认为一个函数应该在调用另一个函数之前强制保存所有 64 个寄存器,即使被调用的函数只使用其中两个吗?保存 64 个 64 位寄存器需要 512 字节的堆栈空间。与保存两个只需要 16 个字节的寄存器相反。

现在用汇编语言编写东西的主要目的是编写比编译器可以编写的代码更快、更小的代码。一个指导原则是不要做比你必须做的更多的工作。这意味着由您决定您的汇编语言函数正在使用哪些寄存器,并在进入时保存这些寄存器并在退出时恢复它们。

关于c - 在 COM 程序中保存寄存器状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29320735/

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