krb
krb

Reputation: 16315

Printing out a number in assembly language?

mov al,10
add al,15

How do I print the value of 'al'?

Upvotes: 32

Views: 247490

Answers (10)

Sep Roland
Sep Roland

Reputation: 39166

Displaying numbers with DOS explains the general method of outputting a numerical value to the screen. However the question seems to specifically ask about displaying what's in the AL register. For that we can write a specific code that uses the AAM instruction. This instruction divides the AL register by 10 and leaves the quotient in AH and the remainder in AL.

Because the byte-sized AL register can hold an unsigned value between 0 and 255, there can be at most 3 decimal digits for which we need to perform 2 divisions by 10.

Next codes use the DOS.DisplayCharacter function 02h to output to the screen (provided output is not redirected).

The first code does not show leading zeroes:

  aam
  add  al, '0'
  mov  bl, al
  mov  al, ah
  aam
  mov  cx, ax
  mov  ah, 02h       ; DOS.DisplayCharacter
  jcxz .UnitsOnly
  test ch, ch
  jz   .NoHundredths
  mov  dl, ch
  add  dl, '0'
  int  21h           ; -> (AL)
.NoHundredths:
  mov  dl, cl
  add  dl, '0'
  int  21h           ; -> (AL)
.UnitsOnly:
  mov  dl, bl
  int  21h           ; -> (AL)

The second code always displays 3 digits:

  aam
  add  al, '0'
  mov  bl, al
  mov  al, ah
  aam
  add  ax, '00'
  mov  cx, ax
  mov  ah, 02h       ; DOS.DisplayCharacter
  mov  dl, ch
  int  21h           ; -> (AL)
  mov  dl, cl
  int  21h           ; -> (AL)
  mov  dl, bl
  int  21h           ; -> (AL)

Upvotes: 1

yasir
yasir

Reputation: 15

; good example of unlimited num print
.model small
.stack 100h
.data
number word 6432
string db 10 dup('$')
.code
main proc
mov ax,@data 
mov ds,ax
mov ax,number
mov bx ,10
mov cx,0
l1:
mov dx,0
div bx
add dx,48
push dx
inc cx
cmp ax,0
jne l1
mov bx ,offset string 
l2:
pop dx           
mov [bx],dx
inc bx
loop l2
mov ah,09
mov dx,offset string
int 21h
mov ax,4c00h
int 21h

main endp

end main

Upvotes: -1

adrian
adrian

Reputation: 1457

Assuming you are writing a bootloader or other application that has access to the BIOS, here is a rough sketch of what you can do:

  • Isolate the first digit of the hex byte
  • If it is greater than 9 (i.e. 0x0A to 0x0F), subtract 10 from it (scaling it down to 0 to 5), and add 'A' (0x41).
  • If it is less than or equal to 9 (i.e. 0x00 to 0x09), add '0' to it.
  • Repeat this with the next hex digit.

Here is my implementation of this:

; Prints AL in hex.
printhexb:
    push ax
    shr al, 0x04
    call print_nibble
    pop ax
    and al, 0x0F
    call print_nibble
    ret
print_nibble:
    cmp al, 0x09
    jg .letter
    add al, 0x30
    mov ah, 0x0E
    int 0x10
    ret
.letter:
    add al, 0x37
    mov ah, 0x0E
    int 0x10
    ret   

Upvotes: 0

user6849738
user6849738

Reputation: 1

AH = 09 DS:DX = pointer to string ending in "$"

returns nothing


- outputs character string to STDOUT up to "$"
- backspace is treated as non-destructive
- if Ctrl-Break is detected, INT 23 is executed

ref: http://stanislavs.org/helppc/int_21-9.html


.data  

string db 2 dup(' ')

.code  
mov ax,@data  
mov ds,ax

mov al,10  
add al,15  
mov si,offset string+1  
mov bl,10  
div bl  
add ah,48  
mov [si],ah  
dec si  
div bl  
add ah,48  
mov [si],ah  

mov ah,9  
mov dx,string  
int 21h

Upvotes: 0

Dirk Wolfgang Glomp
Dirk Wolfgang Glomp

Reputation: 539

