我在emu8086
中实现了两个大整数的乘法,代码如下:
; MULTIPLY N1 * N2 = RES
MULTIPLY PROC
MOV BH, 0H
MOV CH, 0H
MOV CL, L1; initial counter of first loop ( L1 -> length of N1 )
DEC CX
MUL_1:
MOV COUNTER, CL ; store counter of first loop
MOV CL, L2 ; initial counter of second loop ( L2 -> length of N2 )
MUL_2:
MOV BH, 0H
MOV BL, COUNTER
DEC BL
MOV AL, N1[BX] ; get BX th byte of N1
MOV BL, CL
DEC BL
MUL N2[BX] ; multiple N1 and N2 's bytes
MOV BH, 0H
MOV BL, COUNTER
ADD BX, CX
DEC BX
ADD RES[BX], AL ; AL should be add into RES[loop1_counter + loop2_counter - 1]
ADC RES[BX+1], AH; AH and carry should be add into RES[loop1_counter + loop2_counter ]
ADC RES[BX+2], 0H; carry of above addition should be place here.
LOOP MUL_2
MOV CL, COUNTER; retrieve loop 1 counter
LOOP MUL_1
RET ; end function
MULTIPLY ENDP
所以,我想在Decimal Mode
打印,我知道如何在HexaDecimal
打印结果:
PRINT_TABLE PROC
MOV CX, 16D
CASE:
MOV BX, 16D
SUB BX, CX
MOV AL, RES[BX]
CMP AL, 10D
JB LBL1
JAE LBL2
LBL1:
ADD AL, '0'
JMP CONTINUE
LBL2:
ADD AL, 55D
CONTINUE:
MOV DL, AL
MOV AH, 02H
INT 21H
LOOP CASE
RET
PRINT_TABLE ENDP
有人可以帮我按十进制模式打印我的结果吗?
感谢您的进步:)
答案 0 :(得分:2)
不幸的是,将值转换为十进制并不像将其转换为十六进制那么简单。这是因为base-10不是base-2的相关基数(即10不是2的幂)。我们需要使用模数和除法来实现转换。 C中的通用算法看起来像这样:
unsigned int val = 58932; // assume int is 32-bit
char buf[11] = { 0 }, *chr = buf+9; // 11 characters is enough because log10(2^32) = 9,63, +1 for \0
do
{
*chr = (val % 10) + '0'; // to ascii
--chr;
} while((val /= 10) != 0);
++chr;
完成后,chr
将指向一个以空值终止的char*
数组,该数组将保存基数为10的val
值的ASCII表示。
您可以使用DIV
指令在汇编中实现它。大多数优化C编译器将其优化为乘法运算,这比除法快得多(但只有在除数是常数的情况下才可以完成)。
答案 1 :(得分:1)
我通过更改我的代码解决了我的问题,如下所示:
NORMALIZE PROC
MOV CH, 0H
MOV CL, L1
ADD CL, L2
DEC CX
NOMRALIZE_LOOP:
MOV BX, CX
DEC BX
MOV AL, RES[BX]
MOV AH, 1H
MUL AH
AAM
MOV RES[BX], AL
ADD RES[BX-1], AH
LOOP NOMRALIZE_LOOP
RET
NORMALIZE ENDP
; MULTIPLY N1 * N2 = RES
MULTIPLY PROC
MOV CH, 0H
MOV CL, L1
MOV AL, '0'
MOV BH, 0H
SUB_N1:
MOV BL, CL
DEC BL
SUB N1[BX], AL
LOOP SUB_N1
MOV CL, L2
SUB_N2:
MOV BL, CL
DEC BL
SUB N2[BX], AL
LOOP SUB_N2
MOV CH, 0H
MOV CL, L1
MUL_1:
MOV COUNTER, CL
MOV CL, L2
MUL_2:
MOV BH, 0H
MOV BL, COUNTER
DEC BL
MOV AL, N1[BX]
MOV BL, CL
DEC BL
MUL N2[BX]
AAM
MOV BH, 0H
MOV BL, COUNTER
ADD BX, CX
DEC BX
DEC BX
ADD RES[BX], AL
ADC RES[BX-1], AH
ADC RES[BX-2], 0H
LOOP MUL_2
MOV CL, COUNTER
LOOP MUL_1
RET
MULTIPLY ENDP
我使用AAM
函数更改了乘法和存储数字。最后,我添加NORMALIZE
函数将结果转换为十进制。 :)
希望其他人可以使用它:)
答案 2 :(得分:0)
更新:我之前发布了一种只打印16位数字的方法,但现在我已经找到了打印32位数字的方法,所以我决定删除以前的解决方案。这是一般的想法:
- 检查数字是负数还是正数
- 如果它是否定的,则使用两个补码来否定它。但是我们必须处理一个极端情况:一个带符号的32位数从-2 ^ 31到2 ^ 31-1,所以我们可以看到没有正相当于-2 ^ 31。所以我们必须挑出这个案例并存储相应的数字(字符串格式)并打印出来
- 如果它是正数,那么我们重复除以10,取余数,将其推入堆栈,然后弹回并连续打印每个数字(这很容易,因为Assembly x8086提供了适当的例程)
顺便说一句,在我的代码中,我还检查了16位上部是否为零,然后转到_16bits_routine,这是基于相同的原理。
但是,由于div
函数不支持它,因此除以10在32位中并不是微不足道的,所以这就是我所做的:
Let A be the number in question, we now divide by 10:
A = q*10 + r (0 <= r <= 9)
now separate A into the high and low parts:
A_high * 2^16 + A_low = q*10 + r (0 <= r <= 9)
our task is to find q and r. To do that we first divide the high part:
A_high = q_high * 10 + r_high (0<= r_high <= 9)
=> A_high * 2^16 = (q_high*2^16)*10 + r_high * 2^16 . Note that r_high is from 0 to 9, so to divide r_high * 2^16 by 10, we simply need to perform the calculations and then store the results in a lookup table! The result:
r_high * 2^16 = q_high_redundant * 10 + r_high_redundant (0 <= r_high_redundant <= 9) (found by using a lookup table) (an interesting note: q_high_redundant is only 16 bits!)
Now divide the low part:
A_low = q_low * 10 + r_low
=> A = A_high * 2^16 + A_low = (q_high*2^16 + q_low + q_high_redundant)*10 + r_low + r_high_redundant
Now you just have to divide r_low + r_high_redundant and add in to the quotient, then you get the results.
这是代码,它不是非常快但不太慢,所以我希望你发现它很有用:
;Written by Dang Manh Truong
.stack 100h
.data
base_10 dw 10
var_32bits_high dw 0
var_32bits_low dw 0
quotidient_32bits_high dw 0
quotidient_32bits_low dw 0
negate_mask equ 0FFFFh
lowest_signed_32bits_high dw 8000h
lowest_signed_32bits_low dw 0000h
lowest_signed_32bits_string dw "-2147483648$"
qhigh dw 0
rhigh dw 0
qlow dw 0
rlow dw 0
qhigh_redundant dw 0
rhigh_redundant dw 0
q_0 dw 0
qhigh0 equ 0h
rhigh0 equ 0h
qhigh1 equ 1999h
rhigh1 equ 6h
qhigh2 equ 3333h
rhigh2 equ 2h
qhigh3 equ 4CCCh
rhigh3 equ 8h
qhigh4 equ 6666h
rhigh4 equ 4h
qhigh5 equ 8000h
rhigh5 equ 0h
qhigh6 equ 9999h
rhigh6 equ 6h
qhigh7 equ 0B333h
rhigh7 equ 2h
qhigh8 equ 0CCCCh
rhigh8 equ 8h
qhigh9 equ 0E666h
rhigh9 equ 4h
.code
main proc
;Initialization
mov ax,@data
mov ds,ax
;example: 7654321 = 0074CBB1h
; mov ax,74h
; mov var_32bits_high,ax
; mov ax,0CBB1h
; mov var_32bits_low,ax
;example: 10223803 = 009C0BBh
; mov ax,9Ch
; mov var_32bits_high,ax
; mov ax,0BBh
; mov var_32bits_low,ax
;example: 32763
; mov ax,0h
; mov var_32bits_high,ax
; mov ax,32763
; mov var_32bits_low,ax
;example: 86420 = 00015194h
; mov ax,1h
; mov var_32bits_high,ax
; mov ax,5194h
; mov var_32bits_low,ax
;example: 2147483647 (2^31 - 1) = 7FFFFFFFh
; mov ax,7FFFh
; mov var_32bits_high,ax
; mov ax,0FFFFh
; mov var_32bits_low,ax
;example: -2147483648 (-2^31)= 80000000h
; mov ax,8000h
; mov var_32bits_high,ax
; mov ax,0000h
; mov var_32bits_low,ax
;example: -1 = FFFF FFFFh
mov ax,0FFFFh
mov var_32bits_high,ax
mov ax,0FFFFh
mov var_32bits_low,ax
mov ax,0
mov bx,0 ;bx: quotidient_32bits_high
mov dx,0 ;dx: quotidient_32bits_low
mov cx,0 ;counter = 0
;16bits or 32bits ?
mov ax,var_32bits_high
cmp ax,0
jne _32bits_routine
jmp _16bits_routine
;;;
_32bits_routine:
mov cx,0
;if == -2147483648 (-2^31)
mov ax,var_32bits_high
cmp ax,lowest_signed_32bits_high
jne check_if_neg
mov ax,var_32bits_low
cmp ax,lowest_signed_32bits_low
jne check_if_neg
;then
lea dx,lowest_signed_32bits_string
mov ah,9
int 21h
jmp return_to_dos
;if < 0
check_if_neg:
mov ax,var_32bits_high
cmp ax,0
jnl preparations
;then print "-" ...
mov ah,2
mov dl,'-'
int 21h
;... and negate number
mov ax,var_32bits_high
xor ax,negate_mask
mov var_32bits_high,ax
mov ax,var_32bits_low
xor ax,negate_mask
inc ax
mov var_32bits_low,ax
jnc preparations
mov ax,var_32bits_high
inc ax
mov var_32bits_high,ax
preparations:
mov ax,var_32bits_high
mov quotidient_32bits_high,ax
mov ax,var_32bits_low
mov quotidient_32bits_low,ax
while_32bits:
; while >0 do
mov ax,quotidient_32bits_high
cmp ax,0
jne div_high_part
mov ax,quotidient_32bits_low
cmp ax,0
jne div_high_part
jmp print_char
div_high_part:
;divide high part
mov dx,0
mov ax,quotidient_32bits_high
div base_10
mov qhigh,ax
mov rhigh,dx
;case rhigh
mov ax,rhigh
cmp ax,0
je _rhigh0
cmp ax,1
je _rhigh1
cmp ax,2
je _rhigh2
cmp ax,3
je _rhigh3
cmp ax,4
je _rhigh4
cmp ax,5
je _rhigh5
cmp ax,6
je _rhigh6
cmp ax,7
je _rhigh7
cmp ax,8
je _rhigh8
cmp ax,9
je _rhigh9
_rhigh0:
mov ax,qhigh0
mov qhigh_redundant,ax
mov ax,rhigh0
mov rhigh_redundant,ax
jmp _aftercase
_rhigh1:
mov ax,qhigh1
mov qhigh_redundant,ax
mov ax,rhigh1
mov rhigh_redundant,ax
jmp _aftercase
_rhigh2:
mov ax,qhigh2
mov qhigh_redundant,ax
mov ax,rhigh2
mov rhigh_redundant,ax
jmp _aftercase
_rhigh3:
mov ax,qhigh3
mov qhigh_redundant,ax
mov ax,rhigh3
mov rhigh_redundant,ax
jmp _aftercase
_rhigh4:
mov ax,qhigh4
mov qhigh_redundant,ax
mov ax,rhigh4
mov rhigh_redundant,ax
jmp _aftercase
_rhigh5:
mov ax,qhigh5
mov qhigh_redundant,ax
mov ax,rhigh5
mov rhigh_redundant,ax
jmp _aftercase
_rhigh6:
mov ax,qhigh6
mov qhigh_redundant,ax
mov ax,rhigh6
mov rhigh_redundant,ax
jmp _aftercase
_rhigh7:
mov ax,qhigh7
mov qhigh_redundant,ax
mov ax,rhigh7
mov rhigh_redundant,ax
jmp _aftercase
_rhigh8:
mov ax,qhigh8
mov qhigh_redundant,ax
mov ax,rhigh8
mov rhigh_redundant,ax
jmp _aftercase
_rhigh9:
mov ax,qhigh9
mov qhigh_redundant,ax
mov ax,rhigh9
mov rhigh_redundant,ax
jmp _aftercase
_aftercase:
;divide low part
mov ax,0
mov q_0,ax
mov dx,0
mov ax,quotidient_32bits_low
div base_10
mov qlow,ax
mov rlow,dx
mov ax,rlow
add ax,rhigh_redundant
;if remainder >= 10
cmp ax,base_10
jl after_if
sub ax,base_10
mov dx,1
mov q_0,dx
after_if:
mov rlow,ax
mov ax,q_0
add ax,qlow
mov qlow,ax
jnc label1
mov ax,qhigh
inc ax
mov qhigh,ax
label1:
mov ax,qlow
add ax,qhigh_redundant
mov qlow,ax
jnc label2
mov ax,qhigh
inc ax
mov qhigh,ax
label2:
;push remainder to stack
mov ax,rlow
push ax
inc cx
mov ax,qhigh
mov quotidient_32bits_high,ax
mov ax,qlow
mov quotidient_32bits_low,ax
jmp while_32bits
;;;
_16bits_routine:
mov ax,var_32bits_low
mov bx,0 ;bx: quotient
mov cx,0
while_loop:
cmp ax,0
je print_char
mov dx,0
div base_10
mov bx,ax ;ax stores quotidient
mov ax,dx ;dx stores remainder
;push remainder
push ax
;counter = counter + 1
inc cx
;numerator = quotidient
mov ax,bx
jmp while_loop
print_char:
cmp cx,0
je return_to_dos
pop ax
;because at this point 0 <= ax <= 9, setting ah = 2 does not change the results
mov ah,2
mov dl,al
add dl,30h ;0-> '0',1->'1',....
int 21h
dec cx
jmp print_char
return_to_dos:
mov ah,4ch
int 21h
main endp
end main