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