So here's my problem. I wrote a script to do both inline and from-file ASM parsing for a project that I plan on expanding later on. It is still very much a work in progress, but fairly functional. Part of that is parsing loop {label}| JZ |JNZ |... ASM commands. In the from-file functionality there is no problem. My script does a two-pass method to store the commands and parse them, so looping and jumping is handled without issue. However, in the inline parser it gets a bit complicated. Do to the nature of the inline parser, I cannot use the same two pass method until I know for sure that a looping command was entered, so I search for one of the looping commands, and if it was found, enter into the subloop that will deal with that little snippet, then after the loop is finished, exit it, all the while pushing every command that was entered into an array for storage and processing in case a loop was found.
in pseudocode #usr/bin/perl -w sub inline my @asm; #the ASM cmds buffer do { getinput(); push(@asm,input); if(isloop(input)) { dealwithloop(); } else { dealwithregularcommand(); } }
Fine. In theory this is great. However, to control the loop my code has to search each command entered a few times, and check to see if that command is the jump or loop ASM instruction that is controlling the loop and decide whether it should run it again. Horribly inefficient.
our pseudocode for the loop now looks like this sub inline my @asm; #the ASM cmds buffer do { getinput(); push(@asm,input); if(isloop(input)) { do { if(isjmp(input)) { $continue=testjmp(); } elsif(isloop(input())#loops and jumps are handled differently { $continue=testloop(); } else { dothing(input); } }until($continue==0) } else { dealwithregularcommand(); } }
So this works, but is not pretty. My other idea was to use a global variable and change that in the looping/jumping subs, and just check it after the loop
Something like this sub jump # this is basically all psuedocode the real sub is more compl +icated but this is the gist { if($condition == TRUE) { $jmptaken = 1; } else { $jmptaken = 0; } } sub loopstuff { do { &DoAllTheThing!!(); #since the loop/jmp is pushed to the arr +ay anyway, it will be run in the &doallthethings }until($jmptaken == 0) }
BUT! no matter what I tried my $jmptaken, our $jmptaken, no matter what scope, no matter where it was placed, $jmptaken would ALWAYS evaluate to the value it was set with, 1 and the loop never stops, 0 and it only runs once, no matter that the debug output always showed it being set in the corresponding subs correctly AND that the value was being passed to the loop conditional correctly. So I'm stumped. What am I missing here and what's the best way to fix this? For reference, I'll include the actual code I'm using at the bottom, but since I am a terrible perl novice at best, it's both messy and inefficient. Yes I know I shouldn't be using & in front of subs but i use that to differentiate between one I wrote and one that's a native perl function. And &tellme is a debug/standard output sub in use throughout my script &tellme("message",indent,urgency)
the real code: sub interactive { my $current = 0; my %interactives; my @tmpASM; my $placeholder = 0; my $linesplit = ''; my $iLINE= ''; my $tmpstr = ''; my $first = 0; &tellme("\e[31mInteractive mode is enabled.",1,0); &tellme("\e[31mType your commands as you were were putting them in +to a file.",1,0); &tellme("\e[31mType ;status to check status, and int 0x80 to save +a frame.",1,0); &tellme("\e[31mType -v or +v at any time to raise or lower the ver +bosity level.",1,0); &tellme("\e[31mType current or cmd at any time to print out the cu +rrent cmds stored in the main array.",1,0); &tellme("\e[31mType q or quit to leave.",2,0); &tellme("\e[31mType anything to continue.",2,0); &getinput; print "\n"; &status; do { push(@tmpASM,$iLINE); #add it to our main parsing array $interactives{$iLINE} = $placeholder; &tellme("\e[34m".$iLINE."\e[33m pushed into main array. There +have been \e[31m".$placeholder." \e[33m commands entered.",1,3) if$ f +irst > 0; $placeholder++; &parsecmd($iLINE); system 'clear' if $first > 0; &status if $first > 0; print "\e[37mPhant0m>"; $first++; $tmpstr = &getinput; $tmpstr =~ m/(^[^;]*)/; # split at comments $iLINE = &trim($1) if (defined($1) and $1 ne '' and substr(&tr +im($1),0,1) ne ';'); # if we got something... $iLINE =~ m/(\w+)[ \t]+(\w+)[ \t]*,?[ \t]*(([^;]*))/i; #spli +t that sucker up my $quickloop = &trim(uc($1)); my $quicklabel = &trim($2) if ($iLINE ne 'CDQ' and defined($2 +)); if (uc($iLINE) eq '+V') { $verbose++ ; &tellme("\e[31mVerbosity increased.",2,0); $iLINE = ''; } elsif (uc($iLINE) eq '-V') { $verbose-- ; $verbose =0 if $verbose == -1; &tellme("\e[31mVerbosity decreased.",2,0); $iLINE = ''; } elsif (uc($iLINE) eq 'CURRENT' or uc($iLINE) eq "CMD") { $iLINE = ''; &tellme("Main Parsing Array",2,0); &tellme("------------------------------------",1,0); foreach (@tmpASM) { &tellme($_,2,0); } } elsif ($quickloop eq 'JNE' or $quickloop eq 'JNS' or $quickloo +p eq 'JS' or $quickloop eq 'JE' or $quickloop eq 'JNE' or $quickloop +eq 'JZ' or $quickloop eq 'JNZ' or $quickloop eq 'LOOP') { my $isjmptaken = 0; $current = $interactives{$quicklabel.":"}; my $loopnumber = $current; do { $tmpASM[$current] =~ m/(\w+)[ \t]+(\w+)[ \t]*,?[ \t]* +(([^;]*))/i; #split that sucker up yet again... $quickloop = &trim(uc($1)); $quicklabel = &trim($2) if ($iLINE ne 'CDQ' and defin +ed($2)); if (uc($quickloop) eq 'LOOP') { $isjmptaken = &LOOP($quickloop, $quicklabel); } elsif($quickloop eq 'JNE' or $quickloop eq 'JNS' or $q +uickloop eq 'JS' or $quickloop eq 'JE' or $quickloop eq 'JNE' or $qui +ckloop eq 'JZ' or $quickloop eq 'JNZ') { $isjmptaken = &JMP($quickloop, $quicklabel); } else { &parsecmd($tmpASM[$current]); } $current++; if (not defined $tmpASM[$current]) { $current = $loopnumber; } } while ($isjmptaken == 1); push(@tmpASM,$quickloop." ".$quicklabel); #add it to our m +ain loop $iLINE = ''; #clear it out so the loop isnt run again at t +he top of our code :) } } until (uc($iLINE) eq 'QUIT' or uc($iLINE) eq 'Q' or uc($iLINE) +eq 'E' or uc($iLINE) eq 'EXIT'); }
In reply to Variables and Scope: The battle begins by Shadow-Master
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |