assembly 将二进制转换为十进制并在程序集中显示

wi3ka0sx  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(168)

我有一个单词数组,有4个单元格

RESULT DW 4 DUP(0)

它将包含二进制数,例如

MOV RESULT,   0H
MOV RESULT+2, 0H
MOV RESULT+4, 35A4H
MOV RESULT+6, E900H

现在结果包含0000000035A4E900H,这意味着90000000以十进制方式。不是我想在显示器上打印900000000
我该怎么办?

vxf3dgd4

vxf3dgd41#

无论你使用什么语言,转换成十进制打印是相同的过程。嗯,两个过程之一。你可以从任何一端开始。假设你有一个16位数字12345(0x 3039)。
第一种方法是

divide by 10000 result is 1 remainder 2345 save or print the 1
divide by 1000 result is 2 remainder 345 save or print the 2
divide by 100 result is 3 remainder 45 save or print the 3
divide by 10 result is 4 remainder 5 save or print the 4 and 5

第二种方式

divide by 10 result is 1234 remainder 5 save the remainder use the result
divide by 10 result is 123 remainder 4 save the remainder use the result
divide by 10 result is 12 remainder 3 save the remainder use the result
divide by 10 result is 1 remainder 2 save both the remainder and result 
print the results in the right order

现在,如果你的问题是如何用我的指令集将一个64位数除以10的幂,那么有时候你可以,有时候你不能,有时候你必须使用其他的数学规则。除以10和除以2*5是一样的,所以你可以除以2(移位),然后除以5。
0x 3039位(12345)除以10000等于右移4,然后除以5的4次方(625)。0x 303 = 771,771/625 = 1。如果除法不是那么大,乘法也可能不是,因此1 * 625 = 0x 271,0x 271〈〈4 = 0x 2710,0x 3039 - 0x 2710 = 0x 929 = 2345。一旦你得到了一个数字,你可以用硬件相除,然后使用硬件。
你可能需要除以中间的一个数字,比如说你有一个32位的数字(最大值为4,294,967,296),并且您的硬件可以将一个32位数除为16位结果和16位余数。您可以使用上述方法减去几位数,比如留下94,967,295然后除以10000得到9496余数7295然后使用硬件独立地处理这些四位数。
如果你没有除法硬件,但乘法硬件(是的,我知道你指定8086),你可以这样做:
http://www.divms.uiowa.edu/~jones/bcd/divide.html
如果你还记得小学时如何在纸上做乘法:

1234
   x1010 
   =====
    0000  
   1234   
  0000
+1234 
========
 1246340

二进制使得这一点非常简单,正如你从我选择的数字中所想象的那样

abcd
x efgh
======

如果要将四位abcd乘以四位efgh,则:

result = 0;
if(h) result+=abcd << 0;
if(g) result+=abcd << 1;
if(f) result+=abcd << 2;
if(e) result+=abcd << 3;

对于大多数指令集,您可以将此乘法级联到与您的内存一样宽的宽度,希望将1百万位乘以1百万位。没有问题,500,000字节加上多一点或几个寄存器(以及大量时钟周期)。

dohp0rv5

dohp0rv52#

我做的和old_timer说的差不多,但是更优化了一点。如果输入是65535,这将发生:

divide by 1000 result is 65 remainder 535 split the 65 then print it
divide 535 by 10 result is 53 remainder 5 split the 53 print it, then print the 5

它的优化程度更高,因为您只需要执行两次16位除法,并且只需要使用3个16位寄存器几次
下面是代码:

; ax = Value to print
printInteger:
    splitUpperSection:
        mov dx, 0
        mov bx, 1000
        div bx      ; bx / ax:dx --> ax = 65   dx = 535
        aam         ; ax -->  ah = 6    al = 5

    add  ax, 0x3030 ; Add hex 30 or decimal 48 because that's the value of letter 0 in ASCII
    xchg ah, al     ; Switch values
    mov  cl, ah

    mov  bx, 0x0007 ; DisplayPage=0, GraphicsColor=7
    mov  ah, 0x0E   ; BIOS.Teletype (printing AL)
    int  0x10
    mov  al, cl
    int  0x10

    mov  ax, dx

    splitLowerSection:
        mov dl, 10
        div dl      ; al = 53   ah = 5
        mov dl, ah
        aam         ; ah = 5   al = 3

    xchg ah, al
    add  ax, 0x3030
    mov  cl, ah

    mov  ah, 0x0E   ; BIOS.Teletype (printing AL)
    int  0x10
    mov  al, cl
    int  0x10

    mov  al, dl
    add  al, 0x30
    int  0x10

This视频确实帮助我了解了如何以及为什么

相关问题