참고. ARM 어셈블리(Assembly)

원문 : http://kkamagui.springnote.com/pages/432792

 

들어가기 전에...

 

 

1.ARM/THUMB Common Part

1.1 Condition Code

 ARM의 어셈블리 명령어들은 뒤에 post fix가 붙는데, 그 post fix의 의미는 아래와 같다. 일반적으로 아무것도 붙지 않으면 AL이라고 가정한다. Branch 명령인 B와 같은 경우 그냥 사용하면 BAL이 되고 BEQ와 같은 조합으로 CPSR에 있는 Condition flag를 이용하여 조건 분기와 같은 역할을 할 수 있는 것이다.

inst1.PNG

 

1.2 Addressing Mode

 addressMode.PNG

 

 

1.3 Shifter operand Mode

addressMode2.PNG

12. <Rm>, =XXX => XXX의 Address를 Rm에 넣는다.

 

 

 

1.4 Post-Fix

  • S : 계산 후 CPSR에 SPSR을 넣어 복구
  • ! : 계산 결과를 Base Register에 적용
  • ^ : PC가 포함된 경우는 연산 후 CPSR에 SPSR을 넣어 복구 or SYSTEM/USER 모드가 아닌 경우이고 PC가 없는 경우는 SYSTEM/USER 모드 레지스터에 값을 로드/스토어

 

 

2.ARM/THUMB 명령어 리스트

2.1 필수 참고 사항

  • <Rd> : 목적지 레지스터를 의미, 일반적으로 결과값을 저장하거나 전송할 레지스터의 값
  • <post fix : 'S'>
    • <Rd>에 PC가 있을 경우 계산 후 CPSR에  SPSR의 값을 대입. SPSR이 존재하지 않는 모드(SYSTEM/USER) 모드일 경우는 동작을 보장할 수 없음
    • <Rd> PC가 없을 경우 계산 결과 플래그를 CPSR에 업데이트
  • <post fix : '!'> : 계산 후 Base Register의 값을 갱신. Multiple Load/Store Instruction 시에 유용히 쓰임
  • <shifter_operand> : #1와 같이 값 자체로도 쓰일 수 있으며 LSL #2와 같이 배럴 쉬프터(Shifter)를 사용해서 할 수도 있다.

 

