Assembly ASM-8086-使用寄存器和变量

Assembly ASM-8086-使用寄存器和变量,assembly,x86-16,Assembly,X86 16,我开始熟悉asm编程,但我觉得我缺少了一些关于使用寄存器存储变量的内容。 我遇到的问题是,由于内部原因,某些指令会修改其他寄存器。在某些情况下,我使用这些寄存器来存储应用程序逻辑。 如何使用寄存器有什么黄金法则吗 例如:以下代码更改dx寄存器并清除当前变量 mov ax, 04h mov bx, 02h mul bx mov ax,04h mov bx,02h mul bx 我不想也不想声明我希望dx寄存器被删除。这里发生了什么?像mul这样计算函数的指令需要一个寄存器来存储函数的结果。DX主要

我开始熟悉asm编程,但我觉得我缺少了一些关于使用寄存器存储变量的内容。 我遇到的问题是,由于内部原因,某些指令会修改其他寄存器。在某些情况下,我使用这些寄存器来存储应用程序逻辑。 如何使用寄存器有什么黄金法则吗

例如:以下代码更改dx寄存器并清除当前变量

mov ax, 04h mov bx, 02h mul bx mov ax,04h mov bx,02h mul bx
我不想也不想声明我希望dx寄存器被删除。这里发生了什么?

像mul这样计算函数的指令需要一个寄存器来存储函数的结果。DX主要用于此目的

您将无法将所有变量存储在寄存器中。您还需要使用堆和堆栈来存储变量

堆栈对于临时存储变量特别有用。您的代码通常如下所示:

// some variable is in ax
// needing the register for something else now, pushing current variable to the stack

push ax

// put some new value into ax
// ... do some computations with it ...
// now we need the old value back in ax

pop ax

像mul这样计算函数的指令需要一个寄存器来存储函数的结果。DX主要用于此目的

您将无法将所有变量存储在寄存器中。您还需要使用堆和堆栈来存储变量

堆栈对于临时存储变量特别有用。您的代码通常如下所示:

// some variable is in ax
// needing the register for something else now, pushing current variable to the stack

push ax

// put some new value into ax
// ... do some computations with it ...
// now we need the old value back in ax

pop ax

欢迎使用汇编语言编程。简单的回答是选择最常被操纵的值。这是规则编译器用于 寄存器分配。他们用启发式值对用法进行数字评分,然后将最好的分数放入寄存器中,直到没有更多的分数为止

在8086汇编程序中,寄存器的数量非常少,而且许多寄存器都有特殊用途。您发现了一个:mul和div隐式使用ax和dx。只要将mul指令想象成
mul-dx:ax,操作数
,您就会看到发生了什么。这会让你的生活变得更艰难,但是对于装配级别,架构设计师并不关心。他试图使硬件实现小型化和快速化

学习使用32位操作数的x86汇编将使您在这方面的工作变得更轻松,因为许多特殊用途都消失了。例如,有两个操作数
mul
指令采用目标寄存器和源,就像
add
一样

经验法则:

  • 将变量放入寄存器的循环体中。对于嵌套循环,它是最里面的,然后向外工作

  • 对于需要特殊用途的计算:乘法和除法(隐式使用ax和dx作为操作数)、可变移位计数(需要cx)、地址计算(需要bx、si或di)等,请尝试在上一次计算期间将所需数字安排在必要的寄存器中,而不是添加额外的mov。这称为寄存器定位

  • 查看由好的编译器生成的程序集,了解新的思维方式。不过,许多人多年的专家都在研究他们使用的策略。你可以向他们学习


欢迎使用汇编语言编程。简单的回答是选择最常被操纵的值。这是规则编译器用于 寄存器分配。他们用启发式值对用法进行数字评分,然后将最好的分数放入寄存器中,直到没有更多的分数为止

在8086汇编程序中,寄存器的数量非常少,而且许多寄存器都有特殊用途。您发现了一个:mul和div隐式使用ax和dx。只要将mul指令想象成
mul-dx:ax,操作数
,您就会看到发生了什么。这会让你的生活变得更艰难,但是对于装配级别,架构设计师并不关心。他试图使硬件实现小型化和快速化

学习使用32位操作数的x86汇编将使您在这方面的工作变得更轻松,因为许多特殊用途都消失了。例如,有两个操作数
mul
指令采用目标寄存器和源,就像
add
一样

经验法则:

  • 将变量放入寄存器的循环体中。对于嵌套循环,它是最里面的,然后向外工作

  • 对于需要特殊用途的计算:乘法和除法(隐式使用ax和dx作为操作数)、可变移位计数(需要cx)、地址计算(需要bx、si或di)等,请尝试在上一次计算期间将所需数字安排在必要的寄存器中,而不是添加额外的mov。这称为寄存器定位

  • 查看由好的编译器生成的程序集,了解新的思维方式。不过,许多人多年的专家都在研究他们使用的策略。你可以向他们学习


事情就是这样。您必须了解所有指令(或您打算使用的指令)的功能,并在编写代码时将其考虑在内。在您显示的示例中,32位乘积的最高有效字
ax*bx
将存储在
dx
中,这在(
MUL r/m16无符号乘法(dx:ax))中说明← 斧头∗ r/m16)。
)事情就是这样。您必须了解所有指令(或您打算使用的指令)的功能,并在编写代码时将其考虑在内。在您显示的示例中,32位乘积的最高有效字
ax*bx
将存储在
dx
中,这在(
MUL r/m16无符号乘法(dx:ax))中说明← 斧头∗ r/m16)。
)我一直在使用堆栈来存储(push/pop),但我觉得它不对,因为这是一个浪费的操作。了解到这是规划代码时的一个基本关注点,有助于我解决问题;因为我没有做错什么。在那些旧的x86 16位和32位CPU上,直到Intel Pentium 3/AMD Athlon XP,push和pop指令的组合执行速度比combi慢一些