2014-10-20 50 views
-1

我正在寫這個小程序,輸入除數和除數,程序將輸出商和餘數。這裏是代碼:ASCII到十進制,反之亦然,對於NASM中的多個字符

segment .data 

prompt db "Please enter a number: ", 10 
promptLen equ $-prompt 
prompt2 db "Please enter the divisor: ", 10 
prompt2Len equ $-prompt2 
prompt3 db "Your quotient is: ",10 
prompt3Len equ $-prompt3 
prompt4 db "Your remainder is: ",10 
prompt4Len equ $-prompt4 

segment .bss 

inputNum resb 2 
inputDiv resb 2 
quotient resb 2 
remainder resb 2 

segment .text 

global _start 

_start: 

mov eax, 4 
mov ebx, 1 
mov ecx, prompt 
mov edx, promptLen 
int 80h 

mov eax, 3 
mov ebx, 0 
mov ecx, inputNum 
mov edx, 2 
int 80h 

mov eax, 4 
mov ebx, 1 
mov ecx, prompt2 
mov edx, prompt2Len 
int 80h 

mov eax, 3 
mov ebx, 0 
mov ecx, inputDiv 
mov edx, 2 
int 80h 

xor edx, edx 
mov ax, [inputNum] 
mov bx, [inputDiv] 
and ax, 0xff 
and bx, 0xff 
sub ax, '0' 
sub bx, '0' 

div bx 

add ax, '0' 
add dx, '0' 
mov [quotient], ax 
mov [remainder], dx 

mov eax, 4 
mov ebx, 1 
mov ecx, prompt3 
mov edx, prompt3Len 
int 80h 

mov eax, 4 
mov ebx, 1 
mov ecx, quotient 
mov edx, 2 
int 80h 

mov eax, 4 
mov ebx, 1 
mov ecx, prompt4 
mov edx, prompt4Len 
int 80h 

mov eax, 4 
mov ebx, 1 
mov ecx, remainder 
mov edx, 2 
int 80h 
jmp exit 

exit: 

mov eax, 1 
xor ebx, ebx 
int 80h 

代碼是現在的方式,我只能處理一個字符的數字;通過減去'0'並重新加上輸出。 任何人都可以請幫助我使用更有效的方式做這種轉換,這樣我就不會被限制爲只有一個字符的數字?

+0

你關心效率,或正確性? – 2014-10-20 16:04:29

+0

