+1 480 409 0818 
Table Of Contents
  • Morse Code in Assembly Language 

Morse Code in Assembly Language 

In this sample assembly language solution, our tutor is demonstrating the creation of Morse Code. Here, students are required to make use of STDIN (Standard Input) data stream which is assigned to the keyboard of the computer. Data is retrieved from STDIN buffer using the read syscall. Here data is used from STDIN to convert Characters and Numbers into Morse Code.

SOLUTION : –

.global _start

_start: @ we should cycle back to the start until

@ the user tells us they are done

LDR r1, =prompt @ place the address string in r1

BL _sPrint @ use library function to display string

/* Step 1 read stream into memory

*

* Get input from the user using the _sInput function then

* print a newline before displaying morse code of input.

*/

LDR r1, =userInput @ point to the space allocated for input

MOV r2, #40 @ set the limit of character to read

BL _sInput @ get the input

LDR r1, =newline @ move to the next line (make it pretty)

BL _sPrint @ print a ‘\n’

/* Step 2 prepare the input for parsing

*

* Our morse code generator will ignore all characters except letters,

* numbers, and punctuation (which simply prints a newline).

* To make our job easier we will convert all letters to capitals.

*

* Additionally we will check if the user entered a “/q” to indicate

* they would like to quit the program.

*

* NOTE: Comment the following code to demonstrat that you understand it.

*

*/

LDR r1, =userInput @ point to the input string

BL _strUpper @ convert input string to uppercase

LDR r1, =userInput @ point to input string

LDRB r0, [r1], #1 @ load first character from input, advance pointer

CMP r0, #92 @ see if the first character is a slash ‘\’

BNE morseCoder @ if not, go to morse coder

LDRB r0, [r1] @ else, load second character from input string

CMP r0, #81 @ see if the second character is a ‘Q’

BEQ _end @ if the string was \Q, end the program

/* Step 3 stream parser

*

* This code examines each character in our prepared input stream

* and does the following:

* – prints letters as morse code using a lookup table

* – prints numbers as morse code using a lookup table

* – prints periods and commas as newline characters

* – prints a space for a space character

* – ignores all other characters.

*

* NOTE: You will write the parsing engine here. It needs to move through the

* user input and perform the above actions.

*

*/

morseCoder:

LDR r1, =userInput @ load in the address of user input

@ Your code goes here!

processChar:

LDRB r0, [r1], #1 @ load a character from the string

CMP r0, #0 @ see if we reached the end of string

BEQ endOfInput @ if end of string, end input

PUSH {r1} @ save r1 in the stack

CMP r0, #46 @ see if it’s a period

BEQ printNL @ if period, print newline

CMP r0, #44 @ see if it’s a comma

BEQ printNL @ if comma, print newline

CMP r0, #32 @ see if it’s a space

BEQ printSpace @ if space, print spaces

CMP r0, #65 @ see if it’s above or equal to letter ‘A’

BLT testDigit @ if not a letter, test if it’s a digit

CMP r0, #90 @ see if it’s below or equal to letter ‘Z’

BGT nextChar @ if not a letter, skip to next char

printLetter:

SUB r0, r0, #65 @ convert ascii ‘A’ to ‘Z’ to a numeric value 0 to 25

MOV r1, #6 @ load number 6 in r1 for multiplication

MUL r0, r1, r0 @ mulyiply value*6

LDR r1, =letters @ point ot start of letter table

ADD r1, r1, r0 @ add value*6 to point to letter entry in table

BL _sPrint @ print morse conversion

BAL nextChar @ repeat to process next character

testDigit:

CMP r0, #48 @ see if it’s above or equal to digit ‘0’

BLT nextChar @ if not a digit, skip to next char

CMP r0, #57 @ see if it’s below or equal to digit ‘9’

BGT nextChar @ if not a digit, skip to next char

printDigit:

SUB r0, r0, #48 @ convert ascii ‘0’ to ‘9’ to a numeric value

MOV r1, #7 @ load number 7 in r1 for multiplication

MUL r0, r1, r0 @ mulyiply value*7

LDR r1, =numbers @ point ot start of number table

ADD r1, r1, r0 @ add value*7 to point to digit entry in table

BL _sPrint @ print morse conversion

BAL nextChar @ repeat to process next character

printNL:

LDR r1, =newline @ point to string to print

BL _sPrint @ print a ‘\n’

BAL nextChar @ repeat to process next character

printSpace:

LDR r1, =space @ point to string to print

BL _sPrint @ print a series of spaces

nextChar:

POP {r1} @ restore value of r1

BAL processChar @ repeat to process next character

endOfInput:

LDR r1, =newline @ move to the next line (make it pretty)

BL _sPrint @ print a ‘\n’

BAL _start @ do not end the program unless user types \q

_end:

MOV r7, #1 @ set EXIT syscall

SWI 0 @ execute syscall

.data

prompt: .asciz “Please enter text to translate\nMC> ”

newline: .asciz “\n”

space: .asciz ” ”

userInput: .space 44

.align

@ Note that the following are aligned so that each letter takes up

@ exactly six bytes, therefore letters+6bytes gives us the second letter

@ and so on.

letters: .ascii “.- ” @ A

.byte 0x00, 0x00, 0x00

.ascii “-… ” @ B

.byte 0x00

.ascii “-.-. ” @ C

.byte 0x00

.ascii “-.. ” @ D

.byte 0x00, 0x00

.ascii “. ” @ E

.byte 0x00, 0x00, 0x00, 0x00

.ascii “..-. ” @ F

.byte 0x00

.ascii “–. ” @ G

.byte 0x00, 0x00

.ascii “…. ” @ H

.byte 0x00

.ascii “.. ” @ I

.byte 0x00, 0x00, 0x00

.ascii “.— ” @ J

.byte 0x00

.ascii “-.- ” @ K

.byte 0x00, 0x00

.ascii “.-.. ” @ L

.byte 0x00

.ascii “– ” @ M

.byte 0x00, 0x00, 0x00

.ascii “-. ” @ N

.byte 0x00, 0x00, 0x00

.ascii “— ” @ O

.byte 0x00, 0x00

.ascii “.–. ” @ P

.byte 0x00

.ascii “–.- ” @ Q

.byte 0x00

.ascii “.-. ” @ R

.byte 0x00, 0x00

.ascii “… ” @ S

.byte 0x00, 0x00

.ascii “- ” @ T

.byte 0x00, 0x00, 0x00, 0x00

.ascii “..- ” @ U

.byte 0x00, 0x00

.ascii “…- ” @ V

.byte 0x00

.ascii “.– ” @ W

.byte 0x00, 0x00

.ascii “-..- ” @ X

.byte 0x00

.ascii “-.– ” @ Y

.byte 0x00

.asciz “–.. ” @ Z

.align

@ Note that the following data is for numbers (0-9) and you can choose

@ to use the data as is or simply produce the numbers on the fly

@ using the relationship between the number and the dots and dashes.

@ Also note that in ASCII the 0 comes first, in morse code 0 is last.

@ How do you account for this?

@

numbers: .asciz “—– “, “.—- “, “..— “, “…– “, “….- ”

.asciz “….. “, “-…. “, “–… “, “—.. “, “—-. ”

@ 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