繁体   English   中英

遍历2维阵列

[英]Traversing a 2-d array

我无法理解如何遍历x86汇编语言中的二维数组。 我缺少一点理解。 这就是我到目前为止所拥有的。

问题是//offset//moving through array对于//offset行,我得到的错误是“第二个操作数中的非常量表达式”以及“ebx:第二个操作数中的非法寄存器”

对于下一行,我得到错误“edx:非法寄存器在第二个操作数”

    mov esi, dim
    mul esi
    mov eax, 0 // row index
    mov ebx, 0 // column index
    mov ecx, dim
StartFor:
    cmp ecx, esi
    jge EndFor
    lea edi, image;
    mov edx, [eax *dim + ebx] // offset
    mov dl, byte ptr [edi + esi*edx] // moving through array
    mov edx, edi
    and edx, 0x80
    cmp edx, 0x00
    jne OverThreshold
    mov edx, 0xFF


OverThreshold:
    mov edx, 0x0

请参阅标记wiki,包括寻址模式列表

您可以使用常量缩放索引寄存器,但不能在寻址模式下将两个寄存器相乘。 您必须自己完成(例如,使用imul edx, esi ,如果列数不是编译时间常数。如果它是2的幂,则可以移位,甚至使用缩放寻址模式比如[reg + reg*8] )。


回复:编辑: *dim如果应该工作dim与类似定义dim equ 8 如果它是一个存储值的内存位置,那么它当然不会起作用。 比例因子可以是1,2,4或8.(机器代码格式有2位移位计数的空间,这就是选项有限的原因。)


我还建议加载movzx将一个字节零扩展到edx ,而不是只写dl (低字节)。 实际上是nvm,你的代码不需要那个。 实际上,您将覆盖使用edi加载的值。 我认为这是一个错误。


你可以替换

imul  edx, esi
mov dl, byte ptr [edi + edx]   ; note the different addressing mode
mov edx, edi                   ; bug?  throw away the value you just loaded
and edx, 0x80                  ; AND already sets flags according to the result
cmp edx, 0x00                  ; so this is redundant
jne OverThreshold

imul   edx, esi
test   0x80, byte ptr [edi + edx]   ; AND, discard the result and set flags.
jnz

当然,您可以在外循环中添加columns ,而不是在内循环内部进行乘法运算。 这称为强度降低 所以你沿着每一行做p+=1 ,并且p+=cols从一行到p+=cols行。 或者,如果您不需要关心行和列,则可以迭代2D数组的平面内存。

二维数组只是对字节序列的解释。 您必须选择存储项目的顺序。 例如,您可以选择“行主要订单”

我写了一个演示,其中缓冲区充满了一系列数字。 然后将序列解释为单维和二维阵列。

tx86.s

%define ITEM_SIZE 4

    extern printf

    section .bss

cols:   equ     3
rows:   equ     4
buf:    resd    cols * rows
c:      resd    1
r:      resd    1

    section .data

fmt:        db "%-4d", 0          ; fmt string, '0'
fmt_nl:     db 10, 0              ; "\n", '0'

    section .text           ; Code section.

    global main

main:
    push    ebp
    mov     ebp, esp

    ; fill buf
    mov     ecx, cols * rows - 1
    mov     [buf + ITEM_SIZE], ecx
.fill_buf:
    mov     [buf + ecx * ITEM_SIZE], ecx
    dec     ecx
    jnz     .fill_buf

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; buf as 1-dimensional array
; buf[c] = [buf + c * ITEM_SIZE]
    xor     ecx, ecx
    mov     [c], ecx
.lp1d:
    mov     ecx, [c]

    push    dword [buf + ecx * ITEM_SIZE]
    push    dword fmt
    call    printf

    mov     ecx, [c]
    inc     ecx
    mov     [c], ecx
    cmp     ecx, cols * rows
    jl      .lp1d

    ; print new line
    push    dword fmt_nl
    call    printf

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; buf as 2-dimensional array
; buf[r][c] = [buf + (r * cols + c) * ITEM_SIZE]
    xor     ecx, ecx
    mov     [r], ecx
.lp1:
    xor     ecx, ecx
    mov     [c], ecx
.lp2:
    ; calculate address
    mov     eax, [r]
    mov     edx, cols
    mul     edx         ; eax = r * cols
    add     eax, [c]    ; eax = r * cols + c

    ; print buf[r][c]
    push    dword [buf + eax * ITEM_SIZE]
    push    dword fmt
    call    printf

    ; next column
    mov     ecx, [c]
    inc     ecx
    mov     [c], ecx
    cmp     ecx, cols
    jl      .lp2

    ; print new line
    push    dword fmt_nl
    call    printf

    ; next row
    mov     ecx, [r]
    inc     ecx
    mov     [r], ecx
    cmp     ecx, rows
    jl      .lp1


    mov     esp, ebp
    pop     ebp         ; restore stack

    xor     eax, eax    ; normal exit code
    ret

Buidling(在Linux上)

nasm -f elf32 -l tx86.lst tx86.s
gcc -Wall -g -O0 -m32 -o tx86 tx86.o

运行

./tx86
0   1   2   3   4   5   6   7   8   9   10  11  
0   1   2   
3   4   5   
6   7   8   
9   10  11

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM