我无法弄清楚我在这里缺少什么。很明显,这个错误始于read_matrix
程序,但我不明白为什么。
.386
.model flat, stdcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;includem libraria msvcrt.lib, biblioteca.asm si declaram ce functii vrem sa importam
includelib msvcrt.lib
extern exit:proc
extern printf: proc
extern scanf:proc
extern fopen:proc
extern fclose:proc
extern fscanf:proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;declaram simbolul start ca public-de acolo incepe executia procramului
public start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;sectiunile programului, date, respectiv cod
.data
operation dd 0
message db "Introduceti o operatie cu matrici:",10,0
msgA db "A=",0
msgB db "B=",0
msgR db "Rezultat:",0
format db "%s",0
format1 db "%d",0
read_mode db "r",0
write_mode db "w",0
fileA dd 0
fileB dd 0
rezultat dd 0
op1 dd "A+B",0
op2 dd "AB",0
op3 dd "aA",0
op4 dd "A-B",0
op5 dd "detA",0
matA dd 80 dup(?)
dd 80 dup(?)
nrcolA dd 0
nrlinA dd 0
pointerA dd 0
pointerB dd 0
pointerR dd 0
.code
;functie de afisare mesaj pt introducerea operatiei pe matrici
afisare proc
push ebp
mov ebp, esp ; pregatim stack frame-ul
mov eax, [ebp+8] ; citim primul argument de pe stiva
push eax
call printf
add esp,4
mov esp, ebp
pop ebp
ret 4 ; salt inapoi la adresa de return, si curata parametrii de pe stiva
afisare endp
;functie de citire a unei operatii pe matici, ulterior folosita pt citire cale fisier
citire_operation_file proc
push ebp
mov ebp, esp ; pregatim stack frame-ul
mov edi, [ebp+8] ; citim primul argument de pe stiva-format
mov esi,[ebp+12];citim al doilea argument de pe stiva-operatie/fisier
push esi
push edi
call scanf
add esp,8
mov esp, ebp
pop ebp
ret 8 ; salt inapoi la adresa de return, si curata parametrii de pe stiva
citire_operation_file endp
;functie de deschidere a unui fisier
open_file proc
push ebp
mov ebp, esp ; pregatim stack frame-ul
mov edi, [ebp+8] ; citim primul argument de pe stiva-format
mov esi,[ebp+12];citim al doilea argument de pe stiva-operatie/fisier
push esi
push edi
call fopen
add esp,8
mov esp, ebp
pop ebp
ret 8 ; salt inapoi la adresa de return, si curata parametrii de pe stiva
open_file endp
close_file proc
push ebp
mov ebp, esp ; pregatim stack frame-ul
mov edi, [ebp+8] ; citim primul argument de pe stiva-format
push edi
call fclose
add esp,4
mov esp, ebp
pop ebp
ret 4 ; salt inapoi la adresa de return, si curata parametrii de pe stiva
close_file endp
read_matrix proc
push ebp
mov ebp, esp ; pregatim stack frame-ul
;[ebp+8]=pointerA,[ebp+12]=matA,[ebp+16]=nrcol,[ebp+20]=nrlin,[ebp+24]=format
;citesc nr de linii pt matricea
push [ebp+20]
push[ebp+24]
push [ebp+8]
call fscanf
add esp,12
;citesc nr de coloane pt matrice
push [ebp+16]
push[ebp+24]
push[ebp+8]
call fscanf
add esp,12
;citesc matricea
;parcurg cu edi nr de linii,initial acesta este 0
mov edi,0
et_loop:
cmp edi,[ebp+20]
ja urm
;parcurg cu esi nr de coloane,initial acesta este 0
mov esi,0
et_loop1:
cmp esi,[ebp+16]
ja urm1
push [ebp+12][edi][esi]
push [ebp+24]
push [ebp+8]
call fscanf
add esp,12
inc esi
loop et_loop1
urm1:
inc edi
loop et_loop
urm:
mov esp, ebp
pop ebp
ret 20; salt inapoi la adresa de return, si curata parametrii de pe stiva
read_matrix endp
start:
;afisez de afisare a unei operatii cu matrici
push offset message
call afisare
;apelez funtie de citire a unei operatii cu matrici
push offset operation
push offset format
call citire_operation_file
;afisez mesaj de introducere cale fisier pt matricea A
push offset msgA
call afisare
;citesc calea fisieruli pt matricea A
push offset fileA
push offset format
call citire_operation_file
;deschid fisierul pt matricea A
push offset read_mode
push offset fileA
call open_file
mov pointerA,eax
;citesc matricea A
push offset format1
push offset nrlinA
push offset nrcolA
push offset matA
push pointerA
call read_matrix
;afisez mesaj de introducere cale fisier pt matricea B si retin pe stiva pointerul de fisier
push offset msgB
call afisare
;citesc calea fisierului pt matricea B
push offset fileB
push offset format
call citire_operation_file
;deschid fisierul pt matricea B si retin pe sitiva pointerul de fisier
push offset write_mode
push offset fileB
call open_file
mov pointerB,eax
;afisez mesaj de introducere cale fisier pt rezultat si retin pe stiva pointerul de fisier
push offset msgR
call afisare
;citesc calea fisierului pt rezultat
push offset rezultat
push offset format
call citire_operation_file
;deschid fisierul pt rezultat si retin pe sitiva pointerul de fisier
push offset write_mode
push offset fileB
call open_file
mov pointerR,eax
;inchid fisierul pt matricea B
push pointerB
call close_file
;inchid fisierul pt matricea A
push pointerA
call close_file
;inchid fisierul pt rezultat
push pointerR
call close_file
;terminarea programului
push 0
call exit
end start
汇编程序在这一行上给出了一个错误:
push [ebp+12][edi][esi]
但为什么这是一个错误?语法对我来说似乎没问题。
答案 0 :(得分:3)
正如David Hoelzer和Michael Petch所说,[ebp+12][edi][esi]
不是有效的寻址模式。如果它是有效的寻址模式,它将与[ebp+12+edi+esi]
相同,这不是您想要的。您试图推送矩阵元素的地址,并且地址计算要复杂得多。
您需要将其替换为计算正确地址的代码。类似的东西:
mov eax, edi ; row
imul eax, [ebp+16] ; row * nrcol
add eax, esi ; row * nrcol + col
mov edx, [ebp+12] ; matrix address
lea eax, [edx+eax*4] ; element address
push eax
此外,以下代码可能无法完成您的预期目标:
matA dd 80 dup(?)
dd 80 dup(?)
这为160个元素矩阵分配空间,而不是6400个元素(80x80)矩阵。如果你想要更晚一些,你应该使用:
matA dd 80*80 dup (?)
答案 1 :(得分:2)
您收到错误,因为[ebp+12][edi][esi]
表示法无效。老实说,我并不确定你打算用它做什么。以下是PUSH
可以使用的方式:
Registers:
PUSH AX
PUSH EAX
PUSH RAX
Immediate:
PUSH 0xFFFF
PUSH 0xFFFFFFFF
PUSH 0xFFFFFFFFFFFFFFFF
Indirect (Memory):
PUSHW [BX] ;16 bits - I don't believe an 8 bit push is permitted.
PUSHL [BX] ;32 bits
使用AT& T语法,其中一些可能更清楚。例如,push $0xffff
推送立即或push 0x1234
推送内存内容。
通过间接或内存推送,您可以使用其他寄存器来解决它们。您可以找到this等有用的参考资料。
请注意,由于我在内存中说话,因此其中一些可能需要改进。我不认为我曾经实际使用了PUSH
内存地址的内容。