2014-01-27 81 views
0

我想從輸入中讀取一個數字,然後計算它的因子(不知道它們是否是因子,例如10的因子是1,2,5,10)。我相信我的計算部分是正確的,因爲當我計算代碼中預設的價值因子時,它的工作原理。但是當我嘗試輸入值時,我得到錯誤的結果。 我將發佈代碼與預設值1000一起工作(輸入無關緊要,它會計算1000年的因素)。程序集輸入錯誤

; ---------------------------------------------------- 
; LeiaTegurid.asm 
; @brief Leiab sisestatud numbri tegurid. 
; @author Eerik Muuli 

; @date  27.01.2014 
; ---------------------------------------------------- 
global _main  ; make visible for linker 
extern _printf  ; link with printf 
extern _scanf ; Kasutaja sisendi jaoks. 
extern _atoi ;string->int 
; ------------------------------- 
section .const 
    hello db `Tegur: %d \n\0`; 0 on stringi lõpp. 
    otsitav dw 1000 
; ------------------------------- 
section .data 
s6num db `Sisesta arv: \0` ; Küsib sisendi. 
vaste db "%s", 0 ; Sisend. 
; ------------------------------- 
section .bss 
inpt resb 1000 ; Reserveerib 1000 baiti. 
; ------------------------------- 
section .text 
_main: 
push ebp ;proloog 
mov ebp, esp 

push s6num 
call _printf ; Prindib: "Sisesta arv: " 
add esp, 4 

push inpt 
push vaste ; Meie sisend 
call _scanf 
add esp, 8 

push inpt 
call _atoi ; String intiks. 
add esp, 4 

; mov ecx, eax 
mov ebx, dword[otsitav] ; Annab ebx-le kasutaja sisestatud väärtuse. 
mov [esp-4], eax ; Annab esp-4-le kasutaja sis. väärtuse. 

inc ebx ; Suurendab ebx-i. Vajalik tsükli jaoks. 
;mov edx, dword[otsitav] ; Annab edx-le väärtuseks kasutaja valitud arvu. 

.loop1: ; Tsükkel algab. 
cmp ebx , 1 ; võrdleb, et tsüklist välja saada. 
je .end ; hüppab lõppu. 
dec ebx ; võtab eax-ilt ühe ära. 
xor edx, edx ; Nullib jäägi ära. 

mov eax, dword[otsitav] ; Annab eax-le otsitava väärtuse. 
idiv ebx ; Jagab eax-i(otsitava) hetke arvuga. 
; mov ecx, eax ; Paneb vastsuse ecx-i. 
; Jääk on edx-is. 

cmp edx, 0; edx(jääk) ? 0 
jg .loop1 ; Kui jääk > 0, siis läheb insta algusesse. 
push ebx ; Printimiseks. 
push hello ; Printimiseks. 
call _printf ; Kutsub printimise välja. 
add esp, 8 ; Tasakaalustab. 
jmp .loop1 ; Hüppab tsükli algusesse. 

.end: ; lõpp 

mov esp, ebp ;epiloog, taastame registrid 
pop ebp 
ret 

我現在還會發布讀取輸入並且不起作用的版本。 請注意,我在新版本中已經更改的行標有*

; ---------------------------------------------------- 
; LeiaTegurid.asm 
; @brief Leiab sisestatud numbri tegurid. 
; @author Eerik Muuli 
; @date  27.01.2014 
; ---------------------------------------------------- 
global _main  ; make visible for linker 
extern _printf  ; link with printf 
extern _scanf ; Kasutaja sisendi jaoks. 
extern _atoi ;string->int 
; ------------------------------- 
section .const 
    hello db `Tegur: %d \n\0`; 0 on stringi lõpp. 
    otsitav dw 1000 
; ------------------------------- 
section .data 
s6num db `Sisesta arv: \0` ; Küsib sisendi. 
vaste db "%s", 0 ; Sisend. 
; ------------------------------- 
section .bss 
inpt resb 1000 ; Reserveerib 1000 baiti. 
; ------------------------------- 
section .text 
_main: 
push ebp ;proloog 
mov ebp, esp 

push s6num 
call _printf ; Prindib: "Sisesta arv: " 
add esp, 4 

push inpt 
push vaste ; Meie sisend 
call _scanf 
add esp, 8 

push inpt 
call _atoi ; String intiks. 
add esp, 4 

***mov ecx, eax*** 
***mov ebx, ecx ; Annab ebx-le kasutaja sisestatud väärtuse.*** 
mov [esp-4], eax ; Annab esp-4-le kasutaja sis. väärtuse. 

inc ebx ; Suurendab ebx-i. Vajalik tsükli jaoks. 
;mov edx, dword[otsitav] ; Annab edx-le väärtuseks kasutaja valitud arvu. 

