我有这个清单:
list db ' ETA'
我有一个变量索引,包含' 010' (二进制2)我想使用索引(代表2)将2个位置索引到列表中。我有si指向列表但是当我尝试这个时:
mov al,[si+index]
它索引到错误的值,因为我认为它认为索引代表十六进制数(16)而不是二进制数(2)。我想这是因为我插入了' 2'而不是'索引'并且包含了' T'这就是我想要的。这是发生了什么?我该如何避免呢?
答案 0 :(得分:3)
通过演示和价值来了解我的意思:
mov ax,12345 ; load register "ax" with value 12345
现在ax
中的内容是什么?一个值。值,人类通常以十进制格式显示为12345
。但它也是相同的值,可以以十六进制格式打印为0x3039
,或者以二进制格式打印为0011 0000 0011 1001
。或者它可以打印为两个字符长的ASCII字符串,显示为"90"
(字0x3039
以字节为单位:0x39 0x30
在little-endian系统上,0x39
等于char {{1 },'9'
等于ASCII编码中的char 0x30
。当显示为RGB颜色像素时,它将是非常暗的黄色(如果R = 0x39,G = 0x30,B = 0x00)。当作为声音播放时,人类可能听不到声音(太短而无法形成样本数据)。
ax值的这些“演示”都不是计算机“看到”它的方式。计算机具有16个单元/位(电线类型)的不同电流水平,分配为CPU的“ax”。
实际上,对于大多数指令,它甚至不知道我们将特定单元(位)与特定的二次幂值相关联(即二进制中的1001是1 * 2 3 + 0 * 2 2 + 0 * 2 1 + 1 * 2 0 = 9(十进制)。 '0'
指令将从“ax”和“bx”中取出成对的特定单元格,将它(以“add”方式)与临时助手进位标志混合在一起,并将得到的位值放回“ax”单元格中,从“位0”继续到“位15”,在标志寄存器中的进位标志中留下最终进位值。它不需要知道“bit 3”具有值8,这就是生成数字的十进制格式的代码将在以后为人类创建输出时分配它。
因此,如果add ax,bx
的值为index
,则索引还包含0b10
和2
,它们的值相同。在编写代码时如何在源代码中对其进行格式化,或者在将其显示到计算机屏幕时如何对其进行格式化 - 这取决于您,大多数汇编程序支持在源代码中进行各种可能的值格式化,并且您可以编写代码以任何方式显示值。
在您的问题0x02
看起来完全不同的问题,您正在尝试使用汇编程序中的“变量”,但这不是这些工作的方式。 [si+index]
很可能会进入内存,因此普通汇编程序(NASM)中的index
将加载内存地址的“ax”,而不是索引中的值。要加载内存内容,您应该写mov ax,index
。不幸的是,在MASM中,编译器使用伪变量,将mov ax,[index]
自动转换为mov ax,index
,使所有内容混乱。但是在mov ax,[index]
的情况下,它将按预期使用地址偏移量,因为没有能够执行[si+index]
寻址的指令模式。
所以我猜你正在使用MASM,你对它的“可变”怪癖魔术感到困惑。而是阅读英特尔文档,指导参考指南,并了解可能对指令做什么。
要解决您的问题,请先将index的值加载到某个寄存器中,例如:
[si+[index]]
顺便说一句,在调试器中运行时,您的问题必须明显,您应该将调试器中的指令看作mov bx,[index] ; bx = 2
mov al,[si+bx]
而不是mov al,ds:[si+0xSOME_ADDRESS]
。当某些东西没有按预期工作时,要注意调试器显示的每个细节(并强制它显示相关的一切......指令访问内存吗?在内存窗口中查看它的内容,如果有你期望的那样与堆栈值相同。当然还有寄存器中的值......