Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
467 views
in Technique[技术] by (71.8m points)

Converting decimal to binary in assembly x86

I'm trying to write decimal to binary converter and for some numbers it works and for others it doesn't. 0 - 8 mumbers works fine, but when I input 9 it displays 101. I have been trying to fix this code for few hours now and I can't find out what's wrong with it.

SYSEXIT = 1
SYSREAD = 3
SYSWRITE = 4
STDOUT = 1
STDIN = 0

.bss                                   
.equ bufsize, 32               
.lcomm buf, bufsize             #buf - saved user input

.equ buf2size, 32              
.lcomm buf2, buf2size           #binary in wrong order

.equ buf3size, 32              
.lcomm buf3, buf2size           #binary correct order

.data

msg_podaj:
.ascii "Wprowadz liczbe:
"
msg_dlpodaj = .- msg_podaj

msg_test:
.ascii "TEST
"
msg_dltest = .- msg_test

.text
.global _start

_start:


mov $SYSWRITE, %eax                             
mov $STDOUT, %ebx
mov $msg_podaj, %ecx
mov $msg_dlpodaj, %edx
int $0x80

mov $SYSREAD, %eax                              
mov $STDIN, %ebx
mov $buf, %ecx
mov $bufsize, %edx
int $0x80

xor %eax, %eax
xor %ecx, %ecx

mov $0, %edi                            
movb buf(,%edi,), %al                   
sub $48, %eax                           

read:
incl %edi                                            
movb buf(,%edi,), %cl                   
sub $48, %ecx


cmp $0, %cl                            
jl tu                                   
cmp $9, %cl                             
jg tu                              

imul $10, %eax                          
add %ecx, %eax                         

jmp read

tu:

mov $0, %edi                            
mov $0, %edx
mov $2, %ebx

cmp $0, %eax
je wstaw

movb $'1', buf3(,%edi,)
jmp loop

wstaw:
movb $'0', buf3(,%edi,)

loop:
cmp $1, %eax
jle changeorder

incl %edi
DIV %ebx
mov %edx, buf2(,%edi,)
add $'0', buf2(,%edi,)

jmp loop

changeorder:
mov $1, %esi

loop2:
cmp $0, %edi
je display

movb buf2(,%edi,), %ah
movb %ah, buf3(,%esi,)
incl %esi
decl %edi
jmp loop2

display:
mov $SYSWRITE, %eax
mov $STDOUT, %ebx
mov $buf3, %ecx
mov $buf3size, %edx
int $0x80

exit:                                         
mov $SYSEXIT, %eax
int $0x80
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your code could be simplified a lot (and simpler code usually means that it's simpler to find any mistakes). Here's an outline of an easier way of doing this (I'll leave it up to you to implement it in x86 assembly):

void to_bin_string(unsigned input) {
  char output[33];

  // The number of binary digits needed to represent the input number, if we
  // exclude leading zeroes.
  unsigned digits = highest_set_bit(input) + 1;

  // Shift the input so that the most significant set bit is in bit 31.
  input <<= (32 - digits);

  for (unsigned i = 0; i < digits; i++) {
    // If the current msb is set, store a '1' in the output buffer. Otherwise
    // store a '0'.
    output[i] = (input & 0x80000000) ? '1' : '0';
    // Move the second-most significant bit into the msb position.
    input <<= 1;
  }
  output[digits] = '';
}

You can use the BSR instruction to compute highest_set_bit on x86 CPUs. The & operation can be done with an AND or a TEST, and << would be SHL.

Also keep in mind that you typically should be using byte operations when accessing ASCII strings (i.e. not things like mov %edx, buf2(,%edi,)).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...