2016-06-15 100 views
0

我想一个二进制数转换为装配一个小数,但我不断获取零转换ASCII /二进制文件的汇编语言转换为十进制

这是多少

aLength  db "00000000000000000000000000010101", NULL 

我试图用这个代码由“0”让每个字符和底层乘以2,并增加,但它口口声声说,答案是0

mov rbx,aLength 
mov dword[rsum],0 
mov ecx,0 
mov r10,32 


lp: 
mov cl,byte[rbx] 
sub cl,'0' 
mov eax,dword[rsum] 
mul dword[two] 
add eax,ecx 
mov dword[rsum],eax 
add rbx,1 
dec r10 
cmp r10,0 
jbe lp 

mov r8d,dword[rsum] 
mov byte[aLength],r8b 
+2

看起来不错对我来说,除了'MUL DWORD [二]'这是可疑的,可惜你没有告诉我们“二” ......由2乘法,尝试'添加EAX,eax'(或一个'shl')而不是 – Tommylee2k

+0

看起来像x86程序集(几乎每个CPU系列都有自己的程序集,不能一概而论)。 – MSalters

回答

4

你的代码循环只有一次,这是因为你倒上厕所平状态

cmp r10, 0 
jbe lp 

应该

cmp r10, 0 
ja lp 

由于r10举行位转换的剩余数量。
一旦您更改该行,您的代码就可以工作。


也就是说,它可以被简化并且更易读。
从二进制转换为十进制时使用的一个很好的技巧是使用进位标志。

移位指令将输出位(左移lsb,右移msb)放入进位标志。
使用rcl/rcr指令,我们可以获取该位并将其移回另一个寄存器。

由于用于“1”是31H,这是奇数的ASCII值,因此具有位0组,以及用于“0”是30H,这是偶数,因此具有ASCII值0位清晰;通过将数字ASCII值右移1,我们根据预期的数字值设置进位标志:0代表'0',1代表'1'。
现在我们可以使用rcl将该位移入eax

我也喜欢在可能的情况下使用整个寄存器,并在功能分离的代码段之间放置白线。
最后,我使用WORD,DWORD,BYTE(适用的PTR)等内存大小说明符来简单地区分内存操作。
还有一个:我删除了所有的中介内存访问。

xor eax, eax   ;Converted value (so far) 
mov rbx, aLength  ;Pointer to ASCII digits 
mov r10, 32   ;Bits left to convert 

_convert: 
    movzx ecx, BYTE [rbx] ;Grab a digit 
    add rbx, 1   ;And increment the pointer 

    shr ecx, 1   ;Set CF according to the digit value 
    rcl eax, 1   ;Shift CF into EAX from right (Rotate left) 

    sub r10, 1   ;Decrement count 
ja _convert 

;Store results 
mov DWORD [rSum], eax 
mov BYTE [aLength], al