在汇编 80x86 中将二进制转换为十六进制

convert binary to hex in assembly 80x86

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

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

如果任务是将零和一的 字符串 转换为十六进制字符的 字符串 ("10111111100" -> " 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

语法,明白了。 (地球上的每个人都这样做过,包括我无数次。)

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

我不知道你是在使用 Masm/Tasm/Nasm/ 还是什么,但我相信如果你把字母“b”在二进制数的末尾,Masm 会这样识别它们。

(糟糕,编辑:最后的字母 B 是老派了。刚刚在 Microsoft 网站上检查了 HERE 和新的改进(不,不是,但我不t 得到投票)做到这一点的方法是插入“0y”作为 前缀 而不是我最初建议的“B”作为后缀。)

验证我的话:在执行此操作之前,查看汇编程序的输出,看看 00001001 实际上是 9 还是 1001。

如果您在汇编程序中看不到输出,请逐步调试。

任意长度输入的另一种变体。该代码是 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