It looks like you're new here. If you want to get involved, click one of these buttons!

- 141K All Categories
- 103.8K Programming Languages
- 6.5K Assembler Developer
- 1.9K Basic
- 40K C and C++
- 2.9K C#
- 7.9K Delphi and Kylix
- 4 Haskell
- 9.7K Java
- 4.1K Pascal
- 1.3K Perl
- 2K PHP
- 551 Python
- 37 Ruby
- 4.4K VB.NET
- 1.6K VBA
- 20.9K Visual Basic
- 2.6K Game programming
- 317 Console programming
- 92 DirectX Game dev
- 1 Minecraft
- 112 Newbie Game Programmers
- 2 Oculus Rift
- 9K Applications
- 1.8K Computer Graphics
- 744 Computer Hardware
- 3.5K Database & SQL
- 535 Electronics development
- 1.6K Matlab
- 628 Sound & Music
- 258 XML Development
- 3.3K Classifieds
- 199 Co-operative Projects
- 198 For sale
- 190 FreeLance Software City
- 1.9K Jobs Available
- 604 Jobs Wanted
- 210 Wanted
- 2.9K Microsoft .NET
- 1.8K ASP.NET
- 1.1K .NET General
- 3.4K Miscellaneous
- 7 Join the Team
- 355 Comments on this site
- 70 Computer Emulators
- 2.1K General programming
- 187 New programming languages
- 629 Off topic board
- 217 Mobile & Wireless
- 89 Android
- 126 Palm Pilot
- 340 Multimedia
- 156 Demo programming
- 184 MP3 programming
- Bash scripts
- 27 Cloud Computing
- 53 FreeBSD
- 1.7K LINUX programming
- 370 MS-DOS
- Shell scripting
- 321 Windows CE & Pocket PC
- 4.1K Windows programming
- 942 Software Development
- 417 Algorithms
- 68 Object Orientation
- 92 Project Management
- 95 Quality & Testing
- 269 Security
- 7.7K WEB-Development
- 1.8K Active Server Pages
- 62 AJAX
- 5 Bootstrap Themes
- 55 CGI Development
- 28 ColdFusion
- 224 Flash development
- 1.4K HTML & WEB-Design
- 1.4K Internet Development
- 2.2K JavaScript
- 37 JQuery
- 308 WEB Servers
- 152 WEB-Services / SOAP

Bret
Member Posts: **114**

in x86 Assembly

I'm writing some code that needs to be compatible with a 16-bit CPU (8086/8088). I have a 32-bit number stored in two word registers (e.g., DX:AX) and I need to write the value of the number in decimal format. For example, FFFF_FFFFh needs to be written as 4294967295.

Anybody have some sample code on how to do this?

Anybody have some sample code on how to do this?

Terms of use / Privacy statement / Publisher: Lars Hagelin

Programmers Heaven articles / Programmers Heaven files / Programmers Heaven uploaded content / Programmers Heaven C Sharp ebook / Operated by CommunityHeaven

© 1997-2017 Programmersheaven.com - All rights reserved.

## Comments

1141I'm using an old TMS9900 processor, and need to do some 32 bit arithmetic. I have done the adding and subraction (and by extension, multiplication and division), but the thing that is stumping me, is how do I display a 32 bit value, which is split across two 16 registers, in decimal, when the largest useful dividend I can express (for base 10) is 10,000. Hmmmph....

So, basically, I have: 1,234,567 which exists in the memory as:

First 16 bit word: $0012

Second 16 bit word: $D687

(The TMS9900 is big endian)

And I've got to convert that into 1234567 for screen display purposes.

Crikey. Bit stumped on that one!

