如何在x86程序集中正确索引数组

时间:2013-11-06 17:59:44

标签: assembly x86

我正在努力确保我理解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如何在'循环'指令中自动递减。

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

提前感谢您的意见。

4 个答案:

答案 0 :(得分:1)

使用SI完全没问题。 SI具有在大多数英特尔呼叫约定中成为保留寄存器的优点。此外,从历史上看,SI是少数可用作内存加载操作索引的寄存器之一;在现代的英特尔CPU中,任何寄存器都可以。

SI仍然可以使用lods指令获得一些特殊处理。

答案 1 :(得分:0)

你的程序实际上运行正常。在开头添加org $100,我设法用FASM编译它并在DosBox中运行: enter image description here

答案 2 :(得分:0)

在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(您无法更改此类操作的段寄存器)。

答案 3 :(得分:0)

可以正常使用SI。但是你可以在它的基础上使用其他几个寄存器(虽然要注意,与32位x86不同,16位x86代码限制了支持索引的寄存器集.ModRegR / M结构控制它。)

您可能需要考虑在循环之前执行add si, table并在其中mov dl, [si]。它使循环更容易让人阅读,因为游戏中的变量较小。