; ; CPASM03S.ASM ; written by Keith Fenske ; Saturday, 9 March 2002 ; Copyright (c) 2002 by Keith Fenske. All rights reserved. ; ; This is an Intel 80x86 assembly language program to convert a signed ; 16-bit binary number to printed decimal form. The number is declared as ; an arbitrary word in this program file; there is no input from the user. ; ; The following changes are made from CPASM02S.ASM: ; ; (1) The number is signed, and we must sometimes print a minus sign. ; (2) The printed number has leading spaces, not zeros. ; ; Since we are converting a signed binary number from -32768 to +32767, it ; would appear that we should use the signed division instruction (IDIV) ; instead of the unsigned division instruction (DIV). However, it is easier ; to convert non-negative numbers to ASCII, so first we convert any negative ; number to a positive number (with a sign flag). Then the division will be ; operating on a number from 0 to 32768, and we can use either signed or ; unsigned division since clearing DX makes DX:AX unsigned for division. ; ; To test the program properly, the number should be changed several times ; and the program re-assembled and re-run. ; ; The required assembly concepts are: basic instructions, loops, and ; documentation for the DIV/IDIV instructions. ; [BITS 16] ; set 16-bit code generation [ORG 0100H] ; set address of first instruction in COM file CR equ 0Dh ; carriage return character LF equ 0Ah ; line feed character [SECTION .text] ; start code (instruction) section start: ; ; Clear the output string to blanks (20h). Yes, we could do this when we ; declare the data section; however, in general, conversions are done many ; times in the same program, and we don't want to use old garbage sitting ; in the output string. ; mov cx,6 ; five digits to clear, plus space for minus sign mov di,digits-1 ; start clearing from sign byte (before first digit) clear: mov [di],byte 20h ; put blank character in this digit inc di ; address of next digit loop clear ; repeat until CX=0 (six times) ; ; For positive numbers, set the sign flag to zero. ; ; For negative numbers, set the sign flag to one, and negate the number ; because it is easier to convert a non-negative number to ASCII text. ; mov [signflag],byte 0 ; assume number is zero or positive mov ax,[number] ; put signed number in AX register cmp ax,0 ; is this number negative? jge positive ; no, zero or positive: do nothing more mov [signflag],byte 1 ; set flag for later minus sign neg ax ; convert negative signed number to positive positive: ; ; Convert one decimal digit at a time to ASCII. We have to do this ; *backwards* by dividing by ten and using the remainder. ; ; The AX register contains the number to be converted. This number will ; be zero or positive. ; mov bx,10 ; we will divide by ten mov cx,5 ; maximum number of digits to convert is 5 ; minimum number of digits to convert is 1 mov di,digits+4 ; address of last digit in output string convert: mov dx,0 ; clear DX before dividing DX:AX by BX idiv bx ; result: AX has quotient, DX has remainder add dl,'0' ; convert byte remainder to single-digit ASCII mov [di],dl ; save low-order byte as ASCII in output digits dec di ; address of previous digit in output string cmp ax,0 ; test if quotient is now zero je putsign ; stop conversion early if quotient reaches zero loop convert ; repeat for up to CX=5 digits ; ; Put a negative sign in the output string, if the original number was ; negative. The DI register has the address of the byte before the first ; digit in the output string. ; putsign: cmp [signflag],byte 0 ; was original number negative? je write ; no, zero or positive: do nothing mov [di],byte '-' ; insert minus sign ; note: we don't use the DI register again, so there ; is no need to decrement it after inserting '-' ; ; Write the output string. ; write: mov bx,1 ; DOS file handle 1 is standard output mov cx,length ; length of string in bytes mov dx,string ; address of first byte in string mov ah,40h ; DOS function code for write string int 21h ; call DOS mov ah,4Ch ; DOS function code to exit program mov al,0 ; pass this value back as ERRORLEVEL int 21h ; call DOS (does not return) [SECTION .data] ; start data section ; ; The output string has several parts. We only change the part that has ; the digits and the sign. A dummy string of "-99999" is used for the ; converted number so that we reserve the right amount of space. ; number dw -31245 ; 16-bit signed binary number signflag db 0 ; flag is non-zero if number is negative string db "Signed decimal number is " db "-" ; optional minus sign digits db "99999" ; where decimal digits db ".", CR, LF ; new line characters length equ $ - string ; ; End of CPASM03S.ASM ;