Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 用汇编语言添加两个矩阵_Assembly_Nasm - Fatal编程技术网

Assembly 用汇编语言添加两个矩阵

Assembly 用汇编语言添加两个矩阵,assembly,nasm,Assembly,Nasm,我正在编写一个汇编程序,将两个3X6矩阵相加,然后将结果放入一个新矩阵。我遇到了一些问题 问题是矩阵1的输出仅为2-16,矩阵2的输出仅为20-34。我似乎想不出如何让它充分发挥作用 %include "io.mac" .STACK 100H .DATA NO_ROWS EQU 3 NO_COLUMNS EQU 5 SIZE_OF_ROW EQU 5 SIZE_OF_ENTRY EQU 2 matrix1 dw 1,2,3,4,5,6 dw 7,8,9,10,11,12

我正在编写一个汇编程序,将两个3X6矩阵相加,然后将结果放入一个新矩阵。我遇到了一些问题

问题是矩阵1的输出仅为2-16,矩阵2的输出仅为20-34。我似乎想不出如何让它充分发挥作用

%include "io.mac"
.STACK 100H 
.DATA
 NO_ROWS EQU 3
 NO_COLUMNS EQU 5
 SIZE_OF_ROW EQU 5
 SIZE_OF_ENTRY EQU 2


 matrix1 
 dw 1,2,3,4,5,6
 dw 7,8,9,10,11,12
 dw 13,14,15,16,17,18

 matrix2 
 dw 19,20,21,22,23,24
 dw 25,26,27,28,29,30
 dw 31,32,33,34,35,36

matrix3 TIMES 40 DW 0
 .CODE
 .STARTUP


mov  CX, NO_ROWS ; set outer loop count

L1: ; begin the outer loop   
    push CX ; save outer loop count
    mov BX, CX ;move outer loop count into EAX
    sub bx, 1
    mov CX, 5 ; set inner loop count

L2:
   ; use formula arrayName + (elements_in_a_row*row_number + element) *size_of_entry
mov si, 0
mov di, 0
mov dx, 0
mov si, matrix1
mov di, matrix2
mov ax, SIZE_OF_ROW
mul bx ;multiply ax by which row you're on.
add ax, cx ;then add column count, for which column you're on.
shl ax, 1 ;then multiply it by the size of each entry.
add si, ax ; so that the index points to the element.
add di, ax
mov ax, [si]
add ax, [di]
mov [matrix3], ax
PutInt [matrix3]
nwln
add word [matrix3], 2



    loop L2 ; repeat inner loop
    pop CX ;restore outer loop
    loop L1 ;repeat outer loop




 done:
 .EXIT

对于
cx={5,4,3,2,1}
,内部循环
L2
将只执行5次。外部循环将通过
bx={2,1,0}
(确定)。因此,总共只使用15个值。如果矩阵是3x6,那么行的大小也应该是6(同样也是
NO\u列
,实际上为什么需要两个常数来覆盖相同的逻辑)

但总的来说,你只是朝着错误的方向前进。当需要特定矩阵元素(“随机”访问)时,需要进行索引计算

要将两个大小相同的矩阵相加,顺序访问就足够了,因为您需要处理所有元素

你甚至可以忘记矩阵有多少个维度,因为所有三个(源矩阵A和B,以及结果矩阵C)都有相同的大小=>它们有相同数量的总元素

在您的例子中,矩阵是3x6=18个元素。每个元素的大小为
word
大小(2字节)。因此,每个矩阵将占用36个字节(或18个字)。您以连续的方式定义了它们(下一行在上一个=良好设计结束后开始)

这样的过程会做矩阵加法:对于相同大小的矩阵,C=A+B:

; Same-size matrices addition (of 16b word elements): C = A + B
; ds:si = A address, ds:bx = B address
; ds:di = C address, cx = total amount of elements
; modifies: all input registers and ax
matrices_add:
    mov    ax,[si]
    add    ax,[bx]     ; ax = A[i] + B[i]
    mov    [di],ax     ; C[i] = ax
    ; ++i (actually advancing all three pointers instead of using index)
    add    si,2
    add    bx,2
    add    di,2
    ; loop until all elements are added
    dec    cx
    jnz    matrices_add
    ret
