0

我正在研究 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!为 120。现在,目前我只能显示两个十进制值(由于某种原因,full_print 条件的第一部分被跳过,所以 3! 被打印为 06 而不是 6),但 24 被正确打印。我一直在绞尽脑汁寻找一种简单的方法来打印出 3 位数的十进制值,但它开始变得非常混乱。

4

1 回答 1

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

顺便说一句:如果我知道操作系统(Windows 或 Linux)和汇编风格(Nasm 或 Gas),你昨天就得到了这个例子。;-)

于 2014-09-14T10:11:28.830 回答