OK let me say first that I'm using Kip Irvine's book,"Assembly Language for x86 processors", and I'm using Microsoft Visual c++ 2010. OK I need to (1). fill an array with 50 random integers;(2) loop through the array, displaying each value, and count the number of negative values;(3) after the loop finishes, display the count. I'm having a problem with counting the negative numbers. This is what I got so far.
INCLUDE Irvine32.inc
.data
array1 SWORD 50 DUP(0)
count SWORD 0
.code
main PROC
mov ecx,50
mov esi OFFSET array1
mov esi,eax
mov ebx,0
eloop:
add esi,2
call Random32
call WriteInt
mov esi,eax
loop eloop
exit
main ENDP
END main
Quote from: jwill22 on January 27, 2011, 09:35:29 PM
call Random32
mov [esi], ax
call WriteInt
1. We don't use Irvine's lib much here, but normally a function such as WriteInt will overwrite eax. Check also if ecx is preserved, otherwise you need a push ecx/pop ecx pair around the calls.
2. So you must save it
to memory ( [esi], not esi ) before WriteInt, and as ax because your array is word sized.
3. You do know the no homework rule, right? But since you are pretty advanced, and posted your own code, we'll make an exception.
Welcome to the Forum :bg
Yes i did read about the homework rule..and believe me i don't want anybody to spoonfeed me anything..i'm too competitive for that, but thanks for that..I'm about to try that right now :bg :bg :bg :bg
by far the best way of learning is to run your executable with OllyDebug. The F7 and F8 key will be your friends. Check especially the content of eax, ecx, edx after calls.
Check also here (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm) the "register gets trashed" trap.
Kip's library functions tend to preserve all registers, unless something is returned in them
Ok what do you mean by preserve :eek ? by the way I'm still not getting it..I'll post what I have in a lil bit
Preserving a register means essentially preserving the value of the register around code that uses the register. For example, this is the code I have for the Irvine32 Random32 procedure:
push edx
mov eax, 343FDh
imul seed
add eax, 269EC3h
mov seed, eax ; save the seed for the next call
ror eax,8 ; rotate out the lowest digit (10/22/00)
pop edx
ret
EDX is used by the imul instruction, so to preserve it a copy of its value is pushed onto the stack at procedure entry, and the copy is popped off the stack and into the EDX register before the procedure returns. So this procedure preserves all registers, other than the EAX register that it uses to return the random number.
Ooohhhh....oookkkk
here's what I have though. I'm trying to figure out how to loop this so it can move to the next element in the array each time it loops
INCLUDE Irvine32.inc
.data
array1 SDWORD 50 DUP(?)
ptr3 SDWORD array1
.code
main PROC
mov ecx,50
mov esi, OFFSET array1-4
loop1:
add esi,4
call Random32
call WriteInt
mov [esi],eax
call Crlf
loop loop1
mov ecx,50
step:
add esi,4
mov esi,ptr3
mov eax,[esi]
call WriteInt
loop step
Every time It loops at the bottom it just displays the 1st number in [esi]...I know I have to add 4 to [esi] each time to move to the next element, but I'm having a problem with trying to do that. Any Suggestions?
Since I can't test it with Irvine's library, here an example in MB. It works perfectly:
...
negative: -48
negative: -19
29 positive and 21 negative numbers found
Quoteinclude \masm32\MasmBasic\MasmBasic.inc ; download (http://www.masm32.com/board/index.php?topic=12460)
.data
ctPos dd ?
ctNeg dd ?
array1 SDWORD 50 DUP(?)
ptr3 SDWORD array1 ; what is the role of this one??
Init
Rand()[/color] ; initialise random generator
mov ecx, 50
mov esi, OFFSET array1-4 ; put esi on start of array
loop1:
add esi, 4
mov eax, Rand(100) ; generate a random number between 0 and 100
sub eax, 50 ; transform to -50...+50
mov [esi], eax
loop loop1
mov ecx, 50
mov esi, OFFSET array1-4 ; reset esi to start of array
step:
add esi, 4
mov eax, [esi]
test eax, eax
.if Sign?
Print Str$("negative: %i", [esi]), CrLf$
inc ctNeg
.else
Print Str$("positive: %i", [esi]), CrLf$
inc ctPos
.endif
loop step
Inkey Str$("\n%i positive ", ctPos), Str$("and %i negative numbers found", ctNeg)
Exit
end start
Thanks so Much..!! But I still didn't get the final product correct :( :( :( I'm just going to e-mail my instructor what i got. I feel kinda dumb :'(
Here's my code
INCLUDE Irvine32.inc
.data
array1 SDWORD 50 DUP(?) ;allocate room for array
;ptr3 SDWORD array1
count DD 0 ;count variable
deduct dd 0 ;deduct variable
.code
main PROC
mov ecx,50 ;move 50 to loop counter
mov esi, OFFSET array1-4 ;point to the array
loop1:
add esi,4 ;point to first element
call Random32 ;generate random 32 bit integer
call WriteInt
mov [esi],eax ;mov integer to memory
call Crlf ;create a new line
loop loop1
mov ecx,50 ;mov 50 to loop counter
mov esi,OFFSET array1-4 ;point to array
mov ebx,0
step:
add esi,4 ;point to element
mov eax,[esi] ;mov 1st element in memory to eax
cmp eax,0 ;compare eax to 0
.if (eax < 0)
inc count
.else
dec deduct
.endif
loop step
mov eax,count ;mov the count to eax
call WriteInt ;write number to screen
exit
main ENDP
END main
Man I tried.....
Quote from: jwill22 on January 28, 2011, 08:12:55 AM
Man I tried.....
You'll have to tell Masm that the register is supposed to contain a SIGNED value:
.if ( sdword ptr eax < 0)
the code you have works, except that you are not incrementing the index into the array with each loop pass
mov [esi],eax ;mov integer to memory
add esi,4 ;point to next array element
Quote from: dedndave on January 28, 2011, 09:03:58 AM
the code you have works, except that you are not incrementing the index into the array with each loop pass
mov [esi],eax ;mov integer to memory
add esi,4 ;point to next array element
Dave,
He uses mov esi, OFFSET array1
-4, so the
add esi, 4 is in the right position.
The eax<0 issue already flagged by Japheth is more serious (link (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm)):
Quotemov eax, -1
.if eax<0
MsgBox 0, "Eax is less than zero", "Hi", MB_OK
.else
MsgBox 0, "Surprise, surprise: eax is NOT less than zero", "Hi", MB_OK
.endif
The reason is simple: Registers are by definition unsigned integers. After a mov eax, -1, the register contains the
value 0FFFFFFFFh, decimal 4294967295 - and that is indeed a number way above zero. To achieve what you want
with .if eax<0, use .if sdword ptr eax<0 - this ensures that the register will be interpreted as a signed integer.
my mistake :P
INCLUDE Irvine32.inc
ARRAYSIZE = 50
.data
msg BYTE " negative values found.", 13, 10, 0
buffer SDWORD ARRAYSIZE DUP(0)
counter DWORD 0
.code
main PROC
call Randomize
;part 1 - fill array with random numbers
mov ecx, ARRAYSIZE
mov esi, OFFSET buffer
L1:
call Random32
mov [esi], eax
add esi, TYPE buffer
loop L1
;part 2 - loop through the array, display each value, count negative numbers
mov esi, OFFSET buffer
mov ecx, ARRAYSIZE
L2:
mov eax, [esi]
cmp eax, 0
jge @F
inc counter
@@:
call WriteInt
call Crlf
add esi, TYPE buffer
loop L2
;part 3 - Display the count
mov eax, counter
call WriteDec
mov edx, OFFSET msg
call WriteString
exit
main ENDP
END main
that'll do the job but make sure you understand it! if theres anything you don't understand feel free to ask
btw run it through a debugger :wink just change the value of ARRAYSIZE to say, 5, then trace your way through the program. then you'll see how it works
isn't there the need to preserver ECX when calling the functions Random32 and WriteInt?
Quote from: qWord on January 28, 2011, 06:17:31 PM
isn't there the need to preserver ECX when calling the functions Random32 and WriteInt?
no, internally all procs in irvine32.lib push/pop any registers they use (except for a return value in eax, of course :P)
heres one example
QuoteWriteInt PROC
;
; Writes a 32-bit signed binary integer to the console window
; in ASCII decimal.
; Receives: EAX = the integer
; Returns: nothing
; Comments: Displays a leading sign, no leading zeros.
; Last update: 7/11/01
;-----------------------------------------------------
WI_Bufsize = 12
true = 1
false = 0
.data
buffer_B BYTE WI_Bufsize DUP(0),0 ; buffer to hold digits
neg_flag BYTE ?
.code
pushad
CheckInit
mov neg_flag,false ; assume neg_flag is false
or eax,eax ; is AX positive?
jns WIS1 ; yes: jump to B1
neg eax ; no: make it positive
mov neg_flag,true ; set neg_flag to true
.....
:bg :bg :bg I'm sorry I didn't get back to u guys sooner. I had to do a little surgery on my laptop, but I'm alright now. Thanks to everyone, I think I understand now. I really appreciate it. :U