ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [어셈블리어] AArch64 어셈블리어
    임베디드 SW/어셈블리어 2023. 8. 3. 02:35

    글의 참고

    - https://mariokartwii.com/armv8/

    - https://thinkingeek.com/arm-assembler-raspberry-pi/

    - https://thinkingeek.com/2016/10/08/exploring-aarch64-assembler-chapter1/


    글의 전제

    - 내가 글을 쓰다가 궁금한 점은 파란색 볼드체로 표현했다. 나도 모르기 때문에 나중에 알아봐야 할 내용이라는 뜻이다.

    - 밑줄로 작성된 글은 좀 더 긴 설명이 필요해서 친 것이다. 그러므로, 밑 줄 처친 글이 이해가 안간다면 링크를 따라서 관련 내용을 공부하자.

    - `글의 참조`에서 빨간색 볼드체로 체크된 링크는 이 글을 작성하면 가장 많이 참조한 링크다.

    - 이 글은 글의 참조에 있는 링크들을 내 마음대로 번역한 것이다. 심지어 필요없다고 생각된 부분은 생략했음을 알린다.

     

    - Software 환경

    타입 버전
    OS(리눅스 커널 정보) Linux yohda-800G5M-800G5W 5.4.0-139-generic #156~18.04.1-Ubuntu SMP Wed Jan 25 15:56:22 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
    lsb_release -a(리눅스 배포판 정보) No LSB modules are available.
    Distributor ID: Ubuntu
    Description: Ubuntu 18.04.6 LTS
    Release: 18.04
    Codename: bionic
    qemu-aarch64 qemu-aarch64 version 2.11.1(Debian 1:2.11+dfsg-1ubuntu7.41)
    Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers
    aarch64-linux-gnu-gcc aarch64-linux-gnu-gcc (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0
    Copyright (C) 2017 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

     


    글의 내용

    - AArch64는 ARM이 2011년에 발표한 ARMv8 아키텍처의 64-bit mode에서 동작하는 실행 상태를 의미한다. 현재는 스마트폰과 서버에 점차 배포가 되어가고 있다(이 글이 써진 시점이 2016.08). 사실 이미 굉장히 많은 분야에서 사용하고 있다.

     

     

    1) ARMv8 아키텍처를 지원하는 하드웨어

    - 오늘날 ARMv6/ARMv7 아키텍처를 사용하는 single board computers는 쉽게 구할 수 있습니다. 가장 인기있는 선택 중 하나는 `Raspberry Pi`입니다.

     

    - 반면 ARMv8의 64비트 모드를 지원하는 single board computers는 흔하지 않지만, 요즘에는 서서히 대중화되고 있습니다.

    Raspberry Pi 3에는 64비트 시스템을 실행할 수 있는 Cortex-A53 가 내장되어 있다. 하지만 Raspberry Foundation(Raspbian)에서 제공하는 소프트웨어 시스템(Raspbian)은 32비트 전용이다. 라즈베리파이 공식 입장은 64비트 시스템에 대한 계획은 없다고 한다.

    SUSE에는 Raspberry Pi 3에서 실행할 수 있는 64비트 버전의 OpenSUSE 배포판이 있습니다. Archlinux에는 RPi3에 설치할 수 있는 64비트 배포판도 있습니다.

     

    2) 64비트 하드웨어가 없을 경우

    - AArch64 지원 하드웨어가 없어도 우리는 ARM64 프로그래밍을 할 수 가 있다. 왜?

    우리에겐 `cross-toolchain`과 `QEMU`가 있으니께~

     

    - 일단 QEMU와 AArch64 cross-toolchain을 설치하자.

    $ sudo apt-get install qemu-user gcc-aarch64-linux-gnu

    - 일단 C로 작성된 "Hello world"를 실행할 수 있는지 테스트해보자. 다음 내용으로 hello.c 파일을 만듭니다.

     

    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
      printf("Hello AArch64!\n");
      return 0;
    }

    - 이제 이전에 설치한 AArch64용 크로스 컴파일러로 위의 파일을 컴파일한다(-static 플래그가 중요함).

    $ aarch64-linux-gnu-gcc -static -o hello hello.c

     

    - AArch64 binary 인지 확인해보자.

    yohda@yohda-800G5M-800G5W:~/workspace/SW/Exploring-AArch64-assembler$ file hello 
    hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=e5111eb8e87ee9c87a7545629bab22c0c521c9ce, not stripped

    - 실행하려고 하면 아래와 같은 에러가 발생할 수 있다.

     

    $ ./hello 
    -bash: ./hello: No such file or directory

    - aarch64-linux-gnu-gcc를 통해서 만들어진 바이너리는 윈칙적으로 aarch64 환경에서 동작하는 컴퓨터 위에서 실행해야 한다. 결국 우리의 노트북은 인텔 CPU일 확률이 99%이니, qemu를 통해서 해당 프로그램을 실행해야 된다.

     

    yohda@yohda-800G5M-800G5W:~/workspace/SW/Exploring-AArch64-assembler$ qemu-aarch64 ./hello 
    Hello AArch64!

    - 주의점은 `-static` 옵션을 사용하는 경우, 항시 qemu-aarch64를 통해서 프로그램을 실행해야 한다.

     

     

    3) 첫 번째 AArch64 어셈블리어 프로그램

    - 오류 코드 2를 반환하는 매우 간단한 프로그램을 작성해 봅시다.

    // first.s
    .text
    
    .globl main
    
    main:
         mov w0, #2
         ret

    - 위 코드를 일단 내 환경에서는 아래와 같이 빌드를 해야 한다.

     

    aarch64-linux-gnu-gcc -c first.s 
    aarch64-linux-gnu-gcc -static -o first first.o

    - `qeme-aarch64 ./first`를 실행하고 반환값을 확인해보자.

     

    $ qemu-aarch64 ./first
    $ echo $?
    2

    - 이제 코드를 한 번 분석해 봅시다.

     

    // first.s
    .text

    - 1행 : 어셈블리 파일에서 주석은 `//`을 사용할 수 있다.

    -2행 : `.text`는 어셈블러 지시어(assembler directive)중에 하나이다. 이 지시어의 기능은 `이 지시어가 선언된 지점 아래부터는 모두 코드(명령어) 영역이라는 의미`이다. 참고로 데이터는 .data 지시어 뒤에 온다.

     

    .globl main

    - `.global` 또한 어셈블러 지시어중에 하나이다. 이 지시어 뒤에 오는 심볼(symbol)은 전역 심볼(global symbol)이 되는 것을 의미한다. 이것은 컴파일의 최종단계에서 프로그램이 구성될 때, 이 프로그램을 시작하기 위해 C 라이브러리에 필요한 global `main` symbol을 가질 것이라는 것을 의미한다(`global` directive에 대한 내용은 아래 `참고` 확인).

     

     

    main:
         mov w0, #2 // w0 ← 2
         ret        // return

    - `main:`이 우리 프로그램의 시작점이다.

    - 6행 : 위에서 언급한 것은 global `main` symbol에 대한 label이다. 이건 쉽게 함수를 생각하면 된다. 위쪽에 함수를 선언했으면(.global main),  이 부분은 실제 함수의 정의하는 부분이라고 생각하면 될 것 같다.

    - 7행 : 2라는  상수값을 w0 레지스터에 넣는다.

    - 8행 : main을 종료한다.

     

    - 프로그램이 종료되면, w0 레지스터의 값이 이전에 실행됬던 프로그램의 오류 여부를 결정한다. 아래 코드를 보자.

    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
      printf("Hello AArch64!\n");
      return 0; // mov w0, #0
    }

    - 위의 main() 함수에서 `return 0` == `mov w0, #0`고 같다고 보면 된다. 그럼 이제 Shell에서 `echo $?`를 치면 2가 출력되는 것을 확인할 수 있다.

    '임베디드 SW > 어셈블리어' 카테고리의 다른 글

    NASM  (2) 2023.08.12
    x86 명령어  (0) 2023.08.12
Designed by Tistory.