.loop1: ; Tsükkel algab. 
cmp ebx , 1 ; võrdleb, et tsüklist välja saada. 
je .end ; hüppab lõppu. 
dec ebx ; võtab eax-ilt ühe ära. 
xor edx, edx ; Nullib jäägi ära. 

***mov eax, ecx ; Annab eax-le otsitava väärtuse.*** 
idiv ebx ; Jagab eax-i(otsitava) hetke arvuga. 
; mov ecx, eax ; Paneb vastsuse ecx-i. 
; Jääk on edx-is. 

cmp edx, 0; edx(jääk) ? 0 
jg .loop1 ; Kui jääk > 0, siis läheb insta algusesse. 
push ebx ; Printimiseks. 
push hello ; Printimiseks. 
call _printf ; Kutsub printimise välja. 
add esp, 8 ; Tasakaalustab. 
jmp .loop1 ; Hüppab tsükli algusesse. 

.end: ; lõpp 

mov esp, ebp ;epiloog, taastame registrid 
pop ebp 
ret 

回答

0

首先,這條線是錯誤的:

mov [esp-4], eax ; Annab esp-4-le kasutaja sis. väärtuse. 

您沒有在棧上創建空間對於這個變量,你也不會在其他地方使用它。既然你從來沒有騰出過空間,那就搞砸了你的堆棧。部分序言應爲: sub esp, 4爲此變量創建空間。我們只需使用另一個寄存器,它將保存在print調用 - esi

另一個問題是,你沒有正確退出程序。你正在鏈接C庫,並且它在你的_main函數被調用之前做了一些「幕後」工作,所以要正確地退出,你需要調用exit 在這裏,我們清理後的代碼更具可讀性。不知道你在用什麼彙編語言(我正在猜測NASM)以及爲什麼要用下劃線來聲明C函數(也許在Windows上?)我只是重新定義了名稱,以便在我的Linux機器上正確彙編和鏈接。

固定碼之間:

;~ ************* 

;~ ************* 

代碼:

; ---------------------------------------------------- 
; LeiaTegurid.asm 
; @brief Leiab sisestatud numbri tegurid. 
; @author Eerik Muuli 

; @date  27.01.2014 
; ---------------------------------------------------- 
global _main  ; make visible for linker 
extern printf  ; link with printf 
extern scanf ; Kasutaja sisendi jaoks. 
extern atoi ;string->int 
%define _printf printf 
%define _scanf scanf 
%define _atoi atoi 
extern exit 

section .const 
    hello db `Tegur: %d \n\0`; 0 on stringi lõpp. 
    ;~ otsitav dw 10 
; ------------------------------- 
section .data 
s6num db `Sisesta arv: \0` ; Küsib sisendi. 
vaste db "%s", 0 ; Sisend. 
; ------------------------------- 
section .bss 
inpt resb 1000 ; Reserveerib 1000 baiti. 
; ------------------------------- 
section .text 
_main: 
    push ebp ;proloog 
    mov  ebp, esp 

    push s6num 
    call _printf ; Prindib: "Sisesta arv: " 
    add  esp, 4 

    push inpt 
    push vaste ; Meie sisend 
    call _scanf 
    add  esp, 8 

    push inpt 
    call _atoi ; String intiks. 
    add  esp, 4 

    mov  ebx, eax ;dword[otsitav] ; Annab ebx-le kasutaja sisestatud väärtuse. 
    ;~ ************* 
    mov  esi, eax ; Annab esp-4-le kasutaja sis. väärtuse. 
    ;~ ************* 

    inc  ebx ; Suurendab ebx-i. Vajalik tsükli jaoks. 

.loop1: ; Tsükkel algab. 
    cmp  ebx , 1 ; võrdleb, et tsüklist välja saada. 
    je  .end ; hüppab lõppu. 
    dec  ebx ; võtab eax-ilt ühe ära. 
    xor  edx, edx ; Nullib jäägi ära. 

    ;~ ************* 
    mov  eax, esi ;dword[esp-4] ; *****dword[otsitav] ; Annab eax-le otsitava väärtuse. 
    ;~ ************* 
    idiv ebx ; Jagab eax-i(otsitava) hetke arvuga. 

    cmp  edx, 0; edx(jääk) ? 0 
    jg  .loop1 ; Kui jääk > 0, siis läheb insta algusesse. 
    push ebx ; Printimiseks. 
    push hello ; Printimiseks. 
    call _printf ; Kutsub printimise välja. 
    add  esp, 8 ; Tasakaalustab. 
    jmp  .loop1 ; Hüppab tsükli algusesse. 

.end: ; lõpp 

    mov  esp, ebp ;epiloog, taastame registrid 
    pop  ebp 

    ;~ ************* 
    push 0 
    call exit 
    ;~ *************