Coder4Fun250
Coder4Fun250

Reputation: 143

Can't print out 8-bit values of registers

I'm trying to print out current year (CX), month (DH), day (DL) and day of the week (AL) from system timer.

Year stored in CX is printed out correctly.

I tried to printout DH, DL and AL with print_number16bit (I called it print_number initially) but there was a type incompatibility error probably because I tried to pass an 8-bit register to a 16-bit register.

I decided to create a function for 8-bit numbers (print_number8bit initially), but was having weirdly large numbers (>255). I thought maybe it was because I tried to work with h registers like l registers (I passed DH to BL). So I decided to create 2 functions: print_number8bitl for l registers and print_number8bith for h registers. The DH is printed out correctly but the wrong month: 3 instead of 2. Other data is printed wrong (>255).

enter image description here

How do I print the numbers out correctly?

I'm a beginner in assembler and don't know a lot, I hope I get help.

SSEG    segment stack       
        db 256 dup(0)
SSEG    ends

DSEG    segment         
   whitespace db ' $'
DSEG    ends

CSEG    segment         
        assume cs:CSEG,ds:DSEG,ss:SSEG
begin:
        mov ax, DSEG    
        mov ds, ax  


    
    mov ah, 2Ah
    int 21h
    
    mov bx, cx
    call print_number16bit
    
    mov bh, dh
    call print_number8bith
    
    mov bl, dl
    call print_number8bitl
    
    mov bl, al
    call print_number8bitl
    
    mov ah,01h    
    int 21h         
                    

    mov ah,4ch      
    int 21h         

    
    print_number16bit proc
           mov si,10
           mov ax,bx
           mov cx,0
        a1:
           mov dx,0
           div si
           add dx,'0'
           push dx
           inc cx
           cmp ax,0
           jnz a1
        aa1:
           pop dx
           mov ah,02h
           int 21h
           loop aa1
           
           mov ah, 09h
           mov dx, offset whitespace
           int 21h
        ret
    endp
    
    print_number8bitl proc
           mov si,10
           mov al,bl
           mov cx,0
        a3:
           mov dx,0
           div si
           add dx,'0'
           push dx
           inc cx
           cmp al,0
           jnz a3
        aa3:
           pop dx
           mov ah,02h
           int 21h
           loop aa3
           
           mov ah, 09h
           mov dx, offset whitespace
           int 21h
        ret
    endp
    print_number8bith proc
           mov si,10
           mov ah,bh
           mov cx,0
        a4:
           mov dx,0
           div si
           add dx,'0'
           push dx
           inc cx
           cmp ah,0
           jnz a4
        aa4:
           pop dx
           mov ah,02h
           int 21h
           loop aa4
           
           mov ah, 09h
           mov dx, offset whitespace
           int 21h
        ret
    endp
    
    
CSEG    ends        

end begin   

    

Upvotes: 2

Views: 53

Answers (1)

Sep Roland
Sep Roland

Reputation: 39411

Your present 8-bit routines are wrong because they either forget to zero the AH register or the AL register.

The Q/A Displaying numbers with DOS not only explains in great detail how to display a number, it also answers the question about needing separate routines for numbers of different sizes. You only need your one 16-bit routine! But because you didn't preserve the registers, there's little hope to display a correct month (DH), day (DL), or day of the week (AL).

This is my suggestion:

; IN (cx) OUT (cx=0)
print_number16bit proc
  push ax
  push bx
  push dx
  mov  bx, 10
  mov  ax, cx
  xor  cx, cx       ; -> CX=0
.a:
  xor  dx, dx       ; -> DX=0
  div  bx
  add  dx, '0'
  push dx
  inc  cx
  test ax, ax
  jnz  .a
.b:
  pop  dx
  mov  ah, 02h
  int  21h
  loop .b
  mov  dl, ' '   ; whitespace
  int  21h
  pop  dx
  pop  bx
  pop  ax
  ret            ; Return with CX=0 (LOOP zeroed CX already)
endp

With these changes, the main part can use the next calling sequence:

                           ; CX is year
  call print_number16bit   ; -> CX=0
  mov  cl, dh              ; DH is month
  call print_number16bit   ; -> CX=0
  mov  cl, dl              ; DL is day
  call print_number16bit   ; -> CX=0
  mov  cl, al              ; AL is day of week
  call print_number16bit   ; -> CX=0

Upvotes: 0

Related Questions