我正在撰寫一個添加兩個二維矩陣的匯編程式。代碼是用 MASM 語法撰寫的。
; --------------------
; matrixAdd.asm
; --------------------
; Adds two matrices
; extern "C" int matrixAdd(int *matrixOnePtr, int *matrixTwoPtr, long long rows, long long cols)
.code
matrixAdd proc frame
; function prologue
push r12 ; push r12 register for use
.pushreg r12
push r13 ; push r13 register for use
.pushreg r13
push r14 ; push r14 register for use
.pushreg r14
.endprolog
; validate number of rows and columns
cmp r8, 0 ; compare rows
jle InvalidArg ; jump to InvalidArg if rows <= 0
cmp r9, 0 ; compare cols
jle InvalidArg ; jump to InvalidArg if cols <= 0
xor r10, r10 ; set r10 (increment variable) to 0
LoopOne:
xor r11, r11 ; set r11 (inner increment variable) to 0
LoopTwo:
mov r12, rcx ; move first pointer to r12
mov r13, rdx ; move second pointer to r13
; calculate offset
mov r14, r10 ; move r10 (outer increment variable) to r14
imul r14, r9 ; multiply r14 by number of columns
add r14, r11 ; add inner increment variable
imul r14, 4 ; multiply offset by 4
add r12, r14 ; add offset to first pointer
add r13, r14 ; add offset to second pointer
mov r14, [r13] ; move value of second pointer to r14
add [r12], r14 ; add two matrices
inc r11 ; increment inner increment variable
cmp r11, r9 ; compare inner increment variable to columns
jle LoopTwo ; jump if r11 <= cols
; LoopOne; check if outer increment variable is <= rows
inc r10 ; increment outer increment variable
cmp r10, r8 ; compare r10 to rows
jle LoopOne ; jump if r10 <= rows
pop r12 ; restore r12 register
pop r13 ; restore r13 register
pop r14 ; restore r14 register
xor eax, eax ; set successful return code
ret ; return 0
; Rows or columns is invalid
InvalidArg:
pop r12 ; restore r12 register
pop r13 ; restore r13 register
pop r14 ; restore r14 register
mov eax, 1 ; move 1 into eax register
ret ; return 1
matrixAdd endp
end
主要功能如下:
#include <stdio.h>
extern int matrixAdd(int *matrixOnePtr, int *matrixTwoPtr, long long rows, long long cols);
int main(int argc, char **argv) {
int a1[3][3] = {
{1, 2, 3},
{1, 2, 3},
{1, 2, 3}
};
int a2[3][3] = {
{1, 2, 3},
{1, 2, 3},
{1, 2, 3}
};
matrixAdd(a1, a2, 3, 3);
for (int i = 0; i < 3; i) {
for (int j = 0; j < 3; j) {
printf("%d ", a1[i][j]);
}
printf("\n");
}
}
預期的輸出應該是
2 4 6
2 4 6
2 4 6
但結果是
2 6 9
4 8 9
4 8 9
我一直在嘗試除錯代碼,但它不起作用。我的電腦是 Windows 10 64 位。每個矩陣都是 3x3。我是 x86 匯編編程的新手。
uj5u.com熱心網友回復:
- 您的(匯編語言)演算法從根本上是劣等的。顯然,您只是在翻譯兩個嵌套回圈(因為它在 HLL 中是習慣和正確的)。但是,您忘記了一個事實,也就是說
int[6][7],就記憶而言,它相當于一個int[42]. 考慮到您要執行矩陣加法,一系列rows * cols和更有效。 - 此外,它將簡化地址計算。順便說一下,對于(僅)地址計算,您通常使用
lea指令。別擔心,作為一個新手,這可能是一個令人生畏的復雜指令,對我來說也是如此。 - 您正在回圈中加載“指向 r12/r13 的第一個/第二個指標” 。這是錯誤的(或者至少是不必要的,因為您沒有覆寫
rcx/rdx)。你應該只做一次,我。e. 在回圈之外。 - 正如Jester已經評論的那樣:由于陣列的索引從零開始,因此中止條件不應包括
=. 例如,在int[3]您想要迭代 set的情況下{0, 1, 2}。 - 正如Jester已經評論的那樣,這是主要問題:
mov r14, [r13]并且add [r12], r14將檢索和操作64 位數量。a 中目標暫存器的大小mov很重要。mov r14d, [r13]將檢索一個“雙字”,即。e. 一個 32 位的數量。同樣,add dword ptr [r12], r14d將添加兩個 32 位值。請注意,記憶體地址(在 64 位系統上)始終需要指定為完整的64 位暫存器。前綴將dword ptr告知 MASM 記憶體運算元大小,因此它的組裝方式不同。 - 結果
a1[0][0]實際上是正確的,因為 x86 架構是一個小端系統。 - 您
pop在例程(兩個可能的)末端的指令必須是相反push的順序。您的代碼實際上是在交換呼叫站點背景關系r12的內容。r14理想情況下,您將合并兩個函式尾聲,但一次解決一個問題。 - 最后,您的函式正在回傳一個(非常量)
int值,但您的 C 代碼并未對此進行檢查。宣告你的函式void可能是最簡單的解決方案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/424425.html
