Program in Assembly Language, Code Generating Random Numbers
In this assignment, students have to make use of a starter code and string library in order to generate a new program. The program is required to produce and display a series of ten random numbers. In this project random numbers are to be generated in a range of 0 to 9.
SOLUTION : –
/* Frank Emanuel
* String Library
*
* This library of String (byte array) functions allows the user
* to easily work with strings in assembler. Each function is
* described in its own comment block.
*
*/
@ Declarations of functions in library
.equ STDOUT, 1 @ set a constant for the standard output
.equ STDIN, 0 @ set a constant for the standard input
.global _strLen @ returns the length of an array in bytes
.global _strCat @ concatonates two bchar arrays
.global _strUpper @ replaces all lowercase letters with uncials
.global _sPrint @ prints a string onto the STDOUT
.global _sInput @ takes in a string from the STDIN flushing buffer
/* String Length Function
*
* This function takes the address of a null terminated array of bytes
* in register 1 and returns the number of characters in the array in
* register 2.
*
*/
_strLen:
MOV r2, #0 @ start the element counter at 0
findEnd:
LDRB r0, [r1], #1 @ r1 contains the address of the byte to
@ load into r0, increment the address in r1
ADD r2, r2, #1 @ increment the byte counter
CMP r0, #0 @ set the status register by comparing the
@ value in r0 with null (#0)
BNE findEnd @ if r0 is not null continue looping
SUB r2, r2, #1 @ fix that we counted the null character
MOV pc, lr @ restore control to calling code
/* String to Upper Case Function
*
* Takes the addresses of a null terminated string and converts any
* lower case letters to their uncial (upper case) equivalent.
*
*/
_strUpper:
LDRB r0, [r1] @ load the next byte of array 1
CMP r0, #97 @ compare byte to ‘a’
BLT writeChar @ preserve non-lowercase letter
CMP r0, #122 @ compare to ‘z’
SUBLE r0, r0, #32 @ change to uppercase
writeChar:
STRB r0, [r1], #1 @ if not end of array 1 store value
CMP r0, #0 @ look for end of string
BNE _strUpper @ loop until end of string
MOV pc, lr @ return to calling environment
/* String Printer
*
* Takes the address of a null terminated string array and outputs
* that string to STDOUT (console). String address in register 1
*
*/
_sPrint:
MOV r0, #STDOUT @ set the output to the console
PUSH {r0-r1, lr} @ save the working registers and LR
BL _strLen @ set register 2 to string length
POP {r0-r1, lr} @ restore working registers and LR
MOV r7, #4 @ set the syscall to WRITE
SWI 0 @ make the syscall
MOV pc, lr @ return to calling environment
/* String Inputer
*
* Takes the address for a string in register 1 and the number of
* characters to read in register 2. Makes the syscall to READ from
* STDIN and then flushes any remaining characters from the buffer.
*
*/
_sInput:
PUSH {r1-r2, lr} @ preserve values for function
MOV r0, #STDIN @ set the input to the console
MOV r7, #3 @ set the syscall to READ
SWI 0 @ make the syscall
POP {r1-r2, lr} @ restore values sent to function
sInputStrStart:
CMP r2, #0 @ memory bounds checker
MOVLE r0, #0 @ if no more characters put null in R1
STRLEB r0, [r1] @ if no more characters store null in array
BLE sInputEnd @ if no more characters exit
LDRB r0, [r1] @ load in the next byte of sent array
CMP r0, #10 @ check for newline character
MOVEQ r0, #0 @ if end put null charater in R1
STRB r0, [r1], #1 @ write byte out at end of array 1
SUB r2, r2, #1 @ decrement letter counter
BNE sInputStrStart @ loop until newline
sInputEnd:
MOV pc, lr @ return to calling environment
/* Frank Emanuel
* Random Number Generator
*
* In order to generate a random number we need a seed value.
* Traditionally this seed value comes from the clock. This creates
* a pseudo-random number which is usually good enough for our
* programming examples.
*
*/
.equ RNDBOUNDS, 10 @ we want to generate numbers from 0 to 9
.global _start
_start:
LDR r1, =message @ place the address string in r1
BL _sPrint @ use library function to display string
MOV r5, #10 @ I want to loop 10 times.
mainloop:
CMP r5, #0 @ condition check for while loop
BEQ _end @ loop until r5 is 0
SUB r5, r5, #1 @ decrement loop condition
/* Step 1 fetch the time from the processor
*
* Syscall #78 will take an address of memory large enough to hold
* the
*/
MOV r7, #78 @ gettimeofday syscall (#78) returns time_t
LDR r0, =time @ address of holder for time_t
MOV r1, #0 @ put a null in tz field (time zone not needed)
SWI #0
/* Step 2 convert to a number within the range
*
* The number of milliseconds will easily fill a long integer. The
* formula for converting from a number to a range is to use the
* modulus when dividing our number by the target range.
*
* Seed Value MOD 10 = number between 0 and 10 (the remainder).
*
* In ARM you do not usually have a division operator and even when you
* do it simply discards the modulus (or remainder).
*
*/
@ YOUR CODE GOES HERE
LDR r1, =time @ address of holder for time_t
LDR r1,[r1, #4] @ load second byte from time_t
@ calculate division by repeated subtraction
divloop:
CMP r1, #10 @ if the number is less than 10
BLT endloop @ we have completed the division, end loop
SUB r1, r1, #10 @ if not, subtract 10 from it
BAL divloop @ repeat the loop
endloop:
/* Step 3 Convert the number (decimal value) into an ASCII number
*
* If we try to print out the number with a WRITE call, we will get
* strange results. WRITE prints out an array of ASCII characters. So
* we must convert the number to print it out.
*
*/
@ YOUR CODE GOES HERE
ADD r0, r1, #48 @ convert remainder to ascii
LDR r1, =number @ set r1 to address of comma
STRB r0, [r1] @ save digit in number
BL _sPrint @ print digit
/* Step 4 Print out a comma if needed, note that this portion needs r5
* so if you modify r5 elsewhere in the code you will have problems here.
*
*/
CMP r5, #0 @ is comma needed? (r5 set at top of loop)
LDRNE r1, =comma @ set r1 to address of comma
BLNE _sPrint @ print comma if needed
B mainloop
_end:
LDR r1, =period @ at end add period
BL _sPrint @ print final period
MOV r7, #1 @ set EXIT syscall
SWI 0 @ execute syscall
.data
message: .asciz “The following are randomly generated numbers.\n”
number: .asciz “#” @ you will write the ASCII value here
comma: .asciz “, ”
period: .asciz “.\n”
time: .space 8 @ enough space to accomodate time_t
.align