2.2 ARM 모드 Instruction List

  • ADC : Add with carry 
    • ADC{<cond>}{S} <Rd>, <Rn>, <shifter_operand>
    • <Rd> = <Rn> + <sifter_operand>

 

  • ADD : 
    • ADD{<cond>}{S} <Rd>, <Rn>, <shifter_operand>

 

  • AND : 
    • AND{<cond>}{S} <Rd>, <Rn>, <shifter_operand>

 

  • B, BL : Branch
    • B{L}{<cond>} <target_address>
    • BL의 경우 LR 레지스터에 PC + 4의 값을 대입

 

  • BIC : Bit Clear
    • BIC{<cond>}{S} <Rd>, <Rn>, <shifter_operand>

 

  • BKPT : Breakpoint
    • BKPT <immediat>

 

  • BLX : Branch with Link and Exchange
    • BLX{<cond>} <target_addr>
    • Target_Addr의 값의 bit 0의 값으로 CPSR의 THUMB 모드를 설정한다.
    • ARM 모드와 THUMB 모드를 변환하는데 사용된다.

 

  • BX : Branch And Exchange
    • BLX{<cond>} <Rm>
    • Rm의 bit 0의 값으로 CPSR의 THUMB 모드를 설정한다.
    • ARM 모드와 THUMB 모드를 변화하는데 사용된다.

 

  • CDP : Coprocessor Data Processing 
    • CDP{<cond>} <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
    • CDP2{<cond>} <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>

 

  • CLZ : Count Leading Zeros 
    • CLZ{<cond>} <Rd>, <Rm>
    • MSB부터 LSB로 가면서 1로 설정된 첫번째 bit까지 0이 몇개인가 헤아린다.

 

  • CMN : Compare Negative(음수)
    • CMN{<cond>} <Rd>, <Shifter_operand> 
    • Add를 기반으로 비교
    • 두개가 같으면(결과가 0이면) CPSR의 Z 비트가 1로 설정
    • Shifter_operand의 nagative 값과 <Rd>를 비교한 후 결과를 CPSR에 저장

 

  • CMP : Compare
    • CMP{<cond>} <Rd>, <Shifter_operand>
    • Substract를 기반으로 비교
    • 두개가 같으면(결과가 0이면) CPSR의 Z 비트가 1로 설정
    • Shifter_operand의 값과 <Rd>를 비교한 후 결과를 CPSR에 저장

 

  • EOR : Exclusive OR
    • EOR{<cond>}{S} <Rd>, <Rn>, <Shifter_operand>

 

  • LDC : Load Coprocessor
    • LDC{<cond>}{L} <coproc>, <CRd>, <addressing_mode>
    • LDC2{<cond>}{L} <coproc>, <CRd>, <addressing_mode>

 

  • LDM : Load Multiple Instruction
    • LDM{<cond>}<addressing_mode> <Rn>{!}, <registers>
    • PC가 <registers>에 포함되어있으면 BX 명령과 같은 동작을 한다. (0 bit에 따라서 THUMB 모드와 ARM 모드가 바뀐다.)
    • registers는 낮은 번호의 레지스터부터 높은 번호의 레지스터 순서로 정렬되어야 한다.
    • '!'가 붙으면 Load가 끝난 Rn 레지스터의 값이 Registers의 갯수 * 4 만큼 증가된다.
    • 레지스터의 낮은 번호는 메모리의 낮은 주소(Rn의 시작주소)에 로드되고 레지스터의 높은 주소는 메모리의 높은 주소(Rn + ( regiser 개수 - 1 ) * 4)에 로드된다.
    • LDM{<cond>}<addressing_mode> <Rn>{!}, <registers_without_pc>^
      • resisters 에 포함된 레지스터는 User Mode의 레지스터를 의미한다.
    • LDM{<cond>}<addressing_mode> <Rn>{!}, <registers_pc>^  
      • 레지스터를 로드한 후에 SPSR의 값을 CPSR에 넣는다.

 

  • LDR : Load Register
    • LDR{<cond>} <Rd>, <addressing_mode>
    • <Rd>가 PC인 경우는 BX와 같이 동작한다.

 

  • LDRB : Load Register Byte
    • LDR<cond>}B <Rd>, <addressing_mode>
    • <Rd>에는 하위 8bit는 값이 설정되고 나머지는 0으로 체워진다.

 

  • LDRBT : Load Register Byte Width Translation 
    • LDR{<cond>}BT <Rd>, <post_indexed_addressing_mode>

 

  • LDRH : Load Register Halfword
    • LDR{<cond>}H <Rd>, <addressing_mode>

 

  • LDRSB : Load Register Signed Byte
    • LDR{<cond>}SB <Rd>, <addressing_mode>

 

  • LDRSH : Load Register Signed Halfword 
    • LDR{<cond>}SH <Rd>, <addressing_mode>

 

  • LDRT : Load Register with Translation
    • LDR{<cond>}T <Rd>, <post_indexed_addressing_mode>

 

  • MCR : Move to Coprocessor from ARM Register
    • MCR{<cond>} <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, {, <opcode_2>}
    • MCR2{<cond>} <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, {, <opcode_2>}

 

  • MLA : Multiply Accumlator 
    • MLA{<cond>}{S} <Rd>, <Rm>, <Rs>, <Rn>
    • Rd = ( Rm * Rs + Rn )

 

  • MOV : Move
    • MOV{<cond>}{S} <Rd>, <shifter_operand> 

 

  • MRC : Move To ARM Register from Coprocessor
    • MRC{<cond>} <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, {, <opcode_2>}
    • MRC2{<cond>} <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, {, <opcode_2>}

 

  • MRS : Move PSR to General-purpose register
    • MRS{<cond>} <Rd>, CPSR
    • MRS{<cond>} <Rd>, SPSR 

 

  • MSR : Move To Status Register From ARM
    • MSR{<cond>} CPSR_<fields>, #<Immediate> 
    • MSR{<cond>} CPSR_<fields>, <Rm> 
    • MSR{<cond>} SPSR_<fields>, #<Immediate> 
    • MSR{<cond>} SPSR_<fields>, <Rm> 
    • PSR의 특정 비트 플래그만 조작할 수 있다. 
      • fields : c or x or s or f

 

  • MUL : Multiply
    • MUL{<cond>}{S} <Rd>, <Rm>, <Rs>
    • <Rd> = <Rm> + <Rs>

 

  • MVN : Move Negative
    • MVN{<cond>}{S} <Rd>, <shifter_operand> 

 

  • ORR : Logical OR
    • ORR{<cond>}{S} <Rd>, <Rn>, <shifter_operand> 

 

  • RSB : Reverse Subtract
    • RSB{<cond>}{S} <Rd>, <Rn>, <shifter_operand> 
    • <Rd> = <shifter_operand> - <Rn>

 

  • RSC : Reverse Substract Width Carry
    • RSC{<cond>}{S} <Rd>, <Rn>, <shifter_operand> 
    • <Rd> = <shifter_operand> - <Rn> - NOT(C Flag)

 

  • SBC : Substract with Carry
    • SBC{<cond>}{S} <Rd>, <Rn>, <shifter_operand> 
    • <Rd> = <Rn> - <shifter_operand> - NOT(C Flag)

 

  • SMLAL : Signed Multiply Accumulate Long
    • SMLAL{<cond>}{S} <RdLo>, <RdHi>, <Rm>, <Rs> 
    •  SMLAL.PNG

 

  • SMULL : Signed Multiply Long
    • SMULL{<cond>}{S} <RdLo>, <RdHi>, <Rm>, <Rs> 
    • SMULL.PNG

 

  • STC : Store Coprocessor
    • STC{<cond>}{L} <coproc>, <CRd>, <addressing_mode>
    • STC2{L} <coproc>, <CRd>, <addressing_mode>
    • coprocessor의 레지스터 <CRd>로 부터 <addressing_mode>로 값을 저장

 

  • STM : Store Multiple
    • STM{<cond>}<addressing_mode> <Rn>{!}, <registers>
    • STM{<cond>}<addressing_mode> <Rn>{!}, <registers>^
    • <Rn>의 메모리주소부터 시작하여 <registers>의 값을 저장
    • 레지스터의 낮은 번호는 메모리의 낮은 주소(Rn의 시작주소)에 저장되고 레지스터의 높은 주소는 메모리의 높은 주소(Rn + ( regiser 개수 - 1 ) * 4)에 저장된다.
    • '^'가 포함되면 User 모드의 레지스터가 저장됨

 

  • STR : Store Register
    • STR{<cond>} <Rd>, <addressing_mode>
    • <addressing_mode> = <Rd>

 

  • STRB : Store Register Byte
    • STR{<cond>}B <Rd>, <addressing_mode>
    • <addressing_mode> = Rd[7:0]

 

  • STRBT : Store Register Byte width Translation
    • STR{<cond>}BT <Rd>, <post_indexed_addressing_mode>

 

  • STRH : Store Register Halfword
    • STR{<cond>}H <Rd>, <addressing_mode>

 

  • STRT : Store Register with Translation
    • STR{<cond>}T <Rd>, <post_indexed_addressing_mode>

 

  • SUB : Substract
    • SUB{<cond>}{S} <Rd>, <Rn>, <shifter_operand>
    • <Rd> = <Rn> - <shifter_operand>

 

  • SWI : Software Interrupt
    • SWI{<cond>} <immed_24> 

 

  • SWP : Swap
    • SWP{<cond>} <Rd>, <Rm>, [<Rn>]
    • <Rd> = [<Rn>],  [<Rn>] = <Rm>

 

  • SWPB : Swap Byte
    • SWP{<cond>}B <Rd>, <Rm>, [<Rn>]
    • <Rd> = [<Rn>],  [<Rn>] = <Rm>

 

  • TEQ : Test Equivalence
    • TEQ{<cond>} <Rd>, <shifter_operand>
    • Logical Exclusive OR를 이용해서 비교
    • 두 값이 같으면 CPSR의 Z 플래그가 1로 세팅

 

  • TST : Test
    • TST{<cond>} <Rn>, <shift_operand>
    • AND 이용해서 비교
    • 결과가 0이면 CPSR의 Z 비트가 1로 셋팅

 

  • UMLAL : Unsigned Multiply Accumulate Long
    • UMLAL{<cond>}{S} <RdLo>, <RdHi>, <Rm>, <Rs>
    • UMLAL.PNG

 

  • UMULL : Unsigned Multiply Long
    • UMULL{<cond>}{S} <RdLo>, <RdHi>, <Rm>, <Rs>
    • UMLL.PNG

 

 

