Assembly syntax
ARM Assembly Language 관련 syntax에 대해서 정리한 글
Assembly Identifiers
.section <section_name>, "<option>"
섹션을 정의
.balign n
다음 주소가 n바이트 단위로 alignment
.global <variable_name or function_name>
.global 키워드를 사용하여 전역화
label without branch instruction
하기와 같이 예제코드에서 분기문이 없거나, 분기문이 실행되지 않는다면 순차적으로 다음 코드로 넘어감.
# example 1: 해당 예제의 경우 1번째 분기문에서 case1으로 분기되지 않은 경우 순차적으로 다음 code인 "add $s2, $s0, $s1 "로 진행
beq $s0, $s1, case1
add $s2, $s0, $s1
case1:
sub $s1, $s1, $s0
# example 2) 해당 예제의 경우 3번째 분기문에서 case2로 분기되지 않은 경우 순차적으로 다음 code인 case1로 진행
add x1 x1 #4
cmp x0 x1
b.eq case2
case1:
/* code1 */
case2:
/* code2 */
inline assembly 키워드 __asm
C, C++ code 내에서 동작하는 assembly code를 작성하기 위해 사용하는 키워드.
- Shifts the burden of handling the procedure call standard (PCS) from the programmer to the compiler. This includes allocating the stack frame and preserving all necessary callee-saved registers.
- Inline assembly code gives the compiler more information about what the assembly code does.
- The compiler can inline the function that contains the assembly code into its callers.
- Inline assembly code can take immediate operands that depend on C-level constructs, such as the size of a structure or the byte offset of a particular structure field.
__asm
기본적인 형태는 다음과 같다.
/* essential syntax */
__asm [volatile] (code);
/* Extended inline assembly syntax */
__asm [volatile] (code_template
: outputs
[: inputs
[: clobber_list]]
);
- code: assembly instruction
- code_template: 확장된 assembly 명령어, 템플릿 변수를 사용하게 되면 ':'으로 나뉜 outputs, inputs, clobber_list에 템플릿 변수에 대한 정의를 해주어야함.
outputs and inputs
[<name>] "<constraint>" (<value>) 형태로 작성되며
- [<name>]: code templete의 변수를 지정하며, 별도로 명시적으로 지정하지 않을 경우 code templete에서는 %n형태로 0부터 순서대로 사용
- "<constraint>": 해당 operand의 속성 설정
- (<value>): C code 형태의 변수 지정
ex)
void saturating_add(int a, int b)
{
int result;
__asm("qadd %0, %[lhs], %[rhs]" : "=r" (result) : [lhs] "r" (a), [rhs] "r" (b) );
return result;
}
clobber list
- “memory”: 컴파일러에게 해당 asm code가 단순 변수(register)가 아닌 메모리를 수정할 것이라는 것을 알림.
- “cc”: 컴파일러에게 해당 asm code가 condition flags를 변경할 것이라는 것을 알림
Constraints
컴파일러가 하기와 같이 지정한대로 해당 operand에 대한 속성 값을 사용
- r: 해당 operand에 대해 64bit general purpose register를 사용(X0-X30)
- w: for SIMD or floating point(V0-V31)
- x: for 128-bit vector(V0-V15)
Constraint modifiers
모든 output operand는 constraint modifier를 기재해 주어야 함.
- "=": write only, 모든 input operand가 read된 이후에만 write 가능
- "+": both read and write
- "=&": write only, 모든 input operand가 read되기 전에도 수정가능
- "+&": both read and write, 모든 input operand가 read되기 전에도 r/w 가능
&: "earlyclobber" operand를 나타내고 input operand를 사용하는 명령이 끝나기 전에 변경 된다는 것을 의미함.
그래서 input operand나 메모리 어드레스의 일부을 나타내는 register에는 못 쓴다.
gcc는 input 변수가 다 사용되고 나면 output에 사용된다고 가정하기 때문에 input에 사용된 변수가 output과 같게 되고 또 output이 input 보다 먼저 사용되는 경우가 발생할 수 있다. 이런 경우를 막기 위해 output에 사용된 변수가 input이 모두 사용되기 전에 변경될 수도 있다고 알려줘야만 input과 output이 같아져 생기는 에러를 막을 수 있다.
Templete Modifiers
%U
The asm statement must also use %U as a placeholder for the “update” flag in the corresponding load or store instruction.
예제
Correct
asm ("st%U0 %1,%0" : "=m<>" (mem) : "r" (val));
Wrong
asm ("st %1,%0" : "=m<>" (mem) : "r" (val));
'Embedded System > Assembly' 카테고리의 다른 글
WFI / WFE (0) | 2024.06.27 |
---|