2016-03-04 216 views
0

假設1A(十六進制中的26)存儲在EAX寄存器中。我怎樣才能將其轉換爲十進制,然後將其顯示爲輸出?有沒有Irvine的功能呢,還是有另一種方法呢?x86彙編語言:如何將十六進制寄存器值打印爲十進制輸出?

+0

可能重複的[MASM:整數字符串使用std和stosb](http://stackoverflow.com/questions/29065108/masm-整數到字符串使用std和stosb) – zx485

+0

您可能想使用Irvine32函數'WriteInt'來寫有符號整數或'WriteDec'來寫無符號整數。這兩個函數都將_EAX_中的值作爲要打印的值。所以你可以做'mov eax,42''調用WriteInt',那將在控制檯上顯示42 –

回答

0

我不知道如果歐文圖書館包含這樣的事情;我從來沒有使用過這個庫。

(我希望我不會解決某人家庭作業,只是說...)

這是一個非常簡單的練習以純x86彙編,採用重複除法/模量。在C中,基本算法看起來像這樣:

void ConvertToDecimal(unsigned int n, char *output) 
{ 
    char buffer[16]; 
    char *dest = buffer + 15; 

    /* Perform repeated division, which outputs digits in reverse 
     order. But we put them in the buffer in reverse order, too, 
     so they end up coming out in the correct order overall. */ 
    *--dest = '\0'; 
    if (n == 0) { 
     *--dest = '0'; 
    } 
    else { 
     while (n > 0) { 
      *--dest = n % 10 + '0'; 
      n /= 10; 
     } 
    } 

    /* Copy the generated digits to the output. */ 
    strcpy(output, dest); 
} 

程序集版本實際上是做同樣的基本技術的問題。 (並且從C語言中的問題的高級描述開始,然後將該解決方案移植到組裝中是解決類似問題的一種方法。)

因此,從eax中的數字開始,並輸出指針在ebx目標緩衝區,你最終是這樣的:

ConvertToDecimal: 
    push edi    ; Preserve registers we're going to use. 

    sub esp, 16    ; Make room for a local buffer on the stack. 
    mov edi, esp   ; edi will act like 'dest' does in the C version. 
    mov ecx, 10    ; We'll be repeatedly dividing by 10, and the 
          ; div instruction doesn't let you just say 'div 10'. 

    dec edi 
    mov byte ptr [edi], 0 ; Write the trailing '\0'. 

    cmp eax, 0    ; If n == 0... 
    ja l1     ; If it's more than zero, run the loop. 

    dec edi 
    mov byte ptr [edi], '0' ; Write a '0' to the output. 
    jmp l2 

    ; Main division loop. 

l1: xor edx, edx   ; Zero out edx in preparation for the division. 
    div ecx     ; Divide and modulus edx|eax by 10. 
          ; eax gets the quotient; edx gets the remainder. 

    add edx, '0'   ; Change edx from 0-9 to '0'-'9'. 

    dec edi 
    mov byte ptr [edi], dl ; Write the next digit, which is now in dl. 

    cmp eax, 0 
    ja l1     ; Go back and do it again until we reach zero.   

    ; Copy the result to the destination. 

l2: mov al, byte ptr [edi] ; Read the next character from edi... 
    inc edi 
    mov byte ptr [ebx], al ; ...and write that character to ebx. 
    inc ebx 

    cmp al, 0    ; Copy until we reach the trailing 0 byte. 
    jnz l2 

    mov eax, ebx   ; As a bonus for the caller, set the return register 
    dec eax     ; to where we wrote the last byte. 

    add esp, 16    ; Clean up the buffer on the stack. 
    pop edi     ; Restore the registers we used. 

    ret      ; And we're done. 

爲了記錄在案,我還沒有運行上面的代碼,但它應該工作。

至於顯示它作爲輸出,你需要任何庫函數或中斷你可以用來打印一個字符串。在DOS的日子裏,我只是一再呼籲int 10h ...