92 lines
3.9 KiB
NASM
92 lines
3.9 KiB
NASM
|
; bcd.asm
|
||
|
comment ^
|
||
|
This is a small demonstration program to show how one might
|
||
|
handle the addition of IBM 370-style packed decimal numbers
|
||
|
(which are similar to BCD). This particular program imposes an
|
||
|
arbitrary simplifying limitation by only allowing the addition
|
||
|
of numbers which are both the same sign, but it would be easy to
|
||
|
extend by either converting all negative operands to ten's
|
||
|
complement and adding or by implementing a subtraction routine
|
||
|
(which would use SBB, DAS instead of ADC, DAA).
|
||
|
|
||
|
^
|
||
|
.MODEL small ; DOS - small model
|
||
|
.STACK 200h ; allocate a bit of stack
|
||
|
|
||
|
.DATA
|
||
|
OPLEN equ 4 ; the size of operands & result (bytes)
|
||
|
first db 00h, 01h, 23h, 4Ch ; 1234 in packed decimal
|
||
|
second db 00h, 00h, 00h, 9Ch ; 9 in packed decimal
|
||
|
result db OPLEN dup (?) ; allocate space for result
|
||
|
|
||
|
.CODE
|
||
|
.STARTUP
|
||
|
mov si,offset first + OPLEN - 1 ; point to first op
|
||
|
mov bx,offset second + OPLEN - 1 ; second op
|
||
|
mov di,ds ;
|
||
|
mov es,di ; load es
|
||
|
mov di,offset result + OPLEN - 1 ; point to result area
|
||
|
mov cx,OPLEN ; how big are they?
|
||
|
call AddPackedDecimal ; add 'em up!
|
||
|
.EXIT 0
|
||
|
;****************************************************************************
|
||
|
; AddPackedDecimal
|
||
|
;
|
||
|
; add two 370-style packed decimal numbers with identical signs
|
||
|
;
|
||
|
; Entry:
|
||
|
; DS:SI ==> end of first operand
|
||
|
; DS:BX ==> end of second operand
|
||
|
; ES:DI ==> end of pre-allocated result space
|
||
|
; CX = size of operands, result (in bytes)
|
||
|
;
|
||
|
; Exit:
|
||
|
; if CY set, error occurred
|
||
|
; otherwise, result of addition is in result space
|
||
|
;
|
||
|
; Trashed:
|
||
|
; none
|
||
|
;
|
||
|
;****************************************************************************
|
||
|
AddPackedDecimal proc
|
||
|
push ax ; save used regs
|
||
|
push bx
|
||
|
push cx
|
||
|
push dx
|
||
|
push di
|
||
|
push si
|
||
|
mov al,[si] ;
|
||
|
mov ah,[bx] ;
|
||
|
mov dx,ax ;
|
||
|
and dx,00f0fh ; use only low nybbles in DX
|
||
|
and ax,0f0f0h ; save high nybbles in AX
|
||
|
cmp dl,dh ; are they identical?
|
||
|
stc ; (assume they're not)
|
||
|
jnz Done ; if not, it's an error
|
||
|
std ; set dir flag (decrement ptrs)
|
||
|
clc ; clear carry flag
|
||
|
push di ; save original DI for later
|
||
|
AddEmUp: ;
|
||
|
adc al,ah ; add (with carry)
|
||
|
daa ; decimal adjust packed BCD
|
||
|
stosb ; save result
|
||
|
lahf ; save carry flag
|
||
|
dec si ; adjust pointer for first op
|
||
|
dec bx ; adjust pointer for second op
|
||
|
sahf ; restore flag
|
||
|
mov al,[si] ; fetch next digits of first op
|
||
|
mov ah,[bx] ; fetch next digits of second op
|
||
|
loop AddEmUp ; do 'em all (CX is counter)
|
||
|
pop di ; restore original DI
|
||
|
jc Done ; if carry, it's an overflow
|
||
|
or [di],dl ; place sign nybble (and clear CY)
|
||
|
Done: ;
|
||
|
pop si ; restore used registers
|
||
|
pop di
|
||
|
pop dx
|
||
|
pop cx
|
||
|
pop bx
|
||
|
pop ax
|
||
|
ret ;
|
||
|
AddPackedDecimal endp
|
||
|
END
|