Exercises 13.3 Programming Exercises
The functions from Exercise 13.3.2 and Exercise 13.3.4 will be used for other exercises in subsequent chapters.
1.
Enter the C program in Listing 13.2.1. Using the “-S” compiler option, compile it with differing levels of optimization, i.e., “-O1,” “-O2,” “-O3,” and discuss the assembly language that is generated. Compare the results with my solution in Listing 13.2.6. Is the optimized code easier or more difficult to read?
I suggest discussing this with your instructor and colleagues. Opinions will differ. Listen and learn.
2.
Write the function, writeStr, in assembly language. The function takes one argument, a char *, which is a pointer to a C-style text string. It displays the text string on the screen. It returns the number of characters displayed.
Demonstrate that your function works correctly by writing a main function that calls writeStr to display “Hello world” on the screen. Your main function can ignore the character count that is returned by writeStr.
@ writeStr.s
@ Writes a C-style text string to the standard output (screen).
@ Calling sequence:
@ r0 <- address of string to be written
@ bl writestr
@ returns number of characters written
@ 2017-09-29: Bob Plantz
@ Define my Raspberry Pi
.cpu cortex-a53
.fpu neon-fp-armv8
.syntax unified @ modern syntax
@ Useful source code constants
.equ STDOUT,1
.equ NUL,0
@ The code
.text
.align 2
.global writeStr
.type writeStr, %function
writeStr:
sub sp, sp, 16 @ space for saving regs
str r4, [sp, 0] @ save r4
str r5, [sp, 4] @ r5
str fp, [sp, 8] @ fp
str lr, [sp, 12] @ lr
add fp, sp, 12 @ set our frame pointer
mov r4, r0 @ r4 = string pointer
mov r5, 0 @ r5 = count
whileLoop:
ldrb r3, [r4] @ get a char
cmp r3, NUL @ end of string?
beq allDone @ yes, all done
mov r0, STDOUT @ no, write to screen
mov r1, r4 @ address of current char
mov r2, 1 @ write 1 byte
bl write
add r4, r4, 1 @ increment pointer var
add r5, r5, 1 @ count++
b whileLoop @ back to top
allDone:
mov r0, r5 @ return count;
ldr r4, [sp, 0] @ restore r4
ldr r5, [sp, 4] @ r5
ldr fp, [sp, 8] @ fp
ldr lr, [sp, 12] @ lr
add sp, sp, 16 @ restore sp
bx lr @ return
@ helloWorld3.s
@ Hello world program to test writeStr function
@ 2017-09-29: Bob Plantz
@ Define my Raspberry Pi
.cpu cortex-a53
.fpu neon-fp-armv8
.syntax unified @ modern syntax
@ Constant program data
.section .rodata
.align 2
theString:
.asciz "Hello World.\n"
@ The program
.text
.align 2
.global main
.type main, %function
main:
sub sp, sp, 8 @ space for fp, lr
str fp, [sp, 0] @ save fp
str lr, [sp, 4] @ and lr
add fp, sp, 4 @ set our frame pointer
ldr r0, theStringAddr
bl writeStr
mov r0, 0 @ return 0;
ldr fp, [sp, 0] @ restore caller fp
ldr lr, [sp, 4] @ lr
add sp, sp, 8 @ and sp
bx lr @ return
theStringAddr:
.word theString
3.
Write the function, readLn, in assembly language. The function takes one argument, a char *, which is a pointer to a char array, for storing a text string. It reads characters from the keyboard and stores them in the array as a C-style text string. It does not store the ‘\n’ character. It returns the number of characters, excluding the NUL character, that were stored in the array.
Demonstrate that your function works correctly by writing a main function that prompts the user to enter a text string and then echoes the user's input, using the writeStr function from Exercise 13.3.2. When testing your program, be careful not to enter more characters than the allocated space. Explain what would occur if you did enter too many characters. Your main function can ignore the character count that is returned by writeStr and readLn.
Use malloc to allocate memory for storing the user's text string. You can read how to use it by typing man malloc in your terminal window.
@ readLnSimple.s
@ Reads a line (through the '\n') from standard input. Deletes
@ the '\n' and creates a C-style text string.
@ Calling sequence:
@ r0 <- address of place to store string
@ bl readLn
@ returns number of characters read, excluding NUL.
@ 2017-09-29: Bob Plantz
@ Define my Raspberry Pi
.cpu cortex-a53
.fpu neon-fp-armv8
.syntax unified @ modern syntax
@ Useful source code constants
.equ STDIN,0
.equ NUL,0
.equ LF,10 @ '\n' under Linux
@ The code
.text
.align 2
.global readLn
.type readLn, %function
readLn:
sub sp, sp, 16 @ space for saving regs
str r4, [sp, 4] @ save r4
str r5, [sp, 8] @ r5
str fp, [sp, 12] @ fp
str lr, [sp, 16] @ lr
add fp, sp, 12 @ set our frame pointer
mov r4, r0 @ r4 = string pointer
mov r5, 0 @ r5 = count
mov r0, STDIN @ read from keyboard
mov r1, r4 @ address of current storage
mov r2, 1 @ read 1 byte
bl read
whileLoop:
ldrb r3, [r4] @ get just read char
cmp r3, LF @ end of input?
beq endOfString @ yes, input done
add r4, r4, 1 @ no, increment pointer var
add r5, r5, 1 @ count++
mov r0, STDIN @ read from keyboard
mov r1, r4 @ address of current storage
mov r2, #1 @ read 1 byte
bl read
b whileLoop @ and check for end
endOfString:
mov r0, NUL @ string terminator
strb r0, [r4] @ write over '\n'
mov r0, r5 @ return count;
ldr r4, [sp, 4] @ restore r4
ldr r5, [sp, 8] @ r5
ldr fp, [sp, 12] @ fp
ldr lr, [sp, 16] @ lr
add sp, sp, 16 @ space for saving regs
bx lr @ return
@ echoString1.s
@ Prompts user to enter a string, then echoes it.
@ 2017-09-29: Bob Plantz
@ Define my Raspberry Pi
.cpu cortex-a53
.fpu neon-fp-armv8
.syntax unified @ modern syntax
@ Constant for assembler
.equ nBytes,50 @ amount of memory for string
@ Constant program data
.section .rodata
.align 2
prompt:
.asciz "Enter some text: "
@ The program
.text
.align 2
.global main
.type main, %function
main:
sub sp, sp, 16 @ space for saving regs
@ (keeping 8-byte sp align)
str r4, [sp, 4] @ save r4
str fp, [sp, 8] @ fp
str lr, [sp, 12] @ lr
add fp, sp, 12 @ set our frame pointer
mov r0, nBytes @ get memory from heap
bl malloc
mov r4, r0 @ pointer to new memory
ldr r0, promptAddr @ prompt user
bl writeStr
mov r0, r4 @ get user input
bl readLn
mov r0, r4 @ echo user input
bl writeStr
mov r0, r4 @ free heap memory
bl free
mov r0, 0 @ return 0;
ldr r4, [sp, 4] @ restore r4
ldr fp, [sp, 8] @ fp
ldr lr, [sp, 12] @ lr
add sp, sp, 16 @ sp
bx lr @ return
promptAddr:
.word prompt
4.
Modify the readLn function in Exercise 13.3.3 so that it takes a second argument, the maximum length of the text string, including the NUL character. Excess characters entered by the user are discarded.
Demonstrate that your function works correctly by writing a main function that prompts the user to enter a text string and then echoes the user's input, using the writeStr function from Exercise 13.3.2. When testing your program, be careful not to enter more characters than the allocated space. Your main function can ignore the character count that is returned by writeStr and readLn.
When testing the character limit of your readLn function, use a small number.
When testing if your character limit algorithm works in your readLn function, use the debugger. Set a breakpoint at your cmp instruction and single step to see which way the conditional branch goes.
@ readLn.s
@ Reads a line (through the '\n') from standard input. Has
@ a size limit. Extra characters and '\n' are ignored. Stores
@ NUL-terminated C string.
@ Calling sequence:
@ r0 <- address of place to store string
@ r1 <- string size limit
@ bl readLn
@ returns number of characters read, excluding NUL.
@ 2017-09-29: Bob Plantz
@ Define my Raspberry Pi
.cpu cortex-a53
.fpu neon-fp-armv8
.syntax unified @ modern syntax
@ Useful source code constants
.equ STDIN,0
.equ NUL,0
.equ LF,10 @ '\n' under Linux
@ The code
.text
.align 2
.global readLn
.type readLn, %function
readLn:
sub sp, sp, 24 @ space for saving regs
@ (keeping 8-byte sp align)
str r4, [sp, 4] @ save r4
str r5, [sp, 8] @ r5
str r6, [sp,12] @ r6
str fp, [sp, 16] @ fp
str lr, [sp, 20] @ lr
add fp, sp, 20 @ set our frame pointer
mov r4, r0 @ r4 = string pointer
mov r5, 0 @ r5 = count
mov r6, r1 @ r6 = max chars
sub r6, 1 @ for NUL
mov r0, STDIN @ read from keyboard
mov r1, r4 @ address of current storage
mov r2, 1 @ read 1 byte
bl read
whileLoop:
ldrb r3, [r4] @ get just read char
cmp r3, LF @ end of input?
beq endOfString @ yes, input done
cmp r5, r6 @ max chars?
bge ignore @ yes, ignore rest
add r4, r4, 1 @ no, increment pointer var
add r5, r5, 1 @ count++
ignore:
mov r0, STDIN @ read from keyboard
mov r1, r4 @ address of current storage
mov r2, 1 @ read 1 byte
bl read
b whileLoop @ and check for end
endOfString:
mov r0, NUL @ string terminator
strb r0, [r4] @ write over '\n'
mov r0, r5 @ return count;
ldr r4, [sp, 4] @ restore r4
ldr r5, [sp, 8] @ r5
ldr r6, [sp,12] @ r6
ldr fp, [sp, 16] @ fp
ldr lr, [sp, 20] @ lr
add sp, sp, 24 @ sp
bx lr @ return
@ echoString2.s
@ Prompts user to enter a string, then echoes it.
@ 2017-09-29: Bob Plantz
@ Define my Raspberry Pi
.cpu cortex-a53
.fpu neon-fp-armv8
.syntax unified @ modern syntax
@ Constant for assembler
.equ nBytes,5 @ amount of memory for string
@ Constant program data
.section .rodata
.align 2
prompt:
.asciz "Enter some text: "
@ The program
.text
.align 2
.global main
.type main, %function
main:
sub sp, sp, 16 @ space for saving regs
@ (keeping 8-byte sp align)
str r4, [sp, 4] @ save r4
str fp, [sp, 8] @ fp
str lr, [sp, 12] @ lr
add fp, sp, 12 @ set our frame pointer
mov r0, nBytes @ get memory from heap
bl malloc
mov r4, r0 @ pointer to new memory
ldr r0, promptAddr @ prompt user
bl writeStr
mov r0, r4 @ get user input
mov r1, nBytes @ limit input size
bl readLn
mov r0, r4 @ echo user input
bl writeStr
mov r0, r4 @ free heap memory
bl free
mov r0, 0 @ return 0;
ldr r4, [sp, 4] @ restore r4
ldr fp, [sp, 8] @ fp
ldr lr, [sp, 12] @ lr
add sp, sp, 16 @ sp
bx lr @ return
promptAddr:
.word prompt
5.
One problem with using writeStr in the solution to Exercise 13.3.4 is that it needs a newline after echoing the user's input string. Correct this problem. I do not recommend adding the newline character to the string before echoing it. See if you can solve the problem some other way.
There are multiple ways to solve this problem. I chose to write a separate function, newLine to give good flexibility in how I display text for users. It is a given that users will want you to change your program's display.
@ newLine.s
@ Writes a newline character to the standard output (screen).
@ Calling sequence:
@ bl newLine
@ 2017-09-29: Bob Plantz
@ Define my Raspberry Pi
.cpu cortex-a53
.fpu neon-fp-armv8
.syntax unified @ modern syntax
@ Useful source code constants
.equ STDOUT,1
@ Constant program data
.section .rodata
.align 2
theChar:
.ascii "\n"
@ The code
.text
.align 2
.global newLine
.type newLine, %function
newLine:
sub sp, sp, 8 @ space for fp, lr
str fp, [sp, 0] @ save fp
str lr, [sp, 4] @ and lr
add fp, sp, 4 @ set our frame pointer
mov r0, STDOUT @ write to screen
ldr r1, theCharAddr @ address of newline char
mov r2, 1 @ write 1 byte
bl write
mov r0, 0 @ return 0;
ldr fp, [sp, 0] @ restore caller fp
ldr lr, [sp, 4] @ lr
add sp, sp, 8 @ and sp
bx lr @ return
theCharAddr:
.word theChar
