2014-01-27 59 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 
    ;~ *************