如何在x86程序集中正确索引数组
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在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如何在'循环'指令中自动递减。
我希望继续前进,我将能够通过编写有效的代码来节省资源。
提前感谢您的意见。
使用SI
非常好。 SI具有在大多数英特尔呼叫约定中成为保留寄存器的优点。此外,从历史上看,SI是少数可用作内存加载操作索引的寄存器之一;在现代的英特尔CPU中,任何寄存器都可以。
SI
仍然得到lods
指令的一些特殊待遇。
你的程序实际上工作正常。在开头添加org $100
,我设法用FASM编译它并在DosBox中运行:
在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(您无法更改此类操作的段寄存器)。
这是对SI
的好用。但是你可以在它的基础上使用其他几个寄存器(虽然要注意,与32位x86不同,16位x86代码限制了支持索引的寄存器集.ModRegR / M结构控制它。)
你可能想考虑在循环之前做一个add si, table
并在里面做mov dl, [si]
。它使循环更容易让人阅读,因为游戏中的变量少了一个。
以上是关于如何在x86程序集中正确索引数组的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Visual Studio 2017 的 x86 程序集中使用 printf?
如何在 x86(32 位)程序集中将无符号整数转换为浮点数?