使用 Turbo C++ 内联 asm 索引包含常量的数组
Index an array with constants with Turbo C++ inline asm
我正在尝试在 Turbo C++ 3.0 IDE 中编写 16 位内联汇编代码。我需要使用内联汇编访问以高级语言(如 C++ 定义的数组,但我的尝试失败了。编译失败的代码:
#include<stdio.h>
int main()
{
int array[10] = {1,2,3,4,5,6,7,8,9,0};
asm{
mov ax,array[0]
}
// fall off the end of the function with return value in AX
// Or else C++ implicit return 0 still happens.
}
上面的代码在指令 mov ax,array[0]
:
上给我一个错误
Invalid combination of opcode and operands
我试图通过 Turbo C++ 3.0 的手册来学习如何复制内容,但是没有关于如何使用内联汇编来完成的信息。
我什至浏览了 8086 到 Pentium 汇编语言这本书,但我找不到问题的答案。
当我尝试其他方法时,我似乎得到了不正确的答案,例如 -22,而不是 1。
(编者注:不清楚 OP 是用调试器查看 AX 还是只查看 main
的 return 值。)
访问在堆栈上生成的数组元素可能有点棘手。当访问基于堆栈的变量(即:在堆栈上定义的非静态变量,如 array
)时,编译器会生成相对于寄存器 BP 的内存引用。您的指示:
mov ax,array[0]
会报错:
Invalid combinations of opcodes and operands
该语法不适用于包括数组在内的堆栈变量。将起作用的是:
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中。该代码检索第 3 个整数元素 (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;
}
应该将其作为输出:
Third element: 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 中的 goto
语句的 C 标签。您只需将内联程序集分解为多个部分,以便在必要时放置标签,就像上面示例中标签 numloop
所做的那样。
输出应该是:
Sum of all ints: 45
脚注:
- 1BX, DI, SI 是 16-bit addressing modes 中允许的寄存器。 BP 也是允许的,但它隐含地使用 SS 作为段而不是 DS.
我正在尝试在 Turbo C++ 3.0 IDE 中编写 16 位内联汇编代码。我需要使用内联汇编访问以高级语言(如 C++ 定义的数组,但我的尝试失败了。编译失败的代码:
#include<stdio.h>
int main()
{
int array[10] = {1,2,3,4,5,6,7,8,9,0};
asm{
mov ax,array[0]
}
// fall off the end of the function with return value in AX
// Or else C++ implicit return 0 still happens.
}
上面的代码在指令 mov ax,array[0]
:
Invalid combination of opcode and operands
我试图通过 Turbo C++ 3.0 的手册来学习如何复制内容,但是没有关于如何使用内联汇编来完成的信息。
我什至浏览了 8086 到 Pentium 汇编语言这本书,但我找不到问题的答案。
当我尝试其他方法时,我似乎得到了不正确的答案,例如 -22,而不是 1。
(编者注:不清楚 OP 是用调试器查看 AX 还是只查看 main
的 return 值。)
访问在堆栈上生成的数组元素可能有点棘手。当访问基于堆栈的变量(即:在堆栈上定义的非静态变量,如 array
)时,编译器会生成相对于寄存器 BP 的内存引用。您的指示:
mov ax,array[0]
会报错:
Invalid combinations of opcodes and operands
该语法不适用于包括数组在内的堆栈变量。将起作用的是:
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中。该代码检索第 3 个整数元素 (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;
}
应该将其作为输出:
Third element: 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 中的 goto
语句的 C 标签。您只需将内联程序集分解为多个部分,以便在必要时放置标签,就像上面示例中标签 numloop
所做的那样。
输出应该是:
Sum of all ints: 45
脚注:
- 1BX, DI, SI 是 16-bit addressing modes 中允许的寄存器。 BP 也是允许的,但它隐含地使用 SS 作为段而不是 DS.