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?

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

- 140.8K All Categories
- 103.6K Programming Languages
- 6.4K Assembler Developer
- 401 Assembly Code Share
- 239 Getting started in assembly
- 4.6K x86 Assembly
- 1.9K Basic
- 97 Qbasic
- 39.9K C and C++
- 5.6K Beginner C/C++
- 330 C/C++ on Linux/Unix
- 450 C/C++ Windows API
- 522 C++ Builder
- 253 C++ Game Development
- 3.3K C++ MFC
- 103 C++.NET
- 404 Visual C++
- 2.9K C#
- 7.9K Delphi and Kylix
- 334 Advanced Delphi
- 360 Delphi beginners
- 4 Haskell
- 9.7K Java
- 56 Enterprise JavaBeans
- 1.3K Java Beginners
- 304 Java Server Pages
- 4.1K Pascal
- 1.3K Perl
- 11 Perl 6
- 2K PHP
- 546 Python
- 37 Ruby
- 4.4K VB.NET
- 258 Advanced VB.Net
- 1.6K VBA
- 20.8K Visual Basic
- 767 Access databases and VB
- 831 Advance Visual Basic
- 1.2K Beginner VB
- 2.6K Game programming
- 315 Console programming
- 90 DirectX Game dev
- 1 Minecraft
- 112 Newbie Game Programmers
- 2 Oculus Rift
- 9K Applications
- 1.8K Computer Graphics
- 279 3D Graphics
- 129 DirectX
- 125 OpenGL
- 740 Computer Hardware
- 9 Cooling & Overclocking
- 3.4K Database & SQL
- 1.1K Access
- 91 ADO Programming
- 288 MySQL
- 358 Oracle
- 440 SQL-Server
- 535 Electronics development
- 1.6K Matlab
- 628 Sound & Music
- 25 DirectSound
- 257 XML Development
- 3.3K Classifieds
- 199 Co-operative Projects
- 198 For sale
- 190 FreeLance Software City
- 1.9K Jobs Available
- 603 Jobs Wanted
- 209 Wanted
- 2.9K Microsoft .NET
- 1.8K ASP.NET
- 1.1K .NET General
- 22 .NET WEB-Services
- 129 .NET WinForms
- 14 .NET XML
- 50 ADO.NET
- 142 C# & VB.NET School Support
- 3.4K Miscellaneous
- 4 Join the Team
- 354 Comments on this site
- 69 Computer Emulators
- 2.1K General programming
- 187 New programming languages
- 621 Off topic board
- 200 Mobile & Wireless
- 72 Android
- 126 Palm Pilot
- 338 Multimedia
- 154 Demo programming
- 184 MP3 programming
- 0 Bash scripts
- 27 Cloud Computing
- 1 Witsbits Go Cloud
- 53 FreeBSD
- 1.7K LINUX programming
- 1 Awk scripting
- 332 Linux Support
- 0 Sed scripting
- 370 MS-DOS
- 0 Shell scripting
- 321 Windows CE & Pocket PC
- 4.1K Windows programming
- 177 COM/DCOM
- 61 Networking And Security
- 17 Windows 2003 Server
- 6 Windows Vista
- 176 Windows XP
- 939 Software Development
- 416 Algorithms
- 68 Object Orientation
- 24 RUP & UML
- 91 Project Management
- 95 Quality & Testing
- 268 Security
- 63 Evil Scripting
- 81 Hacking
- 7.7K WEB-Development
- 1.8K Active Server Pages
- 61 AJAX
- 4 Bootstrap Themes
- 55 CGI Development
- 28 ColdFusion
- 224 Flash development
- 1.4K HTML & WEB-Design
- 1.4K Internet Development
- 131 Mobile Internet & Messaging
- 211 Wireless development
- 2.2K JavaScript
- 37 JQuery
- 304 WEB Servers
- 153 Apache
- 79 IIS
- 150 WEB-Services / SOAP

## Comments

I'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

[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]