访问在堆栈上生成的数组元素可能有点棘手。当访问基于堆栈的变量(即:在堆栈上定义的非静态变量,如array)时,编译器会生成相对于寄存器BP 的内存引用。您的指示:
mov ax,array[0]
会报错:
操作码和操作数的无效组合
该语法不适用于包括数组在内的堆栈变量。什么会起作用:
mov ax,[array] ; Get first int in array
mov ax,[array+2] ; Get second int in array
mov ax,[array+4] ; Get third int in array
[0] 的使用不像在 C 代码中那样在内联汇编中起作用。您必须计算数组中每个元素的字节地址,这就是为什么[array+2] 指向第二个元素,[array+4] 指向数组中的第三个元素的原因。开发人员必须根据元素的大小来缩放添加的偏移量。如果array 是char 的数组,则[array+1] 指向第二个元素,[array+2] 指向数组中的第三个元素。使用long(32 位值)数组,[array+4] 指向第二个元素,[array+8] 指向数组中的第三个元素。
您的内联程序集可能看起来像这样来访问int 数组的第三个元素:
asm{
mov ax, [array+4]
};
通常,在处理数组时,您可能想要访问多个元素,或者创建一个循环来对多个元素执行一些操作。在这种情况下,您需要考虑将数组的地址加载到像 SI1 这样的寄存器中。一旦你有了数组的地址,你就可以访问单个元素。获得数组地址后,您可以将字节偏移量添加到元素(在本例中为int)并检索该值。如果数组的地址放在SI中,那么[si+0](或[si])就是数组中第一个整数的地址。
要检索堆栈变量或全局变量的地址,您可以使用LEA 指令(加载有效地址)。以下代码使用LEA 将array 的基址(元素0)的地址放入SI。代码检索第三个整数元素 (array+4) 的值并将其放在 AX 中。然后代码将另一个变量myint 设置为AX 中的值。 C 代码然后打印该值。示例代码:
#include<stdio.h>
int main()
{
int array[10] = {1,2,3,4,5,6,7,8,9,0};
int myint;
asm{
lea si, [array]
mov ax, [si+4] ; Get third int element from the array
mov [myint], ax
};
printf("Third element: %d\n", myint);
return 0;
}
应该产生这个作为输出:
第三个元素:3
如果您想对数组中的所有整数求和,则内联汇编可能如下所示:
#include<stdio.h>
int main()
{
int array[10] = {1,2,3,4,5,6,7,8,9,0};
/* arrsize = number of ints in array */
const unsigned int arrsize = sizeof(array)/sizeof(int);
int total;
asm{
/* Sum a non-zero length array from the last element down to first element */
lea si, [array] /* SI = base address of array */
mov bx, [arrsize] /* BX = Number of 16-bit ints in array */
shl bx, 1 /* BX = BX * 2 = length of array in bytes
BX points at element just beyond the end of the array */
xor ax, ax /* AX = current sum = 0 */
}
numloop:
asm{
add ax, [si+bx-2] /* Add current element */
sub bx, 2 /* BX = position of previous element in array */
jnz numloop /* If the index = 0 then we aren't finished */
mov [total], ax /* Move the sum into variable total */
};
printf("Sum of all ints: %d\n", total);
return 0;
}
某些版本的 Turbo-C 不能正确支持内联汇编语句中的标签。相反,您可以使用 C 标签,这些标签通常用于 C 中的 goto 语句。您只需将内联程序集分解为多个部分,以便在必要的地方放置标签,就像上面示例中的标签 numloop 一样。
输出应该是:
所有整数的总和:45
脚注: