-1

Edit: My concern is how ARM instruction is encoded.

Let's examine below example:

  194640:   e92d40f0    push    {r4, r5, r6, r7, lr}
  194644:   e24dd024    sub sp, sp, #36 ; 0x24
  --> sp decrease 36 ~ 0x24 --> Is it calculated by e24dd024 & 0x0000ffff ?

  1995ec:   e92d4ef0    push    {r4, r5, r6, r7, r9, sl, fp, lr}
  1995f0:   e24ddd0a    sub sp, sp, #640    ; 0x280
  1995f4:   e1a04000    mov r4, r0
  --> sp decrease 640 ~ 0x280 --> How it is calculated ?

 Other examples:
  191ea8:   e92d4030    push    {r4, r5, lr}
  191eac:   e24dd034    sub sp, sp, #52 ; 0x34
  191eb0:   e28d5014    add r5, sp, #20

  194f54:   e28d60a8    add r6, sp, #168    ; 0xa8
  194f58:   e28d5e13    add r5, sp, #304    ; 0x130
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    AArch64 doesn't use simple 16-bit immediates like MIPS. Check the manual for how instructions like ADD/SUB encode large immediates. (It's different from bitwise boolean instructions like AND.) BTW, I fixed your question title; you can't of course calculate SP, that would be like asking "what's x after x -= 36" – Peter Cordes Feb 25 '21 at 10:39
  • yes, encode large immediates is the keyword. Now it is clear to me :) – Ngoc Hoang Nguyen Feb 25 '21 at 11:15
  • I think AArch64 add/sub uses a shifted or rotated value, probably 8 bits (correction, 12 bits). `0xa << 6 = 0x280` would explain why there's a `0a` at the bottom of the machine code, but I'd have to look up the rules for how the shift or rotate count is encoded; feel free to post an answer to your own question if you found the docs, unless there's a duplicate already on Stack Overflow. – Peter Cordes Feb 25 '21 at 11:15
  • The explanation in https://stackoverflow.com/questions/17763582/how-to-encode-immediate-value-in-arm is clear for me. For e24ddd0a, 0x0A (1010 in binary) should be rotated right by (2*D=2*13=26), it means the last bit 0 of 0x0A is on the bit 25 (staring from 0, bit 25 is counted as 26), so the final result is 1010 00 0000 ~ 0x280 – Ngoc Hoang Nguyen Feb 25 '21 at 11:29
  • Oh wait a minute, this is 32-bit ARM, not the [arm64] you originally tagged. I didn't notice before, but the reg names are `r0` not `w0` or `x0`. And of course the multi-register push. No wonder the earlier duplicate link I found didn't seem right to match well with the encoding. – Peter Cordes Feb 25 '21 at 11:31

1 Answers1

0
  push    {r4, r5, r6, r7, lr}
  sub     sp, sp, #36 ; 0x24

That's basically a function 'prologue'.
Function preserves registers it's gonna to change (push instruction) and reserve stack (sub sp,...) for function internal variables and intermediate preservation of registers.

So to put it simple, the more variables function uses, the bigger is number subtracted from sp. Note, that's also depends on sizeof(x) of variables. Say if function declares a some big structure, that would take more stack to accommodate it.

Exact value is defined by compiler, and could vary depending on compilation settings.

user3124812
  • 1,861
  • 3
  • 18
  • 39
  • I *think* the question is about trying to understand the machine code, like where the `0x280` comes from in `e24ddd0a` (disassembly: `sub sp, sp, #0x280`). – Peter Cordes Feb 25 '21 at 11:14
  • hmm... that did not make such an impression on me. Question should be better formulated then. Something with words 'instruction encoding' probably – user3124812 Feb 25 '21 at 11:19
  • I already re-titled it before you answered (for that reason), but didn't rewrite the question body. Mostly irrelevant now since I found a duplicate. On my first reading, I thought the OP was trying to calculate the *value* of SP itself, from an instruction that just modified it. – Peter Cordes Feb 25 '21 at 11:24