4

我正在努力确保我了解 SI 和 DI 寄存器。我的汇编语言背景在某种程度上仅限于 6502,所以请耐心等待。

我有一个简单的例子来说明我将如何使用 SI 作为一个简单的计数器。我有点担心我可能会滥用这个寄存器。

mov si, 0   ; set si to 0
mov cx, 5   ; set cx to 5 as we will count down to 1

do:       
   mov ah, 02h          ; setup 02h DOS character output interrupt   
   mov dl, [table + si] ; grab our table with the si offset 
   add dl, '0'          ; convert to ascii integer
   int 21h              ; call DOS service

   inc si               ; increment si
   loop do              ; repeat unto cx = 0
ret

table: db 1,2,3,4,5

---
OUTPUT:> 12345

这是使用 SI 的正确方法吗?我知道在 6502 汇编中,您可以使用 X 和 Y 寄存器来偏移数组/表。然而,在我对 x86 的研究中,我开始意识到还有很多工作要做。比如 CX 如何在 'loop' 指令中自动递减。

我希望继续前进,我将能够通过编写高效的代码来节省资源。

预先感谢您的意见。

4

4 回答 4

2

这种使用SI非常好。SI 具有在大多数英特尔调用约定中作为保留寄存器的好处。此外,从历史上看,SI 是少数可以在内存加载操作中用作索引的寄存器之一。在现代 Intel CPU 中,任何寄存器都可以。

SIlods仍然会在指令中得到一些特殊处理。

于 2013-11-06T20:04:23.420 回答
1

在 6502 上,您有两个索引寄存器(X 和 Y),您可以以不同的方式使用它们(直接、间接、间接索引、索引间接......)。

在 x86 上,您有 4 个可用作指针寄存器的寄存器:BX、BP、SI 和 DI(在 32 位模式下,您几乎可以使用所有寄存器)

BX 和 DI 可以组合(例如:[BX+DI+10])

BP 通常用于在进入函数时(使用 C 编译器时)存储旧堆栈指针。但是,当您在汇编程序中编程时,不会滥用寄存器(除非您将堆栈指针用于不同的东西)。你不能做错任何事!

但要小心:在 x86(16 位模式)上,您还必须关心段寄存器 - 这是 6502 所没有的!

这些寄存器是必需的,因为您只能使用 16 位寄存器寻址 64 KiB,但 8086 有 1 MiB 地址空间。为了解决这个问题,地址由一个 16 位段和一个 16 位偏移量组成,因此地址实际上不是 16 位而是 32 位长。前 16 位的确切含义取决于 CPU 的操作模式。

存在以下段寄存器:

  • CS: CS:IP 是指令指针
  • SS:SS:SP是堆栈指针;默认用于 SP 和 BP 指针操作
  • DS:默认用于所有其他指针操作(除了 SP 和 BP)
  • ES:附加寄存器
  • FS、GS:自 80386 以来的附加寄存器

您可以覆盖要使用的默认段寄存器:

MOV AX,ES:[SI+100] ; Load from ES:SI+100 instead of DS:SI+100

字符串操作(如 movsb)始终访问 DS:SI 和 ES:DI(您不能更改此类操作的段寄存器)。

于 2013-11-06T20:25:47.093 回答
1

您的程序实际上运行良好。在开头添加org $100,我设法用 FASM 编译它并在 DosBox 中运行: 在此处输入图像描述

于 2013-11-06T19:56:32.440 回答
1

这是一个很好的使用SI. 但是你可以在它的基础中使用其他几个寄存器(尽管要注意,与 32 位 x86 不同,16 位 x86 代码限制了支持索引的寄存器集。ModRegR/M 结构控制着这一点。)

您可能需要考虑add si, table在循环之前和mov dl, [si]内部进行。它使人类更容易阅读循环,因为游戏中的变量少了一个。

于 2018-04-02T00:08:42.020 回答