0

This question was asked before here but in the answers I did get what i was looking for.

Consider this:

ADDS R0 RO R1

As far as I know to update the cpsr flags a subtraction has to be made. So after this instruction, is the result subtracted from RO or R1?

Edit: This is what I understand

CMP RO R1 

In this instruction, R1 is subtracted from R0 and based on the results the flags are updated. The thing I dont understand is in operations with S suffix the result after the operation like eg ADDS on the top is it subtracted from R0 or R1 to update the flags or i got it all wrong?

Edit 2:

For example consider these instructions

mov r0, #1
mov r1, #6
tst r1, r0
bne 0x6000

From this example, the result of the tst instruction is 7(111 binary). In the branch instruction how can it branch with the NE condition code if there was no comparison between registers.

2
  • R0 == R0+R1 is the operation here not sure what subtraction you are referring to the S modifies the flags based on the result of operation
    – blabb
    Dec 6, 2021 at 10:53
  • @blabb i have updated the question please correct me if I am wrong.
    – Silent
    Dec 6, 2021 at 12:54

1 Answer 1

1

As I Commented the operation here is R0 == R0+R1
the Current Program Status Register or
Application Program Status Register are modified based on the result

Assume for example

R0 contains 0xffffffff (maximum possible 32 bit unsigned integer)
R1 contains 0x00000001

R0+R1 will be

>>> print(hex(0xffffffff+0x00000001))
0x100000000
>>>

the result is a 33bit or in other words the result is 0x0 and the 33rd bit is lost since result is 0 N or Negative flag is not set N=0

again since result is 0 zero flag is set to 1 Z=1

the upper 33rd bit is lost so Carry flag is set C==1

signed or v flag doesn't not have any overflow (-1 + 1 ) == 0 so V flag is not set V=0

this all are explained in this document

there is a source code and demo also attached in the link

where adds and the cpsr details are retrieved by this assembly stub you can use unicorn or unicorn based qiling to emulate these instruction

doADDS:
    @ Perform the operation, leaving the result in r0 to return it.
    adds    r0, r0, r1
    
    @ Get the APSR flags and dump them into flags (*r2).
    mrs     r3, CPSR
    str     r3, [r2]
    
    @ The recommended (interworking-compatible) return method:
    bx      lr

a sample emulation and cpsr flags using Qiling Framework

:\>type armshell.py
from qiling import *
from qiling.const import QL_VERBOSE

# 0x0000000000000000:  00 00 E0 E3    mvn  r0, #0
# 0x0000000000000004:  01 10 A0 E3    mov  r1, #1
# 0x0000000000000008:  01 00 90 E0    adds r0, r0, r1
# 0x000000000000000c:  00 F0 20 E3    nop
# 0x0000000000000010:  00 F0 20 E3    nop

shellcode = b"\x00\x00\xe0\xe3\x01\x10\xa0\xe3\x01\x00\x90\xe0\x00\xf0\x20\xe3\x00\xf0\x20\xe3"

ql = Qiling(
    code=shellcode,
    rootfs=r"F:\QILING\examples\rootfs\x8664_windows",
    ostype="linux",
    archtype="arm",
    verbose=QL_VERBOSE.DEBUG
)
ql.reg.cpsr = 0
ql.reg.r0 = 0
ql.reg.r1 = 0
print("registers before starting")
print("r0 = 0x{:x}".format(ql.reg.r0))
print("r1 = 0x{:x}".format(ql.reg.r1))
print("cpsr = 0x{:x}\n".format(ql.reg.cpsr))

for i in range(1, 5, 1):
    ql.run(0, len(shellcode), -1, i)
    print("r0 = 0x{:x}".format(ql.reg.r0))
    print("r1 = 0x{:x}".format(ql.reg.r1))
    print("cpsr = 0x{:x}\n".format(ql.reg.cpsr))

executed

:\>python armshell.py
[+]     Profile: Default
[+]     Set init_kernel_get_tls
registers before starting
r0 = 0x0
r1 = 0x0
cpsr = 0x0

r0 = 0xffffffff
r1 = 0x0
cpsr = 0x0

r0 = 0xffffffff
r1 = 0x1
cpsr = 0x0

r0 = 0x0
r1 = 0x1
cpsr = 0x60000000

r0 = 0x0
r1 = 0x1
cpsr = 0x60000000

the cpsr is set with bit 29,30 representing flags Z and C (Zero and Carry)

>>> hex(1<<30|1<<29)
'0x60000000'
>>>

feeding with a ladle

from qiling import *
from qiling.const import QL_VERBOSE

# 0x0000000000000000:  00 F0 20 E3    nop 
# 0x0000000000000004:  01 00 A0 E3    mov r0, #1
# 0x0000000000000008:  06 10 A0 E3    mov r1, #6
# 0x000000000000000c:  00 00 11 E1    tst r1, r0
# 0x0000000000000010:  FA 17 00 1A    bne #0x6000
# 0x0000000000000014:  00 F0 20 E3    nop 

shellcode = b"\x00\xf0\x20\xe3\x01\x00\xa0\xe3\x06\x10\xa0\xe3\x00\x00\x11\xe1\xfa\x17\x00\x1a\x00\xf0\x20\xe3"

ql = Qiling(
    code=shellcode,
    rootfs=r"F:\QILING\examples\rootfs\x8664_windows",
    ostype="linux",
    archtype="arm",
    verbose=QL_VERBOSE.DEBUG
)
ql.reg.cpsr = 0
ql.reg.r0 = 0
ql.reg.r1 = 0
print("registers before starting")
print("r0 = 0x{:x}".format(ql.reg.r0))
print("r1 = 0x{:x}".format(ql.reg.r1))
print("cpsr = 0x{:x}\n".format(ql.reg.cpsr))

for i in range(1, 5, 1):
    ql.run(0, len(shellcode), -1, i)
    print("r0 = 0x{:x}".format(ql.reg.r0))
    print("r1 = 0x{:x}".format(ql.reg.r1))
    print("cpsr = 0x{:x}\n".format(ql.reg.cpsr))

emulation of tst instruction.

F:\QILING\testqiling>python armtstop.py
[+]     Profile: Default
[+]     Set init_kernel_get_tls
registers before starting
r0 = 0x0
r1 = 0x0
cpsr = 0x0

r0 = 0x0
r1 = 0x0
cpsr = 0x0

r0 = 0x1
r1 = 0x0
cpsr = 0x0

r0 = 0x1
r1 = 0x6
cpsr = 0x0

r0 = 0x1
r1 = 0x6
cpsr = 0x40000000 <<<<<<<<<< 
3
  • Oh now I understand. With CMP you have to subtract between the two registers for you to get the result and hence update the cpsr flags. But with the instructions with S suffix the result is used to update the flags whether the instructions was ANDS, SUBS, etc.... But what i dont really get in this concept is how does this really work in EQ and NE condition codes since there was no comparison done. Please see update in question for the example.
    – Silent
    Dec 7, 2021 at 21:55
  • have You Opened the Link i posted ? have you read the contents ? especially the conditional code execution part ? have you given a thought to how tst is equivalent to ands operation and what might be the actual result of such operation ? have you noticed the footnote that says tst discards the result and updates the flags ?
    – blabb
    Dec 8, 2021 at 2:58
  • Thanks I now understand. I read it before but didn't get the S suffix part. I guess I needed the recap.
    – Silent
    Dec 8, 2021 at 3:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.