CSC231 Bash Tutorial 5

From dftwiki3
Jump to: navigation, search

--D. Thiebaut (talk) 08:04, 3 March 2017 (EST)
revised --D. Thiebaut (talk) 15:38, 11 October 2017 (EDT)



BlackCat.png

Friday the 13, Lab!
This lab will introduce you to using Nasm as a tool for better understanding instructions. You will also look at a different way of redirecting standard out (stdout), and play with the powerful for-loop in bash.




Using Nasm to Test Instructions


Writing a short assembly program to answer quick questions is simple and can be quick. We'll do a couple examples.

Testing how DIV works


  • Get a copy of test_skel.asm
getcopy test_skel.asm

  • This is the code you'll find in the program:
;;; Testing sandbox
;;;  nasm -f elf test_asm.asm
;;;  ld -melf_i386 -o test_asm test_asm.o 231Lib.o

	        extern  _printDec
	        extern  _printString
	        extern  _println
	        extern  _getInput
		extern	_printRegs
	
	section	.data
a		dd	100
b		dd	33
c		dd	0
ans		dd	0
	
		section	.text
		global	_start
	
_start:
;-------------------------------------------------
;;; 		mov	edx, 0
;;; 		mov	eax, dword[a]
;;; 		div	dword[b]
;;; 
;;; 		call	_printRegs

	
;;; exit -------------------------------------------------
		mov	ebx, 0
		mov	eax, 1
		int     0x80


  • It has everything needed to test short pieces of code, and you may want to use it for future homework assignments.
  • Notice that we are using a new function from the 231Lib library: _printRegs. You will see shortly what it does.
  • Remove the commas that are commenting out the mov, mov, div and call instructions.


 		mov	edx, 0
		mov	eax, dword[a]
 		div	dword[b]
 
 		call	_printRegs
  • Assembly, link and run:
 nasm -f elf test_skel.asm
 ld -melf_i386 -o test_skel test_skel.o 231Lib.o
 ./test_skel 

  • Do you see the quotient and remainder in the registers?
  • Add another call to _printRegs just before you do the div instruction. Assemble and link again.
  • Run the program. You will now see two sets of registers when you run the program, one set before the div takes place, and one set just before the div has executed. See how the different registers were modified?


You should practice doing this simple exercise every time you are not sure about a particular set of instructions. If you start with a skeleton program, such as test_skel.asm, all you have to do is remove the instructions that are between the dashed lines, put your own instruction block in the middle part, assemble, link and run, and you will see how your registers change. You can also call _printRegs in the middle of your homework code, just to see how registers are set, and then remove these calls before submitting your program.


