我认为 Irvine32 没有光标移动功能。
因此,您只能从左到右打印文本,然后从上到下打印。 (或者如果确实存在光标移动功能,则不必为此使用它们。)
解决办法是弄清楚每一行要打印哪些数组元素,这样就可以弄清楚数组元素的打印顺序。
假设您的数组是dd 1,2,3,4,5,6,7,8,9,10,您打印的顺序是像 Fortran 的“列主要”顺序,而不是像 C (https://en.wikipedia.org/wiki/Row-_and_column-major_order) 这样的行主要顺序。
这意味着循环遍历一行中的元素涉及将索引增加行数。
您需要以某种方式决定使用多少行,可能作为一个额外的函数 arg。鉴于此,以4 * rows bytes 遍历数组以获取该行中的元素。您可以检测到一行的结尾,因为您的指针地址将是>= array_end。然后循环回到下一行的开头。
例如:未经测试
array_square_print PROC
;; array pointer passed in ESI (clobbered)
;; column length = # of rows in ECX (clobbered)
;; total element count in EDX (clobbered)
push ebx
push edi ; save some call-preserved registers
lea edx, [esi + 4*edx] ; endp = one past the end = array + n*size
lea ebx, [ecx * 4] ; row_stride in bytes
mov edi, esi ; start point for this row
@row_loop:
@col_loop:
mov eax, [esi]
add esi, ebx ; p += row_stride
call writedec
cmp esi, edx
jb @col_loop ; }while(p<endp);
add edi, 4 ; next row = advance down the column
mov esi, edi ; p = rowstart
dec ecx
jnz @row_loop
pop edi ; restore regs
pop ebx
ret
array_square_print ENDP
为方便起见,我使用了自定义调用约定。它类似于 fastcall,但带有第三个寄存器 arg (ESI)。
也许可以使用更少的寄存器,但我目前不知道如何使用。 (当然,我们可以在堆栈上留下只读的东西而不会降低效率,但即使是外循环的东西,我们也有足够的寄存器。)