IPB
ЛогинПароль:

> ПРАВИЛА РАЗДЕЛА!!!

1. Заголовок или название темы должно быть информативным
2. Все тексты программ должны помещаться в теги [CODE=asm] [/CODE]
3. Прежде чем задавать вопрос, см. "FAQ",если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно, такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Ассемблера. Исключение только с согласия модератора.
5. НЕ используйте форум для личного общения! Все, что не относиться к обсуждению темы - на PM!
6. Проверяйте программы перед тем, как выложить их на форум!!

 
 Ответить  Открыть новую тему 
> подсчет количества значащих нулей и единиц в двоичной записи числа
сообщение
Сообщение #1


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


доброго дня
необходимо подсчитать количество нулей и единиц в двоичной записи числа
.model small	; Модель памяти
.stack 1000h ; Установка размера стека
.data ; Начало сегмента данных программы
;<описание переменных>
message2 db "result:",13,10,"$"
message3 db "kol-vo nulei:",13,10,"$"
message4 db "kol-vo ediniz:",13,10,"$"
mes3 db 10,13,"$"
result dw 123
kol_odin dw 0
kol_nol dw 0

.code ; Начало сегмента кода
start:
mov ax,@DATA ; Пересылаем адрес сегмента данных в регистр AX
mov ds,ax ; Установка регистра DS на сегмент данных
podschet:
mov bx, 32768
xor ax,ax
mov ax, result
and ax, bx
cmp ax, 1
je odin
jmp podschet2

podschet2:
test bx, bx
jz vivod
shr bx, 1
mov ax, result
and ax, bx
cmp ax, 1
je odin
cmp kol_odin,0
jne nol
jmp podschet2;

odin:
add kol_odin,1
jmp podschet2;

nol:
add kol_nol,1
jmp podschet2;

vivod:
mov ah,09h ; DOS функция вывода строки на экран
mov dx,offset message3 ; Задаём смещение к началу строки
int 21h ; Выводим строку
mov ax,kol_nol ;выводимое число в регисте AX
push -1 ;Сохраним признак конца числа
mov cx,10 ;Делим на 10
l: xor dx,dx
div cx ;Делим
push dx ;Сохраним цифру
cmp ax,0 ;Остался 0?
jne l ;нет -> продолжим
mov ah,02h
l2: pop dx ;Восстановим цифру
cmp dx,-1 ;Дошли до конца -> выход
je ex
add dl, 48
int 21h
jmp l2 ;И продолжим

ex:
mov ah,09h ; DOS функция вывода строки на экран
mov dx,offset message4 ; Задаём смещение к началу строки
int 21h ; Выводим строку
mov ax,kol_odin ;выводимое число в регисте AX
push -1 ;Сохраним признак конца числа
mov cx,10 ;Делим на 10
vt: xor dx,dx
div cx ;Делим
push dx ;Сохраним цифру
cmp ax,0 ;Остался 0?
jne vt ;нет -> продолжим
mov ah,02h
vvv: pop dx ;Восстановим цифру
cmp dx,-1 ;Дошли до конца -> выход
je close
add dl, 48
int 21h
jmp vvv ;И продолжим

close:
mov ax,4C00h ; DOS функция выхода из программы
int 21h ; Выход из программы

end start

считает неправильно, хотя вроде логически правильно понимаю задачу. Буду рад помощи
P.S. с ассемблером еще только знакомлюсь
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Разработчик
Free Pascal: Разработчик

Репутация: -  627  +


Очень сложно ты это все делаешь. Смотри:

.model small	; Модель памяти
.stack 1000h ; Установка размера стека
.data ; Начало сегмента данных программы

; <описание переменных>
; тут все, как и было

.code ; Начало сегмента кода

.startup ; Не надо делать присвоение DS адреса сегмента данных

