CSC231 Bash Tutorial 5
--D. Thiebaut (talk) 08:04, 3 March 2017 (EST)
Contents
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 to 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
- Its code is shown below for completeness:
;;; Testing sandbox 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: ;------------------------------------------------- ;;; exit ------------------------------------------------- mov ebx, 0 mov eax, 1 int 0x80
- It has everything needed to test how short pieces of code work.
- Put the following code between the dashed lines:
mov edx, 0 mov eax, dword[a] div dword[b] call _printRegs
- (If the lines are already there, but commented out, just remove the semi-colons.)
- See what the program does. What quantity will be divided by what other quantity.
- 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? Does it make sense?
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 fill in the middle part, assemble, link and run, and you will have your answer.
Hex, Binary, and 2's Complement
- You can use the same method for testing number representations.
- 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.
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 `seq 1 10` ; do echo "i is $i" 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: |
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: |
Use a nested for-loop to print this pattern of 10 lines with 1 to 10 stars:
* ** *** **** ***** ****** ******* ******** ********* **********
- Loop 6 -- Looping through files
- You can loop through files by using "*", or "*.asm", or some combination of string and "*" character 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.
Solutions
<showafterdate after="20170303 11:45" before="20170601 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
</showafterdate>