Консультация № 185190
16.01.2012, 18:07
52.72 руб.
0 16 1
Уважаемые эксперты! Пожалуйста, ответьте на вопрос:
Подсчитать количество нулей и единиц в произвольно заданном шестнадцатеричном числе.
Код желательно писать в расчёте на его компиляцию FASM.
Программа для Windows. Вывод результата в MessageBox.

Обсуждение

давно
Посетитель
7438
7205
16.01.2012, 18:11
общий
16.01.2012, 18:12
Адресаты:
Здравствуйте-здравствуйте.
Насколько число произвольно? Формат? Двойное слово или, может, строка байт?
Число вводим или задаем в программе?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Мастер-Эксперт
425
4118
16.01.2012, 18:31
общий
Адресаты:
Число произвольно, на Ваш выбор.
Число вводится. Если есть в WinAPI какая-нибудь функция, типа InputBox, то можно использовать её. Я знаю, что во многих высокоуровневых языках есть такая спецфункция, а вот на счёт WinAPI - не знаю.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Посетитель
7438
7205
16.01.2012, 18:34
общий
Адресаты:
Результат обязательно в MessageBox?
Может, лучше создадим небольшой диалог и в нем введем, выведем?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Мастер-Эксперт
425
4118
16.01.2012, 18:57
общий
Как хотите...
Мне показалось, что в MessageBox результат будет выглядеть вполне гламурненько. Что-нибудь типа:
Код:
.data
...
szformat1 db "Число: %X",13,"Кол-во 0: %u",13,"Кол-во 1: %u",0
result db 20 dup(0)
title db "Результат:",0

.code
...
invoke wsprintf,result,szformat1,eax,count0,count1
invoke MessageBox,0,result,title,MB_OK

Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Посетитель
7438
7205
17.01.2012, 02:56
общий
это ответ
Здравствуйте, sir Henry!
Вот такая получилась программа:

[code h=209]format PE GUI 4.0
entry start

include 'win32a.inc'
include 'encoding\win1251.inc'

ID_HEX = 101
ID_MESSAGE = 102
ID_DIALOG = 103

section '.data' data readable writeable

szformat db "Bin=%s, 0=%u, 1=%u",0
szError db "Incorrect format",0
hex rb 40h
message rb 40h
bin rb 40h

section '.code' code readable executable

start:
invoke GetModuleHandle,0
invoke DialogBoxParam,eax,ID_DIALOG,HWND_DESKTOP,DialogProc,0
invoke ExitProcess,0

proc DialogProc hwnddlg,msg,wparam,lparam
push ebx esi edi
cmp [msg],WM_COMMAND
je wmcommand
cmp [msg],WM_CLOSE
je wmclose
wmdefault:
xor eax,eax
jmp finish
wmcommand:
;клавиша Exit
cmp [wparam],BN_CLICKED shl 16 + IDCANCEL
je wmclose
;клавиша Calc
cmp [wparam],BN_CLICKED shl 16 + IDOK
jne processed ;все остальные по-умолчаеию
;читаем строку из редактора
invoke GetDlgItemText,[hwnddlg],ID_HEX,hex,40h
mov ecx,eax ;длина строки
lea esi,[hex] ;адрес строки
xor ebx,ebx ;счетчик единиц
xor edx,edx ;счетчик нулей
lea edi,[bin] ;строка бит
calcLoop:
lodsb ;очередной символ
;проверим на допустимость
cmp al,'0'
jb PrintError ;меньше '0' - ошибка
cmp al,'9'
jbe calcHex ;цифра - в работу
or al,20h ;букву сделаем маленькой
sub al,'a'-10 ;'a'-'f' -> 0ah-0fh
jl PrintError ;'9'< al < 'a' - ошибка
cmp al,0fh
ja PrintError ;> 'f' - ошибка
calcHex:
mov ah,4 ;число бит
shl al,4 ;начнем со старшего
calcBitsLoop:
shl al,1 ;старший бит в С
push eax ;сохраним биты
mov al, '0' ;формируем строку бит
adc al,0
stosb
shr al,1 ;вернем бит в С
pop eax ;восстановим остальные биты
adc ebx,0 ;счетчик единиц
inc edx ;общий счетчик бит
dec ah
jnz calcBitsLoop
loop calcLoop ;по всем цифрам строки
sub edx,ebx ;число нулей = общий счетчик бит - число единиц
mov al,0
stosb

invoke wsprintf,message,szformat,bin,edx,ebx
;запишем во второй редактор результат
invoke SetDlgItemText,[hwnddlg],ID_MESSAGE,message
jmp processed
PrintError:
;не hex-строка
invoke SetDlgItemText,[hwnddlg],ID_MESSAGE,szError
jmp processed
wmclose:
invoke EndDialog,[hwnddlg],0
processed:
mov eax,1
finish:
pop edi esi ebx
ret
endp

section '.idata' import data readable writeable

library kernel,'KERNEL32.DLL',\
user,'USER32.DLL'

import kernel,\
GetModuleHandle,'GetModuleHandleA',\
ExitProcess,'ExitProcess'

import user,\
DialogBoxParam,'DialogBoxParamA',\
GetDlgItemText,'GetDlgItemTextA',\
SetDlgItemText,'SetDlgItemTextA',\
wsprintf,'wsprintfA',\
EndDialog,'EndDialog'

