【问题标题】:Assembly code for converting hex to dec is not working将十六进制转换为十进制的汇编代码不起作用
【发布时间】:2013-04-16 13:31:21
【问题描述】:

我有这个汇编代码(linux 80x86 nasm),假设将十六进制数字转换为十进制:

    my_func:
    push    ebp
    mov ebp, esp    ; Entry code - set up ebp and esp
    pusha           ; Save registers
    mov dword[LC1],0
    mov ecx,dword[ebp+8]    ; Get argument (pointer to string)

start_loop:
    mov ebx,0       ;zero ebx register
    mov eax,16
    mov edx,0
    mov bl, byte[ecx]   ;bl is the curr number
    jmp bl_to_num   ;change it to be a number

continue:
    add dword[LC1], ebx ;dword[LC1] = dword[LC1]+ebx
    inc ecx
    cmp byte[ecx],0
    je  end_func

    mul dword[LC1]  ;dword[LC1]*eax = edx:eax
    mov     dword[LC1],eax

    jmp start_loop

dword[LC1] 是我返回给 C 函数的参数,而 ecx 是指向接收到的字符串的指针。 函数:bl_to_num 只是将 bl 字节转换为数字(a=10,b=11..) 当我使用输入 1 运行此代码时,我收到输出 234。 当我使用输入 2 运行此代码时,我收到输出 250。 所以一个.. 我的错误在哪里? 谢谢!

编辑: 这是 bl_to_num:

bl_to_num:
    cmp bl,'A'
    je  con_a
    cmp bl,'a'
    je  con_a

    cmp bl,'B'
    je  con_b
    cmp bl,'b'
    je  con_b

    cmp bl,'C'
    je  con_c
    cmp bl,'c'
    je  con_c

    cmp bl,'D'
    je  con_d
    cmp bl,'d'
    je  con_d

    cmp bl,'E'
    je  con_e
    cmp bl,'e'
    je  con_e

    cmp bl,'F'
    je  con_f
    cmp bl,'f'
    je  con_f

    sub bl,48
    jmp continue
con_a:
      mov   bl,10
      jmp   continue
con_b:
      mov   bl,11
      jmp   continue
con_c:
      mov   bl,12
      jmp   continue
con_d:
      mov   bl,13
      jmp   continue
con_e:
      mov   bl,14
      jmp   continue
con_f:
      mov   bl,15
      jmp   continue

【问题讨论】:

  • bl_to_num 在哪里?当您说“十六进制到十进制”时,您是指浮点数(IEE754 数字)中的十进制吗?和 BCD 一样?有符号整数?十六进制输入应该是 UINT 吗?
  • 当我说十六进制到十进制时,我的意思是我收到一个包含(最多 8 位)1-9,a-f 的字符串
  • ...您也将其转换为具有 (0-9) 十进制基数的字符串?
  • 我的函数应该返回一个数字,在 dword[LC1]
  • 听起来您打算转换为二进制整数,而不是十进制。 (这是一个重要的区别。)

标签: assembly hex decimal nasm multiplication


【解决方案1】:

您的结果表明您的输入字符串在 NULL 终止符之前包含一个换行符 (0x0A)。所以如果你输入'1' 你会得到:

第一次迭代:
LC1 += 1
LC1 *= 16 (= 16)

第二次迭代:
LC += zero_extend(10-48)LC += 218 (= 16 + 218 = 234)


您的bl_to_num 例程也可以大大简化:

bl_to_num:
  cmp bl,'9'
  jbe digit
  cmp bl,'F'
  jbe already_uppercase
  sub bl,' '
  already_uppercase:
  sub bl,7
  digit:
  sub bl,'0'
  jmp continue


编辑:以下在我的机器(Xeon / Ubuntu 64 位)上对我来说很好:

format: .asciz "%d\n"

.bss
    LC1:  .long 0

.text
.globl main
.type   main, @function
main:

movl  8(%esp),%ecx   # get argv    
movl  4(%ecx),%ecx   # get argv[1] (argv[0] is the program name)

start_loop:
xor  %ebx,%ebx       
movl $16,%eax
xor  %edx,%edx
movb (%ecx),%bl   

sub  $48,%bl     # simplified bl_to_num that handles only '0'..'9'

continue:
add  %ebx,LC1 
inc  %ecx
cmpb $0,(%ecx)
je   end_func

mull LC1  
movl %eax,LC1

jmp  start_loop

end_func:

movl LC1,%eax
pushl %eax
pushl $format       # push the format string
call printf
addl $8,%esp        # pop the arguments

movl $0, %eax    # return value 
ret

$ gcc -m32 -o hexarg hexarg.s
$ ./hexarg 67
103

【讨论】:

  • 感谢您的回答! bl_to_num 不能正常工作,我不明白你的意思是解决方案应该是什么......谢谢!
  • 如果发现除A-Fa-f0-9 之外的任何字符,一个解决方案是退出start_loop,而不仅仅是在找到NULL 终止符时。
  • 我可以期待这个字符串是正确的。不工作的是乘法(在我看来)
  • mul dword [LC1][LC1] 中的任何内容乘以eax 中的内容,并将答案放在edx:eax 中(您可能可以忽略edx)。您可能希望在 mul 之前将 10 放入 eax 并在 [LC1] 之后将 eax 放回 mul...(Michael 在 AT&T 语法中显示的内容)
  • 我看到了你的答案,并试图将它翻译到我的 cpu,但没有成功。@FrankKotler:这就是我正在做的事情:mov eax,16 mul dword[LC1] mov dword[LC1], eax 这不正确吗?
猜你喜欢
  • 2012-06-02
  • 2019-01-01
  • 2014-01-09
  • 2014-03-19
  • 1970-01-01
  • 2018-02-23
  • 2012-06-26
  • 2016-08-21
  • 2014-01-15
相关资源
最近更新 更多