0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AArch64アセンブリ】ファイルを開き内容を出力し閉じるプログラム【Linuxシステムコール】

Posted at

筆者は、こういうのをやろうと思った。

foo.c
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv) {
   if (argc < 2) {
      static char  msg[] = "Usage: $0 FILE\n";
      write(2, msg, sizeof(msg)-1);
      return 1;
   }

   int myfd = openat(AT_FDCWD, argv[1], O_RDONLY);
   if (myfd < 0) {
      static char msg[] = "Could not open\n";
      write(2, msg, sizeof(msg)-1);
      return 1;
   }

   char buf[4096];
   ssize_t n = read(myfd, buf, sizeof(buf));
   if (n<0) {
      static char msg[] = "Read error\n";
      write(2, msg, sizeof(msg)-1);
   } else {
      write(1, buf, n);
      if (n > 0 && buf[n-1] != '\n') write(1, "\n", 1);
   }

   if (close(myfd) < 0) {
      char msg[] = "Close error\n";
      write(2, msg, sizeof(msg)-1);
   }
}

なんでかって?暇だからである。

筆者は適当にいろいろと調べた。その結果、次に示すことが分かった。

  • AArch64などLinuxカーネルにおいて新しく実装されたアーキテクチャのものは新しいシステムコールに統一されたこと
  • openシステムコールはなくopenatを使うように求められてること
  • read、openat、closeのシステムコール番号はそれぞれ63、56、57であること

書いた

foo.s
.data
.L.errorUsage.msg:.ascii "Usage: $0 FILE\n"
.L.errorUsage.msg.len = . - .L.errorUsage.msg
.L.errorOpenFile.msg: .ascii "Open error\n"
.L.errorOpenFile.msg.len = . - .L.errorOpenFile.msg
.L.warnReadError.msg: .ascii "Read error\n"
.L.warnReadError.msg.len = . - .L.warnReadError.msg
.L.warnWriteError.msg: .ascii "Write error\n"
.L.warnWriteError.msg.len = . - .L.warnWriteError.msg
.L.warnCloseError.msg: .ascii "Close error\n"
.L.warnCloseError.msg.len = . - .L.warnCloseError.msg

.L.buf: .ds.b 4096
.L.buf.len = . - .L.buf

.text
.globl _start
_start:
ldr x0,[sp]
cmp x0,2
b.lt .L.errorUsage

mov x0,-100
//
// argc: i32, argv: [*:0][*:0]const u8
ldr x1,[sp,16]
mov x2,xzr
//
// openat
mov x8,56
svc 0
tbnz w0,31,.L.errorOpenFile
mov x19,x0
// x19 = myfd

// x0 = myfd
ldr x1,=.L.buf
ldr x2,=.L.buf.len
mov x8,63
svc 0
mov x20,x0
// x20 = retval of read()
tbz w0,31,.L.myfdOk
bl .L.warnReadError
b .L.writeOk

.L.myfdOk:
mov x0,1
ldr x1,=.L.buf
mov x2,x20
mov x8,64
svc 0
tbz w0,31,.L.writeOk
bl .L.warnWriteError

.L.writeOk:
mov x0,x19
// close
mov x8,57
svc 0
tbz w0,31,.L.finally
bl .L.warnCloseError

.L.finally:
mov x0,0
.L.exit:
mov x8,93
svc 0

.L.errorUsage:
mov x0,2
ldr x1,=.L.errorUsage.msg
ldr x2,=.L.errorUsage.msg.len
.L.error:
mov x8,64
svc 0
mov x0,1
b .L.exit

.L.errorOpenFile:
mov x0,2
ldr x1,=.L.errorOpenFile.msg
ldr x2,=.L.errorOpenFile.msg.len
b .L.error

.L.warnReadError:
ldr x1,=.L.warnReadError.msg
ldr x2,=.L.warnReadError.msg.len
.L.warn:
mov x0,2
mov x8,64
svc 0
ret

.L.warnWriteError:
ldr x1,=.L.warnWriteError.msg
ldr x2,=.L.warnWriteError.msg.len
b .L.warn

.L.warnCloseError:
ldr x1,=.L.warnCloseError.msg
ldr x2,=.L.warnCloseError.msg.len
b .L.warn

書いた感想

デバッグは少し大変だった。
識別子の名付け方は便利になるようにした。

コードゴルフをやってるつもりはないが、次のコード

ldr x1,=.L.buf

するだけでなんかファイルサイズ増えたもんだと思った。何故ならtext領域に該当のアドレスを後置して埋め込むからだ。正直言って直接埋め込められるんだったら埋め込めることができたら良いのにとは思う。まあ無理ではないか。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?