assemblynasmx86-16

How to sum up all ascii values of elements in a stack in assembly x86


At this point i feel pretty lost, that's why my code looks like that

org 100h

start:
    xor ax, ax          
    xor dx, dx          
    mov ah, 1           
    xor cx, cx          

input:
    int 21h             
    cmp al, '+'         
    jz sum          

    push ax             
    inc cx              
    jmp input      

sum:
    push bp              
    mov bp, sp           
    mov cx, [bp+4]       
    mov si, 6            
    xor ax, ax          

sum_loop:
    push bp
    mov bp, sp
    mov ax, [bp+6]
    mov bx, [bp + 4]
    add ax, bx
    mov [result], ax
    pop ax
    loop sum_loop 
    pop bp; 
    ret

print:
    mov al, [result]
    mov bl, 10
    div bl
    mov [pt_one], ah
    
    xor ah, ah
    
    div bl
    mov [pt_two], ah
    xor ah, ah
    
    add al, 48
    mov dl, al
    mov ah, 2
    int 21h
    
    mov al, [pt_two]
    add al, 48
    mov dl, al
    mov ah, 2
    int 21h
    xor al, al
    
    mov al, [pt_one]
    add al, 48
    mov dl, al
    mov ah, 2
    int 21h
    
    mov ax, 4c00h
    int 21h
    
section .data
    pt_one db 1
    pt_two db 1
    result db 0

Here I'm sure that part with input is working, but I can't figure out if it's either my faulty summing protocol or my way fo printing is bad. In summing I try to add 2 next elements and add it to result variable, then remove top of the stack. When I try this code (Usually I go with input 123+) and I put + nothing happens and I frankly have no idea how to fix it.


Solution

  • One problem is caused by ret instruction. ret pops address from stack and loads it into program counter. But you never call this code as a function, so stack doesn't contain any valid return address. The program jumps to "random" address, in particular to 0100h ORed with ASCII code of last input character before +. If your input is 123+, the bogus address is 0133h. Casually it happened that there is mov bl, 10 instruction, so mov al, [result] is skipped. Then div bl tries to divide ax by 10, but ax value depends on initial bp value (after push bp / pop ax) which is undefined in general.

    There are other issues with the code:

    The program can be simplified: keep temporary values in registers instead of storing them to memory. I assume the goal is to explicitly iterate over stack, without poping values or adding them directly on each input iteration without storing them into memory. In this case complete program can be the following:

    org 100h
    
    start:
        mov ah, 1
        xor cx, cx
    
    input:
        int 21h
        cmp al, '+'
        jz sum
    
        push ax
        inc cx
        jmp input
    
    sum:
        mov bp, sp  ; bp points to stack top
        xor ax, ax  ; initial sum is 0
    
        jcxz print  ; skip if no characters entered
    
    sum_loop:
        add al, [bp]    ; add low byte only
        ; hint: you also can `adc ah, 0` here to get 16-bit sum in ax
        add bp, 2       ; next 16-bit word
        loop sum_loop
    
    print:
        mov sp, bp    ; restore initial stack pointer
        ; ah is already zeroed
    
        ; the rest of code is unchanged
        mov bl, 10
        div bl
        mov [pt_one], ah
    
        xor ah, ah
    
        div bl
        mov [pt_two], ah
        xor ah, ah
        
        add al, 48
        mov dl, al
        mov ah, 2
        int 21h
    
        mov al, [pt_two]
        add al, 48
        mov dl, al
        mov ah, 2
        int 21h
        xor al, al
    
        mov al, [pt_one]
        add al, 48
        mov dl, al
        mov ah, 2
        int 21h
    
        mov ax, 4c00h
        int 21h
    
    section .data
        pt_one db 1
        pt_two db 1