如何将整数小数部分转换为程序集8086中的对应二进制小数部分

时间:2015-12-06 22:34:26

标签: assembly binary numbers x86-16 fractions

例如,在纸上,如果我有:

  

14.6875

以十进制表示法,很容易获得二进制表示法的对应部分:

  

1101.1011

这是因为:1*2^(3)+1*2^(2)+0*2^(1)+1*2^(0)+1*2^(-1)+0*2^(-2)+1*2^(-3)+1*2^(-4)

这一切都好。

我可以轻松实现从小数二进制部分到十进制表示法的转换。问题恰恰相反。如果我有

  

0.4321

例如,我如何在程序集8086中执行仅转换小数部分的过程:

  

4321

以二进制表示法?

我应该这样做(或多或少):

(Iteration) Multiplicand    Multiplier  Carry
0           0.432100        2           0
1           0.864200        2           0
2           1.728400        2           1
3           1.456800        2           1
4           0.913600        2           0
5           1.827200        2           1
6           1.654400        2           1
7           1.308800        2           1
8           0.617600        2           0
9           1.235200        2           1
10          0.470400        2           0
11          0.940800        2           0
12          1.881600        2           1
13          1.763200        2           1
14          1.526400        2           1
15          1.052800        2           1
16          0.105600        2           0
17          0.211200        2           0
18          0.422400        2           0
19          0.844800        2           0
20          1.689600        2           1
21          1.379200        2           1
22          0.758400        2           0
23          1.516800        2           1
24          1.033600        2           1
25          0.067200        2           0
26          0.134400        2           0
27          0.268800        2           0
28          0.537600        2           0
29          1.075200        2           1
30          0.150400        2           0
31          0.300800        2           0
32          0.601600        2           0
33          1.203200        2           1
34          0.406400        2           0
35          0.812799        2           0
36          1.625599        2           1
37          1.251198        2           1
38          0.502396        2           0
39          1.004791        2           1
40          0.009583        2           0
41          0.019165        2           0
42          0.038330        2           0
43          0.076660        2           0
44          0.153320        2           0
45          0.306641        2           0
46          0.613281        2           0
47          1.226562        2           1
48          0.453125        2           0
49          0.906250        2           0
50          1.812500        2           1
51          1.625000        2           1
52          1.250000        2           1
53          0.500000        2           0
54          1.000000        2           1

考虑到相同意义上的余数列(根据迭代),二进制中的小数部分是:

  • 考虑到数字位数没有限制:
  

0.4321< => 0.0011011101001111000011011000010001001101000000010011101

  • 考虑一个固定点表示法(bin为16位,dec为4位):
  

0.4321< => 0.0011011101001111 [圆角截止]   

我如何在FLAT 8086中以非常有效的方式完成所有这些工作?

(我先前向所有人道歉,因为他们曾写过过兽性。)

2 个答案:

答案 0 :(得分:0)

我在这里发布了一个可能的解决方案,也许它不是一个优雅的解决方案,我认为它可以改进很多,但至少基本概念似乎有效:

;PROCEDURE EXPLANATION      
;This procedure converts the 4 digits of decimal fraction
;in to correspondent binary notation.   

;DATA STRUCTURE USED

;REGISTERS USED

;EXTERNAL REQUIREMENTS

;OUTPUT

.model small
.stack
.data

;EXAMPLE DATA
int_example dw  0
frac_example dw 1234        ;num is: 0.6425

;REQUIRED DATA

;OUTPUT DATA
int_out dw  ?
frac_out dw ?

.code
.startup

          mov ax, int_example
          mov bx, frac_example
          call convert


.exit

convert proc
    call int_b_conversion
    call frac_b_conversion

    ret
convert endp

int_b_conversion proc

    ;to do
    mov int_out, ax

    ret
int_b_conversion endp 

