Search code examples
assemblyx86emu8086

Assembly x86 | return(ret) is not working


Well, recently I started learning Assembly 8086 out of curiosity mostly.

Input in assembly allows you to type only one character, so I tried to make a program in Assembly 8086 that allows you to enter multi-digit integer input, ending the input with "space"(' '), then adding the number and printing the value.

I saw that push and pop can be used to pass arguments to a procedure but I tried to use them to make my procedure return something and store it to a variable, I couldn't imagine a way to do this with ret based on my knowledge on Assembly 8086 so...anyway, I made a procedure, but for some reason the ret at the end of the procedure doesn't seem to work and the procedure runs infinite times.

The code so far:

.model small
org 100h

.data

    fv db 0 ;variables to store the numbers
    sv db 0 ;

.code
    jmp start ;a pattern of mine in some way to avoid a procedure be called twice and what everyone shows 
              ;just doesn't work, after the main ends, all the procs run again,
              ;it worked perfectly any other time I used procedures to my program

    f1 proc   ;the procedure

        mov cl, 0 ;clear cl bcs later the first time is used I have not stored some thing in there and 
                  ;always for some reason, to all my programs "cx" has a value stored, maybe from the
                  ;emulator I use

        mov ah, 1h ;single character input
        int 21h    ;

        while:
            cmp al, ' ' ;if input is equal to "space"("space" must be the last input, as far as I have
                        ;gone with the program)
            jne true    ; if input != ' '
            je false    ; if input == ' '
            true:       ; in case input != ' '
                mov bl, al ;store the input
                mov al, cl ;digits taken from input previously
                sub bl, 30h;bcs if input == 8, whatactually is stored is the ASCII code of it in this
                           ;case : 38h or 56

                mov dl, 10 ;What I thought : if user writes as input 12, what actually types 1 * 10 + 2
                           ;so I am storing 10 to dl to multiply the previously entered numbers in the
                           ;example above : 1

                mul dl     ;multiplication

                add al, bl ;add new input to (old inputs * 10)

                mov cl, al ;store old inputs

                mov ah, 1h ;input
                int 21h    ;
                jmp while  ;check again if input == ' ' or not
        false: ;in case input == ' '
            mov ch, 0 ; in chase ch had some thing else in it from something else than the
                      ; input(0 <= input <= 127~128(127 + 128 = 255))
            push cx   ; store cx(final result from the inputs) in to the stack to store it to a 
                      ; variable

            ret       ; end procedure
    f1 endp           ; 

    start:            ; with "jmp start" at the start of the ".code" makes the program start from "main"
    main proc

        call f1    ;call procedure
        pop bx     ;store result in to bx bcs `push` and `pop` as far as I know need at least 16-bit
                   ;and varables are 8-bit, I know I can make them 16-bit but anyway
        mov fv, bl ;store result to variable   

    endp
end main

Solution

  • Well, I found it, before I push anything else to the stack(I searched how push, pop, call and ret work)I pop-ed in to bx and then after I push-ed to the stack what I wanted to push, before ret I push-ed what was to bx(the addres ret was supposed to jump) and then I ret.

    Code :

    .model small
    org 256
    
    .data
    
        fv db 0
        sv db 0
    
    .code
        jmp start
    
        f1 proc
    
            mov cl, 0
            mov ah, 1h
            int 21h
    
            while:
                cmp al, ' '
                jne true
                je false
                true:
                    mov bl, al
                    mov al, cl
                    sub bl, 30h
                    mov dl, 10
                    mul dl
                    add al, bl
                    mov cl, al
                    mov ah, 1h
                    int 21h
                    jmp while
            false:
                pop bx
                mov ch, 0
                push cx
                push bx    
                ret
        f1 endp
    
        start:
        main proc
    
            call f1
            pop bx
            mov fv, bl    
    
        endp
    end main