2.3 THUMB 모드 Instruction List

  • BL, BLX : Branch with Link, Branch with Link Exchange
    • BL <target_addr>
    • BLX <target_addr>
    • BL3.PNG
    • BL4.PNG
    • THUMB 모드의 BL은 LR 레지스터에 0bit를 1로 셋팅하여 BX LR과 같은 명령 사용 시 THUMB 모드로 다시 돌아올 수 있도록 하고 있다.

 

 

3.ARM C Calling Convention

 ARM의 경우 레지스터가 많기 때문에 Intel과는 달리 4개의 파라메터까지는 Register 0 ~ Register 3에 저장하게 된다. R0 같은 경우는 일반적으로 리턴 값으로 사용되기도 하며, Register 4 ~ Register 8은 Callee에서 사용하는 레지스터이다.

 Caller는 R0 ~ R3 까지를 저장하고 복원할 책임을 가지며 Callee는 R4 ~ R8 까지를 저장하고 복원하는 책임을 가진다.

arm_calling.PNG

<APCS(Arm Procedure Call Standard)에서 각 레지스터의 역할>

 ARM에서 Branch를 하면 LR 레지스터에 Return Address가 저장되므로, 다시 다른 함수를 Call 하게 되면 LR 레지스터를 저장하고 다시 복구해야 한다.

 

4.마치며...

 ARM 어셈블리에 대해서 간략하게나마 정리했다. 시간 날때 틈틈히 찾아보도록 하자.

 

 

 

 

 

이 글은 스프링노트에서 작성되었습니다.

+ Recent posts