ARM Instruction Set Architecture (1)

­3zu·2022년 4월 19일
0
post-thumbnail

Two Pass Assembly

대부분의 어셈블러는 source file을 두 번 읽는다.

  • 1. First pass : symbol table을 만든다. 각 symbol에 대해 second pass에서 사용할 value를 계산하고 기록한다
    - symbols : global variables, functions, labels
    - values : addresses(symbol의 location), data
    printf는 symbol인건 알겠는데 코드만으로는 뭔지 알 수가 없다. 라이브러리에 정의되어있기 때문임. 어셈블리 파일에 definition이 존재하지 않아서 resolve할 수 없고 value를 생성해낼 수 없음. 하지만 linking의 과정을 수행하면 그 때에 linker를 통해 printf를 resolve할 수 있음.

몇 개의 symbol은 known value를 가지고 있지 않을 수 있다.
그 symbol들은 unresolved이며 linker가 그 값들을 fix한다.

  • 2. Second Pass : object file을 생성한다. code의 output이 object file이고 필요시 값을 제공하기 위해 symbol table을 사용한다. unresolve된 모든 symbol에 대해서 linker를 통해 object file에 정보를 추가한다.

Syntax Of Assembly

  • Basic syntax
    label statements는 :로 끝난다.
    다른 statement는 가장 처음 나온 newline이나 ;로 끝난다.
    directive는 .으로 시작한다.
label:
	instruction[;]
    .directive[;]
    macro_invocation[;]

// single-line comment
@ single-line commnet in AArch32 state only
/* multi-line
   comment */

Assembly Expressions

expression은 instruction operand나 directive argument로 사용될 수 있다.
expression은 operator로 결합된 한 개 혹은 그 이상의 constant나 symbol reference로 이루어져 있다.

assembler가 모든 expression을 evaluate한다. expression의 value를 calculate한다는 의미이다. 어셈블러가 compile time에 value를 계산한다. CPU가 runtime에 하는 것이 아니라.. 미리 계산한다는 의미.

symbol은 반드시 같은 assembly language source file에 정의되거나 expression에 reference될 필요는 없다.
period symbol .은 output file의 current location을 reference할 수 있는 special symbol이다.

Assembly Directives

Section Directives

section의 type을 specify함.

  • .section name
  • .text : text section
  • .data : data section
  • .rodata : read only data section
  • .bss

String Definition Directives

현재 section에 one or more bytes를 할당해서 string literal로 memory content를 initialize함.

  • .ascii "string" : 공간을 allocate해서 string을 넣지만 string뒤에 null byte를 넣지 않는다. C 랑 combine해서 쓰는 경우 이건 쓰면 안된다. null character가 없기 때문에 문자열이 끝나지 않기 때문이다.
  • .asciz "string", .string "string" : string을 넣고 그 뒤에 null byte를 append한다.

Data Definition Directives

current section에 memory를 allocate하고 그 memory의 initial content를 정의한다.
given value로 space를 채운다.

  • .byte expr[, expr]... : multiple expression이 가능하고 byte를 할당해 expression의 결과로 space를 채운다.
  • .hword expr[, expr]...
  • .word expr[, expr]...
  • .quad expr[, expr]...
  • .octa expr[, expr]...

// 1 byte에 42를 넣음
.byte 42

// 1 word(4 byte)에 15532를 넣음
.word 15532

// 1 word에 extern_symbol의 address를 넣음
.word extern_symbol

// 2 byte에 end와 start의 distance를 계산해서 넣음
// end의 address에서 start의 address를 뺐으므로 distance가 됨
.hword end - start

// 4 byte에 extern_symbol이 current location에서 얼마나 떨어져 있는지 distance를 넣음
.word extern_symbol - .

Alignment Directives

alignment directive는 file의 current location을 specified boundary로 aligh해준다.

  • .balign num_bytes[, fill_value] : balignb는 byte이다.
  • .p2align exponent[, fill_value] : p2alignp2는 power 2이다.
  • .align exponent[, fill_value]

num_bytes : 이 parameter은 align되어야 하는 number of bytes를 나타낸다. 이 number은 반드시 2의 지수여야 한다.
exponent : 이 parameter은 alignment boundary를 exponent로 나타낸다. 이 alignment boundary는 2^(exponent)이다.
fill_value : 삽입된 padding bytes를 채울 값. 이 값은 optional이다.

	.p2align 2
value:
	.word 42 // 2^2 = 4 byte boundary로 align됨.
    
    .p2align 4 // function의 entry point가 16-bytes boundary로 align되는 것을 보장함. to better utilize cache
    .type func1, "function"
func1:
	//code

