I'm trying to write decimal to binary converter and for some numbers it works and for others it doesn't. 0 - 8 numbers works fine, but when I input 9 it displays 101.
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:\n"
msg_dlpodaj = .- msg_podaj
msg_test:
.ascii "TEST\n"
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
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] = '\0';
}
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,)
).