如果你不能使用libc,你必須編寫你自己的轉換例程。大量的例子。你可以[每個數字乘以10循環](http://stackoverflow.com/questions/26337518/how-can-i-make-10000-1000-100-from-10-the-easiest-way/26339409 )用於文本到二進制,並在二進制到文本的循環中除以10。 – Jester 2014-10-20 16:04:40

+0

如果你要評論你的代碼的每一行,這將有很大的幫助。 – 2014-10-20 16:18:12

回答

0

沒有錯誤輸入和檢查:

segment .data 

    prompt db "Please enter a number: " 
    promptLen equ $-prompt 
    prompt2 db "Please enter the divisor: " 
    prompt2Len equ $-prompt2 
    prompt3 db 10, "Your quotient is: " 
    prompt3Len equ $-prompt3 
    prompt4 db 10, "Your remainder is: " 
    prompt4Len equ $-prompt4 
    linefeed db 10 

segment .bss 

    inputNum resb 80 
    inputDiv resb 80 
    uNum resd 1 
    uDiv resd 1 
    uQuo resd 1 
    uRem resd 1 
    quotient resb 80 
    quotientLen resd 1 
    remainder resb 80 
    remainderLen resd 1 

segment .text 
global _start 

dec2eax:       ; Arg ESI: ASCII-string (0x0A-terminated) with decimal digits 
    xor eax,eax      ; Result 
    xor edx, edx     ; Especially to clear the 32-bit-part of EDX 

    .loop: 
    mov dl, byte [esi]    ; Read digit 
    cmp dl, 10      ; End of string (SYS_READ - in certain cases not existent)? 
    je .finish      ; Yes: done 
    lea eax, [eax*4+eax]   ; EAX = 5 * EAX ... 
    add eax, eax     ; ... and EAX = 2 * EAX results in EAX = EAX * 10 
    add esi, 1      ; Increment pointer to string 
    and dl, 0x0F     ; Eliminate ASCII part of digit 
    add eax, edx     ; Add digit to result 
    jmp .loop      ; Next character 

    .finish: 
    ret        ; Result: Converted unsigned integer in EAX 

eax2dec:       ; Arg EDI: Pointer to string that gets ASCII-characters 
    mov ebx, 10      ; Divisor 
    xor ecx, ecx     ; CX=0 (number of digits) 

    .first_loop: 
    xor edx, edx     ; Attention: DIV applies also DX! 
    div ebx       ; DX:AX/BX = AX remainder: DX 
    push dx       ; LIFO 
    inc cl       ; Increment number of digits 
    test eax, eax     ; AX = 0? 
    jnz .first_loop     ; No: once more 

    mov ebx, ecx     ; Save strlen 

    .second_loop: 
    pop ax       ; Get back pushed digit 
    or al, 00110000b    ; AL to ASCII 
    mov byte [edi], al    ; Save AL 
    inc edi       ; DI points to next character in string DECIMAL 
    loop .second_loop    ; Until there are no digits left 

    mov byte [edi], 0    ; End-of-string delimiter (ASCIZ) 
    mov eax, ebx     ; Return strlen in EAX 
    ret 

_start: 

    mov eax, 4 
    mov ebx, 1 
    mov ecx, prompt 
    mov edx, promptLen 
    int 80h 

    mov eax, 3 
    mov ebx, 0 
    mov ecx, inputNum 
    mov edx, 80 
    int 80h 

    mov eax, 4 
    mov ebx, 1 
    mov ecx, prompt2 
    mov edx, prompt2Len 
    int 80h 

    mov eax, 3 
    mov ebx, 0 
    mov ecx, inputDiv 
    mov edx, 80 
    int 80h 

    mov esi, inputNum 
    call dec2eax 
    mov [uNum], eax 

    mov esi, inputDiv 
    call dec2eax 
    mov [uDiv], eax 

    xor edx, edx 
    mov eax, [uNum] 
    mov ebx, [uDiv] 
    div ebx 
    mov [uQuo], eax 
    mov [uRem], edx 

    mov eax, [uQuo] 
    mov edi, quotient 
    call eax2dec 
    mov [quotientLen], eax 
    mov eax, [uRem] 
    mov edi, remainder 
    call eax2dec 
    mov [remainderLen], eax 

    mov eax, 4 
    mov ebx, 1 
    mov ecx, prompt3 
    mov edx, prompt3Len 
    int 80h 

    mov eax, 4 
    mov ebx, 1 
    mov ecx, quotient 
    mov edx, [quotientLen] 
    int 80h 

    mov eax, 4 
    mov ebx, 1 
    mov ecx, prompt4 
    mov edx, prompt4Len 
    int 80h 

    mov eax, 4 
    mov ebx, 1 
    mov ecx, remainder 
    mov edx, [remainderLen] 
    int 80h 

    mov eax, 4 
    mov ebx, 1 
    mov ecx, linefeed 
    mov edx, 1 
    int 80h 

    jmp exit 

    exit: 

    mov eax, 1 
    xor ebx, ebx 
    int 80h 
+0

非常感謝您的回答,但我想知道dec2eax和eax2dec背後的邏輯是什麼。我是大會的新手,我正試圖理解如何在較低級別操作數據。如果你能詳細說明,我將不勝感激。 – 2014-10-21 04:02:17

+0

@ O.A .:這有點棘手。我的英語太難以簡單明瞭地解釋了。看看傑斯特對你的問題的評論。你也可以谷歌它(「彙編轉換號碼」),你會發現一堆的例子和一些解釋嘗試。如果您(或您的翻譯計劃)瞭解德語,歡迎您訪問我的主頁:http://dcla.rkhb.de/umwandlung.html – rkhb 2014-10-21 07:28:37

相關問題