Space-Filling Directives

  • .space count[, value] : count는 item의 개수이고 value는 item의 initial value이다. .spacevalue값을 가지고 있는 count만큼의 bytes를 할당한다.
  • .fill count[, size[, value]] : size는 item의 initial size이다. .fillsize만큼의 length에 value값을 가진 count만큼의 공간을 만든다.

Macro Directives

.macro macro_name [, parameter_name]
	// ..
    [.exitm]
.endm

macro_name : macro의 name이다.
parameter_name : macro의 모든 parameter가 나열된다. macro 내부에서 이 parameter를 사용하기 위해서는 prefix \를 써야 한다.

.macromacro_name의 새로운 macro를 정의한다. macro가 한 번 정의되고 나면 instruction mnemonic처럼 instantiate될 수 있다.
macro_name argument[, argument] ...

	.macro pascal_string, str //one parameter를 가진 macro
    .byte 2f - 1f //label 사이의 distance를 구함. f는 forward를 의미함. symbol의 location이 있을 텐데 그 symbol의 forward position을 의미함.
1:
	.ascii "\str" //space를 allocate해서 string을 넣었지만 terminator가 없음.
2:
	.endm

Org Directives

.org는 location counter를 current section에서 new-location으로 증가시킨다.
location counter은 forward로만 움직이고 backward로는 움직이지 않는다.

.org new_location[, fill_value]

  • new_location : mendatory parameter임. current section의 location을 evaluate하기 위한 expression이다.
  • fill_value : optional 1 byte이고 default value는 0이다.
	.macro exc_tab_entry, num //vector table을 initialize하기 위한 macro
1:
	mov x0, #\num
    b unhandled_exception
    .org 1b + 0x80 //labal 1의 backward position에서 128 bytes로 counter를 next entry의 beginning으로 옮길 수 있다.
    .endm

Conditional Assembly Directives

.if[modifier] expression
	//...
   [.elseif expression
    //...]
   [.else
    //...]
.endif

모든 directive는 assembler로 evaluate된다!
어셈블러가 calculate하는거라 런타임에서는 directive를 볼 수 없음.

  • .if expr : expr이 non zero일때 following code를 assemble함.
  • .ifne expr : expr이 non zero일때 following code를 assemble함.
  • .ifeq expr : expr이 zero일때 following code를 assemble함.

Symbol Binding Directives

한 개 혹은 그 이상의ELF binding을 modify한다.

  • .global symbol[, symbol] : link된 모든 object file에게 visible하다. 한 object file의 definition이 다른 object file에서 reference될 수 있다. strong binding.
  • .local symbol[, symbol] : define되거나 reference된 object file 밖에서는 이 symbol들이 보이지 않는다. 그래서 여러 object file이 서로의 간섭 없이 같은 symbol 이름을 사용할 수 있다.
  • .weak symbol[, symbol] : 이 symbol들은 global symbol들과 비슷하지만 차이점이 있다.
    • weak binding 되어있는 symbol은 reference할 수 없다.
    • weak symbol의 정의가 여러 개 있는 것은 error가 아니다. 만약 strong binding된 definition이 있으면 그 definition이 symbol에 대한 모든 reference를 만족시킨다. 그렇지 않으면 weak reference중 하나를 선택한다.

symbol binding directive는 assembly의 어느 지점에서나 나올 수 있다. symbol의 어떤 reference나 definition의 앞이나 뒤에 나올 수 있다.

만약 symbol의 binding이 specify되지 않았다면 default는 다음과 같다

  • 만약 symbol이 assembly file에 정의되지 않았다면 그 symbol은 global visibility를 가진다.
  • 만약 symbol이 assembly file에 정의되었다면 그 symbol은 local visibility를 가진다.
.weak debug_trace
bl debug_trace

위의 예제에서 debug_trace는 global visibility를 가진 weak binding이다. 다른 어셈블리 파일에 debug_trace가 있고 그 파일에 debug_trace이 global definition으로 되어있다면 얘는 그 global definition을 가리키게 되지만 그것이 없다면 다른 global definition들이 얘를 가리키게 됨.

Instruction Set Selection Directives

  • .arm : 어셈블러가 이후의 instruction을 A32 instruction으로 해석한다.
  • .thumb : 어셈블러가 이후의 instruction을 UAL syntax를 사용하는 T32 instruction으로 해석한다.
  • .thumb_func : 이후 나오는 symbol이 Thumb encoded function의 이름임을 나타낸다.
  • .syntax [unified | divided] : 이 directive는 instruction set syntax를 설정한다.
    • divided (default for compatibility with legacy) : ARM instruction과 Thumb isntruction이 개별적으로 사용된다.
    • unified : UAL(unified assembly language) syntax를 enable한다. Thumb2 instruction을 위해 필요하다.

0개의 댓글