现在,在您的案例中,您可以使用以下参数调用它:

NO_ROWS     EQU 3
NO_COLUMNS  EQU 6      ; fixed

    ...
    mov    si,matrix1
    mov    bx,matrix2
    mov    di,matrix3
    mov    cx,(NO_ROWS*NO_COLUMNS)
    call   matrices_add
    ; here memory at address matrix3 will contain matrix1+matrix2 elements
    ...
停止使用控制台输出进行调试,并从MS获取一些DOS调试器,如Turbo debugger或CV.EXE(代码视图),或使用具有内置调试器的虚拟机BOCHS,这是一种更健壮的解决方案,能够在DOS运行之前调试引导加载程序

如果要显示矩阵,请使用单独的代码,以避免在添加过程中产生不必要的影响,并简化调试(例如,您可以先尝试显示
matrix1
,然后退出DOS,以验证输出例程是否正确:

    ...
    mov    si,matrix3      ; pointer to next element
    ; output 3x6 16b matrix from "si" address
    mov    dx,NO_ROWS
output_matrix_row:
    mov    cx,NO_COLUMNS
output_matrix_line:
    PutInt [si]            ; display next element
    PutCh  ' '             ; make space between elements
    add    si,2            ; adjust pointer to point to next element
    dec    cx
    jnz    output_matrix_line
    nwln                   ; new line
    dec    dx
    jnz    output_matrix_row
    ...
如您所见,我再次避免了元素计算的“随机访问”索引,以连续的方式再次访问它们,只需对下一个元素执行基本的
add si,2
,没有缓慢的
mul
甚至一些复杂的计算

这就是汇编代码编写速度快的原因,优化算法以避免执行无用的指令,如果通过执行
offset=(y*ROW\u SIZE+x)*element\u SIZE
,继续计算每个元素的完整索引,那么最终的代码速度将比任何半体面的高级语言编写的好代码都慢(C、Java、C#……所有这些编译器都会将两个嵌套循环视为优化机会,并生成类似于我在asm中编写的代码,其中只有一个循环遍历连续的偏移量)

因此,在编写任何代码之前,您应该首先确保完全理解要计算的内容及其原因,并尽可能简化它以避免任何冗余操作



在您看到调试器中的单步执行指令之前,您将很难发现代码中的所有问题,正如您在最后4个问题中很好地演示的那样。我欣赏您的固执,但您看起来没有足够的天赋在没有调试器的情况下继续进行,最终获得一些,并学会使用再重复几次你以前的问题和别人的提示,看看这次你能重复多少并完全理解。

感谢这些建议。我会听从你的建议。@Rubiks顺便说一句,你的指数计算代码基本上是正确的(输入
cx
是错误的,这就是为什么它没有覆盖所有元素的完整矩阵。。哦,行大小也是错误的)。冗余的,正如您从我的“添加”例程中看到的,该例程忽略了维度,只需遍历从索引0到最后一个索引(=M*N-1)的所有元素,完全忽略二维坐标,但正确,因此您的问题是坐标错误(在调试过程中可以看到)。因此,您成功地编写了代码中更复杂的部分,正确地计算索引,并在更简单的循环部分卡住了…:)我还有一个问题。如果我想旋转矩阵1,最好的方法是什么?Rubiks:旋转?转置还是旋转?如果矩阵足够大,保持它们的原样并只收集变换信息可能会更便宜(您可以将旋转/转置/翻转平移组合成一个复杂的信息,如涉及变换矩阵相乘时的3D,但此处的变换信息类似于2x2矩阵、起始角和行/列方向)然后,矩阵的最终添加将使用较慢的索引计算,包括坐标的最终转换。对于较小的矩阵,转换数据可能更便宜。在您的情况下,我将坚持按字面方式转换数据,因此您将获得具有旋转值的矩阵的新副本。索引计算将是不像在我的代码(+2,+2)中那样简单,您必须在两个嵌套循环中计算2个维度,但是如果您检查元素的索引是如何演变的,您很可能能够避免使用
mul
进行完整的索引计算,只需对起始索引值进行
add/sub
调整(比如在原始矩阵上+2,以及目标索引的Z字形更新)。使用钢笔+纸张的例子来了解你需要什么,寻找模式。