Reputation: 629
I am trying to make sure that I understand the SI and DI registers. My background in assembly language is somewhat limited to 6502, so bear with me here.
I have a quick example of how I would go about using SI as a simple counter. I am a bit concerned that I might be misusing this register though.
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
Is this the right way to use SI? I know in 6502 assembly, you can use the X and Y registers to offset arrays / tables. However, in my studies of x86, I am starting to realize how much more there is to work with. Such as how CX is automatically decremented in the 'loop' instruction.
I am hoping that moving forward, I will be able to save resources by writing efficient code.
Thank you in advance for your input.
Upvotes: 4
Views: 8174
Reputation: 449
That's an alright use of SI
. But you could use several other registers in its base (although beware that unlike 32-bit x86, 16-bit x86 code limits the set of registers on which indexing is supported. The ModRegR/M structure governs this.)
You might want to consider doing an add si, table
before the loop and mov dl, [si]
inside it. It makes the loop slightly easier for the human to read, because there's one less variable in play.
Upvotes: 1
Reputation: 18503
On the 6502 you have two index registers (X and Y) that you can use in different ways (direct, indirect, indirect indexed, indexed indirect, ...).
On the x86 you have 4 registers that can be used as pointer registers: BX, BP, SI and DI (in 32-bit mode you can use nearly all registers)
BX and DI can be combined (Example: [BX+DI+10])
BP is typically used for storing the old stack pointer when entering a function (when using a C compiler). However there is no missuse of registers (unless you use the stack pointer for something different) when you program in assembler. You cannot do anything wrong!
But be careful: On the x86 (in 16-bit mode) you also have to care about the segment registers - this is what the 6502 does not have!
These registers are needed because you can only address 64 KiB using a 16-bit register but 8086 has an 1 MiB address space. To solve this an address is composed of a 16-bit segment and a 16-bit offset so an address is effectively not 16 but 32 bits long. The exact meaning of the first 16 bits depends on the operating mode of the CPU.
The following segment registers are present:
You can overwrite the default segment register to be used:
MOV AX,ES:[SI+100] ; Load from ES:SI+100 instead of DS:SI+100
String operations (like movsb) always access DS:SI and ES:DI (you cannot change the segment register for such operations).
Upvotes: 1
Reputation: 61361
This use of SI
is perfectly fine. SI has the benefit of being a preserved register in most Intel calling conventions. Also, historically, SI was one of the few registers that you could use as an index in a memory load operation; in a modern Intel CPU, any register would do.
SI
still gets some special treatment with the lods
instruction.
Upvotes: 2
Reputation: 7061
Your program actually works fine. Adding org $100
at the beginning, I managed to compile it with FASM and run in DosBox:
Upvotes: 1