2014-10-29 76 views
0

我對我來說似乎是一個相當直接的項目。詢問用戶0-255之間的數字和2-9之間的數字。並在該基地輸出。我打算簡單地執行通常的除法算法並獲取剩餘部分,推入堆棧,然後退出以獲取相反的順序以輸出回用戶。但是將幾個打印調試語句後,我得到很奇怪的輸出剩餘NASM彙編數轉換爲

; Run using nasm -f elf -g -F stabs proj4.asm ; gcc -o proj4 proj4.o -m32 ; To execute type proj4 %macro SAVE_REGS 0 push eax push ecx push edx %endmacro %macro RESTORE_REGS 0 pop edx pop ecx pop eax %endmacro %macro CALL_PUTS 1 push %1 call puts add esp, 4 %endmacro %macro CALL_SCANF 2 push %1 push %2 call scanf add esp, 8 %endmacro %macro CALL_PRINTF1 1 push %1 ;The address of the string to print call printf add esp, 4 %endmacro %macro CALL_PRINTF2 2 push %1 ;The formatted string with a %char place holder push %2 ;The item to place into the place holder call printf add esp, 8 %endmacro SECTION .data prmptNumMsg: db "Enter a number between 0 and 255: ", 0 prmptBaseMsg: db "Enter a base between 2 and 9: ", 0 remShow: db 'The the remainder is: %d', 10, 0 numShow: db 'The number is %d', 10, 0 baseShow: db 'The base is %d', 10, 0 printed: db 'Looped in division method', 10, 0 poped: db 'Looped in pop method',10, 0 ansShow: db '8d', 10, 0
numFormat db '%d', 0 stringFormat db '%s', 0
SECTION .bss numVal resd 1 baseVal resd 1 ans resd 9 i resd 1 n resd 1 j resd 1

SECTION .text global main extern puts extern scanf extern printf main: push ebp ; Set up stack frame for debugger mov ebp, esp push ebx push esi push edi ;Everything before this is boilerplate
getInt: CALL_PRINTF1 prmptNumMsg ;push numVal ;push numFormat ;call scanf ;add esp, 8 CALL_SCANF numVal, numFormat
mov eax, dword[numVal] mov ebx, dword 0 ;check below 0 cmp eax, ebx jb getInt mov eax, dword[numVal] mov ebx, dword 255 ;check above 255 cmp eax , ebx ja getInt ;VALID INTEGER PAST THIS POINT
getBase: CALL_PRINTF1 prmptBaseMsg
CALL_SCANF baseVal, numFormat
mov eax, dword[baseVal] mov ebx, dword 0 cmp eax, ebx jb getBase mov eax, dword[baseVal] mov ebx, dword 9 cmp eax, ebx ja getBase ;END GETBASE ;VALID BASE NUMBER PAST THIS POINT mov eax, dword[numVal] mov [n], eax ;set n to the current number value CALL_PRINTF2 eax, numShow mov eax, dword 0 mov [i], eax mov eax, dword[baseVal] CALL_PRINTF2 eax, baseShow doDivision: ;CALL_PRINTF1 printed xor edx, edx mov eax, dword[n] mov ebx, dword[baseVal] div ebx ;edx = remainder eax = quotient mov [n], eax ;save quotient
CALL_PRINTF2 eax, numShow CALL_PRINTF2 edx, remShow

;push edx ;save remainder on stack to pop in reverse order later ;mov [n], eax ;move quotient to eax mov ebx, dword[i] inc ebx mov [i], ebx ;i++ ;mov eax, [i] mov ecx, dword 8 cmp ebx, ecx jb doDivision ;END DO DIVISION

end: ;Everything after this is boilerplate pop edi pop esi pop ebx mov esp, ebp pop ebp ret

當程序運行我的輸出如下 Enter a number between 0 and 255: 105 Enter a base between 2 and 9: 4 The number is 105 The base is 4 The number is 26 The the remainder is: 13144896 The number is 6 The the remainder is: 13144896 The number is 1 The the remainder is: 13144896 The number is 0 The the remainder is: 13144896 The number is 0 The the remainder is: 13144896 The number is 0 The the remainder is: 13144896 The number is 0 The the remainder is: 13144896 The number is 0 The the remainder is: 13144896 我希望它環路8倍這是正確的,每一個DIV操作的商是正確的,但我得到瘋狂的數字爲剩下這將在edx舉行。我不明白是什麼造成這種情況。

+1

更改這兩行的順序,看看會發生什麼。然後找出原因。除法後的'CALL_PRINTF2 eax,numShow'和'CALL_PRINTF2 edx,remShow'。 – 2014-10-29 22:50:17

+0

什麼? **你的意思是你必須在打印之前計算餘數?**誰聽說過這樣的廢話。首先打印未初始化的值,然後嘗試計算......某些東西......好的結果,用答案形式寫出來,並附上一些解釋,OP應該接受。 – 2014-10-30 06:12:39

+0

更多提示:'printf'返回一個值。它放在哪裏?順便說一句,這個問題看起來[很熟悉](http://stackoverflow.com/questions/26657061/nasm-program-assembly-language/26686793#26686793)(儘管被問到的問題更具體)。 – Tony 2014-11-03 06:15:22

回答

-1

當你調用一個例程(例如:printf)時,有一些規則管理這個工作原理。例如,你把參數放在棧上嗎?或者將它們傳入寄存器?你是否從左向右推參數?或者從左到右?調用者是否將參數從堆棧中彈出?還是被調用者?返回值的位置在哪裏?

最重要的是對於你的問題,被調用者是否需要確保所有寄存器在返回時都具有相同的值?或者它可以覆蓋其中的一些?

這些問題的答案被稱爲「調用約定」(或有時ABI)。並不只有一個答案。例如,cdecl,pascal和fastcall都是x86上的常用調用約定,它們都以稍微不同的方式回答這些問題。

我相信你會發現printf是cdecl。考慮到這一點,你可以檢查出http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl。這應該有助於你理解在這個例子中edx發生了什麼。

+0

OP提供了特定的代碼,其中包含一個需要解決的簡單特定問題。雖然答案的內容通常是真實的,但它並沒有解決這個問題,因爲代碼中調用了CALL_PRINTF2調用。此外,在需要特定幫助時,將OP放棄追查一般信息可能會給問題注入更多混淆,而不是使問題更好。在選擇是留言還是留下答案時,有時候判斷力是勇氣的更好的一部分。 – 2014-10-30 06:17:29