【问题标题】:How to Convert Decimal to Binary in Assembly Language如何在汇编语言中将十进制转换为二进制
【发布时间】:2018-03-11 11:11:38
【问题描述】:

在将十进制值转换为二进制时,我无法分析这段代码。有人可以帮助解释下面的文字行吗?顺便说一句,这是一个工作代码。我非常感谢您的帮助,这是出于学习目的。谢谢你!

calc :
    mul multiplier
    mov bl, byte ptr [si]
    mov bh, 00h
    add ax, bx
    inc si
    loop calc

    mov si, offset buf4 + 2
    mov bx, ax
    mov dx, 0000h
    mov ax, 8000h
convert :
    mov cx, 0000h
conv :
    cmp bx, ax
    jb cont3
    sub bx, ax
    inc cx
    jmp conv
cont3 :
    add cl, 30h
    mov byte ptr [si], cl
    inc si
    mov cx, 0002h
    div cx
    cmp ax, 0000h
    jnz convert

    mov byte ptr [si], '$'
    prnstr buf3
    prnstr buf4+2
stop :
    mov ax, 4c00h
    int 21h

代码的第一部分很容易理解(接受用户输入并检查其是否为有效的十进制数)。我已经添加了一些 cmets.. 代码的前半部分如下所示:

prnstr macro msg     ;acts like a function to print string
    mov ah, 09h
    lea dx, msg
    int 21h
    endm

data segment
    buf1 db "Enter a decimal number : $"
    buf2 db 0ah, "Invalid Decimal Number...$"
    buf3 db 0ah, "Equivalent Binary number is : $"
    buf4 db 6
         db 0
         db 6 dup(0)
    multiplier db 0ah
data ends

code segment
    assume cs:code, ds:data
    start :
    mov ax,@data
    mov ds,ax
    mov es, ax   

    prnstr buf1         ;Display

    mov ah, 0ah         ;Get line function
    lea dx, buf4        ;adress of input buffer
    int 21h

    mov si, offset buf1 + 2 ;Load pointer to beginning of structure
    mov cl, byte ptr [si-1] ;determine end of loop?
    mov ch, 00h
    subtract :
    mov al, byte ptr [si]   ;Load 1 byte of buf1 to cl
    cmp al, 30h             ;check if not below 0
    jnb cont1

    jmp stop
 cont1 :
    cmp al, 3ah         ;check if not above 9
    jb cont2
    prnstr buf2         ;Display
    jmp stop
 cont2 :
    sub al, 30h             ;convert ASCII to Decimal number
    mov byte ptr [si], al   ;place bcd form back to pointed character
    prnstr buf2             ;Display
    inc si                  ;next character
    loop subtract           ;repeat until end of string
    mov si, offset buf1 + 2 ;Load pointer to beginning of structure
    mov cl, byte ptr [si-1] ;reset to determine end of loop using si
    mov ch, 00h
    mov ax, 0000h           ;reset ax to 0

    ;...CONTINUE TO calc.....

【问题讨论】:

    标签: assembly x86 dos masm x86-16


    【解决方案1】:

    calc: 循环不断乘以 10 并累加,因此它似乎计算了以十进制输入的数字的实际值。 (它将您输入的字符串,例如“42”转换为数字 42。)

    剩余的代码将计算的数字转换为二进制。至少可以说,它是以一种非正统的方式编写的。

    指令mov dx, 0000h 清除dx,因为在div cx 指令的更下方将dx:ax 对除以cx,因此如果dx 不为零,那么您将得到垃圾。

    ax 寄存器以值08000h 开头,二进制是1,后跟15 0s,在循环的每次迭代中,它一直被2除,所以每次迭代都会产生一个新的0的二进制数字从左侧进入,1二进制数字向右移动一位,0二进制数字从右侧退出。

    ax 对零的检查将在 1 二进制数字在 16 次迭代后退出时停止循环,而 ax 将全为零。

    conv: 循环是一种非常非正统的将cx 设置为01 的方法,具体取决于ax 表示的位是在bx 中设置还是清除。这个循环最多循环一次,所以我认为jmp conv 指令可能会丢失,它可能会掉到cont2: 标签。

    还要注意,将2 加载到cx 然后执行div cx 会延迟,您可以只使用shr ax, 1

    【讨论】:

    • div 代替简单的移位确实很傻,但是这段代码效率低下。例如calc 循环中的 mov bh,0 可以提升到循环外并替换为 xor bx,bx 可能避免部分寄存器停顿。并且有备用寄存器,因此为mul 使用内存源操作数非常愚蠢,尤其是在为没有缓存的旧 CPU 进行调整时。它使用的是慢速 loop 指令,所以它显然没有针对最近的任何内容进行调整。而不是小代码大小。 (但要避免后来的 CPU 引入的 movzximul ax, cx, 10 之类的指令:/)
    • TL:DR:这段代码到处都是垃圾;可能是新手写的。
    • @PeterCordes ssssh,不要告诉任何人,但教授在实际编码时通常是新手。
    • 我最喜欢的部分是一个名为 prnstr 的宏。我不禁在脑海中将其读作“色情明星”。顺便说一句,好人可以写坏代码;我不是说作者愚蠢,只是缺乏经验。 (和/或只是写一些有效的东西,甚至没有尝试选择一种好的方法来实现。我认为这是asm中的一个错误,因为没有编译器可以将你的语义变成好的代码. 如果您甚至没有尝试针对 某事 进行优化,那么 asm 对于几乎所有内容来说都是错误的语言。)
    • 感谢您的帮助!
    猜你喜欢
    • 2019-05-16
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 2014-07-20
    • 2016-10-16
    • 1970-01-01
    • 2017-04-07
    • 2015-06-02
    相关资源
    最近更新 更多