Hex, Binary, and Signed numbers


  • You can use the _printRegs function to see different representations of numbers.
  • Go to this URL http://www.nasm.us/doc/nasmdoc3.html, and locate Section 3.4.1. Look at the instructions and the different ways Nasm accepts literals.
  • Nasm accepts numbers in decimal, hex, binary, octal, and 2's complements.
  • Let's try a few:
  • Edit your test_skel.asm program and add the following lines between the dashed lines:


		mov	eax, 0x0000FFFF
		mov	ebx, 00000000111111110000000011111111b
		mov	ecx, 1111_1111_1111_1111_1111_1111_1111_1111b
		call	_printRegs


  • Assemble, Link and run. You should see eax, ebx, and ecx, as hex, unsigned, and signed (2's complement) integers.


A Different Way to Redirect stdout


  • If you use > at the end of a command, and add the name of a file at the end, the output of your command will be stored in the file. If the file already existed, it will be erased first, and overwritten.
Example
 du /etc | sort -n |  tail -10  > largest.txt
 cat largest.txt

Notice that this generates the list of the largest files found etc and stores this list in largest.txt
Try this now:
du /usr/games/* | sort -n | tail -10  > largest.txt
cat largest.txt

See that the file largest.txt has been overwritten.


BlackCat.png

Break time: you will notice that Linux has a game directory! This is typical of Linux systems. There are always a few games hidden somewhere on a Linux computer. Ours has only a few. Some linux distributions come with a larger number of them. Let's spend 2 minutes playing: try this:

 
 cowsay Hello there
 cowsay csc231 is not for sissies


Now try this command (a for-loop which you will learn today):

 
 for i in hello there cs231a Student ; do cowsay $i ; done




  • Break over.
  • What if instead of erasing the contents of largest.txt every time we wanted to keep adding to its end, i.e. appending text to it?
  • The redirection symbol for that is >>
du /etc | sort -n |  tail -10  > largest.txt
du /usr/games/* | sort -n | tail -10  >> largest.txt
cat largest.txt

The first du command will create a new largest.txt and the second du command will append to it.
  • In general you want to use > once, for the first command, and >> several times for all the information you need to append to the output file.


Bash Loops


Bash supports loops! It is a powerful way of repeating commands.

  • Try this at the Bash prompt:


 for i in 1 2 3 4 5 6 7 8 9 10 ; do
      echo "i = $i"
 done

  • Explanations:
  • i is used as the index of the loop. It is declared by putting it right after the for keyword.
  • i will take all the values in whatever list is given after the in keyword.
  • the semi-colon ends the declaration, and is followed by do
  • the next lines will be repeated for every value i will take. In our case, just the echo command, which is Bash's print command.
  • we close the body of the for-loop with done


Note that when you want to use the loop variable inside the body of the loop, you write $i. Variables are declared without $ but are prefixed with $ when used.


Several Different Kinds of Loops


  • Try these different variations of loops. They contain new features and constructs, and you will figure out how they work by playing with them.


Loop 2


for i in `seq 1 10` ; do
    echo "i is $i"
done
  • Note: you need to use backquotes around the seq 1 10 command. With Bash, putting backquotes around a string means that it is a command that should be executed, and the output of this command becomes a list of lines through which the for command will iterate.


Loop 3


for i in a b c d e f g h i j ; do
    echo "i = $i"
done

for j in {a..j} ; do
    echo "j = $j"
done


Loop 4


for i in `seq 1 10` ; do echo "i is $i" ;  done


  • Loops can be written on one line only. The semi-colon marks the end of commands. Make sure you put spaces around the semi-colons!



Challenge #1:

QuestionMark1.jpg


Use the man page for seq and figure out a way to make your loop print all the numbers from 20 down to 1.






Loop 5 -- Nested for-loops!


for i in a b c d e f ; do  
    for j in 0 1 2 3 4 5 ; do   
       echo -n "$i$j "  
    done  
    echo ""  
done


  • The "-n" switch for the first echo indicates that the cursor should not go to the next line after printing the string.
  • The echo "" is a way to go to the next line.




Challenge #2:

QuestionMark2.jpg


Use a nested for-loop to print this pattern of 10 lines with 1 to 10 stars:

*
**
***
****
*****
******
*******
********
*********
**********



Challenge #3:

QuestionMark3.jpg


Use a nested for-loop to print all the cs231a-xx accounts:

cs231a-aa
cs231a-ab
cs231a-ac
...
cs231a-az
cs231a-ba
cs231a-bb
cs231a-bc
...
cs231a-bz

Note: this is the kind of loop that is used to create the 231b accounts in the spring. Instead of printing the string "cs231a-xx", our Linux admin, Suzanne, uses the adduser cs231a-xx command which adds a new user to the system.


Loop 6 -- Looping through files


You can loop through files by using "*", or "*.asm", or some combination of a string and the "*" character(s) to generate a list of files and iterate through them. Try the following examples:
for i in *.asm ; do 
    echo "file = $i"  
done

for i in *hello* ; do 
    echo "file = $i"  
done

for i in *.java ; do 
    echo "file = $i"  
done



More Complex Looping


Assume that you want to create a text file that contains all your assembly program, with the name of the program between two dashed lines, followed by the contents of the program. This is how you could do this:


  • First let's make the output of the command go to the display, so that we can see the output:


for i in *.asm ; do
         echo "-------------------------------------------"
         echo "$i"
         echo "-------------------------------------------"
         cat $i
         echo ""
done

  • Try it!
  • Now let's redirect the output of all the commands to a file we'll call allAsmFiles.txt
for i in *.asm ; do
         echo "-------------------------------------------" >> allAsmFiles.txt
         echo "$i" >> allAsmFiles.txt
         echo "-------------------------------------------" >> allAsmFiles.txt
         cat $i >> allAsmFiles.txt
         echo "" >> allAsmFiles.txt
done


  • Try this as well, and look at allAsmFiles.txt with emacs or less. See how quickly you created this? This can be used to generate quick Jupyter or RStudio notebooks, with the correct header information, for those of you using these packages.




Challenge #4:

QuestionMark4.jpg


  • Get a copy of NQueens.java with the getcopy command.
  • Compile it with javac
javac NQueens.java

  • Run it:
java NQueens 8

  • The program attempts to put 8 queens on an 8x8 chessboard such that they do not take each other. When it is done, the program prints the time it took for finding the first solution.
  • You can see how the program would put 9 queens on a 9x9 chessboard by running this command:
java NQueens 9

  • Run the program with the "-q" switch, which will instruct it to be "quiet" and not display the board as it is searching for a solution. It will only display the elapsed time:
java NQueens 8 -q

  • Figure out a way, using bash loops, to record the amount of time the program takes to solve the problem for 8x8, 9x9, 10x10, ...30x30 chessboards.
  • Here's an example of the output wanted:
8 0.269894 ms
9 0.143371 ms
10 0.262931 ms
11 0.177008 ms
12 0.614035 ms
13 0.306408 ms
14 24.345706 ms
15 13.638184 ms
16 41.753702 ms
17 32.20283 ms
18 103.648104 ms
19 25.896647 ms
20 143.685347 ms
21 35.919331 ms
22 602.401496 ms
23 99.678514 ms
24 229.824076 ms
25 106.852737 ms
26 229.789283 ms
27 256.951499 ms
28 1184.52835 ms
29 666.942186 ms
30 21909.152261 ms





Moodle Quizzes


  • You are ready to take the Moodle quiz for today's lab!


Additional Information on Bash Loops


In case you want to learn more about loops, there are many interesting tutorials on the Web. I'm listing here a few of them:





























Solutions


(The solutions will be available at 11:45 a.m., on 10/13/17)
<showafterdate after="20171013 11:45" before="20171231 00:00">

Challenge 1

for i in `seq 10 -1 1` ; do echo "i is $i"; done

Challenge 2

for i in `seq 10` ; do
for j in `seq $i` ; do
echo -n "*"
done
echo ""
done

Challenge 3

for i in a b ; do 
for j in a b c d e f g h i j k l m n o p q r s t u v w x y z ; do 
echo "231b-$i$j"
done
done

Challenge 4

for i in `seq 8 30` ; do echo -n "$i "; java NQueens $i -q; done

</showafterdate>



































 ___________________
< That's all folks! >
 -------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||