· Начало · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.A&O —› dword 2 binary number

Посл.отвђт Сообщенiе


Дата: Июл 12, 2004 17:27:41
Правка

Понадобилась как-то мне функция перевода числа в строку (в двоичной системе). Заглянул в библиотеку CRT — там такой не оказалось (или плохо смотрел?). Попробовал написать сам.

Получилось нечто, преобразующее 32-битное число в 32-символьную строку. Строка монолитная, без разделения на группы по 4 символа (как делает Калькулятор). Потом подумал и сделал 2й вариант, уже с группировкой.

Теперь хотелось бы оптимизировать эти варианты по размеру, но и без большого ущерба скорости.

В принципе, после можно было бы расширить алгоритм, чтобы обрабатывать не 32 бита, а больше (передавать указатель на исходное число и длину его), хотя моя первая проба получилась несколько корявой, чтобы её расширять, да и не уверен в надобности сего: обычно работа ведётся с DWORD'ами, в крайнем случае - с QWORD'ом.

И ещё: чувствую, что со вторым вариантом не совсем гладко, надо бы сделать по-другому.

Заранее благодарен за любые замечания!

Вот код процедур, а к сообщению прикреплён тестовый код:
;<< eax2binstr
;
;  Register to binary string
; arguments:
;	eax - number
;	edi - pointer to string buffer
;
; modified registers:
;	eax,ecx,edx
;	
; 11111111111111111111111111111111
eax2binstr:
	mov		edx,eax
	
	; fill buffer by '0'
	push	edi
	push	8
	pop		ecx
	mov		eax,'0000'
	rep		stosd
	dec		edi

	; process edx bits
.lop:
	mov		eax,edx
	and		eax,1
	jz		.is0			; if 0
	mov		byte[edi],'1'	; add 1
.is0:
	dec		edi
	shr		edx,1
	jnz		.lop
	
	pop		edi
	ret
;
;>> eax2binstr

;<< eax2binstr4
;
;  Register to binary string (with character grouping)
; arguments:
;	eax - number
;	edi - pointer to string buffer
;
; modified registers:
;	eax,ecx,edx
;	
; 1111 1111 1111 1111 1111 1111 1111 1111
eax2binstr4:
	
	; fill buffer by '0'
	push	edi
	push	eax
	push	8
	push	' '
	pop		edx
	pop		ecx

	mov		eax,'0000'
.fill:
	mov		byte[edi],dl
	inc		edi
	mov		dword[edi],eax
	add		edi,4
	dec		ecx
	jnz		.fill
	
	dec		edi
	pop		edx

	; process edx bits
.lop:
	mov		eax,edx
	and		eax,1
	jz		.is0
	mov		byte[edi],'1'	; add '1' if bit = 1
.is0:
	dec		edi
	
	inc		ecx
	cmp		ecx,4
	jne		.ngroup		
	dec		edi
	xor		ecx,ecx
.ngroup:

	shr		edx,1
	jnz		.lop
	
	pop		edi
	ret
;
;>> eax2binstr4


_1733460728__bin2str_test.cmd


Дата: Июл 12, 2004 18:27:05 · Поправил: Black_mirror

eax2binstr4:
  mov ecx,8
  xchg eax,edx
.l0:
  mov eax,'0000' shr 1
  shl edx,1
  rcr eax,8
  shl edx,1
  rcr eax,8
  shl edx,1
  rcr eax,8
  shl edx,1
  rcr eax,8
  stosd
;  mov al,' '; это если на группы нужно разбивать
;  stosb  
  loop .l0
;  dec edi;это чтобы лишний пробел убрать
  ret


Дата: Июл 12, 2004 18:34:24
Правка

Хм… Красиво — это да. Но минут пять вчитывался — так и не понял, как он работает.

Ладно, буду дома медитировать…


Дата: Июл 12, 2004 18:40:34

вот так, мне кажется, должно быть меньше:
;<< eax2binstr
;
;  Register to binary string
; arguments:
;	eax - number
;	edi - pointer to string buffer
;
; modified registers:
;	eax,ecx,edx
;	
; 11111111111111111111111111111111
eax2binstr:
	mov	edx,eax
	mov     ecx, 32

	; process edx bits

