在程序集80x86中将二进制转换为十六进制

时间:2015-03-29 12:01:18

标签: assembly binary hex converter

我正在寻找一个程序,它将1和1的字符串转换为汇编中的十六进制字符串,其中二进制字符串来自我写入的代码' C&#39 ;.
 例如:

10111111100-> "5 F C"

问题是,对于超过12个字符输入,输出是错误的,我的任务最多需要32个字符。

例如给定110010101111-> " CAF"它工作正常! 但是给予10010001101000101011001111000应该是" 12345678" 但我只得到" 123" 使用gdb工具调试我发现值正在被覆盖。如何在代码中进行最小的更改来解决这个问题?感谢

这个想法是将ecx指向的字符串转换为eax中的值。 现在我想每次最右边4个并转换它们,然后把它们放在edx中。

到目前为止,我有:

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

3 个答案:

答案 0 :(得分:2)

如果要将字符串的零和1转换为字符串的十六进制字符(" 10111111100" - >&#34) ; 000005FC")那么首先要做的是将源字符串的值放在寄存器中。 您需要设置ECX以指向字符串 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

您可以将代码shl al,4 shr al,4简化为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 

end 部分不应更改EBX并精确跳回8次。

end:
inc ecx
cmp ecx,LC1+8
jb Again

答案 1 :(得分:2)

语法,陷阱。 (地球上的每个人都做了这件事,包括我在内的数十万次。)

cmp al , 00001001    ;This is actually one thousand and one
jz case1001to9       ;but you treat it like it's nine

我无法判断你是否正在使用 Masm / Tasm / Nasm / 或其他什么,但我相信如果你把这封信放在" {{1} }"在二进制数字的末尾,Masm将识别它们。

(ooops,编辑:最后的字母b是旧学校。只需检查微软网站上的HERE和新的改进(不,它不是,但我不是&# 39; t得投票)这样做的方法是插入" B"作为前缀,而不是我最初建议的" {{1} }"作为后缀。)

说出我的话:在你这样做之前,先查看汇编程序的输出,看看0y实际上是9还是千分之一。

如果您无法在汇编程序中看到输出,请通过调试进行操作。

答案 2 :(得分:1)

任意长度输入的另一种变体。代码是16位的,可能会稍微优化一下。写在膝盖上,以显示想法

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