装配错误[ebp + 12] [edi] [esi]'

时间:2015-12-14 22:29:33

标签: windows assembly masm 32-bit

我无法弄清楚我在这里缺少什么。很明显,这个错误始于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]

但为什么这是一个错误?语法对我来说似乎没问题。

2 个答案:

答案 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内存地址的内容。