mov ax, result ; работаем с числом Result
main_loop:
test ax, 1 ; проверяем последний бит числа
jnz add_ones ; равен 1-це - число нечетное - переходим к увеличению числа единиц
inc kol_nol ; если последний бит не единица - значит, увеличиваем счетчик нулей
jmp next ; и переходим к обработке следующего бита
add_ones:
inc kol_odin
next: ; увеличили либо счетчик 1, либо счетчик 0
shr ax, 1 ; сдвигаем AX вправо на 1 бит
mov cx, ax ; и заносим новое содержимое AX в CX
jcxz vivod ; очень удобно - если в AX был ноль - значащих бит уже нет - выходим на печать

jmp main_loop ; не ноль - еще осталось что-то посчитать

vivod:
; тут выводишь свои kol_nol и kol_odin

close:

.exit ; выходим из программы
end
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


Цитата(IUnknown @ 22.05.2012 18:04) *

Очень сложно ты это все делаешь. Смотри:

.model small	; Модель памяти
.stack 1000h ; Установка размера стека
.data ; Начало сегмента данных программы

; <описание переменных>
; тут все, как и было

.code ; Начало сегмента кода

.startup ; Не надо делать присвоение DS адреса сегмента данных

mov ax, result ; работаем с числом Result
main_loop:
test ax, 1 ; проверяем последний бит числа
jnz add_ones ; равен 1-це - число нечетное - переходим к увеличению числа единиц
inc kol_nol ; если последний бит не единица - значит, увеличиваем счетчик нулей
jmp next ; и переходим к обработке следующего бита
add_ones:
inc kol_odin
next: ; увеличили либо счетчик 1, либо счетчик 0
shr ax, 1 ; сдвигаем AX вправо на 1 бит
mov cx, ax ; и заносим новое содержимое AX в CX
jcxz vivod ; очень удобно - если в AX был ноль - значащих бит уже нет - выходим на печать

jmp main_loop ; не ноль - еще осталось что-то посчитать

vivod:
; тут выводишь свои kol_nol и kol_odin

close:

.exit ; выходим из программы
end


спасибо большое! а вообще сама идея того как я пытался сделать, она верная?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Разработчик
Free Pascal: Разработчик

Репутация: -  627  +


Цитата
а вообще сама идея того как я пытался сделать, она верная?
Не совсем.

Цитата
mov	ax, result
and ax, bx
cmp ax, 1 ; Что ты здесь делаешь?
Сравниваешь AX с 1? А почему там должна быть 1-ца, если, скажем, BX = 00010000b. Сравнивать надо с 0, и если AX != 0 - значит, тот бит AX, в котором сейчас в BX находится 1-ца, тоже выставлен в 1. А если AX = 0 - значит, соответствующий бит сброшен. Понимаешь логику? smile.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


А разве нет готовой команды для определения кол-ва битов? Что-то из серии bsf, bsr


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Гуру
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской
Ада: Разработчик
Embarcadero Delphi: Разработчик
Free Pascal: Разработчик

Репутация: -  627  +


BSF/BSR просто находят первый установленный бит (слева или справа, соответственно). Можно, конечно, заморочиться с этими командами, и сдвигать AX не на 1 бит каждый раз, а если есть несколько подряд идущих нулей - пропускать их сразу. Если у тебя число типа 1000011 - выиграешь несколько тактов (может быть. А может и проиграешь).
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Бывалый
***

Группа: Пользователи
Сообщений: 198
Пол: Мужской

Репутация: -  1  +


Цитата(IUnknown @ 22.05.2012 20:06) *

Не совсем.

Сравниваешь AX с 1? А почему там должна быть 1-ца, если, скажем, BX = 00010000b. Сравнивать надо с 0, и если AX != 0 - значит, тот бит AX, в котором сейчас в BX находится 1-ца, тоже выставлен в 1. А если AX = 0 - значит, соответствующий бит сброшен. Понимаешь логику? smile.gif

теперь да, понимаю. Спасибо
Примерно то же и я имел ввиду
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 




- Текстовая версия 20.02.2018 9:02
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"