【问题标题】:Assembly Addressing mode汇编寻址模式
【发布时间】:2012-11-27 10:09:53
【问题描述】:

这是代码:

section .data
v dw 4, 6, 8, 12
len equ 4
section .text
    global main
main:
    mov eax, 0 ;this is i
    mov ebx, 0 ;this is j
cycle:
    cmp eax, 2 ;i < len/2
    jge exit
    mov ebx, 0
    jmp inner_cycle
continue:
    inc eax
    jmp cycle
inner_cycle:
    cmp ebx, 2
    jge continue
    mov di, [v + eax * 2 * 2 + ebx * 2]
    inc ebx
    jmp inner_cycle
exit:
    push dword 0
    mov eax, 0
    sub esp, 4
    int 0x80

我正在使用数组并将其扫描为矩阵,这是上面代码的C翻译

int m[4] = {1,2,3,4};
for(i = 0; i < 2; i++){
    for(j = 0; j < 2; j++){
        printf("%d\n", m[i*2 + j]);
    }
}

当我尝试编译汇编代码时,我得到了这个错误:

DoubleForMatrix.asm:20: error: beroset-p-592-invalid effective address

指这一行

mov di, [v + eax * 2 * 2 + ebx * 2]

谁能解释一下这条线有什么问题?我认为这是因为寄存器尺寸,我尝试过

mov edi, [v + eax * 2 * 2 + ebx * 2]

但我遇到了同样的错误。

这是 Mac OS X 的程序集,要使其在另一个 SO 上工作,您必须更改退出系统调用。

【问题讨论】:

    标签: arrays assembly matrix memory-address addressing-mode


    【解决方案1】:

    您不能在汇编程序中使用任意表达式。只允许几种寻址模式。

    基本上最复杂的形式是register/imm+register*scale,比例为1,2,4,8

    当然常数(如 2*2)可能会被折叠为 4,因此算作 4 的单个比例(而不是两次乘法)

    您的示例尝试一次做两个乘法。

    解决方法:插入额外的 LEA 指令来计算 v+ebx*2 并在 mov 中使用结果。

         lea regx , [v+ebx*2]
         mov edi, [eax*2*2+regx]
    

    regx 是一个免费寄存器。

    【讨论】:

    • 编译器告诉lea regx , v+ebx*2invalid operand type
    • 这完全取决于语法。我认为,你应该使用 LEA EAX,[V + EBX*2]
    • @AlekseyIvchenko 因为 EAX 已经在下一条指令 mov edi, [eax*2*2 + regx] 中使用,我想我应该使用另一个寄存器,对吗?
    • @AR89 当然。就像上面提到的“regx 是一个免费寄存器”;我使用 eax 只是为了完成一个示例。
    【解决方案2】:

    SIB(Scale Immediate Base)寻址模式只需将一个 Scale 参数(1、2、4 或 8)应用于一个寄存器。

    建议的解决方案是将 eax 预乘 4(还必须修改比较)。那么inc eax可以用add eax,4代替,非法指令可以用mov di,[v+eax+ebx*2]代替

    更高级别的优化只针对for (i=0;i&lt;4;i++) printf("%d\n",m[i]);

    【讨论】:

    • 确实,在很多情况下您不需要进行 2D 扫描。使用组装的力量 - 使用纯一维数据。
    猜你喜欢
    • 2020-01-16
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    相关资源
    最近更新 更多