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