.next_bit:
        xor al, al
        rcl edx, 1
        adc al, '0'
        stosb
        loop .next_bit

	ret
;
;>> eax2binstr


Дата: Июл 12, 2004 18:53:53

Первый вариант:
; arguments:
;	eax - number
;	edi - pointer to string buffer
;
; modified register:
;	eax,edx
00401000    F9              stc
00401001    92              xchg    eax, edx
00401002    B0 30           mov     al, 30
00401004    D1D2            rcl     edx, 1
00401006    14 00           adc     al, 0
00401008    AA              stos    [byte es:edi]
00401009    85D2            test    edx, edx
0040100B  ^ 75 F5           jnz     short 2nd.00401002
0040100D    8857 FF         mov     [byte ds:edi-1], dl


Дата: Июл 12, 2004 19:06:11 · Поправил: S_T_A_S_

Да, спасибо за loop :)
если использовать ecx на байт меньше
00401000    F9              stc
00401001    91              xchg    eax, ecx
00401002    B0 30           mov     al, 30
00401004    D1D1            rcl     ecx, 1
00401006    14 00           adc     al, 0
00401008    AA              stos    [byte es:edi]
00401009    41              inc     ecx
0040100A  ^ E2 F6           loopd   short 2nd.00401002
0040100C    884F FF         mov     [byte ds:edi-1], cl  ; 0-terminated string


Дата: Июл 12, 2004 23:26:17

S_T_A_S_

What the fuflo do you write? ;)

Очевидно, таким способом не будут выводится младшие нули...


Дата: Июл 12, 2004 23:48:51

captain cobalt

„Очевидно, таким способом не будут выводится младшие нули...“

Медитируй дальше 8)


Дата: Июл 13, 2004 00:13:33

если размер Очень критичен, то можно сэкономить ещё пару байт :)
;<< eax2binstr
;
;  Register to binary string
; arguments:
;	eax - number
;	edi - pointer to string buffer
;
; modified registers:
;	eax,ecx,edx
;	
; 11111111111111111111111111111111
eax2binstr:

        xchg	edx, eax
	push	32
	pop	ecx

	; process edx bits

.next_bit:
        xor al, al
        shl edx, 1
        adc al, '0'
        stosb
        loop .next_bit

	ret



Дата: Июл 13, 2004 06:22:37 · Поправил: S_T_A_S_

captain cobalt > „What the fuflo do you write?“

I guess there are some typo errors in the "first-in, last-out" abbreviature =)

Вообще-то это простой пример использование флага переноса в качестве счётчика цикла.
Вместо лишнего регистра.
В качестве недостатков такого подхода можно рассматривать факт, что цикл выполняется 33 раза.
Но я взял на себя смелость заодно и завершить строку нулём.
(в условии задачи этого не было, но наверняка же придётся делать?)

В общем-то можно переделать на цикл с предпроверкой, но тогда код будет весить столько же, сколько в варианте green,
единственно, что edx не портится:
00401BE0    F9              stc
00401BE1    91              xchg    eax, ecx
00401BE2    B0 30           mov     al, 30
00401BE4    D1D1            rcl     ecx, 1
00401BE6    E3 05           jecxz   short 2nd.00401BED
00401BE8    14 00           adc     al, 0
00401BEA    AA              stos    [byte es:edi]
00401BEB  ^ EB F5           jmp     short 2nd.00401BE2
00401BED    C3              retn


Дата: Июл 13, 2004 13:23:17 · Поправил: Edmond

IceStudent
Блин!
Смотрел он в CRT.
И вообще для кого топик был Int_to_Str?


Дата: Июл 14, 2004 19:04:07
Правка

Black_mirror
green
S_T_A_S_
Большое спасибо!

Теперь хоть представил свой уровень кодирования…

Edmond
Гм… Ну, был такой топик. Ну, ужас. А что? Я что ли хуже всех? Между прочим, я всего лишь ученик


Дата: Июл 15, 2004 12:52:59

IceStudent

Айс, я приношу свои извенения за недопустимый тон в своём ответе.

И прошу не покидать форум WASM.RU, так как он собственно ни в чём не виновен.