DOS Print 32 bit value stored in EAX with hexadecimal output (for 80386+)
(on 64 bit OS use DOSBOX)

.code
    mov ax,@DATA        ; get the address of the data segment
    mov ds,ax           ; store the address in the data segment register
;-----------------------
    mov eax,0FFFFFFFFh  ; 32 bit value (0 - FFFFFFFF) for example
;-----------------------
; convert the value in EAX to hexadecimal ASCIIs
;-----------------------
    mov di,OFFSET ASCII ; get the offset address
    mov cl,8            ; number of ASCII
P1: rol eax,4           ; 1 Nibble (start with highest byte)
    mov bl,al
    and bl,0Fh          ; only low-Nibble
    add bl,30h          ; convert to ASCII
    cmp bl,39h          ; above 9?
    jna short P2
    add bl,7            ; "A" to "F"
P2: mov [di],bl         ; store ASCII in buffer
    inc di              ; increase target address
    dec cl              ; decrease loop counter
    jnz P1              ; jump if cl is not equal 0 (zeroflag is not set)
;-----------------------
; Print string
;-----------------------
    mov dx,OFFSET ASCII ; DOS 1+ WRITE STRING TO STANDARD OUTPUT
    mov ah,9            ; DS:DX->'$'-terminated string
    int 21h             ; maybe redirected under DOS 2+ for output to file
                        ; (using pipe character">") or output to printer

  ; terminate program...

.data
ASCII DB "00000000",0Dh,0Ah,"$" ; buffer for ASCII string

Alternative string output directly to the videobuffer without using software interupts:

;-----------------------
; Print string
;-----------------------
    mov ax,0B800h       ; segment address of textmode video buffer
    mov es,ax           ; store address in extra segment register

    mov si,OFFSET ASCII ; get the offset address of the string

; using a fixed target address for example (screen page 0)
; Position`on screen = (Line_number*80*2) + (Row_number*2)

    mov di,(10*80*2)+(10*2)
    mov cl,8            ; number of ASCII
    cld                 ; clear direction flag

P3: lodsb  ; get the ASCII from the address in DS:SI + increase si
    stosb  ; write ASCII directly to the screen using ES:DI + increase di
    inc di ; step over attribut byte
    dec cl ; decrease counter
    jnz P3 ; repeat (print only 8 ASCII, not used bytes are: 0Dh,0Ah,"$")

; Hint: this directly output to the screen do not touch or move the cursor
; but feel free to modify..

Upvotes: 5

ayat ziaee from iran
ayat ziaee from iran

Reputation: 35

PRINT_SUM PROC NEAR
 CMP AL, 0
 JNE PRINT_AX
 PUSH AX
 MOV AL, '0'
 MOV AH, 0EH
 INT 10H
 POP AX
 RET 
    PRINT_AX:    
 PUSHA
 MOV AH, 0
 CMP AX, 0
 JE PN_DONE
 MOV DL, 10
 DIV DL    
 CALL PRINT_AX
 MOV AL, AH
 ADD AL, 30H
 MOV AH, 0EH
 INT 10H    
    PN_DONE:
 POPA  
 RET  
PRINT_SUM ENDP

Upvotes: 1

Rushyo
Rushyo

Reputation: 7604

You might have some luck calling the Win32 API's MessageBoxA, although whether Win16 supports that particular method is for someone else to answer.

Upvotes: 0

mrkj
mrkj

Reputation: 3101

Have you tried int 21h service 2? DL is the character to print.

mov dl,'A' ; print 'A'
mov ah,2
int 21h

To print the integer value, you'll have to write a loop to decompose the integer to individual characters. If you're okay with printing the value in hex, this is pretty trivial.

If you can't rely on DOS services, you might also be able to use the BIOS int 10h with AL set to 0Eh or 0Ah.

Upvotes: 38

anon
anon

Reputation:

Assembly language has no direct means of printing anything. Your assembler may or may not come with a library that supplies such a facility, otherwise you have to write it yourself, and it will be quite a complex function. You also have to decide where to print things - in a window, on the printer? In assembler, none of this is done for you.

Upvotes: 9

Roman
Roman

Reputation: 66156

Call WinAPI function (if u are developing win-application)

Upvotes: -2

Related Questions