section '.rsrc' resource data readable

directory RT_DIALOG,dialogs

resource dialogs,\
ID_DIALOG,LANG_RUSSIAN+SUBLANG_DEFAULT,dlg

dialog dlg,'Calc hex bits',70,70,220,100,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME
dialogitem 'STATIC','Hex:',-1,10,10,70,8,WS_VISIBLE
dialogitem 'EDIT','',ID_HEX,10,20,200,13,WS_VISIBLE+WS_BORDER+WS_TABSTOP
dialogitem 'STATIC','Message:',-1,10,40,70,8,WS_VISIBLE
dialogitem 'EDIT','',ID_MESSAGE,10,50,200,13,WS_VISIBLE+WS_BORDER+WS_TABSTOP+ES_AUTOHSCROLL+ES_READONLY
dialogitem 'BUTTON','Calc',IDOK,85,75,45,15,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON
dialogitem 'BUTTON','Exit',IDCANCEL,135,75,45,15,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON
enddialog
[/code]
5
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Мастер-Эксперт
425
4118
17.01.2012, 11:29
общий
17.01.2012, 11:30
Адресаты:
Всё нормально, кроме одного, но сильно существенного для русскочитающего пользователя:
Код:
include 'encoding\win1251.inc'

Эту штуку надо добавлять, чтобы надписи на форме были на русском языке. В файле сидят необходимые перекодировки.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Посетитель
7438
7205
17.01.2012, 11:39
общий
Адресаты:
Все может быть...
Я на FASM-е практически не работаю, больше прикипел к MASM-у
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Старший Модератор
31795
6196
17.01.2012, 11:53
общий
Адресаты:

Код:
calcBitsLoop:
shr al,1 ;младший бит в С
jc add_1 ;бит = 1?
add_0:
inc dl ;считаем 0
jmp calcNext
add_1:
inc dh ;считаем 1
calcNext:
dec bl ;по всем битам hex-цифры
jnz calcBitsLoop


Я бы так переписал:
Код:
calcBitsLoop:
shr al,1
;
adc edi,0;счетчик единиц
inc esi;общий счетчик бит
;
dec bl
jnz calcBitsLoop


и потом sub esi,edi
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
7438
7205
17.01.2012, 11:57
общий
Адресаты:
Можно и так. Хотелось более понятнее, практически в лоб
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Мастер-Эксперт
425
4118
17.01.2012, 12:13
общий
Адресаты:
У меня семёрка на MASM ругается...
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Мастер-Эксперт
425
4118
17.01.2012, 20:02
общий
Адресаты:
Есть маленький уточнающий вопрос. .
Вот мы ввели 16-тиричное число в поле ввода. А как это число можно вывести в двоичном виде, чтобы только 0 и 1?
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Посетитель
7438
7205
17.01.2012, 21:38
общий
Адресаты:
Ну так, подправить и будет 0 и 1
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
18.01.2012, 00:51
общий
Адресаты:
Подправил. Учел и предложение Константина Николаевича.
Так, действительно, лучше.
Теперь нравится?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Мастер-Эксперт
425
4118
18.01.2012, 12:05
общий
Адресаты:
Откровенно говоря, мне не совсем пнятен код предьявления числа в двоичном виде. Не мотгли бы Вы сделать подробное разъяснение?
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Посетитель
7438
7205
18.01.2012, 13:45
общий
18.01.2012, 13:51
Адресаты:
Добавил комментариев.
Код:

mov ecx,eax ;длина строки
lea esi,[hex] ;адрес строки
xor ebx,ebx ;счетчик единиц
xor edx,edx ;счетчик нулей
lea edi,[bin] ;адрес строки, где сформируем строку бит
calcLoop:
lodsb ;очередной символ
;проверим на допустимость
cmp al,'0'
jb PrintError ;меньше '0' - ошибка
cmp al,'9'
jbe calcHex ;цифра - в работу
or al,20h ;букву сделаем маленькой
sub al,'a'-10 ;'a'-'f' -> 0ah-0fh
jl PrintError ;'9'< al < 'a' - ошибка
cmp al,0fh
ja PrintError ;> 'f' - ошибка
calcHex:
mov ah,4 ;число бит
;Чтобы одновременно сформировать и строку бит, сдвинем влево на 4 бита
shl al,4 ;будем идти от старшего к младшему
calcBitsLoop:
shl al,1 ;старший бит в С
;сформируем символ-бит
push eax ;сохраним остальные биты, чтобы не потерялись
mov al, '0' ;формируем символ-бит
adc al,0 ;добавим к '0' бит С (получим или '0', или '1')
stosb ;пишем по адресу [edi]
shr al,1 ;вернем бит в С, сдвинув на 1 вправо, младший (наш!) уйдет в С
pop eax ;восстановим остальные биты
adc ebx,0 ;счетчик единиц, добавим к счетчику 0+С, фактически считаем единицы
inc edx ;общий счетчик бит
dec ah ;по всем 4 битам hex-цифры
jnz calcBitsLoop
loop calcLoop ;по всем цифрам строки
sub edx,ebx ;число нулей = общий счетчик бит - число единиц
mov al,0
stosb ;закроем строку символов-бит нулем
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Мастер-Эксперт
425
4118
18.01.2012, 15:09
общий
Адресаты:
Спасибо.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Форма ответа