Hey I need some help with this assembly language assignment

Started by jwill22, January 27, 2011, 09:35:29 PM

Previous topic - Next topic

jwill22

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


jj2007

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

jwill22

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

jj2007

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 the "register gets trashed" trap.

dedndave

Kip's library functions tend to preserve all registers, unless something is returned in them

jwill22

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

MichaelW

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.
eschew obfuscation

jwill22

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?

jj2007

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
.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

jwill22

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.....

japheth

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)

dedndave

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

jj2007

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):

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.


brethren

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