Difference between revisions of "CSC231 Homework 4 2014"
(→Helper Program 2) |
|||
(22 intermediate revisions by the same user not shown) | |||
Line 26: | Line 26: | ||
'''N''' represents the total number of words in the string '''msg'''. | '''N''' represents the total number of words in the string '''msg'''. | ||
− | Your assignment is to write a program that uses one or several loops that go ''N'' times and that print all the words on separate lines, one after the other, such that each word is '''capitalized''', i.e. its first letter is uppercase, and the others are lowercase. | + | Your assignment is to write a program, called '''Hw4_1.asm''', that uses one or several loops that go ''N'' times and that print all the words on separate lines, one after the other, such that each word is '''capitalized''', i.e. its first letter is uppercase, and the others are lowercase. |
+ | If you observe the ASCII table, the difference between upper- and lower-case letters is always the same: 32. So, if you have an uppercase character in '''al''' and want to make it lowercase, you can do this: | ||
<br /> | <br /> | ||
+ | <source lang="asm"> | ||
+ | sub al, 32 | ||
+ | </source> | ||
+ | <br /> | ||
+ | Better yet, you can write this instruction in a much more self-documenting fashion: | ||
+ | <br /> | ||
+ | <source lang="asm"> | ||
+ | sub al, 'a'-'A' | ||
+ | </source> | ||
+ | <br /> | ||
+ | In this case you ask nasm to figure out the difference between lower and uppercase letters, and subtract that difference from al. If al contained 'f', for example, then, after the sub instruction, it will contain 'F'. | ||
+ | <br /> | ||
+ | Feel free to use the 231Lib.asm library for printing strings. | ||
+ | <br /> | ||
+ | |||
==Submission== | ==Submission== | ||
<br /> | <br /> | ||
Submit your program in Moodle's '''Homework 4, Problem 1''' section. | Submit your program in Moodle's '''Homework 4, Problem 1''' section. | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
+ | <br /> | ||
<br /> | <br /> | ||
Line 55: | Line 75: | ||
<br /> | <br /> | ||
* You do not have to document each instruction. Only those that are important, or where having some additional details would help. | * You do not have to document each instruction. Only those that are important, or where having some additional details would help. | ||
− | * Make sure you use variables that have self-documenting names. ''x'', ''a'', for example, do not carry much information. But ''message'', ''char'', ''index'' are better. | + | * Make sure you use variables that have self-documenting names. ''x'', ''a'', for example, do not carry much information. But ''message'', ''char'', or ''index'' are much better. |
<br /> | <br /> | ||
==Submission== | ==Submission== | ||
<br /> | <br /> | ||
You need to submit your fully documented program to a different section of Moodle. Your program will not be run or evaluated automatically. Instead I will download it from Moodle later, so that I can read it, annotate it, and comment on your programming style. You won't be able to run or evaluate this problem with Moodle. | You need to submit your fully documented program to a different section of Moodle. Your program will not be run or evaluated automatically. Instead I will download it from Moodle later, so that I can read it, annotate it, and comment on your programming style. You won't be able to run or evaluate this problem with Moodle. | ||
+ | <br /> | ||
+ | |||
+ | <br /> | ||
+ | <br /> | ||
<br /> | <br /> | ||
=Problem #3= | =Problem #3= | ||
<br /> | <br /> | ||
− | Take your solution program (or my solution program) for [[CSC231_Homework_3_2014#Problem_.235| Homework 3, Problem 5]], and rewrite it | + | Take your solution program (or my solution program) for [[CSC231_Homework_3_2014#Problem_.235| Homework 3, Problem 5]], and rewrite it (call it '''Hw4_3.asm'''), and this time make it use functions. |
<br /> | <br /> | ||
Your solution program should have several functions: | Your solution program should have several functions: | ||
Line 69: | Line 93: | ||
* One function called '''printLn''' that prints a new-line character (0x0a). It will replace our ''_println'' function. Your function must use '''int 0x80''' to print the 0x0a char. Your function '''should not''' call _println! ''printLn'' does not receive any parameter through registers, and must save all the registers it uses. In other words, when we return from printLn, all the registers will contain the same values they had before we called the function. | * One function called '''printLn''' that prints a new-line character (0x0a). It will replace our ''_println'' function. Your function must use '''int 0x80''' to print the 0x0a char. Your function '''should not''' call _println! ''printLn'' does not receive any parameter through registers, and must save all the registers it uses. In other words, when we return from printLn, all the registers will contain the same values they had before we called the function. | ||
* One function called '''printMsg''' that prints a string on the screen. ''printMsg'' will replace our ''_printString'' function. Your function must use '''int 0x80''' to print the string. It will get the address of the string to print in ''ecx'' and the number of characters in the string in ''edx''. This function should '''not''' call ''_printString''. It must use the ''int 0x80'' instruction. | * One function called '''printMsg''' that prints a string on the screen. ''printMsg'' will replace our ''_printString'' function. Your function must use '''int 0x80''' to print the string. It will get the address of the string to print in ''ecx'' and the number of characters in the string in ''edx''. This function should '''not''' call ''_printString''. It must use the ''int 0x80'' instruction. | ||
− | * One function called '''printFibMsg''' that gets a number in eax and prints the string ''Fibonacci(###)'' where ''###'' is the decimal value of the number in eax. You should call '''_printDec''' inside ''printFibMsg'' to print the number passed in eax. | + | * One function called '''printFibMsg''' that gets a number in eax and prints the string ''Fibonacci(###) = '' where ''###'' is the decimal value of the number in eax. You should call '''_printDec''' inside ''printFibMsg'' to print the number passed in eax. |
Your ''printFibMsg'' function should save all the registers it modifies and should return them to their original values. | Your ''printFibMsg'' function should save all the registers it modifies and should return them to their original values. | ||
+ | <br /> | ||
+ | ==Restrictions== | ||
+ | <br /> | ||
+ | * You can only use the _printDec library function in your program. No other function from the 231Lib.asm library should be used. | ||
<br /> | <br /> | ||
==Submission== | ==Submission== | ||
Line 76: | Line 104: | ||
Submit your program to the '''Homework 4 Problem 3''' section in Moodle. | Submit your program to the '''Homework 4 Problem 3''' section in Moodle. | ||
<br /> | <br /> | ||
+ | |||
<br /> | <br /> | ||
<br /> | <br /> | ||
Line 81: | Line 110: | ||
<br /> | <br /> | ||
<br /> | <br /> | ||
+ | |||
+ | =Problem #4= | ||
<br /> | <br /> | ||
+ | Your assignment is to write a program in assembly that contains functions, one of which will display the contents of eax in hexadecimal. This function will be called repeatedly from a test program, and given dwords through eax. Your function will print the contents of eax in hexadecimal. | ||
+ | |||
+ | In order to get you started, you are given two helper programs. '''Program 1''' shows you how to take a 4-bit value (i.e. a number between 0 and 15 decimal) and transform it into a character representing its hexadecimal equivalent. For example, 4 decimal, which is also 0x04, will get converted to the ASCII character '4'. 8, which is also 0x08, will be converted to '8', and 10, which is 0x0A, will be converted to the character 'A'. | ||
+ | |||
+ | '''Program 2''' shows you how to '''shift''' the bits inside a register. We haven't covered shifts yet, but they are relatively easy to get. They are covered in [http://cs.smith.edu/~dthiebaut/ArtOfAssembly/CH06/CH06-3.html#HEADING3-1 Randy Hyde's e-text] as well. | ||
+ | |||
<br /> | <br /> | ||
+ | ==Helper Program 1== | ||
<br /> | <br /> | ||
+ | <source lang="asm"> | ||
+ | ;;; ; hw4Prep.asm | ||
+ | ;;; ; D. Thiebaut | ||
+ | ;;; ; | ||
+ | ;;; ; Takes a 4-bit value in al and find the ASCII char that represents | ||
+ | ;;; ; the hex digit associated with this value. | ||
+ | ;;; ; | ||
+ | ;;; ; to assemble and run: | ||
+ | ;;; ; | ||
+ | ;;; ; nasm -f elf -F stabs hw4Prep.asm | ||
+ | ;;; ; ld -melf_i386 -o hw4Prep hw4Prep.o | ||
+ | ;;; ; ./hw4Prep | ||
+ | ;;; ; ------------------------------------------------------------------- | ||
+ | |||
+ | |||
+ | |||
+ | ;;; ------------------------------------------------------------ | ||
+ | ;;; data areas | ||
+ | ;;; ------------------------------------------------------------ | ||
+ | |||
+ | section .data | ||
+ | |||
+ | bin2hex db "0123456789ABCDEF" | ||
+ | ;table of all the hex characters from 0 to F | ||
+ | |||
+ | counter db 0 ;counter incremented from 0 to 15 | ||
+ | |||
+ | ;;; ------------------------------------------------------------ | ||
+ | ;;; code area | ||
+ | ;;; ------------------------------------------------------------ | ||
+ | |||
+ | section .text | ||
+ | global _start | ||
+ | |||
+ | ;;; ------------------------------------------------------------ | ||
+ | ;;; printChar: prints the character in al. Does not modify any | ||
+ | ;;; of the registers. | ||
+ | ;;; ------------------------------------------------------------ | ||
+ | printChar: | ||
+ | section .data | ||
+ | char db 0 ;temporary string holding char to print | ||
+ | |||
+ | section .text | ||
+ | push eax ;save data regs | ||
+ | push ebx | ||
+ | push ecx | ||
+ | push edx | ||
+ | |||
+ | mov byte[char],al | ||
+ | ;save char in string | ||
+ | |||
+ | mov ecx, char ;print string using int 0x80 | ||
+ | mov edx, 1 | ||
+ | mov eax, 4 | ||
+ | mov ebx, 1 | ||
+ | int 0x80 | ||
+ | |||
+ | pop edx ;restore data regs | ||
+ | pop ecx | ||
+ | pop ebx | ||
+ | pop eax | ||
+ | ret | ||
+ | |||
+ | ;;; ------------------------------------------------------------ | ||
+ | ;;; main program. | ||
+ | ;;; ------------------------------------------------------------ | ||
+ | _start: | ||
+ | mov ecx, 16 | ||
+ | |||
+ | for: mov ebx, bin2hex ;make ebx point to array of char | ||
+ | |||
+ | mov edx, 0 ;put counter into edx | ||
+ | mov dl, byte[counter] | ||
+ | |||
+ | mov al, byte[ebx+edx] ;get char at index edx from table | ||
+ | call printChar ;print it | ||
+ | mov al, 0x0a ;print new line | ||
+ | call printChar | ||
+ | |||
+ | inc byte[counter] ;get next index value in array | ||
+ | loop for ;keep on looping 16 times | ||
+ | |||
+ | ;;; exit() | ||
+ | |||
+ | mov eax,1 | ||
+ | mov ebx,0 | ||
+ | int 0x80 ; final system call | ||
+ | </source> | ||
<br /> | <br /> | ||
+ | |||
+ | ==Helper Program 2== | ||
<br /> | <br /> | ||
+ | <source lang="asm"> | ||
+ | ;;; ; hw4Prep2.asm | ||
+ | ;;; ; D. Thiebaut | ||
+ | ;;; ; | ||
+ | ;;; ; Puts 0x89 in al, then prints '9' and '8' on the screen. | ||
+ | ;;; ; These happen to be the characters representing the hex | ||
+ | ;;; ; digits of the number. Replace 0x89 but another 2-digit | ||
+ | ;;; ; hex value, and see the digits printed on the screen. | ||
+ | ;;; ; | ||
+ | ;;; ; to assemble and run: | ||
+ | ;;; ; | ||
+ | ;;; ; nasm -f elf -F stabs hw4Prep2.asm | ||
+ | ;;; ; ld -melf_i386 -o hw4Prep2 hw4Prep2.o | ||
+ | ;;; ; ./hw4Prep2 | ||
+ | ;;; ; ------------------------------------------------------------------- | ||
+ | |||
+ | extern _printDec | ||
+ | extern _println | ||
+ | |||
+ | ;;; ------------------------------------------------------------ | ||
+ | ;;; code area | ||
+ | ;;; ------------------------------------------------------------ | ||
+ | |||
+ | section .text | ||
+ | global _start | ||
+ | |||
+ | _start: mov eax, 0 ;clear full register first | ||
+ | mov al,0x89 ;set lower part to 0x89: 1000 1001 | ||
+ | push eax ;save eax for later. | ||
+ | |||
+ | and eax,0x0F ;clear all bits except last 4 | ||
+ | call _printDec ;print digit (will print 9) | ||
+ | |||
+ | pop eax ;get eax back | ||
+ | |||
+ | shr eax,4 ;shift eax right 4 bits | ||
+ | ;now eax contains 8 | ||
+ | call _printDec ;print digit (will print 8) | ||
+ | |||
+ | call _println | ||
+ | ;;; exit() | ||
+ | |||
+ | mov eax,1 | ||
+ | mov ebx,0 | ||
+ | int 0x80 ; final system call | ||
+ | |||
+ | </source> | ||
<br /> | <br /> | ||
+ | |||
+ | ==Putting It All Together== | ||
<br /> | <br /> | ||
+ | You will notice if you play with Helper Program 2 that it prints the hex digits of what you put in al correctly (in reverse order), except if the digits are letters. 0xAB, for example, is not printed as 'B' followed by 'A'. Instead you will see 11, followed by 10. | ||
+ | <br /> | ||
+ | But... if you combine Helper Program 1 with Helper Program 2, you should be able to. | ||
+ | <br /> | ||
+ | In a first step, combined both program so that 0xAB prints as 'B' followed by 'A'. | ||
+ | <br /> | ||
+ | When you are done, create a function that '''prints all 8 hexadecimal digits in eax, in the correct order'''. Call your function '''_printHex''', and make it '''global''' (the same way that you make the '''_start''' label global): | ||
+ | <br /> | ||
+ | <source lang="asm"> | ||
+ | global _start | ||
+ | global _printHex | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | This way, I will be able to link your program with my test program, which will call your function and pass it different values in eax. | ||
+ | <br /> | ||
+ | ==Requirements== | ||
+ | <br /> | ||
+ | * Your program should be called Hw4_4.asm | ||
+ | * It should contain at least 1 global function called _printHex | ||
+ | * _printHex should print the 8 hex digits (even if they are 0s) corresponding to the 32-bit value in eax. | ||
+ | * _printHex should NOT modify any of the other registers | ||
+ | <br /> | ||
+ | ==Submission== | ||
+ | <br /> | ||
+ | * Submit '''Hw4_4.asm''' to the Moodle '''Homework 4 Program 4''' section. Your function will be tested with 3 numbers: | ||
+ | |||
+ | 00000000 | ||
+ | 12345678 | ||
+ | ABCDEF00 | ||
+ | |||
+ | <br /> | ||
+ | <br /><br /> | ||
+ | <br /><br /> | ||
+ | <br /><br /> | ||
+ | <br /><br /> | ||
+ | <br /><br /> | ||
+ | |||
[[Category:CSC231]][[Category:Homework]][[Category:Nasm]] | [[Category:CSC231]][[Category:Homework]][[Category:Nasm]] |
Latest revision as of 12:42, 29 October 2014
--D. Thiebaut (talk) 07:11, 21 October 2014 (EDT)
The assignment is due on 10/28/10 at 11:55 p.m.
Contents
Problem #1: Addressing modes and one-dimensional arrays
Assume that your data section is initialized with the following variables:
msg db 3,"ALL",11,"PROGRAMMERS",3,"ARE",11,"PLAYWRIGHTS"
db 3,"AND",3,"ALL",9,"COMPUTERS",3,"ARE",5,"LOUSY"
db 6,"ACTORS"
N equ 10
Note that the msg contains byte numbers followed by words. The byte number preceeding a word corresponds to the number of letters in the word. So '3,"ALL"' for example means that the word that follows 3 is a 3-character word. '11,"PROGRAMMERS"' means that the string following the byte that contains 11 is an 11-character word.
N represents the total number of words in the string msg.
Your assignment is to write a program, called Hw4_1.asm, that uses one or several loops that go N times and that print all the words on separate lines, one after the other, such that each word is capitalized, i.e. its first letter is uppercase, and the others are lowercase.
If you observe the ASCII table, the difference between upper- and lower-case letters is always the same: 32. So, if you have an uppercase character in al and want to make it lowercase, you can do this:
sub al, 32
Better yet, you can write this instruction in a much more self-documenting fashion:
sub al, 'a'-'A'
In this case you ask nasm to figure out the difference between lower and uppercase letters, and subtract that difference from al. If al contained 'f', for example, then, after the sub instruction, it will contain 'F'.
Feel free to use the 231Lib.asm library for printing strings.
Submission
Submit your program in Moodle's Homework 4, Problem 1 section.
Problem #2: Documentation and Style
Take your solution program for Problem 1, above, and document it fully. Use past solution programs as examples.
Your program should have:
- A header, containing the name of the program (its file name), the name of the author, a description of what it does (and possible bugs you may know it to contain, and how one should assemble, link, and run it
- Markers highlighting where the data section and code section are located
- Comments throughout the code indicating what the various blocks of instructions do. Do not hesitate to add blank lines in your code to separate logical blocks. Make sure your comments help understand how the computation progresses, rather than what the instruction is doing.
- For example, here is a bad way of documenting an instruction:
inc ebx ; increment ebx
- This is not very helpful because we are not learning anything more about what the code is doing. Instead, if eax is a pointer to a list of characters, a more useful comment would have been:
inc ebx ; move ebx to the next character in string
- You do not have to document each instruction. Only those that are important, or where having some additional details would help.
- Make sure you use variables that have self-documenting names. x, a, for example, do not carry much information. But message, char, or index are much better.
Submission
You need to submit your fully documented program to a different section of Moodle. Your program will not be run or evaluated automatically. Instead I will download it from Moodle later, so that I can read it, annotate it, and comment on your programming style. You won't be able to run or evaluate this problem with Moodle.
Problem #3
Take your solution program (or my solution program) for Homework 3, Problem 5, and rewrite it (call it Hw4_3.asm), and this time make it use functions.
Your solution program should have several functions:
- One function called printLn that prints a new-line character (0x0a). It will replace our _println function. Your function must use int 0x80 to print the 0x0a char. Your function should not call _println! printLn does not receive any parameter through registers, and must save all the registers it uses. In other words, when we return from printLn, all the registers will contain the same values they had before we called the function.
- One function called printMsg that prints a string on the screen. printMsg will replace our _printString function. Your function must use int 0x80 to print the string. It will get the address of the string to print in ecx and the number of characters in the string in edx. This function should not call _printString. It must use the int 0x80 instruction.
- One function called printFibMsg that gets a number in eax and prints the string Fibonacci(###) = where ### is the decimal value of the number in eax. You should call _printDec inside printFibMsg to print the number passed in eax.
Your printFibMsg function should save all the registers it modifies and should return them to their original values.
Restrictions
- You can only use the _printDec library function in your program. No other function from the 231Lib.asm library should be used.
Submission
Submit your program to the Homework 4 Problem 3 section in Moodle.
Problem #4
Your assignment is to write a program in assembly that contains functions, one of which will display the contents of eax in hexadecimal. This function will be called repeatedly from a test program, and given dwords through eax. Your function will print the contents of eax in hexadecimal.
In order to get you started, you are given two helper programs. Program 1 shows you how to take a 4-bit value (i.e. a number between 0 and 15 decimal) and transform it into a character representing its hexadecimal equivalent. For example, 4 decimal, which is also 0x04, will get converted to the ASCII character '4'. 8, which is also 0x08, will be converted to '8', and 10, which is 0x0A, will be converted to the character 'A'.
Program 2 shows you how to shift the bits inside a register. We haven't covered shifts yet, but they are relatively easy to get. They are covered in Randy Hyde's e-text as well.
Helper Program 1
;;; ; hw4Prep.asm
;;; ; D. Thiebaut
;;; ;
;;; ; Takes a 4-bit value in al and find the ASCII char that represents
;;; ; the hex digit associated with this value.
;;; ;
;;; ; to assemble and run:
;;; ;
;;; ; nasm -f elf -F stabs hw4Prep.asm
;;; ; ld -melf_i386 -o hw4Prep hw4Prep.o
;;; ; ./hw4Prep
;;; ; -------------------------------------------------------------------
;;; ------------------------------------------------------------
;;; data areas
;;; ------------------------------------------------------------
section .data
bin2hex db "0123456789ABCDEF"
;table of all the hex characters from 0 to F
counter db 0 ;counter incremented from 0 to 15
;;; ------------------------------------------------------------
;;; code area
;;; ------------------------------------------------------------
section .text
global _start
;;; ------------------------------------------------------------
;;; printChar: prints the character in al. Does not modify any
;;; of the registers.
;;; ------------------------------------------------------------
printChar:
section .data
char db 0 ;temporary string holding char to print
section .text
push eax ;save data regs
push ebx
push ecx
push edx
mov byte[char],al
;save char in string
mov ecx, char ;print string using int 0x80
mov edx, 1
mov eax, 4
mov ebx, 1
int 0x80
pop edx ;restore data regs
pop ecx
pop ebx
pop eax
ret
;;; ------------------------------------------------------------
;;; main program.
;;; ------------------------------------------------------------
_start:
mov ecx, 16
for: mov ebx, bin2hex ;make ebx point to array of char
mov edx, 0 ;put counter into edx
mov dl, byte[counter]
mov al, byte[ebx+edx] ;get char at index edx from table
call printChar ;print it
mov al, 0x0a ;print new line
call printChar
inc byte[counter] ;get next index value in array
loop for ;keep on looping 16 times
;;; exit()
mov eax,1
mov ebx,0
int 0x80 ; final system call
Helper Program 2
;;; ; hw4Prep2.asm
;;; ; D. Thiebaut
;;; ;
;;; ; Puts 0x89 in al, then prints '9' and '8' on the screen.
;;; ; These happen to be the characters representing the hex
;;; ; digits of the number. Replace 0x89 but another 2-digit
;;; ; hex value, and see the digits printed on the screen.
;;; ;
;;; ; to assemble and run:
;;; ;
;;; ; nasm -f elf -F stabs hw4Prep2.asm
;;; ; ld -melf_i386 -o hw4Prep2 hw4Prep2.o
;;; ; ./hw4Prep2
;;; ; -------------------------------------------------------------------
extern _printDec
extern _println
;;; ------------------------------------------------------------
;;; code area
;;; ------------------------------------------------------------
section .text
global _start
_start: mov eax, 0 ;clear full register first
mov al,0x89 ;set lower part to 0x89: 1000 1001
push eax ;save eax for later.
and eax,0x0F ;clear all bits except last 4
call _printDec ;print digit (will print 9)
pop eax ;get eax back
shr eax,4 ;shift eax right 4 bits
;now eax contains 8
call _printDec ;print digit (will print 8)
call _println
;;; exit()
mov eax,1
mov ebx,0
int 0x80 ; final system call
Putting It All Together
You will notice if you play with Helper Program 2 that it prints the hex digits of what you put in al correctly (in reverse order), except if the digits are letters. 0xAB, for example, is not printed as 'B' followed by 'A'. Instead you will see 11, followed by 10.
But... if you combine Helper Program 1 with Helper Program 2, you should be able to.
In a first step, combined both program so that 0xAB prints as 'B' followed by 'A'.
When you are done, create a function that prints all 8 hexadecimal digits in eax, in the correct order. Call your function _printHex, and make it global (the same way that you make the _start label global):
global _start
global _printHex
This way, I will be able to link your program with my test program, which will call your function and pass it different values in eax.
Requirements
- Your program should be called Hw4_4.asm
- It should contain at least 1 global function called _printHex
- _printHex should print the 8 hex digits (even if they are 0s) corresponding to the 32-bit value in eax.
- _printHex should NOT modify any of the other registers
Submission
- Submit Hw4_4.asm to the Moodle Homework 4 Program 4 section. Your function will be tested with 3 numbers:
00000000 12345678 ABCDEF00