错误C2432对';中16位数据的非法引用;第二个操作数';关于asm

错误C2432对';中16位数据的非法引用;第二个操作数';关于asm,c,visual-studio,assembly,inline-assembly,32-bit,C,Visual Studio,Assembly,Inline Assembly,32 Bit,在VisualStudio中,我在用C编译asm时遇到了这个错误。有人知道这段代码有什么问题吗?我什么都试过了,但都没用。我正在尝试在汇编中实现冒泡排序 unsigned short i = 0; unsigned short j = 0; unsigned short max = short(N-2); unsigned short tab[5]; tab[0] = 54; tab[1] = 123; tab[2] = 342; tab[3] = 5436; tab[4] = 1234;

在VisualStudio中,我在用C编译asm时遇到了这个错误。有人知道这段代码有什么问题吗?我什么都试过了,但都没用。我正在尝试在汇编中实现冒泡排序

unsigned short i = 0;
unsigned short j = 0;
unsigned short max = short(N-2);


unsigned short tab[5];
tab[0] = 54;
tab[1] = 123;
tab[2] = 342;
tab[3] = 5436;
tab[4] = 1234;

unsigned short a = 0;

__asm {
loop1:
    inc i
    mov j, 0

        mov si, tab

        loop2:
            mov ax, [si] // <- Error C2432 on this line 
            mov a, ax

            inc j
            mov ax, j
            mov bx, max
            cmp ax, bx
            jz cdnloop2
        loop loop2
        cdnloop2:
    mov ax, i
    mov bx, max
    cmp ax, bx
    jz endof

    loop loop1  
endof :
}
无符号短i=0;
无符号短j=0;
无符号短路最大值=短路(N-2);
无符号短制表符[5];
表[0]=54;
表[1]=123;
表[2]=342;
表[3]=5436;
表[4]=1234;
无符号短a=0;
__asm{
循环1:
公司一
movj,0
mov si,制表符
循环2:

mov ax,[si]/用谷歌搜索错误消息。答案是(第一次谷歌点击)

对“标识符”中16位数据的非法引用

16位寄存器用作索引或基址寄存器。编译器 不支持引用16位数据。不能引用16位寄存器 编译32位代码时用作索引或基寄存器

第一段有点混乱,因为听起来问题是16位操作数大小,而不是16位地址大小。但第二段明确指出:它拒绝使用地址大小前缀来组装类似于
mov ax,[si]
,因为在内联asm中,忽略地址的大写16不是一件有用的事情

他们已经决定,在编译时捕获这样的输入错误比发出崩溃的代码要好


可能只需将行更改为
mov ax,[tab]
。将地址存储在
esi
中不会获得任何好处,因为您不需要修改它。

内存地址是32位。(如果您将程序编译为64位,则为64位)
mov ax,word ptr[si]
解决它?地址寄存器必须是32位或64位。使用
mov ax、[esi]
mov ax、[rsi]
@immibis从技术上讲
mov ax,[si]
在32位模式下允许使用地址大小覆盖前缀(
66 67 8B 04
)。可能没有任何意义,但这是允许的。@Dirkwolfganglomp。在这种情况下,
mov ax,[esi]
通常使用esi(而不是SI)。所讨论的代码不是64位的,因为Visual Studio根本不允许64位内联汇编。这几乎消除了
mov ax,[rsi]
作为替代。@Joshua:是的,它是32位,但不是64位。就像Jester和Michael Petch在评论中说的那样。
67 66 8b 04 mov ax,WORD PTR[si]
。地址大小和操作数大小前缀。这是yasm-f elf32和&objdump-Mintel-d的反汇编输出。