Jump to content
  • Advertisement
Sign in to follow this  
Waaayoff

[Assembly] Loops and input problems?

This topic is 2854 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I just started learning assembly (for fun) and i have 2 problems.

The first is that this generates an 'infinite' loop instead of just looping 5 times:


include '%fasminc%/win32ax.inc'

.data

inchar DB ?
numwritten DD ?
numread DD ?
outhandle DD ?
inhandle DD ?
string1 DB "Hello World!"

.code

start:
invoke AllocConsole
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov [outhandle],eax
invoke GetStdHandle,STD_INPUT_HANDLE
mov [inhandle],eax

MOV ECX,5
loop1:
invoke WriteConsole,[outhandle],string1,12,numwritten,0
LOOP loop1

invoke ReadConsole,[inhandle],inchar,1,numread,0
invoke ExitProcess,0

.end start





Second problem is that i can't seem to be able to get input twice. With this program, the second ReadConsole doesn't seem to be executing.

include '%fasminc%/win32ax.inc'

.data

inchar DB ?
numread DD ?
inhandle DD ?

.code

start:
invoke AllocConsole
invoke GetStdHandle,STD_INPUT_HANDLE
mov [inhandle],eax

invoke ReadConsole,[inhandle],inchar,1,numread,0
invoke ReadConsole,[inhandle],inchar,1,numread,0

invoke ExitProcess,0

.end start




Oh and one more question, what does the %fasminc% in this line of code do? Is it specific to the FASM assembler i'm using?
include '%fasminc%/win32ax.inc'

Share this post


Link to post
Share on other sites
Advertisement
Regarding your first problem. It looks like it should work. Try changing the "loopl" label into something more obviously a label. "loopl" is very close to looking like the loop instruction itself.

loop_label:
loop_start:
loop_top:

Share this post


Link to post
Share on other sites
You are setting up a loop counter, but you aren't actually counting iterations or comparing to the counter or anything.

Share this post


Link to post
Share on other sites
where are you testing for if your loop needs to be exited?

what i'm reading is

basically

put value 5 in register ecx

looplabel
write this to console
loop to looplable

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
You are setting up a loop counter, but you aren't actually counting iterations or comparing to the counter or anything.


That's built into the LOOP instruction.

From the Intel docs:

Quote:

LOOP/LOOPcc - Loop according to ECX counter

Performs a loop operation using the ECX or CX register as a counter. Each time the LOOP instruction is executed, the count register is decremented, then checked for 0. If the count is 0, the loop is terminated and program execution continues with the instruction following the LOOP instruction. If the count is not zero, a near jump is performed to the destination (target) operand which is presumably the instruction at the beginning of the loop. If the address-size attribute is 32 bits, the ECX register is used as the count register. Otherwise, the CX register is used.


So, one cause for an infinite loop might be that ECX is getting trashed by "invoke", that is, the count is being replaced with a garbage value.

Try setting ECX to 1 and see what happens. If you still get an infinite loop, then ECX is getting trashed somewhere in between. If not then try 2, then 3, then 4, then 5 to see if the problem results somewhere along the way.

Share this post


Link to post
Share on other sites
EAX, ECX, and EDX are not saved by the callee in most calling conventions. EBX, ESI, EDI and EBP are supposed to be preserved by most calling conventions.

I examined some of the assembly within _WriteConsoleA@20 and functions it calls. It definitely overwrites ECX without saving/restoring it.

The easiest fix is to replace your loop by using EDI, DEC, and JNZ manually.


MOV EDI, 5
label:
WriteConsole(...)
DEC EDI
JNZ label


[Edited by - Nypyren on August 26, 2010 3:10:16 PM]

Share this post


Link to post
Share on other sites
Quote:
Original Post by LessBread
So, one cause for an infinite loop might be that ECX is getting trashed by "invoke", that is, the count is being replaced with a garbage value.

Try setting ECX to 1 and see what happens. If you still get an infinite loop, then ECX is getting trashed somewhere in between. If not then try 2, then 3, then 4, then 5 to see if the problem results somewhere along the way


Tried them all, still got an infinite loop. Why would "invoke" trash a register?


Quote:
Original post by Nypyren
EAX, ECX, and EDX are not saved by the callee in most calling conventions. EBX, ESI, EDI and EBP are supposed to be preserved by most calling conventions.

I examined some of the assembly within _WriteConsoleA@20 and functions it calls. It definitely overwrites ECX without saving/restoring it.

The easiest fix is to replace your loop by using EDI, DEC, and JNZ manually.


MOV EDI, 5
label:
WriteConsole(...)
DEC EDI
JNZ label


Hey that worked! Thanks :) One question though. This code basically means:

fill EDI with the value 5
label:
WriteConsole(...)
Decrease EDI by 1
Jump to label


So how does JNZ know when to stop?
Google gave me that "JNE (JNZ) jumps if it is not equal or zero."
???

Thanks for the help. Anyone knows the solution to the second problem? Assembly is so confusing :(

[Edited by - Waaayoff on August 27, 2010 1:36:07 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!