在汇编程序中为输出转换十进制值

时间:2014-09-13 19:21:33

标签: assembly yasm

我正在研究64位汇编代码(yasm),试图输出任意大的十进制值,以便它们正确读取,而不是像古怪或单个数字。我环顾四周,但似乎无法在线找到合适的解决方案。我的代码当前输出一个2位十进制数字(输出商,除以10时的输出余数)。对于较大的值,我正在考虑一个do-while循环结构的线路,该结构将重复除以10并输出余数而其余部分不为零。这种方法的问题在于它会反过来输出结果,为代码增加了额外的复杂性,试图扭转这种情况。有谁知道一个有效的解决方案?我看了一下aaa,aam等,但我不完全了解它们的工作方式,并怀疑这些只适用于32位操作。

代码结构如下:

section .data   
  nl db "",2,0
  nlf db "",10,0
  input db '',2,0  
  fact dq 1
  y db 10
  store dq 0
  rem dq 0
  quot dq 0
  check dq 0

section .text
  global _start      

_start:         

 ; reading input value 
  mov rax, 0        ; system read
  mov rdi, 0        ; STD IN
  mov rsi, input    ; address first byte in output
  mov rdx, 1        ; load length into rdx
  syscall

  ; reading newline
  mov rax, 0        ; system read
  mov rdi, 0        ; STD IN
  mov rsi, nl       ; address first byte in output
  mov rdx, 1        ; load length into rdx
  syscall

  mov rbx,  [input]     ; for calculating factorial 
  sub rbx, '0'  
  call  calc_fact
  call de_ASCII_fy

  ;add   rax, 30h   

  mov rax, 1        
  mov rdi, 1        
  mov rsi, nlf      
  mov rdx, 1        
  syscall 

  ; exit
  xor rdi, rdi
  push 0x3c
  pop rax
  syscall

  calc_fact:
      cmp   bl, 1
      jg    do_calculation
      mov   rax, 1
      ret

  do_calculation:
      dec   bl
      call  calc_fact
      inc   bl
      mul   bl        
      ret

  de_ASCII_fy:
      mov  [fact], rax
      movzx rax, byte [fact]
      cmp rax, 0
      je decimal_loop
      movzx rbx, byte [y]
      xor rdx, rdx
      div rbx
      xor rcx, rcx
      mov rcx, rdx ; store remainder
      add rax, '0'
      add rdx, '0'
      mov [rem], rdx
      mov [quot], rax
      cmp rcx, 0
      jnz full_print
            mov rax, 1      ; system write
            mov rdi, 1      
            mov rsi, rem    
            mov rdx, 1
            syscall
            ret
            full_print:
            mov rax, 1      ; system write
            mov rdi, 1      
            mov rsi, quot   
            mov rdx, 1      
            syscall
            mov rax, 1      ; system write
            mov rdi, 1      
            mov rsi, rem    
            mov rdx, 1
            syscall
            jmp endif
      endif:ret
      decimal_loop:
      ret

我正在计算一个阶乘值,试图显示4的输出!作为24和5!现在,此刻,我只能显示两个十进制值(由于某种原因,full_print条件的第一部分被跳过,所以3!打印为06而不是6),但24正确打印。我一直在绞尽脑汁想要打印出一个3位十进制值的简单方法,但它开始变得非常混乱条件。

1 个答案:

答案 0 :(得分:2)

看一下这个例子:

global _start

section .bss
    decimal resb 32

section .data

    number dq 10000000000000000000
    lf db 10

section .text

_start:
    mov rdi, decimal
    mov rsi, [number]
    call IntegerToDecimal

    mov   eax, 1        ; sys_write
    mov   edi, 1        ; STDOUT
    mov   rsi, decimal  ; String address
    mov   edx, 32       ; Max. string length
    syscall

    mov   eax, 1        ; sys_write
    mov   edi, 1        ; STDOUT
    mov   rsi, lf       ; Line Feed address
    mov   edx, 1        ; Max. string length
    syscall

    mov eax, 60         ; sys_exit
    xor edi, edi        ; return 0 (success)
    syscall

IntegerToDecimal:
    mov rax, rsi
    mov ebx, 10         ; Divisor
    xor ecx, ecx        ; RCX=0 (Anzahl der Ziffern)
  .Loop_1:
    xor edx, edx
    div rbx             ; RDX:RAX / RBX = RAX Remainder RDX
    push dx             ; LIFO
    add cl, 1
    or  rax, rax        ; RAX == 0?
    jnz .Loop_1         ; no: once more
  .Loop_2:
    pop ax              ; Get back pushed digits
    or al, 00110000b    ; Convert to ASCII
    mov [rdi], al       ; Store character
    add rdi, 1          ; Increment target address
    loop .Loop_2        ; Until there are no digits left
    mov byte [rdi], 0   ; ASCIIZ-null-terminator

    ret
BTW:如果我知道操作系统(Windows或Linux)和装配风格(Nasm或Gas),你昨天就得到了这个例子。 ; - )