(The TMS9900 has '32 bit' multiply and divide, but....

Multiply: You can multiply two 16 bit values, giving a 32 bit result.

Divide: You can divide a 32 bit value, by a 16 bit dividend (hence the largest 'useful' divisor for base 10 is 10,000).

I'd be extremely interested to see your solution. I hope I can understand Intel assembly!

Thanks

Mark

114[code]

;------------------------------------------------------------------------------

;WRITE A DWORD TO THE SCREEN AS A DECIMAL

;Inputs: DX:AX = DWord to Write

;Outputs: To Screen

;Changes:

;------------------------------------------------------------------------------

WriteDWordMin:

PUSH AX,BX,CX,DX ;Save used registers

PUSH DI,SI,BP ;Save used registers

MOV SI,03B9Ah ;Start Divisor (SI:DI)

MOV DI,0CA00h ; at 1,000,000,000

XOR BP,BP ;Initialize character counter

D10: ;Loop to here for each possible character

MOV CX,SI ;CX:BX =

MOV BX,DI ; Divisor

CALL Divide32s ;Do the division (rtns Quotient DX:AX, Remainder CX:BX)

OR AX,AX ;Non-zero character?

JNZ >D20 ;If so, we need to write it

OR BP,BP ;Has there already been a non-zero character?

JNZ >D20 ;If so, we need to write it

OR SI,SI ;Is this the last character?

JNZ >D40 ;If not, we don't need to write it

CMP DI,1 ;Is this the last character?

JNE >D40 ;If so, we need to write it

D20: ;Need to write this character

INC BP ;Increment character counter

ADD AL,'0' ;Convert the Number to ASCII

D30: ;Write the character

CALL WriteAL ;Write it

D40: ;Done writing character, if appropriate

OR SI,SI ;Was this the units character?

JNZ >D45 ;If not, continue

CMP DI,1 ;Was this the units character?

JE >D90 ;If so, we're done

D45: ;Not done yet

MOV DX,SI ;DX:AX =

MOV AX,DI ; Current Divisor

PUSH CX,BX ;Save Current Remainder (New Dividend) on the stack

XOR CX,CX ;Divisor (CX:BX) =

MOV BX,10 ; 10

CALL Divide32s ;Do the division (calculate new Divisor)

MOV SI,DX ;SI:DI =

MOV DI,AX ; New Divisor

POP AX,DX ;DX:AX = New Dividend (Old Remainder)

JMP D10 ;Keep going

D90: ;We're done

POP BP,SI,DI ;Restore used registers

POP DX,CX,BX,AX ;Restore used registers

RET

;------------------------------------------------------------------------------

;DIVIDE TWO 32-BIT NUMBERS BY EACH OTHER, USING ONLY 16-BIT OPERATIONS

;Inputs: DX:AX = Dividend

; CX:BX = Divisor

;Outputs: DX:AX = Quotient

; CX:BX = Remainder

;Changes:

;NOTES: This is UNSIGNED division!

; This is also a slow division process, but the code is small and

; we only do it a few times in this program if we do it at all,

; so there's no compelling need to optimize for speed.

; This does not check for division by 0 (returns -1 instead of an error).

; I find the code quite interesting, because it does not actually require

; the CPU to do any divison at all -- only shifts, compares, and

; subtracts. The main reason it's so slow is that the loop must be

; performed all 32 times -- there's no way to exit early.

; This implementation came from The Art of Assembly Language by

; Randall Hyde. This is an ASM implementation of the following

; pseudocode:

;

; Quotient := Remainder;

; Remainder := 0;

; FOR I := 1 TO NumberOfBits DO

; Remainder:Quotient := Remainder:Quotient SHL 1;

; IF Remainder >= Divisor THEN

; Remainder := Remainder - Divisor;

; Quotient := Quotient + 1;

; ENDIF

; ENDFOR

;

; During the entire routine:

; DX:AX = Dividend

; CX:BX = Divisor

; SI:DI = Remainder

;------------------------------------------------------------------------------

Divide32s:

OR CX,CX ;Is the Divisor really 32 bits?

JNZ >V20 ;If so, handle it

CMP DX,BX ;Will we only need to do one division?

JB >V10 ;If so, jump to handle it

MOV CX,AX ;CX = Dividend-Low

MOV AX,DX ;DX:AX =

XOR DX,DX ; Dividend

DIV BX ;Do the Division (AX = Quotient)

XCHG AX,CX ;CX = Quotient-High, AX = Dividend-Low

V10: ;First division handled, if appropriate

DIV BX ;AX = Quotient-Low

MOV BX,DX ;BX = Remainder-Low

MOV DX,CX ;DX = Quotient-High

XOR CX,CX ;CX = Remainder-High

JMP >V90 ;Done

V20: ;Divisor really is 32 bits

PUSH DI,SI,BP ;Save used registers

MOV BP,32 ;Do 32 bits

XOR SI,SI ;Remainder :=

XOR DI,DI ; 0

V30: ;Loop to here for each bit

SHL AX,1 ;Remainder:Quotient :=

RCL DX,1 ; Remainder:Quotient

RCL DI,1 ; SHL

RCL SI,1 ; 1

CMP SI,CX ;Remainder HO word more than Divisor HO word?

JA >V40 ;If so, handle it

JB >V50 ;If not, we're done with this bit

V35: ;Remainder HO word = Divisor HO word

CMP DI,BX ;Remainder LO word more than Divisor LO word?

JB >V50 ;If not, we're done with this bit

V40:

SUB DI,BX ;Remainder :=

SBB SI,CX ; Remainder - Divisor

INC AX ;Increment Quotient

V50: ;Go to the next bit

DEC BP ;Decrement Loop Counter

JNZ V30 ;If not 0 yet, keep looking

MOV CX,SI ;Put Remainder

MOV BX,DI ; in CX:BX for the return

POP BP,SI,DI ;Restore used registers

V90: ;Done

RET

[/code]