+1 (315) 557-6473 

Program to Create A Simplified Version Of PrintF In ARM Assembly Language Assignment Solution.


Instructions

Objective
Write a simplified version of PrintF in ARM assembly language.

Requirements and Specifications

For this exercise, you are to write an ARM assembly program that implements a heavily simplifiedversion of the printf function found in the C standard library. Your program will take as input (inspecific registers, your program must use the registers listed for input), the address of a format string to print out (in R1), and the address of a sequence of values (in R2) to interpolate into it.
As with C’s printf(), the format string is composed of zero or more directives: ordinary characters (not ‘%’), which are printed out unchanged; and conversions specifications, which begin with a ‘%’ character. For each conversion specifier encountered in the string, rather than print out the conversion specifier (%s, %d, etc.), your program should instead printout a value of the type specified (string, integer, and so on). These values are specified as a sequence of 32-bit words in memory, with the address of the first value being given to your program in the register, R2.
Some hints for completing this exercise:
  • The address of the format string is specified in R1, the address of the values is specified in R2 — if you use other registers, you program will fail in the pipeline. Likewise, you must not add in code before the label printf in the skeleton file, 01-printf.s, or your program will not execute correctly. You may however (and probably should) modify the format strings and sequence of values to ensure your program works correctly with different input.
  •  Your program will need to loop through every character of the format string, and print out thecharacters (using SWI 0), unless the character is a percent (‘%’) character.
  • Your program should stop looping when it reaches a null character in the format string, (i.e. when the byte read from memory has the literal value of zero (not the ASCII code for the character representing the digit zero). You can find this by comparing with #0.
  • The format string is made up of characters that are one byte long, you will need to use LDRB toaccess these. The values are all 32-bits (four bytes) long, you will need to use LDR to access these.
  • If your program encounters a conversion specifier, (i.e. you read a ‘%’ character from the format string), then your program should fetch the next byte of the format string from memory. Then based on the value of this character, your program should:
  • If the conversion specifier is %%, then your program should print out a single percent character. The value of R2 should not be updated.
  • If the conversion specifier is %c, then your program should read the 32-bit value from the address currently specified in R2. Your program should treat the value read as an ASCII character and print it out using SWI 0. The value of R2 should be updated to contain the address of the next value in the sequence.
  • If the conversion specifier is %d, then your program should read the 32-bit value from the address currently specified in R2. Your program should treat the value read as an unsignedinteger value and print it out using SWI 4. The value of R2 should be updated to contain the address of the next value in the sequence.
  • If the conversion specifier is %s, then your program should read the 32-bit value from the address currently specified in R2. Your program should treat the value read as containing the address of a null-terminated string and print it out using SWI 3. The value of R2 should be updated to contain the address of the next value in the sequence.
  • Invalid conversion specifiers should print nothing out.
  • Bear in mind that each value in the sequence of values is 4 bytes long.
  • It can be instructive to consider this program as being formed from two parts. One part of the program is stepping through each character of the format string deciding what needs to be printed (the character, or a value — and for each value, what type of value). The other part of the program is fetching the value from the sequence of values and printing it out based on the type specified in the string. I’d suggest working on the two parts of the program separately, first get the program stepping through the format string printing out dummy values, then when you are confident that part is working, move onto writing the code to read the actual values from memory.
Screenshots of output
simplified version of PrintF in ARM assembly language

simplified version of PrintF in ARM assembly language 1
Source Code
Printf.s
 B main
tstfmt DEFB "%s%c%c\nNumbers: %d %d\n100%% Bad %zformats %ynot printed\n", 0
tststr DEFB "This is a test string",0
 ALIGN
seq DEFW tststr,'!','!',1,2
main LDR R1, =tstfmt ; format
 LDR R2, =seq ; sequence
printf MOV R3, #0 ; current sequence index
prloop LDRB R0, [R1] ; load character from format string
 CMP R0, #0 ; if end of string
 BEQ prend ; end print
 CMP R0, #'%' ; if not a format specifier
 BNE prchar ; print the character
 ADD R1, R1, #1 ; else, advance to next character in format string
 LDRB R0, [R1] ; load next character from format string
 CMP R0, #0 ; if end of string
 BEQ prend ; end print
 CMP R0, #'%' ; if double percent
 BEQ prchar ; print single percent char
 CMP R0, #'c' ; if %c
 BEQ charfmt ; print using char format
 CMP R0, #'d' ; if %d
 BEQ intfmt ; print using int format
 CMP R0, #'s' ; if %s
 BEQ strfmt ; print using string format
 B prnext ; else, print nothing
charfmt LDR R0, [R2] ; load value from sequence
 ADD R2, R2, #4 ; advance to next position in sequence
 B prchar ; print character
intfmt LDR R0, [R2] ; load value from sequence
 ADD R2, R2, #4 ; advance to next position in sequence
 SWI 4 ; print integer
 B prnext ; advance to next char in format
strfmt LDR R0, [R2] ; load value from sequence
 ADD R2, R2, #4 ; advance to next position in sequence
 SWI 3 ; print string
 B prnext ; advance to next char in format
prchar SWI 0 ; print a character
prnext ADD R1, R1, #1 ; advance to next character in format string
 B prloop ; repeat loop
prend SWI 2
Breaker.h
 B main
width DEFW 20 ; max line width
buffer DEFS 100 ; word buffer
 ALIGN
main LDR R1, =width ; load width in R1
 LDR R1, [R1]
 LDR R2, =buffer ; load buffer address in R2
 MOV R3, #0 ; current buffer length
 MOV R4, #0 ; current line length
rdloop SWI 1 ; read character
 CMP R0, #'#' ; if hash
 BEQ quit ; terminate program
 CMP R0, #' ' ; if space
 BEQ prbuff ; print buffer
 CMP R0, #10 ; if newline
 BEQ prbuff ; print buffer
 STRB R0, [R2, R3] ; else, save char in buffer
 ADD R3, R3, #1 ; increment buffer length
 B rdloop ; read next char
prbuff MOV R5, R0 ; save space or newline char
 CMP R3, #0 ; if there's no info in buffer
 BEQ prnline ; go to print newline if needed
prnxt MOV R0, #0 ; save zero in buffer
 STRB R0, [R2, R3] ; to mark end of string
 ADD R0, R3, R4 ; add length of line plus word
 ADD R0, R0, #1 ; add space
 CMP R0, R1 ; compare with max width
 BLE prword ; if <= width, print the word
 MOV R0, #10 ; else, print a newline before the word
 SWI 0
 MOV R4, #0 ; clear length of line
prword CMP R4, #0 ; if it's the first word
 BEQ prskip ; don't print starting space
 MOV R0, #' ' ; print a space before the word
 SWI 0
 ADD R4, R4, #1 ; increment line length
prskip LDR R0, =buffer ; print the buffer
 SWI 3
 ADD R4, R4, R3 ; add word length to line length
 MOV R3, #0 ; reset word length
prnline CMP R5, #10 ; if input was not a newline
 BNE rdloop ; read next char
 MOV R0, #10 ; else, print a newline
 SWI 0
 MOV R4, #0 ; clear length of line
 B rdloop ; read next char
quit SWI 2