×
Samples Blogs Make Payment About Us Reviews 4.9/5 Order Now

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

July 01, 2024
Rehana Magnus
Rehana Magnus
🇨🇦 Canada
Assembly Language
Rehana Magnus, PhD in Computer Science from the esteemed Acadia Institute of Technology, Canada. With 6 years of experience, specializes in assembly language programming. Proficient in low-level coding, optimizing performance, and enhancing system functionality.
Key Topics
  • Instructions
  • Requirements and Specifications
Tip of the day
Use the REPL (Read-Eval-Print Loop) to test your code interactively, and practice writing concise, readable expressions to harness Scala’s powerful syntax effectively.
News
In 2024, JavaScript's Redux saw updates for efficient state management, and Tailwind CSS gained traction for responsive design. Meanwhile, C++ libraries like Boost.

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

Related Samples

Explore our Assembly Language Assignment samples, providing hands-on solutions to intricate programming challenges. Dive into optimized code snippets for x86 and ARM architectures, covering system calls, memory management, and algorithm implementations. Master Assembly Language with detailed explanations and ready-to-use examples, enhancing your proficiency in low-level programming.