Как вызвать подпрограмму внутри другой подпрограммы? - PullRequest
1 голос
/ 05 апреля 2019

Я недавно начал работу над проектом, который преобразует введенные пользователем выражения Postfix в префиксные и инфиксные выражения соответственно. Однако у меня возникли проблемы с вызовом этих подпрограмм в других подпрограммах, поскольку я не совсем уверен, как они функционируют. То, что я хотел бы сделать, это вызвать подпрограмму strcat в подпрограмме postfix_to_prefix, но я не могу понять, как это сделать.

Этот проект предназначен для класса компьютерной архитектуры, и я потратил около 10 часов на то, чтобы провести личное исследование о том, как написать программу, но мне не удалось найти то, что я должен сделать, чтобы она функционировала правильно , в частности, в метке операции кода.

; A Subprogram that converts Postfix Prefix
segment .data
plus_sign   db ' + ', 0
minus_sign  db ' - ', 0
multiply    db ' * ', 0
divider     db ' / ', 0
parenthsf   db ' ( ', 0
parenthsb   db ' ) ', 0

segment .bss    
operand     resd 1
operators   resd 1

segment .text


postfix_to_infix:
    push    ebp
    mov     ebp, esp

    mov     eax, 0
    mov     esi, 0
    mov     edi, 0
    mov     ebx, [ebp + 8]                      ; ebx = infix
    mov     ecx, [ebp + 16]                     ; ecx = post_len
    mov     edx, [ebp + 12]                     ; edx = postfix

comparison:
    mov     al, [edx + esi]
    cmp     al, '+'
    je      operation
    cmp     al, '-'
    je      operation
    cmp     al, '*'
    je      operation
    cmp     al, '/'
    je      operation
    cmp     al, ' '
    je      opexit

    inc     esi
    push    eax
    loop    comparison


operation:
    mov     [operators], eax
    pop     eax
    mov     [operand], eax
    pop     eax

    ;This point here is what I specifically need to figure out...
    pusha
    push    dword[operand]  
    push    eax
    call    strcat
    add     esp,8
    popa


opexit:
    inc     esi
    loop    comparison

    pop ebx
    pop ebp
    ret



; A subprogram strcat appends the contents of one string to the end of another
; strcat(str1,str2)
; Result: str1= str1 + str2
; stored in str1
segment .bss
append_length   resd 1
read_length     resd 1
segment .text
strcat: 
    push    ebp                             ; 
    mov     ebp, esp                        ;
    mov     edx, [ebp+12]                   enter code here; what we want to append

    push    edx                             ;
    call    length_is                       ;
    add     esp, 4                          ;
    mov     [append_length], eax            ;
    mov     eax, 0                          ;

    mov     ebx, [ebp+8]                    ; original string str1

    push    ebx                             ;
    call    length_is                       ;
    add     esp, 4                          ;
    mov     [read_length], eax              ;
    mov     eax, 0                          ;

    mov     ebx, [ebp+8]                    ; original string str1
    mov     edx, [ebp+12]                   ; what we want to append
    mov     ecx, [append_length]            ;
    mov     edi, 0                          ;
    mov     esi, [read_length]              ; the last location of original string is where to append 

append_loop:
    mov     al, [edx+edi]                   ;
    mov     [ebx+esi], al                   ;
    add     esi, 1                          ;
    add     edi, 1                          ;
    loop    append_loop                     ;

    pop     ebp                             ;
    ret 

Программа предназначена для преобразования постфикса в префикс и отображения его пользователю. Мне нужна помощь, чтобы выяснить, как вызывать эти подпрограммы или как я мог бы использовать их для получения правильного результата.

1 Ответ

0 голосов
/ 05 апреля 2019

Очевидно, что если вы используете pusha / popa вокруг вызова функции, popa уничтожает возвращаемое значение в EAX, заменяя его тем, что было в EAX до вызова.Не делайте этого.

Просто позвольте функциям перекрывать регистры, перекрывающие вызовы (EAX, ECX и EDX в соглашении о вызовах i386 System V 1 ), и используйте эти регистры для временныхили что-то, что не нужно переживать при вызове функции.


Сноска 1: И почти все остальные 32-битные соглашения о вызовах x86.Но если вы когда-нибудь захотите узнать больше о том, как передавать аргументы (например, функциям, которые принимают структуру), вы можете посмотреть на выходные данные компилятора C или посмотреть документацию по i386 System V ABI.

...