Search code examples
assemblyx86dosmasm

Output the loop in masm


I'm trying to simply output CX's values (binary) in loop l1 with OutBin proc, but it gives me only its first value (10).

I guess there's some problem with the loop itself, with saving registers before calling procedure, but I don't know how to fix everything.

 .model small
.stack 100h
.data
  ;  X dw 10  DUP (1,2,3)
.code
.startup
  mov cx, 10
  l1:
    mov ax, cx
    push cx
    call OutBin
    pop cx
  loop l1

OutBin proc
; AX to print
    mov bx, ax
    mov cx, 16
  ob1:
    shl bx,1
    jc ob2
    mov dl,'0'
    jmp ob3
  ob2:
    mov dl, '1'
  ob3:
    mov ah,2
    int 21h
  loop ob1
;call NewLine
OutBin endp

NewLine proc
    mov dx, 0Dh
    mov ah,2
    int 21h
    mov dx, 0Ah
    mov ah,2
    int 21h
NewLine endp 

.exit
end

Solution

  • Your program has 2 procedures OutBin and NewLine. Both are missing the ret instruction just above their endp directives.

    What your program also misses is a descent exit to DOS.
    Look what happens when the l1 loop has finished.

    loop l1
    
    OutBin proc
    

    The code mistakenly falls through in the OutBin procedure. You'll have to insert the necessary intructions to return to DOS:

    loop l1
    
    mov ax, 4C00h   ;DOS.TerminateWithExitcode
    int 21h
    
    OutBin proc
    

    Some additional debugging

    X dw 10  DUP (1,2,3)
    

    Guessing that your ultimate goal is to display 10 numbers (mov cx, 10) taken from the array X, this dw directive is actually defining 30 numbers.

    1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3
    

    That's probably not what you wanted.

    Notice that once you start reading from the array X, you'll have to setup the segment registers first. With .model small they don't automatically point to your .data. If you used .model tiny, they would though.


    A small but important improvement

      shl bx,1
      jc ob2
      mov dl,'0'
      jmp ob3
    ob2:
      mov dl, '1'
    ob3:
    

    The above code can be simplified to the much better:

    mov dl, '0'
    shl bx, 1
    adc dl, 0
    

    If no carry was shifted out, the dl register will remain '0'.
    If a carry is shifted out, the dl register will get incremented to '1'