2012-02-02 81 views
0

我实现了两大整数乘法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 

任何人都可以帮助我在十进制模式下打印结果吗?

感谢您提前:)

回答

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函数将结果转换为十进制。 :)

希望其他人可以使用它:)

+1

'AAM'是一个用于十进制算术和存储在BCD中的数字操作的指令。它在64位模式下不可用。但只要你唯一的兴趣就是在emu8086上工作,那么 - 太棒了! :) – 2012-02-02 19:14:02

2

不幸的是,转换价值为十进制并不像它转换为十六进制的那样简单。这是因为基数10不是基数-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*阵列将持有的val 10为底的值的ASCII表示。

你可以用DIV指令在装配中实现它。大多数优化C编译器将其优化为乘法运算,这比分频要快得多(但只有在除数不变的情况下才能完成)。

+2

因为这是一个8086(16位)的问题 - 处理32位值DIV的方法是在汇编不平凡的,因为潜在的分区溢出的。如果您在DX:AX中放置了一个32位值,该值大于655360,并且使用DIV除以10,则商不能以16位表示,并且会发生异常。 – 2016-07-12 01:21:50

0

更新:我以前贴的方式来打印仅是一个16位数字,但现在我已经找到一种方法来打印32位号码为好,免得我决定删除以前的解决方案。总体思路如下: - 检查数字是负数还是负数 - 如果是负数,则使用二进制补码取反。但是我们必须考虑一个角落案例:一个有符号的32位数字从-2^31到2^31-1,所以我们可以看到没有-2^31的正数等价物。因此,我们必须挑选出这个案例并存储相应的数字(以字符串格式)并打印出来 - 如果是正数,则我们重复除以10,取余数,将其推入堆栈,然后弹出并打印每个数字(这很容易,因为Assembly x8086已经提供了相应的例程) 顺便说一下,在我的代码中,我还检查了16位上部分是否为零,然后转到基于相同原理的_16bits_routine。 然而,除以10,为32个不平凡的,因为div功能不支持它,所以这里是我做的:

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