我正在努力确保我理解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如何在'循环'指令中自动递减。
我希望继续前进,我将能够通过编写有效的代码来节省资源。
提前感谢您的意见。
答案 0 :(得分:1)
使用SI
完全没问题。 SI具有在大多数英特尔呼叫约定中成为保留寄存器的优点。此外,从历史上看,SI是少数可用作内存加载操作索引的寄存器之一;在现代的英特尔CPU中,任何寄存器都可以。
SI
仍然可以使用lods
指令获得一些特殊处理。
答案 1 :(得分:0)
你的程序实际上运行正常。在开头添加org $100
,我设法用FASM编译它并在DosBox中运行:
答案 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的工作模式。
存在以下段寄存器:
您可以覆盖要使用的默认段寄存器:
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]
。它使循环更容易让人阅读,因为游戏中的变量较小。