我无法理解如何在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
答案 0 :(得分:1)
请参阅x86代码wiki,包括list of addressing modes。
您可以使用常量缩放索引寄存器,但不能在寻址模式下将两个寄存器相乘。你自己必须这样做(例如imul edx, esi
,如果列数不是编译时间常数。如果它是2的幂,你可以移位,甚至使用像[reg + reg*8]
)这样的缩放寻址模式。
re:编辑:*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
,而不是在内循环内部相乘。这称为Strength Reduction。因此,每行都p+=1
,p+=cols
从一行到另一行。或者,如果您不需要关心行和列,则可以迭代2D数组的平面内存。
答案 1 :(得分:1)
二维数组只是对字节序列的解释。您必须选择存储项目的顺序。例如,您可以选择"row-major order"。
我写了一个演示文稿,其中缓冲区中填充了一系列数字。然后将序列解释为单维和二维阵列。
<强> 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