Do not understand condition flags on ARM Cortex M4 - arm

I am having trouble understanding why certain xPRS condition flags are being set.
Here is the code (I have commented on the xPRS flag values):
MOVS R0, #0 ; n=0 z=1 c=0 v=0
MOVS R1, #1 ; n=0 z=0 c=0 v=0
MVNS R2, #0 ; n=1 z=0 c=0 v=0
MOVS R3, #0x80000000 ; n=1 z=0 c=1 v=0
MOVS R4, R0 ; n=0 z=1 c=1 v=0
MOVS R5, R1 ; n=0 z=0 c=1 v=0
MOVS R6, R2 ; n=0 z=1 c=1 v=0
The part I have problems understanding are from line 4 onwards (MOVS R3, #0x80000000).
The ARM user guide says that "When an Operand2 constant is used with the instructions MOVS, MVNS, ANDS, ORRS, ORNS, EORS, BICS, TEQ or TST, the carry flag is updated to bit[31] of the constant, if the constant is greater than 255 and can be produced by shifting an 8-bit value. These instructions do not affect the carry flag if Operand2 is any other constant."
This is fine, so the reason the C flag is on is due to 0x80000000 having bit[31] as a 1, which in turn sets the C flag to 1.
However I also have the N flag on, so I thought that bit[31] could also the sign, so maybe 0x80000000 is actually representing -0 ( bit[31] which is the sign being a 1, the rest 0's which is the number, but the Z flag is not on, so this cant be the case? so why is it N but not Z?
Thanks

Related

KEIL: The reason for working a MUL within a loop only in the 1st iteration

I have written a code in keil in which there is a loop containing a multiplication which can be done either by shift left by 1 or MUL command. However, both are executed only in the 1st iteration and in the next ones, compiler executes the code, while nothing happens.
Is there someone who knows the probable reason?
Thanks
Here is the code of the loop:
loop ADD r9, r9, #1
;MUL r8, r7, r11 ;double the X
LSL r12, r7, #1
CMP r12, r4 ;CMP the X with P
BHI G1
BLS G0
it was solved. it occured because this is a consecutive shift and it should be shifted by 1 at each iteration. the written code copies the source into destination and then, shift by 1. So it is not modified after the 1st iteration. the solution is modifying r7 by LSL r7, #1. This is shifted r7 by 1 position at all iterations.

LC-3 Decimal to Binary Converter

I have to create a program that converts the given user input (decimal) into its binary match when the user presses enter or exit when they press X. Can anyone give a pointer on how to start this assignment. We are required to use masks and loops, but I do not know where to start with this.
I wrote this because there aren't a whole lot of examples of binary masks.
A binary mask is useful in assembly because it gives us the power to examine a single bit in a decimal or hex value.
Example:
If we look at the decimal number 5 we know its binary value is 0101, when we AND R4, R4, R5 on our first loop we compare 1000 with 0101. Since bit[3] is a zero in 0101 we then tell the LC3 simulator to print out an ASCII char "0". We then repeat the process with the next binary mask 0100.
This can be a tricky concept to get at first so I would first look at a few examples of loops and bit masks.
LC3 Bit Counter
How do I write a program that prints out “Hello World”, 5 times using a loop in LC3?
.ORIG x3000
LEA R0, PROMPT
PUTs ; TRAP x22
LD R0, ENTER
OUT ; TRAP x21
IN ; TRAP x23
AND R5, R5, #0 ; clear R5
ADD R5, R5, R0 ; Store the user input into R5
AND R1, R1, #0 ; clear R1, R1 is our loop count
LD R2, MASK_COUNT ; load our mask limit into R2
NOT R2, R2 ; Invert the bits in R2
ADD R2, R2, #1 ; because of 2's compliment we have
; to add 1 to R2 to get -4
WHILE_LOOP
ADD R3, R1, R2 ; Adding R1, and R2 to see if they'll
; will equal zero
BRz LOOP_END ; If R1+R2=0 then we've looped 4
; times and need to exit
LEA R3, BINARY ; load the first memory location
; in our binary mask array
ADD R3, R3, R1 ; use R1 as our array index and
; add that to the first array location
LDR R4, R3, #0 ; load the next binary mask into R4
AND R4, R4, R5 ; AND the user input with the
; binary mask
BRz NO_BIT
LD R0, ASCII_ONE
OUT ; TRAP x21
ADD R1, R1, #1 ; add one to our loop counter
BRnzp WHILE_LOOP ; loop again
NO_BIT
LD R0, ASCII_ZERO
OUT ; TRAP x21
ADD R1, R1, #1 ; add one to our loop counter
BRnzp WHILE_LOOP ; loop again
LOOP_END
LD R0, ENTER
OUT ; TRAP x21
HALT ; TRAP x25
; Binary Maps
BINARY .FILL b0000000000001000
.FILL b0000000000000100
.FILL b0000000000000010
.FILL b0000000000000001
.FILL b0000000000000000
; Stored Values
ENTER .FILL x000A
ASCII_ZERO .FILL x0030
ASCII_ONE .FILL x0031
MASK_COUNT .FILL x04 ; loop limit = 4
PROMPT .STRINGZ "Enter a number from 0-9"
.END

ARM Division by 10 Save remainder and quotient

This is a question on homework from CS2400 MSU Denver
Hello,
I have a program that reads keys from the user until they have either entered a non HEX character or entered a max of 8 HEX characters. As keys are entered I maintain a sum of hex values being entered by the user by multiplying the sum register by 16 and adding the new hex value.
This part is all fine and dandy, no help needed. I am having trouble taking this final result, in HEX, and converting it to DEC. I know I need to divide by 10 only I don't know how I can accomplish this.
Please help me determine how to divide by 10 and save the quotient and remainder. Thanks.
AREA HW6, CODE
ENTRY
Divsor EQU 10
MAIN
MOV R1, #0 ; Clear register to be used as symbols received counter
MOV R2, #0 ; Clear register to be used as temp result
LDR R4, =DecStr ; Load address of DecStr
LDR R5, =TwosComp ; Load address of TwosComp
LDR R6, =RvsDecStr
BL READ_CHARS ; Read characters from the keyboard
BL TO_DECIMAL ; Is R2 negative ?
SWI 0x11
READ_CHARS
CMP R1, #8 ; Check if necessary to read another key
BEQ DONE_READ_CHAR ; User has entered 8 hex symbols
SWI 4 ; [R0] <--- Key from keyboard (ASCII)
CMP R0, #'0' ; Verify digit is valid
BLO DONE_READ_CHARS
CMP R0, #'9' ; Verify digit is valid
BHI CHECK_HEX
SUB R0, R0, #'0' ; Obtain Hex equivalent of ASCII char 0-9
B STORE_INPUT
CHECK_HEX
CMP R0, #'A'
BLO DONE_READ_CHARS ; Invalid Hex symbol
CMP R0, #'F'
BHI DONE_READ_CHARS ; Invalid Hex symbol
SUB R0, R0, #'A'
ADD R0, R0, #0xA ; Adding ten to receive Hex equivalent of ASCII A-F
STORE_INPUT
MOV R3, R2, LSL#4 ; *16
ADD R2, R3, R0 ; Add valid Hex symbol to temp result
ADD R1, R1, #1 ; Increase symbol's recieved counter
B READ_CHARS ; Get next key
DONE_READ_CHARS
MOV PC, LR ; Return to BL READ_CHARS ( MAIN )
TO_DECIMAL
TST R2, #2, 2
BEQ POSITIVE
STRB #'-', [R4], #1 ; Store - as first byte in DecStr
MVN R2, R2 ; [R2] <- 1's complement of R2
ADD R2, R2, #1 ; [R2] <- 2's complement of R2
POSITVE
STR R2, [R5] ; Store all entered hex values in memory at TwosComp
LDR R7, [R5] ; Initial quotient
udiv10
LDRB R7, [R5], #1 ; Load a byte of TwosComp
CMP R7, #0
BEQ DONE_TO_DECIMAL
DONE_TO_DECIMAL
MOV PC, LR
AREA data1, DATA
TwosComp
DCD 0
DecStr % 12
RvsDecStr
% 11
ALLIGN
END
You can do it by subtracting-and-shift like elementary division easily. There are also many division algorithms on this site and Google
How does one do integer (signed or unsigned) division on ARM?
Assembly mod algorithm on processor with no division operator
But if you only want to convert from hexadecimal to decimal then double dabble may fit your need. It converts number to packed BCD without any division

MOVS with LSL Carry Flag

I'm learning The Arm System Developers Guide and I am wondering about one of the examples in the book:
cpsr = nzcvqiFt_USER // capital indicates flag is set
r0 = 0x00000000
r1 = 0x80000004
MOVS r0, r1, LSL #1
cpsr = nzCvqiFt_USER // capital indicates flag is set
r0 = 0x00000008
r1 = 0x80000004
I understand that the 8 is carried over and the C flag is set due to this carry based on the logical shift left. Why is the 4 in r1 not shifted as well? Is the MOVS operation only moving the carried 8?
Because your result ends up in r0.
So, what happens is:
carry = r1[31] = 1
r0 = r1 << 1
Thats why r0 becomes 0x00000008 because the MSB of r1 got shifted out to the carry and the third bit (2^3=4) got shifted to the fourth bit (2^4=8).

ARM Assembly for development board

I'm currently messing around with an LPC 2378 which has an application board attached. On the fan there are several components, 2 of which are a fan and a heater.
If bits 6 and 7 of port 4 are connected to the fan (motor controller), the following code will turn on the fan:
FanOn
STMFD r13!,{r0,r5,r14} ; Push r0, r5 and LR
LDR R5, =FIO4PIN ; Address of FIO4PIN
LDR r0, [r5] ; Read current Port4
ORR r0, r0, #0x80
STR r0, [r5] ; Output
LDMFD r13!,{r0,r5,r14} ; Pop r0, r5 and LR
mov pc, r14 ; Put link register back into PC
How can I rewrite this block of code to turn on a heater connected to bit 5 of port 4, (Setting the bit to 1 will turn it on, setting it to 0 will turn it off).
Edit after answered question:
;==============================================================================
; Turn Heater On
;==============================================================================
heaterOn
STMFD r13!,{r0,r5,r14} ; Push r0, r5 and LR
LDR R5, =FIO4PIN ; Address of FIO4PIN
LDR r0, [r5] ; Read current Port4
ORR r0, r0, #0x20
STR r0, [r5] ; Output
LDMFD r13!,{r0,r5,r14} ; Pop r0, r5 and LR
mov pc, r14 ; Put link register back into PC
;==============================================================================
; Turn The Heater Off
;==============================================================================
heaterOff
STMFD r13!,{r0,r5,r14} ; Push r0, r5 and LR
LDR R5, =FIO4PIN ; Address of FIO4PIN
LDR r0, [r5] ; Read current Port4
AND r0, r0, #0xDF
STR r0, [r5] ; Output
LDMFD r13!,{r0,r5,r14} ; Pop r0, r5 and LR
mov pc, r14 ; Put link register back into PC
As best as I understand the code, the fan is connected only to bit 7 (if bits are numerated from 0).
The following line is responsible for turning the fan-bit on:
ORR r0, r0, #0x80
You are setting all the bits that are 1 in the "mask" to 1. Since the mask is 0x80, that is 1000 0000 in binary, it only turns on bit 7.
Now, if you need to turn on the heater instead of the fan, and you have to set bit 5 instead of 7 (on the same port), you only need to change the mask in that line. New mask should be 0010 0000 binary, that is 0x20 in hexa, so the new code should be:
ORR r0, r0, #0x20
Also, if you want to turn the heater off at some point later, you do it by unsetting only bit 5, by anding with a mask that has 1s everywhere except on bit 5. If the mnemonic for bitwise and is BIC, the line would be:
BIC r0, r0, 0xDF
Now, I have not done any assembly in months but if I am not very mistaken, the code snippet you gave is actually a subroutine. You would call it from you main functionality with something like call to the FanOn address. And, to me, it seems that the subroutine is nice in a way that it preserves all the registers it uses, e.g. it pushes them to a stack in the first line and recovers them in the end.
So, to re-use the code, you could just write a new subroutine for turning the heater on, and one for turning each thing off if you want, and only change the label/subroutine name for each one, e.g. FanOff, HeaterOn...
Since all of them preserve all the registers, you can use them sequentially without worries.
The ORR instruction turns ON a bit, the #0x80 constant determines the bit(s) (in this case, only bit 7 is turned on). To turn OFF the bit, you will need an AND instruction and compute the appropriate mask (e.g., to turn OFF bit 7, you would AND with constant #0x7F). The appropriate constants for bit 5 are #0x20 and #0xDF.

Resources