Re: [Асемблер8086]Від нуба до професіонала(або шлях на асемблерну вершину)
Робота за матрицями
Задача
Вирішити систему лінійних алгебраїчних рівнянь за допомогою методу Крамера
Сама складна задача тут - це знайти визначник матриці.
Я використовую такі формули, вони дуже легко запам'ятовуються. (подивіться уважно і зрозумієте чому)
що до коду, то я створив дві функції, DERERMINANT2X2 - обчислює визначник 2х2, а також додатковий множник, DETERMINANT3X3 - обчислює визначник 3х3.
Аргументи записуються в спеціальному порядку, по мірі потрібності.
Ділення визначників - це доволі легка робота, тому тут все зрозуміло.
Для визначення максимально допустимого числа я взяв корінь з 32767, яке є максимально допустимим для числа зі знаком DW, хоча не знаю наскільки це правильно.
Також в програмі використовується регістр BP, не за призначенням, не знаю чи це погано, але для мене не вистачило регістрів загального призначення, тому я використав його (BP).
;CRAMER'S RULE
data segment
;Nothing more than +/-181!!!
;INSERT IN ORDER X11,X12,X13,B1,X21,X22,X23,B2,X31,X32,X33,B3
;------------------------------------------------------------
;Example:
;MATRIX DW 2, 5, 4, 30, 1, 3, 2, 150, 2, 10, 9, 110
;MATRIX DW 1, 0, 1, 4, 0, 2, -1, 1, 3, -1, 0, 1
;MATRIX DW 1, 1, -2, 2, 2, -3, -1, 1, 1, -4, 1, 3; - ERROR
MATRIX DW 2, 3, -1, 4, 1, 1, 3, 5, 3, -4, 1, 0
X1 DW ?
X2 DW ?
X3 DW ?
ends
code segment
DETERMINANT3X3:
JMP DERERMINANT2X2
MOV CX, AX
JMP DERERMINANT2X2
SUB CX, AX
JMP DERERMINANT2X2
ADD AX, CX
RET
DERERMINANT2X2:
POP BX
POP AX
IMUL BX
MOV BP, AX
POP BX
POP AX
IMUL BX
SUB AX, BP
MOV DX, AX
POP AX ;ADDITIONAL ACTION
IMUL DX
RET
start:
; set segment registers:
mov ax, data
mov ds, ax
MOV SI, OFFSET MATRIX
;
;----------------------------------
;A
PUSH 05Dh; RETURN FROM DETERMINANT3X3
;
PUSH 0Ah
;
PUSH MATRIX[SI+4] ;a13
PUSH MATRIX[SI+8] ;a21
PUSH MATRIX[SI+18] ;a32
PUSH MATRIX[SI+10] ;a22
PUSH MATRIX[SI+16] ;a31
;
PUSH 06h
;
PUSH MATRIX[SI+2] ;a12
PUSH MATRIX[SI+8] ;a21
PUSH MATRIX[SI+20];a33
PUSH MATRIX[SI+12] ;a23
PUSH MATRIX[SI+16] ;a31
;
PUSH 02h
;
PUSH MATRIX[SI] ;a11
PUSH MATRIX[SI+10] ;a22
PUSH MATRIX[SI+20];a33
PUSH MATRIX[SI+12] ;a23
PUSH MATRIX[SI+18] ;a32
JMP DETERMINANT3X3
PUSH AX ;SAVE A
;
;----------------------------------
;A1
MOV BX, 098h
PUSH BX; (DON'T WANT TO WORK WITH 09Bh) RETURN FROM DETERMINANT3X3
;
PUSH 0Ah
;
PUSH MATRIX[SI+4]
PUSH MATRIX[SI+14] ;b2
PUSH MATRIX[SI+18]
PUSH MATRIX[SI+10]
PUSH MATRIX[SI+22] ;b3
;
PUSH 06h
;
PUSH MATRIX[SI+2]
PUSH MATRIX[SI+14] ;b2
PUSH MATRIX[SI+20]
PUSH MATRIX[SI+12]
PUSH MATRIX[SI+22] ;b3
;
PUSH 02h
;
PUSH MATRIX[SI+6] ;b1
PUSH MATRIX[SI+10]
PUSH MATRIX[SI+20]
PUSH MATRIX[SI+12]
PUSH MATRIX[SI+18]
JMP DETERMINANT3X3
POP CX
CWD
IDIV CX
MOV X1, AX
PUSH CX
;
;----------------------------------
;A2
MOV BX, 0D9h
PUSH BX; RETURN FROM DETERMINANT3X3
;
PUSH 0Ah
;
PUSH MATRIX[SI+4] ;a13
PUSH MATRIX[SI+8] ;a21
PUSH MATRIX[SI+22] ;b3
PUSH MATRIX[SI+14] ;b2
PUSH MATRIX[SI+16] ;a31
;
PUSH 06h
;
PUSH MATRIX[SI+6] ;b1
PUSH MATRIX[SI+8] ;a21
PUSH MATRIX[SI+20];a33
PUSH MATRIX[SI+12] ;a23
PUSH MATRIX[SI+16] ;a31
;
PUSH 02h
;
PUSH MATRIX[SI] ;a11
PUSH MATRIX[SI+14] ;b2
PUSH MATRIX[SI+20];a33
PUSH MATRIX[SI+12] ;a23
PUSH MATRIX[SI+22] ;b3
JMP DETERMINANT3X3
POP CX
CWD
IDIV CX
MOV X2, AX
PUSH CX
;
;----------------------------------
;A3
MOV BX, 011Ah
PUSH BX; RETURN FROM DETERMINANT3X3
;
PUSH 0Ah
;
PUSH MATRIX[SI+6] ;b1
PUSH MATRIX[SI+8] ;a21
PUSH MATRIX[SI+18] ;a32
PUSH MATRIX[SI+10] ;a22
PUSH MATRIX[SI+16] ;a31
;
PUSH 06h
;
PUSH MATRIX[SI+2] ;a12
PUSH MATRIX[SI+8] ;a21
PUSH MATRIX[SI+22];b3
PUSH MATRIX[SI+14] ;b2
PUSH MATRIX[SI+16] ;a31
;
PUSH 02h
;
PUSH MATRIX[SI] ;a11
PUSH MATRIX[SI+10] ;a22
PUSH MATRIX[SI+22];b3
PUSH MATRIX[SI+14] ;b2
PUSH MATRIX[SI+18] ;a32
JMP DETERMINANT3X3
POP CX
CWD
IDIV CX
MOV X3, AX
PUSH CX
mov ax, 4c00h ; exit to operating system.
int 21h
ends
end start ; set entry point and stop the assembler.
до речі, можливо це єдиний код Крамера на просторах інтернету, тому що мені не вдалося знайти інших прикладів вирішення.