Reputation: 439
I'm looking for a program that coverts a String of 1's and 0's to hexadecimal string in assembly, where the binary string comes from a code that I write in 'C'.
for example:
10111111100-> "5 F C"
The problem is that for more than 12 chars input , the output is wrong , and my mission demands at most 32 chars.
for example given 110010101111-> "CAF" it works ok! but giving 10010001101000101011001111000 should be "12345678" but i only get "123" debugging with gdb tool i see that the values are being override . how to take care of this with minimal changes in the code? Thanks
The idea is to transform the string pointed by ecx to a value in eax. now i want to take the 4 most right each time and convert them , and them put them in edx .
So far, I have:
section .rodata
LC0:
DB "The result is: %s", 10, 0 ; Format string
section .bss
LC1:
RESB 32
section .text
align 16
global my_func
extern printf
my_func:
push ebp
mov ebp, esp ; Entry code - set up ebp and esp
pusha ; Save registers
mov ecx, dword [ebp+8] ; Get argument (pointer to string)
mov ebx, 0 ; counter for length
mov eax, 0 ; will hold the string as a value
mov edx, 0 ; manipulation helper
mov edi, 0 ; counter for ehile_length loop
length:
inc ebx
cmp byte [ecx+ebx], 0x00
jne length
dec ebx
;;;;THIS PART IS PARSING THE STRING INTO A REGISTER;;;
bring_ecx_to_end:
inc ecx
cmp byte [ecx], 0x0
JNE bring_ecx_to_end
dec ecx
dec ecx
or edi ,ebx
add esi,1
while_length:
mov dl,byte [ecx] ; gets 1 char into edx
cmp DL, 0x31 ; the right character
JE inc1 ; if it a '1'
resume_loop:
shl esi,1 ; multiply by 2
dec ecx
sub edi,1
cmp edi,0
jne while_length
;;;;;;;;;;NOW EAX CONSISTS THE STRING ;;;;;;;;;;;;;;
mov dword edx,0 ;target register
while:
mov dword edi ,0
add edi ,15 ; masking
and edi,eax
cmp di , 10
jl less_than_10
;less_than_F
add di ,55
jmp resume
less_than_10:
add di ,48
resume:
or edx,edi
shl edx,8
shr eax,4
cmp al ,0
jne while
shr edx , 8
;;;;;;;;;DONE;;;;;;;;;;;;;
end:
mov dword [LC1],edx
push LC1 ; Call printf with 2 arguments: pointer to str
push LC0 ; and pointer to format string.
call printf
add esp, 8 ; Clean up stack after call
popa ; Restore registers
mov esp, ebp ; Function exit code
pop ebp
ret
inc1:
or eax, esi
jmp resume_loop
Upvotes: 0
Views: 9080
Reputation: 9282
Another variant for any-length input. The code is 16-bit and probably could be optimized a bit. Written on a knee, to show the idea
mov si, input_string
mov di, output_string
mov ax, 7 ;input_string length
call bin2hex
bin2hex:
add si, ax ;si points to the end of input string
mov bx, ax
mov cx, 4 ;\
div cl ;
cmp ah, 0 ;compute how many nibbles to convert
jz short .a ;and point di to the end of the result buffer
inc di ;
mov ah, 0 ;
.a: ;
add di, ax ;/
mov [di], ah ;terminating zero
.next_nibble:
mov cl, 4 ;iterate 4 times
mov dl, 0
.next_bit:
dec si
mov al, [si]
shr al, 1 ;mov bit0 to carry flag
rcl dl, 1 ;shift with carry flag into the least-significant bit
dec bx
jz short .stop ;end of input string?
dec cx
jnz short .next_bit
.stop:
shl dl, cl ;complete last nibble to full
cmp dl, 0x0a
jl short .to_ascii
add dl, 7 ;0Ah - 0Fh = ASCII codes 41h - 46h
.to_ascii:
add dl, 0x30
dec di
mov [di], dl
test bx, bx ;end of input string reached?
jnz .next_nibble ;continue if not
ret
Upvotes: 1
Reputation: 39691
If it is the task to convert a string of zeroes and ones into a string of hexcharacters ("10111111100" -> "000005FC") then the first thing to do is to put the value of the source string in a register. You need to setup ECX to point to the string LC1.
mov ecx,[ebp+8] ;Pointer to an ASCIIZ string of zero and one characters.
xor ebx,ebx
First:
rcl ebx,1
mov al,[ecx]
inc ecx
shr al,1
jnz First
mov ecx,LC1 ;Buffer to recieve 8 hexcharacters.
Again:
rol ebx,4
You can simplify the code shl al,4
shr al,4
to and al,15
.
end:
shr ebx, 4
inc ecx ; increment pointer
cmp byte [ecx], 0 ; check if byte pointed to is zero
jnz while_ebx_not_zero ; keep looping until it is null
The end part should not change EBX and jump back 8 times precisely.
end:
inc ecx
cmp ecx,LC1+8
jb Again
Upvotes: 2
Reputation: 2642
Syntax, gotcha. (Everybody on earth has done this, including me a zillion times.)
cmp al , 00001001 ;This is actually one thousand and one
jz case1001to9 ;but you treat it like it's nine
I can't tell if you're using Masm/Tasm/Nasm/ or whatever, but I believe that if you put the letter "b
" at the end of your binary numbers, Masm will recognize them as such.
(ooops, edit: The letter B
at the end is old school. Just checked HERE on the Microsoft website and the new improved (no it isn't, but I don't get to vote) way to do this is to insert "0y
" as a prefix instead of my originally suggested "B
" as a suffix.)
Put my words to the test: before you do this, look at the output from the assembler, and see if the 00001001
is actually a nine or if it is a thousand and one.
If you can't see the output in assembler, step it through debug.
Upvotes: 2