2014-09-13 39 views
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!現在,目前我只能顯示兩個十進制值(出於某種原因full_print條件的第一部分被跳過,所以3!被打印爲06而不是6),但是24被正確打印。我一直在爲打印出3位十進制值的簡單方法而絞盡腦汁,但它開始變得非常混亂。

+2

第一種方法是最常見的。您可以在第一個循環中將剩餘部分「推」到堆棧中,然後在第二個循環中「彈出」並打印/存儲它們。由於堆棧被組織爲LIFO-Memory,因此您可以以相反的順序輕鬆獲取數字。 – rkhb 2014-09-13 19:43:22

+0

你能告訴我們一些代碼嗎? – 2014-09-14 08:30:57

回答

1

看看這個例子:

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或氣體)。 ;-)

+0

非常感謝。我現在得到了我的輸出,但是我可以看到在我的原始代碼中需要解決一些溢出問題。我對彙編代碼相當陌生,至今仍然在摸索着將C++和Java中非常簡單的結構和技術的邏輯轉化爲彙編。能夠看看其他人的代碼真的有幫助。 – user2781042 2014-09-14 11:01:12

相關問題