Exercises 14.7 Programming Exercises
1.
Write a program in assembly language that asks the user to enter an unsigned integer, adds \(1\) to the number, and displays the result.
The writeStr
, readLn
, newLine
, uDecToInt
, and uIntToDec
functions have been provided earlier in the book. Here is the main
function to solve this problem.
@ incrementDec.s @ Prompts user for unsigned decimal number and adds 1 to it. @ 2017-09-29: Bob Plantz @ Define my Raspberry Pi .cpu cortex-a53 .fpu neon-fp-armv8 .syntax unified @ modern syntax @ Constants for assembler .equ maxChars,11 @ max input chars .equ inputString,-16 @ for input string .equ outputString,-28 @ for output string .equ locals,32 @ space for local vars @ Constant program data .section .rodata .align 2 prompt: .asciz "Enter an unsigned number up to 4294967294: " @ 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 sub sp, sp, locals @ for local vars ldr r0, promptAddr @ prompt user bl writeStr add r0, fp, inputString @ place for user input mov r1, maxChars @ limit input size bl readLn add r0, fp, inputString @ user input bl uDecToInt @ convert it add r1, r0, 1 @ increment user's number add r0, fp, outputString bl uIntToDec add r0, fp, outputString bl writeStr bl newLine mov r0, 0 @ return 0; add sp, sp, locals @ deallocate local var ldr fp, [sp, 0] @ restore caller fp ldr lr, [sp, 4] @ lr add sp, sp, 8 @ and sp bx lr @ return promptAddr: .word prompt
2.
Modify the uIntToDec
function (Listing 14.6.1) that you used in Exercise 14.7.1 to use the mls
instruction for computing the remainder.
@ uIntToDecMls.s @ Converts an int to the corresponding unsigned @ decimal text string. @ Calling sequence: @ r0 <- address of place to store string @ r1 <- int to convert @ bl uIntToDec @ 2017-09-29: Bob Plantz @ 2017-09-30: Use mls for remainder comp - Bob Plantz @ Define my Raspberry Pi .cpu cortex-a53 .fpu neon-fp-armv8 .syntax unified @ modern syntax @ Constant for assembler .equ tempString,-40 @ for temp string .equ locals,16 @ space for local vars .equ zero,0x30 @ ascii 0 .equ NUL,0 @ The program .text .align 2 .global uIntToDec .type uIntToDec, %function uIntToDec: sub sp, sp, 24 @ space for saving regs str r4, [sp, 0] @ save r4 str r5, [sp, 4] @ r5 str r6, [sp, 8] @ r6 str r7, [sp, 12] @ r7 str fp, [sp, 16] @ fp str lr, [sp, 20] @ lr add fp, sp, 20 @ set our frame pointer sub sp, sp, locals @ for local vars mov r4, r0 @ caller's string pointer add r5, fp, tempString @ temp string mov r7, 10 @ decimal constant mov r0, NUL @ end of C string strb r0, [r5] add r5, r5, 1 @ move to char storage mov r0, zero @ assume the int is 0 strb r0, [r5] movs r6, r1 @ int to convert beq copyLoop @ zero is special case convertLoop: cmp r6, 0 @ end of int? beq copy @ yes, copy for caller udiv r0, r6, r7 @ no, div to get quotient mls r2, r0, r7, r6 @ the mod (remainder) mov r6, r0 @ the quotient orr r2, r2, zero @ convert to numeral strb r2, [r5] add r5, r5, 1 @ next char position b convertLoop copy: sub r5, r5, 1 @ last char stored locally copyLoop: ldrb r0, [r5] @ get local char strb r0, [r4] @ store the char for caller cmp r0, NUL @ end of local string? beq allDone @ yes, we're done add r4, r4, 1 @ no, next caller location sub r5, r5, 1 @ next local char b copyLoop allDone: strb r0, [r4] @ end C string add sp, sp, locals @ deallocate local var ldr r4, [sp, 0] @ restore r4 ldr r5, [sp, 4] @ r5 ldr r6, [sp, 8] @ r6 ldr r7, [sp, 12] @ r7 ldr fp, [sp, 16] @ fp ldr lr, [sp, 20] @ lr add sp, sp, 24 @ sp bx lr @ return
3.
Write a program in assembly language that asks the user to enter a signed integer, adds \(1\) to the number, and displays the result.
This would be a good point to write two functions that will also be useful in subsequent chapters. One, getDecInt
will read a signed decimal integer from the keyboard and convert it into int
format. The other, putDecInt
will convert an int
into the signed decimal text string that represents it and write it on the screen. An important software engineering guideline is to reuse code, so you should use your readLn
, writeStr
, uDecToInt
, and uIntToDec
functions to implement getDecInt
and putDecInt
.
@ incrementSigned.s @ Prompts user for signed decimal number and adds 1 to it. @ 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 prompt: .asciz "Enter a signed integer between -2147483648 and +2147483646: " @ 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, promptAddr @ prompt user bl writeStr bl getDecInt @ convert it add r0, r0, 1 @ increment user's number bl putDecInt @ print result bl newLine 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 promptAddr: .word prompt
@ getDecInt.s @ Gets signed decimal integer from keyboard. @ Calling sequence: @ bl getDecInt @ returns equivalent int @ 2017-09-29: Bob Plantz @ Define my Raspberry Pi .cpu cortex-a53 .fpu neon-fp-armv8 .syntax unified @ modern syntax @ Constants for assembler .equ maxChars,12 @ max input chars .equ inputString,-20 @ for input string .equ locals,8 @ space for local vars @ Useful source code constants .equ POS,0 .equ NEG,1 @ The program .text .align 2 .global getDecInt .type getDecInt, %function getDecInt: 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 sub sp, sp, locals @ for the string add r0, fp, inputString @ place to store input mov r1, maxChars @ limit input length bl readLn add r0, fp, inputString @ input string mov r4, POS @ assume postive int ldrb r1, [r0] @ get char cmp r1, '- @ minus sign? bne checkPlus @ no, check for plus sign mov r4, NEG @ yes, flag as neg add r0, r0, 1 @ go to the number b convert @ and convert it checkPlus: cmp r1, '+ @ plus sign? bne convert @ no, we're at the number add r0, r0, 1 @ go to the number convert: bl uDecToInt cmp r4, POS @ positive int? beq allDone @ yes, we're done mvn r0, r0 @ no, complement it add r0, r0, 1 @ and finish negate allDone: add sp, sp, locals @ deallocate local var ldr r4, [sp, 4] @ restore r4 ldr fp, [sp, 8] @ fp ldr lr, [sp, 12] @ lr add sp, sp, 16 @ sp bx lr @ return
@ putDecInt.s @ Converts an int to the corresponding signed @ decimal text string. @ Calling sequence: @ r0 <- int to print @ bl putDecInt @ 2017-09-29: Bob Plantz @ Define my Raspberry Pi .cpu cortex-a53 .fpu neon-fp-armv8 .syntax unified @ modern syntax @ Constants for assembler .equ decString,-20 @ for string .equ locals,8 @ space for local varsbr @ Useful source code constants .equ POS,0 .equ NEGBIT,0x80000000 @ The program .text .align 2 .global putDecInt .type putDecInt, %function putDecInt: 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 sub sp, sp, locals @ space for the string add r4, fp, decString @ place to store string mov r1, '+ @ assume positive strb r1, [r4] tst r0, NEGBIT @ negative int? beq positive @ no, go on mov r1, '- @ yes, need to negate strb r1, [r4] mvn r0, r0 @ complement add r0, r0, 1 @ two's complement positive: mov r1, r0 @ int to convert add r0, r4, 1 @ skip over sign char bl uIntToDec add r0, fp, decString @ string to write bl writeStr add sp, sp, locals @ deallocate local var ldr r4, [sp, 4] @ restore r4 ldr fp, [sp, 8] @ fp ldr lr, [sp, 12] @ lr add sp, sp, 16 @ sp bx lr @ return