frac_b_conversion proc
    mov ax, 5000d
    xor dx, dx ;REG used to store the binary fractional part
    mov cx, 08d ;almost 8 digits in an half REG
    cyc_01:   
        rol dx, 1
        cmp bx, ax
        jg greater_so_sub
        je break
        ;lesser so multiply
        rol bx, 1 ;mul by 2
            ;have 0
        jmp dodge_01
        greater_so_sub:
            inc dx ;have 1
            sub bx, ax
            rol bx, 1
        dodge_01:
    loop cyc_01

    jmp dodge_02


    break:
        sub cx, 1
        inc dx
        cyc_02:    
            rol dx, 1
            loop cyc_02
    dodge_02:

    mov frac_out, dx 

    ret
frac_b_conversion endp

end

答案 1 :(得分:0)

此处更新,没有小数位数限制。

;PROCEDURE EXPLANATION      
;This procedure converts any digits (max 8) of a decimal fractional
;part in to correspondent binary notation.   
; In altre parole, questa funzione si occupa di convertire
; la parte frazionaria di un numero dalla notazione decimale
; a quella binaria.

;DATA STRUCTURE USED

;REGISTERS USED

;EXTERNAL REQUIREMENTS

;OUTPUT

.model small
.stack
.data

;EXAMPLE DATA
frac_example dw 654 ;num is: 0.1234
            ;i.e. the fractional part only

;REQUIRED DATA
some_number_010     dw      ?   ;This number, for example, requires
                                ;five digits to be represented in
                                ;the decimal notation. (INPUT)

number_of_digits_010        dw      ?       ;This is the OUTPUT of the
                                        ;procedure.
subtrahend_010 dw   ?

;OUTPUT DATA
frac_out dw ?

.code
.startup

          ;proc begin (argument passe by bx)
          mov bx, frac_example
          call frac_b_conversion
          ;proc end


.exit


frac_b_conversion proc 
    ;Nelle seguenti tre righe c'è l'algoritmo che serve per capire
    ;quante sono le cifre decimali del numero da convertire 
    ;e in base a questo valore assegna al sottraendo un valore pari a
    ; 5, 50, 500, 5000 o 50000
    mov some_number_010, bx
    call subtrahend_definition_010
    mov ax, subtrahend_010
    xor dx, dx ;REG used to store the binary fractional part
    mov cx, 08d ;almost 8 digits in an half REG
    cyc_01:   
        rol dx, 1
        cmp bx, ax
        jg greater_so_sub
        je break
        ;lesser so multiply
        rol bx, 1 ;mul by 2
            ;have 0
        jmp dodge_01
        greater_so_sub:
            inc dx ;have 1
            sub bx, ax
            rol bx, 1
        dodge_01:
    loop cyc_01

    jmp dodge_02


    break:
        sub cx, 1
        inc dx
        cyc_02:    
            rol dx, 1
            loop cyc_02
    dodge_02:

    mov frac_out, dx 

    ret
frac_b_conversion endp

subtrahend_definition_010        proc
        push ax
        push bx
        push dx

        mov ax, some_number_010
        mov bx, 9
        cmp ax, bx
        jg next_digit_count_1_010
        mov bx, 1       ;One digit.
        mov dx, 5
        mov subtrahend_010, dx
        jmp end_subtrahend_definition_010

next_digit_count_1_010:        
        mov bx, 99
        cmp ax, bx
        jg next_digit_count_2_010
        mov bx, 2       ;Two digit.
                mov dx, 50
        mov subtrahend_010, dx
        jmp end_subtrahend_definition_010

next_digit_count_2_010:        
        mov bx, 999
        cmp ax, bx
        jg next_digit_count_3_010
        mov bx, 3       ;Three digit.
                mov dx, 500
        mov subtrahend_010, dx
        jmp end_subtrahend_definition_010

next_digit_count_3_010:        
        mov bx, 9999
        cmp ax, bx
        jg next_digit_count_4_010
        mov bx, 4       ;Four digit.
                mov dx, 5000
        mov subtrahend_010, dx
        jmp end_subtrahend_definition_010

next_digit_count_4_010:        
        ;Five digit. (Last case: comparisons not needed).
        mov dx, 50000
        mov subtrahend_010, dx
        end_subtrahend_definition_010:
        pop dx
        pop bx
        pop ax      
        ret
subtrahend_definition_010        endp


end