[英]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
您可以使用常量缩放索引寄存器,但不能在寻址模式下将两个寄存器相乘。 您必须自己完成(例如,使用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.