Assembly 主要查找-某些数组值被覆盖?
我已经写了一个Eratosthenes算法的筛子,但我有一个奇怪的错误,我不能弄清楚。(编者按:这不是一个筛子;它使用试除法来测试每个数字是否为素数。) 该程序要求用户输入一个数字,然后程序将该素数输出到屏幕程序正确打印所有素数,11之后除外,在11之后,程序将打印3个垃圾号并跳过数字13,然后从17开始继续使用正确的素数。下面是20个素数的输出示例Assembly 主要查找-某些数组值被覆盖?,assembly,x86,masm,Assembly,X86,Masm,我已经写了一个Eratosthenes算法的筛子,但我有一个奇怪的错误,我不能弄清楚。(编者按:这不是一个筛子;它使用试除法来测试每个数字是否为素数。) 该程序要求用户输入一个数字,然后程序将该素数输出到屏幕程序正确打印所有素数,11之后除外,在11之后,程序将打印3个垃圾号并跳过数字13,然后从17开始继续使用正确的素数。下面是20个素数的输出示例 > Enter number of primes: 20.... prime number: 1 prime numb
> Enter number of primes:
20....
prime number: 1
prime number: 2
prime number: 3
prime number: 5
prime number: 7
prime number: 11
prime number: 538976288
prime number: 909588792
prime number: 3291447
prime number: 17
prime number: 19
prime number: 23
prime number: 29
prime number: 31
prime number: 37
prime number: 41
prime number: 43
prime number: 47
prime number: 53
prime number: 59
这些数字存储在一个数组中,在sieve.asm中,我放置了一个名为“PrintLoop2”的标签,用于查看数组中的每个值,我可以看到其中列出了13个,并且没有垃圾,因此我不确定为什么会发生这种情况
asm是主程序,genprimes.asm创建素数并将它们放在堆栈上,其他文件用于I/O
sieve.asm:
.586
.MODEL FLAT
INCLUDE io.h
EXTERN GenPrimes2:PROC
PUBLIC genPrimes
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
count DWORD ?
sieve BYTE 10000 DUP(1)
string BYTE 40 DUP (?)
prompt1 BYTE "Enter number of primes: ", 0
prompt2 BYTE "prime number: ", 0
prompt3 BYTE ", ", 0
primenum DWORD 11 DUP (?), 0
prime BYTE 11 DUP (?), 0
.CODE
genPrimes PROC
; push ebp ; save base pointer
; mov ebp, esp ; establish stack frame
; push ebx
; CODE
call GenPrimes2 ;call function in genprimes.asm to push primes to stack
sub esp, 4 ;move esp down
sub esp, 4 ;esp points to first value
mov ebx, 4 ; counter
mov ecx, 0 ; index register to hold value of esp that will be put into primenum array
loopArray: ;this loop fills primenum with all primes put on the stack in genprimes.asm
mov ecx, [esp]
sub esp, 4
mov primenum[ebx], ecx
add ebx, 4
cmp ebx, 2200
jb loopArray
mov ebx, 4
mov eax, 0
;This loop is for debug purposes only, i want to see if the array primenum has the value 13, which is does
;because i can see it get copied into ecx. However, i get garbage in my output where 13 should be.
PrintLoop2:
mov ecx, primenum[ebx] ; Prime numbers are the non-zeros in this Array
add ebx, 4
cmp ebx, 400
jb PrintLoop2
mov ebx, 4
mov eax, 0
add esp,2204 ;move esp back to return address
ret ;exit genPrimes
genPrimes ENDP
_sieve PROC ; start of sieve program code
input prompt1, string, 40 ; read ASCII characters
call genPrimes
atod string ; convert to integer the number of primes the user entered
mov edx, 0
;this loop will print all the non-zero values stored in the array primenum, i have set all non-primes to 0's so that only
;they will be printed
PrintLoop:
mov ecx, primenum[ebx] ; Prime numbers are the non-zeros in this Array
cmp primenum[ebx], 0
jne printPrime
add ebx, 4
jmp PrintLoop
printPrime:
dtoa prime, ecx ;convert the prime number to a string for printing
output prompt2, prime ; output label and sum
add ebx, 4
inc edx
cmp edx, eax
jb PrintLoop
mov eax, 0 ; exit with return code 0
ret
_sieve ENDP
END
.586
.MODEL FLAT
.STACK 4096
n=550
.data
prime DWORD n DUP(?)
.code
GenPrimes2 PROC
mov ebx, 4
mov ecx, 0
loopArray:
inc ecx
mov prime[ebx], ecx
add ebx, 4
cmp ecx, n
jb loopArray
mov eax, 3
mov ebx, 2
mov edx, 0
mov ecx,3
sieve_loop:
cmp eax,ebx
je skip
mov edx, 0 ;zero out remainder
div ebx
cmp edx,0 ; if remainder 0, not a prime
je NotPrime ;Jump if is a factor, since it cant be prime
; compare eax with n, if equal increment ebx
cmp ecx,n
jge incrementEbx
; compare ebx with n, if equal end sieve
cmp ebx, n
je sieve_end
inc ecx
mov eax, ecx
jmp sieve_loop
skip:
inc eax
jmp sieve_loop
NotPrime:
mov eax, ecx ; store count in eax
imul ecx, 4
mov prime[ecx],0
mov ecx, eax
inc ecx ; increment ecx count
inc eax ; increment eax divisor
jmp sieve_loop
incrementEbx:
inc ebx
mov eax, 3 ; dividend
mov ecx, 3 ; counter
jmp sieve_loop
sieve_end:
mov ebx, 4
mov eax, 0
; ************* Add break point on print loop, ecx will be loading with primes and 0's ********************
; ************* All non-prime numbers have been changed to a 0 ********************
PrintLoop:
mov ecx, prime[ebx] ; Prime numbers are the non-zeros in this Array
push ecx
add ebx, 4
cmp ebx, 2200
jb PrintLoop
add esp,2196
mov eax, 0 ; exit with return code 0
ret
GenPrimes2 ENDP
END
.586
.MODEL FLAT
PUBLIC wtoaproc, atowproc, dtoaproc, atodproc
.CODE
; wtoaproc(source, dest)
; convert integer (source) to string of 6 characters at given destination address
; source integer passed as a doubleword, but only low-order word is processed
wtoaproc PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
push eax ; Save registers
push ebx
push ecx
push edx
push edi
pushfd ; save flags
mov eax, [ebp+8] ; first parameter (source integer)
and eax, 0ffffh ; mask high-order word
mov edi, [ebp+12] ; second parameter (dest offset)
ifSpecW: cmp ax,8000h ; special case -32,768?
jne EndIfSpecW ; if not, then normal case
mov BYTE PTR [edi],'-' ; manually put in ASCII codes
mov BYTE PTR [edi+1],'3' ; for -32,768
mov BYTE PTR [edi+2],'2'
mov BYTE PTR [edi+3],'7'
mov BYTE PTR [edi+4],'6'
mov BYTE PTR [edi+5],'8'
jmp ExitIToA ; done with special case
EndIfSpecW:
push eax ; save source number
mov al,' ' ; put blanks in
mov ecx,5 ; first five
cld ; bytes of
rep stosb ; destination field
pop eax ; restore source number
mov cl,' ' ; default sign (blank for +)
IfNegW: cmp ax,0 ; check sign of number
jge EndIfNegW ; skip if not negative
mov cl,'-' ; sign for negative number
neg ax ; number in AX now >= 0
EndIfNegW:
mov bx,10 ; divisor
WhileMoreW: mov dx,0 ; extend number to doubleword
div bx ; divide by 10
add dl,'0' ; convert remainder to character
mov [edi],dl ; put character in string
dec edi ; move forward to next position
cmp ax,0 ; check quotient
jnz WhileMoreW ; continue if quotient not zero
mov [edi],cl ; insert blank or "-" for sign
ExitIToA: popfd ; restore flags and registers
pop edi
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret ;exit
wtoaproc ENDP
; dtoaproc(source, dest)
; convert double (source) to string of 11 characters at given destination address
dtoaproc PROC NEAR32
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
push eax ; Save registers
push ebx ; used by
push ecx ; procedure
push edx
push edi
pushfd ; save flags
mov eax, [ebp+8] ; first parameter (source double)
mov edi, [ebp+12] ; second parameter (dest addr)
ifSpecialD: cmp eax,80000000h ; special case -2,147,483,648?
jne EndIfSpecialD ; if not, then normal case
mov BYTE PTR [edi],'-' ; manually put in ASCII codes
mov BYTE PTR [edi+1],'2' ; for -2,147,483,648
mov BYTE PTR [edi+2],'1'
mov BYTE PTR [edi+3],'4'
mov BYTE PTR [edi+4],'7'
mov BYTE PTR [edi+5],'4'
mov BYTE PTR [edi+6],'8'
mov BYTE PTR [edi+7],'3'
mov BYTE PTR [edi+8],'6'
mov BYTE PTR [edi+9],'4'
mov BYTE PTR [edi+10],'8'
jmp ExitDToA ; done with special case
EndIfSpecialD:
push eax ; save source number
mov al,' ' ; put blanks in
mov ecx,10 ; first ten
cld ; bytes of
rep stosb ; destination field
pop eax ; copy source number
mov cl,' ' ; default sign (blank for +)
IfNegD: cmp eax,0 ; check sign of number
jge EndIfNegD ; skip if not negative
mov cl,'-' ; sign for negative number
neg eax ; number in EAX now >= 0
EndIfNegD:
mov ebx,10 ; divisor
WhileMoreD: mov edx,0 ; extend number to doubleword
div ebx ; divide by 10
add dl,30h ; convert remainder to character
mov [edi],dl ; put character in string
dec edi ; move forward to next position
cmp eax,0 ; check quotient
jnz WhileMoreD ; continue if quotient not zero
mov [edi],cl ; insert blank or "-" for sign
ExitDToA: popfd ; restore flags and registers
pop edi
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret ;exit
dtoaproc ENDP
; atowproc(source)
; Procedure to scan data segment starting at source address, interpreting
; ASCII characters as an word-size integer value which is returned in AX.
; Leading blanks are skipped. A leading - or + sign is acceptable.
; Digit(s) must immediately follow the sign (if any).
; Memory scan is terminated by any non-digit.
; No error checking is done. If the number is outside the range for a
; signed word, then the return value is undefined.
atowproc PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
sub esp, 2 ; local space for sign
push ebx ; Save registers
push edx
push esi
pushfd ; save flags
mov esi,[ebp+8] ; get parameter (source addr)
WhileBlankW:cmp BYTE PTR [esi],' ' ; space?
jne EndWhileBlankW ; exit if not
inc esi ; increment character pointer
jmp WhileBlankW ; and try again
EndWhileBlankW:
mov ax,1 ; default sign multiplier
IfPlusW: cmp BYTE PTR [esi],'+' ; leading + ?
je SkipSignW ; if so, skip over
IfMinusW: cmp BYTE PTR [esi],'-' ; leading - ?
jne EndIfSignW ; if not, save default +
mov ax,-1 ; -1 for minus sign
SkipSignW: inc esi ; move past sign
EndIfSignW:
mov [ebp-2],ax ; save sign multiplier
mov ax,0 ; number being accumulated
WhileDigitW:cmp BYTE PTR [esi],'0' ; next character >= '0'
jnge EndWhileDigitW ; exit if not
cmp BYTE PTR [esi],'9' ; next character <= '9'
jnle EndWhileDigitW ; not a digit if bigger than '9'
imul ax,10 ; multiply old number by 10
mov bl,[esi] ; ASCII character to BL
and bx,000Fh ; convert to single-digit integer
add ax,bx ; add to sum
inc esi ; increment character pointer
jmp WhileDigitW ; go try next character
EndWhileDigitW:
; if value is < 8000h, multiply by sign
cmp ax,8000h ; 8000h?
jnb endIfMaxW ; skip if not
imul WORD PTR [ebp-2] ; make signed number
endIfMaxW:
popfd ; restore flags
pop esi ; restore registers
pop edx
pop ebx
mov esp, ebp ; delete local variable space
pop ebp
ret ; exit
atowproc ENDP
; atodproc(source)
; Procedure to scan data segment starting at source address, interpreting
; ASCII characters as an doubleword-size integer value which is returned in EAX.
; Leading blanks are skipped. A leading - or + sign is acceptable.
; Digit(s) must immediately follow the sign (if any).
; Memory scan is terminated by any non-digit.
; No error checking is done. If the number is outside the range for a
; signed word, then the return value is undefined.
atodproc PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
sub esp, 4 ; local space for sign
push ebx ; Save registers
push edx
push esi
pushfd ; save flags
mov esi,[ebp+8] ; get parameter (source addr)
WhileBlankD:cmp BYTE PTR [esi],' ' ; space?
jne EndWhileBlankD ; exit if not
inc esi ; increment character pointer
jmp WhileBlankD ; and try again
EndWhileBlankD:
mov eax,1 ; default sign multiplier
IfPlusD: cmp BYTE PTR [esi],'+' ; leading + ?
je SkipSignD ; if so, skip over
IfMinusD: cmp BYTE PTR [esi],'-' ; leading - ?
jne EndIfSignD ; if not, save default +
mov eax,-1 ; -1 for minus sign
SkipSignD: inc esi ; move past sign
EndIfSignD:
mov [ebp-4],eax ; save sign multiplier
mov eax,0 ; number being accumulated
WhileDigitD:cmp BYTE PTR [esi],'0' ; compare next character to '0'
jl EndWhileDigitD ; not a digit if smaller than '0'
cmp BYTE PTR [esi],'9' ; compare to '9'
jg EndWhileDigitD ; not a digit if bigger than '9'
imul eax,10 ; multiply old number by 10
mov bl,[esi] ; ASCII character to BL
and ebx,0000000Fh ; convert to single-digit integer
add eax,ebx ; add to sum
inc esi ; increment character pointer
jmp WhileDigitD ; go try next character
EndWhileDigitD:
; if value is < 80000000h, multiply by sign
cmp eax,80000000h ; 80000000h?
jnb endIfMaxD ; skip if not
imul DWORD PTR [ebp-4] ; make signed number
endIfMaxD:
popfd ; restore flags
pop esi ; restore registers
pop edx
pop ebx
mov esp, ebp ; delete local variable space
pop ebp
ret ; exit
atodproc ENDP
END
genprimes.asm:
.586
.MODEL FLAT
INCLUDE io.h
EXTERN GenPrimes2:PROC
PUBLIC genPrimes
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
count DWORD ?
sieve BYTE 10000 DUP(1)
string BYTE 40 DUP (?)
prompt1 BYTE "Enter number of primes: ", 0
prompt2 BYTE "prime number: ", 0
prompt3 BYTE ", ", 0
primenum DWORD 11 DUP (?), 0
prime BYTE 11 DUP (?), 0
.CODE
genPrimes PROC
; push ebp ; save base pointer
; mov ebp, esp ; establish stack frame
; push ebx
; CODE
call GenPrimes2 ;call function in genprimes.asm to push primes to stack
sub esp, 4 ;move esp down
sub esp, 4 ;esp points to first value
mov ebx, 4 ; counter
mov ecx, 0 ; index register to hold value of esp that will be put into primenum array
loopArray: ;this loop fills primenum with all primes put on the stack in genprimes.asm
mov ecx, [esp]
sub esp, 4
mov primenum[ebx], ecx
add ebx, 4
cmp ebx, 2200
jb loopArray
mov ebx, 4
mov eax, 0
;This loop is for debug purposes only, i want to see if the array primenum has the value 13, which is does
;because i can see it get copied into ecx. However, i get garbage in my output where 13 should be.
PrintLoop2:
mov ecx, primenum[ebx] ; Prime numbers are the non-zeros in this Array
add ebx, 4
cmp ebx, 400
jb PrintLoop2
mov ebx, 4
mov eax, 0
add esp,2204 ;move esp back to return address
ret ;exit genPrimes
genPrimes ENDP
_sieve PROC ; start of sieve program code
input prompt1, string, 40 ; read ASCII characters
call genPrimes
atod string ; convert to integer the number of primes the user entered
mov edx, 0
;this loop will print all the non-zero values stored in the array primenum, i have set all non-primes to 0's so that only
;they will be printed
PrintLoop:
mov ecx, primenum[ebx] ; Prime numbers are the non-zeros in this Array
cmp primenum[ebx], 0
jne printPrime
add ebx, 4
jmp PrintLoop
printPrime:
dtoa prime, ecx ;convert the prime number to a string for printing
output prompt2, prime ; output label and sum
add ebx, 4
inc edx
cmp edx, eax
jb PrintLoop
mov eax, 0 ; exit with return code 0
ret
_sieve ENDP
END
.586
.MODEL FLAT
.STACK 4096
n=550
.data
prime DWORD n DUP(?)
.code
GenPrimes2 PROC
mov ebx, 4
mov ecx, 0
loopArray:
inc ecx
mov prime[ebx], ecx
add ebx, 4
cmp ecx, n
jb loopArray
mov eax, 3
mov ebx, 2
mov edx, 0
mov ecx,3
sieve_loop:
cmp eax,ebx
je skip
mov edx, 0 ;zero out remainder
div ebx
cmp edx,0 ; if remainder 0, not a prime
je NotPrime ;Jump if is a factor, since it cant be prime
; compare eax with n, if equal increment ebx
cmp ecx,n
jge incrementEbx
; compare ebx with n, if equal end sieve
cmp ebx, n
je sieve_end
inc ecx
mov eax, ecx
jmp sieve_loop
skip:
inc eax
jmp sieve_loop
NotPrime:
mov eax, ecx ; store count in eax
imul ecx, 4
mov prime[ecx],0
mov ecx, eax
inc ecx ; increment ecx count
inc eax ; increment eax divisor
jmp sieve_loop
incrementEbx:
inc ebx
mov eax, 3 ; dividend
mov ecx, 3 ; counter
jmp sieve_loop
sieve_end:
mov ebx, 4
mov eax, 0
; ************* Add break point on print loop, ecx will be loading with primes and 0's ********************
; ************* All non-prime numbers have been changed to a 0 ********************
PrintLoop:
mov ecx, prime[ebx] ; Prime numbers are the non-zeros in this Array
push ecx
add ebx, 4
cmp ebx, 2200
jb PrintLoop
add esp,2196
mov eax, 0 ; exit with return code 0
ret
GenPrimes2 ENDP
END
.586
.MODEL FLAT
PUBLIC wtoaproc, atowproc, dtoaproc, atodproc
.CODE
; wtoaproc(source, dest)
; convert integer (source) to string of 6 characters at given destination address
; source integer passed as a doubleword, but only low-order word is processed
wtoaproc PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
push eax ; Save registers
push ebx
push ecx
push edx
push edi
pushfd ; save flags
mov eax, [ebp+8] ; first parameter (source integer)
and eax, 0ffffh ; mask high-order word
mov edi, [ebp+12] ; second parameter (dest offset)
ifSpecW: cmp ax,8000h ; special case -32,768?
jne EndIfSpecW ; if not, then normal case
mov BYTE PTR [edi],'-' ; manually put in ASCII codes
mov BYTE PTR [edi+1],'3' ; for -32,768
mov BYTE PTR [edi+2],'2'
mov BYTE PTR [edi+3],'7'
mov BYTE PTR [edi+4],'6'
mov BYTE PTR [edi+5],'8'
jmp ExitIToA ; done with special case
EndIfSpecW:
push eax ; save source number
mov al,' ' ; put blanks in
mov ecx,5 ; first five
cld ; bytes of
rep stosb ; destination field
pop eax ; restore source number
mov cl,' ' ; default sign (blank for +)
IfNegW: cmp ax,0 ; check sign of number
jge EndIfNegW ; skip if not negative
mov cl,'-' ; sign for negative number
neg ax ; number in AX now >= 0
EndIfNegW:
mov bx,10 ; divisor
WhileMoreW: mov dx,0 ; extend number to doubleword
div bx ; divide by 10
add dl,'0' ; convert remainder to character
mov [edi],dl ; put character in string
dec edi ; move forward to next position
cmp ax,0 ; check quotient
jnz WhileMoreW ; continue if quotient not zero
mov [edi],cl ; insert blank or "-" for sign
ExitIToA: popfd ; restore flags and registers
pop edi
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret ;exit
wtoaproc ENDP
; dtoaproc(source, dest)
; convert double (source) to string of 11 characters at given destination address
dtoaproc PROC NEAR32
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
push eax ; Save registers
push ebx ; used by
push ecx ; procedure
push edx
push edi
pushfd ; save flags
mov eax, [ebp+8] ; first parameter (source double)
mov edi, [ebp+12] ; second parameter (dest addr)
ifSpecialD: cmp eax,80000000h ; special case -2,147,483,648?
jne EndIfSpecialD ; if not, then normal case
mov BYTE PTR [edi],'-' ; manually put in ASCII codes
mov BYTE PTR [edi+1],'2' ; for -2,147,483,648
mov BYTE PTR [edi+2],'1'
mov BYTE PTR [edi+3],'4'
mov BYTE PTR [edi+4],'7'
mov BYTE PTR [edi+5],'4'
mov BYTE PTR [edi+6],'8'
mov BYTE PTR [edi+7],'3'
mov BYTE PTR [edi+8],'6'
mov BYTE PTR [edi+9],'4'
mov BYTE PTR [edi+10],'8'
jmp ExitDToA ; done with special case
EndIfSpecialD:
push eax ; save source number
mov al,' ' ; put blanks in
mov ecx,10 ; first ten
cld ; bytes of
rep stosb ; destination field
pop eax ; copy source number
mov cl,' ' ; default sign (blank for +)
IfNegD: cmp eax,0 ; check sign of number
jge EndIfNegD ; skip if not negative
mov cl,'-' ; sign for negative number
neg eax ; number in EAX now >= 0
EndIfNegD:
mov ebx,10 ; divisor
WhileMoreD: mov edx,0 ; extend number to doubleword
div ebx ; divide by 10
add dl,30h ; convert remainder to character
mov [edi],dl ; put character in string
dec edi ; move forward to next position
cmp eax,0 ; check quotient
jnz WhileMoreD ; continue if quotient not zero
mov [edi],cl ; insert blank or "-" for sign
ExitDToA: popfd ; restore flags and registers
pop edi
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret ;exit
dtoaproc ENDP
; atowproc(source)
; Procedure to scan data segment starting at source address, interpreting
; ASCII characters as an word-size integer value which is returned in AX.
; Leading blanks are skipped. A leading - or + sign is acceptable.
; Digit(s) must immediately follow the sign (if any).
; Memory scan is terminated by any non-digit.
; No error checking is done. If the number is outside the range for a
; signed word, then the return value is undefined.
atowproc PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
sub esp, 2 ; local space for sign
push ebx ; Save registers
push edx
push esi
pushfd ; save flags
mov esi,[ebp+8] ; get parameter (source addr)
WhileBlankW:cmp BYTE PTR [esi],' ' ; space?
jne EndWhileBlankW ; exit if not
inc esi ; increment character pointer
jmp WhileBlankW ; and try again
EndWhileBlankW:
mov ax,1 ; default sign multiplier
IfPlusW: cmp BYTE PTR [esi],'+' ; leading + ?
je SkipSignW ; if so, skip over
IfMinusW: cmp BYTE PTR [esi],'-' ; leading - ?
jne EndIfSignW ; if not, save default +
mov ax,-1 ; -1 for minus sign
SkipSignW: inc esi ; move past sign
EndIfSignW:
mov [ebp-2],ax ; save sign multiplier
mov ax,0 ; number being accumulated
WhileDigitW:cmp BYTE PTR [esi],'0' ; next character >= '0'
jnge EndWhileDigitW ; exit if not
cmp BYTE PTR [esi],'9' ; next character <= '9'
jnle EndWhileDigitW ; not a digit if bigger than '9'
imul ax,10 ; multiply old number by 10
mov bl,[esi] ; ASCII character to BL
and bx,000Fh ; convert to single-digit integer
add ax,bx ; add to sum
inc esi ; increment character pointer
jmp WhileDigitW ; go try next character
EndWhileDigitW:
; if value is < 8000h, multiply by sign
cmp ax,8000h ; 8000h?
jnb endIfMaxW ; skip if not
imul WORD PTR [ebp-2] ; make signed number
endIfMaxW:
popfd ; restore flags
pop esi ; restore registers
pop edx
pop ebx
mov esp, ebp ; delete local variable space
pop ebp
ret ; exit
atowproc ENDP
; atodproc(source)
; Procedure to scan data segment starting at source address, interpreting
; ASCII characters as an doubleword-size integer value which is returned in EAX.
; Leading blanks are skipped. A leading - or + sign is acceptable.
; Digit(s) must immediately follow the sign (if any).
; Memory scan is terminated by any non-digit.
; No error checking is done. If the number is outside the range for a
; signed word, then the return value is undefined.
atodproc PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
sub esp, 4 ; local space for sign
push ebx ; Save registers
push edx
push esi
pushfd ; save flags
mov esi,[ebp+8] ; get parameter (source addr)
WhileBlankD:cmp BYTE PTR [esi],' ' ; space?
jne EndWhileBlankD ; exit if not
inc esi ; increment character pointer
jmp WhileBlankD ; and try again
EndWhileBlankD:
mov eax,1 ; default sign multiplier
IfPlusD: cmp BYTE PTR [esi],'+' ; leading + ?
je SkipSignD ; if so, skip over
IfMinusD: cmp BYTE PTR [esi],'-' ; leading - ?
jne EndIfSignD ; if not, save default +
mov eax,-1 ; -1 for minus sign
SkipSignD: inc esi ; move past sign
EndIfSignD:
mov [ebp-4],eax ; save sign multiplier
mov eax,0 ; number being accumulated
WhileDigitD:cmp BYTE PTR [esi],'0' ; compare next character to '0'
jl EndWhileDigitD ; not a digit if smaller than '0'
cmp BYTE PTR [esi],'9' ; compare to '9'
jg EndWhileDigitD ; not a digit if bigger than '9'
imul eax,10 ; multiply old number by 10
mov bl,[esi] ; ASCII character to BL
and ebx,0000000Fh ; convert to single-digit integer
add eax,ebx ; add to sum
inc esi ; increment character pointer
jmp WhileDigitD ; go try next character
EndWhileDigitD:
; if value is < 80000000h, multiply by sign
cmp eax,80000000h ; 80000000h?
jnb endIfMaxD ; skip if not
imul DWORD PTR [ebp-4] ; make signed number
endIfMaxD:
popfd ; restore flags
pop esi ; restore registers
pop edx
pop ebx
mov esp, ebp ; delete local variable space
pop ebp
ret ; exit
atodproc ENDP
END
io.asm:
.586
.MODEL FLAT
INCLUDE io.h
EXTERN GenPrimes2:PROC
PUBLIC genPrimes
.STACK 4096 ; reserve 4096-byte stack
.DATA ; reserve storage for data
count DWORD ?
sieve BYTE 10000 DUP(1)
string BYTE 40 DUP (?)
prompt1 BYTE "Enter number of primes: ", 0
prompt2 BYTE "prime number: ", 0
prompt3 BYTE ", ", 0
primenum DWORD 11 DUP (?), 0
prime BYTE 11 DUP (?), 0
.CODE
genPrimes PROC
; push ebp ; save base pointer
; mov ebp, esp ; establish stack frame
; push ebx
; CODE
call GenPrimes2 ;call function in genprimes.asm to push primes to stack
sub esp, 4 ;move esp down
sub esp, 4 ;esp points to first value
mov ebx, 4 ; counter
mov ecx, 0 ; index register to hold value of esp that will be put into primenum array
loopArray: ;this loop fills primenum with all primes put on the stack in genprimes.asm
mov ecx, [esp]
sub esp, 4
mov primenum[ebx], ecx
add ebx, 4
cmp ebx, 2200
jb loopArray
mov ebx, 4
mov eax, 0
;This loop is for debug purposes only, i want to see if the array primenum has the value 13, which is does
;because i can see it get copied into ecx. However, i get garbage in my output where 13 should be.
PrintLoop2:
mov ecx, primenum[ebx] ; Prime numbers are the non-zeros in this Array
add ebx, 4
cmp ebx, 400
jb PrintLoop2
mov ebx, 4
mov eax, 0
add esp,2204 ;move esp back to return address
ret ;exit genPrimes
genPrimes ENDP
_sieve PROC ; start of sieve program code
input prompt1, string, 40 ; read ASCII characters
call genPrimes
atod string ; convert to integer the number of primes the user entered
mov edx, 0
;this loop will print all the non-zero values stored in the array primenum, i have set all non-primes to 0's so that only
;they will be printed
PrintLoop:
mov ecx, primenum[ebx] ; Prime numbers are the non-zeros in this Array
cmp primenum[ebx], 0
jne printPrime
add ebx, 4
jmp PrintLoop
printPrime:
dtoa prime, ecx ;convert the prime number to a string for printing
output prompt2, prime ; output label and sum
add ebx, 4
inc edx
cmp edx, eax
jb PrintLoop
mov eax, 0 ; exit with return code 0
ret
_sieve ENDP
END
.586
.MODEL FLAT
.STACK 4096
n=550
.data
prime DWORD n DUP(?)
.code
GenPrimes2 PROC
mov ebx, 4
mov ecx, 0
loopArray:
inc ecx
mov prime[ebx], ecx
add ebx, 4
cmp ecx, n
jb loopArray
mov eax, 3
mov ebx, 2
mov edx, 0
mov ecx,3
sieve_loop:
cmp eax,ebx
je skip
mov edx, 0 ;zero out remainder
div ebx
cmp edx,0 ; if remainder 0, not a prime
je NotPrime ;Jump if is a factor, since it cant be prime
; compare eax with n, if equal increment ebx
cmp ecx,n
jge incrementEbx
; compare ebx with n, if equal end sieve
cmp ebx, n
je sieve_end
inc ecx
mov eax, ecx
jmp sieve_loop
skip:
inc eax
jmp sieve_loop
NotPrime:
mov eax, ecx ; store count in eax
imul ecx, 4
mov prime[ecx],0
mov ecx, eax
inc ecx ; increment ecx count
inc eax ; increment eax divisor
jmp sieve_loop
incrementEbx:
inc ebx
mov eax, 3 ; dividend
mov ecx, 3 ; counter
jmp sieve_loop
sieve_end:
mov ebx, 4
mov eax, 0
; ************* Add break point on print loop, ecx will be loading with primes and 0's ********************
; ************* All non-prime numbers have been changed to a 0 ********************
PrintLoop:
mov ecx, prime[ebx] ; Prime numbers are the non-zeros in this Array
push ecx
add ebx, 4
cmp ebx, 2200
jb PrintLoop
add esp,2196
mov eax, 0 ; exit with return code 0
ret
GenPrimes2 ENDP
END
.586
.MODEL FLAT
PUBLIC wtoaproc, atowproc, dtoaproc, atodproc
.CODE
; wtoaproc(source, dest)
; convert integer (source) to string of 6 characters at given destination address
; source integer passed as a doubleword, but only low-order word is processed
wtoaproc PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
push eax ; Save registers
push ebx
push ecx
push edx
push edi
pushfd ; save flags
mov eax, [ebp+8] ; first parameter (source integer)
and eax, 0ffffh ; mask high-order word
mov edi, [ebp+12] ; second parameter (dest offset)
ifSpecW: cmp ax,8000h ; special case -32,768?
jne EndIfSpecW ; if not, then normal case
mov BYTE PTR [edi],'-' ; manually put in ASCII codes
mov BYTE PTR [edi+1],'3' ; for -32,768
mov BYTE PTR [edi+2],'2'
mov BYTE PTR [edi+3],'7'
mov BYTE PTR [edi+4],'6'
mov BYTE PTR [edi+5],'8'
jmp ExitIToA ; done with special case
EndIfSpecW:
push eax ; save source number
mov al,' ' ; put blanks in
mov ecx,5 ; first five
cld ; bytes of
rep stosb ; destination field
pop eax ; restore source number
mov cl,' ' ; default sign (blank for +)
IfNegW: cmp ax,0 ; check sign of number
jge EndIfNegW ; skip if not negative
mov cl,'-' ; sign for negative number
neg ax ; number in AX now >= 0
EndIfNegW:
mov bx,10 ; divisor
WhileMoreW: mov dx,0 ; extend number to doubleword
div bx ; divide by 10
add dl,'0' ; convert remainder to character
mov [edi],dl ; put character in string
dec edi ; move forward to next position
cmp ax,0 ; check quotient
jnz WhileMoreW ; continue if quotient not zero
mov [edi],cl ; insert blank or "-" for sign
ExitIToA: popfd ; restore flags and registers
pop edi
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret ;exit
wtoaproc ENDP
; dtoaproc(source, dest)
; convert double (source) to string of 11 characters at given destination address
dtoaproc PROC NEAR32
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
push eax ; Save registers
push ebx ; used by
push ecx ; procedure
push edx
push edi
pushfd ; save flags
mov eax, [ebp+8] ; first parameter (source double)
mov edi, [ebp+12] ; second parameter (dest addr)
ifSpecialD: cmp eax,80000000h ; special case -2,147,483,648?
jne EndIfSpecialD ; if not, then normal case
mov BYTE PTR [edi],'-' ; manually put in ASCII codes
mov BYTE PTR [edi+1],'2' ; for -2,147,483,648
mov BYTE PTR [edi+2],'1'
mov BYTE PTR [edi+3],'4'
mov BYTE PTR [edi+4],'7'
mov BYTE PTR [edi+5],'4'
mov BYTE PTR [edi+6],'8'
mov BYTE PTR [edi+7],'3'
mov BYTE PTR [edi+8],'6'
mov BYTE PTR [edi+9],'4'
mov BYTE PTR [edi+10],'8'
jmp ExitDToA ; done with special case
EndIfSpecialD:
push eax ; save source number
mov al,' ' ; put blanks in
mov ecx,10 ; first ten
cld ; bytes of
rep stosb ; destination field
pop eax ; copy source number
mov cl,' ' ; default sign (blank for +)
IfNegD: cmp eax,0 ; check sign of number
jge EndIfNegD ; skip if not negative
mov cl,'-' ; sign for negative number
neg eax ; number in EAX now >= 0
EndIfNegD:
mov ebx,10 ; divisor
WhileMoreD: mov edx,0 ; extend number to doubleword
div ebx ; divide by 10
add dl,30h ; convert remainder to character
mov [edi],dl ; put character in string
dec edi ; move forward to next position
cmp eax,0 ; check quotient
jnz WhileMoreD ; continue if quotient not zero
mov [edi],cl ; insert blank or "-" for sign
ExitDToA: popfd ; restore flags and registers
pop edi
pop edx
pop ecx
pop ebx
pop eax
pop ebp
ret ;exit
dtoaproc ENDP
; atowproc(source)
; Procedure to scan data segment starting at source address, interpreting
; ASCII characters as an word-size integer value which is returned in AX.
; Leading blanks are skipped. A leading - or + sign is acceptable.
; Digit(s) must immediately follow the sign (if any).
; Memory scan is terminated by any non-digit.
; No error checking is done. If the number is outside the range for a
; signed word, then the return value is undefined.
atowproc PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
sub esp, 2 ; local space for sign
push ebx ; Save registers
push edx
push esi
pushfd ; save flags
mov esi,[ebp+8] ; get parameter (source addr)
WhileBlankW:cmp BYTE PTR [esi],' ' ; space?
jne EndWhileBlankW ; exit if not
inc esi ; increment character pointer
jmp WhileBlankW ; and try again
EndWhileBlankW:
mov ax,1 ; default sign multiplier
IfPlusW: cmp BYTE PTR [esi],'+' ; leading + ?
je SkipSignW ; if so, skip over
IfMinusW: cmp BYTE PTR [esi],'-' ; leading - ?
jne EndIfSignW ; if not, save default +
mov ax,-1 ; -1 for minus sign
SkipSignW: inc esi ; move past sign
EndIfSignW:
mov [ebp-2],ax ; save sign multiplier
mov ax,0 ; number being accumulated
WhileDigitW:cmp BYTE PTR [esi],'0' ; next character >= '0'
jnge EndWhileDigitW ; exit if not
cmp BYTE PTR [esi],'9' ; next character <= '9'
jnle EndWhileDigitW ; not a digit if bigger than '9'
imul ax,10 ; multiply old number by 10
mov bl,[esi] ; ASCII character to BL
and bx,000Fh ; convert to single-digit integer
add ax,bx ; add to sum
inc esi ; increment character pointer
jmp WhileDigitW ; go try next character
EndWhileDigitW:
; if value is < 8000h, multiply by sign
cmp ax,8000h ; 8000h?
jnb endIfMaxW ; skip if not
imul WORD PTR [ebp-2] ; make signed number
endIfMaxW:
popfd ; restore flags
pop esi ; restore registers
pop edx
pop ebx
mov esp, ebp ; delete local variable space
pop ebp
ret ; exit
atowproc ENDP
; atodproc(source)
; Procedure to scan data segment starting at source address, interpreting
; ASCII characters as an doubleword-size integer value which is returned in EAX.
; Leading blanks are skipped. A leading - or + sign is acceptable.
; Digit(s) must immediately follow the sign (if any).
; Memory scan is terminated by any non-digit.
; No error checking is done. If the number is outside the range for a
; signed word, then the return value is undefined.
atodproc PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
sub esp, 4 ; local space for sign
push ebx ; Save registers
push edx
push esi
pushfd ; save flags
mov esi,[ebp+8] ; get parameter (source addr)
WhileBlankD:cmp BYTE PTR [esi],' ' ; space?
jne EndWhileBlankD ; exit if not
inc esi ; increment character pointer
jmp WhileBlankD ; and try again
EndWhileBlankD:
mov eax,1 ; default sign multiplier
IfPlusD: cmp BYTE PTR [esi],'+' ; leading + ?
je SkipSignD ; if so, skip over
IfMinusD: cmp BYTE PTR [esi],'-' ; leading - ?
jne EndIfSignD ; if not, save default +
mov eax,-1 ; -1 for minus sign
SkipSignD: inc esi ; move past sign
EndIfSignD:
mov [ebp-4],eax ; save sign multiplier
mov eax,0 ; number being accumulated
WhileDigitD:cmp BYTE PTR [esi],'0' ; compare next character to '0'
jl EndWhileDigitD ; not a digit if smaller than '0'
cmp BYTE PTR [esi],'9' ; compare to '9'
jg EndWhileDigitD ; not a digit if bigger than '9'
imul eax,10 ; multiply old number by 10
mov bl,[esi] ; ASCII character to BL
and ebx,0000000Fh ; convert to single-digit integer
add eax,ebx ; add to sum
inc esi ; increment character pointer
jmp WhileDigitD ; go try next character
EndWhileDigitD:
; if value is < 80000000h, multiply by sign
cmp eax,80000000h ; 80000000h?
jnb endIfMaxD ; skip if not
imul DWORD PTR [ebp-4] ; make signed number
endIfMaxD:
popfd ; restore flags
pop esi ; restore registers
pop edx
pop ebx
mov esp, ebp ; delete local variable space
pop ebp
ret ; exit
atodproc ENDP
END
.586
.样板房
公共wtoaproc、atowproc、dtoaproc、atodproc
.代码
; wtoaproc(源、目标)
; 在给定的目标地址将整数(源)转换为6个字符的字符串
; 源整数作为双字传递,但只处理低阶字
wtoaproc程序
推动ebp;保存基指针
mov-ebp,esp;建立堆栈框架
推动eax;保存寄存器
推ebx
推ecx
推式edx
推式电子数据交换
pushfd;保存标志
mov-eax,[ebp+8];第一个参数(源整数)
和eax,0ffffh;屏蔽高阶字
移动电子数据交换[ebp+12];第二个参数(目标偏移量)
如果规格:cmp ax,8000h;特殊情况-32768?
jne-EndIfSpecW;如果不是,则为正常情况
mov字节PTR[edi],“-”;手动输入ASCII码
mov字节PTR[edi+1],'3';适用于-32768
mov字节PTR[edi+2],'2'
mov字节PTR[edi+3],'7'
mov字节PTR[edi+4],'6'
mov字节PTR[edi+5],'8'
jmp-ExitIToA;特殊情况下完成
EndIfSpecW:
推动eax;保存源代码
mov al,”;填空
mov-ecx,5;前五名
cld;字节
代表stosb;目的地字段
pop-eax;还原源代码
mov-cl';默认符号(对于+为空)
IfNegW:cmp-ax,0;核对号码
jge-EndIfNegW;如果不是负数,则跳过
mov-cl'-';负数符号
neg-ax;AX中的数字现在>=0
EndIfNegW:
mov-bx,10;除数
WhileMoreW:mov-dx,0;将数字扩展为双字
分区bx;除以10
加上dl,'0';将余数转换为字符
mov[edi],dl;将字符放入字符串中
dec-edi;前进到下一个位置
cmp-ax,0;校验商
jnz WhileMoreW;如果商不为零,则继续
mov[edi],cl;插入空白或“-”作为符号
存在:popfd;还原标志和寄存器
流行电子数据交换
波普edx
波普ecx
流行电子束
波普eax
流行ebp
ret;出口
wtoaproc ENDP
; dtoaproc(源、目标)
; 在给定的目标地址将双精度(源)转换为11个字符的字符串
dtoaproc PROC NEAR32
推动ebp;保存基指针
mov-ebp,esp;建立堆栈框架
推动eax;保存寄存器
推ebx;被使用
推动ecx;程序
推式edx
推式电子数据交换
pushfd;保存标志
mov-eax,[ebp+8];第一个参数(源双精度)
移动电子数据交换[ebp+12];第二个参数(dest addr)
如果特别许可:cmp eax,80000000h;特殊情况-2147483648?
jne-EndIfSpecialD;如果不是,则为正常情况
mov字节PTR[edi],“-”;手动输入ASCII码
mov字节PTR[edi+1],'2';适用于-2147483648
mov字节PTR[edi+2],'1'
mov字节PTR[edi+3],'4'
mov字节PTR[edi+4],'7'
mov字节PTR[edi+5],'4'
mov字节PTR[edi+6],'8'
mov字节PTR[edi+7],'3'
mov字节PTR[edi+8],'6'
mov字节PTR[edi+9],'4'
mov字节PTR[edi+10],'8'
jmp-ExitDToA;特殊情况下完成
EndIfSpecialD:
推动eax;保存源代码
mov al,”;填空
mov-ecx,10;前十名
cld;字节
代表stosb;目的地字段
pop-eax;复制源编号
mov-cl';默认符号(对于+为空)
IfNegD:cmp-eax,0;核对号码
jge-EndIfNegD;如果不是负数,则跳过
mov-cl'-';负数符号
neg-eax;EAX中的数字现在>=0
EndIfNegD:
mov ecx, primenum[ebx] ; Prime numbers are the non-zeros in this Array
test ecx, ecx
jnz printPrime