CMSC313, Computer Organization & Assembly Language Programming, Spring 2013
Project 3: Print Decimal Subroutine
Due: Tuesday March 5, 2013 11:59pm
Objective
The objective of this programming project is for you to practice writing
an assembly language subroutine and to gain more experience with loop
control.
Assignment
For this assignment, you will write an assembly language subroutine that
prints out a 32-bit unsigned number to standard output. The 32-bit value
will be passed to your subroutine through the EAX register. Your
subroutine must preserve all registers (i.e., any registers that
you use must be saved on the stack and restored before you return). Your
subroutine should do nothing else (not even print a linefeed).
To determine the values of the base 10 digits in the decimal
representation of the number, you will use the division method (don't
use repeated subtraction). The DIV instruction will divide the 64-bit
value stored in EDX:EAX by the single 32-bit operand given. After the
DIV instruction is executed, the quotient is stored in the EAX register
and the remainder is stored in the EDX register. (See further
discussion of the DIV instruction in Implementation Notes below.)
Implement your subroutine in a separate file. The entry point of your
subroutine must be called prt_dec. The "main program" will
reside in a separate file. A sample main program is provided for you (main3.asm), but you must make your own
test program as well. Note: your test program must be in
a separate file, otherwise your subroutine will fail to compile with the
test program used for grading.
When you assemble your program, you must assemble each source file
separately:
linux2% nasm -f elf -g main3.asm
linux2% nasm -f elf -g prt_dec.asm
linux2% ld main3.o prt_dec.o
Then, you can run the a.out file produced as usual. A sample
run with the main3.asm file provided should look like:
linux2% ./a.out
0
4294967295
3413151
17
214123
2223187809
1555544444
2 plus 3 equals 5
7 plus 4 equals 3
Note: The graders will use a different main program to test your
subroutine. Your test program should fully exercise your subroutine and
check for cases that are not tested in main3.asm
Implementation Notes
-
New:
The main3.c program for Project 3
is also available for copying directly on the GL file system at:
/afs/umbc.edu/users/c/h/chang/pub/cs313/main3.asm
-
In the division method for converting a number to base 10, you will
get the one's place first (the least significant digit), then the
10's place, then the 100's place, ... This is in the opposite order that
the decimal number will be printed. The easiest way to handle this
situation is to prepare a string starting at a higher numbered
address and loop backwards storing each character at a lower numbered
address.
-
The number of characters that you will print will depend on the value
passed in the EAX register. You will need to determine or keep count
of the length of the decimal number to be printed.
-
If the value in the EAX register is 0, then your subroutine should
print out a single digit 0.
-
In order for code in other files to call your subroutine, you must
declare the prt_dec label to be global. (If the
label is not global, then only code from the same file can use that
label.)
Thus, you must include the following declaration in your
prt_dec.asm file:
global prt_dec
The global declarations are typically made just
after the SECTION .text declaration.
-
In your test main program, you must tell the NASM assembler that
the prt_dec label is from a different file. Otherwise,
it will only look for prt_dec in the current file (and
not find it). To tell NASM this, include the declaration:
extern prt_dec
The extern declarations are also typically made just
after the SECTION .text declaration.
-
There are a couple of quirks about the DIV instruction. First, since
the dividend is always EDX:EAX, it is not specified in the
instruction. For example, to divide EDX:EAX by EBX, we simply say:
div ebx
Another quirk is that the DIV instruction does not support
immediate operands. So, you cannot divide by 10 by saying:
div 10 ; this is WRONG
-
Since you are converting a 32-bit value into decimal, the dividend
always fits in the lower 32 bits. Thus, you must zero out the EDX
register before each DIV instruction.
-
We are always dividing by 10 in this program. So, we know that the
remainder in EDX will always be less than 10. This value fits in 8
bits, which is quite rather convenient. Why?
-
Remember that the bytes that you are printing to the screen will
be interpreted as ASCII values.
Turning in your program
Use the UNIX submit command on the GL system to turn in your project. You
should submit three files: 1) the assembly language program and 2) the
typescript file of sample runs of your program. The class name for submit
is cs313. The name of the assignment name is proj3.
The UNIX command to do this should look something like:
submit cs313 proj3 prt_dec.asm mytest3.asm typescript
Last Modified:
22 Jul 2024 11:28:17 EDT
by
Richard Chang
to Spring 2013 CMSC 313 Homepage