【问题标题】:assembly language registers汇编语言寄存器
【发布时间】:2012-01-03 01:08:42
【问题描述】:

我正在学习汇编编程,但遇到了一些注册表问题。例如我遇到了这个:

mov ax, 3000
mov ds, ax
mov si, 200
mov ax, [si]
add si, 2
add ax, [si]
add si, 2
mov [si], ax
mov ax, 4c00
int 21

这段代码将 3000:200 和 3000:202 的 2 个内存段相加,并将结果放在 3000:202 上,我不明白 ds 和 si 之间的联系,因为我无法解释为什么我们做 mov ds,斧头?而且我通常不了解寄存器之间的联系...我知道它们代表什么但是...我不知道一些帮助会非常有用,谢谢

【问题讨论】:

    标签: assembly


    【解决方案1】:

    DS 是数据段寄存器 - 与所有段寄存器一样,其值乘以 16 表示 64K 内存块的基地址。

    在执行指令时,内存地址的计算方法是将段寄存器表示的基地址(默认情况下,DS寄存器用于数据)加上一个常数或寄存器指定的偏移值。

    因此,mov ax, [si] 等价于 mov ax, [ds:si],后者(使用您的寄存器值)代表 mov ax, [3000:200]。在内部,处理器将计算 (3000*16)+200 的绝对内存地址并将数据从该内存位置复制到ax。添加和保存结果时的内存访问使用类似的过程。

    你不能做mov ds, 3000 的原因仅仅是因为英特尔决定不支持将常量值移动到段寄存器中——没有可编码的指令。相反,您必须通过另一个寄存器传输值(在您的代码中使用ax)。

    您的(原始)描述不太正确 - 代码确实在 [3000:200] 和 [3000:202] 处添加了值,但结果将存储到 [3000:204](而不是 [3000: 202])。

    不要忘记:存储在像 DS(以及 CS、ES、FS 和 GS)这样的段寄存器中的值并不直接指定基地址 - 它们必须始终乘以 16 才能得到真正的基地址。

    【讨论】:

      【解决方案2】:

      Ds 是数据段寄存器。正如您提到的那样,地址是由 ds 寄存器和 si 寄存器组合而成的。在旧的 8088/86 天,在这种情况下,也许您仍然计算了您的地址 (ds

      因此,如果 ds = 3000 且 si = 200,那么我假设地址为 (3000

      ds 和 si 之间的联系是隐含的。查看 intel 的程序员参考手册,DS 段是使用 SI 或 DI 时的默认设置。 CS:ES:SS 是 SI 的替代(但不是 DI),您需要在指令/程序集中指定替代段以使用其他段之一。如何指定备用段取决于汇编器期望的语法。

      【讨论】:

        【解决方案3】:

        简而言之,

        您不能将立即值直接分配给段寄存器。这就是为什么你有那条线使用通用寄存器来为你做这项工作。

        mov ds, ax
        

        关于 DS 和 SI,您有一些说明假设 DS:SI 可以正常工作,但这里并非如此。 DS 是你的默认数据段,所以它只是假设DS:offset;在您的情况下,SI 是您的偏移量。您可以将 SI 更改为任何其他 16 位寄存器,例如 CX,它同样可以工作。做一个测试并反馈给我:P

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-03-16
          • 2018-08-26
          • 2012-01-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多